Where to put validation

254 views
Skip to first unread message

Branislav Hašto

unread,
Sep 15, 2014, 3:21:18 AM9/15/14
to growing-object-o...@googlegroups.com
Hi everyone, 

lately I've been thinking about validation.

Let's say I have a web app with a form that allows to enter e-mail. Let's say it is a classic old web app, no javascript involved. In my code, I want e-mails encapsulated in an Email value object. 
  • I want my Email value object to always represent a valid e-mail, so I would probably need to throw an exception in constructor if invalid string is passed in. Do you agree?
  • I try to respect one rule - exceptions should be used only in exceptional situations. User entering an invalid value into form is not an exceptional situation in this case. So at the same time, I would probably need to put some validation code at the boundary of the system (something like Controller in Spring MVC). In that case, how do you prevent duplication? Would you rather duplicate the validation in both places, or decide to catch an exception from the value object and handle it here?
  • Would anything change if it was an application with rich client that would do it's own validation before sending data to your server?

Thanks,

Braňo.

Steve Freeeman

unread,
Sep 15, 2014, 4:13:17 AM9/15/14
to growing-object-o...@googlegroups.com

On 15 Sep 2014, at 08:21, Branislav Hašto <bha...@gmail.com> wrote:
> lately I've been thinking about validation.
>
> Let's say I have a web app with a form that allows to enter e-mail. Let's say it is a classic old web app, no javascript involved. In my code, I want e-mails encapsulated in an Email value object.
> -I want my Email value object to always represent a valid e-mail, so I would probably need to throw an exception in constructor if invalid string is passed in. Do you agree?

I would write a factory method to do the validation and return a clean instance. Constructors should just fill in the values.

> • I try to respect one rule - exceptions should be used only in exceptional situations. User entering an invalid value into form is not an exceptional situation in this case. So at the same time, I would probably need to put some validation code at the boundary of the system (something like Controller in Spring MVC). In that case, how do you prevent duplication? Would you rather duplicate the validation in both places, or decide to catch an exception from the value object and handle it here?

Validation at the edges of a system is generally a good idea. If you have that, then you don't need it internally. If you don't trust your coders, you have a bigger problem...

> • Would anything change if it was an application with rich client that would do it's own validation before sending data to your server?

probably, but that would depend :)

S

Nat Pryce

unread,
Sep 15, 2014, 5:22:35 AM9/15/14
to growing-object-o...@googlegroups.com
Yes, validate at the edges.  Parse user input into email address values that are known to be valid.

I would rather the email address type made it impossible to pass invalid values to its constructor, rather than have a constructor that can be passed invalid values that are checked at runtime.

E.g.

    class EmailAddress(user: UserName, host: HostName)

But email addressverification is notoriously difficult (http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html). It's often better to send a verification link to the entered address.

--Nat



--

---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriente...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
http://www.natpryce.com

Kevin Rutherford

unread,
Sep 15, 2014, 5:40:52 AM9/15/14
to growing-object-o...@googlegroups.com
Hi Nat, Steve,

On Mon, Sep 15, 2014 at 10:22 AM, Nat Pryce <nat....@gmail.com> wrote:
> Yes, validate at the edges. Parse user input into email address values that
> are known to be valid.
>
> I would rather the email address type made it impossible to pass invalid
> values to its constructor, rather than have a constructor that can be passed
> invalid values that are checked at runtime.

This is what I try to do, where possible.
Does it contradict Steve's advice? Or will Steve's factory method take
a string, parse it into a Username and Hostname, and then call the
constructor?


--
http://xpsurgery.com -- remote one-to-one tutoring in TDD and OO
http://kevinrutherford.co.uk -- software development coaching
http://refactoringinruby.info -- Refactoring in Ruby, the book

Branislav Hašto

unread,
Sep 15, 2014, 5:56:17 AM9/15/14
to growing-object-o...@googlegroups.com
Thank you for your replies.

The part about avoiding parsing if possible is really helpful.

Let's say it would be some other value that needs to have a given format - social security number or something similar - something that needs to be validated at runtime (I am obviously not very good with examples :) ).

As I thought, it would be good to validate at the edge of the system and I would do it. What about checking it in the factory method mentioned above? Would you do it there as well, or just at the edge of the system?

What if we added something like CLI? In that case, would you validate just at the edges, or would you like to have validation also in your value objects?

What I am trying to ask - would you validate just at the edges (with the possibility that someone can accidentally skip a validation when adding a new edge) or would you rather duplicate the checking both at the edges and inside your system?
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriented-software+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriented-software+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Marcin Gryszko

unread,
Sep 15, 2014, 6:10:28 AM9/15/14
to growing-object-o...@googlegroups.com
Would you validate just at the edges (with the possibility that someone can accidentally skip a validation when adding a new edge) or would you rather duplicate the checking both at the edges and inside your system?

I'm in favor of validating at the edge ('soft' validation, just an error message to the user) and inside ('hard' validation, exception). 

I don't agree with Steve that you validation at the system boundary is just enough. Imagine you have a complex business rule (e.g. comparing an amount to a conditional sum of other amounts). If you code this rule in a controller, it will be implemented outside of your domain.

Even if your controller delegates validation to a domain component, you'll lose the relationship between your use case and the business rule related to that use case. In such case they would be related only through a non-domain component (controller).

Steve Freeeman

unread,
Sep 15, 2014, 6:17:36 AM9/15/14
to growing-object-o...@googlegroups.com
I don't think our advice is contradictory. I use factory methods to avoid any hint of decision-taking in the constructor. If there's no behaviour, then just use a constructor.

S

Colin Vipurs

unread,
Sep 15, 2014, 6:31:17 AM9/15/14
to growing-object-o...@googlegroups.com
This is one of the reasons I try to execute my acceptance tests purely from the domain - the relationship is explicit and cannot leak into the infrastructure side of things

Kevin Rutherford

unread,
Sep 15, 2014, 6:34:50 AM9/15/14
to growing-object-o...@googlegroups.com
On Mon, Sep 15, 2014 at 11:17 AM, Steve Freeeman <st...@m3p.co.uk> wrote:
> I don't think our advice is contradictory. I use factory methods to avoid any hint of decision-taking in the constructor. If there's no behaviour, then just use a constructor.

Got it, thanks.

Nat Pryce

unread,
Sep 15, 2014, 8:21:09 AM9/15/14
to growing-object-o...@googlegroups.com
I can't speak for Steve, but what I like to do is write a single parse method that I can use anywhere a program must receive a value of the type from an external source -- user input, command-line parsing, property files, mapping JSON, XML or a SQL result-set, a Hibernate user type, etc etc.  That way I get a consistent representation of the type in external data and type safe construction in code.

It's not always possible -- third party systems may impose their own representations -- but I follow that for anything I'm in control of.

--Nat.

--

---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriente...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Steve Freeeman

unread,
Sep 15, 2014, 9:47:59 AM9/15/14
to growing-object-o...@googlegroups.com
+1

Daniel Wellman

unread,
Sep 15, 2014, 8:31:46 PM9/15/14
to growing-object-o...@googlegroups.com
On Monday, September 15, 2014 8:21:09 AM UTC-4, Nat wrote:
I can't speak for Steve, but what I like to do is write a single parse method that I can use anywhere a program must receive a value of the type from an external source -- user input, command-line parsing, property files, mapping JSON, XML or a SQL result-set, a Hibernate user type, etc etc.  That way I get a consistent representation of the type in external data and type safe construction in code.

Nat (or Steve), I'm not sure I follow. Are you saying that you define a single type for any external data (say, ExternalEmailAddress) that needs to be parsed into a trusted domain type (like EmailAddress)?

Would it be something like this?   I've put some comments inline with some questions.

class EmailAddress {

  private UserName userName;
  private HostName hostName;

  public EmailAddress(UserName username, HostName hostName) {
    // simply assigns fields
  }

  public static EmailAddress parse(ExternalEmailAddress untrusted) {
    // Do something with 'untrusted' ...? 

  }
}

class ExternalEmailAddress {
  // Would this be a String, or something else?
  private String address;

  public ExternalEmailAddress(String address) {
    this.address = address;
  } 

  // What behavior does this object have?
}

Then when I get an input from a configuration file, read user input, or deserialize from JSON I'd do something like:

String input = // say, read from the console
EmailAddress e = EmailAddress.parse(new ExternalEmailAddress(input));


Thanks for your clarification!

Dan

Nat Pryce

unread,
Sep 16, 2014, 5:09:39 AM9/16/14
to growing-object-o...@googlegroups.com
I mean I'll have a single parse *method* that parses untrusted data (a String, for example) into a well typed domain abstraction (value type).

E.g.  

class StockKeepingUnitId {
    public final ProductId pid;     // short terms are what the business use
    public final int subid;

    StockKeepingUnit(ProductId pid, int subid) { ... }

    public static StockKeepingUnitId parse(String s) throws ExternalDataFormatException {
        // monkey about with regex or whatever here...
    }
}





--

---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriente...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Nat Pryce

unread,
Sep 16, 2014, 5:10:47 AM9/16/14
to growing-object-o...@googlegroups.com
Ah  I see where the misunderstanding comes from... "function" would be a better word to use than "method".

--Nat

Torbjörn Kalin

unread,
Sep 16, 2014, 3:27:25 PM9/16/14
to growing-object-o...@googlegroups.com
I think I'm about to say the same thing as others, but I'll use different words.

One of my favourite architectural patterns is Ports and Adapters. I believe it is also mentioned in GOOS. Read about it from Alister Cockburn if you are not familiar with it.

The e-mail address value type belongs to the application hexagon. Instances are, however, never created within the center hexagon, but they are always created in the adapters (using a factory method). Also, an e-mail address can never exist within the center hexagon unless encapsulated by the e-mail value type. This means that there can never exist an invalid e-mail address in the center hexagon (oh, and I agree with Nat, don't kill yourself trying to validate the e-mail address).

If someone skips validation in the adapter ("the edges") it means that it is passed into the center hexagon as a string. That ought to be quite easy to spot for other programmers (re-)viewing the code.

As an answer to your third bullet, the server is one hexagon and the rich client is another. The server should do the validation (in its adapters). This, I think, is both a good design, but also important from a security perspective: you'll never know who obtains access and tries to send SQL commands as e-mail addresses directly to the server.

You'll probably need validation also in your rich client, but that is mainly for usability reasons. You could decide to trust the server validation whenever usability is not a issue.

Duplication is a difficult problem. Having a rich client written in the same language as the server you might be tempted to have them share a library with validation logic. While you could, you might get a bigger headache from the dependency between the two: changes in the library will require a release of both server and client.

/T


To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriente...@googlegroups.com.

Daniel Wellman

unread,
Sep 16, 2014, 6:37:27 PM9/16/14
to growing-object-o...@googlegroups.com
Thanks for that clarification and the example, Nat. I think the part that confused me was:

> ... That way I get a consistent representation of the type in external data and type safe construction in code.

I had wondered if you were suggesting that most of the time you make a type to specifically represent data from outside the system, separate from your "in the domain" type, and then you make a parse method that parses that external type.

Dan



Sent from my iPhone

Steve Freeeman

unread,
Sep 17, 2014, 4:23:38 AM9/17/14
to growing-object-o...@googlegroups.com
I think that's the point. If I'm going to bother with static typing, then I'll use a domain type within the "zone". I'll need a translation from the outside world at some point to create it, probably parsed from a string.

S

Thiago - BOL

unread,
Nov 4, 2014, 12:12:28 PM11/4/14
to growing-object-o...@googlegroups.com
(A late answer, I know)

I think you should perform a soft validation at the client side, just to avoid talking to the server continuously to check things. Maybe you can use some JavaScript library to help you with the job (say, jQuery Validation).

In the server side, I could create a separated domain class to validate your use case. I know some guys here would think this is an anemic domain model but don't get me wrong. Some Customer validation, for example, may need to talk to the CustomerBase or another objects that are out of the "Customer" abstraction. So it doesn't fit to place all the Customer validation in the Customer class.

This new class dedicated to this validation (e.g. CustomerValidation) could have a "validate(obj)" method that throws an exception when the received object is invalid, according to the defined business rules. Note that this class can be reused through different applications or layers in the same application.

An example of a common server processing would be:

// -- save a customer ------------------------------------
customer = createCustomerFromRequestParameters();
cleanCustomer = sanitize( customer ); // << The server sanitizes, but not validates

customerBase = new PersistentCustomerBase();
...
customerValidation = new CustomerValidation( customerBase, ... );
...
customerService = new CustomerService( customerValidation, customerBase, ... );
try {
  // save() will call customerValidation.validate( cleanCustomer ) before doing its job
  customerService.save( cleanCustomer );
  ... send successful response ...
} catch (DomainException e) {
  ... send error response ...
}
// -------------------------------------------------------

What do you think?

- Thiago




De: Branislav Hašto <bha...@gmail.com>
Para: growing-object-o...@googlegroups.com
Enviadas: Segunda-feira, 15 de Setembro de 2014 4:21
Assunto: [GOOS] Where to put validation

Torbjörn Kalin

unread,
Nov 6, 2014, 4:01:53 PM11/6/14
to growing-object-o...@googlegroups.com
Re-reading the thread, I think there has been some confusion about the word validation. For the sake of discussion, let's define two types of validation here: format validations and business rule validations.

Format validations: For instance, from the original poster's example, does the e-mail address have a valid format? Or, since that's difficult to verify, does a credit card number have the correct number of digits and a correct checksum value? Is a given age a positive number?

Business rule validations: Is the age above 18? Is the order sum lower than the maximum allowed? Is the given pay in advance amount lower than the given total amount?

Thiago, correct me if I'm wrong, but I think you are talking about business rule validation (something I would just call business rules).

Using hexagonal architecture, I would perform format validations in the adapter. No ill-formatted data may enter the application hexagon. All business rule validation should however be performed by the application hexagon (although I agree with you that performance increasing validation may also be done by the client).

In your code example, the createCustomerFromRequestParameters() probably performs the format validations while the CustomerValidation class contains the business rules (although I would probably not create a separate class for it, but let CustomerService or even the Customer class contain the business rules).

(I sometimes find it hard to distinguish between format validation and business rules. For instance, is age above 18 really a business rule? Can't you have a value type that guarantees an age above 18, and thus define it as format validation?)
/T

Thiago - BOL

unread,
Nov 11, 2014, 11:32:08 AM11/11/14
to growing-object-o...@googlegroups.com
I agree and also think that "age above 18" is a business rule.

- Thiago




De: Torbjörn Kalin <torb...@kalin-urena.com>
Para: growing-object-o...@googlegroups.com
Enviadas: Quinta-feira, 6 de Novembro de 2014 19:01
Assunto: Re: [GOOS] Where to put validation

Maurício Aniche

unread,
Nov 11, 2014, 12:45:57 PM11/11/14
to growing-object-o...@googlegroups.com
Using hexagonal architecture, I would perform format validations in the adapter. No ill-formatted data may enter the application hexagon. All business rule validation should however be performed by the application hexagon (although I agree with you that performance increasing validation may also be done by the client).

+1. I do the same.

Regards,
Maurício
 

Matt Wynne

unread,
Nov 11, 2014, 3:40:24 PM11/11/14
to growing-object-o...@googlegroups.com

On 6 Nov 2014, at 21:01, Torbjörn Kalin <torb...@kalin-urena.com> wrote:

> In your code example, the createCustomerFromRequestParameters() probably performs the format validations while the CustomerValidation class contains the business rules (although I would probably not create a separate class for it, but let CustomerService or even the Customer class contain the business rules).

I really like the way David West’s Object Thinking describes having an object per rule, so you’d have a Chain of Responsibility that let each of the business rules apply themselves.

cheers,
Matt

---
ma...@mattwynne.net

signature.asc
Reply all
Reply to author
Forward
0 new messages