[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: best practices for using XSLT modes

Subject: Re: best practices for using XSLT modes
From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 5 Dec 2019 18:05:07 -0000
Re:  best practices for using XSLT modes
It is well-known that code inside a conditional operator *increases *the
cyclomatic complexity.

Thus we see many sources that recommend to avoid or refactor conditional
statements -- in many different languages.

I believe XSLT is no exception.

Just for example, here is a recommendation how to refactor Javascript code:
https://webuniverse.io/cyclomatic-complexity-refactoring-tips/

and inside it:
       Refactoring a switch-like logic

Here is another example -- the Pluralsight course "Refactoring for C#
Developers"
https://www.pluralsight.com/library/courses/refactoring-csharp-developers/tab
le-of-contents
<https://app.pluralsight.com/library/courses/refactoring-csharp-developers/ta
ble-of-contents>
.
In the expanded table of contents, under "Code Smells"  we see:

   Smell: Switch Statements

In the "method Code Smells module we see:

  Smell: Conditional complexity


I saw a phrase on a candy cover: "The magic is in the mess" ...

Let us not create "magic" code, please

Cheers,
Dimitre




On Thu, Dec 5, 2019 at 8:34 AM John Lumley john@xxxxxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> On 05/12/2019 14:51, Eliot Kimber ekimber@xxxxxxxxxxxx wrote:
>
> Not really about modes, but I would replace the choice that acts on
different @val values with templates applied to the @val attribute, i.e.:
>
>         <xsl:template match="a">
>           <val><xsl:apply-templates select="@val"/></val>
>        </xsl:template>
>
>      <xsl:template match="@val[. ge 0]">
>         <xsl:value-of select="@val || ': positive'"/>
>     </xsl:template>
>
>      <xsl:template match="@val[. lt  0]">
>         <xsl:value-of select="@val || ': negative"/>
>     </xsl:template>
>
> Note that I handle the bug in the original in that it would produce no
result when @val is "0" (zero).
>
> The use of templates rather than xsl:choose makes the code cleaner, I think,
puts the focus at the template level on the @val attribute, which is the focus
of the business logic, and enables extension and override. For example, if you
want a value of exactly zero to have a different result, you could do that by
adding an override template. The original use of xsl:choose would require
overriding the entire template for the <a> element.
>
> I'm of a different opinion, somewhat in line with some remarks Mike made
> earlier. (Note that this topic can sometimes get a little 'heated' in a
> gentle XSLT manner.)
>
> The design issues in part depend on the 'scope' and 'size' of the
> operation you're invoking and the likelihood that you'll need to 'add
> additional semantics' at a later date or by overriding with 'library'
> importation. Lets look at a slight rewriting of the 'choose' method in
> XSLT3:
>
> <xsl:template match="a" expand-text="true">
>       <val>
>         <xsl:choose>
>         <xsl:when test="@val ge 0">{@val}: positive</xsl:when>
>         <xsl:when test="@val lt 0">{@val}: negative</xsl:when>
>       </xsl:choose>
>     </val>
> </xsl:template>
>
> (Yes it could be terser or it could be conditional XPath, but bear with
> me.) The point of the choose over the template is that the *entirety *of
> the operation choice semantics (identifying the signum of a/@val) is
> contained in a single place, in fact inside a single XML element, and won't
> be effected by any other additional code *outside* this segment. You're
> pretty safe in the knowledge that if something's going wrong (e.g. the zero
> case Eliot pointed out and another possible fault described later), then
> the fault should *only be within this code section, *nowhere else. And
> choose also has a totally defined order of checking - each when is tested
> in turn, so you can control accurately the sequence of checks.
>
> If that is what you wanted (contained scope), then if you used templates,
> even moded ones, an additional matching template, almost anywhere else in
> your stylesheets, might confound your nice solution. For example:
>
> <xsl:template match="a/@val[. mod 2 eq 0]" <a/@val[.mod2eq0]>
> priority="2">{@val}: even</xsl:template>
>
> would alter the result. And similarly the 'default priority order' between
> template rules is sometimes not as straightforward as it seems. Believe me,
> with large stylesheets spread over many files it's extremely easy to find
> that an errant template somewhere in the back of beyond is trumping the
> code sections you're tearing your hair out debugging. And with stylesheet
> importation this becomes even more prevalent as importation precedence wins
> out over priority every time. This means that for example if your
> stylesheet was imported into another, which contained:
>
> <xsl:template match="a/@val[. eq 0]" <a/@val[.eq0]>><zero/></xsl:template>
>
> then your design will have been 'broken' (perhaps unintentionally) by
> someone else - the designer of the importing stylesheet. (Currently there
> are no mechanisms, outside use of packages, to make templates local, even
> as children of a mode, so all are effectively global in scope.)
>
> But if you do expect to have a large and variable set of conditions that
> in different cases will supercede each other, such as for example in the
> design of DITA-OT, then templates are certainly the way. And if you're
> using next-match to pre/post-process special cases, then you will need to
> use templates.
>
> Note that in this particular example lurks a perhaps more insidious design
> issue for which a choose may have advantage. What if a/@val="abc", assuming
> no schema-awareness checking for integer values. With choose an error would
> be thrown during evaluation of the first when/@test ('abc' cannot be cast
> to an integer); in the template case nothing would happen - errors in
> patterns mean 'no match' and the usual default behaviour for @* is never
> matching: hence the result would be just <val/> and you might be left
> scratching your head.
>
> For me the choices really come down to:
>
>    - How local is this operation? How many separable sections? How large
>    are they?
>    - Are some parts likely to be used from another section of the program?
>    - Do I expect to modify it, or update it, or override it?
>
> etc... For some (most?) templates are the answer, for others choose wins
> out. The most interesting are of course a toss-up!
>
>
>
> --
> *John Lumley* MA PhD CEng FIEE
> john@xxxxxxxxxxxx
> on behalf of Saxonica Ltd
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/782854> (by
> email <>)

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.