XQuery Coding Guidelines

June 29, 2011 Data Platform

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.

Micah Dubinko