Monday, August 22, 2005
Those wacky design enthusiasts
Vivi is complaining I haven't written a new blog in a long time. I'm not sure this is what she had in mind, but, it is what I have in mind.
Design enthusiasts are always stirring up trouble. I should know, I'm one myself. We are a strange breed, often caring more about how something is designed and created than how well it works. Not to say it's all impractical pie-in-the-sky time wasting, but I do think it's a personality thing more than an educational thing (ie, many design theorists seem to have the impression that their attitude comes from knowing more).
So I was reading Alan Holub's column about getters and setters being evil. It's a classic of uncompromising design principles. Now, I am considerably sympathetic to the view that implementation inheritance and getters/setters are evil - it seems like a bit of a challenge to write code in such a fashion, and that of course attracts me (see what I mean by it being a personality thing?).
However, like many poor suffering Java developers, I spend much of my time writing dull little CRUDy web apps, and a lot of classes are spent simply holding data that must be transferred to and from a database and to and from a web page. The web pages are written using a templating system (to assist in separating display logic from business logic). So, as I read about how all my getters and setters are evil, I'm wondering how else I could write my (Velocity) templates other than by handing off my holder objects and calling the various get methods on them from the template (this allows me to create an HTML web page with dynamic values embedded within).
According to Mr. Holub, I would tell my object to "draw itself". This plainly is not possible though, since there is not clear line drawn between the display of one object and the display of another - rather, the web page template allows me to create a page in which 5 or 6 such holder objects have their data embedded in no particular order. Mixed data. I suppose I could make conglomerate special purpose objects that would know how to create each page given a set of these holder objects - but then that's pretty much what the template is, and the template is a heck of a lot easier to read and edit.
Besides, I have a basic question about the evilness of getters and setters - is the use of all Map objects evil? After all, using a Map object is nothing more than get/put. I'm sure Mr Holub would say no, the get/put methods of Map are not evil since that's not revealing anything about the implementation of the Map - ie, how a Map works has nothing to do with the specific objects it's holding.
But then, what if my getter/setter methods on class Person are really nothing more than a typed Map get() methods? I could have used a Map object to hold FirstName, LastName, Address, SocialSecurityNumber objects, or I could make a simple class, Person.java, that has these four private instance members and getters/setters for each. Am I revealing implementation details, or am I making a special case Map class?
This Person class has an interface that reveals the semantics of what a Person is (as far as the software is concerned). If the Address class returned needed to be changed to a different implementation class, then that could potentially adversely effect all the code that was pulling that piece of information. The solution there is to make "Address" an interface, and return an object of type Address from the getAddress() method. In fact, Person itself would have to be an interface too, and we could have several different implementations of Person (ie, one with a USAddress instance member, and another with a CongoAddress instance member - or whatever, you get the idea).
Does that mean that if I have a instance members that are essentially acting as special case Map objects, and whose getter/setter methods are defined in a public Interface, then I am not violating the rule that says don't expose implementation? Cause if so, I could get down with this "getters/setters are evil" idea.
Design enthusiasts are always stirring up trouble. I should know, I'm one myself. We are a strange breed, often caring more about how something is designed and created than how well it works. Not to say it's all impractical pie-in-the-sky time wasting, but I do think it's a personality thing more than an educational thing (ie, many design theorists seem to have the impression that their attitude comes from knowing more).
So I was reading Alan Holub's column about getters and setters being evil. It's a classic of uncompromising design principles. Now, I am considerably sympathetic to the view that implementation inheritance and getters/setters are evil - it seems like a bit of a challenge to write code in such a fashion, and that of course attracts me (see what I mean by it being a personality thing?).
However, like many poor suffering Java developers, I spend much of my time writing dull little CRUDy web apps, and a lot of classes are spent simply holding data that must be transferred to and from a database and to and from a web page. The web pages are written using a templating system (to assist in separating display logic from business logic). So, as I read about how all my getters and setters are evil, I'm wondering how else I could write my (Velocity) templates other than by handing off my holder objects and calling the various get methods on them from the template (this allows me to create an HTML web page with dynamic values embedded within).
According to Mr. Holub, I would tell my object to "draw itself". This plainly is not possible though, since there is not clear line drawn between the display of one object and the display of another - rather, the web page template allows me to create a page in which 5 or 6 such holder objects have their data embedded in no particular order. Mixed data. I suppose I could make conglomerate special purpose objects that would know how to create each page given a set of these holder objects - but then that's pretty much what the template is, and the template is a heck of a lot easier to read and edit.
Besides, I have a basic question about the evilness of getters and setters - is the use of all Map objects evil? After all, using a Map object is nothing more than get/put. I'm sure Mr Holub would say no, the get/put methods of Map are not evil since that's not revealing anything about the implementation of the Map - ie, how a Map works has nothing to do with the specific objects it's holding.
But then, what if my getter/setter methods on class Person are really nothing more than a typed Map get() methods? I could have used a Map object to hold FirstName, LastName, Address, SocialSecurityNumber objects, or I could make a simple class, Person.java, that has these four private instance members and getters/setters for each. Am I revealing implementation details, or am I making a special case Map class?
This Person class has an interface that reveals the semantics of what a Person is (as far as the software is concerned). If the Address class returned needed to be changed to a different implementation class, then that could potentially adversely effect all the code that was pulling that piece of information. The solution there is to make "Address" an interface, and return an object of type Address from the getAddress() method. In fact, Person itself would have to be an interface too, and we could have several different implementations of Person (ie, one with a USAddress instance member, and another with a CongoAddress instance member - or whatever, you get the idea).
Does that mean that if I have a instance members that are essentially acting as special case Map objects, and whose getter/setter methods are defined in a public Interface, then I am not violating the rule that says don't expose implementation? Cause if so, I could get down with this "getters/setters are evil" idea.
