Code Smell 139 - Business Code in the User Interface
Validations should be on the interface, or not?
TL;DR: Always create correct objects in your back-ends. UIs are accidental.
Problems
Security problems
Code Duplication
Testability
Extensibility to APIs, micro-services, etc.
Anemic and mutable objects
Solutions
- Move your validations to the back-end.
Context
Code Duplication is a warning for premature optimization.
Building a system with UI validations might evolve to an API or external component consumption.
We need to validate objects on the back-end and send good validation errors to client components.
Sample Code
Wrong
<script type="text/javascript"> function checkForm(form) { if(form.username.value == "") { alert("Error: Username cannot be blank!"); form.username.focus(); return false; } re = /^\w+$/; if(!re.test(form.username.value)) { alert("Error: Username must contain only letters, numbers and underscores!"); form.username.focus(); return false; } if(form.pwd1.value != "" && form.pwd1.value == form.pwd2.value) { if(form.pwd1.value.length < 8) { alert("Error: Password must contain at least eight characters!"); form.pwd1.focus(); return false; } if(form.pwd1.value == form.username.value) { alert("Error: Password must be different from Username!"); form.pwd1.focus(); return false; } re = /[0-9]/; if(!re.test(form.pwd1.value)) { alert("Error: password must contain at least one number (0-9)!"); form.pwd1.focus(); return false; } re = /[a-z]/; if(!re.test(form.pwd1.value)) { alert("Error: password must contain at least one lowercase letter (a-z)!"); form.pwd1.focus(); return false; } re = /[A-Z]/; if(!re.test(form.pwd1.value)) { alert("Error: password must contain at least one uppercase letter (A-Z)!"); form.pwd1.focus(); return false; } } else { alert("Error: Please check that you've entered and confirmed your password!"); form.pwd1.focus(); return false; } alert("You entered a valid password: " + form.pwd1.value); return true; } </script> <form ... onsubmit="return checkForm(this);"> <p>Username: <input type="text" name="username"></p> <p>Password: <input type="password" name="pwd1"></p> <p>Confirm Password: <input type="password" name="pwd2"></p> <p><input type="submit"></p> </form>
Right
<script type="text/javascript"> // send a post to a backend // backend has domain rules // backend has test coverage and richmodels // it is more difficult to inject code in a backend // Validations will evolve on our backend // Business rules and validations are shared with every consumer // UI / REST / Tests / Microservices ... etc. etc. // No duplicated code function checkForm(form) { const url = "https://<hostname/login"; const data = { }; const other_params = { headers : { "content-type" : "application/json; charset=UTF-8" }, body : data, method : "POST", mode : "cors" }; fetch(url, other_params) .then(function(response) { if (response.ok) { return response.json(); } else { throw new Error("Could not reach the API: " + response.statusText); } }).then(function(data) { document.getElementById("message").innerHTML = data.encoded; }).catch(function(error) { document.getElementById("message").innerHTML = error.message; }); return true; } </script>
Detection
[X] Semi-Automatic
We can detect some behavior patterns in our UI code
Tags
- Mutability
Conclusion
Use TDD.
You will put all your business logic behavior on your domain objects.
Relations

Code Smell 97 - Error Messages Without Empathy
Maxi Contieri ・ Oct 27 '21

Code Smell 01 - Anemic Models
Maxi Contieri ・ Oct 20 '20

Code Smell 90 - Implementative Callback Events
Maxi Contieri ・ Oct 7 '21
More Info
Credits
Photo by Lenin Estrada on Unsplash
I think another good principle is separating presentation or user interface (UI) from the real essence of what your app is about. By following that principle I have gotten lucky with changes time and time again. So I think that's a good principle to follow.
Martin Fowler

Software Engineering Great Quotes
Maxi Contieri ・ Dec 28 '20
This article is part of the CodeSmell Series.
Top comments (1)
Is it okay to use <input> constraints?