4.2.5.3.4   if..then..else Ausdrücke

In nicht-funktionalen Programmiersprachen sind die Schlüsselwörter if und then dazu da, um dem Compiler oder Interpreter mitzuteilen, dass eine bedingte Anweisung ausgewertet werden soll.
Was für den Nicht-funktionalen Programmierer etwas befremdlich erscheint, ist der Umstand, dass in XQuery if..then als Ausdrücke ausgewertet werden.
Das ist einerseits sehr praktisch, weil es richtig angewandt den Code verkürzt und damit das Wesentliche herausstellt, kann aber auch weiter zur allg. Verwirrung bzgl. des kryptischen XQuery Codes beitragen.

4.2.5.3.4.1  Beispiel: Konditionale Server App

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
};
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,'!"}')))
Als prozeduraler Programmierer wäre ich mit diesem Switch voll und ganz zufrieden, der funktionale Programmier erkennt abaer 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,'!"}')
)
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,'!"}')
)
Sicherlich lässt sich darüber streiten, ob nun der funktionale Ansatz besser lesbar ist, als der prozedurale oben.
Ich denke jeder Programmierer hat hier seinen eigenen, individuellen und bewährten Programmierstil entwickelt, den er auch beibehalten sollte.
Previous Page Next Page
Version: 93
Jan 25 2021