Sunday, November 30, 2008

Where's the Metaphor?

Remember that television commercial for a fast food restaurant (I think it was Wendy's) that was boasting about the size of their burgers? They would say "Where's the beef?" when they looked at a competitors product. When I look at the supposedly objected oriented design to which some people code, I am often wondering "where's the metaphor?".

Object Oriented Design is Metaphorical Design
OK, the example might not be the best one I could have used, but the point is that many people claim to be Object Oriented Developers just because they use a language like Java. The fact is that what makes a design truly object oriented is that it has a metaphor that illustrates the expected behaviour. Sure, it doesn't have to have a metaphor to be object oriented. If you have a good imagination, you can dream up your own objects that don't have to have any relationship to the real world at all... but you'll be the only one who understands them. Some might say that if a design uses encapsulation, and inheritance, and perhaps even recursion, it is object oriented. I say that those are only some of the hallmarks of object oriented design. I feel quite strongly, that a good object oriented design requires a metaphor. And in bigger projects, the metaphor has many layers that need to be spelled out.

Large projects almost always involve more than one designer, and the designers need to be able to explain and discuss the design with each other and the implementers. A solid, well thought out, metaphor gives your design clarity. For example, if you are designing a data transfer mechanism, referring to it as a truck automatically conjures an image in the mind of whoever is involved in the design discussion. The characteristics of your design become obvious. It has a paylod, or cargo, it has a route, it has an identification, it has a driver. What if your data transfer mechanism doesn't need a driver? Well, you could just refer to it as a "driver-less truck", or perhaps you pick a different metaphor like "rail car". The point is that when you use a metaphor to discuss your objects, problems with your design jump out at you as absurdities in the metaphor. If you try to use your truck as a storage mechanism, it would become quite obvious that though you could park a truck and leave the cargo in it, that's not what it is designed to do.

Just because you can does not mean you should.
The lack of understanding of even the most basic of metaphors leads to sloppy code that is difficult to maintain. Take the parent child metaphor as an example. A parent has one or more children and each child has a parent. Yes, one could argue that a parent could have lost his child, so the parent could have zero children... Again, we could argue about orphans too. In fact, it is just that sort of an argument that illustrates the value of a metaphor. We could say that a Person has no children, and when they have children they become a parent.

In discussing this model, we often refer to the "has a" relationship. What I am proposing is that we use the "has knowledge of a" relationship instead. The "has a" denotes containment, whereas the "has knowledge of a" relationship denotes a reference. It really boils down to this: "Can one object exist without the other?" If not, then containment may be correct. However, many people mistakenly use containment when reference is correct. The use of metaphors exposes this error. Does a son really contain his mother? No. The son has knowledge of his mother, but he doesn't actually contain her. It is almost conceivable to say that a mother contains a son, but even then it is only during the first nine months that she does. If the mother contains her children, and the children contain the mother, you have a situation where the son contains not only his mother, but he also contains his brothers, sisters, and even himself (since they are contained within the mother). (I really wish people would have used "contains a" instead of "has a" from the beginning... it's much more clear.)

So here come the critics. "But in Java all relationships are By Reference, so it's just a pointer anyways!" You would be correct to say so, and in a stand alone project, I might not be concerned. No real harm in circular references. The mechanics of it will be sorted out for you. But even there, I would say use it with caution. Where it is much more problematic, and the problems harder to spot is when you are using an Object Relational Mapping tool like hibernate. And there, especially if you have a complex data structure. In such situations, one MUST think about whether containment is the correct approach or whether merely a reference to the id would be sufficient.

I was brought in to work on a web project that used hibernate to, among other things, retrieve a collection of 15 objects. No problem. However, each of those objects contained multiple collections of other objects which in turn contained references (sometimes several layers deep) to the first object. To get the 15 objects that were sought, our resultset had to pull down 1.5 million records! This situation did not materialize until some realistic data was used. The problem was not the ORM tool (as some people claimed), it was that the objects all contained each other, and hibernate had no choice but to do a bunch of joins (12 in this case). Once the object model was cleaned up we got the resultset down to something like fifty records. What used to cause the web container to timeout now happens in a flash.

Yes, you are allowed to use bi-directional references. But just because you can, doesn't mean you should. In a web application I think I would take it a step further and say that you may do it, only if you have to do it. (And if you are using something like hibernate, you had better read up on it so that you are sure you are using it correctly! More on that some other time.)

K.I.S.S.
Keep It Stupidly Simple. The KISS rule does not give license to laziness! In fact, it will often require extra effort to keep it simple. In my real world example, it turned out that many of the contained objects were only needed from within the data access layer anyways, so they were easily retrieved on an as needed basis. I suspect that they were only ever contained so that they could be retrieved using dot notation.

It may mean that you have to write a few extra lines of code to get the desired object when you need it, but it will likely mean that the rest of your application runs smoother, and be easier to debug.

Sunday, November 23, 2008

Professionalism

I thought this would be a good starting point for my blog.

I am often surprised when I meet software consultants on client sites by the lack of professionalism. I suspect that it's not that they don't care about professionalism or that they don't know what it means, but rather it's more likely that they haven't given it much thought. Now I realize that if you live in a glass house, you shouldn't throw stones, and I'm not saying that this applies to all the people I've worked with, I have had the opportunity to work with many individuals who exemplify professionalism. In fact, some have helped me to formulate my current opinion on the subject. However, I've often heard people who are not consultants question the value of consultants, and I take offense at that because I strive for a level of professionalism that I feel would silent the critics. My goal here is not to criticize but to correct.

I feel that there are five main pillars upon which professionalism is built. In no particular order, they are; Ethics, Accountability, Responsibility, Quality, and Communication.

Ethics. When I was working at Capra, all our consultants were required to accept and sign our Code of Ethics. Don't agree with it, fine, you just won't work on our projects. None of this is earth shattering stuff, but it seems that every time I read it I wonder how many people have actually sat down and thought about what they consider acceptable behaviour. I'm afraid that unless one takes the time to write it out, one is left to make those judgments at the spur of the moment, and then it's too easy to just go with the flow. Ask yourself, when is the last time you "stopped the clock" when what started out as a business conversation turned to a personal nature like sports or movies? Or how about surfing the internet while you're at work? Have you ever walked up to someone's desk and noticed that they were reading slashdot or digg? Now in the spur of the moment, one could argue (as many have) that those are technical sites, and they improve my ability to do my job. My reply to that is that though there may be some value in those sites, the amount of useless drivel in the comments reduces them to an entertainment.

Accountability. "It's not my job!" "It's not my fault!" These are things that you typically only hear from people who are being accused. If one acts professionally, then one voluntarily takes the blame when it's appropriate. Such an individual seldom has to use the above phrases because those he works with know that if it was his job, or his fault, he would have said so already.

Responsibility. This one follows on accountability. Accepting the blame is only part of the problem. The other part is fixing your mistakes... at your own cost. Oooh, I think I just lost half of you! "But what about my paycheque?" My advise to you would be to log your time and write it off as an education expense, but you actually have to learn from it. I've had this discussion many times with a colleague of mine, and I don't see it changing any time soon. If you hire a painter to come into your house and paint your living room, and two weeks later the paint starts to peel off the walls, you would be correct to expect him to come back and not just touch it up, but sand the whole thing down, prime the walls, and paint it again... at his cost (including materials). The sad thing is that I doubt you will ever see this level of responsibility in the software industry. And I think that the reason is that in order to know what is a bug and what is a feature enhancement, one has to have very thoroughly defined requirements identified up front. And though many people do get requirements up front, they fail to accurately identify the knock on effects of change requests, and so when a bug is found it's very difficult to know if it is the result of the original work or some change. Until such a time as we are able to figure out piece work in our industry, let's be responsible and honestly fix our bugs for free. I expect that you know when a bug is really your fault and when it's not. Own your work, and no one will be able to acuse you of just keeping a chair warm.

Quality. How many times have you heard someone say "I don't have time to write unit tests"? My answer is always, if you don't have time to do it right, when will you ever have time to do it over again? If someone asks me how long it will take me to do a job, my estimate includes unit testing, period. If they come back to me and say that my estimate is too long, and that someone else can do it faster, I will inform them of the breakdown in the time, but I will not do the job without the unit testing. If they don't like my estimate, they are free to go with the other consultant... but if they call me in to fix the work of the other consultant, I will have to do the unit tests that the other guy didn't do before I can start any of the current work. The goal is 100% code coverage, but this does not mean writing a unit test for every line of code. (More on unit testing in some future post.)
Another line I've often heard is: "It's not the way I would have done it, but the client told me to do it this way". Go back to our painter example, if you told him to paint your room without priming it, many people would say it's your fault that the paint is now peeling. And yes, you should take part of the blame. However, the painter should have walked away from the job and said that he could not in good conscience do the job because his experience tells him it is going to peel. You would be surprised how convincing it is for most clients when they see that a contractor is prepared to walk away from a paycheque because he does not want to do shoddy work. (Before you painters start emailing me, it's just an example. I know that often you don't need primer.)

Communication. This is one of my pet peeves, and it really has two parts. The first is prompt alerting of problems, and the second is the quality of the written word.
It absolutely drives me crazy when I see someone coding feverishly. It's almost invariably because the task was more complicated than expected, or they ran into some sort of problem with the environment. The professional developer communicates with the project manager immediately as soon as a risk to the delivery date is encountered, and the onus is then on the project manager to "manage" the expectations of the client. This doesn't give the developer carte blanche to put his feet up on the desk and read slashdot, but it does mean that the developer does not have to panic about the date. A rushed job will always be full of bugs. Better to reduce the features than to try to force everything in when it's not ready.
The second part to communication is professionalism in the written (and spoken) word. The popularity of text messaging on cellular phones has started to spill into business communication, and as far as I'm concerned, there is no place for it. Now before you start to think that I'm some old man chasing the kids off my yard, let me tell you I also use abbreviations when I am text messaging, because hitting the same key three or four times to get one letter out drives me nuts. But when I am sending an email from my phone, I do what it takes to make full sentences... including punctuation and capitalization. I had a colleague once come to me raving mad because he felt he was not being treated as a professional. He showed me a print out of his email exchange with the other party, and it was filled with text messaging abbreviations like "ur" instead or "your", "imo" instead of "in my opinion", etc. Furthermore, none of his emails had a salutation or a signature. After reading it, I told him "I'm sorry to say this, but I wouldn't respect the sender of these emails either". Now I'm not claiming to use perfect punctuation or grammar, and quite often I make spelling mistakes, but this stuff is like speaking to someone with a tongue piercing. It's just simply not professional. You want to have a piece of hardware in your mouth while you are out with your friends, great, go nuts, but pull the thing out when you are at work. Same with the text messaging stuff, use it between friends, sure... just keep it out of the office!

Wow, I really do sound like that old man yelling at the kids in the front yard. It's simple, if you want to work with me on one of my projects, better be ready to work professionally. If you want the respect that I get from my clients, consider these some starting tips. I've gone much longer on this than I planned, and I might edit it later to shorten it some. My hope is that some people might read this and that I might infect others with professionalism.

</rant>