Thursday, April 22, 2010

RichFaces - "beautiful" code

I'm extending the rich:calendar control today trying to put its definition into a table (for reasons that are not important here). The outcome should be as easy as input in one cell and the icon in another. Sounds easy, right?

Nothing could be further from the truth!

How I'd envision generation of HTML in such a case would be a container class having things like name, attributes collection, possibly even child controls (if it's a container for other controls) with one method "render(where...)" that would make use of those contained properties.

But it turns out that the guys from RichFaces didn't get the memo, that code duplication is bad. In fact they missed it so much that getting the whole thing to do what I want it to do takes a copy and paste, then refactoring and at the end implementation of the stuff I need.

Here's an example of how the render for example attributes of a control:

getUtils().writeAttribute(writer, "accesskey",
component.getAttributes().get("accesskey"));
getUtils().writeAttribute(writer, "class", "rich-calendar-input " +
convertToString(component.getAttributes().get("inputClass")));
getUtils().writeAttribute(writer, "disabled",
variables.getVariable("disabled"));
getUtils().writeAttribute(writer, "id",
convertToString(clientId) + "InputDate");
getUtils().writeAttribute(writer, "maxlength",
component.getAttributes().get("maxlength"));
getUtils().writeAttribute(writer, "name",
convertToString(clientId) + "InputDate");
getUtils().writeAttribute(writer, "onblur",
component.getAttributes().get("oninputblur"));
getUtils().writeAttribute(writer, "onchange",
component.getAttributes().get("oninputchange"));
getUtils().writeAttribute(writer, "onclick",
component.getAttributes().get("oninputclick"));
getUtils().writeAttribute(writer, "onfocus",
component.getAttributes().get("oninputfocus"));
getUtils().writeAttribute(writer, "onkeydown",
component.getAttributes().get("oninputkeydown"));
getUtils().writeAttribute(writer, "onkeypress",
component.getAttributes().get("oninputkeypress"));
getUtils().writeAttribute(writer, "onkeyup",
component.getAttributes().get("oninputkeyup"));
getUtils().writeAttribute(writer, "onmouseout",
component.getAttributes().get("oninputmouseout"));
getUtils().writeAttribute(writer, "onmouseover",
component.getAttributes().get("oninputmouseover"));
getUtils().writeAttribute(writer, "onselect",
component.getAttributes().get("oninputselect"));
getUtils().writeAttribute(writer, "size",
component.getAttributes().get("inputSize"));
getUtils().writeAttribute(writer, "style",
"vertical-align: middle; " + convertToString(component.getAttributes().get("inputStyle")));
getUtils().writeAttribute(writer, "tabindex",
component.getAttributes().get("tabindex"));
getUtils().writeAttribute(writer, "type",
variables.getVariable("type"));
getUtils().writeAttribute(writer, "value",
getInputValue(context, component));

I mean who does that in the 21th century in an object-oriented programming language?!?!?!?!?

Here's another example of pure madness:

writer.writeText(convertToString(
"dayListTableId: '" +
convertToString(clientId) +
"Day', \n weekNumberBarId: '" +
convertToString(clientId) +
"WeekNum', \n weekDayBarId: '" +
convertToString(clientId) +
"WeekDay',\n currentDate: " +
convertToString(getCurrentDate(context, component, currentDate)) +
", \n selectedDate: " +
convertToString(getSelectedDate(context, component)) +
", \n datePattern: '" +
convertToString(component.getDatePattern()) +
"',\n jointPoint: '" +
convertToString(component.getJointPoint()) +
"',\n direction: '" +
convertToString(component.getDirection()) +
"',\n boundaryDatesMode:'" +
convertToString(component.getBoundaryDatesMode()) +
"',\n popup: " +
convertToString(component.isPopup()) +
",\n enableManualInput: " +
convertToString(component.getAttributes().get("enableManualInput")) +
",\n showInput: " +
convertToString(component.getAttributes().get("showInput")) +
",\n disabled: " +
convertToString(component.isDisabled()) +
",\n readonly: " +
convertToString(component.getAttributes().get("readonly")) +
",\n ajaxSingle: " +
convertToString(component.getAttributes().get("ajaxSingle")) +
",\n verticalOffset:" +
convertToString(component.getVerticalOffset()) +
",\n horizontalOffset: " +
convertToString(component.getHorizontalOffset()) +
",\n style:'z-index: " +
convertToString(component.getAttributes().get("zindex")) +
"; " +
convertToString(component.getAttributes().get("style")) +
"',\n firstWeekDay: " +
convertToString(getFirstWeekDay(context, component)) +
", \n minDaysInFirstWeek: " +
convertToString(getMinDaysInFirstWeek(context, component)) +
",\n todayControlMode:'" +
convertToString(component.getAttributes().get("todayControlMode")) +
"',\n showHeader:" +
convertToString(component.getAttributes().get("showHeader")) +
",\n showFooter:" +
convertToString(component.getAttributes().get("showFooter")) +
",\n showWeeksBar:" +
convertToString(component.getAttributes().get("showWeeksBar")) +
",\n showWeekDaysBar:" +
convertToString(component.getAttributes().get("showWeekDaysBar")) +
",\n showApplyButton:" +
convertToString(component.getAttributes().get("showApplyButton")) +
",\n resetTimeOnDateSelect:" +
convertToString(component.getAttributes().get("resetTimeOnDateSelect")) +
",\n defaultTime:" +
convertToString(getPreparedDefaultTime(component))), null);


Finally please note that both fragments come from the same single method and that's just a fraction of that method!

Now you tell me: would you ever use stuff that looks like that underneath the skin?

Wednesday, April 14, 2010

JSF - a component framework only the mother can love

Hi there,

this is another JSF nonsense - the component creation style.

I'm just sick an tired of going over the renderers that don't render anything, the component tags (like it's not enough to have just one of those guys)... I mean come on!!!

For those of you that say that JSF 2.0 make a difference I rush to clarify that it is so not true - the component model didn't change even a bit! What they added is Facelets which is what most people were already using anyway.

What's screwd though is that Facelets is a templating engine and they try to use it for component creation. That's grouse!!!