質問

Scenario: We receive a couple of input parameters regarding an object, for ex Course

Course has instructor name, number of students, course time, room no, etc.

We need to validate (number of students > 0, 9am < time < 9pm, etc) the input and create the Object. We need to return the source of error for invalid input.

I could think of two approaches

1) Create a separate Validator class with static methods,

  • validate input, (validate method returns true, or some enum like VALID, INVALID_TIME, INVALID_STUDENT_NUMBER).
  • instantiate the Bean if input is valid.

cons:

  • If we have to process input values before validating them, the above pattern leads to doing it twice if input is valid, once in Validator class, and once before bean setters. We can't return Bean object since validate method needs to return source of error in case of invalidity.

2) Have the validate method inside Bean class itself, return exception for invalid input. Trace the source of error through different types of exceptions.

cons:

  • need to create multiple custom exceptions.
  • Is it a right way to include validate method inside holder object itself??

I explored a couple of design patterns, but they were not related.

Please help me understanding pros and cons of above approaches, and a better one to follow.

役に立ちましたか?

解決

One of the commentators points out: "You'll want to end up with a collection of validation errors." That is important.

In my experience, validation methods inside of their model objects do not work because the validation logic changes frequently and because something that is not valid under one set of circumstances is valid under another set of circumstances. For example, if the validation method considers anything later than 9 PM to be invalid, the school administer could change change the rules so that courses during summer quarter can run until 11 PM. You don't want to be stuck with your validation method inside your class when that kind of thing happens, as it inevitably does.

Also, it is often impossible to validate an object without knowing about the state of other objects in the system. For example, if you have a Loan object, loan values over $100,000 might be invalid, expect when the Customer object is of type Institution. You need to know about both the Loan and Customer objects to correctly validate the Loan.

The best practices I've seen for complex validation are:

  1. Valid simple things before accepting the object. This includes checking for invalid characters or non-digits in number fields.

  2. Create a validation framework that validates a group of dependent objects at once. Do not stop your validation routine at the first error you find. Instead, create a class named ValidationError and have your framework create a collection of these objects. This approach let's you account for intra-object and inter-object dependencies. Also, you can present all the errors to the user at once instead of forcing the user to correct errors one-at-a-time.

  3. Don't hard code values like minimumNumberOfStudents or latestClassTime. Instead, put these values in a relational database table or a configuration file. Make the validation framework look up the correct values (and then cache them). When the values change (as they often will) you only need to update a file or a database; there is no need to rebuild and redeploy the entire application. When I did this work, I was coding in Smalltalk. If you are using a dynamic language like Smalltalk or Ruby, it is easy to actually put source code into your database as a "validation block" and execute it at run-time.

A validation framework might use exceptions, but I recommend against this. Exceptions should be reserved for more drastic errors that are harder to recover from. Also, exceptions can incur a big penalty performance, which is important if the validation is done on a server and not on the client. Worse still, a few platforms have shaky exception handling.

他のヒント

Like pointed above, there is an absolute ton of ways you can do something like that.

If I was implementing something like that, I would take a look at this article http://java.dzone.com/news/factories-builders-and-fluent- about fluent interfaces combined with a builder pattern.

Perhaps it suits your needs. Take special attention to the validation of the bean part.

Hope it helps.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top