So, I'm about to create my data access layer... *flashback sequence begins* ...and I reach for my Patterns of Enterprise Application Architecture book. *flips the cabinet door open to see an empty space where the book used to be* Damn...I left it at home. Well, what am I to do? Let me just move over a couple of books and grab my Core J2EE Patterns book (admittedly, still in my to-read stack). I figured this was as good of a time as any to get to know the DAO pattern and how it compares to the TDG pattern. So, I read through the pattern description and I get a little excited. I realize that the only difference in the two patterns is the implementation. While I don't like the idea of tacking on “DAO” to an object name, I figure I'd make a hybrid of the two. *flashback sequence ends*
The fundamental differences between these two patterns are pretty much null and void when you consider that pattern implementation is usually different than the prescribed means. Here are a few of the pros (in my opinion)...
- String constants for insert, select, update, and delete statements
- Pro: One place to update table structure changes
- Con: In methods, you don't know the order of values that need to be inserted (i.e. in .NET, using the
String.Format() method to insert values)
- Method names that match common data access terminology (create, read, update, delete - aka CRUD) and are not specific to any data source
- Pro: Sets a naming standard for the pattern
- Con: ???
Some of the things I didn't like about the TDG pattern were that the method names weren't consistent (where did "find" come from?), methods seemed to be based on SQL (use of "insert" method), and the method signatures didn't suggest the use of objects.*
* The use of objects is very beneficial when passing data through tiers because it allows you to abstract away from the exact data that needs to be transferred. For instance, based on the TDG pattern description, consider the insert method: PersonGateway.insert(lastName, firstName, numberOfDependants). These are the three properties of the Person class, but I don't know why a class instance wasn't passed instead - for instance, PersonGateway.insert(person). Now, consider adding an SSN. With the implementation as-is, you would have to add another PersonGateway.insert() method allowing for the SSN to be passed. And, what if the SSN is required? Then you would have to deprecate the old insert method. However, if you use a class instance, we only have to change the internals of the insert method - no new or deprecated methods. Obviously, this would be a much cleaner implementation.
Also, let me say that the TDG pattern seems to be a bit higher level. It represents the idea of having an object to act as a gateway between business and data. There isn't a lot of guidance for naming conventions or implementation ideas, which I think is important for identifying/using patterns in existing software. As such, you could say that the DAO pattern is just a lower level TDG pattern.
You'd think that this would solve all of my problems, but it doesn't. I like the idea of the Gateway pattern (not the Table Data Gateway pattern) because it is abstract and identifies a way to interface with any type of back-end. Because of this, I think it's important to look at intermediaries as gateways. Now, all of my development is usually in .NET, but I sometimes dabble in Java. I would like to have one standard set of patterns to use, but these two conflict. In my mind, the gateway pattern works in all situations; however, it is pretty much standard practice to have a PersonDAO class as opposed to a PersonGateway class. I don't like deviating from the standard, but at the same time, I don't like having two standards for the same practice.
I've talked to Dan Malks, one of the co-authors of Core J2EE Patterns, and he said that they talked with Martin Fowler when making the book. My question is: Why are there conflicting patterns? And, can we identify the right (read: best) solution so there's only one? I'd like to see the DAO pattern reference the TDG pattern (or maybe just the Gateway pattern). This would identify the relationship and developers would be able to identify each implementation as it was used in projects. This doesn't necessarily get rid of one or the other, which could cause naming conflicts, but at least its a step in the right direction. In my experience, most Java developers don't even know about the TDG or Gateway patterns.