Kiss My App

Wednesday, December 29, 2004

The Corporate Developer

As is such for developers in large companies, you aren't writing a single application for a customer, but you are writing and maintaining seven or eight applications; all with common data structures and requirements. While most of the material we read serves the common case of 'one application for one customer', I don't think there is enough material on the web to support the 'corporate' developer.

Application versus Business Requirements


First and foremost, I don't think there is any emphasis on being able to seperate business requirements and application requirements. To most developers, they are all lumped as one and efficiently categorized in layers and facades. For example, requirements that dictate the validity of orders must be carefully scrutinized so that you can draw the line between what is required for some purchasing application and what is actually intrinsic to the company's operation.

The reason for splitting business and application requirements is for reusability. What behaviors are global and can be reused on other projects while what behavior only helps define the application you are currently writing. I've seen too many programs written that put business logic in their Struts actions (I'm at fault too), then re-written in other applications. If business rules suddenly need to be changed, you now have to maintain these rules in two or more deployed applications.

The corporate developer must be very aware of the differences and seek out their company's business analysts for the answers. The other resolve is that requirement specifications should be categorized into application and business requirements. Some may argue that simple facades are the solution, but we are not talking about layers, we are talking about domains and deployment-- issues that are really only discussed at the enterprise level.

In the following, I will try to describe a bit on how to handle business requirements, and then application requirements, followed by a small rant on persistence solutions.

Business Requirements


I can't help but to use cliché terminology from here on out, but hopefully some of my opinion will make some sense. In the business domain, the key is reusability. This is done though by creating stateless services that offer procedural behavior and beans that only provide state.

I want to start with business rules and behavior. The new hot topic is Service Oriented Architecture. The idea is to build stateless services, modeled as functions that reflect business rules or expose business data. The goal is not only to serve behavior to the innards of your applications, but also provide data to desperate systems where the protocol may be RPC, SOAP, CSV, or just XML. In this case, providing a service layer (that acts like a DAO) would now be useful in a case by case basis (I don't care for DAO's which I will get into later).

Since services now model business rules and behavior, how do they work with data? My suggestion is to keep behavior out of the beans your persistence mechanism works with. Since services may work with both Java beans and SQL datasources, try not to add complexity by having services be dependent on behavior provided by the beans they recieve or gather. Another reason to have services work with behaviorless beans is that behavior can't easily be transferred in a CSV file or XML. To sound like a broken record, the goal is reusability and protocol independence.

In summary, there are few points:

  • Stay away from writing lots of DAO services that encapsulate your relatively static database models. Again, more on this in the section on persistence.

  • Within the business domain, data objects are behaviorless. This is so the same object can be exposed through other protocols and business services are never dependent on behavior offered by objects during service collaborations.

  • Define simple services in Java code that could theoretically be tested in a number of deployments. This means accessed directly within Java applications, or deployed with Axis for use with SOAP RPC, etc. Another rule of thumb is that services should only take in a single parameter to encapsulate change


Application Requirements


The business domain offers us behavior through stateless services and beans that represent the state of our datasources. It is now the application's job to script collaborations between behavior and state. The best pattern to handle this is the domain model. Notice I've pushed the use of a domain model out of the business domain and into the application domain. Core J2EE patterns calls these Business Objects, which is kind of a misnomer in my humble opinion. In collaborating state and behavior, there are other issues that arise such as stale data and transaction management to name a few. A lot of these requirements are often defined on a per application basis and cannot be modelled globally for all concerns within the business domain.

An example would be pulling up and working with a purchase order. The controller layer accesses a service or persistence layer in order to gather an object reprentative of "OrderData". To now provide application behavior, the "OrderData" is wrapped in a domain object called "OrderSession". Within "OrderSession", it collaborates between business services and the state it was provided or gained in order to serve the requirements of the application.

Another requirement would be now validating that order. How and when does it get validated? The 'how' is probably a primary business requirement that defines what the business requires to be able to process an order. This means you may want to create an OrderValidation service that can be exposed or deployed with applications. The second issue was 'when' does the order get validated? This is going to be an application requirement. The when and how together are dictated by your domain model, or to use the example above, within the "OrderSession".

Applications should be free define their own services. These application services often use the transaction script pattern to collaborate between business services in order to serve an application requirement in a procedural manner. Even within domain objects, application behavior should be delegated to services or procedures that aren't locked within a single object.

To summarize the application domain:

  • The application domain relies heavily on domain objects to model collaboration between business services and state in order to serve the application's requirements on a case by case basis.

  • Domain objects themselves should delegate state to reusable, purely stateful objects and behavior to reusable, stateless services.


Persistence


One of the biggest wastes of time developers get into is trying to model the whole business in a series of reusable objects. I did mention using behaviorless objects within the business domain and application domain, but no where did I discuss the importance of a single object model. The reason? Can an order from your handheld application always be the same order that's used in your web sales application? Do all services require the same data from an order? Some parts of your applications may only require an account number, while in other cases an order would be expected to have an account object. Get over trying to model the business in a beautiful collection of aggregate objects, it doesn't work for large companies.

Often times the solution for persistence is a layer of DAOs. I'm actually not a big fan of DAO's. DAO's could be considered a subset or type of service in implementation, and to have a all DAO calls done through a seperate service facade is unecessary for the most part. Also, since DAO's define procedures (representative of a single requirement), they lead not only to bloat but also can add unecessary restrictions to your databases intrinsic business model and the data it contains.

The solution is to examine technologies like Hibernate or JDO and to work with them directly in an "open" manner. These technologies are basically an alternative to straight JDBC, and let's be frank, database's information is where most business make all their money. Why restrict access to it with DAO's and extra facades? The goal is to be able to openly gather the data you need on a case by case basis that most optimally suits the requirement.

You may be thinking about encapsulation at this point, which I'm not saying is bad, just don't try to encapsulate all database access into a golden object model. We want to find a solution that freely allows you to discriminate data without a Java model to conform to everytime, and that's the key point here. Re-evaluate the logic of taking the database model and conforming to an aggregate object model only to produce composite objects for some other application model that's probably a truer representation of what could have been done with a single SQL query.

Fowler has written a bit on Java and SQL collaboration. Fowler is right in saying that there's been a growing seperation between databases and applications. Again, my simple point is to find a flexible solution like Hibernate or JDO. By allowing your code to freely work with an open framework like that, you can gather just the right information you need at any point. Configuration files for JDO or Hibernate are just as easy to maintain as lots of procedural methods on DAOs.

I've followed up this part with an entry on dual persistence strategies.

Conclusion


Corporate developers must think about the big picture in assessing requirements. What is a global requirement of the business and what is required by this one particular application? Implement business requirements in a transient/stateless manner and use domain models only within the specific requirements of each application.

For those apprehensive about committing to a persistence framework without using a facade, trust me, it's just as likely that your application framework will become outdated way before then. Where I find DAO's and persistence facades useful is where there is a specific requirement to handle any multitude of datasources, but always keep in mind that I'm talking about corporate environments with legacy mainframes and server farms.... but I wouldn't hesitate to model simpler projects the same way.

Workflow Continuations

Programmers are looking for simpler ways to define workflows. The simplest form is using what Fowler calls a transaction script. Interactions between the client and server are scripted out in simple method calls-- pretty simple, it's kind of like stating the sky is blue.

With the web, things aren't as simple. During client and server interactions, the client can basically hold the 'transaction' for an infinite length of time (20 or 30 minutes in most cases for the life of their sessions). A couple of solutions to this "wait" period are:

  • Put the workflow in a thread, present the view and put a wait lock on the thread until the next response comes in.

  • Break up the steps of the transaction into seperate methods that allow the transaction to simply be a series of action calls-- such as Struts, etc.

  • Implement continuations to allow the process to mark "pauses" in the execution without the need for threads.


Recently, there has been some talk of having the JVM include continuations-- allowing the JVM state to be paused or persisted and continued at a later time. I've looked at what James Strachan has been doing with CodeHaus and what Rife is suggesting as a solution to scripting transactions on the web. I'm finding a couple issues with continuations as a solution to web applications, such as:

  • I have concerns with memory usage, if the stack/heap is popped from the current thread, how will that be managed? When will the memory be reclaimed?

  • If your thread exits the current process via continuations to serve up the view, nothing says that the state can't change in ways unexpected. Traditional transaction processing involves calling the same processes over and over until it's successful. Continuations say that I can be half way though the process and pick up exactly where I left off-- half way done already. But if we can't restrict changes to the state, then we really can't just pick up half way through the transaction again.

  • Continuations, like AOP can *allow* for poorly written code. By forcing programmers to break operations up into steps, it leads to reusable code. Continuations could lead some programmers to scripting 'special cases' everytime without exposing processes for reuse.


The solution then to modeling workflows? I don't have one yet. I am currently investigating using the visitor pattern with actions, but this may only add unecessary complexity for the common case. Hopefully I will write more this idea later.

Monday, December 27, 2004

Easing Project Development with CSS

A while back, I wrote a short bit on the benefits of CSS. Based on some recent debates within the JavaServerFaces community, I'm not sure developers fully understand what CSS can bring to the table of web applications. CSS isn't simply a new way of marking up HTML, but a new paradigm in web page development.

For those with A.D.D., click here to jump right to the summary. As a proof of concept, click here to see a sample project I'm currently working on.

Structure vs. Presentation


Let's first start by talking about development roles and concerns. MVC has taught us how to seperate our application into managable layers. We have the Model and Controller which are under the programmer's ownership, then we have the View which is under both the programmer's and designer's ownership. This is where issues arise as both the programmer and the designer wish to implement their concerns in the cleanest way possible within the same document or page.

Your programmers' concerns are to provide structure and data to web pages; really they shouldn't care how the data is presented, only that it's there and functions within the application requirements. The designers' concerns are to properly present information in a meaningful manner and should not concern themselves with knowing any server technologies such as tag libraries or the application's Java model.

How is this possible? By seperating structure and presentation with a proper CSS strategy. The end result is you have a base template for all JSP pages that is made up of a few <div> tags where the programmers can play freely, and the designers have free roam of CSS styles via external Style Sheet files. In order to give you a head start on your next project, I will outline a simple, agile strategy to use.

Gather Your Requirements


This phase is familiar to most, but we are only focusing on content at this point. The goal is to gain full knowledge of the amount of information your page structure will have to handle. One of the biggest mistakes designers can make is laying out a page structure without fully understanding the all of the content requirements. Programmers are used to these processes and can easily apply them to web design.

In a brain storming session write each content requirement on a notecard. These requirements can support any part of the application, such as: display global navigation, show order total, display validation errors, and show current login name. The next step is to group the requirements based on the following:

  • Requirements common to all pages. These requirements categorically occur only once on a page.

  • Requirements specific to a single page or section of the web site. These requirements or similar ones could show up multiple times on a single page.



Common Content Requirements


This is simple enough as most sites have common content requirements such as displaying the global navigation or showing the company's logo. These common requirements to all pages will be use to define your JSP template's structure in <div> elements. The <div> elements don't necessarily have to match up to specific requirements, but think of them as mapping behavior to object hierarchies. An example would be:

<div id="page">
<div id="header"/>
<div id="navigation"/>
<div id="subnavigation"/>
<div id="content"/>
<div id="sidebar"/>
<div id="footer"/>
</div>

Notice that we are using id's on the structual <div> elements. Since these elements will be common to all pages, designers can identify these one and only elements within their CSS files to support the layout.

It is very important to get designers' input in defining the common page structure. As a programmer, you are only concerned about being able to categorize your data within that structure. The designer will still need to be able to present that structure in a meaningful way with CSS. Undoubtedly, the designer will already have some layout ideas and will want to add or move <div> elements around. Some of the elements the designer may want to add will only act as "hooks" for laying out content (think of them as template methods). This is okay since we are simply decorating while preserving the original structure. The less elements, the better.

<div id="page">
<div id="header"/>
<div id="navigation"/>
<div id="subnavigation"/>
<div id="content-layout">
<div id="content"/>
</div>
<div id="sidebar-layout"/>
<div id="sidebar"/>
</div>
<div id="footer"/>
</div>

In the above example, we've added hooks for laying out the content and side bar content. The reasons for doing so are beyond the scope of this article, but serve as an example of what should happen to the structure.

Context Specific Content Requirements


You should now think about the second notecard pile of requirements which were specific to some context or page. We will take this pile and categorize it further with the help of the designers.

In reality, we have two different kinds of requirements left, content requirements for a few pages or section, and content requirements specific to a single page. The reason for working with both sub-types of requirements is that we need to now categorize all these requirements within the page structure previously created. These requirements could be anything from displaying validation errors to showing related links. The designers will start to prioritize/categorize these requirements as members of the "content" or "sidebar" <div> elements.

Previously, we labeled our common structual requirements with id's as they were first class members of the page and common to all pages: banner, footer, and content. These other, context specific, requirements could theoretically be replicated multiple times on the same page, such as displaying related links or displaying an order's status. In terms of design, these would show up as boxes within the side bar. Since these elements show up multiple times in a page, we specify them as CSS classes. We don't necessarily care how they are decorated at this point, only that we can categorize these requirements and label them at this point.

<div id="sidebar">
<div class="sidebox">Order Status</div>
<div class="sidebox">Related Links</div>
</div>

There are exceptions to the above statement, but the general rule is: use id's if there can only be one structual occurance of an element on a page, otherwise define a class that can be used multiple times for content categorization. You would be free to use an id to label your <div> for validation messages if it could only show up once on a single page.

Mocking Up the Presentation


At this point, the programmers should feel free to go work on their models and persistence layers. The designer should now formulate a proof of concept for the view layer by mocking up the presentation layer in straight XHTML. Since the designers usually know XHTML better than the programmers, these mocks will also serve as examples to the programmers to work from.

Page mocks should be used and modified throughout the development cycle as a static version of the dynamic pages the programmers will create. Designers can easily work with styles on their local drives and present changes to the client without worrying about any server-side technology.

Programmer Page Development


By now you should have a pretty good feel for the structure of the web pages. We have also been able to define rules for the programmers with the help of the designers. An example rule would be that the current sub navigation goes in a <div> element with an id equal to "subnavigation".

<div id="subnavigation">
<ul>
<li><a>Employee Search</a></li>
<li><a>Add Employee</a></li>
<li id="current"><a>Employee Reports</a></li>
</ul>
</div>

Notice we label the currently selected navigation item with an id of "current". Since only one navigation element can be selected, we use an id instead of class. We aren't defining any formatting in the above example, simply labeling the structure for decoration by CSS. I'm sure we've all written <c:if> statements to determine if we want to wrap some content in a font tag-- a very poor practice. By relying on CSS, the page structure is declarative and is not intermingled with presentation logic.

By not intermingling presentation logic with the structure, maintenance is much easier. No longer do you have to worry about scrolling inside of tables within tables within rows to find out where some content should be added. Additional development tools will help isolate changes.

The Tools of the Trade


The programmer and the designer each have their preferred tools. You can't expect a designer to be as efficient in Eclipse as they are working with Macromedia Dreamweaver. Since you've initially defined the page structures, I recommend having the designers create Dreamweaver templates for the programmers to use. This serves the purpose of isolating changes in the case where a designer and programmer need to modify the same page or some sub set of pages such as all of the "article" pages.

At the same time, Dreamweaver or not, we've really taken out the need to educate the designers on your application models or tags. It's not their responsibility to deal with how the content gets into the page, only how it's presented. Again, the programmer just needs to make sure that their CSS id's and classes are rendered with their content.

JavaServerFaces


Just like we grouped our 'componentized' our page structure, JavaServerFaces offers components that serve the programmer's data models. A <c:forEach> tag with a twenty or so table-related XHTML tags can now be replaced with a single <h:dataTable> tag for rendering collections of data. The best part is that the specification also 'enforces' the use of CSS via various style attributes on the tag, allowing you to delegate the style to a seperate CSS file.

Even though JavaServerFaces comes with a small set of components, I recommend creating new ones or finding new ones where ever possible. These components can be used in place of importing other JSP pages, such as a menu component or an order basket component that programmers can place on their pages. Again, we are isolating the same kind of changes you have gotten from doing JSP includes.

The basic idea is that you want to stay away from "respecifying" data structures within the page. Behavior such as sorting, filtering, and pagination can be isolated within a custom component and dropped into a page with a single JSP tag.

In reference to the tools of the trade section above, Sun has a great product out called Java Studio Creator for working with JavaServerFaces. Not only do you have drag and drop capabilities for rapid application development, but all styles and presentation are specified via CSS, allowing you to easily use a web designer's external style sheet. Awesome stuff.

Summary of Benefits


Since we've been able to clearly define our structual page "framework" in XHTML elements, lets talk about some of the develpment benefits.

  • Development is now asynchronous between the designer and the programmer. As long as the programmer sticks to the agreed upon structure, the designer is free to modify the look and feel of the site at any time without touching the programmer's work.

  • Ideal for environments with micro-managment. Even after the site has been pushed to production, web designers can easily change fonts and graphics in seperate CSS files. Theoretically, you could give your site a whole new look without modifying any pages, only the CSS files.

  • Page structure is much easier to maintain when it isn't intermingled with presentation glitz, such as layout tables.

  • Use id's to label structures that are unique to the page (only one possible occurance) and use classes to label structures that are reoccuring on a single page or slightly different across multiple pages.

  • Use Dreamweaver MX to template pages. Templating technologies such as Sitemesh and Tiles serve the programmer and don't really do anything for the web designer. The designers have ownership of Dreamweaver templates and can easily reflect changes in programmer's JSP pages without modifying their content in any way.

  • Use Sun's Studio Creator to rapidly develop web applications. Studio Creator generates code that has a clean seperation of structure and presentation with CSS. Programmers can create functioning applications quickly and later replace the default styles with those provided by the web designer's CSS files.

  • CSS is quite capable and nay-sayers should spend some time reading and exploring actual examples of CSS design. Mainstream sites such as Yahoo, ABC News, Mapquest, Sprint, FastCompany, and ESPN are all going to a strict XHTML/CSS format.

  • Using CSS media attributes, a single page from a programmer can serve screens, print, and handhelds at once.


I have to admit that taking this approach may initially slow development as employees spend time educating themselves. But from a pure maintainability and flexability aspect, I can't think of a better way to do web pages today.

Sunday, December 19, 2004

Yet Another Servlet Filter You Can't Live Without

At work, we were looking for ways to reduce bandwidth usage on our secure applications. We already have the compression filter, various object caches, etc-- everything you read about. Then we started looking into caveats with using SSL and found something surprising-- HTTP 1.1 SSL usage prevents ANY content from being cached on the user's drive. "So you mean those massive JavaScript and Stylesheet files are getting pulled down with each secure page?" Yes, images too-- multiple times on a single page even.

The solution? Yet another Servlet Filter you can't live without that will be bound to your static content such as Javascript, CSS, and image files. The code for the filter is only a couple lines, but the goal is to write out the 'Cache-Control' header and the 'Expires' header.
long durationSeconds = 28800; // 8 hours

response.setDateHeader("Expires",
System.currentTimeMillis()
+ (duractionSeconds * 1000));
response.setHeader("Cache-Control",
"public, max-age="
+ durationSeconds);
chain.doFilter(request, response);

I couldn't believe how much bandwidth we are now saving with our SSL applications. Read more here.

Friday, December 10, 2004

Validation via Annotation

I've been beating around the bush with posting some of my ideas for validation via annoations. The implementation is extremely simple and offers a protocol independent way of validating input on setter calls. If the validation stuff doesn't interest you, the method of plugging annotations might be applicable to other things.


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Validate {
Class<? extends ValidationHandler> value();
}


Notice that this annotation is meant for annotating other annotations (!) and has a single 'class' value which will be used to handle validation.


public interface ValidationHandler<T> {
public void validate(T settings, Object value) throws ValidationException;
public Class<T> getSettingsType();
}


This is where the validation logic goes. The ValidationHandler is generic and is defined for a specific settings type-- which will be an annotation in our example. To give you some insight at this point, a 'settings' annotation would have minimum and maximum lengths for a String on some bean property's setter, such as 'setLogin(String login)'. Now for an implementation:


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Validate(ValidateExprHandler.class)
public @interface ValidateExpr {
String value();
}

public class ValidateExprHandler
implements ValidationHandler<ValidateExpr> {

public void validate(ValidateExpr validateExpr, Object value)
throws ValidationException {
String i = (value != null) ? value.toString() : "";
Pattern p = Pattern.compile(validateExpr.value());
Matcher m = p.matcher(i);

if (!m.matches()) {
throw new ValidationException(i
+ " does not match the pattern "
+ validateExpr.value());
}
}

public Class getSettingsType() {
return ValidateExpr.class;
}
}


The above example would be used to validate something like an email address or some other user input. The ValidateExpr annotation is annotated with the Validate annotation with the class value of its handler-- ValidateExprHandler.class. Again, the annotation defines what class type is going to handle it. Annotating your object becomes quite simple once you've written a validate annotation and it's handler (two type declarations and two methods).


@ValidateRequired
@ValidateEmail
public void setEmail(String email) {
this.email = email;
}

@ValidateRequired
public String getPassword() {
return password;
}


The final piece to the puzzle is the code to introspect and evaluate the handlers. For brevity's sake, I'm just including the tricky part of it all.


public static void validateProperty(PropertyDescriptor p, Object value)
throws ValidationException {
Method m = p.getWriteMethod();
if (m != null) {
Annotation[] a = m.getAnnotations();
Validate v = null;
Annotation s = null;
ValidationHandler h = null;
for (int i = 0; i < a.length; i++) {
v = a[i].annotationType().getAnnotation(Validate.class);
if (v != null) {
try {
h = v.value().newInstance();
s = m.getAnnotation(h.getSettingsType());
h.validate(s, value);
} catch (InstantiationException ie) {
} catch (IllegalAccessException iae) {
}
}
}
}
}


You may be thinking that there's too much reflection going on, but annotations are statically typed, so you wouldn't have to think twice about caching all the validators for an object.

I was thinking this same kind of annotation could be used for converters in the view, where again, we define a single Converter annotation that has a ConversionHandler type with two methods: stringToObject(T settings, String str) and objectToString(T settings, Object obj).

The reason why I like this way of providing behavior is that by annotating, we have not changed the behavior of the object itself. In addition, you have type safety and IDE support and the implementation is protocol generic so it can be used within JSF, Struts, or before persisting.



Tuesday, December 07, 2004

Rediscovering OOP

I remember writing Java Battleship in my freshman year of college. You know, it was your first big programming project that everyone has. That first project that you want to set yourself above everyone else in class. Simply coloring squares in a grid? Not for me sir, we are talking actual ovals with holes for the pegs. How about we go one step further and add a simple AI opponent? It's something I'm still proud of to this day, but not when I look at the code--

One thing I really thought was awesome, in the Computer Science program I graduated out of, was that our curriculum included not one, but two semesters of patterns in software development. When I came into my first job, that's all I could speak in-- command this, filter that, use the bridge pattern here, and pass a memento over there. Wow, my first job out of college and I was lucky enough to be the 'lead' designer on their next enterprise application. I went wild with patterns, everything in it's own layer which delegated to the next through a series of half a dozen interfaces. What a beautiful mess.

I thought patterns made my code the cleanest it could possibly be. The best part is that other new programmers to the project would follow the same patterns that I laid out before them; adding even more useless implementations to the application.

About 6 month later, I discovered AOP. What if I had gotten my hands on AOP when I started my last project? How easy would it have been to model customer and account relations? How easy would it have been to manage transactions on this method or that method? So I started investigating its ability to model what we were doing at work-- even started implementing some foundation components that were geared for use with AOP. I came back to my managers and coworkers with some examples and AOP articles I've read-- and this is where I hit a brick wall. "Who's going to maintain that? I don't understand pointcuts, can't we just do it this way?" I felt discouraged by the response I had gotten from others and tried to find some way to argue that we needed to adapt to the future, which I believed was AOP.

I started looking for methodologies like Agile development that would encourage new development with AOP. Consequently, I picked up a copy of Agile Software Development by Robert C. Martin. I know that Agile development promotes quick development and lighter code and documentation, it all sounds so good. Maybe this book would have the ammo I need to bring back to my department in order to encourage AOP? Starting from chapter one, it described the processes we should be doing in software development, the steps in managing the code we wrote. But, then I continued on into the chapters on object oriented principals and found myself second guessing every program I've written before. This wasn't the way I've modeled objects before! Single Responsibility, the Liskov Substitution Principle, compositional objects and delegation? As I read, I started to put things together in my mind, the same as I had done while reading about AOP. If I would have simply followed these few principals in the first place, maybe our application wouldn't have been so difficult to model in OO?

If I would have used the Single responsibility Principle here in the first place and delegated here, I wouldn't have all these other concerns to maintain in AOP. I'm not saying that I found the 'meaning of OOP', but pretty damn close. I backtracked through my other patterns books and bookmarked articles with a much higher degree of understanding at what we were trying to accomplish. I found some programmer's writings to be misdirected, while strengthening my opinion of others.

In a sense, I feel as though I missed out on something when I initially learned OOP (probably a fault of my own). I don't feel the strong need to seek out frameworks or patterns to do X or Y, I'm going back to basics-- good citizen principles, contracts, object inheritance, composition, delegation, etc. My code becomes unbelievable intrinsic and light, I'm no longer seeking patterns and frameworks as solutions but now realizing the solutions inherent to the language itself. "Keep it simple stupid," I said, and boy was I stupid.

Friday, December 03, 2004

Factory Pattern w/ Delegates

I've been focusing some of my efforts on rounding out a lightweight IoC Factory. The implementation is fairly simple, you have a Factory object that has Delegates, each Delegate represents a type that can be created by the Factory. The Factory itself only has few methods on it:

public interface UserDao { ... }

public class UserDaoImpl implements UserDao { ... }

public class User { .... }

public class UserSaveAction {
public UserSaveAction(UserDao dao) { ... }
public UserSaveAction(UserDao dao, User user) { ... }
// getter/setters
public String save() { ... }
}


DefaultFactory f = new DefaultFactory();
f.register(new SingletonDelegate(UserDaoImpl.class));
f.register(UserSaveAction.DELEGATE); // register(Delegate)

...
// builds a UserSaveAction with new User
UserSaveAction newUser = f.get(UserSaveAction.class);
newUser.setFirstName("John");
newUser.setLastName("Doe");
newUser.save();

// refetch that user, generics removes the need for casting
User user = f.get(UserDao.class).getByFirstName("John");

// get(Class,Object... params) (variable arguments)
UserSaveAction updateUser = f.get(UserSaveAction.class, user);
updateUser.setFirstName("Jacob");
updateUser.setLastName("Hookom");
updateUser.save();

In the above example, we've registered the UserDaoImpl in a Singleton Delegate. The Delegate lookup within the Factory is smart enough to return the UserDaoImpl anytime a developer requests UserDao (it's interface).

One thing you'll notice is that the 'get' method uses variable arguments, just like the new System.out.printf(...) method. This allows the Delegate to take that input and automatically uses it during instantiation. e.g., UserSaveAction has a 2 constructors, calling Factory.get(UserSaveAction.class) didn't take any parameters, so it will create a UserSaveAction with whatever other Types are in the Factory (UserDaoImpl). In the second case of updating a user, the example had taken in a user-- get(UserSaveAction.class, user). This caused the Factory to find a constructor that also took in a User object.

In order to speed up performance, lets say this Action was used on the web and we wanted to squeak out a little more performance, UserSaveAction declares it's own public Delegate to be registered. This allowed UserSaveAction to control how it was going to be created based on input.

public static final UserSaveDelegate DELEGATE =
new UserSaveDelegate();

public static class UserSaveDelegate
implements Delegate {

public UserSaveAction create(Factory f)
throws ActualizationException {
return new UserSaveAction(f.get(UserDao.class));
}

public UserSaveAction create(Factory f, Object[] p)
throws ActualizationException {
return new UserSaveAction((User) p[0],
f.get(UserDao.class));
}

public Class getType() {
return UserSaveAction.class;
}
}

By creating it's own delegate, my performance tests performed only a fraction slower than wiring the components together directly.

I would now like to add "listener" behavior to creation. Allowing additional components to be wired together in ways other than constructor injection-- such as annotations. I'm open to suggestions on how/where the listener behavior should occur, if it should be assigned on a per Delegate level or at the Factory level. Also, since the Factory doesn't dictate lifecycles at all, listeners at the Factory level would be notified whenever an object is "grabbed", not knowing if it was just created or if it's the 4th time it's been grabbed.