Wednesday, December 21, 2005

Joe on Inversion of Control!

Last night I got into a nice long discussion on the coldfusion channel with blanketgirl, no idea who she is, which ended up cornering me into trying to explain why ColdSpring is actually a good thing, not just a whole bunch of xml based hubbub. Unfortunately, since I was relaxing and having a few beers, my defenses didn't go too far past the basics of dependency injection and why I think it so usefull, shots easily deflected by the xml hating blanketgirl! What a surprise to read this excellent post on Inversion of Control by Joe Reinhart today!. Joe puts out a very solid example on using mock implementations in development, but being able to make deployment changes in the ColdSpring config file, not in code. Hey man, where were you last night when I needed you! Kudos to a very well written post, and since Joe mentions that he will be writing about AOP soon, I'm very much looking forward to some great articles. Thanks again, and blanketgirl, go read up!

Monday, December 19, 2005

Defending the Bean

Over the last week there’s been some really interesting discussion about the idea of an ‘Anemic Domain Model’ for some reason including rethinking the usage of DAOs. I find it a pretty strange concern, if you want me to be honest. I’m not sure I follow the logic of reorganizing tiers of your domain model just to satisfy this notion that every object MUST have logic in them. Here’s some background, most of this discussion refers to this thread on TheServerSide which raises concern over having thin domain objects that are passed into DAOs for persistence instead of knowing how to persist themselves (ActiveRecord pattern, btw). The funny thing is the very first reply sums everything up pretty well by bringing up the analogy of a Cake (your anemic bean), an Oven (your persistence mechanism) and a Baker (which he says is the controller, I’ll get to that). In his scenario he asks the question, does a cake know how to bake itself? Of course not. I have a slightly different take on this example, though.

You have a bakery, it’s a service, which provides cakes, as well as cookies and bread and what not. Components that make up the bakery, like the refrigerator, the oven, the display case, the baker, are each part of different tiers that, when composed together into the bakery, provide services to return cakes, cookies, bread, etc. Lets look at that oven/persistence tier. What exactly is wrong with putting persistence code into it’s own tier now? Doesn’t that assist in making clean, cohesive components? If I put that logic into the Cake object, isn’t that muddying up the logic of the cake a bit? Personally I find the DAO approach to fit nicely into an organized persistence tier off my applications. And, of course, ColdSpring will assist in building that bakery. Just as a side note, in the TSS thread the consensus was quickly reached that the DAO example was a pretty bad choice. So what was the issue again? Oh yeah the thin business objects.

This is an argument that has been going on in the Java world for a while now. It’s against using transfer objects, because they don’t actually have any real business logic in them, so they’re not a real objects. I guess it could be said that this is contrary to the basic ideas of object oriented design, ok I guess Martin Fowler can say that. Rod Johnson, the creator of Spring, also warns against writing objects that only contain methods to expose their data, as they are not actual objects. But lets look at this. This is a Java issue. Java has no lightweight typed objects. C# solves this by providing an excellent Struct implementation which is really a lightweight typed class. So when you ask for the ‘name’ you get a String back. Quite different from Java’s alternative, various types of Maps, which all return Objects back, so casting is necessary. For many purposes, using a bean is a better alternative to a map, because getters return data in the correct type (this is addressed with generics in java 5). But wait a second. ColdFusion. Don’t we have a Struct? Of course we do. Any we are dynamically typed, so the casting issues are not a problem. So if transfer objects are such a problem, why not use Structs, right?

But wait. I don’t think we’ve really looked at the issues here. There’s more to consider. Typing IS an issue. We need to validate types when putting data INTO transfer objects, we want numbers to be numbers, not strings, just for a simple example of why, consider this. We pass a struct into a gateway object to retrieve all users of typeID=6, our where clause looks like this: WHERE user.typeID = #myStruct.type#. But some wily hacker comes along and figures out how to set that value to ‘truncate table user’. Whoa, hold on! That’s like uh, SUPER BAD! Certainly having a numeric type enforced on that data could have really helped here (any yeah I know, queryparam could help, but that’s not my point). I could have also built a validate method in either the TO or validator object which could have been used by some service object before even attempting to send the TO to the DAO. The point is that even though beans / TOs have little logic in them, their use is a part of a bigger picture, which makes up business logic. I have a novel idea that beans and transfer objects are actually part of architectures which represent logic by design. Isn’t that a huge part of OOP anyway? Complex logic is often represented by the interactions of the objects that make up our domain model. Some of those objects are going to make up our Persistence tier. Some of them are going to make up our Service tier. Some of them are going to be Domain Objects and represent our primary business (we sell books, so we have book objects). And some of those objects may very well be lightweight objects, but they assist in clear separation of our logic, they assist in typing and data validation, they may model forms from our view tier, etc, etc. Are they second class citizens on our domain, no way! Embrace the Bean!

Thursday, December 08, 2005

Reinventing the wheel is BAD!

I know you’ve probably been told that before, and it’s one thing I’ve told myself over and over again, but sometimes I just forget. I’m working on a soon to be explained, but I’ll keep quite for now, little side project in Java which requires creating beans and setting properties (hint). As I got down into the setProperty methods, I realized the rabbit hole is a lot deeper than I thought. The problem is, I will have a property name and a value that I want to find a method for in some given object. So I can look for methods with reflection, but a lot of issues arise. I have to look for a method that accepts not only the type of value I have, but also any classes it extends, the same goes for interfaces. Also, the bean may accept a primitive type, such as int, but for all sorts of reasons, you may have to wrap that value as an Integer object, which means I need to try to un-box those types (that’s what c# calls it, I can’t remember the java term) as well. After more than an hour, and after all sorts of methods, (setProperty is now becoming a chain of 4 or 5 methods and I’m not done!) I realized I better do some googling to see how this is done in say, Struts. I ended up looking into some apache commons code, initially reading it (dumb), when it struck me. What the hell am I doing? This code is written, and open source! Duh! So I scrapped my code and replaced it with one line of code using commons.beanUtils.

Moral? Reinventing the wheel is a waste of time! There are lots of GREAT open source solutions to many common problems, the apache commons project is just one of them, specific to Java programming issues. The great thing is, other than the fact that the code is already written, you or I are just one person, dealing with the issues of entire systems. These tools are written by groups of very skilled programmers, they are singularly focused to provide highly tested, well written solutions, which are probably going to be better designed than what you or I are trying to come up with. I spent 2 hours doing something that really only had to take 5 minutes! This is one of the core mantras of the book Better, Faster, Lighter Java, which I guess I forgot for a second.