Kiss My App

Friday, February 25, 2005

Components: JSF or Tapestry

Based on comparisons between Tapestry and JSF, I've been trying to determine who is actually doing components the 'right' way.

The debate should probably start with defining HTML itself as a presentation layer. HTML is 'now' actually composed of two parts with the help of CSS: structure and presentation. For those who've read my previous blogs, this is old news.

Component development emphasizes reusability and modularity. Neither is clearly represented in normal HTML structure under the ownership of a designer. If you want to show a menu on 5 pages, then you must replicate the same menu structure on each page. Now introduce the concept of components such that a menu structure is described once and referenced on each of the 5 pages. Referencing cannot be accomplished in normal HTML-- so we seek out a framework such as Tapestry or JSF.

Tapestry mixes standard HTML and additional attributes ('jwcid' for example) to convey additional dynamic behavior with components. Where I feel Tapestry falls short is that it b*stardizes HTML. Also, the use of elements versus expressions for inserting runtime data is odd (<span value="ognl:...."/> vs. ${bean.name}). Finally, while Tapestry is expressive from a view standpoint, it doesn't offer as strong of a model 1 approach as JSF.

JSF instead uses JSP pages. This is both a negative and a positive. It's a negative in that JSP was never meant to do anything other than simply execute which raises issues that Hans wrote about. The positive is that the JSP document is more dynamic than straight HTML and accepted in most editors.

Maybe it's just because I haven't had much luck with having designers and programmers work in the same document. When a designer designs a page, they are basically creating mock ups with lots of content to play with. When a programmer structures a page, they aren't concerned with the design at all. This difference of concerns leads me to believe that the designer and programmer should develop in two completely different documents. This is why I have a slight distaste for Tapestry. Yes, Tapestry can offer a strong sense of seperation, but you are doing so within HTML which isn't as expressive as JSP.

Referencing a previous article of mine on seperating presentation and structure with CSS, I believe this is only where presentation comes into play with component development. Let the designer design in their document and let the programmer create in standard JSP.

For some reason, I'm not fully comfortable with that conclusion though. When it comes to rendering component structure, I do see the benefits of expressing output directly in HTML (a difficult task with JSF). But then again, maybe we should start looking at HTML simply as a structured XML document-- think of the structures we present with web services to other clients. For applications that require XML, why aren't there any popular templating frameworks-- everything is done in DOM or some other flavor of XML lib that I know of for generating documents. If document structure is agreed upon between the designer and the programmer (and the W3C in this case), why not give the programmer the ability to abstract that structure with components and leverage flexible JSP markup and other tags to express that structure, rather than limiting it to a specialized version of HTML.

Sunday, February 20, 2005

Monkey See, Monkey Do

I went snowboarding today with one of my buddies. He's with a firm that designs/engineers server rooms. He was talking about how well business is going for the firm in part to the fact that software is written so poorly today that companies just keep on throwing more hardware at the problem to keep performance on par. He asked if I thought the development trend would ever resolve itself. No question in my mind, this trend will continue as long as programmers aren't taught the fundamentals programming and fill that lack of knowledge with the wrong solutions.

Rewind to two weeks ago...

I was 'fortunate' enough to attend a week long intro to C# course provided by my employer. The class had about 20 developers of various skill levels which was quickly realized when the instructor started going over inheritance and OO fundamentals.

One of my co-workers who is new to programming was having some difficulty tackling abstraction and interfaces. She said, "We've learned how to do all of this stuff with objects, now we have interfaces and abstract classes? How am I supposed to know when to use them when I'm designing objects?" What a great question! I replied, "Interfaces and abstraction are there to support designing relationships, but never while designing objects."

That can sound confusing, but an example was provided by another guy in class with his 'best' programming practices. He told us that we should write interfaces for all of our Objects, and then provide seperate implementations. This is an example of using interfaces to design objects instead of relationships. Using interfaces to design relationships means: only use them if you have a series of objects that need to interface with another object-- hence the name 'interface'.

Reflect for a second on what you are writing: are you writing an application or a framework? Most of us are writing applications, yet we code them as if we are writing a framework. The old saying, monkey see, monkey do applies here. With open source, programmers are exposed to tons of excellent framework code where they use interfaces and abstraction to allow others to integrate-- this is a requirement of a framework isn't it? Go back to application development. The key with application development is, "Less is more." Don't write extra interfaces unless you absolutely need to and don't abstract objects unless you absolutely need to. You can always refactor later with a few clicks if the need arises.

I'm thinking of putting together a 'best practices' programming guide for my company next week. I might post a link to it here. These are just my ideas on my blog, but we are to a point where frameworks are written for programmers who code as if they are writing frameworks-- enter most IoC containers.

3 Objects - 300 lines of Code

3 Interfaces for those objects - 100 lines of Code

1 Spring XML configuration file - 50 lines of Code

1 Class to Integrate with Spring - 20 lines of Code

1 Year of Application Performance/Maintenance - Slow and Painful

-versus-

3 Objects - 300 lines of Code

1 Year of Application Performance/Maintenance - Fast and Easy

Container and Factory Seperation

I recently finished rewriting a simple container that uses Constructor Injection-- woohoo. I decided to create my own container because I wanted to be able to uniquely manage the lifecycles of a heirarchy of containers: Application, Session, and Request.

The idea is that you separate configuration from lifecycle management through the use of 'wormholes'. This means that objects from the top layer are passed to objects lower in the heirarchy, basically allowing customizations at the top level to act upon data at much lower layers via passed parameters in method calls.

CompositeFactory factory = ....
Container c = new Container(factory);
UserSaveAction action = c.create(UserSaveAction.class);

// the Container...
public <T> T create(Class<T> t, Object... p)
throws ActualizationException {
if (this.factory.contains(t)) {
// note 'this' is passed to factory
return this.factory.create(this, t, p);
} else if (this.parent != null) {
return this.parent.create(t, p);
}
throw new ActualizationException(...);
}

// the internal CompositeFactory reference
public <T> T create(Container c, Class<T> t, Object... p)
throws ActualizationException {
Factory<T> f = this.factories.get(t);
T result = null;
if (f != null) {
// Container passed again
result = f.create(c, p);
}
return result;
}

// within the Factory
public UserSaveAction create(Container c, Object[] p)
throws ActualizationException {
// Container used to wire objects together
UserDao dao = c.create(UserDao.class);
return new UserSaveAction(dao);
}

To take advantage of this layer managment, we seperate responsibilities between the container and the factory.

CompositeFactory cf = new CompositeFactory();
cf.add(new Factory(UserDaoImpl.class));
cf.add(new Factory(UserSaveAction.class));
cf.add(OrderController.FACTORY);

Container mine = new Container(cf);
Container yours = new Container(cf);

In the example above, both containers can act upon and use the CompositeFactory independently of each other. My Container could have it's own lifecycle, while your Container could have a different lifecycle. Ideally, I could pre-configure three different CompositeFactorys for each web scope and allow each user to declare their own Containers backed by their own Session or Request for lifecycle managment.

CompositeFactory app = new CompositeFactory();
CompositeFactory ses = new CompositeFactory();
CompositeFactory req = new CompositeFactory();

// initialize each factory in the appropriate scope

// only once at app initialization
ApplicationContainer appC =
new ApplicationContainer(servletContext, app);


// only once for each session
// pass the ApplicationContainer in as parent
SessionContainer sesC =
new SessionContainer(appC, httpSession, ses);


// for each request
// pass the SessionContainer in as parent
RequestContainer reqC =
new RequestContainer(sesC, httpRequest, req);



I really do enjoy constructor injection as it seems to solve a lot of problems that setter injection has in dealing with 'good citizen' principles. With constructors, when you 'new' and object, it's wired and ready to go. If you depend on various settters to be used, then you have to add code all over to gaurantee that supporting objects have been set before some operation can be made. This is sloppy coding IMHO.

In addition, by following 'single responsibility' principles, you start to write more reusable objects that are used in the construction of more complex objects that are founded on delegation and composition. Really, you reach a point in this style of coding where the requirement for dependency-injection containers kind of falls away.

Wednesday, February 16, 2005

Model 3 Architecture

I've been pondering a bit on web architecture and how component frameworks, such as JSF, should really be interpreted. Most developers are familiar with Model 1 and Model 2 architectures:

Taking from Sun Blueprint Guidelines, "A Model 1 architecture consists of a Web browser directly accessing Web-tier JSP pages. ... A Model 1 application control is decentralized, because the current page being displayed determines the next page to display."

Model 2 is described as, "A Model 2 architecture introduces a controller servlet between the browser and the JSP pages or servlet content being delivered. The controller centralizes the logic for dispatching requests to the next view based on the request URL, input parameters, and application state. The controller also handles view selection, which decouples JSP pages and servlets from one another."

I really don't think that from a developer standpoint, that true component frameworks fall into either of these categories since they draw from the "benefits" of both models. Model 1 architecture allows simplicity of development and removes the need to centralize control. With Model 2 architecture, you have the ability to decouple JSP pages from controller/business logic.

Let me explain how I interpret true component frameworks in relation to the points above:

  1. Similar to Model 1, any combination of components can be declared within a single view.

  2. As with Model 2 "actions", components are implemented in such a way that they decouple controller/business logic from the view.

  3. Components within a single view can operate and execute independent of each other.

  4. Components manage their own state within any number of request lifecycles


To provide an example, lets say you have two different pages below, where the colored sections are identical components and the white boxes are different between the two pages:


Each component acts as an independently of each other as stated above and for sake of discussion, component B is a search box and components E and G are sortable and pageable lists of data.

According to the items I've outlined above, a developer can simply drop component B into any page and get search capabilities without tying it's implementation to any specific page or 'Action'. Also, because components operate independently within their own state and lifecycle, components E and G can be paged and sorted without affecting the rest of the page or having to worry about managing the state of those other components such as the search box.

According to these rules, you can page component E to the third set of results and then submit an invalid query within the search box (B) and have component E preserve its state on the third set of results when the search box returns with an error.

Within current models, some search action would be called, and if it fails, it would have to figure out what page referred it and how to preserve whatever the original view was for all the rest of the features presented (such as pageable and sortable results). Of course, you can find ways using the HttpSession to preserve state in a request/page-agnostic manner, but the point is that you have to code specifically for these cases.

Where I feel that a true component model differs from some other people's concept of components is that they:

  1. Aren't part of a specific 'page' or 'action' as with centralized Model 2 architectures, but fall more in line with Model 1 architectures in that components decentralize requirements in a reusable manner.

  2. Components aren't simply glorified HTML decorators and they actually extend their life beyond rendering to the next request.

  3. Any component included in the view could drive application flow.


I would enjoy comments from others.

Tuesday, February 15, 2005

Framework Consequences

In my blog about dual persistence strategies, someone had commented:

Doesn't this result in tight coupling of view and model? What if we wanted to replace hibernate by iBatis, for example?

In my experience, this mindset of defensive programming only hurts projects as you spend more time developing ways to cleanly abstract models/services than simplifying the core competancies of the task at hand.

In the blog on dual persistence strategies, I mentioned using JSP tag libraries to support the view. I'm not going to slide around this one, it does couple the view and model-- producing a model 1 architecture. Yes, it would be difficult to suddenly switch to iBatis for persistence, but maybe I'm a unique case, but I've never changed persistence frameworks within an application. In using JSP tag libraries, the view becomes dependent on the persistence API you've chosen, which is fine to me. The view is the most volitile part of a web application and would probably be changed before the persistence framework is ever changed.

What if you didn't go with a model 1 architecture and opted to directly call Hibernate within model 2 'Actions'? Well, in a model 2 architecture, the controller Actions still support the view and act as an adaptor to your testable business model. Since the Actions support the view and are at whim for modification to support view functionality, the same consequences apply as model 1. If you now want to support sorting the data set in some view, you are going to have to add that functionality within the controller Action, if not the view. The same arguments apply here as above with model 1.

But I really haven't touched on my first remark on defensive programming. Lets provide two solutions to supporting the view with a persistence framework:

  1. You've chosen Hibernate and use its API directly to pull the exact data you need in less than five lines of code within your Action.

  2. You've chosen Hibernate, but want to accomodate a change to iBatis later. You create a generic persistence facade and create a Hibernate implementation of that model. To implement an Action requirement, you must modify the generic persistence model, and then implement it within your Hibernate implementation.


Now, everyone has their own opinion, but I would prefer to opt for the first choice. Instead of basically writing and maintaining a generic facade for your persistence framework, just make those calls directly. If some issue comes up where you do need to switch to direct JDBC or iBatis, just refactor that code. If you had written and properly maintained the generic goals of your persistence facade, you would still spend the same amount of time developing the new implementation as refactoring existing code. On top of that, it might be likely that your peristence facade was steered by the original implementation, and the new implementation would require additional changes to the persistence facade.

When would I choose a generic persistence facade? For non-view operations that I want to test within a main method, or if I was producing an application with specific requirements to accomodate multiple persistence solutions.