One thing that really stuck with me while reading/watching/learning about Uncle Bobs Clean Architecture was the idea that invalid data should not cross the boundary between the delivery mechanism and the application code.1 As a consequence the application code is free of validations and only works with proper data.
To illustrate why this is a desirable result we take a look at Ruby on Rails. Let's assume we have a web form and users can sign up. They have to provide an email address and a password. In a vanilla Ruby on Rails project you would have an ActiveRecord model
Identity and add two presence validations to it. While this works for this case it starts breaking when you add the ability for admins to create new users without providing a password. Now you have to start mutilating your application code by skipping validations in certain places.
Having to skip validations is a sign that validating data occurs in the wrong place.
The correct place to validate that an email and a password are provided is at the boundary to the application. The user action has a different entry point than the admin action. Therefore it is easy to specify the proper validation rules for each entry point and prevent invalid data from entering the system. Lotus has this mechanism built into its controller actions. These actions are the entry points to your application when HTTP is used as a delivery mechanism.
Even when you don't know Lotus the code above should be understandable. We specify that we expect the parameters
identity[password]. First of all this acts as a whitelist, parameters not specified get stripped before they enter the application.
type: String tells Lotus to coerce the parameter, your application code does not have to be bothered with type checks because the data will always have the correct type. The final part is the presence validation making sure that the parameters are actually present.
Should the validations fail we halt the request and return a
422 Unprocessable Entity response. This is exactly what we want in terms of incoming data validations. Adding an admin action where the password is not required is easy because the validations happen at the boundary and not inside the application.
How can we produce such a response in Lotus? Simple, we pass
halt a message as second argument, this will be the body of our response. In order to achieve this in a clean way we write a small module and a class. The module will hold our unified logic for halting the request if the parameters are not valid. The class serializes the Lotus validations errors object into a consumable format. (If you know a better way to accomplish this I would love to hear from you.)
Having these two pieces of code in place we can include the module in our action and add an before callback to invoke the
validate! method. Now we can clean up the
call method and remove the guard condition. At this point the action works again as we want and it is easy to add the same behaviour to other actions. Using
controller.prepare you can easily add it by default to all actions.
A quick search did not turn up a resource where Uncle Bob himself talks about this. In Adam Hawkins article about Form Objects with Virtus Avdi Grimm is mentioned in the context of this topic. But I do believe Adam Hawkins article series about software architecture aligns well with Clean Architecture. ↩