Code gets read more often than it gets written, so how it gets laid out on the screen is a critical component of maintainability. When a project involves more than one person checking in code, it gets even more important.
So, here’s a peek inside the MarkLogic Engineering team’s process — our set of agreed-upon guidelines for formatting XQuery code. It’s arranged in a laws-of-robotics sequence with the cardinal rule first. Following rules fill out the details, but can’t override the earlier rules.
It’s my hope that this is a useful resource for XQuery programmers everywhere. The intent of this guide is to provide a few key rules for sensible application, rather than exhaustive enumeration.
Rule 0
Thou shalt not mix tabs and spaces. The entire project must exclusively use spaces (four) for indentation, except for third party libraries (e.g. XSLTforms, YUI).
Rule 1
Structure function signatures using the following example:
declare function my:function( $a as xs:string, $b as element(my:options) ) as empty-sequence() { (: body of function :) };
Rule 2
Use common sense and make code readable on the screen unless it would conflict with rule 0 or 1.
Rule 3
If editing existing code, adopt a style to fit in with what’s already there, unless it would conflict with rules 0, 1 or 2.
Rule 4
If/Then/Else or For/Let/Where/Order by/Return statements should either fit on a single line, or else have the aforementioned keywords left aligned, unless it would conflict with rules 0, 1, 2 or 3.
Examples:
(: one line if/then/else :) if ($condition) then $action else ()
(: multiple line if/then/else :) if ($condition) then xdmp:log("If we kept this on one line, it would be unreadable") else xdmp:log("This is a very long action, don't want it to scroll")
(: chained if/then/else :) if ($condition) then xdmp:log("If we kept this on one line, it would be unreadable") else if ($condition2) then xdmp:log("This is a very long action, don't want it to scroll") else for $i in (1,2,3) return concat("line ",$i)
(: flwor :) let $a := "alpha" for $i in (1 to 50) where $i mod 2 eq 1 return concat($a,$i)
(: flwor :) let $a := "alpha" for $i in (1 to 50) let $x := $i mod 2 where $x eq 1 return concat($a,$i)
(: flowr with subordinate flwor :) let $a := "alpha" let $x := for $i in (1 to 50) where $i mod 2 eq 1 return concat($a,$i) return $x
Rule 5
Use a consistent amount of indentation as the rest of the project (four spaces), unless it would conflict with rules 0, 1, 2, 3 or 4.
Rule 6
Use sparing comments to indicate the intent of blocks of code; if the project uses XQDoc-style comments, do this also, unless it would conflict with rules 0, 1, 2, 3, 4 or 5.
Rule 7
Use short, but meaningful, variable and function names. Use a default prefix instead of fn: and always use a prefix for defined functions, unless it would conflict with rules 0, 1, 2, 3, 4, 5 or 6.