People don’t get the difference between business and UI logic

People most of the time use business logic in their templates, be them JSP, Velocity or Rails. They confuse business logic and UI logic. Those are two different things. I always found it very useful to make UI logic explicit and only have UI logic in my JSPs or templates. So when using IF JSTL tags only test for UI logic not business logic. The examples are for JSP, but nevertheless are valid for other templating engines like Rails or Velocity. Where is the difference between UI and business logic?

<c:if test="${showMenu}">
// show menu


<c:if test="${user.loggedIn && user.bookedProducts}">
// show menu

The first example contains only UI logic, the second one contains business logic and should be avoided. With the second version your templating code is depending on your business layer. This makes it hard to refactor or reuse. Somewhere in the controller or an adapter it's best to translate your business logic to UI logic

 boolean showMenu = user.loggedIn() && user.bookedProducts();

Such a separation makes refactoring and reuse easier and encapsulates the rules how business logic maps to UI logic in one place. You could even write the mapper with rule engines. It also eases the understanding of the template code. Often when using business logic in their templates, people use copy & paste to reuse the logic. So the user.loggedIn code gets distributed over lots of templates. If the logic changes so the menu should only be show for paid users, you need to modify all templates where the logic is used.

<c:if test="${user.loggedIn && user.bookedProducts && user.hasPaid}">

(I know about components, sub-templates etc. but people nevertheless use cut & paste for reuse. So make sure they cut&paste the right things)

When externalizing business-to-UI logic into seperate classes, it's also much easier to test.

public class UserUIState {
 private User user;
 public UserUIState(User user) {
    this.user = user;
 public boolean showMenu() {
   return user.loggedIn() && user.bookedProducts();

can be easily tested from a Unit test.

  User user = with().isLoggedIn().addProduct("Intellij IDEA").create();
  UserUIState state = new UserUIState(user);
  assertThat( state.showMenu(), is(true));

The test uses fluent interfaces to create a user and a pseudo Hamcrest DSL to specify assertions. The assertions would be nicer written as specs with easyb.

Another aspect of templating is the power of the templating engine. Turing completeness is not a good thing for templating as the power introduces bugs. Less power leads to less bugs. Examples for engines who make this a virtue are String Template and RIFE. The same goes for variables. Never set variables in templates. Never modify state in templates. The best paper on this topic is Terence Parrs "Enforcing Strict Model-View Separation in Template Engines".

And of course never use Scriptlets in your JSP or other templating code, the main reason that the developer has to manage two hierarchies in her head. The <html> on one side and the Java { ... } hierarchie on the other.

<% if (loggendIn) { %>
<p>Logged in<p>
<% } %>

With larger pages this leads to bugs. With only one <html> hierarchie, your IDE is able to verify the hierarchie at edit-time which prevents invalid HTML.

You can enfore these rules with code reviews or automatic style and architecture checkers. Probably best to use both to reduce your bug count and enable reusability.

Thanks for listening.

Update: Gavin King got me wrong. Reading simple attributes like "test=${user.loggedIn}" doesn't contain a lot of "logic" so it's no must to encapsulate the logic and it leads to unnecessarilly complex code. YAGNI. But "test=${user.loggedIn && user.hasBookProducts && sales.hasPromotion(user)}" does contain logic which should be encapsulated and tested. Perhaps I'm a stronger believer in TDD than Gavin. I wanted to stress that there is a difference between UI and business logic and a lot of people don't see the difference.