Well, it was late, dark and mainly, I was lazy
"separating as much as possible" is actually a combiniation of several
reasons. Mainly, it's the knowing that in big projects, murphey will
strike where you're least prepared to handle him. Not "seperating", or
not using a factory/interface pattern, would leave you hanging for a
refactoring later, when the need arises.
I think there's something to be said for leaving that refactoring until
the need arises, since the need may never arise and therefore it's wasted
effort now.
I agree that it is often useful to have an interface so that a stub
implementation can be created for testing. But in the particular scenario
in this thread, I don't see a need. The Record class presumably does
nothing particularly complicated and can be used "as is" for unit
testing. You could advocate that all public methods should be declared in
an interface, such that you would have no concrete class that did not
implement at least one interface. However, I don't think that this line
of reasoning is valid for all situations, particularly for classes like
our hypothetical Record class which is presumably not much more than data
and a whole load of getters and setters.
In small applications the
direct creation method usually suffice. This is due to the short life
cycle/small amount of data types involved. When you're starting to
handle big and very big applications, especially if it's in a
multi-developer environment, the original specification of the data
type is bound to change.
I want to make it clear that I am not arguing against the use of
interfaces or factories. I'm just saying that they shouldn't be used
blindly for every class. I'm also not sure that I am following your
argument in the above paragraph. Are you talking about the situation in
which a new field is added to some data type class or the type of the
field changes, or something else? How will extracting the getters and
setters into an interface and using a factory help in this situation? You
will have to add new getters and setters to the interface just as you
would to the class, and factory method signatures will change just like
constructor signatures would. All you are gaining is another level of
indirection.
Another reason is testability. Using a factory class makes if much
easier to unit-test the package. From the inside, you can just use the
factory as a main installation point. Since it controls what goes into
the constructor, it makes a nice point of entry for the unit-test. From
the outside, the replacing the factory will allow you to mimic/mock the
record class (and persistors and all other related class) without
getting into reflection/aspectJ related mock strategies.
In the approach I was advocating, the Record class would have no knowledge
of persistence. It therefore would not need to be mocked. You could
still mock the persistors if required, since there would be an interface
for those.
My final reason is murphey again, but from a debugging point of view.
Each class should handle it's responsibilities and nothing more. While
Record should be able to handle data type get/set, it shouldn't be able
to handle it's own creation. And just as an example, think of a record
getting created from numerous sources - DB, socket, xml, file...
My main argument is against the seemingly unnecessary Record interface (in
this particular instance where there would appear to be no need for
alternative implementations). I concede there may be good reasons for
using a factory, if you do need to do something more complicated than
invoking a constructor (such as cloning or deserialisation). However, I'd
still defer adding the complexity until there is a need for it. In other
words, if at present the only way to create a Record object is to invoke a
constructor, then I'll just invoke the constructor, rather than creating a
factory that has a method that takes all the same arguments as the
constructor and merely delegates. If I write a factory for every concrete
class I write, that's more places for your friend Murphy to strike.
It's
true they should all be in the Persist classes. However, the record
should not be coupled to a specific persist class. Also, your code
should not be coupled to the persist classes. It is better, imho, that
the factory is coupled to them.
If I'm following you, I agree (about not coupling the Record to the
persistence). But for this to be the case, the Record class you posted
would have to lose its persist method and reference to the persistence
strategy. Whether you have another class that manages the invocation of
the persistence (both loading and saving) would depend on exactly how you
were planning on using the classes. It may be that you need something
more like the EntityManager in JavaEE 5 rather than a traditional factory
(which, to me at least, implies loading but not saving).
Dan.