I'm looking into developing my entities so that they cannot be in an invalid state.

In particular I'm starting with my Customer entity. This would have fields like:

  • Title (enum)
  • FirstName (string)
  • LastName (string)
  • Address (value object with another 6 fields)
  • MainTelephone (string)
  • AlternateTelephone (string)
  • EmailAddress (string)

I've added methods such as ChangeOfAddress() to facilitate the changing of address, which will ensure a valid address is entered as a replacement.

In the UI, I consider most fields (except for AlternateTelephone and EmailAddress) as 'required', encouraging users to complete fields such as Title to make addressing mail shots easier in the future.

For methods like ChangeOfAddress() the concept of 'invalid state' is an easy one, as I can apply validation on the new Address value object, but for the construction of a new Customer object I'm not as sure.

I guess my question is, should the bare minimum for the construction of a Customer entity include all the fields I feel are 'required' from the perspective of the UI? I can't imagine how creating a Customer with only a FirstName and LastName (without any contact details), would be valid in the business sense I intend to use the Customer object in. Although in a sense FirstName and LastName are good starting points for a minimum description of a Customer and I guess the Customer wouldn't be 'invalid' it'd just be lacking enough information to be useful to my business needs (which would be, to be able to contact them).

Hope this makes sense, I'd be interested to hear any opinions, as I'm still learning as I go.

  • 1
    As a side note consider using value objects for all customer attributes (i.e. FirstName, LastName, Address,...etc.) instead of primitive data types such as strings. This way you can validate for empty strings, null, invalid characters, max size, min size and many more in the value object itself and maybe reuse the validation logic in the forms.
    – Songo
    Apr 21, 2013 at 11:17
  • 1
    Sometimes you don't get all of the data in the first go. The first time a sales rep loses a sale because he had to say, "I'm sorry, I can't sell to you because the system won't let me add you without (whatever)," you'll hear about it. Or he'll put in bogus placeholder data.
    – Blrfl
    Apr 21, 2013 at 12:03
  • Thanks @Blrfl the sort of suck-it-and-see approach seems a good idea, make a best effort to satisfy the business use and then adapt and change if it's not right. Apr 21, 2013 at 20:34
  • Data with placeholders is much harder to find and clean up than data with missing values. Putting up a nudge notice ("Please ask customer for missing postal code") whenever someone is doing something involving that customer may help you get the missing data.
    – Blrfl
    Apr 22, 2013 at 12:40
  • That's got me thinking, the minimum set of data for a customer is probably less than I originally thought. Cheers. Apr 22, 2013 at 18:03

1 Answer 1


Sure, go ahead. Write your constructor so that it requires all fields that are required in the usual, "happy-path" rout to creating a customer. If it works, great! You've completed part of the requirements and enforced the integrity of a key data asset at the same time.

If it doesn't work, you will have learnt something about the system that you didn't know before, i.e. that your assumptions about the flow of data were wrong on an important point. This will almost certainly enable you to create a better model of the domain: revise your assumptions and revise the code to match them, and the system will profit from it.

Note that having had wrong assumption is in no way shameful or a setback. The ways that even the most basic assumptions can go wrong are manifold. Maybe a key lead must be entered because it is too valuable to pass up even without having completed the questionnaire. Maybe you need to interoperate with a legacy system that had different optionality rules. Maybe the state of California secedes, so that a previously valid contact becomes invalid even though the data are the same as they were before! My point is: you will have to revise assumptions. If you have cast them into the terms of your language, then the compiler will warn you when that happens. If you haven't, then you may go on for a quite a while following a rationale that no longer makes sense without noticing it. That's why making assumptions explicit is a good thing.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.