<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <generator uri="http://jekyllrb.com" version="3.8.5">Jekyll</generator>
  
  
  <link href="https://igorpopov.io/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://igorpopov.io/" rel="alternate" type="text/html" />
  <updated>2019-10-09T08:25:00+00:00</updated>
  <id>https://igorpopov.io//</id>

  
    <title type="html">Igor Popov</title>
  

  
    <subtitle>Igor's website, a place where he writes about software development.</subtitle>
  

  
    <author>
        <name>Igor Popov</name>
      
      
    </author>
  

  
  
    <entry>
      
      <title type="html">Asynchronous Programming in C#</title>
      
      
      <link href="https://igorpopov.io/2018/06/30/asynchronous-programming-in-csharp/" rel="alternate" type="text/html" title="Asynchronous Programming in C#" />
      
      <published>2018-06-30T00:00:00+00:00</published>
      <updated>2018-06-30T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2018/06/30/asynchronous-programming-in-csharp</id>
      <content type="html" xml:base="https://igorpopov.io/2018/06/30/asynchronous-programming-in-csharp/">&lt;p&gt;Asynchronous programming causes a lot of confusion because the documentation is a bit lacking and this results in awfully bad implementations. This post compiles my research on this subject so you’ll see lots of quotes from various sources (official and trusted third parties).&lt;/p&gt;

&lt;h1 id=&quot;wtf-is-asynchronous-programming&quot;&gt;WTF is asynchronous programming?&lt;/h1&gt;

&lt;p&gt;To clear up the confusion we’re going to see what all the fancy words below actually mean:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;synchronous&lt;/li&gt;
  &lt;li&gt;asynchronous&lt;/li&gt;
  &lt;li&gt;multithreading&lt;/li&gt;
  &lt;li&gt;concurrency&lt;/li&gt;
  &lt;li&gt;parallelism&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;synchronous-vs-asynchronous&quot;&gt;Synchronous vs Asynchronous&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;When you execute something &lt;strong&gt;synchronously&lt;/strong&gt;, you wait for it to finish before moving on to another task. When you execute something &lt;strong&gt;asynchronously&lt;/strong&gt;, you can move on to another task before it finishes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;source:  &lt;a href=&quot;https://stackoverflow.com/questions/748175/asynchronous-vs-synchronous-execution-what-does-it-really-mean&quot;&gt;Stackoverflow&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;multithreading&quot;&gt;Multithreading&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Multithreading&lt;/strong&gt; is the ability of a central processing unit (CPU) or a single core in a multi-core processor to execute multiple processes or threads concurrently, appropriately supported by the operating system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;source: &lt;a href=&quot;https://en.wikipedia.org/wiki/Multithreading_(computer_architecture)&quot;&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;concurrency-vs-parallelism&quot;&gt;Concurrency vs Parallelism&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Concurrency&lt;/strong&gt; is when two or more tasks can start, run, and complete in overlapping time periods. It doesn’t necessarily mean they’ll ever both be running at the same instant. For example, multitasking on a single-core machine.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Parallelism&lt;/strong&gt; is when tasks literally run at the same time, e.g., on a multicore processor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;source: &lt;a href=&quot;https://stackoverflow.com/questions/1050222/what-is-the-difference-between-concurrency-and-parallelism&quot;&gt;Stackoverflow&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;when-to-use-synchronousasynchronous&quot;&gt;When to use synchronous/asynchronous?&lt;/h1&gt;

&lt;p&gt;This post is about asynchronous programming in C# with the Task-based Asynchronous Pattern, so let’s see when and how to use it. There are 2 types of operations that have to be considered: &lt;strong&gt;CPU bound&lt;/strong&gt; and &lt;strong&gt;I/O bound&lt;/strong&gt; when deciding what to use. Here’s what &lt;strong&gt;Stephen Toub&lt;/strong&gt; has to say about this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Both compute-bound and I/O-bound asynchronous operations may be implemented as TAP methods.  However, &lt;em&gt;when exposed publicly from a library&lt;/em&gt;, &lt;strong&gt;TAP implementations should only be provided for workloads that involve I/O-bound operations&lt;/strong&gt; (they may also involve computation, but should not be purely computation).  &lt;strong&gt;If a method is purely compute-bound, it should be exposed only as a synchronous implementation&lt;/strong&gt;; a consumer may then choose whether to wrap an invocation of that synchronous method into a Task for their own purposes of offloading the work to another thread and/or to achieve parallelism.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;At the API level, the way to achieve waiting without blocking is to provide callbacks.&lt;/strong&gt;  For Tasks, this is achieved through methods like &lt;code class=&quot;highlighter-rouge&quot;&gt;ContinueWith&lt;/code&gt;. Language-based asynchrony support hides callbacks by allowing asynchronous operations to be awaited within normal control flow, with compiler-generated code targeting this same API-level support.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;source: the &lt;strong&gt;TAP.docx&lt;/strong&gt; document (check in the resources below)&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;essential information&lt;/strong&gt; is this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;I/O-bound operations?&lt;/strong&gt; - then await asynchronous I/O methods provided by the .NET framework&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CPU bound operations?&lt;/strong&gt; - then expose it as a synchronous/plain implementation, the caller/user of the operation will wrap it in a &lt;code class=&quot;highlighter-rouge&quot;&gt;Task.Run&lt;/code&gt; if needed&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;what-is-cpu-bound&quot;&gt;What is CPU bound?&lt;/h1&gt;

&lt;p&gt;Sometimes concepts are difficult to follow without proper examples. CPU bound or compute bound means that you have a problem to solve/calculate and you &lt;strong&gt;actively need to use the processor to perform the calculation&lt;/strong&gt;. One such example (maybe not the best one, but it illustrates my point exactly) would be calculating the sine of an angle. This is &lt;em&gt;pointless&lt;/em&gt; (we’re not even storing the result), but is a &lt;strong&gt;great example of a CPU bound operation&lt;/strong&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;99999999&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;what-is-io-bound&quot;&gt;What is I/O bound?&lt;/h1&gt;

&lt;p&gt;I/O bound means that you &lt;strong&gt;request the disk to save or load some information&lt;/strong&gt; for example. Another example would be &lt;strong&gt;requesting to download a file from an HTTP server&lt;/strong&gt; like below:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WebClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;DownloadFileTaskAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Downloading is a network operation which requires opening a TCP connection to a server and receiving data through multiple network devices (ex. routers) - this operation takes time. One (wrong) way of doing it is to offload the work to a separate thread, but then this thread will get execution time from the CPU for doing nothing else then &lt;strong&gt;waiting&lt;/strong&gt; for the server to send back a response.&lt;/p&gt;

&lt;p&gt;The right way to do the download would be to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; methods provided by .NET. These are actually wrappers for native code that actually do the work in an async way, meaning sending the request to the server and then suspending the thread until it gets the response back.&lt;/p&gt;

&lt;h1 id=&quot;more-details-about-cpu-bound-and-io-bound&quot;&gt;More details about CPU bound and I/O bound&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;More importantly, because I/O-bound work spends virtually no time on the CPU, dedicating an entire CPU thread to perform barely any useful work would be a poor use of resources.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;The call to &lt;code class=&quot;highlighter-rouge&quot;&gt;GetStringAsync()&lt;/code&gt; calls through lower-level .NET libraries (perhaps calling other &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; methods) until it reaches a P/Invoke interop call into a native networking library. The native library may subsequently call into a System API call (such as &lt;code class=&quot;highlighter-rouge&quot;&gt;write()&lt;/code&gt; to a socket on Linux). A task object will be created at the native/managed boundary, possibly using &lt;code class=&quot;highlighter-rouge&quot;&gt;TaskCompletionSource&lt;/code&gt;. The task object will be passed up through the layers, possibly operated on or directly returned, eventually returned to the initial caller.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;source: &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/async-in-depth&quot;&gt;MSDN: Async in Depth&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A program is &lt;strong&gt;CPU bound if it would go faster if the CPU were faster&lt;/strong&gt;, i.e. it spends the majority of its time simply using the CPU (doing calculations). A program that computes new digits of π will typically be CPU-bound, it’s just crunching numbers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;A program is &lt;strong&gt;I/O bound if it would go faster if the I/O subsystem was faster&lt;/strong&gt;. Which exact I/O system is meant can vary; I typically associate it with disk. A program that looks through a huge file for some data will often be I/O bound, since the bottleneck is then the reading of the data from disk.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;source: &lt;a href=&quot;https://stackoverflow.com/a/868577/354009&quot;&gt;Stackoverflow&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;examples-and-comparison&quot;&gt;Examples and comparison&lt;/h1&gt;

&lt;p&gt;Now we’re going to compare performance and resource usage for I/O and CPU bound operations. For this we’ll use the &lt;strong&gt;Parallel Stacks&lt;/strong&gt; and &lt;strong&gt;Tasks&lt;/strong&gt; windows from &lt;code class=&quot;highlighter-rouge&quot;&gt;Visual Studio -&amp;gt; Debug -&amp;gt; Windows -&amp;gt; Parallel Stacks&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Tasks&lt;/code&gt;. These windows show something only when the application is in debug mode and in &lt;code class=&quot;highlighter-rouge&quot;&gt;Break All&lt;/code&gt; state.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/MGUeS1D.png&quot; alt=&quot;Parallel Stacks and Tasks Windows&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For more info on how to use the Parallel Stacks feature please check the &lt;a href=&quot;https://docs.microsoft.com/en-us/visualstudio/debugger/walkthrough-debugging-a-parallel-application&quot;&gt;Official MSDN Walkthrough: Debugging a Parallel Application in Visual Studio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: all the examples below are done on a single machine and in the same conditions. If you do them you’ll get &lt;strong&gt;different numbers&lt;/strong&gt; but you should have the &lt;strong&gt;same relative performance and resource usage&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-bad-use-of-async-io&quot;&gt;The bad use of &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; I/O&lt;/h2&gt;

&lt;p&gt;The implementation below is &lt;em&gt;stupid&lt;/em&gt;! &lt;strong&gt;NEVER DO THIS!!!&lt;/strong&gt; I did it just to show you what actually happens when you do it and to demonstrate that it’s an extremely bad way of achieving what you want.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://apod.nasa.gov/apod/image/1806/IMG_5938Mauduit_2048.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;file.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;IoBoundOperationBadAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WebClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;DownloadFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Button_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;IoBoundOperationBadAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 29 seconds, 10 worker threads&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Stopwatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;StartNew&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WhenAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elapsedMs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ElapsedMilliseconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;MessageBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;$&quot;Async task completed in &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elapsedMs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; seconds!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;Information&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;MessageBoxButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;MessageBoxImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Information&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In this case the download takes 29 seconds and uses 10 worker threads (and 14 threads in total). You can verify this by running the app, pressing the button and then &lt;code class=&quot;highlighter-rouge&quot;&gt;Break All&lt;/code&gt; from Visual Studio to get the status in &lt;code class=&quot;highlighter-rouge&quot;&gt;Parallel Stacks&lt;/code&gt; window.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/LUZViHH.png&quot; alt=&quot;Bad I/O - Parallel Stacks&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-good-use-of-async-io&quot;&gt;The good use of &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; I/O&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://apod.nasa.gov/apod/image/1806/IMG_5938Mauduit_2048.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;file.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;IoBoundOperationGoodAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WebClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;DownloadFileTaskAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Button_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// code you already saw in the previous example&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;IoBoundOperationGoodAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 24 seconds, 0 worker threads&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// code you already saw in the previous example&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In this example I used the special &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; method from &lt;code class=&quot;highlighter-rouge&quot;&gt;WebClient&lt;/code&gt; that downloads a file in an &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; way. It took only 24 seconds and used no worker threads. The 4 threads you see in the screenshot below are from the thread pool that’s created for all apps anyway.&lt;/p&gt;

&lt;p&gt;Compared to the previous example (for the bad I/O) this one was not only faster, but also didn’t use any worker threads! &lt;strong&gt;By using less, we achieved more!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/ZUJxzpk.png&quot; alt=&quot;Good I/O - Parallel Stacks&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-good-use-of-async-cpu&quot;&gt;The good use of &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; CPU&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CpuBoundOperationGoodAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;99999999&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Button_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// code you already saw in the previous example&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CpuBoundOperationGoodAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 12 seconds, 8 worker threads&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// code you already saw in the previous example&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In this case the operation took 12 seconds and 8 worker threads - you may wonder why not 10 (since we used &lt;code class=&quot;highlighter-rouge&quot;&gt;Task.Run&lt;/code&gt; in a loop of 10 iterations)? The answer is simple &lt;code class=&quot;highlighter-rouge&quot;&gt;Task.Run&lt;/code&gt; only queues the given work on the thread pool which automatically adjusts the number of threads it uses - that means it doesn’t start a new thread every time you call &lt;code class=&quot;highlighter-rouge&quot;&gt;Task.Run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is a good example of when to use &lt;code class=&quot;highlighter-rouge&quot;&gt;Task.Run&lt;/code&gt; for CPU bound code. A really bad way of doing this would be to have &lt;code class=&quot;highlighter-rouge&quot;&gt;Task.Run&lt;/code&gt; inside the &lt;code class=&quot;highlighter-rouge&quot;&gt;Math.Sin&lt;/code&gt; implementation (not that you can control that, it’s just an example: it could be in a CPU bound method that you could write): always leave calls to &lt;code class=&quot;highlighter-rouge&quot;&gt;Task.Run&lt;/code&gt; at the highest level possible - definitely not in library methods (or any lower level APIs for that matter).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/JN11svu.png&quot; alt=&quot;Good CPU bound - Parallel Stacks&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to read more about when to use &lt;code class=&quot;highlighter-rouge&quot;&gt;Task.Run&lt;/code&gt; please check out this blog post from Stephen Cleary: &lt;a href=&quot;http://blog.stephencleary.com/2013/10/taskrun-etiquette-and-proper-usage.html&quot;&gt;Task.Run Etiquette and Proper Usage&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;how-do-i-made-an-async-method-and-how-do-i-use-asyncawait&quot;&gt;How do I made an async method? And how do I use async/await?&lt;/h1&gt;

&lt;p&gt;Put simply, you start by writing the normal synchronous method and then check what methods can be called asynchronously.&lt;/p&gt;

&lt;p&gt;Basically follow these steps:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;write the normal synchronous method&lt;/li&gt;
  &lt;li&gt;check if the I/O methods that you call from .NET API have an equivalent method whose name ends with &lt;code class=&quot;highlighter-rouge&quot;&gt;Async&lt;/code&gt; and returns a &lt;code class=&quot;highlighter-rouge&quot;&gt;Task&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;await&lt;/code&gt; those method calls&lt;/li&gt;
  &lt;li&gt;propagate &lt;code class=&quot;highlighter-rouge&quot;&gt;await&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; keywords up the call stack&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;net-types-with-async-methods&quot;&gt;.NET types with async methods&lt;/h2&gt;

&lt;p&gt;These types have &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt; methods that you can use for true asynchronous/non-blocking I/O with the web/filesystem:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Web access: &lt;code class=&quot;highlighter-rouge&quot;&gt;HttpClient&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Filesystem access: &lt;code class=&quot;highlighter-rouge&quot;&gt;StreamWriter&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;StreamReader&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;XmlReader&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;recommendations-from-lucian-wischik&quot;&gt;Recommendations from Lucian Wischik&lt;/h1&gt;

&lt;p&gt;There’s a great presentation given by this guy (check out the resources section) that you should watch. I extracted the &lt;strong&gt;tips that I find absolutely essential&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/NhBbqbA.png&quot; alt=&quot;Lucian Wischik, Creating Async Libraries Conference, Slide 3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/saw0hOy.png&quot; alt=&quot;Lucian Wischik, Creating Async Libraries Conference, Slide 4&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/OrZooAU.png&quot; alt=&quot;Lucian Wischik, Creating Async Libraries Conference, Slide 9&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;tips-summarized&quot;&gt;Tips summarized&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The app is in the best position to manage its threads&lt;/li&gt;
  &lt;li&gt;Provide synchronous methods that block the current thread&lt;/li&gt;
  &lt;li&gt;Provide asynchronous methods when you can do so without spawning new threads&lt;/li&gt;
  &lt;li&gt;Let the app that called you use its domain knowledge to manage its threading strategy!&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;source-code&quot;&gt;Source Code&lt;/h1&gt;

&lt;p&gt;The full source code is available on &lt;a href=&quot;https://github.com/igorpopovio/DownloadAsyncIsBlockingInterface&quot;&gt;GitHub&lt;/a&gt;. You can clone the repo and try it locally.&lt;/p&gt;

&lt;h1 id=&quot;resources&quot;&gt;Resources&lt;/h1&gt;

&lt;p&gt;These resources are &lt;strong&gt;official&lt;/strong&gt;, which means that they are either &lt;strong&gt;written by Microsoft or recommended/recognized by them&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/csharp/async&quot;&gt;Asynchronous programming&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/async-in-depth&quot;&gt;Async in Depth&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lucian Wischik&lt;/strong&gt; is a Senior Program Manager for Managed Languages at Microsoft. He made several presentations at conferences that explain in depth what to do in various scenarios related to asynchronous programming:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://channel9.msdn.com/Events/TechEd/Europe/2013/DEV-B318&quot;&gt;Creating Async Libraries That Are Modular, Reusable and Fast&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async&quot;&gt;Six Essential Tips for Async&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stephen Toub&lt;/strong&gt; is a &lt;a href=&quot;https://social.msdn.microsoft.com/profile/Stephen+Toub+-+MSFT&quot;&gt;Microsoft Employee&lt;/a&gt;. He’s the guy that wrote the detailed &lt;a href=&quot;https://www.microsoft.com/en-us/download/details.aspx?id=19957&quot;&gt;Task-based Asynchronous Pattern Document&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stephen Cleary&lt;/strong&gt; is a &lt;a href=&quot;https://mvp.microsoft.com/en-us/PublicProfile/5000058?fullName=Stephen%20Cleary&quot;&gt;Microsoft MVP&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.stephencleary.com/2013/11/there-is-no-thread.html&quot;&gt;There is no Thread!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.stephencleary.com/2013/10/taskrun-etiquette-and-proper-usage.html&quot;&gt;Task.Run Etiquette and Proper Usage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/a/18015586/354009&quot;&gt;When correctly use Task.Run and when just async-await&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="async" />
      
        <category term="await" />
      
        <category term="asynchronous" />
      
        <category term="programming" />
      

      
        <summary type="html">Asynchronous programming causes a lot of confusion because the documentation is a bit lacking and this results in awfully bad implementations. This post compiles my research on this subject so you’ll see lots of quotes from various sources (official and trusted third parties).</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Asynchronous programming in C# with WPF</title>
      
      
      <link href="https://igorpopov.io/2018/06/16/asynchronous-programming-in-csharp-with-wpf/" rel="alternate" type="text/html" title="Asynchronous programming in C# with WPF" />
      
      <published>2018-06-16T00:00:00+00:00</published>
      <updated>2018-06-16T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2018/06/16/asynchronous-programming-in-csharp-with-wpf</id>
      <content type="html" xml:base="https://igorpopov.io/2018/06/16/asynchronous-programming-in-csharp-with-wpf/">&lt;p&gt;I know nothing about the Task Parallel Library and writing a blog post about this is a great opportunity to learn about it. This post won’t be exhaustive: I’ll just explore Microsoft’s recommended way of implementing asynchronous programming.&lt;/p&gt;

&lt;h1 id=&quot;way-of-working&quot;&gt;Way of working&lt;/h1&gt;

&lt;p&gt;I’m more focused now &lt;strong&gt;only on the specifics of asynchronous programming&lt;/strong&gt; so I won’t write the app using best practices like MVVM. For that you should check my previous posts about it.&lt;/p&gt;

&lt;h1 id=&quot;starting-out-the-unresponsive-app&quot;&gt;Starting out: the unresponsive app&lt;/h1&gt;

&lt;p&gt;The app is very simple: just 2 buttons - one for a long running task (which we are going to simulate using &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread.Sleep&lt;/code&gt;) and another, quicker one that just updates a counter. We’re going to see how different approaches work.&lt;/p&gt;

&lt;p&gt;The first approach is the dumb implementation which makes the app unresponsive while the long task executes. We’re doing this just so we have something to compare to.&lt;/p&gt;

&lt;p&gt;Here’s the source code for the long task button click. As you can see, we’re just simulating that it takes long with &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread.Sleep&lt;/code&gt; and then updating the interface to signal that we’re done.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LongTaskButton_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Completed long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And here’s how the application looks like. While the task is executing in background the interface freezes and you can’t do anything else (like clicking the other button).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/nCvloFl.gif&quot; alt=&quot;The unresponsive app&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;introducing-the-task-parallel-library&quot;&gt;Introducing the Task Parallel Library&lt;/h1&gt;

&lt;p&gt;Now let’s use the Task Parallel Library to put the long running task in a background thread and also make a few improvements to the user experience like disabling the button while the task executes and finally updating the interface when the task completes.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LongTaskButton_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Starting long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ContinueWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Dispatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Completed long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Task.Run&lt;/code&gt; will queue the operation to run on the thread pool and will return a &lt;code class=&quot;highlighter-rouge&quot;&gt;Task&lt;/code&gt; object.
In order to update the interface when the task is complete we’re using &lt;code class=&quot;highlighter-rouge&quot;&gt;Task.ContinueWith&lt;/code&gt;. An important thing to notice here is the use of a &lt;code class=&quot;highlighter-rouge&quot;&gt;Dispatcher&lt;/code&gt;. WPF requires all interface updates to be done from a single thread: the UI thread, which queues work items inside an object called a &lt;code class=&quot;highlighter-rouge&quot;&gt;Dispatcher&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you try to update the interface from a different thread then the UI thread you will get an &lt;code class=&quot;highlighter-rouge&quot;&gt;System.InvalidOperationException&lt;/code&gt;: &lt;strong&gt;The calling thread cannot access this object because a different thread owns it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s how the application works now:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/Ytj82d9.gif&quot; alt=&quot;Task Parallel Library&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you can notice, &lt;strong&gt;the app no longer freezes&lt;/strong&gt; after the long task starts: we can still click on the second button to increase the count.&lt;/p&gt;

&lt;p&gt;In case the task fails, we have to check if the task &lt;code class=&quot;highlighter-rouge&quot;&gt;IsFaulted&lt;/code&gt; and if so, then show a message to the user:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LongTaskButton_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Starting long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Something crashed!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ContinueWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Dispatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsFaulted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InnerException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Message&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;Completed long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can also return a status result from the task which you can later access in &lt;code class=&quot;highlighter-rouge&quot;&gt;ContinueWith&lt;/code&gt; by checking the task &lt;code class=&quot;highlighter-rouge&quot;&gt;Result&lt;/code&gt; property:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LongTaskButton_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Starting long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Completed long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ContinueWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Dispatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsFaulted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InnerException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Message&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;handling-exceptions-in-tasks&quot;&gt;Handling exceptions in tasks&lt;/h1&gt;

&lt;p&gt;Here’s what Microsoft has to say about &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-based-asynchronous-programming#handling-exceptions-in-tasks&quot;&gt;handling exceptions in tasks&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When a task throws one or more exceptions, the exceptions are wrapped in an &lt;code class=&quot;highlighter-rouge&quot;&gt;AggregateException&lt;/code&gt; exception. That exception is propagated back to the thread that joins with the task, which is typically the thread that is waiting for the task to finish or the thread that accesses the &lt;code class=&quot;highlighter-rouge&quot;&gt;Result&lt;/code&gt; property. This behavior serves to enforce the .NET Framework policy that all unhandled exceptions by default should terminate the process. The calling code can handle the exceptions by using any of the following in a &lt;code class=&quot;highlighter-rouge&quot;&gt;try/catch&lt;/code&gt; block:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Wait&lt;/code&gt; method&lt;/li&gt;
    &lt;li&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;WaitAll&lt;/code&gt; method&lt;/li&gt;
    &lt;li&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;WaitAny&lt;/code&gt; method&lt;/li&gt;
    &lt;li&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Result&lt;/code&gt; property&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;async-and-await&quot;&gt;async and await&lt;/h1&gt;

&lt;p&gt;These keywords simplify work with Task Parallel Library since you no longer need to use explicit continuations. You simply need to &lt;code class=&quot;highlighter-rouge&quot;&gt;await&lt;/code&gt; a long running task and the current thread will be suspended until that task completes. Everything after await will be executed when the task completes so we no longer need to call &lt;code class=&quot;highlighter-rouge&quot;&gt;ContinueWith&lt;/code&gt; on the returned task.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LongTaskButton_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Starting long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Completed long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And here’s how we handle exceptions in this case:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LongTaskButton_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Starting long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Something crashed!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Completed long task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;awaiting-on-multiple-tasks&quot;&gt;Awaiting on multiple tasks&lt;/h1&gt;

&lt;p&gt;Besides declaring each task, you need to call &lt;code class=&quot;highlighter-rouge&quot;&gt;Tasks.WhenAll&lt;/code&gt; with all the tasks you want to &lt;code class=&quot;highlighter-rouge&quot;&gt;await&lt;/code&gt; upon:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LongTaskButton_Click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RoutedEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Starting long tasks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstLongTask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;first&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secondLongTask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;second&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thirdLongTask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;third&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WhenAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;firstLongTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secondLongTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thirdLongTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;LongTaskButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LongTaskTextBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Completed &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;, &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; tasks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;source-code&quot;&gt;Source Code&lt;/h1&gt;

&lt;p&gt;The full source code is available on &lt;a href=&quot;https://github.com/igorpopovio/AsyncProgramming&quot;&gt;GitHub&lt;/a&gt;. You can clone the repo and try it locally. Just a note though: the examples are available all in the same file, but in different commits - you need to check the &lt;code class=&quot;highlighter-rouge&quot;&gt;git log&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;resources&quot;&gt;Resources&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/csharp/async&quot;&gt;Asynchronous programming&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/async-in-depth&quot;&gt;Async in depth&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.parallel&quot;&gt;Parallel Class&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/12414601/async-await-vs-backgroundworker&quot;&gt;Async/await vs BackgroundWorker&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/index&quot;&gt;Asynchronous Programming Patterns&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap&quot;&gt;Task-based Asynchronous Pattern (TAP)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async&quot;&gt;Six Essential Tips for Async from Channel9&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Concurrency-Cookbook-Asynchronous-Multithreaded-Programming/dp/1449367569&quot;&gt;Concurrency in C# Cookbook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="async" />
      
        <category term="await" />
      
        <category term="asynchronous" />
      
        <category term="programming" />
      

      
        <summary type="html">I know nothing about the Task Parallel Library and writing a blog post about this is a great opportunity to learn about it. This post won’t be exhaustive: I’ll just explore Microsoft’s recommended way of implementing asynchronous programming.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Executing the right project in Visual Studio</title>
      
      
      <link href="https://igorpopov.io/2018/06/13/executing-the-right-project-in-vs/" rel="alternate" type="text/html" title="Executing the right project in Visual Studio" />
      
      <published>2018-06-13T00:00:00+00:00</published>
      <updated>2018-06-13T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2018/06/13/executing-the-right-project-in-vs</id>
      <content type="html" xml:base="https://igorpopov.io/2018/06/13/executing-the-right-project-in-vs/">&lt;p&gt;Often, when you’re working you want to quickly open a file, edit that and run it so you can test it. What happens when you press &lt;code class=&quot;highlighter-rouge&quot;&gt;F5&lt;/code&gt; in Visual Studio is that it will start some other project (when you have a solution with more than 1 project). In this post you’ll learn a simple trick that allows you to start the project where the file you just edited is.&lt;/p&gt;

&lt;h1 id=&quot;the-trick&quot;&gt;The trick&lt;/h1&gt;
&lt;p&gt;You just need to go to the solution settings and choose &lt;strong&gt;Current selection&lt;/strong&gt; as the &lt;strong&gt;Startup Project&lt;/strong&gt; like so:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/0SH9GAT.png&quot; alt=&quot;Starting the Correct Project in Visual Studio&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once you do that, every time you select a file, the project in which that file resides will become active so that when you press &lt;code class=&quot;highlighter-rouge&quot;&gt;F5&lt;/code&gt; to run it will start that specific project. Notice how when you select a different file, the project name becomes &lt;strong&gt;bolded&lt;/strong&gt; in the &lt;strong&gt;Solution Explorer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/5WlLExw.gif&quot; alt=&quot;Demo on how it works&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hopefully, this trick will help you at least in some cases. Of course, it won’t every time (in library projects for example).&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="visual" />
      
        <category term="studio" />
      
        <category term="tips" />
      
        <category term="tricks" />
      

      
        <summary type="html">Often, when you’re working you want to quickly open a file, edit that and run it so you can test it. What happens when you press F5 in Visual Studio is that it will start some other project (when you have a solution with more than 1 project). In this post you’ll learn a simple trick that allows you to start the project where the file you just edited is.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">C# Reflection API</title>
      
      
      <link href="https://igorpopov.io/2018/06/02/csharp-reflection-getting-property-values/" rel="alternate" type="text/html" title="C# Reflection API" />
      
      <published>2018-06-02T00:00:00+00:00</published>
      <updated>2018-06-02T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2018/06/02/csharp-reflection-getting-property-values</id>
      <content type="html" xml:base="https://igorpopov.io/2018/06/02/csharp-reflection-getting-property-values/">&lt;p&gt;In this post we’re going to see how to dynamically get the value of a property by using only its name. This started from me trying to understand how data binding works in XAML and implementing it myself. For this, I needed a view model which implements the &lt;code class=&quot;highlighter-rouge&quot;&gt;INotifyPropertyChanged&lt;/code&gt; and then subscribe to its &lt;code class=&quot;highlighter-rouge&quot;&gt;PropertyChanged&lt;/code&gt; event.&lt;/p&gt;

&lt;h1 id=&quot;the-view-model&quot;&gt;The view model&lt;/h1&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.ComponentModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;CSharpEventsReflectionAndDataBinding&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Robot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INotifyPropertyChanged&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;years&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Years&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;years&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;years&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;nf&quot;&gt;OnPropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Years&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PropertyChangedEventHandler&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnPropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;propertyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;PropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;PropertyChangedEventArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propertyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;the-main-program&quot;&gt;The main program&lt;/h1&gt;
&lt;p&gt;Just for fun I used &lt;strong&gt;R. Daneel Olivaw&lt;/strong&gt; as an example…&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Timers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;CSharpEventsReflectionAndDataBinding&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Program&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mainArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Program&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rDaneelOlivaw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Robot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Daneel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Olivaw&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;Years&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;19200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

            &lt;span class=&quot;nf&quot;&gt;PrintYearsWhenItIsChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rDaneelOlivaw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;CreateTimerToIncreaseYears&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rDaneelOlivaw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;PrintYearsWhenItIsChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Robot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PropertyChanged&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;propertyName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PropertyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;propertyValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propertyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

                &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; now has &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propertyValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propertyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Timer&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CreateTimerToIncreaseYears&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Robot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AutoReset&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Elapsed&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Years&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;explanation&quot;&gt;Explanation&lt;/h1&gt;
&lt;p&gt;To get the property value we first need to know on what &lt;code class=&quot;highlighter-rouge&quot;&gt;Type&lt;/code&gt; it resides, then the property name and finally the target object.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;propertyValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propertyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is a simple concept and in case I ever need it I know where to look for a quick refresher.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="C#" />
      
        <category term="reflection" />
      
        <category term="api" />
      
        <category term="properties" />
      
        <category term="tips" />
      
        <category term="tricks" />
      

      
        <summary type="html">In this post we’re going to see how to dynamically get the value of a property by using only its name. This started from me trying to understand how data binding works in XAML and implementing it myself. For this, I needed a view model which implements the INotifyPropertyChanged and then subscribe to its PropertyChanged event.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">StringFormat in XAML</title>
      
      
      <link href="https://igorpopov.io/2018/05/26/stringformat-in-xaml/" rel="alternate" type="text/html" title="StringFormat in XAML" />
      
      <published>2018-05-26T00:00:00+00:00</published>
      <updated>2018-05-26T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2018/05/26/stringformat-in-xaml</id>
      <content type="html" xml:base="https://igorpopov.io/2018/05/26/stringformat-in-xaml/">&lt;p&gt;In an usual application sometimes you need to “adapt” the values from the view model. This is normally done using &lt;code class=&quot;highlighter-rouge&quot;&gt;StringFormat&lt;/code&gt;, but we’ll see some other options as well.&lt;/p&gt;

&lt;h1 id=&quot;simple-stringformat-with-binding-escape&quot;&gt;Simple StringFormat with binding escape&lt;/h1&gt;
&lt;p&gt;Let’s say that you need to display a temperature in degrees. In the view model you have just the numerical value and in the interface you want to append the &lt;code class=&quot;highlighter-rouge&quot;&gt;°C&lt;/code&gt; string to make it clear what type of degrees are displayed. Here’s how that’s done:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding CelsiusTemp, StringFormat={}{0}°C}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;multibinding&quot;&gt;MultiBinding&lt;/h1&gt;
&lt;p&gt;The zero from XAML binding is actually the first binding. In the next example &lt;code class=&quot;highlighter-rouge&quot;&gt;Name&lt;/code&gt; is the &lt;code class=&quot;highlighter-rouge&quot;&gt;{0}&lt;/code&gt; part and &lt;code class=&quot;highlighter-rouge&quot;&gt;ID&lt;/code&gt; is the &lt;code class=&quot;highlighter-rouge&quot;&gt;{1}&lt;/code&gt; part:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock.Text&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;MultiBinding&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;StringFormat=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}{0} + {1}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;Binding&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Path=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Name&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;Binding&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Path=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ID&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/MultiBinding&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/TextBlock.Text&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TextBlock&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There are however some other ways you can concatenate string values in XAML. Let’s review them quickly:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;TextBlock with Run text&lt;/li&gt;
  &lt;li&gt;Using StackPanel to group&lt;/li&gt;
  &lt;li&gt;Using Converters&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;textblock-with-run-text&quot;&gt;TextBlock with Run text&lt;/h1&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;TextBlock&lt;/code&gt; supports an inner element called &lt;code class=&quot;highlighter-rouge&quot;&gt;Run&lt;/code&gt; which can be helpful when you want to concatenate more things.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Run&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Temperature is &quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Run&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding CelsiusTemp}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Run&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;°C&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TextBlock&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;using-stackpanel-to-group&quot;&gt;Using StackPanel to group&lt;/h1&gt;
&lt;p&gt;In this case you can just dump everything in a &lt;code class=&quot;highlighter-rouge&quot;&gt;StackPanel&lt;/code&gt; having the &lt;code class=&quot;highlighter-rouge&quot;&gt;Orientation&lt;/code&gt; set to &lt;code class=&quot;highlighter-rouge&quot;&gt;Horizontal&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;StackPanel&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Orientation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Horizontal&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Temperature is &quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding CelsiusTemp}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;°C&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/StackPanel&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;using-converter&quot;&gt;Using Converter&lt;/h1&gt;
&lt;p&gt;And the last example, although I wouldn’t really use it in this case (but shown nonetheless just for completeness sake):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TemperatureConverter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IValueConverter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Convert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targetType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CultureInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;culture&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;Temperature is &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; °C&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ConvertBack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targetType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CultureInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;culture&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;NotImplementedException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And here’s how to use it in XAML:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Grid&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Grid.Resources&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;local:TemperatureConverter&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x:Key=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;temperatureConverter&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Grid.Resources&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding CelsiusTemp, Converter={StaticResource temperatureConverter}}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Grid&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;most-common-formatting-specifiers&quot;&gt;Most common formatting specifiers&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Formatting numbers using 2 decimal points&lt;/strong&gt; is done using &lt;code class=&quot;highlighter-rouge&quot;&gt;F2&lt;/code&gt; - F means floating point and the following digit is the number of decimal digits. In this case I used 2, but it can be any value. If you want to show only the integral part then use &lt;code class=&quot;highlighter-rouge&quot;&gt;F0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you also want to &lt;strong&gt;display the thousands separator&lt;/strong&gt; you can use &lt;code class=&quot;highlighter-rouge&quot;&gt;N2&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Consider CelsiusTemp = 1234.5678 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Also take note that the values will be rounded! --&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- This will be: 1234.57 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding CelsiusTemp, StringFormat={}{0:F2}}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- This will be: 1235 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding CelsiusTemp, StringFormat={}{0:F0}}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- This will be: 1,234.57 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding CelsiusTemp, StringFormat={}{0:N2}}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- This will be: 1,235 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding CelsiusTemp, StringFormat={}{0:N0}}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here are some more examples showing how to &lt;strong&gt;display currency and dates&lt;/strong&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Window&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x:Class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;PlayingWithXAML.MainWindow&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;x:Name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wnd&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;xmlns=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;xmlns:x=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;xmlns:system=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;clr-namespace:System;assembly=mscorlib&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;Width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;300&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;Height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;200&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;StackPanel&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Margin=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding ElementName=wnd, Path=ActualWidth, StringFormat=Window width: {0:#,#.0}}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding ElementName=wnd, Path=ActualHeight, StringFormat=Window height: {0:C}}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Source={x:Static system:DateTime.Now}, StringFormat=Date: {0:dddd, MMMM dd}}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Source={x:Static system:DateTime.Now}, StringFormat=Time: {0:HH:mm}}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/StackPanel&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Window&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/framework/xaml-services/escape-sequence-markup-extension&quot;&gt;{} Escape Sequence / Markup Extension&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings&quot;&gt;Standard Numeric Format Strings&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/19278515/use-stringformat-to-add-a-string-to-a-wpf-xaml-binding&quot;&gt;Use StringFormat to add a string to a WPF XAML binding&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.wpf-tutorial.com/data-binding/the-stringformat-property&quot;&gt;The StringFormat property&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/2552853/how-to-bind-multiple-values-to-a-single-wpf-textblock&quot;&gt;How to bind multiple values to a single WPF TextBlock?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="stringformat" />
      
        <category term="xaml" />
      
        <category term="tips" />
      
        <category term="tricks" />
      

      
        <summary type="html">In an usual application sometimes you need to “adapt” the values from the view model. This is normally done using StringFormat, but we’ll see some other options as well.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Visual Studio Productivity Tips &amp;amp; Tricks</title>
      
      
      <link href="https://igorpopov.io/2018/05/13/visual-studio-productivity-tips-and-tricks/" rel="alternate" type="text/html" title="Visual Studio Productivity Tips &amp; Tricks" />
      
      <published>2018-05-13T00:00:00+00:00</published>
      <updated>2018-05-13T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2018/05/13/visual-studio-productivity-tips-and-tricks</id>
      <content type="html" xml:base="https://igorpopov.io/2018/05/13/visual-studio-productivity-tips-and-tricks/">&lt;p&gt;You can boost your Visual Studio productivity if you know these little &lt;strong&gt;tips and tricks&lt;/strong&gt;. We’ll go through some of the most useful &lt;strong&gt;code snippets&lt;/strong&gt;, &lt;strong&gt;keyboard shortcuts&lt;/strong&gt; and &lt;strong&gt;extensions&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;code-snippets&quot;&gt;Code snippets&lt;/h2&gt;

&lt;p&gt;Code snippets are a way to &lt;strong&gt;write frequent code faster&lt;/strong&gt;. This is achieved by typing a mnemonic followed by &lt;code class=&quot;highlighter-rouge&quot;&gt;TAB TAB&lt;/code&gt; in order for it to be replaced with the final code.&lt;/p&gt;

&lt;h3 id=&quot;1-svm---static-void-main&quot;&gt;1. &lt;code class=&quot;highlighter-rouge&quot;&gt;svm&lt;/code&gt; - &lt;code class=&quot;highlighter-rouge&quot;&gt;static void main&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;When you start a new project you obviously want to write the &lt;code class=&quot;highlighter-rouge&quot;&gt;main&lt;/code&gt; method first. In order to do so faster you can use the &lt;code class=&quot;highlighter-rouge&quot;&gt;svm&lt;/code&gt; snippet. After you write &lt;code class=&quot;highlighter-rouge&quot;&gt;svm&lt;/code&gt; press &lt;code class=&quot;highlighter-rouge&quot;&gt;TAB TAB&lt;/code&gt; and the snippet will be replaced with the &lt;code class=&quot;highlighter-rouge&quot;&gt;main&lt;/code&gt; method:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/lhduOMd.gif&quot; alt=&quot;VS snippet: svm&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;2-cw---consolewriteline&quot;&gt;2. &lt;code class=&quot;highlighter-rouge&quot;&gt;cw&lt;/code&gt; - &lt;code class=&quot;highlighter-rouge&quot;&gt;Console.WriteLine&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Normally you would be making GUI programs so why should you care about being able to write to the command line faster?!&lt;/p&gt;

&lt;p&gt;Well, if you’re like me, when you encounter a problem that it’s more difficult you want to simplify it as much as possible. One way of doing this is to create a separate command line project to isolate the problem to the most essential parts. In that case, if you want to &lt;strong&gt;quickly display a message&lt;/strong&gt; you can use the &lt;code class=&quot;highlighter-rouge&quot;&gt;cw&lt;/code&gt; snippet (as before - followed by &lt;code class=&quot;highlighter-rouge&quot;&gt;TAB TAB&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/bZPK7rI.gif&quot; alt=&quot;VS snippet: cw&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;3-mbox---messageboxshow&quot;&gt;3. &lt;code class=&quot;highlighter-rouge&quot;&gt;mbox&lt;/code&gt; - &lt;code class=&quot;highlighter-rouge&quot;&gt;MessageBox.Show&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;In the same style as the previous snippet, this one helps us when we want to show a quick message to the user. Normally the &lt;code class=&quot;highlighter-rouge&quot;&gt;MessageBox&lt;/code&gt; is a bit old and not so user friendly, but it works quite well when debugging.&lt;/p&gt;

&lt;p&gt;One quick note, though, if you’re using Windows Forms then you can leave the namespace untouched, but if you’re using WPF you have 2 options: either add the &lt;code class=&quot;highlighter-rouge&quot;&gt;System.Windows.Forms&lt;/code&gt; reference or just &lt;strong&gt;delete the&lt;/strong&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;Forms&lt;/code&gt; &lt;strong&gt;part from the inserted line&lt;/strong&gt;. I prefer the second options (also demoed below) because you keep &lt;strong&gt;using WPF without needing to depend also on Windows Forms&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/S0QbfGf.gif&quot; alt=&quot;VS snippet: mbox&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;4-prop--propfull---c-properties&quot;&gt;4. &lt;code class=&quot;highlighter-rouge&quot;&gt;prop&lt;/code&gt; &amp;amp; &lt;code class=&quot;highlighter-rouge&quot;&gt;propfull&lt;/code&gt; - C# Properties&lt;/h3&gt;
&lt;p&gt;Another thing that’s quite often and useful is &lt;strong&gt;adding C# properties quickly&lt;/strong&gt;. After the snippet is inserted, you can continue pressing &lt;code class=&quot;highlighter-rouge&quot;&gt;TAB&lt;/code&gt; to cycle between the type and the name. If you need also the property backing field you should use &lt;code class=&quot;highlighter-rouge&quot;&gt;propfull&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/aW2CqlR.gif&quot; alt=&quot;VS snippet: prop&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;5-propdp--propa---dependency-properties--attached-properties&quot;&gt;5. &lt;code class=&quot;highlighter-rouge&quot;&gt;propdp&lt;/code&gt; &amp;amp; &lt;code class=&quot;highlighter-rouge&quot;&gt;propa&lt;/code&gt; - Dependency Properties &amp;amp; Attached Properties&lt;/h3&gt;
&lt;p&gt;When creating a new user control you often need to write new &lt;strong&gt;dependency properties&lt;/strong&gt;. Unfortunately, the syntax for doing so is quite complex and difficult to get right the first time. In the same style there’s also &lt;code class=&quot;highlighter-rouge&quot;&gt;propa&lt;/code&gt; that inserts an &lt;strong&gt;attached property&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/ucypHKY.gif&quot; alt=&quot;VS snippet: propdp&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;keyboard-shortcuts&quot;&gt;Keyboard shortcuts&lt;/h2&gt;

&lt;p&gt;Keyboard shortcuts are by far the &lt;strong&gt;quickest way to improve your productivity&lt;/strong&gt;. In the next lines I’ll show the shortcuts that I consider critical.&lt;/p&gt;

&lt;h3 id=&quot;the-most-potent-shortcuts&quot;&gt;The most potent shortcuts&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;quick fix: &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL + .&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;search commands: &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL + Q&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;search type: &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL + T&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;navigation-shortcuts&quot;&gt;Navigation shortcuts&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;navigate to definition: &lt;code class=&quot;highlighter-rouge&quot;&gt;F12&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;find references: &lt;code class=&quot;highlighter-rouge&quot;&gt;SHIFT + F12&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;navigate backward: &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL + -&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;navigate foreward: &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL + SHIFT + -&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;code-handling&quot;&gt;Code handling&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;format code: &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL + K,D&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;comment code: &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL + K,C&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;uncomment code: &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL + K,U&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;move line up: &lt;code class=&quot;highlighter-rouge&quot;&gt;ALT + ↑&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;move line down: &lt;code class=&quot;highlighter-rouge&quot;&gt;ALT + ↓&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;rename: &lt;code class=&quot;highlighter-rouge&quot;&gt;F2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;personal-favorite-quick-fix&quot;&gt;Personal favorite: quick fix&lt;/h3&gt;
&lt;p&gt;The most amazing shortcut has to be the &lt;em&gt;quick fix&lt;/em&gt;! If you have an error, a warning or a code suggestion you just have to press &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL + .&lt;/code&gt; to get a list of quick fixes and choose the one you want. It’s the shortcut that can fix almost any problem.&lt;/p&gt;

&lt;p&gt;In the example below I used &lt;a href=&quot;http://wiki.c2.com/?ProgrammingByIntention&quot;&gt;programming by intention&lt;/a&gt; to first call the method I need and then using quick fix to add a placeholder for the method thus saving my time I would have spent writing it. I know, I know, it’s so small it doesn’t matter… but it adds up after a while.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/EanCj5Z.gif&quot; alt=&quot;VS keyboard shortcut: quick fix&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;personal-favorite-expandcontract-selection&quot;&gt;Personal favorite: expand/contract selection&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;expand selection: &lt;code class=&quot;highlighter-rouge&quot;&gt;ALT + SHIFT + =&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;contract selection: &lt;code class=&quot;highlighter-rouge&quot;&gt;ALT + SHIFT + -&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This shortcut is very useful when you want to refactor code. Let’s say that you want to extract a method for the conditional expression in an &lt;code class=&quot;highlighter-rouge&quot;&gt;if&lt;/code&gt; statement. If you move your caret (using the keyboard) you could press &lt;code class=&quot;highlighter-rouge&quot;&gt;ALT + SHIFT + =&lt;/code&gt; until you select the expression you want and then press &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL + R,M&lt;/code&gt; to extract a method. Here’s how the selection works:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/ddTTjGI.gif&quot; alt=&quot;VS keyboard shortcut: expand/contract selection&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Just a &lt;strong&gt;quick warning&lt;/strong&gt; though: this was added in Visual Studio 2017 15.5.2 so in previous versions you won’t be able to do this (although this functionality might be supported through an extension).&lt;/p&gt;

&lt;h2 id=&quot;extensions&quot;&gt;Extensions&lt;/h2&gt;
&lt;p&gt;Extensions are the last pillar - they offer stuff that’s not built-in Visual Studio. &lt;strong&gt;WARNING:&lt;/strong&gt; Please be aware that &lt;strong&gt;too many extensions will slow down Visual Studio&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here are the extensions that I consider most useful:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.ProductivityPowerPack2017&quot;&gt;Productivity Power Tools 2017&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=josefpihrt.Roslynator2017&quot;&gt;Roslynator (refactoring)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=SharpDevelopTeam.RefactoringEssentialsforVisualStudio&quot;&gt;Refactoring Essentials for Visual Studio&lt;/a&gt; (&lt;a href=&quot;http://vsrefactoringessentials.com/&quot;&gt;official website&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=OneCodeTeam.DeveloperAssistant&quot;&gt;Developer Assistant&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=MatthewJohnsonMSFT.HideMainMenu&quot;&gt;Hide Main Menu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ShemeerNS.ColorPicker&quot;&gt;Color Picker&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=TomasRestrepo.Viasfora&quot;&gt;Viasfora (colors matching parenthesis)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=EWoodruff.VisualStudioSpellCheckerVS2017andLater&quot;&gt;Spell Checker&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=MikeWard-AnnArbor.VSColorOutput&quot;&gt;VSColorOutput&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=SonarSource.SonarLintforVisualStudio2017&quot;&gt;SonarLint&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.VSIntelliCode&quot;&gt;Visual Studio IntelliCode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hopefully all these &lt;strong&gt;tips and tricks&lt;/strong&gt; will help you &lt;strong&gt;improve your productivity&lt;/strong&gt;.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="vs" />
      
        <category term="visual" />
      
        <category term="studio" />
      
        <category term="productivity" />
      
        <category term="tips" />
      
        <category term="tricks" />
      

      
        <summary type="html">You can boost your Visual Studio productivity if you know these little tips and tricks. We’ll go through some of the most useful code snippets, keyboard shortcuts and extensions.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Mutation testing and the quest for quality</title>
      
      
      <link href="https://igorpopov.io/2015/06/01/mutation-testing-and-the-quest-for-quality/" rel="alternate" type="text/html" title="Mutation testing and the quest for quality" />
      
      <published>2015-06-01T00:00:00+00:00</published>
      <updated>2015-06-01T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2015/06/01/mutation-testing-and-the-quest-for-quality</id>
      <content type="html" xml:base="https://igorpopov.io/2015/06/01/mutation-testing-and-the-quest-for-quality/">&lt;p&gt;In this post you’ll learn the differences between &lt;strong&gt;mutation testing&lt;/strong&gt; and &lt;strong&gt;code coverage&lt;/strong&gt; by &lt;strong&gt;comparing several code examples&lt;/strong&gt; and you’ll also receive &lt;strong&gt;practical advice on improving software quality&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-100-percent.jpg&quot; alt=&quot;100% coverage&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The best ways to teach someone a new concept that I know of are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;comparing the new concept with an existing one which they already know&lt;/li&gt;
  &lt;li&gt;showing a lot of examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post I’ll do both.&lt;/p&gt;

&lt;p&gt;To understand &lt;strong&gt;mutation testing&lt;/strong&gt;, let’s review what &lt;strong&gt;code coverage&lt;/strong&gt; is… If we were to check the &lt;a href=&quot;https://en.wikipedia.org/wiki/Code_coverage&quot;&gt;Wikipedia page&lt;/a&gt; (as of 01.06.2015), &lt;strong&gt;code coverage&lt;/strong&gt; is defined as:&lt;/p&gt;

&lt;p&gt;“a measure used to describe &lt;strong&gt;the degree to which the source code of a
program is tested&lt;/strong&gt; by a particular test suite. A program with high
code coverage has been &lt;strong&gt;more thoroughly tested&lt;/strong&gt; and has a lower
chance of containing software bugs than a program with low code coverage.”&lt;/p&gt;

&lt;p&gt;Unfortunately, the statements above are not very acurate. Code coverage is the
degree to which the source code of a program is &lt;strong&gt;executed, not tested&lt;/strong&gt; which is not the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can execute the code without testing anything&lt;/strong&gt;. In the next example you’ll see what I mean, but first let’s setup the demo project.&lt;/p&gt;

&lt;h2 id=&quot;the-gilded-rose-kata&quot;&gt;The Gilded Rose Kata&lt;/h2&gt;

&lt;p&gt;I’m going to use the &lt;strong&gt;Gilded Rose Kata&lt;/strong&gt; as an example codebase so you can follow my explanation.
This project is specifically designed so you can practice working with &lt;strong&gt;legacy code&lt;/strong&gt; and it fits perfectly for &lt;strong&gt;learning about code coverage and mutation testing coverage&lt;/strong&gt;. &lt;strong&gt;The story&lt;/strong&gt; behind the project is that &lt;strong&gt;you are working for a shop and have to add support for a new item type while keeping the current behaviour&lt;/strong&gt; (not breaking it).&lt;/p&gt;

&lt;p&gt;You can find the project on &lt;a href=&quot;https://github.com/igorpopovio/GildedRoseJavaKata&quot;&gt;GitHub&lt;/a&gt;. Read the &lt;code class=&quot;highlighter-rouge&quot;&gt;README.markdown&lt;/code&gt; file for more instructions.&lt;/p&gt;

&lt;h2 id=&quot;code-coverage&quot;&gt;Code coverage&lt;/h2&gt;

&lt;p&gt;Now that you have the project let’s see how we can get the &lt;strong&gt;code coverage&lt;/strong&gt; by &lt;strong&gt;executing the main method&lt;/strong&gt;. While this is not the first thing someone thinks of when hearing about &lt;strong&gt;code coverage&lt;/strong&gt; it will help illustrate my point.&lt;/p&gt;

&lt;p&gt;Execute the following command:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./gradlew appCodeCoverage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will run the main method and collect &lt;strong&gt;code coverage&lt;/strong&gt; using the JaCoCo Gradle plugin. After the command finishes you should check the &lt;code class=&quot;highlighter-rouge&quot;&gt;build/reports/jacoco/applicationCodeCoverageReport/html/index.html&lt;/code&gt; file to read the coverage report.&lt;/p&gt;

&lt;p&gt;This is the project level &lt;strong&gt;code coverage&lt;/strong&gt;. In the first column you can see the packages and in the next 2 columns you can see the &lt;strong&gt;line coverage&lt;/strong&gt; which is also called &lt;strong&gt;statement coverage&lt;/strong&gt; and it means the percent of lines that were executed from the total. The following 2 columns (columns 4 and 5) show the &lt;strong&gt;branch coverage&lt;/strong&gt; which means the percent of conditional branches (if, for, while) that were executed from the total.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example1-project.png&quot; alt=&quot;Example 1. Code coverage for main method - project level&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The branch coverage is usually lower than the statement coverage&lt;/strong&gt;. For example, in an &lt;code class=&quot;highlighter-rouge&quot;&gt;if&lt;/code&gt; statement you can execute just one branch and have 100% statement coverage, but you only have 50% branch coverage because you executed just a single branch, not both. You can see in the image above that we have 76% &lt;strong&gt;branch coverage&lt;/strong&gt; versus 81% &lt;strong&gt;statement coverage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the next view (which you get by clicking on the package name) you can see the code coverage distribution for all classes in the package. For this specific project we are interested only in the &lt;code class=&quot;highlighter-rouge&quot;&gt;GildedRose&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example1-package.png&quot; alt=&quot;Example 1. Code coverage for main method - package level&quot; /&gt;&lt;/p&gt;

&lt;p&gt;By clicking on the &lt;code class=&quot;highlighter-rouge&quot;&gt;GildedRose&lt;/code&gt; class and then one of the methods you get to the code level view where you can see each line with a different background based on the executed status:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example1-method.png&quot; alt=&quot;Example 1. Code coverage for main method - method level&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;green line - was executed&lt;/li&gt;
  &lt;li&gt;red line - was not executed&lt;/li&gt;
  &lt;li&gt;yellow line - only one branch of the conditional statement was executed&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;partial-test-coverage&quot;&gt;Partial test coverage&lt;/h2&gt;

&lt;p&gt;There is another way to obtain &lt;strong&gt;code coverage&lt;/strong&gt;: by &lt;strong&gt;running the automated tests&lt;/strong&gt;, which is the &lt;strong&gt;most widely accepted definition&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I prefer to call it &lt;strong&gt;test coverage&lt;/strong&gt; instead of merely &lt;strong&gt;code coverage&lt;/strong&gt; just to highlight the way they have been obtained. The &lt;strong&gt;code coverage&lt;/strong&gt; is obtained by running the main method (see previous example) and &lt;strong&gt;test coverage&lt;/strong&gt; by running the automated tests.&lt;/p&gt;

&lt;p&gt;You can &lt;code class=&quot;highlighter-rouge&quot;&gt;git checkout incomplete_tests&lt;/code&gt;, run &lt;code class=&quot;highlighter-rouge&quot;&gt;./gradlew jacoco&lt;/code&gt; and open the report available in the &lt;code class=&quot;highlighter-rouge&quot;&gt;build/reports/jacoco/test/html/index.html&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;In the test coverage report you will see that the code dealing with backstage passes is not executed at all from the tests. The reason for that is simple: there are no tests for it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example2-backstage-passes-uncovered.png&quot; alt=&quot;Example 2. Test coverage - backstage passes uncovered&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;test coverage&lt;/strong&gt; is a pretty good way for you to find out (at least in the beginning) what new tests to write, but as you’ll see in the next examples it &lt;strong&gt;has certain limitations&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;full-test-coverage&quot;&gt;Full test coverage?!&lt;/h2&gt;

&lt;p&gt;Now, let’s improve that test coverage we have. I mean if we get to &lt;strong&gt;100% test coverage&lt;/strong&gt; that means &lt;strong&gt;the code is fully tested&lt;/strong&gt;, right? Wrong… and you’ll see why by checking out the &lt;code class=&quot;highlighter-rouge&quot;&gt;tests_without_asserts&lt;/code&gt; branch. If you execute again the command to gather &lt;strong&gt;test coverage&lt;/strong&gt;: &lt;code class=&quot;highlighter-rouge&quot;&gt;./gradlew jacoco&lt;/code&gt; you’ll see that the coverage jumped to 100% (for the &lt;code class=&quot;highlighter-rouge&quot;&gt;GildedRose&lt;/code&gt; class which contains the logic we want to test).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example3-package.png&quot; alt=&quot;Example 3. Full test coverage&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, if you check the test code you’ll see that &lt;strong&gt;all the asserts are commented out&lt;/strong&gt;… Obviously, this is just &lt;strong&gt;to demonstrate the test coverage weaknesses&lt;/strong&gt; and I’m sure none of you have seen such things in &lt;strong&gt;The Real World&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The most likely case is that you are missing &lt;strong&gt;some asserts&lt;/strong&gt; in your test code, but it is &lt;strong&gt;hard to see which ones&lt;/strong&gt; because you already have &lt;strong&gt;high test coverage&lt;/strong&gt; as demonstrated in this example - 100% test coverage even without asserts.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example3-commented-asserts.png&quot; alt=&quot;Example 3. Full test coverage - commented asserts&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;is-the-code-actually-tested&quot;&gt;Is the code actually tested?&lt;/h2&gt;

&lt;p&gt;We saw that having &lt;strong&gt;high test coverage&lt;/strong&gt; doesn’t mean anything else that the code was executed. But, you may ask, &lt;strong&gt;how can we actually ensure that the code is tested now that we can’t trust the test coverage?!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well, there’s an &lt;strong&gt;easy answer&lt;/strong&gt; for that: &lt;strong&gt;the tests you have should fail if the production code is broken&lt;/strong&gt;…&lt;/p&gt;

&lt;p&gt;Oh, yeah, you couldn’t state something more obvious you say…&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-safety-net.png&quot; alt=&quot;Unit tests - safety net&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Knowing that, you could &lt;strong&gt;try breaking the production code and running the tests&lt;/strong&gt;. If the tests fail, then the code is tested. If the tests still pass then obviously they aren’t any good since they should act as your &lt;strong&gt;safety net&lt;/strong&gt; in case you break something.&lt;/p&gt;

&lt;p&gt;This is all about &lt;strong&gt;increasing the confidence in your tests&lt;/strong&gt; and ensuring that you won’t fall right through your “test” &lt;strong&gt;safety net&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s a nice story that illustrates it from &lt;a href=&quot;http://www.agitar.com/downloads/TheWayOfTestivus.pdf&quot;&gt;&lt;strong&gt;The Way of Testivus&lt;/strong&gt;&lt;/a&gt; by &lt;strong&gt;Alberto Savoia&lt;/strong&gt; (you should check the other stories as well - they contain a lot of wisdom):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-good-tests-fail.png&quot; alt=&quot;Good tests fail&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-to-break-the-production-code&quot;&gt;How to break the production code?&lt;/h2&gt;

&lt;p&gt;Following the previous advice, let’s see how we can &lt;strong&gt;break the code to highlight the problems in our tests&lt;/strong&gt;…&lt;/p&gt;

&lt;p&gt;If we try deleting random parts of the code we could break the code in such a way that it doesn’t compile anymore and obviously we wouldn’t be able to run the tests in that case. Clearly this is not what we want. So while we break the code we must ensure that the code still compiles.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-break-all-the-things.jpg&quot; alt=&quot;Unit tests - safety net&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If we try deleting a lot of code at once (keeping the code compilable) then it’s very likely that all (or almost all) the tests will fail. We don’t want that… What we want instead is to find the minimum things to break in the production code so that the tests will all pass.&lt;/p&gt;

&lt;p&gt;The best approach is to &lt;strong&gt;emulate a programmers usual mistakes&lt;/strong&gt;: off by one errors, edge cases, removing calls to functions (programmer forgot to call it), exceptions, negating boolean expressions, replacing addition with subtraction and the other way around. These are all subtle changes and it’s very likely you will discover that for some of these your tests still pass. Obviously you have to add a unit test that detects that issue.&lt;/p&gt;

&lt;h2 id=&quot;mutation-testing-concepts&quot;&gt;Mutation testing concepts&lt;/h2&gt;

&lt;p&gt;We finally got to the &lt;strong&gt;mutation testing&lt;/strong&gt; part which is the easiest to understand. You have to know these three concepts:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;a mutant&lt;/strong&gt; is created by making (manually or automatically) a small change in the production code&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;the mutant is killed&lt;/strong&gt; means that your tests fail when run after creating the mutant&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;the mutant survived&lt;/strong&gt; means that your tests still pass when run after creating the mutant&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;To ensure the production code is fully tested your tests must kill all the mutants&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;manual-mutation-testing&quot;&gt;Manual mutation testing&lt;/h2&gt;

&lt;p&gt;Let’s take an example and do it manually just so we understand better the process. Checkout the &lt;code class=&quot;highlighter-rouge&quot;&gt;almost_complete_tests&lt;/code&gt; branch. Now we have almost all the tests and 100% test coverage. Let’s see which tests are missing.&lt;/p&gt;

&lt;p&gt;If we try changing something small (creating our &lt;strong&gt;mutant&lt;/strong&gt;), like a subtraction to an addition:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example4-small-manual-change-tests-fail.png&quot; alt=&quot;Example 4. Small change&quot; /&gt;&lt;/p&gt;

&lt;p&gt;and we run the unit tests again, we’ll see that they &lt;strong&gt;fail&lt;/strong&gt;… this means &lt;strong&gt;the tests killed the mutant&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example4-small-manual-change-tests-fail2.png&quot; alt=&quot;Example 4. Small change - tests fail&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If we try doing the following change and running all the tests:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example4-small-change-tests-pass.png&quot; alt=&quot;Example 4. Small change - tests pass&quot; /&gt;&lt;/p&gt;

&lt;p&gt;we’ll see that they &lt;strong&gt;pass&lt;/strong&gt;… &lt;strong&gt;the mutant survived&lt;/strong&gt;. This is a bad thing - it means that we are missing some tests…&lt;/p&gt;

&lt;p&gt;Let’s check again the requirements for Sulfuras (you can find them in the &lt;code class=&quot;highlighter-rouge&quot;&gt;README.markdown&lt;/code&gt; file):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Sulfuras&lt;/strong&gt;, being a legendary item, &lt;strong&gt;never has to be sold&lt;/strong&gt; or decreases in quality&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, now we can write a test for this requirement:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example4-missing-test.png&quot; alt=&quot;Example 4. The missing test&quot; /&gt;&lt;/p&gt;

&lt;p&gt;and sure enough, when running the tests again for the previous mutant we can see that they fail:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example4-missing-test-failing.png&quot; alt=&quot;Example 4. The missing test failing&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;automated-mutation-testing&quot;&gt;Automated mutation testing&lt;/h2&gt;

&lt;p&gt;While creating these mutants for one or two lines of code is trivial, we wouldn’t want to do it manually for a whole class or for the whole code base. Fortunately, there are solutions for that - plugins and automated tools that can create the mutants, run the tests automatically and show you a coverage report - that is a &lt;strong&gt;mutation test coverage&lt;/strong&gt; report - which gives you &lt;strong&gt;a lot more confidence in your tests&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I set up everything so you can get the &lt;strong&gt;true coverage&lt;/strong&gt; by running &lt;code class=&quot;highlighter-rouge&quot;&gt;./gradlew pitest&lt;/code&gt; and opening the &lt;code class=&quot;highlighter-rouge&quot;&gt;build/reports/pitest/index.html&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Now you will see what parts of the code &lt;strong&gt;are not actually tested&lt;/strong&gt; (even though we have 100% test coverage):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example5-pitest-coverage.png&quot; alt=&quot;Example 5. Pitest coverage&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I will leave writing the missing tests as an exercise. If you want to check your answers you can look in the &lt;code class=&quot;highlighter-rouge&quot;&gt;with_tests&lt;/code&gt; branch which contains the &lt;strong&gt;complete tests&lt;/strong&gt; that lead to &lt;strong&gt;100% mutation test coverage&lt;/strong&gt; - &lt;strong&gt;the highest coverage you can get&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;parameterized_tests&lt;/code&gt; branch has the same tests as the &lt;code class=&quot;highlighter-rouge&quot;&gt;with_tests&lt;/code&gt; branch except that I have removed (almost) all the duplicate code - the tests were looking very similar so I used the &lt;code class=&quot;highlighter-rouge&quot;&gt;JUnitParams&lt;/code&gt; library to parameterize a single method:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example6-parameterized-tests.png&quot; alt=&quot;Example 6. Parameterized tests&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;mutation-testing---not-a-silver-bullet&quot;&gt;Mutation testing - not a silver bullet&lt;/h2&gt;

&lt;p&gt;Sure, now you achieved 100% mutation test coverage and you’re absolutely sure that the tests will protect you from breaking the code. But will they also help you and not hinder the development by slowing you down?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-silver-bullet.jpg&quot; alt=&quot;No silver bullet&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let’s see an example of how we could have written the tests by checking out the &lt;code class=&quot;highlighter-rouge&quot;&gt;messed_up_tests&lt;/code&gt; branch. If you run again &lt;code class=&quot;highlighter-rouge&quot;&gt;./gradlew pitest&lt;/code&gt; and check the mutation test coverage you’ll see that we have 100% coverage, but something tells me you wouldn’t want to maintain those tests (which I wrote just as a &lt;strong&gt;proof of concept&lt;/strong&gt;):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-example7-messed-up-tests.png&quot; alt=&quot;Example 7. Messed up tests&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-pyramid-of-software-quality&quot;&gt;The Pyramid of Software Quality&lt;/h2&gt;

&lt;p&gt;I have discovered that the &lt;strong&gt;software quality&lt;/strong&gt;, as the end user sees it, is highly influenced by a set of factors which I arranged into a &lt;strong&gt;pyramid of software quality&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-pyramid-of-software-quality.png&quot; alt=&quot;The Pyramid of Software Quality&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code quality influences software quality&lt;/strong&gt;&lt;br /&gt;
If the code is not maintainable then every change you make will break something else in the codebase. No change will be trivial. Every addition or modification to the code will require all the tangles, twists, and knots to be “understood”.&lt;/p&gt;

&lt;p&gt;The logic should be straightforward to make it hard for bugs to hide. &lt;strong&gt;C.A.R. Hoare&lt;/strong&gt; put it best, although it &lt;strong&gt;applies to everything, not just software design&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“There are two ways of constructing a software design. One way is to make it &lt;strong&gt;so simple that there are obviously no deficiencies&lt;/strong&gt;. And the other way is to make it &lt;strong&gt;so complicated that there are no obvious deficiencies&lt;/strong&gt;.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Test quality influences code quality&lt;/strong&gt;&lt;br /&gt;
If you want to keep the code quality high then you have to refactor often and you can’t do it if you don’t have tests or if they don’t cover the code you’re interested in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mutation testing influences test quality&lt;/strong&gt;&lt;br /&gt;
To have confidence that your tests will keep you from breaking the production code you need to have a high mutation test coverage. If you note, in this pyramid, I didn’t include “normal” test coverage because mutation test coverage is a stronger/better version of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Craftsman programmers influence everything&lt;/strong&gt;&lt;br /&gt;
Finally, craftsman programmers influence every aspect of software development: they increase software quality by improving both: the production code and the test code. It doesn’t matter if you have high mutation test coverage if you have flickering tests and/or they are unreadable and have a high maintenance cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Michael Feathers&lt;/strong&gt; put it best in this quote from the “Clean code” book by Robert C. Martin:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I could list all of the qualities that I notice in clean code, but there is one overarching quality that leads to all of them. Clean code always looks like it &lt;strong&gt;was written by someone who cares&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;mutation-testing-and-performance&quot;&gt;Mutation testing and performance&lt;/h2&gt;

&lt;p&gt;Mutation testing tools like pitest have to run the automated tests for each mutant they produce. This means that it will take quite a lot of time to run them compared to simply running the tests. Of course, good tools don’t run all the tests. They perform optimizations like running only the tests that execute the changed code based on the (normal) test coverage. This is very helpful and improves the performance quite a bit.&lt;/p&gt;

&lt;p&gt;However, there are still things that you can do to get the mutation test coverage faster. One of these is to write true unit tests like &lt;strong&gt;Michael Feathers&lt;/strong&gt; defines them:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A test is not a unit test if:&lt;br /&gt;
    - It talks to the database&lt;br /&gt;
    - It communicates across the network&lt;br /&gt;
    - It touches the file system&lt;br /&gt;
    - It can’t run at the same time as any of your other unit tests&lt;br /&gt;
    - You have to do special things to your environment (such as editing config files) to run it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another thing you can do is to make the tool gather the coverage just for the module you’re currently working on and to also limit the mutators used. In pitest you can do this by specifying the &lt;code class=&quot;highlighter-rouge&quot;&gt;targetClasses&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;targetTests&lt;/code&gt; and the &lt;code class=&quot;highlighter-rouge&quot;&gt;mutators&lt;/code&gt; in the &lt;code class=&quot;highlighter-rouge&quot;&gt;build.gradle&lt;/code&gt; script:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'com.gildedrose'&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pitest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;targetClasses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;${project.group}.GildedRose&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;targetTests&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;${project.group}.AllTests&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mutators&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ALL&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;coverage-and-quality-targets&quot;&gt;Coverage and quality targets&lt;/h2&gt;

&lt;p&gt;Don’t transform coverage (of any type: being it normal or mutation test coverage) into a target if you don’t want programmers to cheat it by writing the worst tests possible that will hinder the maintenance/development more than anything else. I showed you an example in the &lt;code class=&quot;highlighter-rouge&quot;&gt;messed_up_tests&lt;/code&gt; branch how bad can the tests be.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/mutation-testing-coverage-is-not-a-target.png&quot; alt=&quot;Coverage is not a target&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The only &lt;strong&gt;purpose&lt;/strong&gt; any coverage has is to help you &lt;strong&gt;find untested code&lt;/strong&gt; and to &lt;strong&gt;reduce risks&lt;/strong&gt; when improving the codebase.&lt;/p&gt;

&lt;h2 id=&quot;mutation-testing-tools&quot;&gt;Mutation testing tools&lt;/h2&gt;

&lt;p&gt;For some languages the tools aren’t that well developed. The highest quality tools &lt;strong&gt;seem&lt;/strong&gt; (haven’t tried all of them) to be for java, ruby and php. The .NET and python tools are quite limited.&lt;/p&gt;

&lt;p&gt;Other languages (like C/C++) don’t have any tools but this doesn’t mean you can’t write tests and before refactoring try them out by changing manually some lines and checking if the tests fail. That’s the least you can do in that case.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;java&lt;/strong&gt; there is &lt;a href=&quot;http://pitest.org&quot;&gt;pitest&lt;/a&gt;. There are others as well, but pitest seems the best considering the integration with build tools.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;ruby&lt;/strong&gt; you have &lt;a href=&quot;http://ruby.sadi.st/Heckle.html&quot;&gt;Heckle&lt;/a&gt; and &lt;a href=&quot;https://github.com/mbj/mutant&quot;&gt;Mutant&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;php&lt;/strong&gt; you can use &lt;a href=&quot;https://github.com/padraic/humbug&quot;&gt;Humbug&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;.NET&lt;/strong&gt; the tools are seriously limited so don’t be dissapointed:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://nester.sourceforge.net/&quot;&gt;Nester&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.mutation-testing.net/&quot;&gt;NinjaTurtles&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://galera.ii.pw.edu.pl/~adr/CREAM/&quot;&gt;CREAM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;strong&gt;python&lt;/strong&gt; there’s &lt;a href=&quot;http://jester.sourceforge.net/&quot;&gt;Pester&lt;/a&gt;. Don’t be surprised you see Java and JUnit - if you continue reading the page you’ll see links for pester too. Another (not very mature) tool for Python is &lt;a href=&quot;https://github.com/sk-/elcap&quot;&gt;elcap&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;more-on-improving-the-code&quot;&gt;More on improving the code&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.artima.com/weblogs/viewpost.jsp?thread=126923&quot;&gt;A Set of Unit Testing Rules by &lt;strong&gt;Michael Feathers&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.exampler.com/testing-com/writings/coverage.pdf&quot;&gt;How to Misuse Code Coverage by &lt;strong&gt;Brian Marick&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.agitar.com/downloads/TheWayOfTestivus.pdf&quot;&gt;The Way of Testivus by &lt;strong&gt;Alberto Savoia&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.james-carr.org/2006/11/03/tdd-anti-patterns&quot;&gt;Unit Testing Antipatterns by &lt;strong&gt;James Carr&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.planetgeek.ch/wp-content/uploads/2014/11/Clean-Code-V2.4.pdf&quot;&gt;Clean Code and TDD Cheat Sheet by &lt;strong&gt;Urs Enzler&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="mutation" />
      
        <category term="testing" />
      
        <category term="code" />
      
        <category term="quality" />
      
        <category term="coverage" />
      
        <category term="pyramid" />
      
        <category term="software" />
      

      
        <summary type="html">In this post you’ll learn the differences between mutation testing and code coverage by comparing several code examples and you’ll also receive practical advice on improving software quality.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Rocking with Jira’s Script Runner</title>
      
      
      <link href="https://igorpopov.io/2014/11/24/rocking-with-jira-script-runner/" rel="alternate" type="text/html" title="Rocking with Jira's Script Runner" />
      
      <published>2014-11-24T00:00:00+00:00</published>
      <updated>2014-11-24T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2014/11/24/rocking-with-jira-script-runner</id>
      <content type="html" xml:base="https://igorpopov.io/2014/11/24/rocking-with-jira-script-runner/">&lt;p&gt;In this post I will show you how to get up to speed with scripting in Jira. You
will learn how to develop scripts, test them and various tips and tricks on how
to develop in a productive way. I will show you a lot of examples and also
provide a separate git repository which you can clone and play with.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-logo.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I found out that there are &lt;strong&gt;a lot of great tools&lt;/strong&gt; out there, but there’s no
documentation on &lt;strong&gt;how to make them all work equally great together&lt;/strong&gt;. This
post aims to change that and show you how to use Jira, Jira’s API, the Script
Runner add-on, the Groovy language, the Gradle build system and the IntelliJ
IDEA IDE &lt;strong&gt;the best way possible&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;how-to-develop-your-scripts&quot;&gt;How to develop your scripts&lt;/h2&gt;

&lt;p&gt;Install &lt;em&gt;IntelliJ IDEA&lt;/em&gt; - the Community Edition which is &lt;em&gt;free to use&lt;/em&gt; and has
&lt;em&gt;built-in support for Groovy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Run &lt;code class=&quot;highlighter-rouge&quot;&gt;git clone https://github.com/igorpopovio/jira-scripting.git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Run &lt;code class=&quot;highlighter-rouge&quot;&gt;gradlew&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;./gradlew&lt;/code&gt; (depending on your operating system: Windows or
    Linux) to generate the IntelliJ IDEA projects… this will take a while
since it will download all the required libraries from Atlassian’s maven
repository.&lt;/p&gt;

&lt;p&gt;After the previous step finishes, open the &lt;code class=&quot;highlighter-rouge&quot;&gt;ipr&lt;/code&gt; file in IntelliJ IDEA then
open any script from the project and begin experimenting. When you finish
writing the script just copy paste it into the Script Runner Console and run
it.&lt;/p&gt;

&lt;h2 id=&quot;code-completion-with-intellij-idea&quot;&gt;Code completion with IntelliJ IDEA&lt;/h2&gt;

&lt;p&gt;After you generate and import the IntelliJ IDEA project you should get code
completion automatically when typing a variable and &lt;code class=&quot;highlighter-rouge&quot;&gt;.&lt;/code&gt; (dot). If the popup
doesn’t show up like in the image below then you can force it with &lt;code class=&quot;highlighter-rouge&quot;&gt;CTRL +
SPACE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-code-completion.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-to-test-your-scripts&quot;&gt;How to test your scripts&lt;/h2&gt;

&lt;p&gt;After you write your scripts you might want to test them on a test server just
to make sure you don’t mess up the production server… To set up a testing
server locally you need to install the &lt;em&gt;Atlassian SDK&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;After installing it you can start an instance of Jira from the command line:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;atlas-run-standalone --product jira
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You might also want to specify which version you want to start:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;atlas-run-standalone --product jira --version 6.3.10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You might want to grab a coffee or something since this command will take a bit
of time to download everything it needs.&lt;/p&gt;

&lt;p&gt;When the previous command finishes go to the URL printed in the command line
(should be &lt;code class=&quot;highlighter-rouge&quot;&gt;http://localhost:2990/jira&lt;/code&gt; or something similar). Login with
user/password: &lt;code class=&quot;highlighter-rouge&quot;&gt;admin/admin&lt;/code&gt; and &lt;em&gt;create a new demo project&lt;/em&gt; (see the next
    section). This project will already have some issues created so you can go
on directly to the testing part.&lt;/p&gt;

&lt;p&gt;Install the &lt;em&gt;Script Runner&lt;/em&gt; plugin from the &lt;em&gt;Atlassian Marketplace&lt;/em&gt; and go to
&lt;code class=&quot;highlighter-rouge&quot;&gt;Administration -&amp;gt; Add-ons -&amp;gt; Script Console&lt;/code&gt; (see the image below).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-where-to-paste-the-script.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;creating-a-test-project&quot;&gt;Creating a test project&lt;/h2&gt;

&lt;p&gt;Luckily, Atlassian made a demo project with several issues. Here’s how to
create it:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-create-new-project-1.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-create-new-project-2.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-build-script&quot;&gt;The build script&lt;/h2&gt;

&lt;p&gt;The build script is done in Gradle because it is much easier to use than other
tools: you don’t even need to have it installed. You just need to have the Java
Development Kit installed which I assume you have because you installed the
Atlassian SDK which requires it.&lt;/p&gt;

&lt;p&gt;The build script will download the &lt;code class=&quot;highlighter-rouge&quot;&gt;jira-core&lt;/code&gt; libraries from Atlassian’s maven
repository and will also generate the IntelliJ IDEA project which you’ll later
use. All that you have to change in this script is the Jira version:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;com.atlassian.jira:jira-core:&amp;lt;REPLACE WITH YOUR JIRA VERSION&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now run &lt;code class=&quot;highlighter-rouge&quot;&gt;gradlew&lt;/code&gt; from the command line to generate the project and then import
it in IntelliJ.&lt;/p&gt;

&lt;p&gt;Here is the full Gradle build script:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;plugin:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'groovy'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;plugin:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'idea'&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;defaultTasks&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'idea'&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;repositories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mavenCentral&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;maven&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'https://maven.atlassian.com/repository/public'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dependencies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'org.codehaus.groovy:groovy-all:2.3.6'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'com.atlassian.jira:jira-core:6.3.6'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;jiras-componentaccessor&quot;&gt;Jira’s &lt;code class=&quot;highlighter-rouge&quot;&gt;ComponentAccessor&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;To achieve anything when scripting for Jira you need some kind of manager for
the objects you want to change. Examples include (but are not limited) to:
ProjectManager, IssueManager, UserManager, PermissionManager, VersionManager,
  FieldManager, CommentManager, IssueEventManager and ServiceManager.&lt;/p&gt;

&lt;p&gt;You can access them easily by typing &lt;code class=&quot;highlighter-rouge&quot;&gt;ComponentAccessor.manager&lt;/code&gt; in IntelliJ
IDEA and select the one you need like in the image below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-component-accessor-managers.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Please note that only some of the managers appear as properties on
&lt;code class=&quot;highlighter-rouge&quot;&gt;ComponentAccessor&lt;/code&gt;. There are others as well which you can find about by
browsing the javadoc documentation.&lt;/p&gt;

&lt;p&gt;Here are some examples on how to get those managers (some of them, like the
    &lt;code class=&quot;highlighter-rouge&quot;&gt;SearchProvider&lt;/code&gt; don’t even have “manager” in their names):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issueManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;issueManager&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;jiraAuthenticationContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jqlQueryParser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JqlQueryParser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;searchProvider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SearchProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There are 2 ways of getting something. First you have some fields for the
really common stuff. For the uncommon stuff just use &lt;code class=&quot;highlighter-rouge&quot;&gt;getComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also please use the Groovy way instead of classical getters. Use &lt;em&gt;just the
property name&lt;/em&gt;: &lt;code class=&quot;highlighter-rouge&quot;&gt;ComponentAccessor.issueManager&lt;/code&gt;, not
&lt;code class=&quot;highlighter-rouge&quot;&gt;ComponentAccessor.getIssueManager()&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;now-why-would-you-need-that-componentaccessor&quot;&gt;Now, why would you need that &lt;code class=&quot;highlighter-rouge&quot;&gt;ComponentAccessor&lt;/code&gt;?&lt;/h2&gt;

&lt;p&gt;Let’s assume you need an &lt;code class=&quot;highlighter-rouge&quot;&gt;IssueManager&lt;/code&gt; - it is the most used one: how would
you get it?&lt;/p&gt;

&lt;p&gt;If you check the javadoc you would see that it is just an interface with 2
implementations: &lt;code class=&quot;highlighter-rouge&quot;&gt;DefaultIssueManager&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;MockIssueManager&lt;/code&gt;. The
&lt;code class=&quot;highlighter-rouge&quot;&gt;MockIssueManager&lt;/code&gt; is just a replacement class used in Atlassian’s unit tests,
  so we’re left with just one choice: the &lt;code class=&quot;highlighter-rouge&quot;&gt;DefaultIssueManager&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s see how we can create it… here is the constructor taken from the
javadoc:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;DefaultIssueManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OfBizDelegator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ofBizDelegator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WorkflowManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workflowManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NodeAssociationStore&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nodeAssociationStore&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserAssociationStore&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userAssociationStore&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IssueUpdater&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issueUpdater&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PermissionManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permissionManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MovedIssueKeyStore&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;movedIssueKeyStore&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProjectKeyStore&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;projectKeyStore&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To create that issue manager you would first need to create all the objects
given as a parameter and before doing that you’d need to create all the objects
that those objects need and so on…&lt;/p&gt;

&lt;p&gt;In case you’re wondering how Jira manages all those objects: they use an
&lt;em&gt;Inversion of Control&lt;/em&gt; container called &lt;em&gt;PicoContainer&lt;/em&gt;. You can Google it for
more information…&lt;/p&gt;

&lt;h2 id=&quot;finding-issues-using-jql&quot;&gt;Finding issues using JQL&lt;/h2&gt;

&lt;p&gt;Probably the most common thing you’d want to change in Jira is an issue. To get
hold of it you need to use the &lt;em&gt;Jira Query Language&lt;/em&gt; which is a kind of query
language designed for interrogating Jira about issues.&lt;/p&gt;

&lt;p&gt;I have written a groovy method that can return a list of issues based on a
query that you give as a parameter. After obtaining the list of issues you can
change them however you want.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findIssues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jqlQuery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issueManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;issueManager&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;jiraAuthenticationContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jqlQueryParser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JqlQueryParser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;searchProvider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SearchProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jqlQueryParser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;parseQuery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jqlQuery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;searchProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PagerFilter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;unlimitedFilter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;issues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;collect&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issueManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getIssueObject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;jqlQuery&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;project = DEMO and text ~ 'shortcut'&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logImportantMessage&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Executing query: &amp;lt;pre&amp;gt;${jqlQuery}&amp;lt;/pre&amp;gt;&quot;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issues&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findIssues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jqlQuery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;i-dont-know-jql-what-should-i-do&quot;&gt;I don’t know JQL! What should I do?&lt;/h2&gt;

&lt;p&gt;Well, you can always learn by example: first of all search the issues in Jira,
  switch to advanced mode and copy paste the JQL query. See the screenshots
  below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-jql-1.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-jql-2.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-jql-3.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Besides the copy paste you can always check Atlassian’s documentation on JQL
queries…&lt;/p&gt;

&lt;h2 id=&quot;jira-issue-objects&quot;&gt;Jira issue objects&lt;/h2&gt;

&lt;p&gt;IntelliJ IDEA gives you all the code completion suggestions but not all of them
are useful in Jira’s case - some of the methods are internal and shouldn’t be
touched (unless you know what you’re doing). I recommend you stick to the
methods that have &lt;code class=&quot;highlighter-rouge&quot;&gt;Object&lt;/code&gt; in name - these are the actual domain objects that
have all the properties easily accessible:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-use-objects.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;updating-issues&quot;&gt;Updating issues&lt;/h2&gt;

&lt;p&gt;Just changing the issue won’t actually update it in Jira’s internal database.
To do that you have multiple options. There doesn’t seems to be a standard way
of doing it, so I’ll just describe and provide examples for each method I
encountered.&lt;/p&gt;

&lt;p&gt;This initial example is using the manager for labels. There are managers for
pretty much everything in Jira - you just need to get it using the
&lt;code class=&quot;highlighter-rouge&quot;&gt;ComponentAccessor&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addLabelToIssue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MutableIssue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labelManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LabelManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;jiraAuthenticationContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;directoryUser&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sendEmailUpdates&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;labelManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sendEmailUpdates&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;addLabelToIssue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;productivity&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;jira-bulk-change-vs-script-runner&quot;&gt;Jira Bulk Change vs Script Runner&lt;/h2&gt;

&lt;p&gt;You can do almost the same thing using Jira’s Bulk Change with a single
exception: you cannot &lt;em&gt;append&lt;/em&gt; something to a list (of labels, of versions, of
    anything actually…). You can just overwrite the previous values which is
probably not what you expect… See the images below to get an idea…&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-bulk-change-overwrites.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The change that appears at &lt;code class=&quot;highlighter-rouge&quot;&gt;12 minutes ago&lt;/code&gt; was done using the Script Runner
and my example script… The change from &lt;code class=&quot;highlighter-rouge&quot;&gt;4 minutes ago&lt;/code&gt; was done using Bulk
Change… Note the difference: when using Bulk Change you lose the previous
values!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-script-vs-bulk-change.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;updating-issues-with-modifiedvalue&quot;&gt;Updating issues with &lt;code class=&quot;highlighter-rouge&quot;&gt;ModifiedValue&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;This is an example on how to add and update the fix versions. This way of
updating issues is very coupled to the field name, much like the previous
example. In the next section I’ll show a better and more general way of
updating.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addFixVersionToIssue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MutableIssue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Version&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixVersion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldFixVersions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fixVersions&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newFixVersions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldFixVersions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixVersion&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ModifiedValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;oldFixVersions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newFixVersions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fieldManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOrderableField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;fixVersions&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;updateValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DefaultIssueChangeHolder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fixVersions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newFixVersions&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getVersion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;projectKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;versionName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;versionManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;allVersions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;projectObject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;projectKey&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;versionName&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;projectKey&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DEMO&quot;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixVersionName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Version 1.0&quot;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixVersion&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getVersion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projectKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixVersionName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;addFixVersionToIssue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixVersion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;finding-out-dynamic-fields&quot;&gt;Finding out dynamic fields&lt;/h2&gt;

&lt;p&gt;In some cases you’ll need methods that receive field names or other similar
things. This is the case we had in the previous example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fieldManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOrderableField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;fixVersions&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;How were we supposed to know what we have to use &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;fixVersions&quot;&lt;/code&gt; as
parameter??? Well, you can use the Script Runner to help you find out the
&lt;code class=&quot;highlighter-rouge&quot;&gt;orderableFields&lt;/code&gt; like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-quick-documentation.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;better-way-to-update-issues&quot;&gt;Better way to update issues&lt;/h2&gt;

&lt;p&gt;This is the most general way to update something related to an issue. Normally
you should call it no matter what you update.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updateIssue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MutableIssue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;jiraAuthenticationContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issueManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;issueManager&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;issueManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;updateIssue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;createIssueUpdateRequest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createIssueUpdateRequest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UpdateIssueRequest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;UpdateIssueRequestBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;eventDispatchOption&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EventDispatchOption&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DO_NOT_DISPATCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sendMail&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;updateIssue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;indexing-updated-issues&quot;&gt;Indexing updated issues&lt;/h2&gt;

&lt;p&gt;This isn’t always required, but here’s how to do it anyway…&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;reindex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Collection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MutableIssue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issueIndexManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;issueIndexManager&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wasIndexing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ImportUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isIndexIssues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ImportUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setIndexIssues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;issues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issueIndexManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;reIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ImportUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setIndexIssues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wasIndexing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;reindex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;issues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;providing-feedback-on-the-results&quot;&gt;Providing feedback on the results&lt;/h2&gt;

&lt;p&gt;By default the logs will get buried somewhere in Jira’s logs and while it is
possible to go hunt them down it would be too much hassle. Instead you can
return a string from the script and the Script Runner will show it after
running your script. I made several methods that help with the logging -
basically just appending stuff to a string and finally returning it.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;finalMessage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;logMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;finalMessage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;${message}&amp;lt;br/&amp;gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;logImportantMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logMessage&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;strong&amp;gt;${message}&amp;lt;/strong&amp;gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finalMessage&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;finding-the-issue-links&quot;&gt;Finding the issue links&lt;/h2&gt;

&lt;p&gt;Although this is not required and doesn’t actually change anything in Jira, I
prefer to have it. Basically instead of getting just a list of issues that can
be updated you get a list where you can click on any issue and get more
details. It saves me from having to copy paste the issue key from the list to
the browser’s address bar.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getIssueLink&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MutableIssue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentAccessor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;applicationProperties&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jiraBaseUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;APKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;JIRA_BASEURL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;${jiraBaseUrl}/browse/${issue.key}&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;formatIssue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MutableIssue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issueLink&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getIssueLink&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;issue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;htmlLink&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;a href=\&quot;${issueLink}\&quot;&amp;gt;${issue.key}&amp;lt;/a&amp;gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;strong&amp;gt;${htmlLink}&amp;lt;/strong&amp;gt; - ${issue.summary}&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logImportantMessage&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Found ${issues.size()} issues. Here they are:&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logIssues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;issues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;script-results&quot;&gt;Script results&lt;/h2&gt;

&lt;p&gt;After running the script you should see the results in a nice format like in
the screen shot below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-script-result.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It can get even better: by using nicely styled tables from AUI (Atlassian User
    Interface):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocking-with-jira-script-runner-issue-table.png&quot; alt=&quot;Description&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can check the repository with examples and see how it’s done.&lt;/p&gt;

&lt;h2 id=&quot;how-can-i-do-thisthatwhatever&quot;&gt;How can I do &lt;code class=&quot;highlighter-rouge&quot;&gt;this/that/whatever&lt;/code&gt;?&lt;/h2&gt;

&lt;p&gt;From what I noticed, in Jira, there are quite a lot of managers and these are
available as directly accessible fields in the &lt;code class=&quot;highlighter-rouge&quot;&gt;ComponentAccessor&lt;/code&gt; class. I
would first look if there’s any manager that seems to have what I want  then
fumble up with IntelliJ IDEA’s code assistance and then look it up in Jira’s
javadoc. If that doesn’t work you could check &lt;em&gt;Atlassian Answers&lt;/em&gt; (either
    search or even ask questions) or Google.&lt;/p&gt;

&lt;h2 id=&quot;more-resources&quot;&gt;More resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.atlassian.com/display/DOCS/Getting+Started&quot;&gt;Atlassian SDK&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.jetbrains.com/idea&quot;&gt;IntelliJ IDEA&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://marketplace.atlassian.com/plugins/com.onresolve.jira.groovy.groovyrunner&quot;&gt;Script Runner plugin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://jamieechlin.atlassian.net/wiki/display/GRV/Script+Runner&quot;&gt;Script Runner documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.atlassian.com/display/JIRADEV/Java+API+Policy+for+JIRA&quot;&gt;The Java API policy for Jira&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.atlassian.com/display/DOCS/Atlassian+Maven+Repositories&quot;&gt;Atlassian maven repositories&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.atlassian.com/display/JIRADEV/Java+API+Reference&quot;&gt;Java API reference&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://confluence.atlassian.com/display/JIRA/Advanced+Searching&quot;&gt;Jira Query Language - JQL&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://answers.atlassian.com&quot;&gt;Atlassian Answers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="atlassian" />
      
        <category term="jira" />
      
        <category term="script-runner" />
      
        <category term="groovy" />
      

      
        <summary type="html">In this post I will show you how to get up to speed with scripting in Jira. You will learn how to develop scripts, test them and various tips and tricks on how to develop in a productive way. I will show you a lot of examples and also provide a separate git repository which you can clone and play with.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">7zip gotchas</title>
      
      
      <link href="https://igorpopov.io/2014/08/16/7zip-gotchas/" rel="alternate" type="text/html" title="7zip gotchas" />
      
      <published>2014-08-16T00:00:00+00:00</published>
      <updated>2014-08-16T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2014/08/16/7zip-gotchas</id>
      <content type="html" xml:base="https://igorpopov.io/2014/08/16/7zip-gotchas/">&lt;p&gt;This is going to be a short post about some &lt;strong&gt;gotchas&lt;/strong&gt; when archiving files with 7zip from the command line.&lt;/p&gt;

&lt;h2 id=&quot;archiving-files&quot;&gt;Archiving files&lt;/h2&gt;

&lt;p&gt;Let’s start from the following directory structure:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;files
|-- file1.txt
`-- file2.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s the simplest way to archive those files using 7zip:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;7z a archive.zip files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will create the following structure:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;archive.zip
`-- files
    |-- file1.txt
    `-- file2.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is fine, but what if you don’t want the &lt;code class=&quot;highlighter-rouge&quot;&gt;files&lt;/code&gt; top directory? Like in this example:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;archive.zip
|-- file1.txt
`-- file2.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this case you should use the following command:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;7z a archive.zip .\files\*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Slashes, the initial dot (current directory) and the final asterisk are required or else 7zip will fallback to archive everything including the top level directory.&lt;/p&gt;

&lt;h2 id=&quot;examples-repository&quot;&gt;Examples repository&lt;/h2&gt;

&lt;p&gt;I made a small PowerShell script that you can use to test the examples described in this post. Here’s &lt;a href=&quot;https://github.com/igorpopovio/7zip-usage-examples/blob/master/7zip-usage-examples.ps1&quot;&gt;the link&lt;/a&gt;.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="7zip" />
      
        <category term="archiving" />
      

      
        <summary type="html">This is going to be a short post about some gotchas when archiving files with 7zip from the command line.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Reducing boilerplate with Fody</title>
      
      
      <link href="https://igorpopov.io/2014/08/06/reducing-boilerplate-with-fody/" rel="alternate" type="text/html" title="Reducing boilerplate with Fody" />
      
      <published>2014-08-06T00:00:00+00:00</published>
      <updated>2014-08-06T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2014/08/06/reducing-boilerplate-with-fody</id>
      <content type="html" xml:base="https://igorpopov.io/2014/08/06/reducing-boilerplate-with-fody/">&lt;p&gt;This post is regarding reducing boilerplate code when implementing the MVVM pattern for WPF applications. One of the great things about MVVM is that you can bind properties to GUI elements and when you change one of them the other will update automatically. To get this to work you need to implement the &lt;code class=&quot;highlighter-rouge&quot;&gt;INotifyPropertyChanged&lt;/code&gt; interface.&lt;/p&gt;

&lt;h2 id=&quot;the-classic-way&quot;&gt;The classic way&lt;/h2&gt;

&lt;p&gt;Normally you’d create an &lt;code class=&quot;highlighter-rouge&quot;&gt;ObservableObject&lt;/code&gt; similar to this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ObservableObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INotifyPropertyChanged&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PropertyChangedEventHandler&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PropertyChanged&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnPropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;propertyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;PropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;PropertyChangedEventArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propertyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s say that you have an &lt;code class=&quot;highlighter-rouge&quot;&gt;Item&lt;/code&gt; class and you want to bind it’s properties to the GUI. Here’s the class:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ObservableObject&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Testing Item&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Just an item used for testing&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;OnPropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Description&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;OnPropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And here’s the GUI:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Window&lt;/span&gt;
        &lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;xmlns:src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;clr-namespace:MyApp&quot;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Window.DataContext&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;src:Item/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Window.DataContext&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;StackPanel&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Orientation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Vertical&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Name}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Description}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/StackPanel&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Window&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;When you want to use binding you cannot use automatic properties so you have to provide similar implementations for all of them. Add a private field, make the getter return it and the setter call the &lt;code class=&quot;highlighter-rouge&quot;&gt;OnPropertyChanged&lt;/code&gt; method from &lt;code class=&quot;highlighter-rouge&quot;&gt;ObservableObject&lt;/code&gt;. It’s not difficult, but &lt;strong&gt;it’s code that I don’t want to write and I don’t want to see&lt;/strong&gt; - because it’s code that has no (business) logic in it and it’s highly repetitive.&lt;/p&gt;

&lt;p&gt;Of course, you might argue that if I don’t want to see them then I could use those &lt;code class=&quot;highlighter-rouge&quot;&gt;#region&lt;/code&gt; directives, but I feel like I’m sweeping them under the carpet. It doesn’t really solve the problem. Some people (me being one of them) &lt;a href=&quot;http://programmers.stackexchange.com/a/53114/3704&quot;&gt;recommend that you shouldn’t use regions&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-fody-way&quot;&gt;The Fody way&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Fody/Fody&quot;&gt;Fody&lt;/a&gt; is a “tool for weaving .net assemblies”. Probably this short intro doesn’t tell you much so here’s my explanation: Fody adds new attributes (based on the plugins you use) that generate (Intermediate Language) code during the build. That IL code is code that you don’t see and you don’t write, but does the job. It’s basically eliminating boilerplate code - really similar code that you must always write that doesn’t achieve much.&lt;/p&gt;

&lt;h3 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h3&gt;

&lt;p&gt;In Visual Studio add the Nuget package for &lt;code class=&quot;highlighter-rouge&quot;&gt;PropertyChanged.Fody&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/fody-dot-net-nuget.png&quot; alt=&quot;Go to Nuget Package Manager&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/fody-dot-net-nuget-install.png&quot; alt=&quot;Install the PropertyChanged.Fody package&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After installing it just add the &lt;code class=&quot;highlighter-rouge&quot;&gt;[ImplementPropertyChanged]&lt;/code&gt; attribute and the automatic properties. Here’s the &lt;code class=&quot;highlighter-rouge&quot;&gt;Item&lt;/code&gt; class again:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ImplementPropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Testing Item&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Just an item used for testing&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I know that this isn’t much, but considering that in a normal project you can have a lot more properties this is pretty nice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classic way&lt;/strong&gt;: 10 lines for each property (braces included, spacing removed)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;OnPropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Fody way&lt;/strong&gt;: 1 line for each property (disregarding the attribute line, since it’s once per class)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This looks to me like a &lt;strong&gt;major win: 10 times less code!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before Fody I found out about &lt;a href=&quot;http://www.postsharp.net/&quot;&gt;PostSharp&lt;/a&gt; which seems to do the same thing (regarding &lt;code class=&quot;highlighter-rouge&quot;&gt;INotifyPropertyChanged&lt;/code&gt; - it also does a lot more), but they use the &lt;code class=&quot;highlighter-rouge&quot;&gt;NotifyPropertyChanged&lt;/code&gt; attribute instead.&lt;/p&gt;

&lt;p&gt;There are a lot of other cool plugins for Fody like: &lt;code class=&quot;highlighter-rouge&quot;&gt;Equals&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;ToString&lt;/code&gt; (among many others). It’s worth checking them out.&lt;/p&gt;

&lt;p&gt;The full code that I used for this blog post is available on GitHub:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/igorpopovio/FodyWithPropertyChanged/tree/82d1ab934e2867705709bc3a2109c4eb9063904f&quot;&gt;without Fody (classic way)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/igorpopovio/FodyWithPropertyChanged/tree/7768dfafb63c53b3174afc9915dd3ad69daab474&quot;&gt;with Fody&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="wpf" />
      
        <category term="inotifypropertychanged" />
      
        <category term="boilerplate" />
      
        <category term="fody" />
      

      
        <summary type="html">This post is regarding reducing boilerplate code when implementing the MVVM pattern for WPF applications. One of the great things about MVVM is that you can bind properties to GUI elements and when you change one of them the other will update automatically. To get this to work you need to implement the INotifyPropertyChanged interface.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Understanding Gradle</title>
      
      
      <link href="https://igorpopov.io/2014/05/01/understanding-gradle/" rel="alternate" type="text/html" title="Understanding Gradle" />
      
      <published>2014-05-01T00:00:00+00:00</published>
      <updated>2014-05-01T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2014/05/01/understanding-gradle</id>
      <content type="html" xml:base="https://igorpopov.io/2014/05/01/understanding-gradle/">&lt;p&gt;In this blog post I’ll review a bit how Gradle works behind the scenes and how
certain parts may seem magical if you don’t know Groovy. And, of course, I’ll
explain how that DSL magic works.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/understanding-gradle-nirvana.jpg&quot; alt=&quot;Gradle Nirvana&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When I started learning Gradle this was one of the major blockers in doing
something with it. If you don’t understand that magic then you’re limited to
the examples in the documentation which aren’t that revealing and don’t help
you when you have similar issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warning!&lt;/strong&gt; this blog post just tries to bring you closer to understanding
Gradle, but it’s not an exact overview of how Gradle works.&lt;/p&gt;

&lt;h1 id=&quot;gradle-basics&quot;&gt;Gradle basics&lt;/h1&gt;

&lt;p&gt;Let’s say that you have a fairly standard java project. You’ll need the JUnit
library, because, well, you do test your code, riiiight? We’ll add that as a
dependency for the test code.&lt;/p&gt;

&lt;p&gt;This is how the build script would look like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;plugin:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'java'&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;repositories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mavenCentral&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dependencies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;testCompile&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'junit:junit:4.11'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Basically, what’s happening here is that you add the java plugin that
automatically adds some defaults for building java projects.&lt;/p&gt;

&lt;p&gt;Then you configure the repositories that tell Gradle where to download it’s
dependencies from.&lt;/p&gt;

&lt;p&gt;After that you tell that in order to compile the tests you need an external
library that will be downloaded from the above defined repository.&lt;/p&gt;

&lt;h1 id=&quot;a-billion-gradle-questions-for-a-total-noob&quot;&gt;A billion Gradle questions for a total noob&lt;/h1&gt;

&lt;p&gt;Now, if you have a java background that syntax looks fairly alien. It seems
like a dedicated language for specifying builds. But how does it work? What is
&lt;code class=&quot;highlighter-rouge&quot;&gt;apply&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;repositories&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies&lt;/code&gt;? How do I know what’s available so
I can do my work? What’s that curly braces thing?! It looks like a code
block… What about that &lt;code class=&quot;highlighter-rouge&quot;&gt;testCompile&lt;/code&gt;? I don’t see where it is defined… I
don’t even know what it is and what I can do with it…&lt;/p&gt;

&lt;p&gt;I had all these questions initially and although I could create a basic Gradle
script I couldn’t undestand it or make it do something that wasn’t described in
the Gradle user guide.&lt;/p&gt;

&lt;h1 id=&quot;groovy-closures-and-gradle-nirvana&quot;&gt;Groovy closures and Gradle Nirvana&lt;/h1&gt;

&lt;p&gt;After reading the documentation, Gradle DSLs, the Gradle forums and lots of
Googling I achieved nirvana. That is: the Gradle nirvana.&lt;/p&gt;

&lt;p&gt;First, those &lt;code class=&quot;highlighter-rouge&quot;&gt;apply&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;repositories&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies&lt;/code&gt; thingys are just
normal methods. You may ask: “Wooaah! Methods! But if they are methods then
they must belong to an object, right?” Yes, they are defined in the &lt;a href=&quot;http://www.gradle.org/docs/current/dsl/org.gradle.api.Project.html&quot;&gt;Project
class&lt;/a&gt;.
Once you know this, more things start to get clearer. Now if there’s something
you don’t understand you can look it up in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Project&lt;/code&gt; class documentation:
method definition, etc.&lt;/p&gt;

&lt;p&gt;Now, the way you call these methods may seem a bit strange. For example, what
is that curly brace thing? It’s a Groovy closure! It’s something like an
anonymous method that can be passed as a parameter to other methods. It’s
actually implemented as an anonymous java class with just one method.&lt;/p&gt;

&lt;p&gt;Here’s how to make that &lt;code class=&quot;highlighter-rouge&quot;&gt;testCompile&lt;/code&gt; thing - add the following code to
&lt;code class=&quot;highlighter-rouge&quot;&gt;build.gradle&lt;/code&gt; and run it with &lt;code class=&quot;highlighter-rouge&quot;&gt;./gradle -q&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DependencySpec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testCompile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;libraryIdentifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Adding the $libraryIdentifier library...&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dependencies2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Closure&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configurationClosure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dependencySpec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DependencySpec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;configurationClosure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dependencySpec&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;configurationClosure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;resolveStrategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Closure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DELEGATE_FIRST&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;configurationClosure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dependencies2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;testCompile&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'junit:junit:4.11'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ok, so I’ll take you through all the above code, since it’s quite a lot to take
at once. First, I used &lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies2&lt;/code&gt; so my code doesn’t conflict with what’s
already provided in Gradle and it shouldn’t affect your understanding anyway
:).&lt;/p&gt;

&lt;p&gt;Then, the &lt;code class=&quot;highlighter-rouge&quot;&gt;DependencySpec&lt;/code&gt; class and the &lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies2&lt;/code&gt; method are present in
the &lt;code class=&quot;highlighter-rouge&quot;&gt;build.gradle&lt;/code&gt; script, but the &lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies&lt;/code&gt; method (from Gradle) is
available in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Project&lt;/code&gt; class which is compiled and put in the class path of
the build script. So, all that’s left for you to see is only the &lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies&lt;/code&gt;
method call, which seems kind of magical if you don’t know how it’s
implemented.&lt;/p&gt;

&lt;p&gt;I left the supporting code in the same script so you can see and understand how
everything works.&lt;/p&gt;

&lt;p&gt;Let’s start from the &lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies2&lt;/code&gt; method call:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;dependencies2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;testCompile&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'junit:junit:4.11'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It may not seem a method call, since in java you have to put parenthesis like
this: &lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies2( /* method arguments */ )&lt;/code&gt;. Well, in Groovy (which Gradle
    builds on top), the parenthesis are optional if you have at least one
argument (if there’s no argument you &lt;strong&gt;MUST&lt;/strong&gt; use them).&lt;/p&gt;

&lt;p&gt;Now, things get confusing again: there are no arguments for the &lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies2&lt;/code&gt;
method call (or so it seems). And again, that certainly doesn’t look like a
method call! How can a method &lt;strong&gt;call&lt;/strong&gt; have a “definition code block”?!&lt;/p&gt;

&lt;p&gt;Well, let’s rewrite that section of the code without using Groovy
magic/syntactic sugar so it’s a bit more clear.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;Closure&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configurationClosure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;testCompile&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'junit:junit:4.11'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;dependencies2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;configurationClosure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now you can clearly see that we have a method call. What about the
&lt;code class=&quot;highlighter-rouge&quot;&gt;testCompile&lt;/code&gt;? Well, that’s a method call too. Just add the paranthesis and
everything becomes clear again: &lt;code class=&quot;highlighter-rouge&quot;&gt;testCompile('junit:junit:4.11')&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, to understand how it’s possible to call the &lt;code class=&quot;highlighter-rouge&quot;&gt;testCompile&lt;/code&gt; method even
though it’s in another class let’s review the first part:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DependencySpec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testCompile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;libraryIdentifier&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;println&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Adding the $libraryIdentifier library...&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;First, you define a new Groovy class that has the code you need, &lt;code class=&quot;highlighter-rouge&quot;&gt;testCompile&lt;/code&gt;
in our case. Then you define a new &lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies2&lt;/code&gt; method that receives a
closure as an argument.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dependencies2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Closure&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configurationClosure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dependencySpec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DependencySpec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;configurationClosure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dependencySpec&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;configurationClosure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;resolveStrategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Closure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DELEGATE_FIRST&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;configurationClosure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now you need to understand one cool thing about closures: you can “delegate”
method calls that are not defined in them to an object. In our case this object
is of type: &lt;code class=&quot;highlighter-rouge&quot;&gt;DependencySpec&lt;/code&gt;. So this means that when you call a method in the
configuration closure it will be “forwarded” to a &lt;code class=&quot;highlighter-rouge&quot;&gt;DependencySpec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To achieve this you have to set the closure’s &lt;code class=&quot;highlighter-rouge&quot;&gt;delegate&lt;/code&gt; to our object &lt;strong&gt;AND&lt;/strong&gt;
set the &lt;code class=&quot;highlighter-rouge&quot;&gt;resolveStrategy&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;Closure.DELEGATE_FIRST&lt;/code&gt; so Groovy/Gradle knows
that it should first look for any undefined thingy in our own object.&lt;/p&gt;

&lt;p&gt;The Groovy closures practically hold the (Gradle) Universe together. They are
the key to understanding Gradle and getting to a productive level with it.&lt;/p&gt;

&lt;p&gt;You can read more about &lt;a href=&quot;http://groovy.codehaus.org/Closures&quot;&gt;Groovy closures&lt;/a&gt;
to get a better understanding.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="groovy" />
      
        <category term="gradle" />
      
        <category term="closure" />
      

      
        <summary type="html">In this blog post I’ll review a bit how Gradle works behind the scenes and how certain parts may seem magical if you don’t know Groovy. And, of course, I’ll explain how that DSL magic works.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Artifactory, Gradle and publishing</title>
      
      
      <link href="https://igorpopov.io/2014/04/27/artifactory-gradle-and-publishing/" rel="alternate" type="text/html" title="Artifactory, Gradle and publishing" />
      
      <published>2014-04-27T00:00:00+00:00</published>
      <updated>2014-04-27T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2014/04/27/artifactory-gradle-and-publishing</id>
      <content type="html" xml:base="https://igorpopov.io/2014/04/27/artifactory-gradle-and-publishing/">&lt;p&gt;In this post I’ll show you how to setup Artifactory from scratch and how to
publish a jar from gradle.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/artifactory-gradle-publishing.jpg&quot; alt=&quot;Conveyor belt packets&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;downloading-and-running&quot;&gt;Downloading and running&lt;/h1&gt;

&lt;p&gt;Go to &lt;a href=&quot;http://www.jfrog.com/home/v_artifactory_opensource_download&quot;&gt;JFrog’s Artifactory download
page&lt;/a&gt; and get the
zip archive. Extract it somewhere and then start &lt;code class=&quot;highlighter-rouge&quot;&gt;bin/artifactory.sh&lt;/code&gt; (or
    &lt;code class=&quot;highlighter-rouge&quot;&gt;bin/artifactory.bat&lt;/code&gt; in case you’re using Windows).&lt;/p&gt;

&lt;p&gt;You should now be able to access Artifactory at: &lt;code class=&quot;highlighter-rouge&quot;&gt;http://localhost:8081/artifactory&lt;/code&gt;.
The default credentials are: &lt;code class=&quot;highlighter-rouge&quot;&gt;admin/password&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;creating-a-java-project-with-gradle&quot;&gt;Creating a java project with gradle&lt;/h1&gt;

&lt;p&gt;Gradle is a build tool for java projects. It’s more powerful than maven and
ant. We’ll use it to create a very simple java project. But first you need to
download the latest version and add it to your &lt;code class=&quot;highlighter-rouge&quot;&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After you got gradle, run these commands from the command line:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir gradle-artifactory-publishing
cd gradle-artifactory-publishing
gradle init --type java-library
gradlew build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you should have a fully functional java project.&lt;/p&gt;

&lt;h1 id=&quot;using-artifactory&quot;&gt;Using Artifactory&lt;/h1&gt;

&lt;p&gt;After running &lt;code class=&quot;highlighter-rouge&quot;&gt;gradle init --type java-library&lt;/code&gt; you get to use the central
maven repository. Let’s change the build to use our own Artifactory.&lt;/p&gt;

&lt;p&gt;The default (in case you don’t use any custom maven server) is:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;repositories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mavenCentral&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We need to change this to:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;repositories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;maven&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'http://localhost:8081/artifactory/repo'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In case you’re wondering where does that &lt;code class=&quot;highlighter-rouge&quot;&gt;repo&lt;/code&gt; at the end of the URL come
from: it’s &lt;a href=&quot;http://www.jfrog.com/confluence/display/RTF/Virtual+Repositories&quot;&gt;the default virtual
repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Quote from their documentation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Artifactory defines a default global virtual repository which effectively
aggregates all other repositories at the following URL:
&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;host&amp;gt;:&amp;lt;port&amp;gt;/artifactory/repo&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;By configuring Maven with this URL, any request for an artifact will go through
Artifactory which will search through all of the local and remote repositories
defined in the system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;publishing-artifacts&quot;&gt;Publishing artifacts&lt;/h1&gt;

&lt;p&gt;Most of the times you need to publish a library to your Artifactory server.
Let’s see how we can achieve this using gradle.&lt;/p&gt;

&lt;p&gt;Apply &lt;a href=&quot;http://www.gradle.org/docs/current/userguide/publishing_maven.html&quot;&gt;the new maven publishing
plugin&lt;/a&gt;:
&lt;code class=&quot;highlighter-rouge&quot;&gt;apply plugin: 'maven-publish'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next configure what you want to publish and where:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'io.igorpopov'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'1.0'&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;publishing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;publications&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mavenJava&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MavenPublication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;java&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;repositories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;maven&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;credentials&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'admin'&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'password'&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://localhost:8081/artifactory/libs-release-local&quot;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here’s the output you should get:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ➜  ./gradlew publish
:generatePomFileForMavenJavaPublication
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:publishMavenJavaPublicationToMavenRepository
Uploading: io/igorpopov/gradle-artifactory-publishing/1.0/gradle-artifactory-publishing-1.0.jar to repository remote at http://localhost:8081/artifactory/libs-release-local
Transferring 1K from remote
Uploaded 1K
:publish

BUILD SUCCESSFUL

Total time: 5.472 secs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s review the most important parts of the publication. You need to have the
three maven standard identifiers for a library:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the &lt;code class=&quot;highlighter-rouge&quot;&gt;groupId&lt;/code&gt; (&lt;code class=&quot;highlighter-rouge&quot;&gt;group&lt;/code&gt; in gradle)&lt;/li&gt;
  &lt;li&gt;the &lt;code class=&quot;highlighter-rouge&quot;&gt;artifactId&lt;/code&gt; (&lt;code class=&quot;highlighter-rouge&quot;&gt;name&lt;/code&gt; in gradle)&lt;/li&gt;
  &lt;li&gt;the &lt;code class=&quot;highlighter-rouge&quot;&gt;version&lt;/code&gt; (same in gradle)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next most important is the &lt;code class=&quot;highlighter-rouge&quot;&gt;publishing&lt;/code&gt; gradle closure that defines exactly
what we want to publish:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;publishing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;publications&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mavenJava&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MavenPublication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;java&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;mavenJava(MavenPublication)&lt;/code&gt; can be changed to reflect the name of your
library. You could for example use: &lt;code class=&quot;highlighter-rouge&quot;&gt;mylibrary(MavenPublication)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, you need to specify what files you want to publish (the &lt;code class=&quot;highlighter-rouge&quot;&gt;from&lt;/code&gt; part).
You should probably check the &lt;a href=&quot;http://www.gradle.org/docs/current/dsl/org.gradle.api.publish.maven.MavenPublication.html&quot;&gt;gradle documentation for publishing to
maven&lt;/a&gt;
for full details and examples.&lt;/p&gt;

&lt;p&gt;You also need to tell gradle &lt;strong&gt;where&lt;/strong&gt; you want to publish your artifact. For
this we need to review what type of repositories Artifactory provides us:
local, remote and virtual.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local repositories&lt;/strong&gt; are physical, locally-managed repositories into which
&lt;strong&gt;you can deploy artifacts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remote repositories&lt;/strong&gt; serve as a &lt;strong&gt;caching proxy&lt;/strong&gt; for other repositories.
Artifactory is deployed with a number of pre-configured, remote repositories
which are in common use, but &lt;strong&gt;you can add new repositories&lt;/strong&gt; based on your
needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Virtual repositories&lt;/strong&gt; aggregate several repositories under a common URL.
The repository is virtual in that &lt;strong&gt;you can resolve and retrieve artifacts from
it&lt;/strong&gt; but &lt;strong&gt;you cannot deploy artifacts to it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This means that &lt;strong&gt;you cannot use the default virtual repository&lt;/strong&gt;
(&lt;code class=&quot;highlighter-rouge&quot;&gt;http://localhost:8081/artifactory/repo&lt;/code&gt;) to deploy artifacts (or any other
virtual repository for that matter).&lt;/p&gt;

&lt;p&gt;For this reason &lt;strong&gt;you must use one of the local repositories&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/local-artifactory-repositories.png&quot; alt=&quot;Local Artifactory repositories&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For full details you can check &lt;a href=&quot;https://www.jfrog.com/confluence/display/RTF/Configuring+Repositories&quot;&gt;Artifactory’s documentation on
repositories&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s how to configure gradle to use the snapshots repository when you have
&lt;code class=&quot;highlighter-rouge&quot;&gt;SNAPSHOT&lt;/code&gt; versions:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'io.igorpopov'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'1.0-SNAPSHOT'&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;publishing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;publications&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;repositories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;maven&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;credentials&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;endsWith&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'-SNAPSHOT'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://localhost:8081/artifactory/libs-snapshot-local&quot;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://localhost:8081/artifactory/libs-release-local&quot;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;debugging&quot;&gt;Debugging&lt;/h1&gt;

&lt;p&gt;In case something goes wrong and you want to follow more closely what is
happening you can use these simple tricks:&lt;/p&gt;

&lt;h2 id=&quot;gradle-info&quot;&gt;Gradle Info&lt;/h2&gt;

&lt;p&gt;Use &lt;code class=&quot;highlighter-rouge&quot;&gt;./gradlew build --info&lt;/code&gt; to get the download URLs for each jar dependency.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// the important part of the logs
:compileJava
Download http://localhost:8081/artifactory/repo/org/slf4j/slf4j-api/1.7.5/slf4j-api-1.7.5.pom
Download http://localhost:8081/artifactory/repo/org/slf4j/slf4j-parent/1.7.5/slf4j-parent-1.7.5.pom
Resource missing. [HTTP HEAD: http://localhost:8081/artifactory/repo/org/slf4j/slf4j-parent/1.7.5/slf4j-parent-1.7.5.jar]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Resource missing&lt;/code&gt; you get above might be an issue and it can be further
investigated. These kind of issues are pretty hidden and you need to use the
&lt;code class=&quot;highlighter-rouge&quot;&gt;--info&lt;/code&gt; flag to find them. Left unfixed, these issues can lead over time to a
greatly increased build time.&lt;/p&gt;

&lt;h2 id=&quot;artifactory-trace&quot;&gt;Artifactory trace&lt;/h2&gt;

&lt;p&gt;Take the URL that gives “resource missing” from the previous step, paste it in
your browser and append: &lt;code class=&quot;highlighter-rouge&quot;&gt;?trace&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://localhost:8081/artifactory/repo/org/slf4j/slf4j-parent/1.7.5/slf4j-parent-1.7.5.jar?trace
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will show a page with Artifactory’s full log of what happens when it tries
to get that dependency: what repositories it tries first, does it find the
dependency in one of the local repositories or does it fetch it from some
remote repositories? This can be very useful when debugging why some dependency
is not found or when you have performance issues.&lt;/p&gt;

&lt;p&gt;You can check &lt;a href=&quot;http://www.jfrog.com/confluence/display/RTF/Artifactory+REST+API#ArtifactoryRESTAPI-TraceArtifactRetrieval&quot;&gt;Artifactory’s documentation on this
topic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This should be enough to get you up and running with Gradle, Artifactory and
publishing new artifacts.&lt;/p&gt;

&lt;h1 id=&quot;considerations&quot;&gt;Considerations&lt;/h1&gt;

&lt;p&gt;This blog post just shows the basics how to get started with Gradle,
     Artifactory and publishing. When taken into production use you obviously
     need to change the default users and to install Artifactory as a service
     (not just start it from the command line like I did in this blog post).
     You also need to define the security permissions and inclusion and
     exclusions rules for artifact repositories.&lt;/p&gt;

&lt;p&gt;You should check Artifactory’s documentation to know exactly what to configure
and where to be careful regarding the security.&lt;/p&gt;

&lt;h1 id=&quot;resources&quot;&gt;Resources&lt;/h1&gt;

&lt;p&gt;You can find the full example project on GitHub and the documentation I used to
learn these things.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/igorpopovio/gradle-artifactory-publishing&quot;&gt;Full example on Github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.jfrog.com/confluence/display/RTF/Configuring+Repositories&quot;&gt;Configuring repositories&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.jfrog.com/confluence/display/RTF/Virtual+Repositories&quot;&gt;What are virtual repositories?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.gradle.org/docs/current/userguide/publishing_maven.html&quot;&gt;Publishing artifacts from Gradle&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.gradle.org/docs/current/dsl/org.gradle.api.publish.maven.MavenPublication.html&quot;&gt;More details on how to publish artifacts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="artifactory" />
      
        <category term="gradle" />
      
        <category term="maven" />
      
        <category term="publish" />
      

      
        <summary type="html">In this post I’ll show you how to setup Artifactory from scratch and how to publish a jar from gradle.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">WPF - From Zero to Hero - Part II</title>
      
      
      <link href="https://igorpopov.io/2014/03/08/wpf-from-zero-to-hero-part-2/" rel="alternate" type="text/html" title="WPF - From Zero to Hero - Part II" />
      
      <published>2014-03-08T00:00:00+00:00</published>
      <updated>2014-03-08T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2014/03/08/wpf-from-zero-to-hero-part-2</id>
      <content type="html" xml:base="https://igorpopov.io/2014/03/08/wpf-from-zero-to-hero-part-2/">&lt;p&gt;In the previous post I just looked at some examples and started banging code. I
learned quite a lot of stuff. Now I’ll learn how to use the MVVM pattern. This
pattern was first introduced by Martin Fowler and then adopted by Microsoft as
part of the WPF framework.&lt;/p&gt;

&lt;p&gt;This pattern is used to separate the business logic from the gui logic. So in
this case you’ll have a data model, which deals only with the business logic,
     and a view model, which deals only with display logic, for example
     formatting and getting the data from the data model into the user
     interface.&lt;/p&gt;

&lt;h2 id=&quot;inotifypropertychanged&quot;&gt;INotifyPropertyChanged&lt;/h2&gt;

&lt;p&gt;The most important things are using data binding and implementing the
&lt;code class=&quot;highlighter-rouge&quot;&gt;INotifyPropertyChanged&lt;/code&gt; interface or using the &lt;code class=&quot;highlighter-rouge&quot;&gt;ObservableCollection&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I saw that Telerik, in their examples, have extracted this in a separate class
called &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModelBase&lt;/code&gt;. This class is only available if you’re using Telerik
which doesn’t apply in this case. I thought that I would extract my own, but I
didn’t quite like the name. It’s not very consistent with what WPF offers. So,
  we have an &lt;code class=&quot;highlighter-rouge&quot;&gt;ObservableCollection&lt;/code&gt; already available in WPF… what would be a
  proper name for just one object? It still needs to be “observable”… Maybe
  &lt;code class=&quot;highlighter-rouge&quot;&gt;ObservableObject&lt;/code&gt;? Actually I was quite surprised it’s not already provided
  by WPF…&lt;/p&gt;

&lt;p&gt;Here’s the code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ObservableObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INotifyPropertyChanged&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PropertyChangedEventHandler&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PropertyChanged&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RaiseOnPropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;propertyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;PropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;PropertyChangedEventArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propertyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;the-viewmodel&quot;&gt;The ViewModel&lt;/h2&gt;

&lt;p&gt;The next thing is the &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; which needs to extend the &lt;code class=&quot;highlighter-rouge&quot;&gt;ObservableObject&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;DiagnoseTry2_WithMvc&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ViewModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ObservableObject&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Message&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;nf&quot;&gt;RaiseOnPropertyChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// other code&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here’s how we connect the &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; to the view:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Window&lt;/span&gt; 
        &lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;xmlns:src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;clr-namespace:DiagnoseTry2_WithMvc&quot;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Window.DataContext&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;src:ViewModel/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Window.DataContext&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Window&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;When someone updates the &lt;code class=&quot;highlighter-rouge&quot;&gt;Message&lt;/code&gt; property, the subscribers (in this case the
    View: &lt;code class=&quot;highlighter-rouge&quot;&gt;MainWindow.xaml&lt;/code&gt;) will be notified using the
&lt;code class=&quot;highlighter-rouge&quot;&gt;RaiseOnPropertyChanged()&lt;/code&gt; method. You may wonder who sets those subscribers,
  since we didn’t do it anywhere… Well, in fact we did it using data binding
  on this line:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Message}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I won’t go into details on how the &lt;code class=&quot;highlighter-rouge&quot;&gt;Items&lt;/code&gt; are implemented since they are very
similar to the normal &lt;code class=&quot;highlighter-rouge&quot;&gt;Message&lt;/code&gt;. The only differences are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Items&lt;/code&gt; is an &lt;code class=&quot;highlighter-rouge&quot;&gt;ObservableCollection&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Item&lt;/code&gt; should be an &lt;code class=&quot;highlighter-rouge&quot;&gt;ObservableObject&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;the binding is done like this:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;ListBox&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;ItemsSource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Items}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The next step is to actually show something in the GUI. For this we just add
some items in the constructor. I know this is not the normal way, but I prefer
using simpler methods while I’m learning till I get all the moving parts.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Items&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ObservableCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;first item name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;first item description&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;second item name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;second item description&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Message&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;There are &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Count&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; items&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;resources&quot;&gt;Resources&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/sensui/DiagnoseTry2-WithMvc&quot;&gt;my laughable attempts on GitHub&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial&quot;&gt;an extremely helpful tutorial on CodeProject by Barry Lapthorn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="WPF" />
      
        <category term="Visual Studio" />
      
        <category term="C#" />
      

      
        <summary type="html">In the previous post I just looked at some examples and started banging code. I learned quite a lot of stuff. Now I’ll learn how to use the MVVM pattern. This pattern was first introduced by Martin Fowler and then adopted by Microsoft as part of the WPF framework.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Boolean Logic</title>
      
      
      <link href="https://igorpopov.io/2014/02/17/boolean-logic/" rel="alternate" type="text/html" title="Boolean Logic" />
      
      <published>2014-02-17T00:00:00+00:00</published>
      <updated>2014-02-17T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2014/02/17/boolean-logic</id>
      <content type="html" xml:base="https://igorpopov.io/2014/02/17/boolean-logic/">&lt;p&gt;&lt;img src=&quot;/images/boolean-logic-less-code-matters.png&quot; alt=&quot;Less code matters&quot; /&gt;&lt;/p&gt;

&lt;p&gt;While learning WPF I encountered &lt;a href=&quot;http://code.msdn.microsoft.com/windowsdesktop/Data-Binding-Demo-82a17c83/sourcecode?fileId=17219&amp;amp;pathId=822232916&quot;&gt;this example on Microsoft’s
website&lt;/a&gt;.
You can either scroll down or download the C# version of the code.&lt;/p&gt;

&lt;p&gt;It’s about this code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// MainWindow.xaml.cs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ShowOnlyBargainsFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FilterEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;AuctionItem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuctionItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Filter out products with price 25 or above&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CurrentPrice&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Accepted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Accepted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The entire inner if statement can be reduced to:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Accepted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CurrentPrice&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This reads very well in &lt;em&gt;plain english&lt;/em&gt; (unlike the original version which is
    also longer):&lt;br /&gt;
“&lt;em&gt;accepted means that the product’s current price is smaller than 25&lt;/em&gt;”.&lt;/p&gt;

&lt;p&gt;Actually, the whole method can be rewritten as:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// MainWindow.xaml.cs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ShowOnlyBargainsFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FilterEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;AuctionItem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuctionItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Accepted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CurrentPrice&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is only 5 lines of code, unlike the original version which is 16 lines of
code, 11 lines of code waste! The final is &lt;em&gt;just one third&lt;/em&gt;! Imagine if this
would be happening in a real project!&lt;/p&gt;

&lt;p&gt;I really hate when people don’t understand boolean logic and write billions of
lines of code that others have to read and maintain!&lt;/p&gt;

&lt;p&gt;Regarding the example above: I would go even further. If we look at the method
name we see that it shows &lt;em&gt;bargains&lt;/em&gt;. This concept can be expressed more
clearly in the code by creating a function &lt;code class=&quot;highlighter-rouge&quot;&gt;isBargain&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;AuctionItem&lt;/code&gt;.&lt;br /&gt;
This is called the &lt;a href=&quot;http://martinfowler.com/bliki/TellDontAsk.html&quot;&gt;&lt;em&gt;tell, don’t ask! principle&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s how I would do it:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// MainWindow.xaml.cs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ShowOnlyBargainsFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FilterEventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;AuctionItem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuctionItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Accepted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;IsBargain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// AuctionItem.cs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;IsBargain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CurrentPrice&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This type of logic should be in the &lt;em&gt;domain model&lt;/em&gt;, not in the user interface as
it was in the original code.&lt;/p&gt;

&lt;h1 id=&quot;dealing-with-boolean-expressions&quot;&gt;Dealing with boolean expressions&lt;/h1&gt;

&lt;p&gt;Here are some of the bad examples I encountered and how you can correct them.
The examples are in java, but it shouldn’t matter.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://programmers.stackexchange.com/a/12828/3704&quot;&gt;&lt;em&gt;Don’t compare a boolean with true!&lt;/em&gt;&lt;/a&gt; It is already true!&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// bad way&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;something&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doThis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// good way&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doThis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// even better: rename the boolean so it reads like English&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isSomething&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doThis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// good examples: isBargain, isValid, isFile, exists, shouldReceiveBonus&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Same goes for false:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// bad way&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;something&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// good way&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Other programmers have an urge to check the boolean when returning from a function.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// bad way&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// good way&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Some other programmers use the ternary operator:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// bad way&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userDisabled&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// good way&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userDisabled&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And finally: don’t &lt;em&gt;EVER&lt;/em&gt; use booleans as parameters to a function. This
violates the &lt;a href=&quot;http://www.codinghorror.com/blog/2007/03/curlys-law-do-one-thing.html&quot;&gt;Single Responsibility
Principle&lt;/a&gt;.
If you need a boolean parameter you are doing &lt;em&gt;2 things&lt;/em&gt;: one for true and the
other for false. If you didn’t know about the Single Responsibility Principle,
      maybe you should check the full stack which is called the &lt;a href=&quot;https://en.wikipedia.org/wiki/SOLID&quot;&gt;&lt;em&gt;SOLID
      principles&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// bad way&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;setVisible&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;setVisible&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// good way&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// other good examples: enable/disable, switchOn/switchOff&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;tips-and-tricks&quot;&gt;Tips and Tricks&lt;/h1&gt;

&lt;p&gt;How can you avoid writing code as in the original example? Well, here are some
tips:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://sourcemaking.com/refactoring/replace-nested-conditional-with-guard-clauses&quot;&gt;use guard
clauses&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.codinghorror.com/blog/2006/12/code-tells-you-how-comments-tell-you-why.html&quot;&gt;remove stupid comments that just repeat code&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://programmers.stackexchange.com/q/199939/3704&quot;&gt;remember that the “stuff” you put between parens is a boolean expression and
that you can assign it directly to a variable…&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/q/359732/354009&quot;&gt;remove all those stupid brackets when you have single statements. And you
SHOULD always have only one statement (extract functions for each branch)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;the-moral-of-the-story&quot;&gt;The moral of the story&lt;/h1&gt;

&lt;p&gt;The C# code I showed in the beginning of the article is an example, a demo…
no wonder why new programmers (and not only) write &lt;em&gt;shitty code&lt;/em&gt;! When they start
learning a new technology they only see &lt;em&gt;piles of crap all over the Internet&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So, one moral is for software professionals to be more careful what type of
code they use as examples (unlike Microsoft in this case).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What type of code YOU want to promote?&lt;/em&gt;
Don’t forget that it always backfires and you end up working with people that
will write the same kind of code.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="C#" />
      
        <category term="boolean" />
      
        <category term="logic" />
      
        <category term="refactoring" />
      
        <category term="clean code" />
      

      
        <summary type="html"></summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">WPF - From Zero to Hero - Part I</title>
      
      
      <link href="https://igorpopov.io/2014/02/15/wpf-from-zero-to-hero-part-1/" rel="alternate" type="text/html" title="WPF - From Zero to Hero - Part I" />
      
      <published>2014-02-15T00:00:00+00:00</published>
      <updated>2014-02-15T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2014/02/15/wpf-from-zero-to-hero-part-1</id>
      <content type="html" xml:base="https://igorpopov.io/2014/02/15/wpf-from-zero-to-hero-part-1/">&lt;p&gt;I’d like to learn WPF to create a tiny application (something like a TODO list
    application). This is my first time ever touching Microsoft technologies.
That’s why I will document all the steps I take while learning.&lt;/p&gt;

&lt;p&gt;Let’s begin… The first thing I need is Visual Studio. After a quick search on
google I found &lt;a href=&quot;http://www.microsoft.com/en-us/download/details.aspx?id=40787&quot;&gt;Microsoft Visual Studio Express for Windows
Desktop&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the GUI I want to end up with:
&lt;img src=&quot;/images/wpf-from-zero-to-hero-gui-sketch.png&quot; alt=&quot;GUI sketch&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Pretty simple, huh?&lt;/p&gt;

&lt;p&gt;I created a new &lt;em&gt;Visual C# WPF Application&lt;/em&gt; project and began playing a bit with
the Designer. Obviously, since this was my first attempt it didn’t look very
good. Besides, I want to add each item (line with image, small description and
    recommendations) dynamically. This means I have to create some kind of
component or a template which I can refer to from code.&lt;/p&gt;

&lt;p&gt;After a bit of googling and looking at sample projects I was a bit disappointed
with what I found… The most relevant information I have found is in &lt;a href=&quot;http://stackoverflow.com/a/9262452/354009&quot;&gt;this
stackoverflow answer&lt;/a&gt; which provides
some very good links for &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms752347.aspx&quot;&gt;data
binding&lt;/a&gt; and &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms742521.aspx&quot;&gt;data
templating&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;nice-looking-interface&quot;&gt;Nice looking interface&lt;/h1&gt;

&lt;p&gt;While the information I found is very good, I still don’t know how to make good
looking items. That’s why I began googling for some professional “WPF
components” and I found Telerik (a company that seems to specialize in creating
    various GUI components). After looking a bit on their site I found a &lt;a href=&quot;http://demos.telerik.com/wpf&quot;&gt;demo
to download&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Playing with their demos, I noticed they have some examples for a custom
ListBox and they also have &lt;em&gt;code samples&lt;/em&gt;. The ListBox I found looks somewhat
similar to what I want to do:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wpf-from-zero-to-hero-telerik-demo.png&quot; alt=&quot;Telerik Demo&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After checking the source code I saw that they obviously use their own
components, but I also noticed that some parts could be used in a standalone
project (without Telerik).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wpf-from-zero-to-hero-telerik-listbox.png&quot; alt=&quot;Telerik ListBox&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But, of course, I had to actually try and see if the components are as
independent as I thought they were. That’s why I replaced the empty Grid I got
when I created the WPF Application with the one from Telerik examples (section
    3. in the image above).&lt;/p&gt;

&lt;p&gt;After doing so, I noticed that there were some issues (code underlined with
    blue wiggles) which are related to some resources I haven’t copied. This
and the fact that the window rendering from the upper half of Visual Studio is
quite empty and I couldn’t figure out the layout easily, made me remember a
&lt;em&gt;useful technique for debugging layouts&lt;/em&gt;. The basic idea is to &lt;em&gt;add a bright
and noticeable background color&lt;/em&gt; to the component you’re debugging so that you
can better notice overflows and floating issues.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wpf-from-zero-to-hero-telerik-visual-studio.png&quot; alt=&quot;Visual Studio Telerik
Example&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is what I got after replacing all those wiggly underlines with the debug background colors:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wpf-from-zero-to-hero-visual-studio-debugging-layouts.png&quot; alt=&quot;Visual Studio Debugging
Layouts&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This kinda looks similar to one of the lines from the Telerik demo (it’s just a
    bit stretched on height as you can notice from the huge green rectangle):
  circle on left side, then a title and a small description, and then another
  image:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wpf-from-zero-to-hero-telerik-listbox-item.png&quot; alt=&quot;Telerik ListBox item&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now, at least, I know I got the layout right and it works outside of Telerik.&lt;/p&gt;

&lt;h1 id=&quot;code&quot;&gt;Code&lt;/h1&gt;

&lt;p&gt;Here’s the part that creates the (future) item template:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;StackPanel&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Orientation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Vertical&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Background=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Green&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Margin=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Name}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;FontSize=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;18&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Background=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Yellow&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Description}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;FontSize=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;12&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Background=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Orange&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/StackPanel&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code also contains the data binding part which seems to use it’s &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms752300.aspx&quot;&gt;own
little language&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I found that &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms752039.aspx&quot;&gt;these how-to
articles&lt;/a&gt; and in
particular &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms748857.aspx&quot;&gt;this one about how to make data available for binding in
XAML&lt;/a&gt; were quite useful
in understanding how everything fits together.&lt;/p&gt;

&lt;p&gt;The next step is to create the data template for one item.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Window.Resources&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;DataTemplate&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x:Key=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;itemTemplate&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;DataType=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;src:Item&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;StackPanel&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Orientation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Vertical&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Background=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Green&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Margin=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Name}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;FontSize=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;18&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Background=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Yellow&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextBlock&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding Description}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;FontSize=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;12&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Background=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Orange&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/StackPanel&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/DataTemplate&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Window.Resources&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The basic idea is to put the DataTemplate in the resources part of the
application. I saw in some examples that people put these in a separate file,
  but I’ll do it in the same file for simplicity (and this is just a learning
      project anyway).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;DataTemplate&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x:Key=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;itemTemplate&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;DataType=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;src:Item&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;x:key&lt;/code&gt; part is used to give an identifier for the DataTemplate so you can
later reference it and the &lt;code class=&quot;highlighter-rouge&quot;&gt;DataType&lt;/code&gt; sets the object types that can be
represented using this template.&lt;/p&gt;

&lt;p&gt;This is where I stumbled I bit since there were different examples on the
Internet: &lt;code class=&quot;highlighter-rouge&quot;&gt;src:Something&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;local:Something&lt;/code&gt; or even &lt;code class=&quot;highlighter-rouge&quot;&gt;c:Something&lt;/code&gt;. I
couldn’t understand how and where are those defined.&lt;/p&gt;

&lt;p&gt;I figured it out in the end after a bit of swearing. It looks like you should
define it using &lt;em&gt;XML namespaces&lt;/em&gt; (the &lt;em&gt;xmlns&lt;/em&gt; part) like this:
&lt;code class=&quot;highlighter-rouge&quot;&gt;xmlns:src=&quot;clr-namespace:DiagnoseTry1&quot;&lt;/code&gt;. Only after you do this you can
reference classes inside that namespace using this syntax: &lt;code class=&quot;highlighter-rouge&quot;&gt;src:Item&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here are all the puzzle pieces:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- MainWindow.xaml --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;Window&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x:Class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DiagnoseTry1.MainWindow&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;xmlns=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;xmlns:x=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;xmlns:src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;clr-namespace:DiagnoseTry1&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;Title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MainWindow&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;350&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;525&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- other code --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Window&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Item.cs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;DiagnoseTry1&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Item&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// more code&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That’s why the &lt;code class=&quot;highlighter-rouge&quot;&gt;DataType=&quot;src:Item&quot;&lt;/code&gt; part works:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;DataTemplate&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x:Key=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;itemTemplate&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;DataType=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;src:Item&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Oh, by the way, in case you’re wondering: &lt;em&gt;CLR&lt;/em&gt; is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Common_Language_Runtime&quot;&gt;Common Language
Runtime&lt;/a&gt;, some kind of a
virtual machine used to run .NET programs and it’s similar to the JVM (Java
    Virtual Machine).&lt;/p&gt;

&lt;p&gt;So, probably I can extract a &lt;em&gt;good practice&lt;/em&gt; here: to use the same XML
namespace as CLR namespace. That means in my case I would need to use
&lt;code class=&quot;highlighter-rouge&quot;&gt;xmlns:DiagnoseTry1=&quot;clr-namespace:DiagnoseTry1&quot;&lt;/code&gt; (besides coming up with
    better names for namespaces; at least for this project it doesn’t matter
    this much since I’m just learning).&lt;/p&gt;

&lt;p&gt;And now here’s the part that uses the &lt;code class=&quot;highlighter-rouge&quot;&gt;DataTemplate&lt;/code&gt;:
&lt;code class=&quot;highlighter-rouge&quot;&gt;ItemTemplate=&quot;{StaticResource itemTemplate}&quot;&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;ListBox&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x:Name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ItemListBox&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;400&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Margin=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;ItemsSource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{Binding items}&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;ItemTemplate=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{StaticResource itemTemplate}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/ListBox&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now follows the part where I couldn’t find more walls where to bang my head.
The binding to a list of items is simply done in XAML, just:
&lt;code class=&quot;highlighter-rouge&quot;&gt;ItemsSource=&quot;{Binding items}&quot;&lt;/code&gt;. It’s just that the binding doesn’t work
without a &lt;em&gt;DataContext&lt;/em&gt;. What follows is a &lt;em&gt;hack&lt;/em&gt; due to not having enough
knowledge to do it the right way in this post.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;partial&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MainWindow&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Window&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;MainWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;InitializeComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetItems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;DataContext&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Normally the &lt;code class=&quot;highlighter-rouge&quot;&gt;DataContext&lt;/code&gt; should be set in XAML code, but this doesn’t work in
&lt;code class=&quot;highlighter-rouge&quot;&gt;MainWindow.xaml&lt;/code&gt; (it &lt;a href=&quot;http://stackoverflow.com/a/15205381/354009&quot;&gt;causes a StackOverflow exception&lt;/a&gt;):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Window.DataContext&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;src:MainWindow/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Window.DataContext&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If I set the &lt;code class=&quot;highlighter-rouge&quot;&gt;DataContext&lt;/code&gt; from the C# code then it works:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;n&quot;&gt;DataContext&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After reading the explanation from the above mentioned StackOverflow post I
understood that I have to use the MVVM pattern. So, the next part will focus on
the &lt;a href=&quot;https://en.wikipedia.org/wiki/Model_View_ViewModel&quot;&gt;MVVM pattern&lt;/a&gt; and how
to use it in WPF.&lt;/p&gt;

&lt;h1 id=&quot;result-for-the-first-part&quot;&gt;Result for the first part&lt;/h1&gt;

&lt;p&gt;I know that this is pretty &lt;em&gt;laughable&lt;/em&gt;, but this is what I got working for this first part:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wpf-from-zero-to-hero-first-attempt.png&quot; alt=&quot;First attempt&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;tips&quot;&gt;Tips&lt;/h1&gt;

&lt;p&gt;Use &lt;em&gt;CTRL + E, D&lt;/em&gt; to format the XAML and C# code.&lt;/p&gt;

&lt;h1 id=&quot;resources&quot;&gt;Resources&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/sensui/DiagnoseTry1&quot;&gt;my laughable attempts on GitHub&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.microsoft.com/en-us/download/details.aspx?id=40787&quot;&gt;Microsoft Visual Studio Express for Windows Desktop&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gomockingbird.com/mockingbird/&quot;&gt;the site I used to create the gui sketch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/a/9262452/354009&quot;&gt;the StackOverflow answer which gave me the push in the right direction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms752347.aspx&quot;&gt;Microsoft Data Binding Documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms742521.aspx&quot;&gt;Microsoft Data Templating Documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://demos.telerik.com/wpf/&quot;&gt;Telerik Demo I used as example&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/github/gitignore&quot;&gt;.gitignore for all languages and tools&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/github/gitignore/blob/master/VisualStudio.gitignore&quot;&gt;.gitignore for Visual Studio&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://wpftutorial.net/GridLayout.html&quot;&gt;WPF Grid tutorial&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/b142f8e7.aspx&quot;&gt;Solution and Project Basics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.youtube.com/watch?v=ZCVIYDREWsk&quot;&gt;WPF video tutorial&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/a/5517400/354009&quot;&gt;the StackOverflow answer explaining the DataContext&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/a/15205381/354009&quot;&gt;binding fails with MainWindow (StackOverflow)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="WPF" />
      
        <category term="Visual Studio" />
      
        <category term="C#" />
      

      
        <summary type="html">I’d like to learn WPF to create a tiny application (something like a TODO list application). This is my first time ever touching Microsoft technologies. That’s why I will document all the steps I take while learning.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Fluent Assertions</title>
      
      
      <link href="https://igorpopov.io/2014/02/09/fluent-assertions/" rel="alternate" type="text/html" title="Fluent Assertions" />
      
      <published>2014-02-09T00:00:00+00:00</published>
      <updated>2014-02-09T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2014/02/09/fluent-assertions</id>
      <content type="html" xml:base="https://igorpopov.io/2014/02/09/fluent-assertions/">&lt;p&gt;One of the tricks I learned regarding writing unit tests is that sometimes it’s
better to write your own assertion classes.  Say you need to test the
conversion of measurements.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/fluent-assertions.jpg&quot; alt=&quot;Fluent Assertions&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;code-we-want-to-test&quot;&gt;Code we want to test&lt;/h1&gt;

&lt;p&gt;In this example we’re interested just to see how the tests end up looking so
we’re not going to write any implementation code; we’ll just use a library for
the actual conversion (jscience).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;valueOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getConverterTo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;valueOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;normal-way&quot;&gt;Normal way&lt;/h1&gt;

&lt;p&gt;This is how we would normally write the tests. Just use the standard junit
asserts.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DELTA&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;01&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;normalAsserts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actualKilometres&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;km&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actualKilometres&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DELTA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actualPounds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;t&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;lb&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2204.62&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actualPounds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DELTA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actualGallons&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;L&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gal&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2.64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actualGallons&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DELTA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;improved-way&quot;&gt;Improved way&lt;/h1&gt;

&lt;p&gt;The normal way is ok in most cases, but we want to increase their readability
and maintainability. One method of doing this is to make the tests describe as
close as possible to English the behaviour we want to test.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;improvedAsserts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;km&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;t&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2204.62&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;lb&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;L&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2.64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gal&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s take a closer look at one of the asserts:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;km&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;/images/fluent-assertions-readable-tests.png&quot; alt=&quot;Readable tests&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It reads almost as English (if you ignore the punctuation): “Assert that 1000
  metres equals 1 kilometre”. Another thing to notice here is that the value
  and the unit are grouped together as a single concept which is not so clear
  in the first example. Of course, the unit and the value might be better in a
  separate class called Measurement or something like that.&lt;/p&gt;

&lt;h1 id=&quot;how-to-do-it&quot;&gt;How to do it?&lt;/h1&gt;

&lt;p&gt;The basic idea is to create a method &lt;code class=&quot;highlighter-rouge&quot;&gt;assertThat&lt;/code&gt; that returns a new
ConversionAssert and contains a method that does the actual verification.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConversionAssert&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ConversionAssert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConversionAssert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ConversionAssert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fromUnit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;conversion from %f %s to %s&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toUnit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DELTA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;resources&quot;&gt;Resources&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/sensui/fluent-assertions-example&quot;&gt;Full example on Github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/magazine/cc163665.aspx&quot;&gt;Write Maintainable Unit Tests That Will Save You Time And Tears&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/alexruiz/fest-assert-2.x/wiki/One-minute-starting-guide&quot;&gt;FEST Assertions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="test" />
      
        <category term="tdd" />
      
        <category term="fluent" />
      
        <category term="junit" />
      
        <category term="assert" />
      

      
        <summary type="html">One of the tricks I learned regarding writing unit tests is that sometimes it’s better to write your own assertion classes. Say you need to test the conversion of measurements.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Pipe Viewer - the Linux flow meter</title>
      
      
      <link href="https://igorpopov.io/2013/12/25/pipe-viewer-the-linux-flow-meter/" rel="alternate" type="text/html" title="Pipe Viewer - the Linux flow meter" />
      
      <published>2013-12-25T00:00:00+00:00</published>
      <updated>2013-12-25T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2013/12/25/pipe-viewer-the-linux-flow-meter</id>
      <content type="html" xml:base="https://igorpopov.io/2013/12/25/pipe-viewer-the-linux-flow-meter/">&lt;p&gt;&lt;strong&gt;Pipe viewer&lt;/strong&gt; is just &lt;strong&gt;a flow meter for Linux command line programs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/pipe-viewer-digital-flow-meter.jpg&quot; alt=&quot;digital flow meter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It allows you to see the progress of a long running command. For example if you extract a big archive using &lt;code class=&quot;highlighter-rouge&quot;&gt;tar&lt;/code&gt; you are left in the dark regarding how much was already extracted, how much is left and when it will finish. Pipe viewer adds a progress bar much like &lt;code class=&quot;highlighter-rouge&quot;&gt;wget&lt;/code&gt; when it shows the download progress.&lt;/p&gt;

&lt;h2 id=&quot;a-simple-example&quot;&gt;A simple example&lt;/h2&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;igor@vm:~/temp$ pv archive.tar.gz | tar -xz
35MB 0:00:03 [10.3MB/s] [==========&amp;gt;                          ] 32% ETA 0:00:06
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;explanation&quot;&gt;Explanation&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Pipe viewer&lt;/strong&gt; works very much like &lt;code class=&quot;highlighter-rouge&quot;&gt;cat&lt;/code&gt;. Indeed, if you’ll replace &lt;code class=&quot;highlighter-rouge&quot;&gt;pv&lt;/code&gt; with &lt;code class=&quot;highlighter-rouge&quot;&gt;cat&lt;/code&gt; you’ll get exactly the same result, but without the progress indication. Here is the previous example, but this time using &lt;code class=&quot;highlighter-rouge&quot;&gt;cat&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;igor@vm:~/temp$ cat archive.tar.gz | tar -xz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Normally, in &lt;code class=&quot;highlighter-rouge&quot;&gt;*nix&lt;/code&gt; systems all the command line programs are designed to read from standard-in and write to standard-out (&lt;code class=&quot;highlighter-rouge&quot;&gt;stdin&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;stdout&lt;/code&gt;). This allows for a very cool trick: you can “&lt;strong&gt;pipe&lt;/strong&gt;” (using the &lt;code class=&quot;highlighter-rouge&quot;&gt;|&lt;/code&gt; operator) the output of a program into another program. This allows most of the &lt;code class=&quot;highlighter-rouge&quot;&gt;*nix&lt;/code&gt; commands to focus on just one thing. This is the case with &lt;strong&gt;Pipe Viewer&lt;/strong&gt; too: it just shows progress information, but the actual decompression (from the previous example) is done by a separate command: &lt;code class=&quot;highlighter-rouge&quot;&gt;tar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Perhaps it’s easier if you think about &lt;strong&gt;data flow&lt;/strong&gt;: you have a long pipe (a real-world pipe), through one end you feed data and through the other end you get the processed data. You can consider each &lt;code class=&quot;highlighter-rouge&quot;&gt;*nix&lt;/code&gt; program from the (software) pipe as a &lt;strong&gt;filter&lt;/strong&gt; you put on the real-world pipe.&lt;/p&gt;

&lt;p&gt;The simplest (software) “&lt;strong&gt;pipe&lt;/strong&gt;” is &lt;code class=&quot;highlighter-rouge&quot;&gt;cat&lt;/code&gt; which copies standard-in to standard-out and doesn’t do any transformations on the input data.&lt;/p&gt;

&lt;h2 id=&quot;other-examples&quot;&gt;Other examples&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Restoring a MySQL database dump&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pv mysql-dump.sql | mysql -u root -p db-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Copy big files locally&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pv big-file.txt &amp;gt; /path/to/new/location
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Copy big files from local to remote computer&lt;/strong&gt;&lt;br /&gt;
This will create the archive first then pipe it to &lt;strong&gt;Pipe Viewer&lt;/strong&gt; and send it to the remote computer using &lt;code class=&quot;highlighter-rouge&quot;&gt;netcat&lt;/code&gt; (&lt;code class=&quot;highlighter-rouge&quot;&gt;-l number&lt;/code&gt; means listen on port &lt;code class=&quot;highlighter-rouge&quot;&gt;number&lt;/code&gt; - used on the server to listen for connections, &lt;code class=&quot;highlighter-rouge&quot;&gt;-q number&lt;/code&gt; - after EOF on stdin, wait the specified number of seconds and then quit. If seconds is negative, wait forever).&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# local (ip: 192.168.33.10)
tar -cf – /path/to/dir | pv | nc -l 12321 -q 5

# remote
nc 192.168.33.10 12321 | pv | tar -xf -
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’ll want to use this instead of &lt;code class=&quot;highlighter-rouge&quot;&gt;scp&lt;/code&gt; (secure copy) when copying files on the internal network and you’re concerned only with getting a file as fast as possible on the new computer (using just the network, without external storage).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using named pipe viewers&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;igor@vm:~/temp$ pv -N archive sql-dump.tar.gz | tar -xz
  archive: 23.6MB 0:00:02 [15.3MB/s] [====&amp;gt;                     ] 21% ETA 0:00:07
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Using more than one pipe viewer&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;igor@vm:~/temp$ pv -cN reading sql-dump.tar.gz | \
    &amp;gt; tar -xz --to-stdout | \
    &amp;gt; pv -cN writing &amp;gt; sql-dump.sql
  reading: 63.1MB 0:00:05 [10.1MB/s] [=============&amp;gt;            ] 57% ETA 0:00:03
  writing: 69.2MB 0:00:05 [11.8MB/s] [   &amp;lt;=&amp;gt;                                    ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;how-to-create-big-files-fast&quot;&gt;How to create big files fast&lt;/h1&gt;
&lt;p&gt;If you want to follow along with the examples described here you’ll need some big files. One way is to find some files you already have or to generate some on the fly. This is how you can generate a file having 10 GB:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fallocate -l 10G big-file.bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.catonmat.net/blog/unix-utilities-pipe-viewer/&quot;&gt;http://www.catonmat.net/blog/unix-utilities-pipe-viewer/&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://davedash.com/2009/09/16/getting-started-with-pipe-viewer/&quot;&gt;http://davedash.com/2009/09/16/getting-started-with-pipe-viewer/&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://securfox.wordpress.com/2009/07/03/pv-pipe-viewer/&quot;&gt;http://securfox.wordpress.com/2009/07/03/pv-pipe-viewer/&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.ibm.com/developerworks/aix/library/au-spunix_pipeviewer/&quot;&gt;http://www.ibm.com/developerworks/aix/library/au-spunix_pipeviewer/&lt;/a&gt;&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="pipe" />
      
        <category term="viewer" />
      
        <category term="linux" />
      

      
        <summary type="html">Pipe viewer is just a flow meter for Linux command line programs.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">phpmyadmin on ubuntu</title>
      
      
      <link href="https://igorpopov.io/2013/12/08/phpmyadmin-on-ubuntu/" rel="alternate" type="text/html" title="phpmyadmin on ubuntu" />
      
      <published>2013-12-08T00:00:00+00:00</published>
      <updated>2013-12-08T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2013/12/08/phpmyadmin-on-ubuntu</id>
      <content type="html" xml:base="https://igorpopov.io/2013/12/08/phpmyadmin-on-ubuntu/">&lt;p&gt;Installing &lt;code class=&quot;highlighter-rouge&quot;&gt;phpmyadmin&lt;/code&gt; on Ubuntu can be a bit difficult for someone that
doesn’t know how to configure apache (like me till now).  I just executed the
following command:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get update
sudo apt-get install phpmyadmin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and expected that when I navigate to &lt;code class=&quot;highlighter-rouge&quot;&gt;http://localhost/phpmyadmin&lt;/code&gt; it would
simply work. Actually, what I got was &lt;em&gt;page not found&lt;/em&gt; :(&lt;/p&gt;

&lt;h2 id=&quot;proper-way-to-configure-apache&quot;&gt;Proper way to configure apache&lt;/h2&gt;

&lt;p&gt;After a bit of googling here’s what I found out:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;with the above 2 commands I just installed phpmyadmin,&lt;/li&gt;
  &lt;li&gt;what this means is that I only have the phpmyadmin files on my server,&lt;/li&gt;
  &lt;li&gt;I need to configure apache to tell it about the new phpmyadmin site location.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apache has multiple ways of accomplishing this:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;use the &lt;code class=&quot;highlighter-rouge&quot;&gt;conf.d&lt;/code&gt; directory,&lt;/li&gt;
  &lt;li&gt;use the &lt;code class=&quot;highlighter-rouge&quot;&gt;apache2.conf&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;use the &lt;code class=&quot;highlighter-rouge&quot;&gt;httpd.conf&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;use the &lt;code class=&quot;highlighter-rouge&quot;&gt;sites-available&lt;/code&gt; directory and &lt;code class=&quot;highlighter-rouge&quot;&gt;a2ensite&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;use the &lt;code class=&quot;highlighter-rouge&quot;&gt;sites-enabled&lt;/code&gt; directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not knowing what is the proper way of doing this I began looking for “best
practices”. It seems that the &lt;code class=&quot;highlighter-rouge&quot;&gt;conf.d&lt;/code&gt; directory is used for global apache
configuration, the &lt;code class=&quot;highlighter-rouge&quot;&gt;apache2.conf&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;httpd.conf&lt;/code&gt; provide defaults and they
shouldn’t be normally touched and the &lt;code class=&quot;highlighter-rouge&quot;&gt;sites-enabled&lt;/code&gt; directory should contain
only symbolic links to files from the &lt;code class=&quot;highlighter-rouge&quot;&gt;sites-available&lt;/code&gt; directory.&lt;/p&gt;

&lt;h2 id=&quot;activating-phpmyadmin-in-apache&quot;&gt;Activating phpmyadmin in apache&lt;/h2&gt;

&lt;p&gt;Ok, so now that we’ve eliminated all the “wrong” ways to do it only one way
remains: using the &lt;code class=&quot;highlighter-rouge&quot;&gt;sites-available&lt;/code&gt; and the &lt;code class=&quot;highlighter-rouge&quot;&gt;a2ensite&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;But first: phpmyadmin already comes with an apache configuration and we need to
just use it. This configuration is available in:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/etc/phpmyadmin/apache.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we need to put it in:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/etc/apache2/sites-available
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To do this we’ll create a symbolic link:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo ln -s /etc/phpmyadmin/apache.conf /etc/apache2/sites-available/phpmyadmin.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The next step is to activate this new site using:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo a2ensite phpmyadmin.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command will actually create a link from the &lt;code class=&quot;highlighter-rouge&quot;&gt;sites-available&lt;/code&gt; to the
&lt;code class=&quot;highlighter-rouge&quot;&gt;sites-enabled&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;The final step is to restart apache with the following command:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo /etc/init.d/apache2 restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Navigate to &lt;code class=&quot;highlighter-rouge&quot;&gt;http://localhost/phpmyadmin&lt;/code&gt; and enjoy!&lt;/p&gt;

&lt;h2 id=&quot;quick-commands&quot;&gt;Quick commands&lt;/h2&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo ln -s /etc/phpmyadmin/apache.conf
           /etc/apache2/sites-available/phpmyadmin.conf
sudo a2ensite phpmyadmin.conf
sudo /etc/init.d/apache2 restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;vagrant-and-puppet&quot;&gt;Vagrant and puppet&lt;/h2&gt;

&lt;p&gt;If you need a &lt;code class=&quot;highlighter-rouge&quot;&gt;phpmyadmin&lt;/code&gt; server just execute these commands:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/sensui/vagrant-phpmyadmin.git
vagrant up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In a few moments you’ll have a phpmyadmin server running on: &lt;code class=&quot;highlighter-rouge&quot;&gt;http://192.168.33.10/phpmyadmin/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the puppet script that accomplishes what this post describes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Exec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/bin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/sbin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/usr/bin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/usr/sbin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'system-update'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'sudo apt-get update'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'system-update'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Package&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;|&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'phpmyadmin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;present&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# linux way: ln -s /etc/phpmyadmin/apache.conf /etc/apache2/sites-available/phpmyadmin.conf&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/etc/apache2/sites-available/phpmyadmin.conf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/etc/phpmyadmin/apache.conf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'phpmyadmin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'enable-phpmyadmin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'sudo a2ensite phpmyadmin.conf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/etc/apache2/sites-available/phpmyadmin.conf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'restart-apache'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'sudo /etc/init.d/apache2 restart'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'enable-phpmyadmin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;

&lt;p&gt;I found these links very helpful in my research:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/a/15467127/354009&quot;&gt;stackoverflow answer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.ubuntu.com/12.04/serverguide/httpd.html#http-configuration&quot;&gt;apache configuration section from ubuntu manuals&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="phpmyadmin" />
      
        <category term="ubuntu" />
      
        <category term="linux" />
      

      
        <summary type="html">Installing phpmyadmin on Ubuntu can be a bit difficult for someone that doesn’t know how to configure apache (like me till now). I just executed the following command:</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Augeas, the configuration editor</title>
      
      
      <link href="https://igorpopov.io/2013/12/07/augeas-configuration-editor/" rel="alternate" type="text/html" title="Augeas, the configuration editor" />
      
      <published>2013-12-07T00:00:00+00:00</published>
      <updated>2013-12-07T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2013/12/07/augeas-configuration-editor</id>
      <content type="html" xml:base="https://igorpopov.io/2013/12/07/augeas-configuration-editor/">&lt;p&gt;I just found a new interesting tool that can be used to edit configuration
files. It’s so good that you can change some options without parsing the file.
You just need to give it the file name and tell it to change a specific option.&lt;/p&gt;

&lt;p&gt;If you’re on ubuntu you need to install it using the following command:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get install augeas-tools augeas-lenses
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;printing-properties&quot;&gt;Printing properties&lt;/h2&gt;

&lt;p&gt;I recently wanted to enable the &lt;code class=&quot;highlighter-rouge&quot;&gt;display_errors&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;php.ini&lt;/code&gt; in an automated
way. To make things easier we’re just going to display the contents of the
file. This is done using:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;augtool print /files/etc/php5/apache2/php.ini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice I used the &lt;code class=&quot;highlighter-rouge&quot;&gt;/files&lt;/code&gt; prefix before putting the full path of the file I
want to access. That’s how it’s done in augeas.&lt;/p&gt;

&lt;p&gt;Now, to show the property we’re interested in we need to run the following
command:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;augtool print /files/etc/php5/apache2/php.ini/PHP/display_errors
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s the output returned:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/files/etc/php5/apache2/php.ini/PHP/display_errors = &quot;On&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;debugging&quot;&gt;Debugging&lt;/h2&gt;

&lt;p&gt;I tried the above command without luck for a while before I realized that my
&lt;code class=&quot;highlighter-rouge&quot;&gt;php.ini&lt;/code&gt; file had a mistake from a previous manual editing I’ve done.  In this
case augeas didn’t show any errors. It just didn’t show anything. So you have
to be careful with this type of things. To actually see what was wrong with the
file you’re trying to parse run this command:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;augtool print /augeas//error
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will at least show the line number where the problem is.&lt;/p&gt;

&lt;h2 id=&quot;changing-properties&quot;&gt;Changing properties&lt;/h2&gt;

&lt;p&gt;Now that we know how to show the value of a property let’s see how can we change it, shall we?
Run the augtool as root and set the &lt;code class=&quot;highlighter-rouge&quot;&gt;display_errors&lt;/code&gt; configuration as shown below:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo augtool
augtool&amp;gt; set /files/etc/php5/apache2/php.ini/PHP/display_errors &quot;Off&quot;
augtool&amp;gt; save
Saved 1 file(s)
augtool&amp;gt; exit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you get an error or something doesn’t work remember to run &lt;code class=&quot;highlighter-rouge&quot;&gt;augtool print
/augeas//error&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;lenses&quot;&gt;Lenses&lt;/h2&gt;

&lt;p&gt;Till now you probably have the impression that this &lt;code class=&quot;highlighter-rouge&quot;&gt;augtool&lt;/code&gt; works only with
php configuration files… Well, it actually works with any configuration file
and here’s why… Augeas actually reads the file you give it and saves it into
a tree based on a &lt;em&gt;lense&lt;/em&gt;. This lense is actually a file containing regular
expressions that identify each option for a specific configuration file. So we
can have lenses for pretty much anything: cron, grub, hosts, mysql, passwd,
    ssh, xml, json, ini. Here’s &lt;a href=&quot;http://augeas.net/stock_lenses.html&quot;&gt;&lt;em&gt;a list&lt;/em&gt;&lt;/a&gt;
    with all the lenses that augeas comes with by default.&lt;/p&gt;

&lt;h2 id=&quot;puppet&quot;&gt;Puppet&lt;/h2&gt;

&lt;p&gt;If you happen to use puppet, here’s how to do it:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;augeas&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'display_errors'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/files/etc/php5/apache2/php.ini'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;changes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;'set PHP/display_errors On'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;more-information&quot;&gt;More information&lt;/h2&gt;

&lt;p&gt;You can read more about augeas on the official website (although I didn’t find
    it particularly informative) and on this page that actually contains really
good information: &lt;a href=&quot;http://projects.puppetlabs.com/projects/1/wiki/puppet_augeas&quot;&gt;&lt;em&gt;Augeas puppet
documentation&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      

      
        <category term="configuration" />
      
        <category term="editor" />
      
        <category term="augeas" />
      

      
        <summary type="html">I just found a new interesting tool that can be used to edit configuration files. It’s so good that you can change some options without parsing the file. You just need to give it the file name and tell it to change a specific option.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Vagrant and puppet kata</title>
      
      
      <link href="https://igorpopov.io/2013/12/02/vagrant-puppet-librarian-kata/" rel="alternate" type="text/html" title="Vagrant and puppet kata" />
      
      <published>2013-12-02T00:00:00+00:00</published>
      <updated>2013-12-02T00:00:00+00:00</updated>
      <id>https://igorpopov.io/2013/12/02/vagrant-puppet-librarian-kata</id>
      <content type="html" xml:base="https://igorpopov.io/2013/12/02/vagrant-puppet-librarian-kata/">&lt;p&gt;OK, so maybe you’re wondering what’s all this post about… Well, kata means a
kind of exercise used to learn something new.  Vagrant is a command line
wrapper for VirtualBox which is a tool to manage virtual machines.&lt;/p&gt;

&lt;p&gt;Software development is pretty hard in general… one of the reasons why it’s
so hard is because each project has a lot of external dependencies: the
operating system, specific versions of libraries, the network, the database
etc. One of the consequences of these dependencies is the so called &lt;em&gt;works on
my machine&lt;/em&gt; type of issues that almost always happens.&lt;/p&gt;

&lt;p&gt;So, there’s a lot of stuff that can go wrong… How can we solve this, at least
on the development side? Well, this is where vagrant comes into play! You
create a virtual machine for your application and then automatically install
all the dependencies. Now you test and develop only on that virtual machine.
This has the advantage that it pins down everything you need for the project
and that everyone uses the same environment. When you fix an issue on your
machine you can be sure as hell that it’s solved once and for all!!! Besides
this, if you’re working on multiple projects with conflicting dependencies (for
example 2 projects requiring different versions of the same library or
framework) you’ll have them both nicely separated and totally independent.&lt;/p&gt;

&lt;h2 id=&quot;requirements&quot;&gt;Requirements&lt;/h2&gt;

&lt;p&gt;Download and install: git, VirtualBox, vagrant and librarian-puppet.  You
should have at least basic knowledge of the command line (bash/zsh), although I
still explain some of the commands and tricks I use.&lt;/p&gt;

&lt;p&gt;In this kata, I’ll create a virtual machine with all the required software to
run &lt;em&gt;a basic php website&lt;/em&gt; (and I’ll also play with some of the puppet’s
    features).&lt;/p&gt;

&lt;p&gt;OK, enough talk… let’s get to work!&lt;/p&gt;

&lt;h2 id=&quot;the-vagrantfile&quot;&gt;The Vagrantfile&lt;/h2&gt;

&lt;p&gt;Create a git repository called &lt;code class=&quot;highlighter-rouge&quot;&gt;vagrant-puppet-librarian-kata&lt;/code&gt;. Now &lt;code class=&quot;highlighter-rouge&quot;&gt;cd&lt;/code&gt; into it
(there’s a cool trick for this: type &lt;code class=&quot;highlighter-rouge&quot;&gt;cd&lt;/code&gt; then press &lt;code class=&quot;highlighter-rouge&quot;&gt;ALT+.&lt;/code&gt; and the previous
command line argument will autocomplete so you don’t need to type it twice).
Create a directory called &lt;code class=&quot;highlighter-rouge&quot;&gt;provisioning&lt;/code&gt; so everything stays nicely grouped
together. Create a &lt;code class=&quot;highlighter-rouge&quot;&gt;Vagrantfile&lt;/code&gt; with the following contents:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Vagrant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'2'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;box&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'precise32'&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;box_url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'http://files.vagrantup.com/precise32.box'&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:node&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hostname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'node'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;network&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:private_network&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;ip: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'192.168.33.10'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;synced_folder&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'../'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/var/www/vagrant'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;provision&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:puppet&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;puppet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;puppet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;module_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'modules/third-party'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'modules/main'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;puppet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;manifests_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'manifests'&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;puppet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;manifest_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'node.pp'&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;puppet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;facter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'fqdn'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'node.igorpopov.me'&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Vagrantfile&lt;/code&gt; is just a ruby script with some DSL (Domain Specific
    Language) on top of it. This means that anything written in ruby will also
work. &lt;code class=&quot;highlighter-rouge&quot;&gt;Vagrant.configure('2')&lt;/code&gt; selects what version of the vagrant API you want
to use. The next 2 lines (with &lt;code class=&quot;highlighter-rouge&quot;&gt;config.vm.box*&lt;/code&gt;) describe what base operating
system image we should use. We can choose from the 
&lt;a href=&quot;http://vagrantbox.es&quot;&gt;VagrantBoxes&lt;/a&gt; website.&lt;/p&gt;

&lt;p&gt;The next line defines a new node called &lt;code class=&quot;highlighter-rouge&quot;&gt;:node&lt;/code&gt; and configures it in a ruby
block.  One particularly interesting feature is that we can set an ip address
to this virtual machine. This means that when you start it you could use its
ip address in your browser (if you have a web server installed).&lt;/p&gt;

&lt;p&gt;Another interesting feature is that we can specify some folders to be
synchronized between the host and the guest machine. For example you can set
the project directory to be mapped to some directory on the virtual machine and
in this case you can edit the project files on your machine using any editors
you like and then have those files automatically syncronized on the guest
machine.&lt;/p&gt;

&lt;h2 id=&quot;the-provisioning&quot;&gt;The provisioning&lt;/h2&gt;

&lt;p&gt;The next lines configure the &lt;em&gt;provisioning&lt;/em&gt; of the virtual machine. This is
just a complicated word for &lt;em&gt;automatic installation&lt;/em&gt; of software. For this
kata, I’m using puppet. Puppet requires a manifest file that describes what we
want installed on the machine. In our case, this file is &lt;code class=&quot;highlighter-rouge&quot;&gt;manifests/node.pp&lt;/code&gt;.
By the way, the puppet script is, just like the Vagrantfile, a ruby script
(with a DSL on top).&lt;/p&gt;

&lt;h2 id=&quot;third-party-modules&quot;&gt;Third party modules&lt;/h2&gt;

&lt;p&gt;Normally, in a programming language, you have libraries/jars/gems/dlls etc.
that you want to use in your project. You also have them in puppet, but they
are called &lt;em&gt;modules&lt;/em&gt;. You can find them on the &lt;a href=&quot;http://forge.puppetlabs.com&quot;&gt;Puppet
Forge&lt;/a&gt;. Let’s see how we can specify what
third-party modules we need for our project…&lt;/p&gt;

&lt;p&gt;Create a &lt;code class=&quot;highlighter-rouge&quot;&gt;Puppetfile&lt;/code&gt; with the following contents:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;forge&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'http://forge.puppetlabs.com'&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'puppetlabs/apache'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'example42/php'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We will use &lt;em&gt;librarian-puppet&lt;/em&gt; to manage all the third party modules.
Historically, adding third party puppet modules was done using git submodules
which aren’t the best solution. First, because they are pretty complicated to
use and second, because they just sit there in your repository. The most
desirable solution would be to just add them as dependencies somewhere, but not
include the actual source code in your repository. Librarian-puppet will do
this for you. All you have to do is give it a Puppetfile that tells it what
modules you need and librarian-puppet will go and download them for you.&lt;/p&gt;

&lt;p&gt;Run the following command to change the directory where librarian-puppet puts
the third-party modules (by default it’s &lt;code class=&quot;highlighter-rouge&quot;&gt;modules&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;librarian-puppet config --local path modules/third-party
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will save the configuration in the &lt;code class=&quot;highlighter-rouge&quot;&gt;.librarian&lt;/code&gt; directory that you should
add to source control.  Then, to actually get the third party modules you
declared in the Puppetfile you need to run:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;librarian-puppet install --verbose
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;--verbose&lt;/code&gt; flag is needed so that librarian-puppet actually tells it’s
progress (by default you’ll only see that librarian-puppet hangs for 15 seconds
without showing anything). This command will put all the downloaded modules
in the &lt;code class=&quot;highlighter-rouge&quot;&gt;modules/third-party&lt;/code&gt; directory (the one you’ve configured above).&lt;/p&gt;

&lt;p&gt;Now, we need to create the required directories and we’ll use a very cool trick
for this, called &lt;em&gt;shell expansion&lt;/em&gt;. OK, so, this is the directory structure we
need:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.
`-- provision
    |-- manifests
    `-- modules
        |-- main
        `-- third-party
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Normally, we’d just do:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir provision
mkdir provision/manifests
mkdir provision/modules
mkdir provision/modules/main
mkdir provision/modules/third-party
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But there are a few tricks we could use. The mkdir command accepts a command
line switch: &lt;code class=&quot;highlighter-rouge&quot;&gt;-p&lt;/code&gt; that creates all the directories till the last one. So the
above list of commands becomes:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir -p provision/manifests
mkdir -p provision/modules/main
mkdir -p provision/modules/third-party
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And there’s one more trick we can use: shell expansion! If we want to create
multiple directories on the same level in the hierarchy we can use curly
brackets and the shell will automatically expand them. The above example
becomes:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir -p provision/manifests
mkdir -p provision/modules/{main,third-party}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next we need to create the &lt;code class=&quot;highlighter-rouge&quot;&gt;provision/manifests/node.pp&lt;/code&gt; file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Exec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/bin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/sbin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/usr/bin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/usr/sbin'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'system-update'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'sudo apt-get update'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'system-update'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Package&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;|&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'tree'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'git'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'vim'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'augeas-tools'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;present&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'igor'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;present&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'apache'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;mpm_module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'prefork'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vhost&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$fqdn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;priority&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;docroot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/var/www/vagrant/labs'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;php&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;php&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;command-paths&quot;&gt;Command paths&lt;/h2&gt;

&lt;p&gt;The first Exec statement tells puppet where to look on the disk when running
commands. If we don’t do it here, we’ll need to prefix each command with it’s
path and that’s not so nice…&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Exec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/bin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/sbin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/usr/bin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/usr/sbin'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;puppet-resources&quot;&gt;Puppet resources&lt;/h2&gt;

&lt;p&gt;Before we advance, you should know about “puppet resources”. Among the most
important ones are exec, package and service. All the resources have the
following format:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'custom-resource-name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;key1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'value1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;key2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'value2'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;updating-the-system&quot;&gt;Updating the system&lt;/h2&gt;

&lt;p&gt;The exec resource is used to tell puppet to execute a shell command on the
virtual machine.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'system-update'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'sudo apt-get update'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The next thing tells puppet that before installing any package it should first
update the list of packages available:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'system-update'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Package&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;|&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;messing-around&quot;&gt;Messing around&lt;/h2&gt;

&lt;p&gt;Now we tell puppet that we want a list of packages installed:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'tree'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'git'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'vim'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'augeas-tools'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;present&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s also create a new user, just for fun :)&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'igor'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;present&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;See? It was pretty simple, huh?&lt;/p&gt;

&lt;h2 id=&quot;configuring-apache-and-php&quot;&gt;Configuring apache and php&lt;/h2&gt;

&lt;p&gt;Now, for the apache and php installation it’s a bit more complex. If we want
both apache and php we need to activate the &lt;code class=&quot;highlighter-rouge&quot;&gt;prefork&lt;/code&gt; option of the
&lt;code class=&quot;highlighter-rouge&quot;&gt;mpm_module&lt;/code&gt;. At least that’s how it was documented on the &lt;a href=&quot;http://forge.puppetlabs.com/puppetlabs/apache&quot;&gt;module’s main
page&lt;/a&gt;. Next, we need to define a
vhost. This will be used so apache knows what files it should use when we
navigate to it. One thing I had difficulties with is that you should set a
&lt;em&gt;priority less than 15&lt;/em&gt; if you want to use the port 80 or else your files won’t
be taken into use. Now we also need to specify where are those files located.
Remember that we configured a &lt;code class=&quot;highlighter-rouge&quot;&gt;synced_folder&lt;/code&gt; in the Vagrantfile? This is where
we’ll use it. As the docroot for the current vhost.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'apache'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;mpm_module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'prefork'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vhost&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$fqdn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;priority&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;docroot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/var/www/vagrant/labs'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Next, we need to activate the php module in apache and also include the php puppet module in the current script:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;php&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;php&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;starting-the-virtual-machine&quot;&gt;Starting the virtual machine&lt;/h2&gt;

&lt;p&gt;To start it, just run this command from the directory where the Vagrantfile is
located: &lt;code class=&quot;highlighter-rouge&quot;&gt;vagrant up&lt;/code&gt;. After vagrant starts the virtual machine it will
provision it using the &lt;code class=&quot;highlighter-rouge&quot;&gt;node.pp&lt;/code&gt; script I have described.&lt;/p&gt;

&lt;h2 id=&quot;check-if-apache-and-php-are-installed&quot;&gt;Check if apache and php are installed&lt;/h2&gt;

&lt;p&gt;Ok, now add a &lt;code class=&quot;highlighter-rouge&quot;&gt;index.php&lt;/code&gt; file with the following content:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;phpinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To check if everything is alright (in case you didn’t have errors from vagrant
    and/or puppet) you can use ping and curl in this way:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ping 192.168.33.10
curl 192.168.33.10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;

&lt;p&gt;I have pushed the complete example (which may be a bit different) &lt;a href=&quot;https://github.com/sensui/vagrant-puppet-librarian-kata&quot;&gt;on
github&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;I have done this kata more than 20 times (over the course of about 2 weeks),
  each time recording myself and reviewing my mistakes. In the beginning I made
  lots of mistakes and I researched a lot on the Internet even the trivial
  stuff.&lt;/p&gt;

&lt;p&gt;Each time I have progressed bit by bit and now I can do this kata in about 17
minutes almost perfectly using only vim and the command line. I still make
small typos which I fix pretty quickly. The first time I did it in about 40
minutes and I made lots of mistakes and did lots of research on the Internet.&lt;/p&gt;

&lt;p&gt;This post will serve me as a reminder in case I forget some steps and why
they are done… and maybe, just maybe, it will also help someone else.&lt;/p&gt;

&lt;p&gt;I will also post somewhere the final video with me doing the kata.&lt;/p&gt;

&lt;p&gt;Well, if you’re still reading, this concludes the explanations. If you have
questions you can comment and ask clarifications.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Igor Popov</name>
          
          
        </author>
      

      
        <category term="katas" />
      

      
        <category term="kata" />
      
        <category term="vagrant" />
      
        <category term="puppet" />
      

      
        <summary type="html">OK, so maybe you’re wondering what’s all this post about… Well, kata means a kind of exercise used to learn something new. Vagrant is a command line wrapper for VirtualBox which is a tool to manage virtual machines.</summary>
      

      
      
    </entry>
  
  
</feed>
