Coding Standards for Front-end templates
Author: Michiel Meeuwissen
Date: 2007-10-19
This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative.
The license (Mozilla version 1.0) can be read at the MMBase site. See http://www.mmbase.org/license
I'm working with MMBase for 6 or 7 years now or so, and during that time I did encounter
lots of JSP code. Much of it was incredibly ugly, and hard to maintain.
The first, and most important, rule of these code conventions is, that everybody who is
responsible for JSP-coding, must realize that JSP is code. Everything
which is considered bad practice in other code, should be considered bad practice in JSP
too. I mention e.g. code-duplication, sloppy, errorneous or even no indentation, very wide
variable scoping, huge blocks of code etc.
But besides that, I can propose some clear guidelines, for JSP's in an MMBase
web-site. This is about JSP's which in principle are implemented using the MMBase taglib. I
don't like JSP's contains only java, but those are out of the scope of this document.
-
Use clean (X)HTML. I do realise that the HTML is often produced by someone else. But
nevertheless it's my opinion that HTML is code too, and should be
subject to code conventions as well. Generally there should be a good ratio between
quantity of HTML and of taglib tags. E.g. 1 in every 5 tags is an HTML tag. If you have
much more, then probably your HTML is too noisy, and you should do more in the CSS, if you
have much less, then probably you're stuffing too much functionality in the JSP, and you
should consider moving it too java code or a tag file.
Use only taglib(s). Though the possibility exists to fall back to Java, this is usually a
bad idea. Alternatively the desired functionality could be implemented in a tag-file or
some actual java class (e.g. as an MMBase 'function'). This makes this code better
reusable, and reduces noise in the JSP.
This is no dogma though. If you're going to stick hundreds of lines of taglib in your jsp
to replace a piece of Java, then you can better just use java. You should start to wonder
if the functionality should be implemented in the JSP at all though.
-
Besides MMBase taglib don't hesitate to use the JSTL tag libraries, and EL. Prefer
mm:include over jsp:include, mm:import over c:set, but c:choose over mm:compare.
-
Be reluctant to introduce other external tag libraries. Some libraries provide very little
extra functionality which is not already provided by MMBase taglib and/or JSTL. Check
first if a dependency on a similar tag library was already introduced, before adding yet
another one. Sometimes the gain is not worth the extra dependency and complexity. Don't be
too reluctant though, if you really need it, use it.
-
Avoid switches. If you make a switch, use c:choose, so that it immediately visible that
this is a switch. Don't use mm:compare's to collect a lot of
unrelated funcationality in one file. Use more, smaller, files.
-
Prefer JSPx. JSP is more convenient if you use a lot of java in the JSP, but you should
not do that any way. JSP can occasionaly be a good idea for tag files, because for those
it is more acceptable to contain java code. Consider producing (valid) XHTML. JSPX is XML,
so you can use any XML editor, which will make it easier to format the code in a readable
way. Consider using mm:content type="application/xml+xhtml", at least during development,
so that you spot invalid XML early. Use a decent browser. You can leave it even in
production enviroments with th attribute 'unacceptable="CRIPPLE"', which will cause the
content type to fall back 'text/html', in case it is sent to certain browsers which report not beining able to
handle xml. Most noticeably Internet Explorer.
-
Smaller jsp files are better. Generally the entire jsp file should fit in one or two
screens of your favourite editor. A JSP should actually do something,
so too small is no good either.
-
Indentation of JSP is like an XML. I.e. 2 spaces.
-
Use a new line for every tag and close tag. Sometimes it can be acceptable to add the
close tag on the same line as its opening tag. Especially when the body is very small, or
contains only CDATA.
-
Don't overdo it. Though MMBase taglib together with JSTL is pretty powerful, this does
not mean that you should implement the complete logic of your site with it.
-
Don't underdo it either. Simple and straightforward functionality can be done in
taglib. HTML is about representing the structure of content any way, so mirroring some of
the functionality used to back this structure in the JSP is ok, and can make things easier
to understand. If you have trouble finding back such functionality amongst myriad of HTML
tags and attributes then your HTML is probably not clean enough. Get the graphical
designer sacked.
The previous two points can perhaps be summarized with that you must be 'declarative' and
not 'implementative' in your JSP. Simple statements like 'list all posrel related images,
order on the pos' are ok but please don't program something complex like 'list all related
images, related to the current node, unless those are none, then use a set of default
images, unless the current node has a related 'imagecontainer' then use the images related
to that node, unless, that too is an empty set'. Your JSP will pretty soon become a
horrible, unmaintainable mess then.
In such a case, please add a function 'images' to the builder of the current node, or
create a tag file mytags:images or so, in which case you can still use taglib to implement
if you prefer that over java code.
You can also go for fully fledged MVC in some other way, of course but that may lead in
an 'underdo' of in-page functionality, because it is not immediately visible any more what
more or less is happening.
-
Avoid mm:import. The goal of mm:import is to 'import' variables from some
external. Generally it should be used as a way to take parameters from the URL or
request. That you can also use it to create and fill new variables on the fly does not
mean you should use it all over the place. Often it is nicer to use an 'id' on an mmbase
tag, or to use an implicit EL variable like '_' or '_node'.
-
Use mm:import 'required' attribute as much as possible. If a parameter is essential for
the correct working of a page, it is good idea to mark it as required, so that you don't
have to decypher a cryptic error message, and you can immediately see in the code
that this parameter is required.
-
Use mm:import's 'reset' attribute as sparingly as possible. We want to be declarative, not
implementative. See also XSL.
-
Use 'notfound' attributes as little as possible. Don't take the habit of adding all over
the place 'notfound="skip"' to any node tag which you may find. If you use it, consider
adding comments which explain why it is not an errorneous situation if the node is for
some reason not found or not available. Perhaps go all the way, and state that reason. A
'notfound' attribute on something which is expected to always be found, only obfuscates
the code of the page.
-
Prefer dynamic includes (mm:include) over static includes (jsp:directive.include). Dynamic
includes don't pollute the scope of their parent. Small scopes are good.
-
If the dynamic includes needs parameters, consider making it a tag file in stead.
-
If a jsp is to be used as a static include, it should have no more then 15
lines.
-
Avoid (future) hacking. If you encounter a limitation or bug in the the mmbase taglib, or
mmbase itself, please take the trouble to report it, before or after
you're going to hack your way around it. It may just be possible that the issue gets
fixed, and next time you, or somebody else can do a similar thing without hacking.