Thursday, April 5, 2012

Back to the roots

I've been going over some of my old stuff that I wrote back in the day in 1998 when I started to work professionally as a developer. Among other things (like using polish names for variables, classes and what have you and seeing absolutely no automated tests whatsoever) I've also spotted some nice stuff that I wanted to share with the class.

DDD was normal

Back in the day having a TTeacher (Delphi) class that knew about the schedule and could tell you which one is going on at a particular point in time was no big deal. Classes were not PODO, they actually knew how to do stuff. Just to give you another example here's something that struck me fairly recently:

Given a Company company and a Candidate candidate if the company decides to hire candidate then the output is an Employee employee. This could be written down more/less like this:
Employee employee = company.hire(candidate)
Now take a look at this and tell me how would you call this now a days? IT IS DDD at its purest! We have domain classes that can be retrieved from some source and operated upon.

Short methods were normal

Actually this isn't entirely true but it was pretty much the standard that a method contained calls to other methods that contained calls to other methods. I kind of felt the necessity too express things clearly or else the code would then be unreadable. So the whole "one-screen method" or "CCC < 5" was kind of natural even though nobody told me to do so. It just felt right.

Coding standard

This has surprised me most: All (and I mean it when I say "all") of the code has one and the same coding convention. There's no deviation whatsoever when there is no special case that needed separate consideration of formatting rules. And above all: it was based on VCL's code. Maybe not 100% equal but very, very close. Now that is some code you read like an open book just a after minutes of getting used to the coding style.

I, J and K were iteration variables - and nothing else!

Back then there was a number of variable names that were reserved for a certain task. "I, J, K" were always and without exception the iteration variables. There was no itinerary "i" or class "K". Similarly "S" was always a temporary string variable. The code was so damn short even though there were no closures to express things better!

What has changed?

Well, what has really changed after the year 2000? There were 3 major factors that influenced me to write worse code:

  • I stopped writing code for myself
  • The schedule became a lot tighter
  • The complexity sky-rocketed when I started writing calculation-intensive apps

With that in the picture when I look at the code I wrote after 2001 I feel like the IQ of the author just dropped 30-40 points!

The Corporate times

One very much disastrous time for me was the time when I started working for an international corporation. And I mean it in every single way one can possibly imagine. That was the place where I learned that even though the application is mission critical (people's life depends on it!!!) it is not really important that the quality of the code is kept at a reasonable level. It was really enough that the application worked around 60%-70% of the time! AAAAARGH!!! I remember fighting the original team members to the death trying to teach'em about quality of the code. That was the time I worked for the first time with "legacy code".

Java - the ultimate readability killer

As much as I hate Java the language for its verbosity and lack of advanced features like properties I'm inclined to say that the worse thing about Java are Hibernate and POJO-style programming model. Why?

Let's summarize what a POJO is, shall we? A POJO (plain old java object) is just a class. This simple and quite good idea turned into a disaster with Hibernate where most of the objects started to be those gigantic pile of annotation crap but besides that didn't contain anything else. That's how I came to learn POJOs as a programming style: dump, idiotic and trivial classes. So it is not a POJO anymore - you might say. And you'd be right! That'd be a dumb Java Object (DJO) but unfortunately when you see code that has to do with EntityManager, pure Hibernate or some other ORM (which is very likely) this is what you are going to experience..

Back to the roots

Now that I am old enough to look back and see the mistakes I made I've decided to find a way to get back to the programming style where a "Company" has the ability to "hire" a "Candidate" which would spit out an "Employee" but at the same time to keep things as separated as they should be for the sole reason of testability.

Spring sucks - Grails to the rescue

It should come as no surprise that my first attempt to mimic a rich domain object was undertaken in Spring. I admit I'm no spring expert and I still believe it is a vastly bloated library but I do get the idea behind it (unlike myself 3 years ago). But stuff is very much complicated with pure Spring. And one thing in particular - dependency injection in domain classes.

When I say that Spring sucks it really means that "Spring sucks by comparison to Grails". It is really great that spring does all the wrapping and all that but making domain classes automatically injectable borders on the infinity...

The whole point to this exercise is to have an object model that is usable without GUI and still makes a whole lot of sense.

Candidate.groovy:
class Candidate {
    String firstName
    String lastName
}
Company.groovy:
class Company {
    String name

    def hiringService

    Employee hire(Candidate candidate) {
        return hiringService.hire(candidate)
    }
}
Employee.groovy:
class Employee {
    String firstName
    String lastName
}
Now how about this:
Employee employee = company.hire(candidate)
Isn't that nice? And it is so damn readable!

The best part of all this is that in Grails domain classes are by default eligible for dependency injection which means that the hiringService is injected automatically. And I really mean AUTOMATICALLY! This means that when you do "new Company(name: "Test")" the "hiringService is automatically injected!!! This is the best thing ever!!!

I strongly recommend you try to look at your application from within the code and see if you can read it as you'd read plain text. If not there's something wrong with either your eyes or the code before you. If I was a betting man I'd go with the latter one :)

Write clean code!

No comments: