When designing a class, should logic to maintain valid state be incorporated in the class or outside of it ? That is, should properties throw exceptions on invalid states (i.e. value out of range, etc.), or should this validation be performed when the instance of the class is being constructed/modified ?
-
See this question for more insight : http://stackoverflow.com/questions/88541/business-objects-validation-and-exceptions – Mac Jul 21 '09 at 08:35
8 Answers
It belongs in the class. Nothing but the class itself (and any helpers it delegates to) should know, or be concerned with, the rules that determine valid or invalid state.

- 160,644
- 26
- 247
- 397
-
Thank you for your reply. In this case, would I surround instantiations with try...catch's or fail "gracefully" ? For example: try { Type myType = new Type(aValue); } catch (InvalidException e) { .. } or set to some "safe" default ? – Scott Davies Jul 13 '09 at 22:13
-
3No. That's not a graceful failure, that's a lie. Leave the exception alone until there's something you can _do_ about it. – John Saunders Jul 13 '09 at 22:18
-
Ok, I think I am starting to get this. I am assuming that the "safe" default is the lie, not the try..catch ? In the try..catch case, I am not "eating" the exception, I have just left the handling out and put in .. – Scott Davies Jul 13 '09 at 22:24
Yes, properties should check on valid/invalid values when being set. That's what it's for.

- 8,802
- 8
- 40
- 62
It should be impossible to put a class into an invalid state, regardless of the code outside it. That should make it clear.
On the other hand, the code outside it is still responsible for using the class correctly, so frequently it will make sense to check twice. The class's methods may throw an ArgumentException
if passed something they don't like, and the calling code should ensure that this doesn't happen by having the right logic in place to validate input, etc.
There are also more complex cases where there are different "levels" of client involved in a system. An example is an OS - an application runs in "User mode" and ought to be incapable of putting the OS into an invalid state. But a driver runs in "Kernel mode" and is perfectly capable of corrupting the OS state, because it is part of a team that is responsible for implementing the services used by the applications.
This kind of dual-level arrangement can occur in object models; there can be "exterior" clients of the model that only see valid states, and "interior" clients (plug-ins, extensions, add-ons) which have to be able to see what would otherwise be regarded as "invalid" states, because they have a role to play in implementing state transitions. The definition of invalid/valid is different depending on the role being played by the client.

- 114,894
- 38
- 205
- 284
-
1So what happens if you have a validation requirement that an entity that has a Widget must also have a Gadget and vice versa. Since you can't assign both at the same time (typically), you will have to live with an invalid state for at least a short period of time. For most purposes, I think it's sufficient that you can't **persist** an invalid state. Ephemeral objects can be invalid as long as they aren't stored. – tvanfosson Jul 13 '09 at 22:17
-
1Is this in some hypothetical language where I can't define a method that takes two arguments? – Daniel Earwicker Jul 13 '09 at 22:26
-
1@Earwicker -- note, that the question is tagged C# where the class' data is usually set via property accessors rather than methods. Are you arguing that in order to maintain valid state you need to have methods that set all related properties at the same time? Assuming that you allow some intermediate invalid states for the duration of the method, that is. This seems to be a rather onerous requirement. Why not let external entities build up a valid object in the same way the class methods would and defer validation until the object is persisted? – tvanfosson Jul 13 '09 at 22:38
-
...I'll grant that there are cases where you would want to be this strict, but I don't think that those cases are typical. – tvanfosson Jul 13 '09 at 22:38
-
@tvanfosson: There are conventions to deal with this: ISupportInitialize.BeginInit/.EndInit, for instance. – John Saunders Jul 13 '09 at 22:41
-
1@tvanfosson - if the state can be modified in stages by setting properties, then by definition you are saying that the intermediate states are valid from the perspective of the code setting the properties. – Daniel Earwicker Jul 14 '09 at 06:19
Generally this belongs in the class itself, but to some extent it has to also depend on your definition of 'valid'. For example, consider the System.IO.FileInfo
class. Is it valid if it refers to file that no longer exists? How would it know?

- 399,467
- 113
- 570
- 794
I would agree with @Joel. Typcially this would be found in the class. However, I would not have the property accessors implement the validation logic. Rather I'd recommend a validation method for the persistence layer to call when the object is being persisted. This allows you to localize the validation logic in a single place and make different choices for valid/invalid based on the persistence operation being performed. If, for example, you are planning to delete an object from the database, do you care that some of its properties are invalid? Probably not -- as long as the ID and row versions are the same as those in the database, you just go ahead and delete it. Likewise, you may have different rules for inserts and updates, e.g., some fields may be null on insert, but required on update.

- 524,688
- 99
- 697
- 795
-
This is the stake of Paul Stovell, which he summed up in this article : http://www.codeproject.com/KB/cs/DelegateBusinessObjects.aspx – Mac Jul 21 '09 at 08:34
It depends.
If the validation is simple, and can be checked using only information contained in the class, then most of the time it's worth while to add the state checks to the class.
There are sometimes, however, where it's not really possible or desirable to do so.
A great example is a compiler. Checking the state of abstract syntax trees (ASTs) to make sure a program is valid is usually not done by either property setters or constructors. Instead, the validation is usually done by a tree visitor, or a series of mutually recursive methods in some sort of "semantic analysis class". In either case, however, properties are validated long after their values are set.
Also, with objects used to old UI state it's usually a bad idea (from a usability perspective) to throw exceptions when invalid values are set. This is particularly true for apps that use WPF data binding. In that case you want to display some sort of modeless feedback to the customer rather than throwing an exception.

- 24,561
- 8
- 60
- 89
The valid state in a class is best express with the concept of class invariant. It is a boolean expression which must hold true for the objects of that class to be valid.
The Design by Contract approach suggests that you, as a developer of class C, should guarantee that the class invariant holds:
- After construction
- After a call to a public method
This will imply that, since the object is encapsulated (noone can modify it except via calls to public methods), the invariant will also be satisfied at entering any public method, or at entering the destructor (in languages with destructors), if any.
Each public method states preconditions that the caller must satisfy, and postconditions that will be satisfied by the class at the end of every public method. Violating a precondition effectively violates the contract of the class, so that it can still be correct but it doesn't have to behave in any particular way, nor maintain the invariant, if it is called with a precondition violation. A class that fulfills its contract in the absence of caller violations can be said to be correct.
A concept different from correct but complementary to it (and certainly belonging to the multiple factors of software quality) is that of robust. In our context, a robust class will detect when one of its methods is called without fulfilling the method preconditions. In such cases, an assertion violation exception will typically be thrown, so that the caller knows that he blew it.
So, answering your question, both the class and its caller have obligations as part of the class contract. A robust class will detect contract violations and spit. A correct caller will not violate the contract.
Classes belonging to the public interface of a code library should be compiled as robust, while inner classes could be tested as robust but then run in the released product as just correct, without the precondition checks on. This depends on a number of things and was discussed elsewhere.

- 1
- 1

- 22,454
- 9
- 63
- 116
The class really should maintain valid values. It shouldn't matter if these are entered through the constructor or through properties. Both should reject invalid values. If both a constructor parameter and a property require the same validation, you can either use a common private method to validate the value for both the property and the constructor or you can do the validation in the property and use the property inside your constructor when setting the local variables. I would recommend using a common validation method, personally.
Your class should throw an exception if it receives invalid values. All in all, good design can help reduce the chances of this happening.

- 368
- 1
- 10