Starbucks-fueled Developer

Friday, February 18, 2005

The Case for the Special Case

I found myself today strugglingly immensely with modeling "typical" business data. If this isn't a sign of a true novice, I'm not sure what is...

Essentially, from a database perspective, I'm struggling with look-up tables - those values like 1 = DVD, 2 = Book, 3 = CD, etc. to use Products and Product Types as an example. So I have a Product class and and Product Type class, but I realize that not all data for a DVD will go with a Book or CD, so the different Product Types become subclasses of Product. Am I right in calling these an occurence of Fowler's Special Case EAA Pattern?

At this point, depending on the application, I might ask myself: "well then why in the world do I have a Product Type class?!" In one application, I realize that I still need the Type class because I need those boolean, read-only properties like "IsBook". This, however, leads to a more intensely puzzelling dialouge that I have yet to close knowing that I've explored it thoroughly: so do I store those flags in the database? But if I do, those data members shouldn't be mutable...should they?? What's the point in having all those ProductType classes (or classes that implement an IProductType interface) if I'm going to have 1 per record in the database? If the user adds a new type, won't I have to create a new class that implements that IProductType interface as well?!

I have to say that, while I was writing this, the debate was continuing to swirl about in my head and I came up with yet another question: so, if I have all those different IProductType objects, I could only store the necessary data in the database (e.g. name, PKID, description, etc.) and then have the immutable boolean properties to determine whether or not it is of the type I'm looking for (e.g. IsBook), but I still have to create another object for every new type that's created. Granted, a product catalog, and other applications with similar models, have a lower probability of being modified. If I'm Amazon, sure I'm going to have books, CDs, movies, etc. and maybe every-so-often I'll update my product line so that I can offer my customers more items. I suppose that's the risk involved - knowing that the model is only as good as the defined application and data requirements.

Maybe these are extremely simple questions, but I feel I'm not looking in the correct places for answers. I checked out an older version of NHibernate (0.3.0.0) and noticed their IType interface for working with the various types used in defining properties/member data. Almost immediately, I reverted back to my arguments: it doesn't matter, they don't have to ever pull those ITypes from a persistant medium!

I feel as though this would be a rather all-to-common problem/scenario in Agile/Domain-Driven Design and that there's gotta be some-sort-of formal response to the questions out there that the GoF or Fowler just copy and paste to people like me when I mentioned the points I've raised here. I'd love to find some sort of article or two to at least hear rebutals to my arguments and answers to my questions...

Thursday, February 17, 2005

DTOs: What's the Point?

Scott, after I sent him an e-mail, read my post about serializing ADAPTERS to XML, sent me the following reply:

"I don't know enough about XML serialization to be able to speak to theproblem in any significant depth.

Am I understanding that you're serializing the adapter? If so, that's areally uncommon thing to do. Adapters often sit at component boundaries,but aren't often passed back and forth between them... kinda contradicts thenotion of an adapter.

Maybe what you need is the Data Transfer Object(http://www.martinfowler.com/eaaCatalog/dataTransferObject.html).

Rather than serialize raw objects, put the raw objects' data into a simpler structure that can be more easily serialized. DTO's are intended for moving data between boundaries.

Beyond that, it's hard for me to say without really having hands-on experience with the serializer."

I think he's right; I missed the point of the ADAPTER pattern, to a degree. I think my intention was correct, in trying to decouple the application from a particular service implementation. I think I got that part right. The ADAPTER is allowing an object from an external library that provides the desired functionality by providing the "client" an interface to it, that it is expeciting, so that it is usuable (boy, that seems awfully wordy...).

But here's where I get lost in this whole OOP/TDD thing: why should I create that Data Transfer Object when the runtime will persist the object to the desired format for me? For instance, take the example given in the link Scott referenced in his reply, Fowler's DTO. The AlbumDTO class has a ToXmlElement() method; this is perfect for Java - at least to my understanding - because Java doesn't have a way to easily persist an object to and from XML without actually writing out the representation using some-sort-of XML StreamWriter. The programmer has to write that code manually saying "write an element named 'album' and add a 'title' attribute and a child element named 'artist' with the artist's name as it's text" (that would result in <album name="asdf"><artist>Foo</artist></album> for clarification). Who in their right mind would go through all that?! (aside: I might entertain a discussion on that issue some other time)

In the world of .NET, the XmlSerializer will persist the entire object graph to XML, unless you instruct it to do otherwise. Why would I write a DTO if the runtime does this for me? In fact, when you write a Web Service and return an object, the runtime invokes the XmlSerializer on your object to return your object to the client anyway! I had the same beef with DTOs when they appeared in Newkirk's .NET TDD book.

I realize I could be over-generalizing things here, but I still feel my point is valid, arguable to say the least: do DTOs have a purpose in .NET when the runtime provides these services for us?

Quite a Ways to Go

I have to admit, first off, that I feel guilty for openly asking a person hundreds of miles away specifically to view a post that I wrote because I don't know what I'm doing and frustrated with my lack of success. I feel as though I get paid to come up with solutions, not to create new problems and get outside help only to reaffirm the feelings of jumping in without being able to tred water. Granted, sometimes this is the way we learn: others showing were we went wrong so that we are less likely to make the same mistake again. But I feel as though I just hit the panic button and ran to the first person I knew, tugged on their shirt and said "fix it please" even though I probably spent about a whole day's worth of time trying to determine if it was even possible only to come up with the answer of "no"...

Truth-be-told, the near 8 hours of pseudo-prototyping and design testing and coming up with the no is what hurts most, closely followed by the feelings of giving up, throwing in the towel, and asking someone else to fix it...

Quite a ways to go, indeed...Thus I digress...

Wednesday, February 16, 2005

Serializing "Adapted" Objects to XML (or, "Just Bar Damn It!!")

Background Information

My company, long ago, developed a Role/Task-based authentication service that has since been converted to a .NET Web Service. This service, I'll call it IMS, is basically used by any application we design, and personally, I think it's overused. When it was developed, there really wasn't anything that similar available - at least to my knowledge - and it made sense for us to have our own product that we could stand by and support. This was all before I worked for them; that's not to say I would/could do it better.

However, I'm here now and I seem to know how to gum things up real good. So, I got this crazy idea (not out of the ordinary). I'm writing this application and I can just see that IMS isn't going to be around for ever. It very well could be replaced by AzMan or some other third-party security service that is already in place at a client that they are not willing to give up. So what do I do, attempting to be the pragmatist? I design for it. I try to decouple my application from IMS, creating IUser, IRole, and ITask interfaces, creating ADAPTER classes around the existing IMS classes so that, should we switch providers, my application isn't coupled to IMS. Score one for the developer!

Adapt THIS!

Here's where I ran into a world of hurt: IMS expects XML when doing any CRUD operations on its data. No problem, we have objects! We'll just serialize them using the XmlSerializer, decorating the IMS objects appropriately. Oh, if only it were that easy!! See, when there's an object hierarchy, the XmlSerializer expects the base class, in this case the IMS objects, to be decorated with XmlInclude attributes for each type that extends it. The interesting thing to note is that when I ran my tests, the error message in the exception thrown by the XmlSerializer says:

The type Namespace.Foo was not expected. Use the XmlInclude or SoapInclude attributes to specify types that are not known statically.

That one I don't get. It's absolutely right, I don't know all the types that may or may not derive from any given object at compile time. I tried slapping an XmlInclude attribute on my Adapter class; no luck. The only thing I did have luck with was comparing the Type specified in the XmlSerializer to the Type of the instance to be serialized and, if the instance is a subclass of the original Type specified, I create a new XmlSerializer specifying the subclass' Type. But that defeats the purpose!! It seems ridiculous to me that I have to specify all the types that could've subclassed the object I'm asking the serializer to give me. I honestly just want that piece, no more, no less. I typically write this kind of thing off saying "Microsoft probably had a good reason for doing it this way" but that just doesn't put my mind at easy. If I say "give me the Foo part of Bar" that's what I want damn it, not the whole Bar!! You shouldn't need to know anything about Foo, ya foo' !!! (sorry, couldn't resist...)

Obviously, if I create an instance of the IMS object, assign it the values from the adpated IMS object, serializing the IMS object itself works fine, but that seems like replacing the carpet when soda's spilled on it because steam-cleaning would be too easy...

Tuesday, February 15, 2005

Welcome

My first post using Blogger; it's not a .NET blogging application, but it's Google so that's earned it kudos thus far. I hope to post and write here about both my personal and professional lives and look to focus on Test-Driven Development and my aspirations to become more test-first oriented in developing and designing professional business applications.

I've learned a ton by reading numerous blogs over the past year or so; it would give me great joy should I discover that something I wrote about was of great value to someone else.