DEV Community

Cover image for Code Smell 139 - Business Code in the User Interface
Maxi Contieri
Maxi Contieri

Posted on • Originally published at maximilianocontieri.com

Code Smell 139 - Business Code in the User Interface

Code Smell 139 - Business Code in the User Interface

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

  • Bijection Violation

Solutions

  1. 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> 
Enter fullscreen mode Exit fullscreen mode

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> 
Enter fullscreen mode Exit fullscreen mode

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

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


This article is part of the CodeSmell Series.

Top comments (1)

Collapse
 
yoursunny profile image
Junxiao Shi

Is it okay to use <input> constraints?

<input type="number" min="1" max="9"> 
Enter fullscreen mode Exit fullscreen mode