Form Objects

Do You Need That Validation?

Do You Need That Validation?

by Tobias Pfeiffer

The video titled "Do You Need That Validation?" features Tobias Pfeiffer, presenting during the Pivorak Conf 3.0 in Lviv. The main theme centers around the complexities of validations in software development, particularly within Rails applications. Tobias discusses various challenges developers face when implementing validations and highlights ways to improve code maintainability.

Key Points:
- Community and Events: The session begins with an appreciation of the Lviv community and the importance of organizing events, leading to the idea of creating an event management app.
- Event Management App Development: A prototype app is proposed which simplifies event organization by reducing redundancy in date entries while addressing potential pitfalls related to validation hooks.
- Challenges with Validations: Tobias explains how overly complex validations can obscure issues, using the example of a doctor’s appointment to illustrate how they might lead to unexpected errors in the system.
- GitLab User Model Case Study: A detailed analysis of the user model at GitLab is presented, showcasing how complex conditional validations can entangle logic and make debugging difficult.
- Affordances and Simplification: There’s a strong emphasis on the concept of "affordances," promoting the idea that software should communicate its requirements clearly without unnecessary complexity in validation logic.
- Overcomplication of Models: Highlighted are the risks of adding too many responsibilities to models, which can cause clutter and decrease maintainability.
- Service Objects and Form Objects: Alternatives to handle validations effectively include implementing service and form objects, separating the validation logic from the core user model and ensuring clarity.

- Frameworks and Libraries: Recommended tools like Active Type and techniques for managing applications with distinct contexts help improve readability and maintenance of code.
- Main Takeaways: Recognizing the burden of complex validations leads to a call for better design approaches that enhance the clarity, maintainability, and scalability of software.
- Final Remarks: Tobias encourages developers to reflect on their implementations, advocating for structured separation of concerns to advance their projects effectively.

00:00:08.179 Thank you everyone for having me back. I had a blast last time, staying about five days in the beautiful city of Lviv. I enjoyed discovering all it has to offer and I'm thrilled to see that you have an amazing community here. When I was here, I visited your free Rails course and I would love to know how many of you are alumni of that course. I know at least one person here was, who I recognized from the last time I was in town. I'm very happy to be back, and I'm excited to meet all of you. It's great to reconnect, especially with familiar faces like Anton, who has since moved to Kyiv.
00:01:10.030 In such a great community, one important thing you need is to organize events. So today, let’s build an app to help organize an event. An event typically has a name, a location, a date, and a schedule for the crew and performers. It also has a start and end time, among other details. However, repeating the date appears cumbersome, especially if it’s a one-day event. Instead, we should have a single date entry and simply reference the times. This approach is a perfect opportunity to create our new MVP for event management software.
00:01:42.290 To make this application work, we could implement a before validation hook. This feature will handle the time fields to set dates correctly by leveraging Ruby’s powerful capabilities. By entering the event date, the hook can automatically adjust the time fields. We can then check whether the event setup works correctly, indicating that our new event management software is effective. However, this simplicity can lead us to overlook potential pitfalls; for instance, if we save an event with an arbitrary date in the future, there may be unexpected consequences due to this hook.
00:02:56.269 When performing tests on a future date, we might find that values revert to a default state due to our validation hook. This unexpected backtracking to a previous date can cause significant confusion, leading to failed tests because the event is technically considered valid as it references an outdated date. As developers, this can lead us down a rabbit hole of debugging and might lead us to wrongly conclude that our query implementations are flawed instead of recognizing the issue in our event setup.
00:03:59.990 This situation leads me to believe that before validation hooks can be a sign of trouble. Such hooks can subtend problems by obscurely changing inputs—their presence can suggest that something might not be right. Validations can often go awry when they become overly complex and tied into business logic, leading to maintainability issues. For instance, a model's responsibility is not to sanitize all inputs before each validation run. This approach can lead to unusual side effects, like CPU-bound execution times, along with silent errors when validations get skipped altogether.
00:05:35.269 As we explore the concept of validations, let’s look at an example from a user model in GitLab. Good engineers, even those at large organizations, can still produce code that isn’t entirely straightforward. In this instance, we see complex conditional validations for unique emails that can cascade from various situations, reflecting a defensive coding approach—where one validation can easily obstruct another. The design leads to complicated logic flows that can be hard to debug.
00:06:31.159 Taking a step back, we need to ask ourselves why such convoluted patterns persist. Could it be that we’re not considering the affordances of our code? Affordances relate to how a piece of software is intended to function: for example, when designing forms, how are we communicating requirements to the user? By simplifying how we handle code segments and validations, we can make sure our software stays maintainable.
00:06:56.270 Validations can eventually lead us to overcomplicate our models. When we include too many responsibilities in our user models that relate to things like email formats or terms of service acceptance checks, validations may inadvertently end up cluttering our code. Most validations should reflect specific business logic and not become a catch-all for every possible state.
00:07:55.920 In many cases, the same value being validated against multiple attributes can result in tangled, overlapping concerns. This makes it very hard to track down issues that arise during development. If multiple states trigger side effects, we risk entering into complex debugging scenarios—inevitably making it more difficult to understand what the intent was behind each validation rule.
00:08:37.850 Next, as we consider alternatives to handling validations in our Rails applications, we might focus on implementing service objects or form objects, both of which can help decouple validations from models to manage duties effectively. This way, validation logic can reside within dedicated classes that only serve to validate specific scenarios without needing to interfere with each other or the database layer.
00:09:40.580 For example, using a form object would separate the registration flow of a user: handling inputs for creating a user, such as emails and passwords, can reside in a dedicated object that knows nothing about the database or persistent conditions. Hence, it only focuses on simply ensuring the correct format, information, and handling any operations, including sending welcome emails in a direct method.
00:10:54.950 Thus far, we have covered potential issues, such as excessive validations and unintended coupling due to complex dependencies across models. Now, let’s say we transition more towards utilizing service objects to handle particular tasks while isolating unnecessary validations and callbacks, making overall structural designs clearer and easier to manage.
00:12:02.500 I will also bring attention to libraries that can appropriately achieve this design separation. Services like Active Type, for example, allow you to create separate models specific to a certain context. This means we’re not enforcing irrelevant fields and functionalities in our central user model; instead, we can encapsulate specific logic and validations relevant only to specific features of our application.
00:13:23.750 Finally, let’s distinguish between validations and the various contexts for operations within our application architecture. When using systems like Trailblazer or Hanami, information can flow into distinct parts of an app cleanly, allowing for better readability and, by extension, better maintenance. These frameworks remind us to retain only crucial logic in models while extracting any side functionalities into clearer structures.
00:14:37.940 So, with all that said, what can we take away from my observations today? First off, I don’t harbor any dislike towards Rails; it has shaped many of our careers, including mine. However, it’s important we recognize areas for improvement in how we impose validations and the coupling that occurs when business logic is intertwined carelessly. We should all also consider the affordances of our implementations: does the design properly reflect the purpose and utility of the software—the overall behaviors expected from users and their interactions with it?
00:15:32.800 Remember, in the framework of Rails, there’s always room for us to innovate by ensuring our software designs promote value clarity, making it easier to test, maintain, and extend. Acknowledging the importance of structure and thoughtful separation of concerns can strengthen our future projects—as well as refining how we conceive business logic in a coherent manner that’s more efficient, maintainable, and scalable.
00:16:31.000 Thank you for your attention, it’s been great engaging with all of you on this topic. I look forward to your questions!
00:17:07.600 Thank you! It’s been an insightful session altogether.
00:17:12.300 I appreciate the interaction and perspective shared during this workshop. I’m happy to connect with everyone as we explore how these approaches adapt to our evolution as developers.