    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Scenarios Using Custom DSLs</title>
        <link>https://members.accu.org/index.php/journals/2705</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">Overload Journal #153 - October 2019 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c403/">o153</a>
                    (6)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c403-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c403+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Scenarios Using Custom DSLs</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 05 October 2019 22:05:39 +01:00 or Sat, 05 October 2019 22:05:39 +01:00</p>
<p><strong>Summary:</strong>&nbsp;Natural-language BDD can be hard to maintain. Liz Keogh demonstrates a simple code-based alternative.</p>
<p><strong>Body:</strong>&nbsp;<p>One of my clients recently asked me how often I use Cucumber or JBehave in my own projects. Hardly ever, is the answer, so I want to show you what I do instead.</p>

<p>The English-language Gherkin syntax is hard to refactor. The tools form another layer of abstraction and maintenance on top of your usual code. Thereâ€™s a learning curve that comes with them that can be a bit tricky. The only reason to use the tools is because you want to collaborate with non-technical stakeholders. If nobody outside your team is reading your scenarios after automation, then you donâ€™t need them.</p>

<p>There may still be other reasons you <em>want</em> the tools. Theyâ€™ll be more readable than the code Iâ€™m about to show you. Dynamic languages are harder to refactor anyway; I work primarily with static typing. Maybe you want to take advantage of hooks for your build pipeline. Maybe you already know and feel comfortable with the tools. Maybe you just really want to learn the technique. Thatâ€™s OK. But you donâ€™t need them.</p>

<p>So hereâ€™s a simple alternative.</p>

<h2>Have some conversations, and write down the examples</h2>

<p>I like it when the developers do this, and get feedback on their understanding. Writing it in semi-formal Gherkin syntax is pretty useful for helping spot missing contexts and outcomes. All the usual goodness of Three Amigos conversations still applies.</p>

<h2>Find a capability, and the thing that implements it</h2>

<p>Your application or system probably has a number of things that it enables people or other systems to do. Weâ€™re going to be using a noun that matches those things as a way of starting our DSL. Here are some examples:</p>

<ul>
	<li>Buying things &#8594; the basket</li>
	<li>Making trades &#8594; a trade</li>
	<li>Commenting on an article &#8594; a comment / the comments</li>
	<li>Doing banking &#8594; the account</li>
</ul>

<p>You may find the language is a bit stilted here (I did say the English was clearer!) but thatâ€™s a trade-off for the ease of getting started with this. You might find other things which make more sense to you; itâ€™s sometimes possible to use verbs for instance.</p>

<ul>
	<li>Searching for a car &#8594; I search</li>
</ul>

<p>Youâ€™ll get the idea in a moment. Each of these is going to be the stem of a bit of code.</p>

<h2>Start with comments in the code</h2>

<p>Sometimes I like to just start with my scenario written in comments in the code. For each step, think about whether the step has already happened, is the thing that triggers some interesting behaviour, or is the outcome of that behaviour. Add Given, When or Then as appropriate:</p>

<pre class="programlisting">
  // Given an article on Climate Change
  // When I post a comment &quot;This is a really
  // conservative forecast.&quot;
  // Then it should appear beneath the article.</pre>

<h3>Add the Given, When or Then to your stem, andâ€¦</h3>

<ul>
	<li>Given the basketâ€¦</li>
	<li>When the tradeâ€¦</li>
	<li>When a commentâ€¦</li>
	<li>When a searchâ€¦</li>
	<li>Then the accountâ€¦</li>
</ul>

<h3>â€¦construct your steps!</h3>

<p>Now weâ€™re in code.</p>

<pre class="programlisting">
  GivenAnArticle().on(&quot;Climate Change&quot;)

  GivenTheBasket().contains(&quot;Pack of Grey Towels&quot;)

  WhenTheTrade().isCreated()
    .withCounterparty(&quot;Evil Corp&quot;)
    .forPrice(150.35, &quot;USD&quot;)
    .....
    .andSubmitted()

  WhenISearch().For(&quot;Blue Ford Fiesta&quot;)

  ThenTheAccount().shouldHaveBalance(15.00, &quot;GBP&quot;)</pre>
  
<p>You can see that trading one is using a builder pattern; each step returns the trade being constructed for further changes, until itâ€™s submitted. I sometimes like to use boring, valid defaults in my builder so that these steps only call out the really interesting bits.</p>

<p>I normally suggest that a â€˜Whenâ€™ should be in active voice; that is, it should show who did it. If thatâ€™s important, add the actor.</p>

<pre class="programlisting">
  WhenTheTrade().isCreated()
    .....
    .andSubmittedBy(&quot;Andy Admin&quot;)</pre>
	
<p>or</p>

<pre class="programlisting">
  WhenTheTrade().isCreated()
    .by(&quot;Andy Admin&quot;)
    .....
    .andSubmitted()</pre>
	
<p>Active voice would normally look more like:</p>

<pre class="programlisting">
  When(&quot;Andy Admin&quot;).createsATrade()
    ....
    .andSubmitsIt()</pre>
	
<p>But now our â€˜Whenâ€™ is ambiguous; we canâ€™t tell which kind of capability weâ€™re about to use, so it makes it really, really hard to maintain. Itâ€™s OK to use passive voice for DSLs.</p>

<p>As I construct these, I delete the comments.</p>

<p>Sometimes I like to just put all the detailed automation in which makes the steps run, then remove the duplication by refactoring into these steps. (Sometimes itâ€™s enough just to just leave it with detailed automation, too, but at least leave the comments in!)</p>

<h3>Pass the steps through to Page Objects; use the World for state</h3>

<p>Youâ€™ll probably find you need to share state between the different steps. I normally create a â€˜Worldâ€™ object, accessible from the whole scenario.</p>

<p>Each of the stems you created will correspond to one or more page objects. I like to keep those separate, so my steps in the DSL donâ€™t do anything more than just call through to that object and return it.</p>

<p>Listing 1 is an example of my scenario object for a Sudoku solver.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
public class Scenario
{
  private readonly SudoqueSteps _sudoqueSteps;
  private readonly CellSteps _cellSteps;
  private readonly HelpSteps _helpSteps;

  private World _world;

  protected Scenario()
  {
    _world = new World();
    _sudoqueSteps = new SudoqueSteps(_world);
    _cellSteps = new CellSteps(_world);
    _helpSteps = new HelpSteps(_world);
  }
  
  protected CellSteps WhenISelectACell{ get 
  { return _cellSteps; }}
  
  protected CellSteps ThenTheCell{ get 
  { return _cellSteps; }}

  protected SudoqueSteps GivenSudoque{ get 
  { return _sudoqueSteps; }}
  
  //...

  protected HelpSteps WhenIAskForHelp { get 
  { return _helpSteps; } }

  protected HelpSteps ThenTheHintText { get 
  { return _helpSteps; } }
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<p>It does get quite long, but itâ€™s pretty easy to maintain because it doesnâ€™t do anything else; all the complexity is in those underlying steps.</p>

<p>And Listing 2 shows how I use it.</p> 

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
[TestFixture]
public class PlayerCanSetUpAPuzzle : Scenario
{
  [Test]
  public void APlayerCanSetUpAPuzzle()
  {
    GivenSudoque.IsRunning();
    WhenISelectACell.At(3, 4).AndToggle(1);
    ThenSudoque.ShouldLookLike(
      &quot;... ... ...&quot; + NL +
      &quot;... ... ...&quot; + NL +
      &quot;... ... ...&quot; + NL +
      &quot;           &quot; + NL +
      &quot;... ... ...&quot; + NL +
      &quot;.1. ... ...&quot; + NL +
      &quot;... ... ...&quot; + NL +
      &quot;           &quot; + NL +
      &quot;... ... ...&quot; + NL +
      &quot;... ... ...&quot; + NL +
      &quot;... ... ...&quot; + NL);
  }
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<p>Full scenarios are available at <a href="https://github.com/lunivore/sudoque/tree/master/Sudoque.Scenarios">https://github.com/lunivore/sudoque/tree/master/Sudoque.Scenarios</a>.</p>

<p>This one was written in plain old NUnit with C#. Iâ€™ve done this with JUnit and Java, and with JUnit and Kotlin. The examples here are only from toy projects, but Iâ€™ve used this technique on several real ones.</p>

<p>There are lots of tools out there which help you to construct these kind of DSLs; but Iâ€™ve found they also come with their own learning curve, constraints, maintainability issues etc.. This is a pretty easy thing to do; I donâ€™t think it needs anything more complicated than Iâ€™ve put here.</p>

<p>Itâ€™s also very easy to refactor overly-detailed, imperative scenarios, of the kind created by lots of teams who didnâ€™t know about the conversations, into this form.</p>

<h3>Itâ€™s easy to move to the BDD tools if you need them</h3>

<p>With your Page Objects already in place, itâ€™s pretty quick to get something like Cucumber up and running and make the step definitions call through to the page objects exactly as you were before, with just a little bit of refactoring of method names.</p>

<p>Itâ€™s a lot harder to move from Cucumber and regex to a DSL.</p>

<p>Chris Matts once had some great wisdom. â€œIf you donâ€™t know which technology to choose, pick the one thatâ€™s easy to change. If itâ€™s wrong, you can change it.â€</p>

<p>This is the one thatâ€™s easy to change, so I tend to start with this. And sometimes it doesnâ€™t need to change.</p>

<p class="EditorIntro">This article was first published on Liz Keoghâ€™s blog:
<a href="https://lizkeogh.com/2019/08/27/scenarios-using-custom-dsls/">https://lizkeogh.com/2019/08/27/scenarios-using-custom-dsls/</a>.</p>

<p class="bio"><span class="author"><b>Liz Keogh</b></span> is a Lean and Agile consultant based in London. She is a well-known blogger and international speaker, a core member of the BDD community and a passionate advocate of the Cynefin framework and its ability to change mindsets. She has a strong technical background with 20 yearsâ€™ experience in delivering value and coaching others to deliver, from small start-ups to global enterprises. Most of her work now focuses on Lean, Agile and organizational transformations, and the use of transparency, positive language, well-formed outcomes and safe-to-fail experiments in making change innovative, easy and fun.</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
