Code Monkeyism

Programming is hard by Stephan Schmidt

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>

and

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

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 sepration 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}">
...
</c:if>

(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.

About the author: Stephan Schmidt is currently a team manager at ImmobilienScout24 in Berlin. Stephan has been working as a head of development and CTO. He has used a lot of different technologies in the last 20 years including Java, Rails and Python. Stephans main field of interest is maintainablity and productivity in software development. Want to know more? All views are only his own.

If you did like this article but you don't want to subscribe to new articles with your reader, you can follow me on Twitter or subscribe to new posts with your email:

Comments

I agree. Originally, I was not convinced that creating the UserUIState is useful. However, upon reflection (no pun intended) I can see that using a state object simplifies the design. Each state variable (showMenu, showFooter, etc) does not need to be placed into the UI context, just the UserUIState object.

stephan

I’m not sure if UserUIState is the right name and I’m not sure the method should be called showMenu, it depends on the code and the project. This was just an example. But it tremendously simplifies Unit testing and template coding. And it leads to much more maintenable code and a lot less bugs (simpleness leads to quality).

The Wicket way is better. There are no doubts of where business logic lives. http://www.systemmobile.com/?page_id=253

stephan

“I know about components, sub-templates etc.”

You’re way doesn’t provide a solution for the distributed nature of the mapping. With your example you still distribute the decision of showMenu over several components possibly.

I could use a JSTL custom tag just like you use a wicket component. But the still: Put the decision of showMenu in the component or put it in an adaption layer. What if you have several widget which should be shown depending on a condition?

With JSP the code is in the c:if, with wicket it’s in here.

isVisible = hasPrice();

public boolean isVisible() {
return hasPrice();
}

But this mapping has to be written down somewhere. That’s my point. Either explicit or implicit. And I vote im most - but the simpliest cases - for explicit.

Stephan,

Agree with you completely.

Thanks
Prashant

raveman

I disagree,

c:if test=”${user.loggedIn && user.bookedProducts && user.hasPaid}”

is easier to change, lets say you want to show something more if user.bookedProducts, in this example is easy and in your version you need to add another business method/field for that.

I think great example of UI logic are reports, for example FOP, you pass xml data to fop and it creates report using XPath. When reports need to be changed, for example you want to count how many products is ordered you just execute XPath query and NOT add another xml field with count result. This way there really is UI logic in your example UI logic is … not existing, you have just business logic.
I also worked with reports on production and using UI logic i was able to change them, in your example that wouldn’t be possible because you need to also change your business logic for that.

I don’t think you should worry about things being reused, but worry about how things might change in time.

stephan

@raveman: Suppose someone asks you (a new developer or a product manager or whoever) what the logic is for displaying a field? Would you rather like to look at UserUIState and tell him (or better show him a readable BDD spec) or search through 1k JSP to find out? I’d rather like to look in one class.

Leave a Reply