Where to put validation logic?
This evening I was working on TeamDocs and had to make the decision about where to put some validation code. The code in particular is a bit of logic that I use to determine if a directory name is legal or not. In the code, I have a Directory and a DirectoryManager. The DirectoryManager is used to create new Directory objects. In terms of workflow, the new directory name first is sent to the DirectoryManager where it is used to create a new Directory. So, should the validation logic go into the setDirectoryName method in the Directory object or into the createNewDirectory method in the DirectoryManager?
Personally, I can see an argument for both. On one hand, the Directory object should posses the knowledge of what makes a valid directory name. On the other hand, by placing the logic outside of the Directory object, it allows that logic to be more dynamic. I can check if a name is legal based on the OS or some user configuration. In addition, I am not sure if Hibernate allows setter methods to throw exceptions. I will have to look into that.
I think the argument for putting the validation logic into the Directory object is more persuasive given the current trend away from “Anemic Objects”:http://www.martinfowler.com/bliki/AnemicDomainModel.html.
Back when I had to write code that was portable to MacOS 9 and Windows, I created “FileSpec” and “DirectorySpec” objects. These represent a potential entities in the file system - file or directory - but not necessarily an actual entity in the file system.
aDirectorySpec.create() or aFileSpec.create() would create the actual entity if it did not exist.
aDirectorySpec.exists() or aFileSpec.exists() would identify if the entity existed.
These would take a name in the constructor (and directory ID, volume ID, etc., on MacOS 9). Could throw an exception for an invalid name, (or maybe I had it just drop or substitute characters and truncate to make the name valid. It’s been awhile.)
So basically you are saying that the validation behaviour should be placed in the class that most closely represents the object, in this case, the directory or file class? I tend to agree with this.
However, to raise a similar issue, one I have seen debated elsewhere, if you extend this logic, then shouldn’t you put into a persisted object the ability to persist itself? In other words, if I have a Domain Object whose state is persisted to a database, should that domain object no contain the knowledge to retrieve and store its state from/to the database? This would seem like a logic extension of the above argument?
The problem with this, that most people argue, is that you want to abstract the state of an object away from how it is persisted. This allows you to change the persistence mechanism (e.g., flat files instead of a database) without the domain object knowing about the change. I think in my case, a similar argument could be made.
I just find it tough to figure out when the abstraction is required and when direct knowledge is required (if that makes any sense).