Betrachten wir ein einfaches Beispiel: Wir generieren auf einer Marklogic-Webapp eine JSON Response. Da wir diesen Mechanismus an mehreren Stellen im Code einsetzen, empfiehlt es sich das Rendern des Headers in eine Funktion auszulagern.
declare function common:wrap-response($json) { xdmp:add-response-header("Pragma", "no-cache"), xdmp:add-response-header("Cache-Control", "no-cache"), xdmp:add-response-header("Expires", "0"), xdmp:set-response-content-type('text/json; charset=utf-8'), $json };Plain Text
In unserem Request-Handler wird je nach Auswertung einer Variablen eine bedingte Anweisung ausgeführt, diese sieht bspw. so aus:
let $name := xdmp:get-request-field('name'), $is-afternoon := xs:time(current-dateTime()) gt xs:time('12:00:00') return if ($is-afternoon) then common:wrap-response(xdmp:unquote(concat('{"greeting":"Good Afternoon! ',$name,'!"}'))) else common:wrap-response(xdmp:unquote(concat('{"greeting":"Good Morning! ',$name,'!"}')))Plain Text
Als prozeduraler Programmierer wäre ich mit diesem Switch voll und ganz zufrieden, der funktionale Programmierer erkennt aber sofort einen Optimierungsbedarf.
Da es sich bei der bedingten Anweisung auch um einen Ausdruck handelt, der true oder false zurückgibt, können wir die gleichen Funktionsaufrufe herausziehen:
ommon:wrap-response(xdmp:unquote( let $is-afternoon := xs:time(current-dateTime()) gt xs:time('12:00:00') return if ($is-afternoon) then concat('{"greeting":"Good Afternoon! ',$name,'!"}') else concat('{"greeting":"Good Morning! ',$name,'!"}') )Plain Text
Hier wird der abstrakt denkende Programmierer aber einwenden, dass eine abstrakte Logik nicht in eine Low-Level Funktion, wie xdmp:unquote gewrapped werden sollte.
Das stimmt - und mehr noch, die Maskierung mit xdmp:unquote sollte auch noch in unsere Funktion gepackt werden. So dass der Code schliesslich so aussehen würde:
declare function common:render-response($json) { xdmp:add-response-header("Pragma", "no-cache"), xdmp:add-response-header("Cache-Control", "no-cache"), xdmp:add-response-header("Expires", "0"), xdmp:set-response-content-type('text/json; charset=utf-8'), xdmp:unquote($json) }; common:render-response( let $is-afternoon := xs:time(current-dateTime()) gt xs:time('12:00:00') return if ($is-afternoon) then concat('{"greeting":"Good Afternoon! ',$name,'!"}') else concat('{"greeting":"Good Morning! ',$name,'!"}') )Plain Text
Sicherlich lässt sich darüber streiten, ob nun der funktionale Ansatz besser lesbar ist, oder der prozedurale von oben.
Ich denke jeder Programmierer hat hier seinen eigenen, individuellen und bewährten Programmierstil entwickelt, den er auch beibehalten sollte.