Thursday, July 12, 2012

Anemia or not anemia, that's the question

Bottom line:
A refactoring transition from an anemic to a rich object model is possible, painful, and—at least for me—necessary.

I'm currently working on an anemic, Struts based J2EE POJO solution that is a few years old. As I understand it, it goes by the book, with class name patterns like OrderLogicOrderDTO (Data Transfer Object)OrderDAO (Data Access Object) and Hibernate annotated OrderVO (Value Object). They implement an anemic model with logic classes and DAOs containing purely code, and DTOs and VOs containing purely data, close to a Table Module architecture, with VOs acting as data records, which is basically a well structured Transaction Script model: Plain old data based, structured programming.


Oo freak as I am, this frustrates me, especially as there is leakage of responsibility between the classes. On the positive side, there are some good architectural efforts, with OrderLogic managing the high level request for orders, delegating the pure db-access to the DAO. Operations on the resulting OrderVO is mostly also found in OrderLogic, but also elsewhere, for instance in Struts Action classes, as well as in other XxxLogic classes. And there is duplication. And, surprise, surprise, all this is also to be expected, "by the book".


For my brain to function properly, I need to apply the SRP and the IE principles, so as to find my operations close to my data. I also need to support the changes I make with TDD. All this requires a rich, non-anemic domain model. Successively, instead of one big folder (and namespace) common for everything relating to say customer and order management, I create folders for three architectural layer, like Presentation Layer (common.PL), Domain Logic (common.DL) and Data Access (common.DA). To start with, PL contains the DTOs and related stuff, DL contains the new domain objects and other domain layer logic, like class repository objects, mostly refactored out of the Logic classes. Finally, DA contains DAOs and DVs. 


At least, that's what I thought.


Actually, after some refactorings, I am heading in a slightly different direction. In my search for how to design my domain objects, I have investigated three different models:
  1. inherit from the VOs
  2. delegate to the VOs
  3. promote the VOs to rich domain objects
I chose the third one, So I am successively moving the VOs to the DL (Domain Logic) package, removing the VO postfix in the process, and successively moving logic from Logic classes and elsewhere into them. That raised the dilemma of the DAOs, managing the low level Hibernate access and actually creating and saving the former VOs. They cannot be located in an architectural layer below the objects they are to manage. So now, I have promoted the DA package to the domain logic layer, and I am moving the Repository classes into DA, the difference between them and DAOs being that DAO contains the Hibernate mapping, whereas the repositories handle requests for domain objects from the rest of the system.


When time allows, I will add a figure here to explain this more clairly. For the time being, I am curious to see where this strategy takes me.

Wednesday, May 9, 2012

Comments considered harmful 2

I am getting "Too many open files" errors. So I check every usage of files and streams, and make sure I always close them. Here is a snippet I found that was not closing the out stream after use (empty lines and failure detection suppressed):

JspWriter out = pageContext.getOut();
if (errorMessageToUser == null)
{
    drawCalendar(out);
} else {
    out.println(errorMessageToUser);
}


So I add a line closing the writer, like this:

JspWriter out = pageContext.getOut();
try {
    if (errorMessageToUser == null)
    {
        drawCalendar(out);
    } else {
        out.println(errorMessageToUser);
    }
} finally {
    out.close();
}


Of course, this broke one of the golden rules, saying that you only should close files that you have opened yourself. This writer was opened by the jsp framework, so I got a "Stream already closed" error somewhere else when jsp wanted to close it.

I need some way to avoid redoing the same mistake. My first attempt was to add a comment:

JspWriter out = pageContext.getOut(); // Don't close
if (errorMessageToUser == null)
{
    drawCalendar(out);
} else {
    out.println(errorMessageToUser);
}


Now, I have a problem with this kind of comments. It is localized with the declaration, so to see it, you have to go back there. My recommended practice today is to try to incorporate the comment into the variable name. So this is my present version of this code:

JspWriter outDontClose = pageContext.getOut();
if (errorMessageToUser == null)
{
    drawCalendar(outDontClose);
} else {
      outDontClose.println(errorMessageToUser);
}


I find this pattern outstanding. By being its own comment, the code tells me about its semantics, its rules of usage. And, best of all, it is not localized to the point of declaration. I am reminded of the rules every time I see the variable name.

Thursday, November 3, 2011

Comments considered harmful

At school, I was taught to comment my programs well. Today, I wonder why I should.

Every comment relating to the code itself is redundant. Redundancy creates inconsistencies, and inconsistencies are a serious threat to code quality. So I prefer not to comment.

"Hey, come on! How do you expect anybody to understand your program if you don't comment it?" I hear being shouted at me. I will ask the opposite question: Why should I write such a lousy program that it needs comments to be understood?

I worked in a group where the coding guidelines said: Comment every class, comment every method. I refused. I mean, as an example, look at this getter, generated by the Refactor -> Encapsulate Fields... operation of NetBeans:

    private String name;
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

What does that comment add that I did not already learn from the method name? So rather than commenting a method, I prefer to use the comment,  kind of, as the method name. That guarantees consistency and also propagates the "commented" intent to every place the method name is referred to. Far superior to a localized comment!

Martin Fowler once said: "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." I strive to be one of them.

Friday, September 30, 2011

Iterations and increments iterated

It seems hard to get this right. Jeff Patton uses Mona Lisa to explain it. Alistair Cockburn uses Michelangelo and van Bruegel the elder, stating that "Incremental means adding, iterative means reworking" (my emphasis). That would be in the product dimension. Thomas Nilsson, in a Swedish agile forum, writes "In my world, incremental relates to the product dimension, whereas iterative relates to the process dimension" (my emphasis).

To summarize, I find it helpful to consider iterations and increments in both of these dimensions.
  • An iterative process would be like any agile process. You repeat the same development activities over and over. That's what we like to do.
  • An iteration in the product dimension would be, as Cockburn points out, improving quality or functionality of the product. That is certainly legitimate in a lot of situations. You make a tentative solution — not necessarily a prototype — and you present it. It may be accepted or rejected. But even if accepted, the customer may want to iterate on it to improve it. Tom Gilb calls it evolutionary development. And we may want to iterate on it, refactor it, to improve its internal quality.
  • An increment in the process would imply doing more and more things in each iteration, like documenting more, testing more, designing more, or even adding new steps. This happens in many situations where thing go wrong. Then you add rules or steps to go through to prevent that from happening again. Isn't that how heavy processes emerge?
  • Incrementing the product would be adding new features to it. That's what we normally do.
All of this may be summarized in a small table.
Is this distinction helpful? Well, I think it is always helpful to understand the words you are using.

So, within the framework of an iterative process, we both iterate on the product and we increment the product.

Does all of this assume an iterative process in the first place? I don't think so. Look at a typical waterfall development process. While deployment may be neither iterative nor incremental, I am sure that in most cases the development is de facto incremental, despite the linear process. The developers are even likely to iterate over the (still undeployed) product. So the product is developed both iteratively and incrementally. But the process is not iterative.

And I find that in RUP, for instance, the process is iterative, and you are supposed to build the product incrementally. But RUP does not encourage iterating on the product itself. To me, that's one important factor that makes it very waterfallish and inapt to adaptive development.

To implement the agile values, the process needs to be iterative, and you need to both iterate on the product and increment the product during your process iterations. Waterfall fails in not being an iterative process. RUP fails in not iterating on the product.

Sunday, April 26, 2009

The Agile Team Room

During a recent training course, we discussed the agile team room, especially the whiteboard space for modelling. Fortunately, Mike Cohn just published a blog, listing the essential features for The Ideal Agile Workspace:
  • Big Visible Charts
  • Additional feedback devices
  • Everyone on your team
  • The sprint backlog
  • The product backlog
  • At least one big white board
  • Someplace quiet and private
  • Food and drink, and finally
  • A window
The comments link to several implementations of this list. For instance, one of the comments link to a tour through the msdn Patterns and Practices Lab and a peek inside the p&p Team Room. Of course, these are quite advanced implementations of Mike's list, but show how important these companies find the physical environment.

Saturday, March 28, 2009

DCI, or restoring order to OO

Object orientation (OO) is often contrasted with structured programming (SP). OO has many advantages when it comes to managing complexity, but it clearly lacks in exposing clairly what the code is actually achieving. SP on the other hand has many defeciencies when it comes to separation of concerns and maintainability, but at least it is normally possible to follow the execution sequence in the code.

In my OO training courses, I frequently warn the attendees, saying that OO may solve the problem of complexity and changeability, but requires another level of competence to maintain clarity and overall understandability. A lack of this competence may produce a spaghetti code that is an order of magnitude worse that the traditional, structured spaghetti code. Please be warned!

Enters Professor Trygve Reenskaug, the principal inventor of the MVC paradigm, with a new DCI paradigm, supported by Jim Coplien. As I understand it, DCI is complementing OO and MVC, supplying the overall interaction scheme, showing how the individual objects, based on their roles, collaborate to deliver business value: It supplies a role based expression of the communication logic, like in sequence or communication diagrams.

I have to look closer into the material, for instance how DCI expresses the communication scheme better than e.g. communication digrams, but it does look interesting.

Sunday, February 15, 2009

… but please do repeat me

Do you have to choose duplication, paralysis, or chaos?

Johannes Brodwall wrote a blog with this title on a subject that has interested me for a long time: How to avoid chaos and support stability in face of a constantly changing interface (my rephrasing). He sketches three different approaches:
  1. Duplicate code, so that change at one place does not affect code somewhere else, but at the cost of duplicated changes of common logic
  2. Share code, to avoid duplicated changes of common logic, but at the cost of requiring change in all the clients when the logic of any of the suppliers changes
  3. Do not allow changes, to avoid both of the inconveniences above, but at the cost of conserving unsatisfactory solutions
I tend to think that the solution will change over time.
  • Initial code is unstable and has only a few clients. Apply approach 2.
  • As code matures and stabilizes, fix its contract (precondition and postcondition). Apply rule 3 and the open/closed principle.
  • A subsequent change may of may not break the contract.
  1. If it does not (weaker precondtion, stronger postcondition), there is nothing to worry about - clients are not affected by the change. All tests will pass unchanged.
  2. If it does, apply rule 1 and define a new function for the new contract, possibly making the old definition deprecated to leave a transision time for the clients.