During coding I frequently encounter this situation:
- I have several objects (
ConcreteType1
,ConcreteType2
, ...) with the same base typeAbstractType
, which has abstract methodssave
andload
. Each object can (and has to) save some specific kind of data, by overriding thesave
method. - I have a list of
AbstractType
objects which contains variousConcreteTypeX
objects. - I walk the list and the
save
method for each object.
At this point I think it's a good OO design. (Or am I wrong?) The problems start when I want to reload the data:
Each object can load its own data, but I have to know the concrete type in advance, so I can instantiate the right ConcreteTypeX
and call the load
method. So the loading method has to know a great deal about the concrete types. I usually "solved" this problem by writing some kind of marker before calling save
, which is used by the loader to determine the right ConcreteTypeX
.
I always had/have a bad feeling about this. It feels like some kind of anti-pattern...
Are there better ways?
EDIT: I'm sorry for the confusion, I re-wrote some of the text. I'm aware of serialization and perhaps there is some next-to-perfect solution in Java/.NET/yourFavoriteLanguage, but I'm searching for a general solution, which might be better and more "OOP-ish" compared to my concept.
-
Is this either .NET or Java? If so, why aren't you using serialisation?
George Stocker : Serialization is correct as well. Damn brits. :-)Mitch Wheat : The irony is, I usually spell it with an 's', as I'm a brit!George Stocker : Ah ha! So we are rubbing off on you. When you start drinking coffee instead of tea, then we can claim victory!Bill the Lizard : LOL. I'm American, but I accidentally set my system to English without noticing that it was British English. :)DR : It's neither .NET nor Java :) Of course serialization would get the job done, but as does my solution. But I clarified my question.George Stocker : Well, the Abstract-Factory applies across all OOP languages. I'd recommend looking at the Gang of Four Design Patterns book. Also, the concept of developing with each layer doing a specific task applies to all OOP languages. It just so happens that Java and .NET are two major OOP Languages. -
If you can't simply use serialization, then I would still definitely pull the object loading logic out of the base class. Your instinct is correct, leading you to correctly identify a code smell. The base class shouldn't need to change when you change or add derived classes.
The problem is, something has to load the data and instantiate those objects. This sounds like a job for the Abstract Factory pattern.
-
There are better ways, but let's take a step back and look at it conceptually. What are all objects doing? Loading and Saving. When you get the object from memory, you really don't to have to care whether it gets its information from a file, a database, or the windows registry. You just want the object loaded. That's important to remember because later on, your maintanence programmer will look at the LoadFromFile() method and wonder, "Why is it called that since it really doesn't load anything from a file?"
Secondly, you're running into the issue that we all run into, and it's based in dividing work. You want a level that handles getting data from a physical source; you want a level that manipulates this data, and you want a level that displays this data. This is the crux of N-Tier Development. I've linked to an article that discusses your problem in great detail, and details how to create a Data Access Layer to resolve your issue. There are also numerous code projects here and here.
If it's Java you seek, simply substitute 'java' for .NET and search for 'Java N-Tier development'. However, besides syntactical differences, the design structure is the same.
DR : The method names where meant as sketches to describe my problem. Of course I use better names in real applications :) But thanks for the article, I will read it!
0 comments:
Post a Comment