Ask Brian: How to Handle Object Validation?

Jason asks:

Brian,

I'd like to ask a question about Beans and Validation. Feel free to use it is a blog post.

So a lot of people have been telling me that Beans could/should have a validate() method to validate their own data.

My issue with this is, how can a bean validate it's own data if it is throwing errors in get() methods because you are trying to insert invalid data.

Since I cannot insert "Jason" into a date var or a numeric var, what good is my bean's validate() method gonna do me.

It seems to me that I have two choices.

1. I can do pre-validation validation. And validate the data before I insert it into the bean for validation

2. I can do all of my validation in the service layer or handler/listener(if no service layer) and THEN populate my bean with valid data.

I like option 2.

Am I making sense?

FYI, I am an OO n00b.

Hi Jason, don't worry, you're making sense. I actually don't do either of these. Before I do anything like a save() of an object, I create a Result object. My Result is a generic object with methods like isSuccess(), hasErrors(), getErrors(), etc. I use this to handle my validation.

Basically, I call user.populate(data, result). The populate function attempts to populate the object by calling setters that correspond to the data that was passed. (For customization, an object can override it's inherited populate() method if the generic behavior isn't sufficient.) If there are any failures, an error is caught and added to the Result object.

Once that is done, attempt to save the object even if there are errors, so that I can get additional validation error messages (i.e. end date must be after start date). Saving is done the same way: user.save(result). The save() call triggers a validation, and any validation errors not based on type are added to the Result as well. If the Result contains no errors after validation, I proceed with the save. If there are errors, the save does not continue.

Once that is done, I have a Result object that either has errors or it doesn't. These may be population errors cause by type mismatches, or they may be validation errors handled by my validation rules. Regardless, I now have a nicely packaged Result object that I can return to the calling code. This can be returned to something like Flex, or it can be returned to an HTML Controller such as Model-Glue, but either way, that code can now decide how to proceed.

This is just the way I do things but I've found it to be very flexible and useful. I hope that helps!

Comments Comments (6) | del.ico.us del.icio.us | Digg It! Digg It! | Linking Blogs Linking Blogs | 7446 Views

Ask Brian: Handling Custom Object Behavior

Robb asks:

I have an architecture question. I am building a site with MG2/Transfer/Coldspring and looking to refine my model. I have a User object that can handle several different "user-roles" i.e. admin, prospect, agent, etc... I have been struggling with the best way to provide the configuration details/properties for each user-role. I don't want to end up with class explosion with say a strategy pattern or even a quasi-abstract CF factory method. I am not sure that configuration details/properties should be a singleton CS managed object as they are more transient but what is the best way to handle?

Robb is looking for a way to assign custom behavior to his User object. To his credit, he isn't immediately trying to go down the inheritance path, which is what many people will initially try. The idea of creating a base User object and extending it with AdminUser, AgentUser, etc. looks easy and appropriate upon first glance. Unfortunately, it has a big problem: inheritance is static and it is a "one or the other" proposition.

In other words, what if you have an Agent who is also an Admin? This gets nasty very quickly. What do you do, go with User > Agent > AdminAgent? Or User > Admin > AgentAdmin? This is the very definition of a class explosion, and again, it is good that Robb appears to see the problems with trying that approach.

Robb mentioned the Strategy Pattern, which might be a good fit. His fear of a class explosion here may be misplaced though. Clearly, the Strategy pattern will cause much less of a class explosion than inheritance probably would. And the bottom line is that the custom behavior has to live somewhere. So my take would be something like this:

There's really nothing wrong with this, and there really is no class explosion. You have one class for each type of specialized behavior you which to apply to a User. It doesn't get much tighter than that. He can also associate more than one Strategy with a User if necessary. The only downside here is that the User object needs to have a static API (unless you want to start playing with method injection but that is another topic and would add another layer of complexity). In other words, the User object would need a method for doAgentThing() even if that particular User instance did not use the Agent role strategy. This may not be an issue, and in fact it may be a good thing for the object to always have a known API.

There is another take on the problem, which essentially reverse the composition relationship. This is the Decorator Pattern. It might look like this:

You can see that it is almost identical to the Strategy Pattern except that the relationship is reversed. Essentailly, the Decorator "wraps around" the original object and adds additional behavior. Again we have one class per custom set of behavior we want to apply. And a User can have more than one Decorator applied (sort of a "russian dolls" approach where we have more than one wrapper). But the difference here is that the API of the Decorator would not remain static. The object would have a doAgentThing() method only if the Agent decorator was applied to the User.

This might be a benefit or a drawback depending on how you create and use the object and how certain you are of what kind of object you are dealing with. But it does introduce coupling, because now the code using the object needs to know what kind of User it is dealing with. This is called "type coupling" because the calling code has to know which type of User it is interacting with. In some cases this might be fine. i.e. if you know you are only calling agent-related methods from within some other agent-specific code, this may not be a problem. (One could also specify all possible Decorator methods in the abstract UserDecorator class and have it throw an error or do nothing if the User doesn't have a specific decorator applied, but then we get into needing to handle exceptions in the calling code which would also add more complexity.)

As you can see, there are a few ways one might address this problem and they each have their own benefits and consequences. Which one Robb might use probably depends on how he uses the User, how important it is that the User object maintain a stable API, and how much type coupling he is willing to accept when using the object from other code.

Hopefully that gives Robb some ideas to consider. If anyone has comments or other ideas, please feel free to comment and give your thoughts. Thanks!

Comments Comments (2) | del.ico.us del.icio.us | Digg It! Digg It! | Linking Blogs Linking Blogs | 7886 Views

Ask Brian: How to Handle Object Composition?

Christopher R contacted me through my contact form to ask about object composition. I thought I would answer it here in case it helps other folks as well. I'm also planning on answering questions like this going forward, so if anyone has questions that you think I can help with, feel free to contact me through the blog and I'll do my best to answer!

greetings...i recently came across a great article you wrote called "Write efficient code with the Composition object pattern and CFCs". it greatly assisted in my initial dilemma involving how to relate distinct but related classes. the current article works for related classes (PhoneNumber) into which you pass a final piece of data (e.g. the phone number). however, whats the best approach when that data is merely a reference or pointer (e.g. PhoneID) that requires further querying / creation of data access objects? as an example, several customers may share the same phone number (PhoneID). in this case - bear in mind that we still want to stick to OOP + not introduce db queries into the related class (e.g. PhoneID.cfc) - we might use a DAO to communicate with the related class (e.g. PhoneDAO.cfc) into which we would need to pass a database ref along with the PhoneID(s) in order to find the proper record. i would like to return a reference to the Phone object that the main class (e.g.Customer) could then utilize. to better elucidate the approach, im following a series of articles at iknowkingfoo.

hopefully this makes some sense - difficult to encapsulate in writing succintly. im getting up in arms as far as these objects, accessing their data as well as trying to access application variables. any help greatly appreciated.

thanks in advance.

To reiterate, composition models a "has-a" relationship between objects, as opposed to an "is-a" relationship which is typically done through inheritance or interface implementation. However, Christopher seems to be working with two different kinds of objects here: Singletons and business objects. How you handle the composition can depend on the kind of object you are dealing with and what they are meant to do.

For example, a PhoneDAO would almost certainly be a Singleton object, meaning that only one instance of the PhoneDAO exists in the application. However, a PhoneNumber object would be a business object, meaning that there could be many instances of PhoneNumber, each with their own data, modeling many different actual phone numbers. The same goes for Customer. Customer is a business object.

The question seems to be how to build up composite object relationships in your business objects. The answer is usually to use a Factory to build your business object. The Factory would also be a Singleton since you only need one. So Christopher might consider creating a CustomerFactory which he would call "getCustomer(13)" on to create an instance of that Customer and return it. The factory would then be responsible for also creating and setting any composite objects. As a result, the factory may itself have other singletons composed within it such as a CustomerDAO, PhoneNumberDAO, etc. The factory would use these objects and know what to do with the results (in this case, setting the resulting PhoneNumber into the resulting Customer before returning it).

The idea with factories is not only that they create objects. It has to do with the primary OO design principle of encapsulation. What the factory encapsulates is knowledge of how to create and relate a Customer and a PhoneNumber. This is crucial to understand, because it means that you become free to change how the Customer and PhoneNumber are created and related at any time. Nothing outside the factory would ever know that you made any changes.

Consider the Transfer ORM framework. Transfer handles making queries to the database as well as building object relationships for you. It is very handy, and I would recommend that Christopher have a look at it when he has the time to evaluate it. But lets say that he creates a CustomerFactory and any code that needs a user calls customerFactory.createCustomer(id). If he later decides to use Transfer, he can easily make that change because he only has to change one thing: the CustomerFactory. He can remove his own DAOs and rip out the logic that relates these objects, and replace it with calls to Transfer. Nothing outside his factory needs to know that the way these objects are being created has changed. That is the beauty and power of encapsulation, and why factories are so useful.

For building composite relationships in your Singletons, there is another option to consider: the ColdSpring framework. This framework is designed primarily to "wire up" or relate your Singleton objects. That means things like Services, DAOs, Gateways, etc. It is a really powerful tool but does have a learning curve to wrap your head around. I have a number of blog entries on ColdSpring and there are numerous other blogs and mailing lists that can help with this as well. If you give ColdSpring a look and I can offer any additional help please let me know.

Hopefully that helps, Christopher? I'd look at using a factory to handle creating and relating your objects. The factories can get rather complex if you have a lot of object relationships to manage, but again, the logic is all kept in the factories. It's certainly possible for one factory to use another factory as well, so don't feel like you have to create a single uber-factory that does everything. And if or when you decide to try out another approach such as Transfer, you'll be happy you went the factory route. Good luck!

Comments Comments (1) | del.ico.us del.icio.us | Digg It! Digg It! | Linking Blogs Linking Blogs | 10039 Views