views:

87

answers:

1

I'm wondering what the best approach is to verify that a class has all the required details before it can be used.

For example say I have a Book class and I want to pass in a set of properties about the book to the Book constructor.

Book book = new Book(bookProperties);

What I want to make sure that BookProperties is complete, i.e. has all the information.

Let's say in this example I have the following:

  • Book Title
  • Book Author
  • Book Original Publishing Date

One way is that I could create a default constructor that only accepts all 3 items:

BookProperties bookProperties = new BookProperties("2001: A Space Odyssey",
                                                   "Arthur C. Clarke",
                                                   1968);

Now this is ok, if we only have three values, but say my class has 10 or more properties that need to be initialized by the user before the Book class can be created.

One thing I was thinking was having a method in the BookProperties called isValid. Then in the constructor of the Book class I would see if bookProperties.isValid and assert if the return is false.

Is this a good idea or am I going about this all wrong?

+3  A: 

If it needs 10 values, then it isn't unheard of to pass 10 values into the constructor - but what you describe sounds more like an entity object. For convenience, it is common to just use the property setters. With C# 3.0 you can use initializer syntax to do this conveniently and clearly:

Book book = new Book {
    Title = "2001: A Space Odyssey",
    Author = "Arthur C. Clarke",
    PublishedYear = 1968
};

You can use a BookProperties object (as some kind of builder) - but in that case, why not make construction a method on the builder? Then the builder does the validation before creating a Book (presumably via an internal constructor) - and throws an exception if there is a problem. I'm assuming the use of BookProperties is (for example) to allow an immutable Book - but there is no need for the builder to be immutable:

var bookProperties = new BookProperties(); // builder?
bookProperties.Title = "2001: A Space Odyssey";
...
Book book = bookProperties.CreateBook();

Personally, I'd use just the Book approach (topmost above) in most cases - this approach plays well with common .NET serialization engines and binding frameworks (both of which like parameterless constructors and get/set properties), for example. If you want validation, then perhaps just add a Validate() method (or IsValue {get;} property) to Book. Or implement IDataErrorInfo.

Marc Gravell
However, it can get difficult to preserve correct class invariants at all times when you build up state property by property. If you're not careful, you can end up with a class that has different modes, depending on whether enough properties have been filled in or not. I prefer the object builder approach (BookProperties), but using initializer syntax for *it*, rather than the final class.
Barry Kelly
The official guidelines are that the order of setting properties shouldn't matter; so **if** you are in this scenario, property setters aren't an appropriate solution. But most of the time this isn't the case...
Marc Gravell
I think I'll go with the Validate() method on the properties class when the book constructor is called. Then it will error if the result if false.
Coding Monkey