Showing posts with label html. Show all posts
Showing posts with label html. Show all posts

Monday

You don't know what a controller is for, do you?

This is my second post in what I'm going to call the "You deserve verbal abuse because your code is dumb" series. These are things that frustrate me greatly, like creating spaghetti code because you don't understand CSS. (In fairness, my solution may not be obvious, but there is no excuse for highly fragmented spaghetti code in the view layer; someone should have come up with something better).

Last time I talked about how you can use CSS to get rid of most of that if/else logic you have in your page templates. Today, I'm going to explain controllers to you. That's the C in MVC. You should know this stuff. The controller is the thing that receives the HTTP request and decides what to do with it. Most frameworks will map URLs to different controller classes and methods. The controller is responsible for picking the view to render and loading the right data based on the request (and maybe the URL).

Most of you seem to think that it ends there, and that it's OK to take whatever convulted data structure your service layer spits out and pass that right on to the view. Lean in really close so I can hit you. No! Bad developer! The whole reason that we moved away from CGI/Servlets is because mixing the processing code and the view markup is a bad idea. Unfortunately, you Philistines didn't get it, so you invented crap like Struts that just puts a layer of abstraction around HTML code and then get yourselves back into the same mess.

This is what your templates look like:
<div id="${result.product.productInfo.productId.toString()}">
<h4> ${result.product.productInfo.productName.getLocalizedString(request.client.language)} </h4>
etc....
and here is how they should look:
<div id="${productId}">
<h4> ${productName} </h4>
etc....
The controller is responsible for getting and creating a model that makes sense for the view. Even the most technically averse designer can look at a view with a smart controller and figure out what's going on and how to edit it. It's when the expressions start to get long and the if/else logic creeps in that they start to get confused and scared. So, have pity on the designers, keep the logic in the controller. If you're careful, maybe someday the designers can get in there and actually change the templates themselves, instead of having to file a bug report for every single HTML change. Wouldn't that be nice?

Tuesday

Whadya know, this semantic markup crap is actually useful

why you should use a rules engine

The UI of a web application generally consumes 60-90% of the development effort. UIs are complex, and they're big. All the cross cuttng concerns of the application combine in the UI to give you as many versions as there are variables. For many sites that means there can be hundreds of unique ways for a page to be rendered. As a consultant, I see a lot of you writing templates that look like this:
<div id="product">
<c:if test="${hasErrors}">
<div class="errors">
Bid must be a number
</div>
</c:if>
<c:if test="${forSale}">
<input class="buyButton" value="Buy!" type="button">
</c:if>
<c:else>
<span id="saleMessage">Sorry, not for sale.</span>
</c:else>
<c:if test="${isAdmin}">
<input value="Delete" class="deleteButton" type="button">
</c:if>
</div>
You get tag/conditional soup, because the there are a bunch of different states that the page could be in, and you have to show/hide lots of things, or give things different colors, or whatever based on whatever state the page is in. Or maybe you list several things on a page, and some of them will be in different states than others. Or you have some button that the user isn't allowed to click because they don't have the right role.

If you have tag soup, you're doing it wrong. All of the things I described above are state, or semantically useful information. With the exception of hiding information from those who are not allowed to see it, there is absolutely no reason not to render just about everything and use CSS rules to hide and otherwise transform the page based on the current situation. Here's an example:
<div id="product" class="user${userRole} ${forSale ? '' : 'notForSale'} ${hasErrors ? 'error' : ''}">
<div class="errors">
Bid must be a number
</div>
<input class="buyButton" value="Buy!" type="button">
<span id="saleMessage">Sorry, not for sale.</span>
<input value="Delete" class="deleteButton" type="button">
</div>
And you have CSS rules like so:
.errors, .deleteButton, .notForSale .buyButton, #saleMessage { display: none; }
.error .errors { display: block; }
.notForSale #saleMessage { display: inline; }
You can't tell me that isn't simpler. It's easier to read too. All those business rules that you have translate nicely to CSS rules. Imagine that, rules begin easily represented as rules. This approach combines nicely with Ajax as well. Receive an update from the server and suddenly the item is for sale? $('#product').removeClass('notForSale'); and the browser takes care of the rest.

You might tell your self such an approach would never fly, what about security? Anyone could look at the source and see the delete button, or use Firebug to show it, then suddenly they're deleting things! Hopefully you understand the problem with that argument, but for the naive: if you're not checking permissions and validating data on the server, you're wide open to all kinds of attacks. Your rendered HTML is just the preferred interface. The real interface to your application is HTTP, and an attacker will quickly figure out what a real delete request looks like, so unless you're also checking credentials, you're screwed.

The exception, as I said before, is information that needs to stay secret. You shouldn't render some element with user passwords and hide it with CSS. Don't do it with trade secrets, launch codes or your secret pictures of yourself dressed as a drag queen either. For anything else, take advantage of one of those things about semantic markup that actually works well, and make your life simpler.

Next time: You obviously don't understand what a controller is for.

But first: Writing one liners; for readability.