<?xml version="1.0" encoding="utf-8" ?><?xml-stylesheet type="text/css" href="https://www.earthli.com/resources/styles/rss.css" ?><rss version="2.0">
  <channel>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>earthli News 3.7</generator>
    <language>en-us</language>
    <ttl>720</ttl>
    <title><![CDATA[Programming &gt; earthli News 3.7]]></title>
    <link>https://www.earthli.com/news/</link>
    <pubDate>Mon, 16 Feb 2026 18:17:45 +0100</pubDate>
    <lastBuildDate>Mon, 16 Feb 2026 18:17:45 +0100</lastBuildDate>
    <image>
      <link>https://www.earthli.com/news/</link>
      <title><![CDATA[Programming &gt; earthli News 3.7]]></title>
      <url>https://www.earthli.com/news/icons/webcore_png/app/news_100px.png</url>
    </image>
    <description><![CDATA[]]></description>
    <copyright><![CDATA[Copyright (c) 1999-2026 earthli.com. All Rights Reserved.]]></copyright>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5297</guid>
    <title><![CDATA[jj vs. git vs. GUIs]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5297</link>
    <pubDate>Mon, 16 Feb 2026 18:17:45 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Feb 2026 18:17:45 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://v5.chriskrycho.com/essays/jj-init/"><code>jj init</code> — Sympolymathesy</a> by <cite>Chris Krycho</cite> explains what Jujutsu is and what it does. I was reminded of these notes that I wrote over a year ago when I read <a href="https://lwn.net/SubscriberLink/1057561/bddc1e61152fadf6/">Evolving Git for the next decade</a> by <cite>Joe Brockmeier</cite> (<cite><a href="http://lwn.net/">LWM.Net</a></cite>), which briefly mentioned it as a command-line UX toward which Git itself is working. [1]</p>
<h2>Git is not worse than all the others</h2><blockquote class="quote quote-block "><div>&ldquo;Jujutsu is two things: It is a new front-end to Git. This is by far the less interesting of the two things, but in practice it is a substantial part of the experience of using the tool today. In this regard, it sits in the same notional space as something like gitoxide. Jujutsu’s <code>jj</code> is far more usable for day to day work than gitoxide’s <code>gix</code> and <code>ein</code> so far, though, and it also has very different aims. That takes us to: <strong>It is a new design for distributed version control.</strong> This is by far the more interesting part. In particular, Jujutsu brings to the table a few key concepts — none of which are themselves novel, but the combination of which is really nice to use in practice: <strong>Changes are distinct from revisions: an idea borrowed from Mercurial, but quite different from Git’s model. Conflicts are first-class items: an idea borrowed from Pijul and Darcs.</strong> The user interface is not only reasonable but actually really good: an idea borrowed from… literally every VCS other than Git.&rdquo;</div></blockquote><p>I don&rsquo;t think that this is true. but I have perhaps more experience with <span class="quote-inline">&ldquo;literally every VCS&rdquo;</span> than the author does. For example, Perforce changelists are anything but intuitive for new users. TFS and Subversion branches were a horror to deal with. Every feature of VSS was only <em>tolerated</em> because it was amazing to have source control at all.. It&rsquo;s not just Git that has difficulties with UX.</p>
<p>The author is being a dick here, taking easy swipes that they know no-one will question. They just expect to get an <em>amen</em> from their chorus who think that, because there is room for improvement in the Git UX, that every other tool must be better. This is not true. But it doesn&rsquo;t matter because Git can&rsquo;t just be an amazing tool for which GUIs have filled the gaps in its UX: it has to suck in order for Jujutsu to save us all from it. People are tiring.</p>
<h2>It&rsquo;s a Google thing</h2><blockquote class="quote quote-block "><div>&ldquo;[…] given it is <strong>being actively developed at and by Google</strong> for use as a replacement for its current custom VCS setup, it <strong>seems like it has a good future ahead of it.</strong>&rdquo;</div></blockquote><p>That is such a naive thing to say, given the history of most of the software that comes out of Google. The best that you can hope for is that Google doesn&rsquo;t try actively kill it while an open-source community tries to keep it alive.</p>
<h2>Jujutsu&rsquo;s features</h2><blockquote class="quote quote-block "><div>&ldquo;Jujutsu has two discrete operations: <code>describe</code> and <code>new</code>. <code>jj describe</code> lets you provide a descriptive message for any change. <code>jj new</code> starts a new change. You can think of <code>git commit –message &ldquo;something I did&rdquo;</code> as being equivalent to <code>jj describe –message &ldquo;some I did&rdquo; &amp;&amp; jj new</code>. This falls out of the fact that <strong><code>jj describe</code> and <code>jj new</code> are orthogonal, and much more capable than <code>git commit</code> as a result.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;[…] a given change logically the child of four other changes, with identifiers <code>a</code>, <code>b</code>, <code>c</code>, and <code>d</code>? <code>jj new a b c d</code>. That’s it. One neat consequence that falls out of this: a merge in Jujutsu is just <code>jj new</code> with the requirement that it have at least two parents. (“At least two parents” because having multiple parents for a merge is not a special case as with Git’s “octopus” merges.)&rdquo;</div></blockquote><p>When would you need this? Am I missing a use case? I&rsquo;ve never felt particularly like I needed to merge four branches together but I&rsquo;m just a simple guy with simple needs. I&rsquo;m sure I&rsquo;m missing something by not wrangling four simultaneous branches instead of programming. Is this something that LLMs need maybe?</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] you can describe the change you are working on and then keep working on it . The act of describing the change is distinct from the act of “committing” and thus starting a new change. This falls out naturally from the fact that the working copy state is something you can operate on directly: <strong>akin to Git’s index, but without its many pitfalls.</strong>&rdquo;</div></blockquote><p>What pitfalls does Git&rsquo;s index have? It seems pretty useful to me. At the end of the article, he actually backs off on this and admits that Git&rsquo;s index is kinda necessary for staging parts of the workspace. Also, the whole feature—separating &ldquo;describing&rdquo; and &ldquo;committing&rdquo;—isn&rsquo;t as revelatory as he&rsquo;s making it out to be.</p>
<blockquote class="quote quote-block "><div>&ldquo;With <code>jj new -A &lt;some change ID&gt;</code>, <strong>you just insert the change directly into the history.</strong> Jujutsu will rebase every child in the history, including any merges if necessary; it “just works”. <strong>That does not guarantee you will not have conflicts, of course,</strong>&rdquo;</div></blockquote><p>Um. Ok. I mean, how could it possibly have guaranteed that? It&rsquo;s not magic. Conflicts are the nasty part, though, and are always more difficult to deal with when doing operations on multiple commits at once.</p>
<h2>Delaying conflict-resolution is cool</h2><blockquote class="quote quote-block "><div>&ldquo;Jujutsu can incorporate both the merge and its resolution (whether manual or automatic) directly into commit history. Just having the conflicts in history does not seem that weird. “Okay, you committed the text conflict markers from git, neat.” But: <strong>having the conflict and its resolution in history, especially when Jujutsu figured out how to do that resolution for you, as part of a rebase operation?</strong> That is just plain wild .&rdquo;</div></blockquote><p>I kind of like the idea of committing conflicts instead of forcing the user to resolve them immediately. That&rsquo;s a good idea. It lets you revisit the merge by preserving the inputs.</p>
<blockquote class="quote quote-block "><div>&ldquo;Jujutsu will add conflict markers to a file, not unlike those Git adds in merge conflicts. However, unlike Git, those are not just markers in a file. They are <strong>part of a system which understands what conflicts are semantically, and therefore also what resolving a conflict is semantically.</strong> This not only produces nice automatic outcomes like the one I described with my library above; it also means that you have more options for how to accomplish a resolution, and for how to treat a conflict. Git trains you to see a conflict between two branches as a problem. <strong>It requires you to solve that problem before moving on. Jujutsu allows you to treat a conflict as a problem which [must eventually] be resolved,</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Jujutsu allows you to create a merge, leave the conflict in place, and then introduce a resolution in the next commit</strong>, telling the whole story with your change history.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Conflicts are inevitable when you have enough people working on a repository. Honestly: conflicts happen when I am working alone in a repository, as suggested by my anecdote above. <strong>Having this ability to keep working with the repository even in a conflicted state, as well as to resolve the conflicts in a more interactive and iterative way is something I now find difficult to live without.</strong>&rdquo;</div></blockquote><p>The article discusses <em>retaining conflicts in commits as first-class, semantically valuable artifacts</em> that the conflict resolver can either resolve immediately or <em>later</em> when another commit comes along to make the conflict go away. This is very interesting for multi-commit rebases where git currently makes you resolve the conflicts <em>every step of the way</em>, even when you <em>know</em> that the conflict will definitely go away further up the chain.</p>
<p>Often, you don&rsquo;t even remember how you actually want to resolve the conflict in the &ldquo;old&rdquo; commits—and you don&rsquo;t care. This only happens with rebase, which I use much, much, much more than merge. When you merge, git considers the sum of all changes in all commits that you&rsquo;re merging, so you get the behavior you want: the sum of the commits eliminate irrelevant conflicts. Rebase in git doesn&rsquo;t benefit from this behavior. In jujutsu, it does.</p>
<h2>Massaging your commits is good, too</h2><blockquote class="quote quote-block "><div>&ldquo;[…] this ability to move part of one change into a different change is a really useful thing to be able to do in general. I find it particularly handy when building up a set of changes where I want each one to be coherent — say, <strong>for the sake of having a commit history which is easy for others to review.</strong>&rdquo;</div></blockquote><p>Yes, of course. Some of us have just been using powerful GUIs to do this for a long time, with hotkeys flying, instead of furiously typing commands into a command line. This is a laudable goal. I&rsquo;m glad that jujutsu brings that experience—and that ability—to command-line users.</p>
<h2>Wait. No branch names?</h2><blockquote class="quote quote-block "><div>&ldquo;The default log template shows me the current set of branches, and their <strong>commit messages are usually sufficiently informative that I do not need anything else.</strong>&rdquo;</div></blockquote><p>Sure, ok. No branch label required. That&rsquo;s definitely not a recipe for disaster for most developers. It never struck me as too burdensome to have to make little bookmarks, really. It felt kind of obvious and logical. I guess I didn&rsquo;t notice that I was wasting time when I could have just been reading commit messages instead.</p>
<h2>Acknowledging Git GUIs</h2><blockquote class="quote quote-block "><div>&ldquo;<strong>GUI tools could make all of those much easier. Any number of the Git GUI s have tried, but Git’s underlying model simply makes it clunky.</strong> That does not have to be the case with Jujutsu. Likewise, surfacing things like Jujutsu’s operation and change evolution logs should be much easier than surfacing the Git reflog, and provide easier ways to recover lost work or simply to change one’s mind.&rdquo;</div></blockquote><p>First of all, I don&rsquo;t think there&rsquo;s that strong a point to make here. A GUI like SmartGit manages to elide a lot of the complexity and has done so for years.</p>
<p>I wonder if Syntevo is working on anything for <code>jj</code>? Or is there no point because SmartGit has actually already been doing what Jujutsu does for a while? Maybe there is an advantage to storing the conflicts that SmartGit could also leverage.</p>
<h2>Editing history for code you don&rsquo;t have checked out</h2><p>The article <a href="https://drewdevault.com/2024/12/10/2024-12-10-Daily-driving-jujutsu.html">I&rsquo;m daily driving Jujutsu, and maybe you should too</a> by <cite>Drew Devault</cite> writes,</p>
<blockquote class="quote quote-block "><div>&ldquo;As a git power user, I rely heavily on <code>git rebase</code> to edit my git history as I work, <strong>frequently squashing and splitting and editing commits as I work</strong>, and I used “stacked diffs” without branches before it was cool.&rdquo;</div></blockquote><p>Same. I&rsquo;ve just never done it on the command-line, so I&rsquo;ve never felt the pain of doing any of this git-fu there. SmartGit makes most of my history-editing seamless, easy, and foolproof. I know all of you console-jockeys hate them but give me drag-and-drop operations any day.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;When I edited this earlier commit, I was in the middle of working on something else and I hadn’t committed or even staged it. I did not run <code>git stash</code>, nor <code>git commit -m&rdquo;WIP&rdquo;</code>, nor <code>git add</code>, nor <code>git checkout</code>, nor <code>git rebase</code>, at any point. The only command I ran was <code>jj squash</code>. <strong>When it was done, I was returned immediately to where I left off, with a half-written, uncommitted change in my workdir. It took all of two seconds to complete this operation and pick up where I left off.</strong></p>
<p>&ldquo;The “wow” moment came when I realized that I had done this several times that day without finding it particularly remarkable. <strong>Jujutsu makes editing history absolutely effortless.</strong>&rdquo;</p>
</div></blockquote><p>This is, I think, the killer feature of jujutsu: <em>you can edit history that you don&rsquo;t currently have checked out.</em></p>
<p>While better conflict-handling and editing commits anywhere in the tree are attractive features, I still feel that switching back to using the command-line would incur enough drawbacks to outweigh the benefits for me.</p>
<p><span style="width: 600px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5297/jujutsu_kaisen.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5297/jujutsu_kaisen.webp" alt=" " style="width: 600px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5297/jujutsu_kaisen.webp">Jujutsu Kaisen is a completely unrelated anime</a></span></span></p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5297_1_body" class="footnote-number">[1]</span> <p>That article wrote,</p>
<blockquote class="quote quote-block "><div>&ldquo;There are a number of things that Jujutsu got right, he said. For example, history is malleable by default. &ldquo;It&rsquo;s almost as if you were permanently in an interactive rebase mode, but without all the confusing parts.&rdquo; When history is rewritten in Jujutsu all dependents update automatically &ldquo;so if you added a commit, all children are rebased automatically&rdquo;. Conflicts are data, not emergencies. &ldquo;You can commit them and resolve them at any later point in time.&rdquo; These features are nice to have, he said, and <strong>fundamentally change how users think about commits. &ldquo;You stop treating them as precious artifacts and rather start treating them as drafts that you can freely edit&rdquo;.</strong>&rdquo;</div></blockquote></div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=6035</guid>
    <title><![CDATA[Optimize by keeping only the code you need]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=6035</link>
    <pubDate>Sun, 08 Feb 2026 17:16:25 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Feb 2026 17:16:25 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In the video <a href="https://vimeo.com/644068002">Context is Everything</a> by <cite>Andreas Fredriksson</cite> (<cite><a href="http://vimeo.com/">Vimeo</a></cite>), the author pinpoints that a dependency in his app—a JSON-handling library—is sucking all the performance out of it.</p>
<p>So, he takes a look at it.</p>
<p>It&rsquo;s a general-purpose library, with a lot of edge cases…edge cases that his input data doesn&rsquo;t have. That is, if he can guarantee a certain <em>context</em>, then he can use an optimized version of the JSON library&rsquo;s code. This isn&rsquo;t always going to be the solution—it will, in fact, rarely be the solution for a LOB app for which every line of maintenance is a burden—but, when you&rsquo;re making something with performance constraints, it&rsquo;s good to be able to think like this. [1]</p>
<p>He takes the original JSON library and profiles it. Then he starts to excise the slow bits—bits his app doesn&rsquo;t need anyway. This gets him impressive performance boosts.</p>
<p>First, he gets it to be 2x faster with a simple linear fix (removing unneeded branches), then  boosts it to over 11x faster by using a mixed-parsing mode.</p>
<p>Another profile shows that a function called <code>isspace()</code> is taking up 45% of the processing time now. He trims that down to just handle the whitespace characters his file might actually contain. He also ditches the <em>locale check</em> that happened <em>every single time</em>.</p>
<p>17x faster now.</p>
<p>OK. What else can we do? Ah, we could observe that the data doesn&rsquo;t have to contain spaces at all! That is, instead of parsing the spaces as they come along, you can use a SIMD-based solution combined with a LUT (Look-Up Table) to normalize the input data before you even parse it. He uses a quick-and-dirty Perl script to build the LUT.</p>
<p>22x faster now.</p>
<p>That performance improvement alone is 5x more than the original speed of the parser.</p>
<blockquote class="quote quote-block "><div><ul>
<li>We just removed a bunch of poorly predicted branches, nothing else</li>
<li>Low-level thinking = not paying for things you don&rsquo;t need</li>
<li>Low-level thinking = partition work in hardware-friendly ways</li></ul><p>&ldquo;[…]</p>
<p>&ldquo;We didn&rsquo;t change any of the behavior of the program. All we did was we separated these two passes in a way that was friendly for the hardware. We moved branches from being in the integer control flow to being inside masks in the SIMD flow.&rdquo;</p>
</div></blockquote><p>The next step is to reexamine what &ldquo;white space&rdquo; actually is: he reinterprets it to mean anything that&rsquo;s not a printable character, which allows him to optimize the mask even further.</p>
<p>29x faster.</p>
<p>Over 1GB/s of throughput.</p>
<p>Are we done? Bitch, please.</p>
<p>He moves on to two more levels of optimization that still bring good-sized gains, but at the cost of more complexity. They also contain more <em>assumptions</em> but that&rsquo;s <em>OK</em> if the assumptions will always be correct. You want to stop optimizing when it makes sense for your use case. If you&rsquo;re writing code for a very tight loop on some low-level hardware—or in a game where the budget per frame is a maximum of 16ms—then it might be very important: you might end up saving incredible amounts of time for your users; you might be using a <em>lot</em> less power.</p>
<blockquote class="quote quote-block "><div><ul>
<li><div>Solve the right problem<ul>
<li>Ask the right questions</li>
<li>Consider the liabilities and overall economics of your approach</li></ul></div></li>
<li><div>Consider the unique context and the potentially massive wins<ul>
<li>Generic means &ldquo;not tuned for your use case&rdquo;</li></ul></div></li>
<li>Don&rsquo;t be afraid to look inside</li></ul></div></blockquote><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_6035_1_body" class="footnote-number">[1]</span> I can&rsquo;t help but notice that this is absolutely not what LLMs tend to do: they don&rsquo;t know how to remove code. They don&rsquo;t know how to remove unnecessary functionality. Maybe you can corral it into doing so but I&rsquo;ve not read of too many experiments in that direction.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=6001</guid>
    <title><![CDATA[Learning about OCaml Effects]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=6001</link>
    <pubDate>Sun, 18 Jan 2026 12:08:41 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. Jan 2026 12:08:41 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/6001/ocaml_logo.webp"><img src="https://www.earthli.com/data/news/attachments/entry/6001/ocaml_logo_tn.webp" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/6001/ocaml_logo.webp">OCaml Logo</a></span></span>I don&rsquo;t program with OCaml. I never have. I have a good colleague who does, occasionally, write stuff in OCaml, and he sent me a bunch of links about OCaml Effects, starting with a discussion asking <a href="https://discuss.ocaml.org/t/are-we-rational-about-exceptions-and-effects/17111">Are we rational? About exceptions and effects</a> by <cite>olleharstedt</cite> (<cite><a href="http://discuss.ocaml.org/">OCaml Community</a></cite>).</p>
<p>The author writes,</p>
<blockquote class="quote quote-block "><div>&ldquo;I was thinking about the fact that there’s no consensus about exceptions and whether to include them or not in a programming language. <strong>Think about Go. They decided to not add support for exceptions. Did they cite any study to support this decision</strong>, that supports the notion that exceptions in general lower the quality[1] of the ecosystem? Not that I know of. <strong>Now OCaml goes in the opposite direction − adding more ways to jump around in the code, with effects. Also no studies, no experiments.</strong>&rdquo;</div></blockquote><p>This is an excellent point to make: we consider ourselves to be rational engineers and scientists but, very often, we nearly completely elide our reasoning for major decisions about architecture and functionality. [1]</p>
<p>From there, I was intrigued to learn more about this controversial feature in OCaml and I landed on the documentation page called <a href="https://ocaml.org/manual/5.3/effects.html">Chapter 12 Language extensions − 24 Effect handlers</a> (<cite><a href="http://ocaml.org/">OCaml Manual</a></cite>), which summarizes its topic as follows,</p>
<blockquote class="quote quote-block "><div>&ldquo;Effect handlers are a mechanism for modular programming with user-defined effects. Effect handlers allow the programmers to describe computations that perform effectful operations, whose meaning is described by handlers that enclose the computations. <strong>Effect handlers are a generalization of exception handlers and enable non-local control-flow mechanisms such as resumable exceptions, lightweight threads, coroutines, generators and asynchronous I/O to be composably expressed.</strong>&rdquo;</div></blockquote><p>While I—someone who&rsquo;s been reading programming-language specifications for over 30 years—really like the sound of that, I&rsquo;m forced to admit that most of the documentation, while comprehensible to someone versed in language constructs and terminology, serves as a perfect example of &ldquo;why no-one uses OCaml.&rdquo;</p>
<p>It is <em>dense</em>.</p>
<p>Consider the following description of a concept like exception-handling, which many programmers can grok relatively easily, when it&rsquo;s been abstracted away into a generalized effect mechanism, described as follows,</p>
<blockquote class="quote quote-block "><div>&ldquo;We run the computation <code>comp1 ()</code> under an effect handler that handles the <code>Xchg</code> effect with a continuation bound to <code>k</code>. Here <code>effect</code> is a keyword which signifies that the <code>Xchg n</code> pattern matches effects and not exceptions. As mentioned earlier, effect handlers are a generalization of exception handlers. Similar to exception handlers, when the computation performs the <code>Xchg</code> effect, the control jumps to the corresponding handler, and unhandled effects are forwarded to the outer handler. However, unlike exception handlers, the handler is also provided with the delimited continuation <code>k</code>, which represents the suspended computation between the point of <code>perform</code> and this handler.&rdquo;</div></blockquote><p>This is not to take anything away from the documentation—which is precise, indubitably accurate, extensive, and replete with examples—but you&rsquo;re not going to be onboarding any newcomers or dilettantes with this kind of stuff.</p>
<p>As a sign that even OCaml community members are aware that this might be a problem, the page <a href="https://github.com/ocaml-multicore/ocaml-effects-tutorial">Concurrent Programming with Effect Handlers</a> (<cite><a href="http://github.com/">GitHub</a></cite>) offers another view on it. It describes OCaml effects as,</p>
<blockquote class="quote quote-block "><div><p>&ldquo;An algebraic effect handler is a programming abstraction for manipulating control-flow in a first-class fashion. They <strong>generalise common abstractions such as exceptions, generators, asynchronous I/O, or concurrency</strong>, as well as other seemingly esoteric programming abstractions such as transactional memory and probabilistic computations.</p>
<p>&ldquo;<strong>Operationally, effect handlers offer a form of first-class, restartable exception mechanism.</strong> In this tutorial, we shall introduce gently algebraic effect and handlers with gentle examples and then continue on to more involved examples.&rdquo;</p>
</div></blockquote><p>Don&rsquo;t get me wrong, I find reading about a generalized mechanism that collects all of the effect-ful mechanisms hard-coded into other languages <em>fascinating</em>. With effects, OCaml has sacrificed &ldquo;elegance and approachability of the language&rdquo; for &ldquo;provability of the program&rdquo;. Even if the number of people who end up using this feature in OCaml amounts to a rounding error, I think that research into mechanisms like this is vital because it leads to improvements in other, more mainstream languages.</p>
<p>Related to this all is a practical implementation using effects for a laudable goal: inversion of control and dependency injection [2], for which the approaches in OCaml are described in detail in <a href="https://gr-im.github.io/a/dependency-injection.html">Basic dependency injection with objects</a> (<cite><a href="http://gr-im.github.io/">Grim&#039;s web corner</a></cite>). It discusses two common approaches to DI in OCaml and then proposes a more practical alternative.</p>
<p>On the effect-based approach, the author writes,</p>
<blockquote class="quote quote-block "><div>&ldquo;an Effect system is often described as <strong>a systematic way to separate the denotational description of a program, where propagated effects are operational “holes” that are given meaning via a handler</strong>, usually providing the ability to control the program’s execution flow (its continuation), unlocking the possibility to describe, for example, concurrent programs.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;It’s quite amusing to see that <strong>dependency injection and exception capturing can be considered two special cases of effect abstraction</strong>, differing only in how the continuation is handled.&rdquo;</div></blockquote><p>Spoiler: the author ends up using objects rather than modules (weak type-inference support, overly verbose) or effects (weak type-inference support, complexity).</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_6001_1_body" class="footnote-number">[1]</span> <p>Where the OCaml discussion centers on the rationality of how a working group chooses which features to include in a programming language, the article <a href="https://spf13.com/p/the-hidden-conversation/">Why Engineers Can&rsquo;t Be Rational About Programming Languages</a> by <cite>Steve Francia</cite> (<cite><a href="http://spf13.com/">spf13</a></cite>) has a very good discussion about the general irrationality that influences choosing a programming language for a project.</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] <strong>what struck me was how broken their reasoning was.</strong> If they were making a logical argument, surely they would have considered Go and in doing so with their presented criteria they would have realized Go was a better option and, at the very least, refined their criteria. I pulled the VP aside after the meeting. <strong>“Walk me through how you evaluated other language candidates,” I said. His face went blank. “We… didn’t really look at any others,” he admitted. “Everyone’s talking about Rust.” There it was: a 50 million dollar decision made on hype, about to be green lit.</strong> For me this was the moment of epiphany, finally an answer to the question for the beginning of my career. <strong>The presentation didn’t share an analysis, they hadn’t done one; it was a justification for a choice already made.</strong> This was a decision based purely on hype, emotion, and identity.&rdquo;</div></blockquote><p>This is utterly unsurprising. No evaluation. Gut feeling. Justify <em>that</em> when things go tits-up. Or maybe—and stick with me here—it wouldn&rsquo;t have gone tits-up if you&rsquo;d done an evaluation.</p>
<blockquote class="quote quote-block "><div>&ldquo;The researchers’ conclusion was stark: <strong>“To consider an alternative view, you have to imagine an alternative version of yourself.”</strong> Your brain can’t objectively evaluate challenges to identity based beliefs because doing so requires temporarily dismantling the neural architecture that defines who you are. It’s not a matter of being more rational or trying harder. <strong>The mechanism that would allow you to see the bias clearly is the same mechanism the bias has compromised.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Every time an engineer evaluates a language that isn’t “theirs,” their brain is literally working against them. They’re not just analyzing technical trade offs, <strong>they’re contemplating a version of themselves that doesn’t exist yet, that feels threatening to the version that does.</strong> The Python developer reads case studies about Go’s performance and their amygdala quietly marks each one as a threat to be neutralized. <strong>The Rust advocate looks at identical problems and their Default Mode Network constructs narratives about why “only” Rust can solve them.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;The moment you hire a Rust developer to evaluate languages, you’ve already chosen Rust. <strong>You’ve just added a $2 million feasibility study to make the predetermined decision feel rational.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Industry research suggests that technology stack decisions account for 40-60% of total development costs over a product’s lifecycle.</strong> Research by Stripe found that developers spend 42% of their time on technical debt.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Instead of asking “which language is best?” we need to ask “what is this language going to cost us?”</strong> Not just in salaries, but in velocity, in technical debt, in hiring difficulty, in operational complexity, in every dimension that actually determines whether you survive.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Choosing a programming language is the single most expensive economic decision your company will make.</strong> It will define your culture, constrain your budget, determine your hiring pipeline, set your operational costs, and ultimately dictate whether you can move fast enough to win your market.&rdquo;</div></blockquote><p>This goes for frameworks and technologies as well.</p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_6001_2_body" class="footnote-number">[2]</span> <p>Something that I&rsquo;ve been writing about quite extensively recently. See, e.g.,</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=5903">Discussing DI, IOC, and containers</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=5982">Thinking about the null-object pattern</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=5857">The goal is to test everything automatically</a></li></ul></div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5857</guid>
    <title><![CDATA[The goal is to test everything automatically]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5857</link>
    <pubDate>Fri, 16 Jan 2026 09:21:34 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Jan 2026 09:21:34 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>So it all started with the following line of code in the <code>Startup.cs</code> of a WPF application,</p>
<pre class=" "><code>locator.GetInstance&lt;IAuthenticationService&gt;().LogInBasedOnGeneralSettings();</code></pre><p>It was to be replaced with these lines of code.</p>
<pre class=" "><code>#if DEBUG
    locator.GetInstance&lt;IAuthenticationService&gt;().LogInBasedOnGeneralSettings();
#else 
    locator.GetInstance&lt;LoginViewModel&gt;().Show();
#endif</code></pre><h2>Reduce startup complexity</h2><p>Going by the single-responsibility principle, the startup should be responsible for starting the app but not for making decisions.</p>
<p>The new code makes a decision, so it should be encapsulated in a component. </p>
<p>The simplest (though not testable) way of reducing <a href="https://www.sonarsource.com/docs/CognitiveComplexity.pdf">cognitive complexity</a> (<cite><a href="http://www.sonarsource.com/">SonarCube</a></cite>) (PDF Download) is to move the logic to a function. E.g.,</p>
<pre class=" "><code>private void EnsureLoggedIn(IServiceLocator locator)
{
#if DEBUG
    locator.GetInstance&lt;IAuthenticationService&gt;().LogInBasedOnGeneralSettings();
#else 
    locator.GetInstance&lt;LoginViewModel&gt;().Show();
#endif
}</code></pre><p>Now the calling code is much simpler,</p>
<pre class=" "><code> EnsureLoggedIn(locator);</code></pre><h2>Define a login service</h2><p>I also like to reduce calls to <code>locator.GetInstance()</code> as much as possible, so I prefer do define something like a <code>LoginService</code> that consumes the <code>IAuthenticationService</code> and the <code>LoginViewModel</code>, so that you have something like this:</p>
<pre class=" "><code>class LoginService(
    IAuthenticationService authenticationService,
    LoginViewModel loginViewModel)
{
    public void EnsureLoggedIn()
    {
#if DEBUG
        authenticationService.LogInBasedOnGeneralSettings();
#else 
        loginViewModel.Show();
#endif
    }
}</code></pre><p>Now we can make the method in the startup file use the <code>LoginService</code> instead.</p>
<pre class=" "><code>locator.GetInstance&lt;LoginService&gt;().EnsureLoggedIn()</code></pre><p>We don&rsquo;t need to pollute the startup with the nuance of which mode we&rsquo;re in.</p>
<h2>Making it testable</h2><p>A colleague responded that,</p>
<blockquote class="quote quote-block "><div>&ldquo;But then you have to […] inject a ViewModel into a Service?&rdquo;</div></blockquote><p>I&rsquo;ll include the reply to show how the sausage is made: instead of just showing the solution, I often appreciate learning how people think about problems.</p>
<p>So, here was my response,</p>
<p>I&rsquo;m not trying to be pedantic; it just comes naturally. 😃</p>
<ul>
<li>I was going to write that injecting a <code>ViewModel</code> into a service isn&rsquo;t bad because it&rsquo;s just a view model. But then I noticed that it seems to be communicating with the view in order to show something to the user. 😃</li>
<li>We&rsquo;re trying to abstract away complexity and to make our logic testable.</li>
<li>We need to call <code>Show()</code> during startup; that&rsquo;s a fact. If we introduce a service, it actually makes that part mockable.</li>
<li>If we wanted to test that the <code>LogInBasedOnGeneratedSettings()</code> is called when expected, we couldn&rsquo;t do that right now, could we?</li>
<li>If we make it a service, then we could think about verifying the logic with a test.</li>
<li>Of course, once we want to build the test, we&rsquo;d then be confronted with the need to abstract away the compiler-define. Otherwise, we wouldn&rsquo;t be able to test both branches without recompiling. That&rsquo;s a code smell, too.</li>
<li>Which is why I usually end up with some standard settings objects like the following.</li></ul><pre class=" "><code>public interface ICompilerSettings
{
    public bool IsDebug { get; }
}

public class CompilerSettings : ICompilerSettings
{
    public bool IsDebug
    {
        get
        {
#if DEBUG
        return true;
#else 
        return false;
#endif
        }
    }
}

public interface ILoginServiceSettings
{
    public bool ForceLogin { get; }
}

public class LoginServiceSettings(ICompilerSettings compilerSettings) : ILoginServiceSettings
{
    public bool ForceLogin =&gt; !compilerSettings.IsDebug;
}</code></pre><p>You might think that this is over-engineering, overkill, an excess of ceremony introduced by an architect astronaut!</p>
<p>I, on the other hand, think that this is a minimal solution that separates concerns and makes all branches testable.</p>
<p>Once we inject the <code>ILoginServiceSettings</code> into the <code>LoginService</code>, we can easily verify the behavior with tests (using fakes, mocks, etc.).</p>
<pre class=" "><code>class LoginService(ILoginServiceSettings settings,
    IAuthenticationService authenticationService,
    LoginViewModel loginViewModel)
{
    public void EnsureLoggedIn()
    {
        if (!settings.ForceLogin())
        {
            authenticationService.LogInBasedOnGeneralSettings();
        }
        else
        {
            loginViewModel.Show();
        }
}</code></pre><p>It might look like a lot of ceremony but, without it, how else can you say with confidence that the login is required in some cases but not others? We can even verify that it&rsquo;s not required in <code>DEBUG</code> mode by mocking <code>ICompilerSettings</code>.</p>
<p>Then the only thing we have to verify without automated tests is that the <code>CompilerSettings</code> are implemented as expected, which is very little code to manually check. We don&rsquo;t need to look at the rest. 👍</p>
<h2>We want to test everything</h2><p>My colleague very politely responded,</p>
<blockquote class="quote quote-block "><div>&ldquo;Injecting ViewModels into Services is generally considered bad practice. The rest seems to depend on what you wish to test and don&rsquo;t overengineer it…&rdquo;</div></blockquote><p>At this point, we took the conversation to meatspace, i.e., I ran over to his desk to tell him that &ldquo;I always want to <em>test everything</em>.&rdquo; I am willing to concede on time constraints, priority, and planning, but my goal is &ldquo;test all the code paths&rdquo; <em>eventually</em>. I&rsquo;m patient, though, so will accept unwritten tests as technical debt. I will design my could so that it <em>could</em> be tested, though, when we eventually find time to do so. This </p>
<p>We shouldn&rsquo;t just punt on tests because &ldquo;it looks difficult&rdquo; or &ldquo;it&rsquo;s not much logic&rdquo;. </p>
<p>In the first case, the fact that it looks difficult may indicate you&rsquo;re not writing your code in a testable way or may reveal architectural problems. In the second case, those are famous last words. If it&rsquo;s just a little logic, then why wouldn&rsquo;t you just test it instead of investing the time arguing that you don&rsquo;t need a test?</p>
<p>If you have a code base that’s difficult to test because of some unfortunate architectural decisions, then the thing to  do is <em>not to ignore it</em> but to <em>slowly chip away at it.</em></p>
<p>How else would we get a higher percentage of our code covered by tests? Hint: it&rsquo;s not by continuing to write more code without tests.</p>
<h2>Addendum: A note on architectural boundaries</h2><p>He&rsquo;d also argued about mixing levels—injecting a <code>ViewModel</code> into a <em>service</em>—but I convinced him that this is already what was happening whether you wrap a service around it or not. The startup is already instantiating and using a view model. Is that somehow better?</p>
<p>I don&rsquo;t think it&rsquo;s a bad thing, as it&rsquo;s just a way of asking the user for input in order to continue starting the application. It&rsquo;s a step in the application startup. If you wrap it in a service, then you can at least test that the code does what you want. <strong>This is exactly the kind of thing that everyone is going to forget to test manually.</strong></p>
<p>Should the startup be using the view? Maybe, maybe not. It currently <em>does</em> and it makes for a legible workflow. Being too pedantic about architectural  boundaries <em>just for the sake of it</em> is often wasted effort and can often lead to overly complex solutions.</p>
<p>Ordinarily, the problem would be that introducing a dependency across a boundary weakens testability, but that&rsquo;s obviously not the case here. We can just mock away the view and test all of our logic.</p>
<p>I wouldn&rsquo;t worry about this one too much, though it&rsquo;s a good rule of thumb.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5991</guid>
    <title><![CDATA[Using extensions for operators in C# 14]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5991</link>
    <pubDate>Tue, 13 Jan 2026 22:59:03 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Jan 2026 22:59:03 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://laurentkempe.com/2025/12/29/csharp-14-extension-members-complete-guide/">C# 14 Extension Members: Complete Guide to Properties, Operators, and Static Extensions</a> by <cite>Laurent Kempe</cite> writes,</p>
<blockquote class="quote quote-block "><div>&ldquo;Perhaps the most powerful C# 14 capability is extension operators. You can now <strong>add user-defined operators to types you don’t control, enabling natural mathematical operations.</strong>&rdquo;</div></blockquote><p>When I first saw this, I thought it was kind of gimmick-y. But I just realized why it&rsquo;s very nice that you can declare operators separately—<em>optionally</em>—from the type. Adding operators by default is a heavy decision in most APIs. You generally don&rsquo;t do it except for the most obvious cases, like matrices, etc. where there is really only one possible way to implement the standard operators.</p>
<p>However, for a lot of other types, it would be convenient to have these operators but they might be annoying for some. This way, you can either add them in yourself—tailoring the implementation for your needs—or you can pull in a NuGet package that <em>extend</em> standard types with operators. This allows you to <em>opt in</em> to the operators.</p>
<p>With these new extensions, we&rsquo;re probably going to see more lightweight types that are delivered in multiple NuGet packages, the satellite packages being extensions that enhance the base type for specific scenarios.</p>
<p>The author demonstrates such a custom operator, using tuples.</p>
<pre class=" "><code>extension(Point point)
{
    public static Point operator +(Point point, (int dx, int dy) offset) =&gt;
        new Point(point.X + offset.dx, point.Y + offset.dy);
}

// Usage:
Point translated = <strong class="highlight">myPoint + (5, -3);</strong></code></pre><p>Nice.</p>
<p><img title="C# Logo" src="https://www.earthli.com/data/news/attachments/entry/5991/csharp-icon-clr.webp" alt=" " class=" align-center"></p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5982</guid>
    <title><![CDATA[Thinking about the null-object pattern]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5982</link>
    <pubDate>Sat, 27 Dec 2025 22:27:23 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">27. Dec 2025 22:27:23 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I had never thought of an <code>if</code> statement as a type-check until a Smalltalk programmer explained it to me in this video. She explained how Smalltalk has six keywords—according to <a href="https://en.wikipedia.org/wiki/Smalltalk">Wikipedia</a>, they&rsquo;re <code>true</code>, <code>false</code>, <code>nil</code>, <code>self</code>, and <code>super</code>, but her list had <code>thisContext</code> on it as well [1]—and you can get rid of conditions and turn them into message-passing instead, <em>as God intended</em>.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/OMPfEXIlTVE" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=OMPfEXIlTVE">RailsConf 2015 − Nothing is Something</a> by <cite>Sandi Metz</cite> on May 1, 2015 (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>From the official video description,</p>
<blockquote class="quote quote-block "><div>&ldquo;Our code is full of hidden assumptions, things that seem like nothing, secrets that we did not name and thus cannot see. These secrets represent missing concepts and this talk shows you how to expose those concepts with code that is easy to understand, change and extend. <strong>Being explicit about hidden ideas makes your code simpler, your apps clearer and your life better. Even very small ideas matter. Everything, even nothing, is something.</strong>&rdquo;</div></blockquote><h2>The null-object pattern</h2><p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5982/null-object_pattern.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5982/null-object_pattern_tn.webp" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5982/null-object_pattern.webp">Null-object pattern</a></span></span>I often use sentinel (or placeholder) objects so that I don&rsquo;t have to query a condition, like <code>if (a == null) {  }</code>. Instead, as Sandi says, you just <span class="quote-inline">&ldquo;pass a message&rdquo;</span>. She calls it the <span class="quote-inline">&ldquo;null-object pattern&rdquo;</span> or an <span class="quote-inline">&ldquo;active nothing&rdquo;</span>. Fine, cool. Lots of names for it.</p>
<p>As she also noted, you don&rsquo;t get <em>rid</em> of the conditional, but you <em>move</em> it to the place where the decision <em>should</em> be made, rather than propagating the decision to every caller or dependency.</p>
<p>She spent a lot of time on it, but it&rsquo;s basically about the following pattern, which is drastically simplified from what you&rsquo;d probably find in the wild.</p>
<pre class=" "><code>interface  IAnimal
{
    public string Name { get; }
}

class Animal : IAnimal
{
    public string Name { get; init; }
}

List&lt;IAnimal&gt; animals = [new Animal { Name = "Pig" }, null, new Animal { Name = "Cow" }];

foreach (var animal in animals)
{
    <strong class="highlight">if (animal != null)</strong>
    {
        Console.WriteLine(animal.Name);
    }
    <strong class="highlight">else</strong>
    {
        Console.WriteLine("no animal");
    }
}</code></pre><p>The <strong class="highlight">condition</strong> is the problem, because every client of that list has to deal with the possibility of <code>nulls</code>. One way to handle it would be to move the condition out of the (obvious) loop, eliding <code>nulls</code> from the list, as shown below.</p>
<pre class=" "><code><strong class="highlight">var actualAnimals = animals.Where(a =&gt; a != null);</strong>

foreach (var animal in <strong class="highlight">actual</strong>Animals)
{
    Console.WriteLine(animal.Name);
}</code></pre><p>You still have the conditional, of course, but you&rsquo;re also handling it just <em>once</em> and then letting the rest of your code be free of needing to deal with possible <code>nulls</code>.</p>
<p>However, this <em>hides</em> the <em>length</em> of the original list, which is not always what you want. What if you want to represent the &ldquo;empty&rdquo; slots? What if, as the talk is called, <span class="quote-inline">&ldquo;Nothing is Something&rdquo;</span>? Then you would use the <span class="quote-inline">&ldquo;null-object pattern&rdquo;</span>.</p>
<pre class=" "><code><strong class="highlight">class MissingAnimal : IAnimal
{
    public Name =&gt; "no animal";
}</strong>

var actualAnimals = animals.<strong class="highlight">Select</strong>(a =&gt; a <strong class="highlight">?? new MissingAnimal()</strong>);

foreach (var animal in actualAnimals)
{
    Console.WriteLine(animal.Name);
}</code></pre><p>Voila.</p>
<h2>Composition beats inheritance</h2><p>In the second act of this 36-minute talk, she demonstrates how to use composition rather than inheritance by ruthlessly applying the single-responsibility principle. She starts with a simple-looking class that returns some data.</p>
<pre class=" "><code>class Thing
{
    private IEnumerable&lt;string&gt; _data;

    public Thing(IEnumerable&lt;string&gt; data)
    {
        _data = data ?? throw new ArgumentNullException(nameof(data));
    }

    public IEnumerable&lt;string&gt; Data =&gt; _data;
}</code></pre><p>She then shows how you can use inheritance to make two descendants, one of which returns the data in a random order and another that returns the data with each entry doubled.</p>
<pre class=" "><code>class Thing
{
    private IEnumerable&lt;string&gt; _data;

    public Thing(IEnumerable&lt;string&gt; data)
    {
        _data = data ?? throw new ArgumentNullException(nameof(data));
    }

    public <strong class="highlight">virtual</strong> IEnumerable&lt;string&gt; Data =&gt; _data;
}

class RandomThing
{
    public override IEnumerable&lt;string&gt; Data =&gt; base.Data.Shuffle();
}

class DoubleThing
{
    public override IEnumerable&lt;string&gt; Data =&gt; base.Data.Zip(data, (x, y) =&gt; new[] { x, y }).SelectMany(o =&gt; o).
}</code></pre><p>Now try to make one that returns the data in a random order and doubles each entry. Don&rsquo;t repeat yourself.</p>
<p>With inheritance, you&rsquo;re quickly <a href="https://www.youtube.com/watch?v=nh3lICcIVrE">in a tight spot</a>.</p>
<p>The thing to remember is that you&rsquo;ve now introduced two new features to <code>Things</code>, which kind of slipped in there: <code>RandomThing</code> <em>orders</em> the data but does not <em>transform</em> it, whereas <code>DoubleThing</code> <em>transforms</em> the data but doesn&rsquo;t touch the <em>order</em>.</p>
<p>It sounds like the <code>Thing</code> now has <em>two</em> responsibilities, i.e., it addresses two <em>concerns</em>.</p>
<p>The answer is to separate out these two concerns into components and then to inject those components into the <code>Thing</code>. It&rsquo;s always the same answer. It&rsquo;s boring, right? Boring is good.</p>
<p>This is an intermediate step, to illustrate the simplest form of composition, with the fewest changes. It&rsquo;s going to be more code than we&rsquo;d like, but let&rsquo;s go ahead and write it.</p>
<pre class=" "><code>class Transformer
{
    public virtual IEnumerable&lt;string&gt; Transform(IEnumerable&lt;string&gt; data) =&gt; data;
}

class Doubler : Transformer
{
    public override IEnumerable&lt;string&gt; Transform(IEnumerable&lt;string&gt; data)
    {
        return data.Zip(data, (x, y) =&gt; new[] { x, y }).SelectMany(o =&gt; o);
    }
}

class Sorter
{
    public virtual IEnumerable&lt;string&gt; Sort(IEnumerable&lt;string&gt; data) =&gt; data;
}

class Shuffler : Sorter
{
    public override IEnumerable&lt;string&gt; Sort(IEnumerable&lt;string&gt; data) =&gt; data.Shuffle();
}

class Thing(IEnumerable&lt;string&gt; data, Transformer transformer, Sorter sorter)
{
    public IEnumerable&lt;string&gt; Data =&gt; sorter.Sort(transformer.Transform(data));
}

new Thing(["A", "B", "C"], new Doubler(), new Shuffler());</code></pre><p>This is immediately obviously suboptimal First of all, we should recognize that changing the order and transforming the data aren&rsquo;t different operations. They&rsquo;re both functions on a sequence that return another sequence. Instead of passing in a <code>Sorter</code> and a <code>Transformer</code>, as in the example in the video, we could instead pass in a sequence of transfomers to apply.</p>
<pre class=" "><code>class Transformer
{
    public virtual IEnumerable&lt;string&gt; Transform(IEnumerable&lt;string&gt; data) =&gt; data;
}

class Doubler : Transformer
{
    public override IEnumerable&lt;string&gt; Transform(IEnumerable&lt;string&gt; data)
    {
        return data.Zip(data, (x, y) =&gt; new[] { x, y }).SelectMany(o =&gt; o);
    }
}

class Shuffler : <strong class="highlight">Transformer</strong>
{
    public override IEnumerable&lt;string&gt; <strong class="highlight">Transform</strong>(IEnumerable&lt;string&gt; data) =&gt; data.Shuffle();
}

class Thing(IEnumerable&lt;string&gt; data, IEnumerable&lt;Transformer&gt; transformers)
{
    public IEnumerable&lt;string&gt; Data =&gt; <strong class="highlight">transformers.Aggregate(data, (current, t) =&gt; t.Transform(current))</strong>;
}

new Thing(["A", "B", "C"], [new Doubler(), new Shuffler()]);</code></pre><p>Another thing we can notice is how rigid this all is in the type of the item. Let&rsquo;s make this a more generalized pattern.</p>
<pre class=" "><code>class Transformer&lt;<strong class="highlight">T</strong>&gt;
{
    public virtual IEnumerable&lt;<strong class="highlight">T</strong>&gt; Transform(IEnumerable&lt;<strong class="highlight">T</strong>&gt; data) =&gt; data;
}

class Doubler&lt;<strong class="highlight">T</strong>&gt; : Transformer&lt;<strong class="highlight">T</strong>&gt;
{
    public override IEnumerable&lt;<strong class="highlight">T</strong>&gt; Transform(IEnumerable&lt;<strong class="highlight">T</strong>&gt; data)
    {
        return data.Zip(data, (x, y) =&gt; new[] { x, y }).SelectMany(o =&gt; o);
    }
}

class Shuffler&lt;<strong class="highlight">T</strong>&gt; : Transformer&lt;<strong class="highlight">T</strong>&gt;
{
    public override IEnumerable&lt;<strong class="highlight">T</strong>&gt; Transform(IEnumerable&lt;<strong class="highlight">T</strong>&gt; data) =&gt; data.Shuffle();
}

class Thing&lt;<strong class="highlight">T</strong>&gt;(IEnumerable&lt;<strong class="highlight">T</strong>&gt; data, IEnumerable&lt;Transformer&lt;<strong class="highlight">T</strong>&gt;&gt; transformers)
{
    public IEnumerable&lt;<strong class="highlight">T</strong>&gt; Data =&gt; transformers.Aggregate(data, (current, t) =&gt; t.Transform(current));
}

new Thing<strong class="highlight">&lt;string&gt;</strong>(["A", "B", "C"], [new Doubler<strong class="highlight">&lt;string&gt;</strong>(), new Shuffler<strong class="highlight">&lt;string&gt;</strong>()]);</code></pre><p>Note that now we have all of our logic independent of the type of item in the sequences. It&rsquo;s only in creating the <code>Thing</code> that you decide on the item type.</p>
<p>The <code>Transformer</code> is called a <em>functional interface</em>—i.e., an interface with a single function—which would be type-compatible with a function signature in Java, but still isn&rsquo;t in C#. It&rsquo;s kind of clunky and repeats a bunch of code. Can we get rid of it? Can we also get rid of the dynamic dispatch (i.e., the <code>virtual</code> and <code>override</code>)?</p>
<p>Sure, we can.</p>
<pre class=" "><code>class Thing&lt;T&gt;(IEnumerable&lt;T&gt; data, IEnumerable&lt;Func&lt;IEnumerable&lt;T&gt;, IEnumerable&lt;T&gt;&gt;&gt; transformers)
{
    public IEnumerable&lt;T&gt; Data =&gt; transformers.Aggregate(data, (current, t) =&gt; t(current));
}

new Thing&lt;string&gt;(["A", "B", "C"], [<strong class="highlight">data =&gt; data.Zip(data, (x, y) =&gt; new[] { x, y }).SelectMany(o =&gt; o), Shuffle</strong>]);</code></pre><p>Well, that&rsquo;s a lot less code, but it&rsquo;s a bit messy at the declaration point. One nice thing, though, is that we&rsquo;re only declaring the item type once now, in the type parameter to <code>Thing</code>.</p>
<p>We can clean that up a bit but we&rsquo;re going to be limited by the requirement to specify the type parameter as soon as we leave the constructor of the <code>Thing</code>. The <code>Shuffle</code> part is succinct enough but the <code>Double</code> part isn&rsquo;t at all obvious.</p>
<p>How about we encode the types in a static method call?</p>
<pre class=" "><code><strong class="highlight">public static class ThingTools
{
    public static IEnumerable&lt;T&gt; Double&lt;T&gt;(this IEnumerable&lt;T&gt; data)
    {
        return data.Zip(data, (x, y) =&gt; new[] { x, y }).SelectMany(o =&gt; o);
    }
}</strong>

new Thing&lt;string&gt;(["A", "B", "C"], [<strong class="highlight">ThingTools.Double</strong>, Shuffle]);</code></pre><p>That&rsquo;s quite a bit better. Now that we already have a helper class, we can keep improving things by making another helper method that allows us to create a <code>Thing</code> by passing in a collection of items without specifying the item type explicitly. Instead, the item type is picked up from the <code>data</code> passed in.</p>
<pre class=" "><code>public static class ThingTools
{
    public static IEnumerable&lt;T&gt; Double&lt;T&gt;(this IEnumerable&lt;T&gt; data)
    {
        return data.Zip(data, (x, y) =&gt; new[] { x, y }).SelectMany(o =&gt; o);
    }

    <strong class="highlight">public static Thing&lt;T&gt; Create&lt;T&gt;(IEnumerable&lt;T&gt; data, IEnumerable&lt;Func&lt;IEnumerable&lt;T&gt;, IEnumerable&lt;T&gt;&gt;&gt; transformers)
    {
        return new Thing&lt;T&gt;(data,transformers);
    }</strong>
}

<strong class="highlight">ThingTools.Create</strong>(["A", "B", "C"], [ThingTools.Double, data =&gt; data.Shuffle()]);</code></pre><p>Isn&rsquo;t that fun?</p>
<p>Did I go too far? You decide what you want to use based on your comfort level with any of the versions that use composition (don&rsquo;t use the ones that don&rsquo;t use composition).</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5903</guid>
    <title><![CDATA[Discussing DI, IOC, and containers]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5903</link>
    <pubDate>Sat, 27 Dec 2025 22:01:40 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">27. Dec 2025 22:01:40 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">14. Feb 2026 17:48:49 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I was recently allowed to observe as a team discussed the benefits and drawbacks of using an IOC container. [1]</p>
<p>I was asked not to directly participate because it was a team-building exercise; the team needed to convince itself based on the merits of its own arguments. If those <em>for</em> the technology were unable to articulate their convictions sufficiently, then it wouldn&rsquo;t help for an outside authority to dictate the answer. I assisted in the background, with clarification and alternate explanations.</p>
<h2>Why no tests?</h2><p>Some team members had a reasonable hesitation to using an IOC. Why reasonable? Because they&rsquo;d been hurt in the past by non-pragmatic and overly magical solutions.</p>
<p>The main reason that the other team members wanted to use DI and an ICO container was to improve testability. They also appreciated that a side-effect of DI is that it makes it so much easier not only to reason about your system, but to repurpose parts of it.</p>
<p>The disconnect arose because <strong>the first group doesn&rsquo;t write automated tests.</strong> Therefore, they never felt the pain of trying to replace an annoyingly <em>impure</em> component deep in the program logic with something else in order to test other components. If that situation doesn&rsquo;t comes up, then you might not see what the big deal is.</p>
<p>So, part of the confusion was that some of the team still had an at-best antiquated—and at-worst irresponsible and inefficient—approach to engineering because they did all of their testing manually and in an ad-hoc manner.</p>
<p>Another part of the confusion was terminology, where people were arguing against a technology by naming the concept. This was a missed opportunity for finding common ground and then focusing on the details, where they had different preferred approaches.</p>
<p><img title="Application components" src="https://www.earthli.com/data/news/attachments/entry/5903/application_components.webp" alt=" "></p>
<h2>Clarifying terminology</h2><p>My colleagues were contrasting DI with what they were calling &ldquo;static class trees&rdquo;. I think that expression is quite confusing because what they probably meant was &ldquo;static <em>object</em> trees,&rdquo;  which I think was meant to mean the untestable evil that is &ldquo;bottom-up-instantiated object graphs.&rdquo;</p>
<p>Let&rsquo;s be clear about which kind of static class trees we think are bad.</p>
<h3>Not using DI</h3><p>This is a static class tree rooted at <code>D</code> that does not inject any dependencies.</p>
<pre class=" "><code>class A {}
class B {}
class C {
    A a;
    B b;
    C()
    {
        this.a = new A();
        this.b = new B();
    }
}
class D
{
    A a;
    C c;

    D()
    {
        this.a = new A();
        this.c = new C();
    }
}

D d = new D();</code></pre><h3>Using some DI</h3><p>You might complain that this is pathological because we&rsquo;ve created <code>A</code> twice. OK, fine, let&rsquo;s pass it in to <code>C</code>.</p>
<pre class=" "><code>class A {}
class B {}
class C {
    A a;
    B b;
    C(A a)
    {
        this.a = a;
        this.b = new B();
    }
}
class D
{
    A a;
    C c;

    D()
    {
        this.a = new A();
        this.c = new C(a);
    }
}

D d = new D();</code></pre><p>Congratulations! You&rsquo;ve injected your first dependency.</p>
<p>Now keep going!</p>
<h3>Using DI</h3><p>The following code illustrates a static class tree rooted at <code>D</code> that uses dependency injection for everything. Note that this example uses primary constructors without confusing things too much, shortening the code considerably. All instantiations are under the control of the calling code.</p>
<pre class=" "><code>class A {}
class B {}
class C(A a, B b) {}
class D(A a, C c) {}

A a = new A();
D d = new D(a, new C(a, new B()));</code></pre><h3>How DI and IOC are related</h3><ul>
<li><strong>IOC</strong> is the concept. It stands for &ldquo;inversion of control&rdquo;, which means that the control over who gets to decide which implementation backs a given interface is no longer with the <em>consumer</em> of the interface but the <em>provider</em>.</li>
<li><strong>DI</strong> is a way of implementing IOC. (Usually rounded up to be equivalent.)</li>
<li>An <strong>IOC Container</strong> services requests for instances based on interface-to-implementation mappings.</li></ul><p>Looking at the examples above, I think we can all agree that DI is a good thing. That is, &ldquo;dependency injection&rdquo; and &ldquo;inversion of control&rdquo; as concepts are good things.</p>
<h3>What does the IOC container do?</h3><p>An IOC container generally consists of two parts:</p>
<ul>
<li>A mapping of abstractions to implementations.</li>
<li>A method to resolve implementations from abstractions.</li></ul><p>In .NET, these are two completely separate interfaces, so that you can&rsquo;t register mappings when you should only be using them. You use the <code>IServiceCollection</code> in .NET to register mappings and then use <code>IServiceProvider</code> to request instances.</p>
<p>The service provider locates a requested service and constructs an instance where necessary. It recursively locates any parameters to the constructor of a requested service. Obviously, a directly requested service must be registered with a concrete implementation. But also, every service on which it depends must also be registered with a concrete implementation, recursively until dependencies don&rsquo;t have dependencies of their own.</p>
<p>Using an <em>IOC container</em> carries the following implications.</p>
<ul>
<li>✅ It reduces fragility when constructors are refactored.</li>
<li>⚠️ It can make it unclear which constructors are called.</li>
<li>✅ It can be helpful for implementing very generalized factories (where you inject the service provider into, say, a &ldquo;plugin factory&rdquo;).</li></ul><p>A white paper I wrote six years ago has an extended example (in Swift, of all things): <a href="https://www.earthli.com/news/view_article.php?id=4436">Encodo White Papers: DI, IOC and Containers (2019)</a>.</p>
<p>As in the examples above, and in the extended one below, most of the steps in the paper do not use a container. You can do DI without a container—it just gets kind of tedious and wordy. Let the IOC container do the brain-dead stuff for you.</p>
<h3>What&rsquo;s a DAG?</h3><p>Some folks might refer DAGs, which are <a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph">directed acyclic graphs</a> (<cite><a href="http://en.wikipedia.org/">Wikipedia</a></cite>). This is just another way of referring to the graph of objects represented by the <em>composition root</em>, which is the single object you should create in your program&rsquo;s root method—often called <code>main</code>, but sometimes it&rsquo;s just the main file of your application—to create your application.</p>
<p>It&rsquo;s possible to build a DAG without DI. The second and third examples in the sections above also create DAGs. The reason those DAGs are hard to change or extend is because dependencies are created at lower levels rather than <em>injected</em>. We <em>want</em> a DAG … but not like that. We want a DAG created with explicit dependencies, as illustrated by the first example.</p>
<p>For the most part, it&rsquo;s not really important what you call it, as long as you end up with testable components.</p>
<h3>&ldquo;Refining&rdquo; your code (separating pure logic from impure)</h3><p>Any non-trivial application comprises <em>pure</em> and <em>impure</em> parts. The impure parts are the messy bits that communicate with the unpredictable outside world:</p>
<ul>
<li>Reading from the command line</li>
<li>Reading configuration from a file</li>
<li>Reading values from the environment</li>
<li>Reading data from files</li>
<li>Reading from a database</li>
<li>Reading user input</li>
<li>Calling network services</li>
<li>Etc.</li></ul><p>We don&rsquo;t want unpredictability in our testing application, so we&rsquo;ll push all of the impure stuff as far out to the edges as possible, leaving a nice, fat pile of pure logic that we can reliably and reproducibly test.</p>
<p>The preceding sections have hopefully convinced you that IOC is useful, and that constructor-based DI is a good way of implementing it. We&rsquo;ve also discussed the advantages of using an IOC container to improve flexibility and reduce code-duplication.</p>
<p>All of these things are going to help achieve our goal of testing as much of the program logic as possible automatically.</p>
<h3>The single-responsibility principle</h3><p>Components should not only be pure, but should have a <em>single responsibility</em>. That&rsquo;s the  &ldquo;S&rdquo; in <a href="https://en.wikipedia.org/wiki/SOLID#Liskov_substitution_principle">SOLID</a>.</p>
<p>For functional languages, parameters serve as dependencies; for C# and many other languages, another natural &ldquo;injection point&rdquo; is a constructor. Where injection by parameter mixes parameter types—that is, which parameters are <em>data</em> and which are <em>tools</em> for the calculation—a constructor is more clearly a point at which to inject <em>tools</em>.</p>
<p>Now that we have a concept—use IOC to define dependencies as <em>abstractions</em>—and a mechanism—use DI via constructor to <em>inject</em> dependencies—we can write components that address a single responsibility. That is, we have a mechanism for ruthlessly separating concerns.</p>
<p>Components will stitch other dependencies together to accomplish their task (i.e., their sole responsibility). If this stitching code becomes too <em>involved</em>, then the act of stitching might be its own task!</p>
<p>When each component does only a single thing, it is easier to test its logic in isolation. It is, in many cases, <em>trivial</em>.</p>
<h3>We can&rsquo;t test yet! (We need abstractions.)</h3><p>Do we have testable components yet, though? No. Even if we were to use a container with the examples above, we&rsquo;re not done yet! Our goal is to make our logic <em>testable</em> with automated tests. None of the examples above is <em>testable</em> because, although dependencies are injected, they are <em>concrete</em> dependencies.</p>
<p>These cannot be replaced with other implementations and thus cannot be mocked away in tests. That is, if the component <code>A</code> above accessed an external service available only in the cloud or when connected to hardware, you cannot test <code>D</code> without having access either to the cloud or hardware because <em>you can only ever pass in <code>A</code></em>.</p>
<p>We want all modules, high and low, to define and depend on abstractions that can be replaced. This is the &ldquo;L&rdquo; in <a href="https://en.wikipedia.org/wiki/SOLID#Liskov_substitution_principle">SOLID</a>. A component should <em>receive</em> configuration through an interface rather than either creating it itself or accessing a static, global, concrete instance. When all components receive all external dependencies as other, injected components, it&rsquo;s extremely easy to both reason about the code and to test it in isolation.</p>
<p>So, to be able to write automated tests, our next step will be to inject <em>abstractions</em> rather than concrete implementations. An abstraction defines a narrow interface that makes as few promises as possible while still fulfilling its task.</p>
<p>In C#, we typically use <em>interfaces</em> or <em>abstract classes</em>. Interfaces are way better. Just trust me.</p>
<h2>A more concrete example</h2><p>Instead of continuing with the toy classes defined above, let&rsquo;s look at how we would make a part of our program logic more testable.</p>
<p>Suppose you have the following code:</p>
<pre class=" "><code>class EmailClient 
{
    void Send(Email email) { … }
}

class SubscriptionManager
{
    void Notify()
    {
        var client = new EmailClient();
        foreach (var email in _subscriptions.Select(CreateEmail))
        {
            client.Send(email);
        }
    }

    Email CreateEmail(Subscription subscription) { … }
}</code></pre><p>Now, suppose you&rsquo;d like to test this code. You can&rsquo;t test it without an email server configured because the <code>EmailClient</code> is hard-coded. If you invert control, though, you can pass that dependency in to the <code>SubscriptionManager</code>. One way to do this is to pass the dependency directly into the method, like this:</p>
<pre class=" "><code>class SubscriptionManager
{
    void Notify(<strong class="highlight">EmailClient client</strong>)
    {
        foreach (var email in _subscriptions.Select(CreateEmail))
        {
            client.Send(email);
        }
    }

    Email CreateEmail(Subscription subscription) { … }
}</code></pre><p>Is this really solving anything, though? No. The callee is still in control of the type because the type of the parameter is a specific class. The caller has no choice but to pass in an <code>EmailClient</code>, which will try to sent mails to an external server over a network.</p>
<p>In order to support IOC, the callee needs to <em>abstract</em> its requirement. In C#, you use an <em>interface</em>.</p>
<pre class=" "><code><strong class="highlight">interface IEmailClient
{
    void Send(Email email);
}</strong>

class EmailClient <strong class="highlight">: IEmailClient</strong>
{
    public void Send(Email email) { … }
}

class SubscriptionManager
{
    void Notify(<strong class="highlight">I</strong>EmailClient client)
    {
        foreach (var email in _subscriptions.Select(CreateEmail))
        {
            client.Send(email);
        }
    }

    Email CreateEmail(Subscription subscription) { … }
}</code></pre><p>We&rsquo;re done. We&rsquo;ve implemented inversion of control. The caller now controls the concrete type.</p>
<p>We are also using <em>dependeny injection</em> but of a very manual kind: the caller is expected to provide the email-sending mechanism. This can be inconvenient and can muddy otherwise legible code because each and every caller has to have a reference the thing that the <code>SubscriptionManager</code> needs. That is, instead of coupling just the <code>SubscriptionManager</code> to an <code>IEmailClient</code>, we end up coupling any client of the <code>SubscriptionManager</code> as well.</p>
<p>Therefore, a common practice is to inject dependencies like this through the constructor.</p>
<pre class=" "><code>class SubscriptionManager
{
    <strong class="highlight">private readonly IEmailClient _client;

    public SubscriptionManager(IEmailClient client)
    {
        _client = client ?? throw new ArgumentNullException(nameof(client));
    }</strong>
    
    void Notify()
    {
        foreach (var email in _subscriptions.Select(CreateEmail))
        {
            <strong class="highlight">_</strong>client.Send(email);
        }
    }

    Email CreateEmail(Subscription subscription) { … }
}</code></pre><p>The code that calls <code>Notify()</code> no longer has to know anything about the dependency, thus better decoupling the <code>SubscriptionManager</code> interface from its consumers. The <code>SubscriptionManager</code> declares its dependencies in the constructor, which makes good use of that language construct. That is, we&rsquo;re leveraging the language to improve the clarity of our design.</p>
<p>At this point, we can still construct the <code>SubscriptionManager</code> manually, passing in the concrete type for <code>IEmailClient</code> but we can now also consider using an IOC <em>container</em>, as outlined above.</p>
<h3>Another example: Injecting configuration</h3><p>Let&rsquo;s take a look at how we can lean on the IOC container to build our application&rsquo;s configuration.</p>
<pre class=" "><code>public class AppSettings :
	ITimerSettings,
	IListenerSettings,
	IPathSettings,
	IBroadcastSettings,
	IDashBoardSettings
{
/* … */
}</code></pre><p>At first glance, you may think this is over-engineered, but there&rsquo;s a good reason for it. There is a single object holding all the settings for the app. But each service only needs to know about <em>one part</em> of these settings. That is, it&rsquo;s convenient on the implementation side to have a single object handling all settings, but each service should only be <em>coupled</em> to the settings that it uses.</p>
<p>We don&rsquo;t want to increase coupling in the services just because of how the <em>current</em> implementation works. Therefore, we register the single implementation for all of service-settings interfaces in the IOC container, and each service uses its own settings interface.</p>
<h2>Getting the ball rolling</h2><p>For this section, I&rsquo;m going to be referencing from two older articles I wrote about a framework I used to work on. It&rsquo;s fun that nothing has really changed in the last decade.</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=3137">Encodo’s configuration library for Quino: part III</a> (2015)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3165">API Design: Running an Application (Part I)</a> (2015)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3166">API Design: To Generic or not Generic? (Part II)</a> (2015)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3175">Quino 2: Starting up an application, in detail</a> (2015)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3222">Mini-applications and utilities with Quino</a> (2016)</li></ul><p>So we can see how to construct an application out of components. We see how to stitch them together with very simple rules. We see how we can test those components.</p>
<p>But…now we want to <em>run</em> the application. We want it to do the thing that it does. Do we just create a <em>component root</em> and call … um … <code>Run()</code> on it?</p>
<pre class=" "><code>IServiceCollection services = AppTools.CreateServiceCollection();
IServiceProvider provider = services.CreateServiceProvider();
IApplication application = provider.GetRequiredService&lt;IApplication&gt;();

application.Run();</code></pre><p>Are we cool?</p>
<p>Kind of. Like, that works just fine. The articles referenced above provide a lot more background on providing exception-handling, standard logging, command-line support, etc. But the code above is what we&rsquo;re shooting for, for <em>real</em> applications. What&rsquo;s a real application?</p>
<p>Let&rsquo;s flesh this out a bit.</p>
<ul>
<li>How many applications do we have? </li>
<li>What kind of application are we running?</li>
<li>What even is an application?</li></ul><p>Any solution is going to have at least two applications: Whatever the <em>real</em> application is, and one or more test runners. An application is any way of executing part or all of your program logic.</p>
<h3>&ldquo;Real&rdquo; applications have event loops</h3><p>A real application might be a console, a GUI, or a server application. These applications have one thing in common: they contain one or more <em>event loops</em> that <em>react</em> to external input.</p>
<p>Most applications have an event loop.</p>
<ul>
<li>A <strong>console application</strong> that &ldquo;watches&rdquo; for changes in the file system, updating other files base on that. It exits when the user issues a special command like <kbd>Ctrl</kbd> + <kbd>C</kbd>.</li>
<li>A <strong>web server</strong> that &ldquo;listens&rdquo; on specific ports, returning responses to requests. It exits when the user issues a special command like <kbd>Ctrl</kbd> + <kbd>C</kbd> or when the system terminates the service.</li>
<li>A <strong>GUI</strong> that &ldquo;responds&rdquo; to user input—mouse and keyboard events—and runs until the user issues a special command to exit.</li></ul><h3>Run-once applications</h3><p>Some applications don&rsquo;t have an event loop They run the parameters through their flowcharts one time and then exit automatically.</p>
<ul>
<li>A console application or script that processes a single set of command-line parameters, like processing a file and producing a report.</li>
<li>A test runner that executes part of the logic in your real application.</li></ul><h3>Application &ldquo;actions&rdquo;</h3><p>The example above doesn&rsquo;t show any detail about what the <code>IApplication</code> <em>does</em> when it runs.</p>
<p>As the referenced articles show in more detail, &ldquo;getting the whole ball rolling&rdquo; in a nontrivial application always involves several &ldquo;actions&rdquo; to execute during &ldquo;startup&rdquo;. That is, the application is not just a service collection, but also a list of startup actions, a list of shutdown actions. Each action is created by the IOC container, so it can have all of the services it needs injected into it.</p>
<p>The basic loop in <em>Application.Run()</em> is something like this:</p>
<pre class=" "><code>foreach (var action in _startupActions)
{
  action.Execute();
}</code></pre><p>The actual implementation ended up being more complicated than this, as noted above, to accommodate general error-handling, async startup actions, debugging comfort, and to support re-running the application, e.g., when it showed command-line help, or when it needed to run a schema-migration for a database. See the linked article for more information.</p>
<h2>I heard you like IOC containers…</h2><p>Another common problem with IOC containers is: how can you dynamically configure the IOC? What if you want to use a <code>AmazonS3Provider</code> by default, but allow a command-line parameter or configuration file to enable an <code>FTPProvider</code> instead?</p>
<p>DI and IOC are awesome, so we want to use them everywhere, right?</p>
<p>But we can&rsquo;t, can we? As soon as you get a service provider, you can no longer modify it. As soon as we request the <code>IApplication</code> service above, it&rsquo;s all over for modifying service registrations.</p>
<p>I&rsquo;ve wrestled with this a lot in the past. The most relevant article is linked above: <a href="https://www.earthli.com/news/view_article.php?id=3175">Quino 2: Starting up an application, in detail</a>.</p>
<p>Basically, the answer is to <em>use two IOCs</em>.</p>
<dl><dt class="field">Bootstrap IOC</dt>
<dd>The first IOC is much smaller and contains registrations for services needed to configure the <em>Main IOC</em> (e.g. configuration-loader, command-line-reader, fs-location-resolver, etc.). These registrations are necessarily a small core of services that cannot be changed by configuration (files, command-line parameters, database values, etc.). That keeps things simple.</dd>
<dt class="field">Main IOC</dt>
<dd>Includes all registrations from the <em>Bootstrap IOC</em>, plus overrides that came out of the configuration, plus anything else needed for the main app.</dd>
</dl><p>As noted above, an appilcation&rsquo;s startup and shutdown are lists of actions (discussed in <a href="https://www.earthli.com/news/view_article.php?id=3137">Encodo’s configuration library for Quino: part III</a>).</p>
<p>Specifically, there are actions to execute during,</p>
<ul>
<li>the bootstrap phase,</li>
<li>the main phase,</li>
<li>and shutdown.</li></ul><p>So, the application startup kind of looks like this:</p>
<ul>
<li><div>Configure services and actions for the Bootstrap IOC and Main IOC.<ul>
<li>Any registration in the Bootstrap IOC is made in the main IOC as well.</li>
<li>Crucially, singletons in the Main IOC are <em>the same</em> as those in the Bootstrap IOC.</li></ul></div></li>
<li>Seal the Bootstrap IOC (i.e., get the service provider from the service collection).</li>
<li><div>Execute application-startup actions <em>using the Bootstrap IOC</em>.<ul>
<li>The first few actions will be stuff like &ldquo;read command line&rdquo;, &ldquo;read configuration&rdquo;, etc.</li>
<li>These might alter the registrations in the main IOC and might add or modify actions to execute. That&rsquo;s OK. It&rsquo;s not &ldquo;sealed&rdquo; yet.</li>
<li>Any attempt to alter a registration in the bootstrap IOC results in an error.</li>
<li>Modifying an action in the list before the app&rsquo;s current position in that list will have no effect.</li>
<li>At some point, the &ldquo;bootstrap&rdquo; actions are finished, and an action executes that &ldquo;seals&rdquo; the main IOC from modification.</li>
<li>Now we&rsquo;re in the &ldquo;classic&rdquo; app startup.</li></ul></div></li>
<li>Run the main actions.</li>
<li>Run the event loop or application logic (e.g, fixed handling for command-line parameters).</li>
<li>Run the shutdown actions.</li></ul><p>There&rsquo;s more documentation but it’s no longer available because Encodo has taken down all public documentation … and we never published the source code as open source. I&rsquo;m working from memory and my existing articles. 🤷</p>
<p>But that&rsquo;s the general gist of it. There are clean solutions to anything that might come up. For example, if you need a more &ldquo;heavyweight&rdquo; service during the bootstrap—like a database, which you also use in the main application, but which you want to keep configurable—consider making an interface like <em>IBootstrapConfigurationDatabase</em> or something like that, which will be its own singleton and not even available in the main application phase.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5903_1_body" class="footnote-number">[1]</span> This isn&rsquo;t the first time I&rsquo;ve taken a run at this topic, although I only recently remember that I&rsquo;d written <a href="https://www.earthli.com/news/view_article.php?id=3487">Why use an IOC? (hint: testing)</a> in April 2019.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5818</guid>
    <title><![CDATA[A review of 35 Microsoft Ignite 2025 dotnet videos]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5818</link>
    <pubDate>Sun, 21 Dec 2025 22:47:15 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Dec 2025 22:47:15 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I watched/listened to 35 videos, each between 20 and 30 minutes long, and each listed below. I&rsquo;ve grouped them but retained the order in which I watched them. I&rsquo;ve left the notes mostly as I wrote them, which is kind of stream-of-consciousness, kind of snarky.</p>
<p>Some videos that I didn&rsquo;t like got a lot of notes, some videos I liked got fewer notes. It might seem like I hated the video from my snarky notes but I still ended up rating some of them as 🆗, which means that I thought that either the video was well-presented even though the material doesn&rsquo;t have much broad appeal or that I thought the material was important even though the presentation wasn&rsquo;t that great.</p>
<p>Don&rsquo;t read too much into it. The notes are just to help me remember what I learned from the videos—and can hopefully give you a bit of an idea of what the video is about and whether you want to spend 20–30 minutes on it. YMMV.</p>
<ul>
<li><div><a href="#dotnet">C#, F#, &amp; .NET</a><ul>
<li><a href="#Nullable">🆗 Nullable Reference Types: It&rsquo;s Actually About Non-Nullable Reference Types</a></li>
<li><a href="#Performance">✅ Performance Improvements in .NET 10</a></li>
<li><a href="#Community">🆗 Community Toolkit Roundup</a></li>
<li><a href="#Features">✅ C# Features you need Habits you want</a></li>
<li><a href="#Smatterings">✅ Smatterings of F#</a></li>
<li><a href="#Rx">✅  Rx.NET status and plans</a></li></ul></div></li>
<li><div><a href="#Migration">Migration</a><ul>
<li><a href="#Scores">⛔ .NET Scores &ldquo;A Perfect 10&rdquo;</a></li>
<li><a href="#Framework">✅ .NET Framework 4.8 to .NET 9 Step by Step</a></li>
<li><a href="#Modernizing">⛔️ Modernizing .NET Applications for the Cloud</a></li></ul></div></li>
<li><div><a href="#Tools">Tools</a><ul>
<li><a href="#Debugger">🆗 Visual Studio Debugger: Advanced Techniques</a></li>
<li><a href="#Test">🆗 New dotnet test Experience with Microsoft.Testing.Platform</a></li>
<li><a href="#NuGet">🆗 What&rsquo;s New in NuGet</a></li>
<li><a href="#Profiling">🆗 Real-World .NET Profiling with Visual Studio</a></li></ul></div></li>
<li><div><a href="#UIs">UIs</a><ul>
<li><a href="#Forms">⛔ What&rsquo;s New in Windows Forms</a></li>
<li><a href="#Windows">⛔ Modern Windows Development with .NET</a></li>
<li><a href="#TUIs">✅ TUIs Are Back (Although They Never Left): Creating Modern CLI Apps in .NET.</a></li>
<li><a href="#Ship">🆗 Ship Faster with .NET MAUI: Real-World Pitfalls and How to Nuke Them</a></li>
<li><a href="#Headless">✅ Building Rock-Solid Avalonia Apps A Guide to Headless Testing with AI Assistance</a></li>
<li><a href="#Maui">✅  What&rsquo;s New in .NET MAUI</a></li>
<li><a href="#Blazor">✅ Build better web apps with Blazor in .NET 10</a></li></ul></div></li>
<li><div><a href="#Aspire">Aspire</a><ul>
<li><a href="#Aspire">✅ Taking .NET out of .NET Aspire − working with non-.NET applications</a></li>
<li><a href="#Architecure">⛔ From Architecture to Docs: .NET Aspire Documented with Copilot</a></li>
<li><a href="#Supercharging">✅ Windows 365 Meets Aspire − Supercharging Multi-Repo Microservice Productivity</a></li>
<li><a href="#DeepDive">✅ Deep Dive: Extending and Customizing Aspire</a></li>
<li><a href="#Maddy">✅ Aspire Unplugged with David and Maddy</a></li></ul></div></li>
<li><div><a href="#Cloud">Cloud</a><ul>
<li><a href="#Containers">🆗 What&rsquo;s New in Containers for .NET 10</a></li>
<li><a href="#Service">✅ What&rsquo;s new in Azure App Service for .NET developers</a></li>
<li><a href="#Carbon">🆗 Carbon Aware Computing − Using .NET Open Source libraries for more sustainable applications</a></li></ul></div></li>
<li><div><a href="#AI">AI</a><ul>
<li><a href="#Dashboard">⛔️ Architecting an AI-Powered Sales Dashboard with .NET MAUI and Azure OpenAI</a></li>
<li><a href="#Seamless">🆗 One Question, One Answer: Designing Seamless AI Agents with C#</a></li>
<li><a href="#Overcoming">✅ Overcoming the limitations when using AI</a></li></ul></div></li>
<li><div><a href="#Everything else">Everything else</a><ul>
<li><a href="#Italian">🆗 Modernizing a 17th Century Italian-English Dictionary</a></li>
<li><a href="#Passkeys">🆗 Going Passwordless − A Practical Guide to Passkeys in ASP.NET Core</a></li>
<li><a href="#Pipelines">✅ GitHub Actions DevOps Pipelines as Code using C# and Cake SDK</a></li>
<li><a href="#Beer">🆗 If .NET brewed beer…</a></li></ul></div></ul><p><span style="width: 601px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/5818/microsoft_ignite_2025.webp" alt=" " style="width: 601px"></span><span class="auto-content-caption">Microsoft Ignite 2025</span></span></p>
<h2 id="dotnet">C#, F#, &amp; .NET</h2><dl><dt><span id="Nullable"><a href="https://www.youtube.com/watch?v=7Sz4heIk_lM">🆗 Nullable Reference Types: It&rsquo;s Actually About Non-Nullable Reference Types</a> by <cite>dotnet | Shawn Wildermuth</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" ">This is a decent, thorough—though somewhat slow—introduction to non-nullable reference types in .NET/C# (which have been available since .NET 3.x / C# 8). If you already know about them, then there&rsquo;s nothing new here.</div></dd>
<dt><span id="Performance"><a href="https://www.youtube.com/watch?v=snnULnTWcNM">✅ Performance Improvements in .NET 10</a> by <cite>dotnet | Stephen Toub</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>An in-depth examination of performance improvements in .NET 10. He explains how the various compilers (AOT, JIT, etc.) have been optimized to eliminate allocations and just generally optimized for performance. A reduction in allocations is a multi-win: the performance is better because the allocator isn&rsquo;t working, the memory usage has dropped, and the garbage collector also works less.</p>
<p>He compares .NET Framework 4.8 vs. .NET 9 vs. .NET 10. The most impressive improvements are from 4.8 to 9.0, of course, but he highlights some interesting places where .NET 10 eclipses .NET 9, where .NET 9 had already eclipsed .NET Framework 4.8.</p>
<p>The last example shows how regular expressions have been continually optimized so that an operation that took 24ms in .NET Framework 4.8 was improved by about 12x to 2.5ms in .NET 9 but has been further improved by about 62,500x to about 40ns in .NET 10.</p>
<p>For more coverage, see <a href="https://www.earthli.com/news/view_article.php?id=5732">Toub’s 232-page tour-de-force on performance in .NET 10</a>.</p>
</div></dd>
<dt><span id="Community"><a href="https://www.youtube.com/watch?v=i_-dZEifOQQ">🆗 Community Toolkit Roundup</a> by <cite>dotnet | Gerald Versluis, SergioPedri, Michael Hawker</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>They spent some time touting the benefits of the toolkits.</p>
<ul>
<li>There is an introduction to improvements to the MVVM toolkit.</li>
<li>There is also a toolkit for Aspire, which is interesting.</li>
<li>Then there&rsquo;s the Maui MVVM toolkit, which adds a bunch of media support.</li>
<li>The Windows toolkit added a lot of fixes and controls for WinUI3.</li></ul><p>They note that a lot of stuff incubates in the toolkits and is often migrated to the official libraries after a while.</p>
</div></dd>
<dt><span id="Features"><a href="https://www.youtube.com/watch?v=yIswUU7lKpk">✅ C# Features you need Habits you want</a> by <cite>dotnet | Bill Wagner</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>He introduces an existing &ldquo;magic 8-ball&rdquo; program, demonstrating its functionality. He doesn&rsquo;t show any tests, though. That does not stop him from refactoring the app to take advantage of &ldquo;newer&rdquo; C# features. I write it in quotes because, while some of the features he shows aren&rsquo;t necessarily new, it&rsquo;s good to have a video that shows how you should be upgrading your types when you touch old code, to take advantage of better type-checking, to convert potential runtime errors to compile-time errors.</p>
<ul>
<li>non-nullable references.</li>
<li><code>required</code> and <code>init</code> properties.</li>
<li>The <code>field</code> element for properties, which <em>is</em> new to C# 14.</li>
<li>The <code>System.Threading.Lock</code> type instead of <code>System.Object</code>, which allows the compiler to generate more efficient code, all without any change in behavior of the application.</li>
<li>Using verbatim strings and the newer multi-line verbatim strings.</li>
<li>Collection expressions. (He explains how the compiler can optimize the capacity for a collection expression, where it cannot for a direct instantiation of <code>new List&lt;T&gt;()</code>.)</li>
<li>The spread operator. (He uses this to replace the explicit call to <code>ToArray()</code>. Again, it&rsquo;s easier to read and the compiler has more optimization opportunities.)</li>
<li>The <code>with</code> keyword. (He explains how this allows you to more easily work with immutable types and structures.)</li>
<li><div>Using a <code>readonly struct</code> (This sets immutability, which also allows much better optimization, such as lowering copying/allocation when passing data through function/stack boundaries.)<div class=" "><p>He optimizes his <strong>pattern-matching</strong>, where the compiler helps a lot to figure out exactly how much information is needed in the pattern. If a case can&rsquo;t be reached, it&rsquo;s an error. He removes the lower-bound check on several cases because they&rsquo;re not needed. If you remove too much, the compiler tells you.</p>
<pre class=" "><code>AnswerType type = randomIndex switch
{
    &gt;= 0 and &lt;= 5 =&gt; AnswerType.Affirmation,
    &gt;= 6 and &lt;= 9 =&gt; AnswerType.Encouraging,
    &gt;= 10 and &lt;= 13 =&gt; AnswerType.Uncertain,
    &gt;= 14 and &lt;= 16 =&gt; AnswerType. Doubtful,
    &gt;= 17 and &lt;= 18 =&gt; AnswerType.Rejection,
    19 =&gt; AnswerType.Redo,
    _ =&gt; AnswerType.Uncertain
};</code></pre><p>The following is equivalent:</p>
<pre class=" "><code>AnswerType type = randomIndex switch
{
    &lt;= 5 =&gt; AnswerType.Affirmation,
    &lt;= 9 =&gt; AnswerType.Encouraging,
    &lt;= 13 =&gt; AnswerType.Uncertain,
    &lt;= 16 =&gt; AnswerType. Doubtful,
    &lt;= 18 =&gt; AnswerType.Rejection,
    19 =&gt; AnswerType.Redo,
    _ =&gt; AnswerType.Uncertain
};</code></pre><p>If you were to change the order of the cases, putting the <code>&lt;= 13</code> case at the top, the compiler warns that the <code>&lt;= 5</code> and <code>&lt;= 9</code> cases will never be matched.</p>
<pre class=" "><code>AnswerType type = randomIndex switch
{
    <strong class="highlight">&lt;= 13 =&gt; AnswerType.Uncertain,</strong>
    &lt;= 5 =&gt; AnswerType.Affirmation,  <span style="color: red">// Compile error.</span>
    &lt;= 9 =&gt; AnswerType.Encouraging,  <span style="color: red">// Compile error.</span>
    &lt;= 16 =&gt; AnswerType. Doubtful,
    &lt;= 18 =&gt; AnswerType.Rejection,
    19 =&gt; AnswerType.Redo,
    _ =&gt; AnswerType.Uncertain
};</code></pre></div></div></li></ul></div></dd>
<dt><span id="Smatterings"><a href="https://www.youtube.com/watch?v=GcEHiY6Vp-8">✅ Smatterings of F#</a> by <cite>dotnet | Matthew Watt</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>The first five minutes is an introduction to the programmer himself, which was a bit odd but it&rsquo;s fine. It just might not be very interesting if you&rsquo;re looking for technical guidance.</p>
<p>He moves on to an introduction to his blog, which he wrote with F# on the back-end, and React for the front-end. The comments section that he built uses <em>Elmish</em>, which is a library for emulating the highly functional Elm pattern of building code. The whole web site is functional from top to bottom so it&rsquo;s kind of neat to see how that works for a real-world application.</p>
<p>He finishes up with five minutes on contributing to open-source code. Again, a nice touch.</p>
</div></dd>
<dt><span id="Rx"><a href="https://www.youtube.com/watch?v=y7Ks_bwSHUg">✅  Rx.NET status and plans</a> by <cite>dotnet | Ian Griffiths</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>He discusses some examples of some new methods in the 6.1 release. These are quite nice, and the concept of RX is just neat, even though I&rsquo;ve only ever played with it rather than used it in production.</p>
<p>He discusses in detail how some of the new handling for exceptions <span class="quote-inline">&ldquo;bridges between RX&rsquo;s world of observable streams and more ordinary async programming.&rdquo;</span></p>
<p>In the next section, he discusses how the RX project had to do some extra work because <code>System.Linq.Async</code> is no longer their responsibility. It&rsquo;s now in the standard library. But they had to make sure that their version gets deprecated in favor of the new one. As a library developer, think that this detail is fascinating, because you can see the the tools available for managing changing APIs and dependencies have gotten quite good.</p>
<p>Finally, he discusses the feature set for Rx.NET 7.0. The functionality won&rsquo;t change much; it&rsquo;s mostly library and platform-compatibility. There is a fix for the &ldquo;bloat&rdquo; issue, which only affects projects that target UI applications on Windows. It turns out that design decision in version 4.0 left self-contained deployments with implicit references to UI frameworks, which add dozens of megabytes needlessly. </p>
<p>The fix causes a compile error, for which they added an analyzer that nicely explains the fix to apply. This is a neat example of how to help consumers of your library get around compiler errors, which we didn&rsquo;t have available before it was so easy to write and include custom analyzers. Previously, you&rsquo;d have had to jump through more hoops to avoid giving upgraders compiler errors that weren&rsquo;t warnings in the previous version. Now, if something like that is unavoidable, then you can still provide guidance with a diagnostic.</p>
<p>I thought it was a very interesting presentation but I&rsquo;m a library and framework geek. Your mileage may vary.</p>
</div></dd>
</dl><h2 id="Migration">Migration</h2><dl><dt><span id="Scores"><a href="https://www.youtube.com/watch?v=cBZopiZeuL8">⛔ .NET Scores &ldquo;A Perfect 10&rdquo;</a> by <cite>dotnet | Shaun Walker</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" ">He describes a successful migration of a large Blazor application to .NET 10 (the open-source <a href="https://github.com/oqtane/oqtane.framework">Oqtane</a> (<cite><a href="http://github.com/">GitHub</a></cite>)), presumably from .NET 8. This is OK, but he just describes what he did without showing it. Once he gets to the product, he actually ends up demoing the Oqtane software—and Blazor&rsquo;s capabilities—more than he showed any details about what migrating to .NET 10 entailed, apart from a few sentences in the slides. Instead, he spent a bunch of time discussing features introduced by .NET 10 that Oqtane ended up using. That is, instead of covering the migration itself, he discussed the extensions to the product that were enabled by a move to .NET 10.</div></dd>
<dt><span id="Framework"><a href="https://www.youtube.com/watch?v=AEbJzTF03F0">✅ .NET Framework 4.8 to .NET 9 Step by Step</a> by <cite>dotnet | Michael Christiansen</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>He recommends <em>modernizing</em> the app before retargeting it. This means:</p>
<ul>
<li>Updating to use the SDK-style project format.</li>
<li>Using package references.</li>
<li>Using the <code>Microsoft.Extensions.*</code> packages, like dependency injection, configuration, logging, and hosting, all of which target the .NET Standard API surface and are therefore available for .NET Framework and .NET.</li></ul><p>After that, he recommends side-by-side versions of libraries so that you can split them up better without affecting the existing, working version of the code.</p>
<p>One of the projects was a tougher nut to crack: it was an old-school ASP.NET application, where the patterns had completely changed in .NET 9 and 10. For that, he managed to have Claude Code do about 90% of the conversion and finished it up manually. The process was very manual—<span class="quote-inline">&ldquo;spec-driven development&rdquo;</span> and <span class="quote-inline">&ldquo;very hands-on&rdquo;</span>—but Claude Code was quite helpful once he figured out how to steer it properly.</p>
<p>If you have a .NET Framework application, then this is a great video. He really has a lot of good advice for how to avoid certain pitfalls (e.g., platform-specific code, like <em>Windows Services</em>).</p>
</div></dd>
<dt><span id="Modernizing"><a href="https://www.youtube.com/watch?v=vrxn-y0tFTI">⛔️ Modernizing .NET Applications for the Cloud</a> by <cite>dotnet | Matt Soucoup</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>Was there ever going to be a chance that he wouldn&rsquo;t start off with telling you that Copilot can do all of the tedious work for you? No. No, there wasn&rsquo;t. Was he ever going to tell you to use your mad skillz with your IDE to apply a ton of changes automatically using tools and refactoring? No, he wasn&rsquo;t. Like the NuGet guy, he&rsquo;s going to get copilot to spend ten minutes running a NuGet one-liner.</p>
<p>So like how cool is that? Not only do you have a super-old application that you never upgrade but now you don&rsquo;t even have to understand what you&rsquo;re migrating to! I love how he says that going from .NET Framework to .NET 10 is just soooo easy. You know, don&rsquo;t make any stops along the way, just take the express train. What could go wrong?</p>
<p>Anyway … he shows how to install the Copilot modernization tools, then opens a .NET Framework IIS-based project. Once again, we&rsquo;re watching a guy watch a Copilot chat window write a ton of text that he barely reads. He asks it to explain the security problems, as if this is something that you should do. Shouldn&rsquo;t you inform yourself about the packages? Shouldn&rsquo;t you just upgrade the old things? Do you really need the explanation?</p>
<p>And, once again, he says that <span class="quote-inline">&ldquo;you&rsquo;re giving up the reins to Copilot,&rdquo;</span> but, like everyone else, just assumes that everything that Copilot returns in bulletproof. This is still not my experience, to this very day.</p>
<p>Back to the update plan: I see the attraction, I really do. It&rsquo;s very detailed … but who is it for? Is he keeping this upgrade plan in the repository? How much control does the plan actual give him? Doesn&rsquo;t the commit that results just show the changes?</p>
<p>He says it <span class="quote-inline">&ldquo;took about an hour to upgrade&rdquo;</span>. 😱 Oh, hell no. It just works for an <em>hour</em> for what he calls <span class="quote-inline">&ldquo;a simple app&rdquo;</span>, using God knows how many tokens, and then you still have to review everything? Why not just do it yourself? He really needs to show the diffs. Show us the diffs, bro. I don&rsquo;t think he&rsquo;s going to show us the diffs. He&rsquo;s just going to show us how he has to coddle the tool, which is basically making black-box changes. <span class="quote-inline">&ldquo;That&rsquo;s just the way it is, that&rsquo;s the way it is working with AI-assisted dev tooling.&rdquo;</span></p>
<p>He didn&rsquo;t show the diffs. I have no idea what this tool did for him on this project. This tool is for people who would have <em>no idea</em> how to go about upgrading a solution on their own, who can use a chat windows but run screaming from a command-line upgrade tool.</p>
<p>At the very end, he runs the upgraded version but there are warnings in the build that two packages were restored using .NETFramework,Version=4.6.1 (the <em>worst</em> .NET Framework version ever), which strongly indicates that, even after an hour of f@&amp;king around, the solution still references .NET Framework.</p>
<blockquote class="quote quote-block "><div>&ldquo;The amount of coding that I had to do was basically zero. All I had to do was supervise things.&rdquo;</div></blockquote><p>Well done, buddy. You still have old packages and weird references. Check your warnings. I wouldn&rsquo;t touch this tooling with a ten-foot pole.</p>
<p>As I wrote in a comment on the video,</p>
<p>This kind of workflow doesn&rsquo;t translate well to a nearly half-hour-long video. There&rsquo;s nothing to see. He ran a command or two. He didn&rsquo;t even show the diffs at the end, to show us what the tool actually did. You could still see some odd warnings about .NET Framework in the output that he had to pretend weren&rsquo;t there. He did a good job FWIW but a lot of this video is watching the Copilot chat window scroll by. The explanation is good but it would have been better as a blog post.</p>
</div></dd>
</dl><h2 id="Tools">Tools</h2><dl><dt><span id="Debugger"><a href="https://www.youtube.com/watch?v=6afeRSFQiw0">🆗 Visual Studio Debugger: Advanced Techniques</a> by <cite>dotnet | Harshada Hole</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>She takes us through the various live and inline indicators in the debugger, with predictive evaluation, including highlighting of the particular part of a condition that caused it to evaluate to true or false. The debugger has moved much closer to Rider&rsquo;s, showing a lot of calculated values in the whitespace next to code, so you can see return values and calculated values without having to look in the variables or watches panes. This also allows you to use more concise coding while still being able to see interim values while debugging.</p>
<p>When showing how to analyze exceptions, she showed how to dig down into the call stack to find out why something&rsquo;s null. She used right-clicking for everything, which was already slower than it needed to be…but then she decided to ask Copilot. The &ldquo;quick&rdquo; analysis took 30 seconds and then she had to ask it to do a &ldquo;deep analysis&rdquo;, whereupon it found the error that she would have probably found manually much more quickly. Maybe a more complex example wouldn&rsquo;t have had such an obvious fix. Most people suck at debugging and don&rsquo;t really understand their code, so probably Copilot is better at this than they are (or ever will be). So who am I to stand in the way of progress? I&rsquo;m just John Henry.</p>
<p>I cannot stress enough how annoying it is to have to watch people &ldquo;ask Copilot&rdquo; and then we all gather around the chat-window output like it&rsquo;s the word of God. It&rsquo;s too bad, because the first few minutes of this video showed interesting deterministic tools before devolving into an orgy of just clicking that stupid little Copilot icon everywhere and then watching the completely useless and always-disregarded text in the chat windows scroll by. I cannot recall any one of these presenters actually reading any of this text. No-one cares.</p>
<p>These tools are really trying to reach out to and onboard completely unskilled developers to an unprecedented degree. These kinds of presentations make me sad. It&rsquo;s fine for what it is, but I don&rsquo;t think that this is the final form of software-development.</p>
</div></dd>
<dt><span id="Test"><a href="https://www.youtube.com/watch?v=6afeRSFQiw0">🆗 New dotnet test Experience with Microsoft.Testing.Platform</a> by <cite>dotnet | Jakub Jares</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>This is a demo video, with the presenter working in Visual Studio Code but only from the command line. He shows how the console UI has been considerably improved. He also gets into new analyzers, assertions, and attributes. The improvement to the assertions is that they start analyzing the expression tree, which I find to be more fragile than the NUnit approach, which uses an explicit API to declare the assertion, with no magic. The attributes are for extending the framework, e.g., for determining when and in which environments tests will run.</p>
<p>Finally, he shows how the MSTest runner has massively improved execution speed, not in this version (4.0), but already in the 3.0 version.</p>
<p>The video is OK but the product is quite exciting, as it is a massive improvement over the previous test-runner.</p>
</div></dd>
<dt><span id="NuGet"><a href="https://www.youtube.com/watch?v=blGOP6adqa4">🆗 What&rsquo;s New in NuGet</a> by <cite>dotnet | Sean Iyer &amp; Nikolche Kolev</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>He starts off by threatening us that he will show a bunch of AI stuff. First up: tell us to use the MCP  server for NuGet. He uses it to show how to get Copilot to update your dependencies when you have a vulnerability. This is not a hard task and, honestly, you should be aware enough of your dependencies to solve them yourself. It&rsquo;s nice that the warnings are so good now that you can get a tool to fix up all f the things that people never could figure out on their own. Dude, since assembly-binding redirects were fixed in .NET, there&rsquo;s no problem anymore. I don&rsquo;t understand how it&rsquo;s secure to let a hallucinating machine pick your dependencies for you. Now you don&rsquo;t have to understand anything!</p>
<p>He spends a bunch of time talking about how to avoid getting outdated implementations that aren&rsquo;t in the training data using an MCP. Or you could, you know, just update to the latest version. I don&rsquo;t know why they&rsquo;re making everything so complicated.</p>
<p>In the second half, he talks about security improvements but then just starts talking about how Copilot did all of his work for him. So, like, it&rsquo;s secure but also an only partially reliable machine made all of the changes and he didn&rsquo;t seem to look at them.</p>
<p>Nikolche shows how to eliminate vulnerabilities without Copilot (thank God) and shows how to use the pruning option with the <code>audit</code> command to remove unneeded dependencies that might show up in audits unnecessarily.</p>
</div></dd>
<dt><span id="Profiling"><a href="https://www.youtube.com/watch?v=IjDRYqtRkWA">🆗 Real-World .NET Profiling with Visual Studio</a> by <cite>dotnet | Nik Karpinsky</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>The first four minutes is a discussion of what profiling even is, with a nice workflow diagram for noobs. Next, he grabs the NLog open-source repository and opens the solution in Visual Studio.</p>
<blockquote class="quote quote-block "><div>&ldquo;Now I want to talk to the profiler agent.&rdquo;</div></blockquote><p>Oh no.</p>
<p>He has the agent build a benchmark for a given class. The build fails, though because the solution uses advanced trimming options. Of course, he can figure this out, but if a developer who needs an agent to write benchmarks gets this failure, their day is already over. Copilot is not going to figure something like this out, either.</p>
<p>He goes on to generate more code but it&rsquo;s very clear that the agent is a support tool because he brings a lot of knowhow to the table. For example, he sees immediately that the agent&rsquo;s proposed solution never cleared the <code>StringBuilder</code>, which would skew the results toward better initial performance because of thrashing caused by reallocation that affects only subsequent runs. Of course, if you don&rsquo;t notice this, then you have a shit benchmark that you will trust unreservedly because we&rsquo;ve all long since stopped doubting the output of our new overlords, LLM agents.</p>
<p>What I don&rsquo;t understand is why he keeps having the agent build and run the benchmarks. There are <kbd>hotkeys</kbd> for this. Is the future of Visual Studio just a chat interface? Who is the target audience here?</p>
<p>Anyway, his new benchmark finds a problem with <code>Boolean</code> boxing issue and the profiler agent jumps on it, optimizing the code. He shows how tedious the stack trace would be to investigate—which is not tedious at all because he clicks through it quickly—but we&rsquo;re also supposed to ignore how long that little progress circle next to &ldquo;Analyzing performance trace&rdquo; in the agent window is spinning. It takes long minutes while the developer has long since explained what the problem is and would likely have fixed it. The agent is really there for people who wouldn&rsquo;t have understood the problem illustrated by the profiling trace and who wouldn&rsquo;t be capable of judging the proposed solution.</p>
<p>The solution is <em>wrong</em>. He characterizes it as <span class="quote-inline">&ldquo;the first time I ran it, it came up with a better solution,&rdquo;</span> but that&rsquo;s a cop-out because the solution shown in the video <em>doesn&rsquo;t compile</em>. He begs the agent to return a boolean instead of a string which, like, <em>duh</em>, because the whole problem was with boxing <em>booleans</em>. But, sure, let&rsquo;s run the profiler by writing <span class="quote-inline">&ldquo;run the benchmark again&rdquo;</span> in the chat window instead of hitting a f@&amp;king <kbd>hotkey</kbd>. F@&amp;k, people are absolutely in a cult about these agents! </p>
<blockquote class="quote quote-block "><div>&ldquo;What&rsquo;s really cool here is that the profiler agent was able to have a, um, successful impact on this code and help me contribute to this repository in a meaningful way when I don&rsquo;t really know anything about this repository.&rdquo;</div></blockquote><p>WTF BRO.</p>
<p>You just made a video showing non-developers how to pad their GitHub commit histories with performance-improvement PRs that they don&rsquo;t understand (and that might not even work) by spamming open-source projects.</p>
<p>I was more excited about this one, and I think it would have worked better without the agent, but he wanted to show the agent.</p>
</div></dd>
</dl><h2 id="UIs">UIs</h2><dl><dt><span id="Forms"><a href="https://www.youtube.com/watch?v=f0971pImtlw">⛔ What&rsquo;s New in Windows Forms</a> by <cite>dotnet | Mary McGalla &amp; Klaus Loeffelmann</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>The two presenters use a giant prompt with Copilot to build a .NET 10 Winforms app to show slides like PowerPoint. As usual, they feed this prompt in to the &ldquo;planner&rdquo; to get a more agent-friendly plan that they&rsquo;ll send to the agent. They had to jabber quite a bit because the tool takes a long time to run.</p>
<p>The tool generates a list of steps in Markdown with checkboxes and a progress bar that it regenerates as it works. OK? I guess? Is Markdown a UI target now? WTF? Like, how shitty are your WPF or HTML skills when you&rsquo;re hacking a new UI library on top of a Markdown renderer? Who thought that this was a good idea? I guess the last state of the UI is preserved and can be fed back in to the planner or agent?</p>
<p>It seems to have worked, though, … except that you can&rsquo;t go to the next slide. Oh, no, wait, cursor keys are supported. </p>
<p>As usual, they didn&rsquo;t show any of the content in the gigantic prompt that they wrote.</p>
<p>These two fools seem to have no idea how the tool that they spent 25 minutes using works.</p>
<p>Also, they barely talk about Winforms. The few things that they mentioned are better covered in the <a href="https://learn.microsoft.com/en-us/dotnet/desktop/winforms/whats-new/net100">What&rsquo;s new in Windows Forms for .NET 10</a> release notes.</p>
<p>This video sucked unless you enjoy watching people watch Visual Studio build code for them.</p>
</div></dd>
<dt><span id="Windows"><a href="https://www.youtube.com/watch?v=IJ8s5OvbFdg">⛔ Modern Windows Development with .NET</a> by <cite>dotnet | Roy &amp; Michael Hawker</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>The two presenters discuss how much the community has done for WinUI3 development, with a huge style guide and much-better integration with the common MVVM toolkit also used in WPF and Maui. The WinUI3 styles can also be used with WPF, so that&rsquo;s neat, I guess. They didn&rsquo;t mention Maui. They talked about open-sourcing WinUI for quite a while.</p>
<p>They also pretty much watched Copilot do stuff like generating UI chunks from text examples, converting to JSON then to a view (I think). This was all running locally, on the NPU (Neural Processing Unit) rather than using a model in the cloud, which is kind of nice. However, it&rsquo;s amazing how happy they are to demonstrate brute-forcing regeneration of a tool that generates a JSON then view from text, again and again and again.</p>
<p>No-one asks at all anymore whether the generated code is the same, whether it works, whether there are tests to verify it, whether it makes sense to generate umpteen copies, whether the time couldn&rsquo;t be better spent on just doing it yourself, etc. etc. Of course, they never, ever show what was generated or give any indication that they have reviewed the code or consider it necessary to do so. Just run it once, look at it for a second, commit, push, and make a pull request.</p>
<p>Hey everyone! We&rsquo;ve all been wasting our time all of these years with structured development practices. With this tool that&rsquo;s right 70% of the time, you can skip all of that. Look at that UI go! Watch it flicker as it generates a whole bunch of stuff you&rsquo;re never even going to bother looking at until you get a call at 03:00 in the morning because everything blew up. Just kidding. No-one&rsquo;s going to call you. They&rsquo;re going to call other people who were stupid enough to take jobs on an on-call team.</p>
</div></dd>
<dt><span id="TUIs"><a href="https://www.youtube.com/watch?v=Z6e5ZP9y3_8">✅ TUIs Are Back (Although They Never Left): Creating Modern CLI Apps in .NET.</a> by <cite>dotnet | Andres Pineda</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>He goes through the history of UIs for the first third of the video, which is kind of interesting and provides decent context for why we might want a TUI. In the second third, he presents the <code>Spectre.Console</code> framework for building TUIs. The initial version uses an in-memory database, then an SQLite database, and then an external database. It uses dependency injection and the by-now standard application startup.</p>
<p>He also discusses <code>Terminal.Gui</code>, which runs on all supported platforms and has Miguel de Icaza as a contributor. This one creates apps that kind of look the old Borland DOS-mode applications. You build them with MVVM (supports <code>CommunityToolkit.Mvvm</code>) and generated views (not XAML) that you build with a text-console-based visual designer. You kind of have to see it to believe it. It&rsquo;s really pretty cool.</p>
<p>If you want to use XAML, though, you can use <code>RazorConsole</code> with <code>Spectre.Console</code> to build UIs with that instead.</p>
</div></dd>
<dt><span id="Ship"><a href="https://www.youtube.com/watch?v=iaU3lsvB_Ig">🆗 Ship Faster with .NET MAUI: Real-World Pitfalls and How to Nuke Them</a> by <cite>dotnet | Paul Usher</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>A lot of the pitfalls he discusses are relatively general: resolution, distribution, deployment, staying up to date with security, etc.</p>
<p>Dude recommends <code>Console.WriteLine()</code> as an important debugging tool. Ok, buddy. On the other hand, it&rsquo;s nice to see someone who shows his whole setup in detail, which, even though some of his tools are outdated (e.g., he uses <em>CodeRush</em>!), is nice to see, especially if you really have no idea how to get started.</p>
<p>He goes on to discussing app-store-related problems and how to overcome some of them, which is also quite helpful, as this is a part of the process that few people talk about. It&rsquo;s not particularly enlightening but it&rsquo;s good to discuss, as you can&rsquo;t deploy an app without getting on app store.</p>
<p>Another pitfall is dealing with lifecycle changes and interruptions: is the app in the foreground? Is the device asleep? Is there network connectivity? Is the battery low? Is the app in sleep mode? When do you perform which initialization? Which expectations can you have about connectivity? Everything is asynchronous and the situation outside the app changes all the time. You have to watch all of the events and respond appropriately.</p>
<p>He advises using the emulator or simulator for a tighter feedback loop but there&rsquo;s no way to avoid testing on a target device—or multiple target devices, as their behavior varies as well. He mentions that two recent Android devices (a Pixel and a Samsung) had different behavior in crucial areas affecting his apps.</p>
</div></dd>
<dt><span id="Headless"><a href="https://www.youtube.com/watch?v=0Z1plDp_rvI">✅ Building Rock-Solid Avalonia Apps A Guide to Headless Testing with AI Assistance</a> by <cite>dotnet | Dong Bin</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>Whereas Avalonia and Maui both support iOS, Android, Windows, and MacOS targets, Avalonia also support Linux targets, including Linux running on embedded systems. The target that Dong addresses though is the <em>headless</em> mode, which is used for end-to-end UI testing. Avalonia&rsquo;s rendering is completely decoupled from the platform, with the headless platform being just another target, like Windows or Mac.</p>
<p>God bless him for actually showing us how to write tests in the code editor. he&rsquo;s using Rider on Windows. His code uses <code>ObservableProperty</code> from the Community Toolkit. This is a good demo.</p>
<p>In an advanced demo, he shows how to use &ldquo;screenshot&rdquo; rendering, even in headless mode. He also shows how to test controls for performance, both in speed and memory-usage, which is very important for building controls for highly constrained environments like embedded systems.</p>
<p>He points out that headless testing won&rsquo;t help you with testing native features, actual visual look-&amp;-feel. Instead, you can use the Skia renderer to approximate tests like that.</p>
<p>Finally, he actually introduces a usage of AI that makes sense to me: helping to write all of the unit, integrated, headless, and render tests. He explains how the task is focused, verifiable, and already has a lot of context to keep the generated code on the right path.</p>
</div></dd>
<dt><span id="Maui"><a href="https://www.youtube.com/watch?v=6kz3XWCVij0">✅  What&rsquo;s New in .NET MAUI</a> by <cite>dotnet | David Ortinau</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>This one starts with an overview of the project. SyncFusion contributes heavily, from dozens of PRs to providing over 30 controls as open-source controls. </p>
<p>They&rsquo;re also working much more closely with the Uno platform, which is ostensibly a competing framework but seems to be merging or moving closer to Maui. They&rsquo;re working on NativeAOT for Android, SkiaSharp improvements (it&rsquo;s their main rendering library), as well as WebAssembly multi-threading (that&rsquo;s another target that they have that Maui does not, unless you count Blazor integration).</p>
<p>His demonstration is kind of neat: he shows a Maui app with SyncFusion controls and Community Toolkit, all running within an Uno Platform App. He shows it running in an Android emulator. This kind of support may extend Maui&rsquo;s reach without having to replicate everything. For example, the WebAssembly target Uno offers works seamlessly with .NET Maui apps. He demos a NuGet browser that was written for desktop, but now running in a browser.</p>
<p>Next up is a very prosaic but very welcome addition: global usings/namespace declarations for XAML files. You no longer need to use prefixes and you no longer have a clump of stuff at the top of the file. On top of that, they also now support implicit namespaces (the feature is in preview).</p>
<p>Now a XAML file for Maui can look like this:</p>
<pre class=" "><code>&lt;ContentPage x:Class="DeveloperBalance.Pages.MainPage"
             x:DataType="MainPageModel"
             x:Name= "OverviewPage"
             Title="{Binding Today}"&gt;</code></pre><p>This is really nice.</p>
<p>There&rsquo;s also XAML source-generation now. This increases speed of debugging and reduces the differences between the debug and release builds massively. This is an <em>opt-in</em> feature but it sounds great. You can debug the generated code instead of relying on a bunch of reflection. Debugging uses 99% less memory and view-inflation is now 1000% faster (10x). Overall app performance is 25% faster with 30% less memory usage.</p>
<p>He talks about support for &ldquo;safe edges&rdquo; (UI integration with mobile form factors) and improved support for hybrid apps. He briefly discusses Aspire orchestration, which is completely integrated. This is especially interesting with hybrid solutions because the front-end actually has two parts that need to be coordinated. Doing this with Aspire is interesting. You can use the dashboard to inspect telemetry because the standard rendering is integrated as well. This telemetry is also available on the command line if you don&rsquo;t use Aspire.</p>
</div></dd>
<dt><span id="Blazor"><a href="https://www.youtube.com/watch?v=V0Af7y7aMBE">✅ Build better web apps with Blazor in .NET 10</a> by <cite>dotnet | Daniel Roth</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>The author talks a bit about large-scale apps in the U.S. and Europe that are built with Maui and, specifically, Maui Blazor. His presentation in this part is quite stilted and seems to have been massaged by the PR department. Like, he says that .NET Aspire makes you <span class="quote-inline">&ldquo;cloud-ready,&rdquo;</span> which, if you&rsquo;ve watched the Aspire talks, is no longer the focus of Aspire, and hasn&rsquo;t been for a while. Deploying to the cloud is <em>possible</em> and well-supported, but it&rsquo;s not the main use case.</p>
<p>He does demo some code, though. He shows passkey-integration for Blazor apps. I love how people watch this and think, &ldquo;this is great; so much easier to log in,&rdquo; whereas I watch it and have just watched someone log in using a 4-digit PIN rather than a safe password. How is this better? It&rsquo;s similar to using a password manager on your device that&rsquo;s always logged in, though. But passkeys are really replicating a bunch of the convenience that you already had with a password manager.</p>
<p>Next up is better integration for telemetry, which all appears in the Aspire dashboard. There are also advanced diagnostics, like being able to extract memory dumps and low-level runtime metrics from a running WASM Blazor app using a JavaScript command. The <code>dottrace</code> file can be easily converted to a <code>gcdump</code> file using the <code>dotnet</code> command and can then be analyzed in Visual Studio. This got very technical very quickly and I am here for it.</p>
<p>Blazor is also about 20% faster in .NET 10. For developers,</p>
<ul>
<li>Hot Reload is better; he demonstrates an over 10x speed improvement, from 38s to about 3s.</li>
<li>Full-graph form-validation, so complex forms no longer need custom validation.</li>
<li>Automated browser/end-to-end testing using <code>WebApplicationFactory</code> but then also launching a full-fledged headless browser and then running Playwright tests against it.</li>
<li>Better state-persistence support, with automatic  persistence on idle, pause/resume on idle, etc. This all integrates with the telemetry and can be inspected in the Aspire dashboard.</li></ul><p>Very interesting and encouraging.</p>
</div></dd>
</dl><h2 id="Aspire">Aspire</h2><dl><dt><span id="Aspire"><a href="https://www.youtube.com/watch?v=FcAi-kqo3ps">✅ Taking .NET out of .NET Aspire − working with non-.NET applications</a> by <cite>dotnet | David Gardiner</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>He presents a multi-language, multi-environment solution that uses Python/uv, Rust/cargo, and TypeScript/pnpm, each of which are run manually. From there, he shows a template Aspire solution with a Redis cache, an API service, and a web front-end.</p>
<p>He starts with a new Aspire solution, then integrates Mongo support using <code>aspire-add-mongo</code> and then integrates the PowerShell script that populates the data using an Aspire API. With that loaded up, he searches for an Aspire extension that works with his existing Python/uv setup. He doesn&rsquo;t have to change anything; he just binds the startup of that part into Aspire so that the service is available to his &ldquo;app host&rdquo; (and also shows up on the dashboard). The Rust service easily follows, again by using an existing Aspire package to integrate Rust/cargo specifically. Finally, he binds the React/Vite/pnpm solution using a node.js extension from the Community Toolkit (again).</p>
<p>Where Aspire shines is that you don&rsquo;t need to run these disparate apps from various command lines or scripts, and you don&rsquo;t need to configure containers with YAML; you bind the various components and services with C# code, indicating dependencies between them, which Aspire not only handles but displays in the dashboard.</p>
<p>He uses this power to remove hard-coded ports from his services, using the C# variables to read the and use the dynamically assigned ports instead. Finally, he integrates OpenTelemetry into the Python and Rust services so that the various services show their telemetry in the Aspire console, structured logging, traces, and metrics views.</p>
<p>Finally, he adds an extra service that uses a node backend. Adding it once you have Aspire configured is very, very easy.</p>
<p>This is an absolutely great 22-minute video that you can send to anyone who asks &ldquo;what can Aspire do for me?&rdquo;</p>
</div></dd>
<dt><span id="Architecure"><a href="https://www.youtube.com/watch?v=8NoetLolw-0">⛔ From Architecture to Docs: .NET Aspire Documented with Copilot</a> by <cite>dotnet | Jorge Fernandez &amp; David Oliva</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>This video explains the basics of Aspire (like, the <em>very</em> basics), as well as the basics of Copilot and MCP. You can skip that part, as they&rsquo;re just reading from the slides, in what I am forced to note are pretty strong Spanish accents.</p>
<p>I honestly can barely tell what&rsquo;s going on here. I feel so bad for these guys because they are probably much better in their native language but it&rsquo;s so much work understanding them in English. They&rsquo;re generating stuff with Copilot to generate an architecture overview for an existing solution file, using Markdown and ASCII diagrams. They then upgrade to using Mermaid diagrams. But I dare you to replicate what they did.</p>
</div></dd>
<dt><span id="Supercharging"><a href="https://www.youtube.com/watch?v=p_zslgBi06k">✅ Windows 365 Meets Aspire − Supercharging Multi-Repo Microservice Productivity</a> by <cite>dotnet | Eric Guo &amp; Chuanbo Zhang</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>This video demonstrates using .NET Aspire to wire up microservice servers with simulated Azure services in order to test InTune deployment software. It&rsquo;s quite a complex use case. They show how you can test locally, using Docker and the Azure-service simulators, and also deploy to Azure infrastructure.</p>
<p>They even show how to simulate some of your own microservices by using the VS .http file format to quickly mock responses for a subset of the functionality. In this vein, they also discuss how to configure data-seeding for a stable environment, then finish up by discussing how to use XUnit to run automated tests against this entire infrastructure, both locally and in pipelines.</p>
<p>Although the specific use case is quite complex, there is a lot of good stuff to learn about testing automation in this talk. .NET Aspire makes it a lot easier to run locally and in the cloud without different approaches.</p>
</div></dd>
<dt><span id="DeepDive"><a href="https://www.youtube.com/watch?v=WSHMfrCHD0c">✅ Deep Dive: Extending and Customizing Aspire</a> by <cite>dotnet | David Fowler &amp; Damian Edwards</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>Fowler shows a single-project solution with a .NET Aspire AppHost project that binds non-.NET dependencies (i.e., they&rsquo;re not they&rsquo;re own projects). One of the dependencies is a postgres database that is absolutely a dependency but has classically been managed outside of the solution. Now, you can declare and bind the dependencies with C#. The takeaway is: a much slimmer readme file, that you just clone and call <code>aspire run</code>.</p>
<p>The great thing about this is that it has to stay in-sync, unlike a readme file.</p>
<p>Fowler shows the app dashboard with a lot of custom dependencies, including the .NET 10 OpenAPI replacement called Scalar, which is fully integrated into the Aspire dashboard. Fowler even shows how you can customize the dashboard appearance with C# code, using very standard options customization, as you would see in other host-based applications like ASP.Net (or many other types, Console, Windows Service, etc.).</p>
<p>Damian points out what we&rsquo;re all thinking: holy crap, Fowler, WTH you hacked everything into the <code>AppHost.cs</code> file, like hundreds of lines, including a custom database seeder that uses the endpoint spun up by Aspire. It&rsquo;s neat to see how you can bind in that kind of code, though, to just wait until the HTTP REST server is available and then to run some C# code to seed it with data. It&rsquo;s ugly and it&rsquo;s hacky in his code, but it&rsquo;s wonderful that you can prototype and test so quickly with disparate systems and components. He has only one C# file and orchestrates diverse other components and scripts from it.</p>
<p>OK, he continues to show how you can bind commands into the Aspire Dashboard that he uses to bind a &ldquo;reset command&rdquo; that uses the Aspire interaction service to show a message box requesting approval.</p>
<p>Finally, at the very end, he shows how to use an MCP integration with Aspire. This is no more exciting than watching anyone else watch Copilot stumble drunkenly around a dark room. It&rsquo;s only the last two minutes so we&rsquo;re not subjected to too much of this foolishness. It was still writing furiously into the chat as the video ended.</p>
<p>Fowler is also using <em>Visual Studio Code</em> rather than <em>Visual Studio</em>. He also speaks very, very quickly, so brace yourself.</p>
</div></dd>
<dt><span id="Maddy"><a href="https://www.youtube.com/watch?v=dJdXdRiIfDw">✅ Aspire Unplugged with David and Maddy</a> by <cite>dotnet | David Fowler &amp; Maddy Montaquila</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>They have T-Shirts with a great sentiment on them, <span class="quote-inline">&ldquo;Friends don&rsquo;t let friends write YAML.&rdquo;</span> Except that the <span class="quote-inline">&ldquo;Write YAML&rdquo;</span> part is really, really big for some reason, so it looks like the shirts are exhorting users to actually write YAML. Whatever.</p>
<p>The first question is for Fowler, who describes the impetus of Aspire. It came from the pains of configuring so many scripts for infrastructure, even with a strong tool like Kubernetes.</p>
<p>It grew into a <span class="quote-inline">&ldquo;general-purpose  dev tool&rdquo;</span> for any sort of environment. It was originally scoped as a cloud-native tool but it quickly became obvious that nearly every solution has some sort of orchestration and scripting that always ended up in readme files or PowerShell or Bash scripts: starting the database, starting the backend for a mobile app, whatever.</p>
<blockquote class="quote quote-block "><div>&ldquo;That became one of our key things, right? Like you want to onboard someone, you model all the stuff in code and then like you don&rsquo;t have to tell someone run this script, run that script, pass the output from this script to that script, string together stuff. Like you can just kind of like put it in code, have it be there.&rdquo;</div></blockquote><p>He gives a lot of examples and detail about how polyglot and scalable .NET Aspire is. The other video he did—<a href="https://www.youtube.com/watch?v=WSHMfrCHD0c">Deep Dive: Extending and Customizing Aspire</a> by <cite>dotnet | David Fowler &amp; Damian Edwards</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)—showed a lot of code for integrating JavaScript and Python services. Another video—<a href="https://www.youtube.com/watch?v=FcAi-kqo3ps">Taking .NET out of .NET Aspire − working with non-.NET applications</a> by <cite>dotnet | David Gardiner</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)—also shows how to integrate a lot of plugins from the community, including a Rust backend service.</p>
<p>The next big question is about persisting containers, supporting hot-reload, which is finicky to design and increases the complexity of the architecture significantly but the upside is huge if they can get it working. They managed a huge rewrite of all of the plumbing to support this type of scenario and are much better positioned for future developments.</p>
<p>The next question builds on this, asking about multi-repo support, with what&rsquo;s called the &ldquo;AppHost in AppHost&rdquo; question: can you nest .NET Aspire apps? How does that work? It would be nice to be able to group shared services into one AppHost and then reference then from another high-level AppHost (for much larger solutions, obviously). What happens to the dashboards, though?</p>
<p>The idea of Aspire is to work with existing solutions, so the <code>aspire init</code> is a much more important workflow than <code>aspire new</code>. That is, you&rsquo;re much more likely to already have a solution into which you&rsquo;d like to integrate an AppHost or set of projects around which you&rsquo;d like to wrap an AppHost than you are to be green-fielding a solution and starting with Aspire.</p>
<p>I love the dynamic between Fowler and Maddy. You can really tell they love working together, that they really, really respect one another. They love the &ldquo;adult&rdquo; Damian as well.</p>
</div></dd>
</dl><h2 id="Cloud">Cloud</h2><dl><dt><span id="Containers"><a href="https://www.youtube.com/watch?v=IfhxdKKd4GU">🆗 What&rsquo;s New in Containers for .NET 10</a> by <cite>dotnet | Rich Lander &amp; Chet Husk</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" ">The two presenters first discuss the history of containers in .NET, including operating systems, support periods, etc. The second half demonstrates using <code>dotnet publish</code> using AOT and multiple OS targets and then deploying them into various containers. This targets are all variations of Linux and for command-line or server apps.</div></dd>
<dt><span id="Service"><a href="https://www.youtube.com/watch?v=WSHMfrCHD0c">✅ What&rsquo;s new in Azure App Service for .NET developers</a> by <cite>dotnet | Byron Tardif</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>He quickly covers when .NET 10 will be available in App Service for Linux (Ubuntu, not Debian) and Windows, then moves on to showing how to use .NET Aspire to build and deploy an application to App Service.</p>
<p>Blessedly, he&rsquo;s doing it manually, following a simple guide, rather than &ldquo;getting Copilot to do it for him.&rdquo; This inspires much more confidence that it&rsquo;s well-designed and simple enough to actually learn, rather than implying that you need to ask a black-box globe-girdling data-model in order to grok it.</p>
<p>He&rsquo;s got the standard Aspire app and then types <code>azd up</code>. It takes five minutes for the system to analyze, find a subscription, determine existing resources, and then deploy, creating services where needed. Access to the deployment is automatically configured (e.g., the dashboard is only available for authorized users).</p>
<p>He quickly shows the Azure Portal resources that were created for the App Service. This is nice. .NET Aspire is a worthy and welcome successor to Bicep scripts.</p>
<p>He shows a bunch of features of App Services specifically, including scaling options.</p>
</div></dd>
<dt><span id="Carbon"><a href="https://www.youtube.com/watch?v=IqSzmerSXuk">🆗 Carbon Aware Computing − Using .NET Open Source libraries for more sustainable applications</a> by <cite>dotnet | Aydin Mir Mohammadi</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>This video covers tactics and tooling for running data services in a sustainable manner. E.g., load-shifting from day to night, adjusting available capacity depending on local energy availability, etc. There&rsquo;s a lot of telemetry and real-time monitoring needed to even begin working in a sustainable manner.</p>
<p>In the second half, he gets to integrating an SDK that calculated best-execution time. Even libraries like Hangfire have methods like <code>IncludeCarbonAwareExecution()</code> (I&rsquo;m not kidding!) that wrap all of this in a very high-level abstraction.</p>
</div></dd>
</dl><h2 id="AI">AI</h2><dl><dt><span id="Dashboard"><a href="https://www.youtube.com/watch?v=vFSHgAlr9oE">⛔️ Architecting an AI-Powered Sales Dashboard with .NET MAUI and Azure OpenAI</a> by <cite>dotnet | Shriram Sankaran</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>The app he discusses summarizes market data using AI. Did we all just choose to forget that AIs are not good at numbers? Did I miss the technology that we used to fix this problem? Remember &ldquo;AIs are not good at numbers?&rdquo; I do! When did we fix that?</p>
<p>Anyway, the UI looks decent and it&rsquo;s completely cross-platform thanks to Maui. It uses SyncFusion&rsquo;s controls as well as standard Maui controls. He spends quite a bit of time going over the features of his app. The AI is used to query the app data with a built-in chatbot.</p>
<p>When he finally gets to the code, his project is curiously not using CommunityToolkit.MVVM (all of the properties are implemented manually instead of source-generated. He eventually gets to more source but it&rsquo;s not very illuminating. I can&rsquo;t really recommend it.</p>
</div></dd>
<dt><span id="Seamless"><a href="https://www.youtube.com/watch?v=yKhaYLYK4Sg">🆗 One Question, One Answer: Designing Seamless AI Agents with C#</a> by <cite>dotnet | Mark Miller</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>The presenter works on CodeRush for DevExpress. He uses CodeRush (I guess?) in dictation mode to build his calculator app, which, you know, is going to be something that the AI can easily build, as there are probably millions of examples in the training data. The generated code is horrifically defensive and not even close to what I would have made, or what I consider to be maintainable, but it&rsquo;s fine for a prototype.</p>
<p>So, here we have another video that&rsquo;s just showing how to program with an AI. He&rsquo;s arguing for a workflow that stays in the code and is delivered via <em>talking</em>—because it&rsquo;s 2-4 times faster than typing for most people and LLMs are very forgiving of extra words and filler words—so that you can avoid most of the pain points of working with the by-now &ldquo;classic&rdquo; AI-chat interface.</p>
<p>He talks about lot about how to optimize the context but I guess his tool does this?</p>
</div></dd>
<dt><span id="Overcoming"><a href="https://www.youtube.com/watch?v=QZsxrDC8hr0">✅ Overcoming the limitations when using AI</a> by <cite>dotnet | Michael Washington</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>This guy doesn&rsquo;t show up on the video. His voiceover and cadence is somewhat odd. It sounds very much like a text-to-speech engine. The whole presentation seems fake but the information is quite interesting. I guess he wrote the presentation but then had a machine read it for him.</p>
<p>He discusses how LLMs are bad at math, so the solution was to have the LLM create code to calculate answers. It&rsquo;s wild how much f@&amp;king processing power we&rsquo;re willing to invest in getting the correct answer to 43 × 34. The LLM interprets the text, then generates an answer that includes a little Python program that it then executes in a sandbox so that i can include the output in its answer. It&rsquo;s just flat-out nuts. Still, he shows off how he&rsquo;s managed to work around these limitations but they are really elaborate.</p>
<p>Next up is that <span class="quote-inline">&ldquo;AIs can&rsquo;t write fiction&rdquo;</span>. He discusses AI story-builders, which use text-file databases in order to maintain context and continuity for stories. He found that page-by-page and chapter-by-chapter doesn&rsquo;t work very well, but that paragraph-by-paragraph is the level of granularity at which an LLM needs guidance. There is a whole program surrounding the LLM&rsquo;s inputs and outputs. Without it, the story goes off the rails immediately.</p>
<p>After that, he shows that AI cannot create applications. They can <em>code</em> but they have no idea of architecture and no idea how to deal with complex systems.</p>
<p>Find his slides and work at <a href="https://blazorhelpwebsite.com/ViewBlogPost/20079">Overcoming limitations When Using AI</a>.</p>
</div></dd>
<dt><span id="Italian"><a href="https://www.youtube.com/watch?v=kNPTDlxEA-Y">🆗 Modernizing a 17th Century Italian-English Dictionary</a> by <cite>dotnet | Wayne Sebbens</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" ">This was not uninteresting but it wasn&rsquo;t a lot of programming information. Half of the video is a discussion of European martial arts and its relation to archaic Italian dialects and spellings. He basically made an app for searching these terms using vector databases and ML in .NET. If that sounds like something you want to do, check out the video and his <a href="https://github.com/Sebbs128/florio-dotnetconf-links">repo</a> (<cite><a href="http://github.com/">GitHub</a></cite>). If not, then you can safely skip the video.</div></dd>
</dl><h2 id="Everything else">Everything else</h2><dl><dt><span id="Passkeys"><a href="https://www.youtube.com/watch?v=U4_KcjJOxOE">🆗 Going Passwordless − A Practical Guide to Passkeys in ASP.NET Core</a> by <cite>dotnet | Maarten Balliauw</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" ">This is a decent and thorough introduction to authentication mechanisms, from passwords to MFA to passkeys, illustrating both the differences between passkeys and other methods as well as the .NET support for working with passkeys in your own applications (mostly in the last third of the video).</div></dd>
<dt><span id="Pipelines"><a href="https://www.youtube.com/watch?v=e7hkKyQEcN8">✅ GitHub Actions DevOps Pipelines as Code using C# and Cake SDK</a> by <cite>dotnet | Mattias Karlsson</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>Cake is a build system written in C# with a rich .NET API. Mattias did a bunch of live-coding. The Cake scripts might be useful for defining a bunch of stuff that we currently use Azure Pipeline Definitions for. he demonstrates how provider plugins enable high-level abstractions that make it much easier to specify a declarative pipeline. It&rsquo;s all in C#, so you use a code editor like Rider, with code-completion, refactoring, etc.</p>
<p>You continue to use the YAML pipeline definition to set up the environment but everything else will be in the Cake file. This makes a lot of sense and could be quite powerful. Instead of using a bunch of pipeline nested templates that you can&rsquo;t run or debug, you could have a NuGet package with common APIs for Cake. You can also test a bunch of the Cake script locally (unless you have some highly specific steps like signing with a key only available in the cloud or calling a tool that&rsquo;s only available in the cloud. You can use standard C# to make these optional when testing locally, though.</p>
</div></dd>
<dt><span id="Beer"><a href="https://www.youtube.com/watch?v=Yi6Uf5DojaU">🆗 If .NET brewed beer…</a> by <cite>dotnet | Shaun Lawrence</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></dt>
<dd><div class=" "><p>He starts with a 10-minute presentation on his home-brewing setup, finally getting to the point where he discusses the embedded device for which he used .NET: A Meadow F7v2 DevModule. For the next ten minutes, he just kind of muddles about, showing the API surface of the meadow library. </p>
<p>After showing how to integrate a temperature sensor, he shows how to integrate PID control (<a href="https://en.wikipedia.org/wiki/Proportional&ndash;integral&ndash;derivative_controller">Proportional-Integral-Derivative control</a>), again using the API. He mixes in support for PWN (<a href="https://en.wikipedia.org/wiki/Pulse-width_modulation">Pulse-width Modulation</a>). Both of these are commonly used algorithms to stabilize the interaction with a sensor: for interpreting and smoothing the signal and for ensuring that the written value corresponds to the desired value without slewing about. At the very end, he shows that his UI is built with Maui but he doesn&rsquo;t get into it too much.</p>
<p>It&rsquo;s nice that they provide low-level support for working directly with hardware but it&rsquo;s not too fascinating. It&rsquo;s good to know that C# is increasingly becoming a viable alternative to systems programming with C, C++, or even Rust or Go. He uses Visual Studio Code.</p>
</div></dd>
</dl>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5732</guid>
    <title><![CDATA[Toub&rsquo;s 232-page tour-de-force on performance in .NET 10]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5732</link>
    <pubDate>Tue, 18 Nov 2025 22:55:56 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. Nov 2025 22:55:56 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5732/stephen_toub.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5732/stephen_toub_tn.jpg" alt=" " class=" align-right"></a>The book-length <a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-10/">Performance Improvements in .NET 10</a> by <cite>Stephen Toub</cite> (<cite><a href="http://devblogs.microsoft.com/">Microsoft DevBlogs</a></cite>) arrived a couple of months ago.</p>
<p>He explains how the various compilers (AOT, JIT, etc.) have been optimized to eliminate allocations and just generally optimized for performance. A reduction in allocations is a multi-win: the performance is better because the allocator isn&rsquo;t working, the memory usage has dropped, and the garbage collector also works less.</p>
<p>See previous coverage in:</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=5189">Toub’s 234-page tour-de-force on performance in .NET 9</a> (2024)</li>
<li>Somehow, I never documented .NET 8. Huh.</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4554#programming">Performance Improvements in .NET 7</a> (2022).</li></ul><h2>A presentation at .NET Build 2025</h2><p>If you prefer a 30-minute video, then you&rsquo;re in luck.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/snnULnTWcNM" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=snnULnTWcNM">Performance Improvements in .NET 10</a> by <cite>dotnet | Stephen Toub</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>He compares .NET Framework 4.8 vs. .NET 9 vs. .NET 10. The most impressive improvements are from 4.8 to 9.0, of course, but he highlights some interesting places where .NET 10 eclipses .NET 9, where .NET 9 had already eclipsed .NET Framework 4.8.</p>
<p>The last example shows how regular expressions have been continually optimized so that an operation that took 24ms in .NET Framework 4.8 was improved by about 12x to 2.5ms in .NET 9 but has been further improved by about 62,500x to about 40ns in .NET 10.</p>
<h2>Citations and Notes</h2><p>And now, on to the citations from Toub&rsquo;s book along with my notes.</p>
<p>He starts off with a bit of history and context in the wider world.</p>
<blockquote class="quote quote-block "><div>&ldquo;What made <a href="https://en.wikipedia.org/wiki/Frederic_Tudor">Tudor’s</a> ice last halfway around the world wasn’t one big idea. It was a plethora of small improvements, each multiplying the effect of the last. In software development, the same principle holds: <strong>big leaps forward in performance rarely come from a single sweeping change, rather from hundreds or thousands of targeted optimizations that compound into something transformative.</strong> .NET 10’s performance story isn’t about one Disney-esque magical idea; it’s about carefully shaving off nanoseconds here and tens of bytes there, streamlining operations that are executed trillions of times.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;As with many languages, .NET historically has had an “abstraction penalty,” those extra allocations and indirections that can occur when using high-level language features like interfaces, iterators, and delegates. Each year, the JIT gets better and better at optimizing away layers of abstraction, so that developers get to write simple code and still get great performance. .NET 10 continues this tradition. <strong>The result is that idiomatic C# (using interfaces, foreach loops, lambdas, etc.) runs even closer to the raw speed of meticulously crafted and hand-tuned code.</strong>&rdquo;</div></blockquote><h3>JIT</h3><blockquote class="quote quote-block "><div>&ldquo;If the compiler can prove an object doesn’t escape, then that object’s lifetime is bounded by the method, and it can be allocated on the stack instead of on the heap. Stack allocation is much cheaper (just pointer bumping for allocation and automatic freeing when the method exits) and reduces GC pressure because, well, the object doesn’t need to be tracked by the GC. <strong>.NET 9 had already introduced some limited escape analysis and stack allocation support; .NET 10 takes this significantly further.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;[…] where things gets interesting is around what the JIT is able to devirtualize. In .NET 9, it struggles to devirtualize calls to the interface implementations specifically on T[], so it won’t devirtualize either the <code>_list.GetEnumerator()</code> call nor the _list[index] call. However, the enumerator that’s returned is just a normal type that implements <code>IEnumerator&lt;T&gt;</code>, and the JIT has no problem devirtualizing its <code>MoveNext</code> and <code>Current</code> members. Which means that <strong>we’re actually paying a lot more going through the indexer, because for N elements, we’re having to make N interface calls, whereas with the enumerator, we only need the one with <code>GetEnumerator</code> interface call and then no more after that.</strong>&rdquo;</div></blockquote><p>To be clear: this has been addressed in .NET 10, so that the indexer is also almost always devirtualized.</p>
<blockquote class="quote quote-block "><div>&ldquo;dotnet/runtime#110827 from @hez2010 also helps more methods to be inlined by doing another pass looking for opportunities after later phases of devirtualization. The JIT’s optimizations are split up into multiple phases; each phase can make improvements, and those improvements can expose additional opportunities. If those opportunities would only be capitalized on by a phase that already ran, they can be missed. But <strong>for phases that are relatively cheap to perform, such as doing a pass looking for additional inlining opportunities, those phases can be repeated once enough other optimization has happened that it’s likely productive to do so again.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;The <strong>static readonly</strong> field is immutable, arrays can’t be resized, and the JIT can guarantee that the field is initialized prior to generating the code for <strong>Read</strong>. Therefore, when generating the code for <strong>Read</strong>, it can know with certainty that the array is of length three, and we’re accessing the element at index two. Therefore, <strong>the specified array index is guaranteed to be within bounds, and there’s no need for a bounds check.</strong>&rdquo;</div></blockquote><p>The JIT has been doing these kinds of optimizations for a long time but the number of cases for which it can &ldquo;prove&rdquo; increases with each release.</p>
<blockquote class="quote quote-block "><div>&ldquo;My choice of benchmark in this case was not coincidental. This pattern shows up in the <code>FormattingHelpers.CountDigits</code> internal method that’s used by the core primitive types in their <code>ToString</code> and <code>TryFormat</code> implementations, in order to determine how much space will be needed to store rendered digits for a number. As with the previous example, this routine is considered core enough that <strong>it was using unsafe code to avoid the bounds check. With this fix, the code was able to be changed back to using a simple span access, and even with the simpler code, it’s now also faster.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Many of these different optimizations interact with each other. Dynamic PGO triggers a form of cloning, as part of the guarded devirtualization (GDV) mentioned earlier: if the instrumentation data reveals that a particular virtual call is generally performed on an instance of a specific type, <strong>the JIT can clone the resulting code into one path specific to that type and another path that handles any type. That then enables the specific-type code path to devirtualize the call and possibly inline it.</strong> And if it inlines it, that then provides more opportunities for the JIT to see that an object doesn’t escape, and potentially stack allocate it. dotnet/runtime#111473, dotnet/runtime#116978, dotnet/runtime#116992, dotnet/runtime#117222, and dotnet/runtime#117295 enable that, <strong>enhancing escape analysis to determine if an object only escapes when such a generated type test fails</strong> (when the target object isn’t of the expected common type).&rdquo;</div></blockquote><p>This led to several several dozen performance-test improvements across the board when the PR landed. The whole section boils down to the JIT optimization working not only for regular loops, enumerable loops, but also hand-unrolled code with multiple array accesses (where bounds-checks can now be elided using clever cloning).</p>
<h4>Inlining</h4><blockquote class="quote quote-block "><div>&ldquo;[…] <strong>generally the most benefit from inlining comes from knock-on benefits.</strong> Just as a simple example, if you have code like:&rdquo;<pre class=" "><code>int i = Divide(10, 5);

static int Divide(int n, int d) =&gt; n / d;</code></pre>&ldquo;if <code>Divide</code> doesn’t get inlined, then when <code>Divide</code> is called, it’ll need to perform the actual <code>idiv</code>, which is a relatively expensive operation. In contrast, if <code>Divide</code> is inlined, then the call site becomes:&rdquo;<pre class=" "><code>int i = 10 / 5;</code></pre>&ldquo;which <strong>can be evaluated at compile time</strong> and becomes just:&rdquo;<pre class=" "><code>int i = 2;</code></pre></div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Just inlining everything would be bad; inlining copies code, which results in more code, which can have significant negative repercussions. For example, <strong>inlining’s increased code size puts more pressure on caches.</strong> Processors have an instruction cache, a small amount of super fast memory in a CPU that stores recently used instructions, making them really fast to access again the next time they’re needed (such as the next iteration through a loop, or the next time that same function is called).&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;As part of these heuristics, the JIT has <strong>the notion of “boosts,” where observations it makes about things methods do boost the chances of that method being inlined.</strong> dotnet/runtime#114806 gives a boost to methods that appear to be returning new arrays of a small, fixed length; <strong>if those arrays can instead be allocated in the caller’s frame, the JIT might then be able to discover they don’t escape and enable them to be stack allocated.</strong> dotnet/runtime#110596 similarly looks for boxing, as the caller could possibly instead avoid the box entirely.&rdquo;</div></blockquote><h4>Code Layout</h4><blockquote class="quote quote-block "><div>&ldquo;When the JIT compiler generates assembly from the IL emitted by the C# compiler, it organizes that code into “basic blocks,” a sequence of instructions with one entry point and one exit point, no jumps inside, no branches out except at the end. These blocks can then be moved around as a unit, and the order in which these blocks are placed in memory is referred to as “code layout” or “basic block layout.” This <strong>ordering can have a significant performance impact</strong> because modern CPUs rely heavily on an instruction cache and on branch prediction to keep things moving fast. <strong>If frequently executed (“hot”) blocks are close together and follow a common execution path, the CPU can execute them with fewer cache misses and fewer mispredicted jumps.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Consider a tight loop executed millions of times. A good layout keeps the loop entry, body, and backward edge (the jump back to the beginning of the body to do the next iteration) right next to each other, letting the CPU fetch them straight from the cache. <strong>In a bad layout, that loop might be interwoven with unrelated cold blocks (say, a <code>catch</code> block for a <code>try</code> in the loop), forcing the CPU to load instructions from different places and disrupting the flow.</strong> Similarly, for an <code>if</code> block, the likely path should generally be the next block so no jump is required, with the unlikely branch behind a short jump away, as that <strong>better aligns with the sensibilities of branch predictors.</strong>&rdquo;</div></blockquote><h4>GC Write Barriers</h4><blockquote class="quote quote-block "><div>&ldquo;<strong>Whenever there’s a reference write that could cross a generation, the JIT emits a call to a helper</strong> that tracks the information in a “card table,” and <strong>when the GC runs, it consults this table to see if it needs to scan a portion of the higher generations.</strong> That helper is referred to as a “GC write barrier.” Since a write barrier is potentially employed on every reference write, it must be super fast, and in fact the runtime has several different variations of write barriers so that the JIT can pick one optimized for the given situation. Of course, <strong>the fastest write barrier is one that doesn’t need to exist at all, so as with bounds checks, the JIT also exerts energy to try to prove when write barriers aren’t needed, eliding them when it can. And it can even more in .NET 10.</strong>&rdquo;</div></blockquote><h4>Miscellaneous</h4><blockquote class="quote quote-block "><div>&ldquo;As with most compilers, the JIT employs common subexpression elimination (CSE) to find identical computations and avoid doing them repeatedly. dotnet/runtime#106637 teaches the JIT how to do so in a more consistent manner by <strong>more fully integrating CSE with its Static Single Assignment (SSA) representation.</strong> This in turn allows for more optimizations to kick in, e.g. some of <strong>the strength reduction done around loop induction variables in .NET 9 wasn’t applying as much as it should have, and now it will.</strong>&rdquo;</div></blockquote><p>I just love how Toub manages to keep up his excitement so deep into this document. He&rsquo;s really a great writer.</p>
<h3>Native AOT</h3><blockquote class="quote quote-block "><div>&ldquo;Native AOT [Ahead Of Time [compilation]] is the ability for a .NET application to be compiled directly to assembly code at build-time. The JIT is still used for code generation, but only at build time; the JIT isn’t part of the shipping app at all, and no code generation is performed at run-time. As such, <strong>most of the optimizations to the JIT already discussed, as well as optimizations throughput the rest of this post, apply to Native AOT equally.</strong>&rdquo;</div></blockquote><h3>VM</h3><blockquote class="quote quote-block "><div>&ldquo;With dotnet/runtime#114462, the runtime now uses a single shared “template” for many of the small executable “stubs” it needs at runtime; <strong>stubs are tiny chunks of machine code that act as jump points, call counters, or patchable trampolines.</strong> Previously, each memory allocation for stubs would regenerate the same instructions over and over. The new approach builds one copy of the stub code in a read-only page and then maps that same physical page into every place it’s needed, while giving each allocation its own writable page for the per-stub data that changes at runtime. <strong>This lets hundreds of virtual stub pages all point to one physical code page, cutting memory use, reducing startup work, and improving instruction cache locality.</strong>&rdquo;</div></blockquote><h3>Threading</h3><blockquote class="quote quote-block "><div><p>&ldquo;If a thread is blocked on an operation that depends on work items in that thread’s local queue getting processed, <strong>that work item being picked off now depends on the global queue being exhausted and another thread coming along and stealing the work item from this thread’s queue.</strong> If there’s a steady stream of incoming work into the global queue, though, that will never happen; essentially, <strong>the highest priority work item has become the lowest priority work item.</strong></p>
<p>&ldquo;So, back to these PRs. The idea is fairly simple: when the thread is about to block, and in particular when it’s about to block waiting on a Task, <strong>it first dumps its entire local queue into the global queue.</strong> That way, this work which was <strong>highest priority for the blocked thread has a fairer chance of being processed by other threads</strong>, rather than it being the lowest priority work for everyone.&rdquo;</p>
</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;dotnet/runtime#107843 from @hamarb123 adds two new methods to the Volatile class: ReadBarrier and WriteBarrier. <strong>A read barrier has “load acquire” semantics, and is sometimes referred to as a “downward fence”</strong>: it prevents instructions from being reordered in such a way that memory accesses below/after the barrier move to above/before it. In contrast, <strong>a write barrier has “store release” semantics, and is sometimes referred to as an “upwards fence”</strong>: it prevents instructions from being reordered in such a way that memory accesses above/before the barrier move to below/after it.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;These barriers are referred to as “half fences”; the read barrier prevents later things from moving earlier, but not the other way around, and the write barrier prevents earlier things from moving later, but not the other way around. (As it happens, though, while not required by specification, today <strong>the implementation of <code>lock</code> does use a full barrier on both enter and exit, so nothing before or after a lock will move into it.</strong>)&rdquo;</div></blockquote><h3>Reflection</h3><blockquote class="quote quote-block "><div>&ldquo;<code>System.Net.Http</code> sits above <code>System.Security.Cryptography</code>, referencing it for critical features like <code>X509Certificate</code>. But <code>System.Security.Cryptography</code> needs to be able to make HTTP requests in order to download OCSP information, and with <code>System.Net.Http</code> referencing <code>System.Security.Cryptography</code>, <strong><code>System.Security.Cryptography</code> can’t in turn explicitly reference <code>System.Net.Http</code>. It can, however, use reflection or <code>[UnsafeAccessor]</code> and <code>[UnsafeAccessorType]</code> to do so, and it does. It used to use reflection, now in .NET 10 it uses <code>[UnsafeAccessor]</code>.</strong>&rdquo;</div></blockquote><h3>Primitives and Numerics</h3><blockquote class="quote quote-block "><div>&ldquo;dotnet/runtime#111505 from @alexcovington enables <code>TensorPrimitives.Divide&lt;T&gt;</code> to be vectorized for int. The operation already supported vectorization for float and double, for which there’s SIMD hardware-accelerated support for division, but it didn’t support int, which lacks SIMD hardware-accelerated support. <strong>This PR teaches the JIT how to emulate SIMD integer division, by converting the ints to doubles, doing double division, and then converting back.</strong>&rdquo;</div></blockquote><p>That fix, roundabout as it sounds, ends up making that operation 4x faster. This is pretty cool because dividing integers in SIMD code just became 4x faster on .NET. You don&rsquo;t use this, you say? Well, are you sure? Are you sure that there is no code in handshake-negotiation (e.g.) that needs to divide multiple integers in parallel? These are exactly the kind of improvements that, as noted in Toub&rsquo;s introduction, lead to smoother operation in many other places. This is such a low-level primitive.</p>
<blockquote class="quote quote-block "><div><p>&ldquo; We can then reuse those methods to do the same thing that’s already done for scalar operations but do it vectorized: take a vector of <code>Halfs</code>, convert them all to <code>floats</code>, process all the <code>floats</code>, and convert them all back to <code>Halfs</code>. Of course, I already stated that the vector types don’t support <code>Half</code>, so <strong>how can we “take a vector of <code>Half</code>“? By reinterpret casting the <code>Span&lt;Half&gt;</code> to <code>Span&lt;short&gt;</code> (or <code>Span&lt;ushort&gt;</code>), which allows us to smuggle the <code>Halfs</code> through.</strong> And, as it turns out, even for scalar, the very first thing <code>Half</code>‘s float cast operator does is convert it to a short.</p>
<p>&ldquo;The net result is that a ton of operations can now be accelerated for <code>Half</code>.&rdquo;</p>
</div></blockquote><p>These optimizations improve performance for processing <code>Half</code> in dozens of operations by 11x.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;with C# 14, it’s possible for a type to not only define a <code>+</code> operator, <strong>it can also define a <code>+=</code> operator.</strong> If a type defines a += operator, it will be used <strong>rather than expanding <code>a += b</code> as shorthand for <code>a = a + b</code>.</strong> And that has performance ramifications.</p>
<p>&ldquo;[…] that means that <strong>such compound operators on the tensor types can just update the target tensor in place rather than allocating a whole new (possibly very large) data structure for each computation.</strong> dotnet/runtime#117997 adds all of these compound operators for the tensor types. (Not only are these using C# 14 user-defined compound operators, they’re doing so <strong>as extension operators</strong>, using the new C# 14 extension types feature. Fun!)&rdquo;</p>
</div></blockquote><h3>Collections</h3><blockquote class="quote quote-block "><div>&ldquo;[…] as noted earlier in the JIT section, the JIT has been gaining super powers around dynamic PGO, escape analysis, and stack allocation. This means that in many situations, <strong>the JIT is now able to see that the most common concrete type for a given call site is a specific enumerator type and generate code specific to when it is that type, devirtualizing the calls, possibly inlining them, and then, if it’s able to do so sufficiently, stack allocating the enumerator.</strong> With the progress that’s been made in .NET 10, this now happens very frequently for <code>arrays</code> and <code>List&lt;T&gt;</code>. While the JIT is able to do this in general regardless of an object’s type, the ubiquity of enumeration makes it all that much more important for <code>IEnumerator&lt;T&gt;</code>, so dotnet/runtime#116978 <strong>marks <code>IEnumerator&lt;T&gt;</code> as an <code>[Intrinsic]</code>, giving the JIT the ability to better reason about it.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;For shorter lists, dynamic PGO will see <code>MoveNextRare</code> invoked a reasonable number of times, and will consider it for inlining. And if all of the calls to the enumerator are inlined, the enumerator instance can avoid escaping the call frame, and can then be stack allocated. But <strong>once the list length grows to a much larger amount, that <code>MoveNextRare</code> method will start to look really cold, will struggle to be inlined, and will then allow the enumerator instance to escape, preventing it from being stack allocated.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div><p>&ldquo;While OSR is awesome, it unfortunately causes some complications here. Once the list gets long enough, <strong>an invocation of the tier 0 (unoptimized) method will transition to the OSR optimized method… but OSR methods don’t contain dynamic PGO instrumentation</strong> (they used to, but it was removed because it led to problems if the instrumented code never got recompiled again and thus suffered regressions due to forever-more running with the instrumentation probes in place). Without the instrumentation, and in particular <strong>without the instrumentation for the tail portion of the method (where the enumerator’s <code>Dispose</code> method is invoked), even though <code>List&lt;T&gt;.Dispose</code> is a nop, the JIT may not be able to do the guarded devirtualization that enables the <code>IEnumerator&lt;T&gt;.Dispose</code> to be devirtualized and inlined.</strong> Meaning, ironically, that the nop <code>Dispose</code> causes escape analysis to see the enumerator instance escape, such that it can’t be stack allocated. Whew.</p>
<p>&ldquo;[…] Specifically for enumerators, this PR <strong>enables dynamic PGO to infer the missing instrumentation based on the earlier probes used with the other enumerator methods</strong>, which then enables it to successfully devirtualize and inline <code>Dispose</code>.&rdquo;</p>
</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Labels A and B form a loop, but that loop can be entered by jumping to either A or to B. If the compiler could prove that this loop were only ever enterable from A or only ever enterable from B, then the loop would be “reducible.” Irreducible loops are much more complex than reducible loops for a compiler to deal with, as they have more complex control and data flow and in general are harder to analyze. dotnet/runtime#116949 <strong>rewrites the <code>MoveNext</code> method to be a more typical while loop, which is not only easier to read and maintain, it’s also reducible and more efficient, and because it’s more streamlined, it’s also inlineable and enables possible stack allocation.</strong>&rdquo;</div></blockquote><p>This results in a 7x performance improvement when iterating a list of integers.</p>
<p>There are also a ton of optimizations in Linq, for <code>Contains</code> (with 10x − 400x improvements), <code>Fill</code> (40x), <code>Shuffle</code> (2x − 40x), <code>LeftJoin</code>, and <code>RightJoin</code> (2x). There are also specific improvements for many of the base collection types.</p>
<h3>IO</h3><p>The next section on IO is also interesting, with one case where they didn&rsquo;t actually change any code but instead introduced an analyzer that discourages using the <code>EndOfStream</code> property in asynchronous code, which can lead to pathological cases in which the stream is blocked until more data arrives.</p>
<h3>Searching / Regular Expressions</h3><p>This section includes a longer discussion about the improvements included in previous versions of .NET, especially as it relates to avoiding backtracking. There are normalized forms of regular expressions that incur no backtracking penalty and can thus be evaluated with the faster version of the regular-expression engine that doesn&rsquo;t have to account for it.</p>
<p>Here&rsquo;s an example that I&rsquo;ve lifted up from much further down in this section.</p>
<blockquote class="quote quote-block "><div>&ldquo;Given the pattern <code>^abc|^abd</code>, the code generators would end up emitting this exactly as it’s written, with an alternation with two branches, the first branch checking for the beginning and then matching <code>&ldquo;abc&rdquo;</code>, the second branch also checking for the beginning and then matching <code>&ldquo;abd&rdquo;</code>. <strong>Now in .NET 10, the anchor can be factored out, such that <code>^abc|^abd</code> ends up being rewritten as <code>^ab[cd]</code>.</strong>&rdquo;</div></blockquote><p>The idea here is to search for pathological formulations for which there is a non-pathological equivalent and automatically use that version under the hood. That is my interpretation of the following rather-dense section.</p>
<blockquote class="quote quote-block "><div>&ldquo;Consider a pattern <code>a*b. a*b</code> is observably identical to <code>(?&gt;a*)b</code>, which says that the <code>a*</code> should not be backtracked into. That’s because there’s nothing the <code>a*</code> can “give back” (which can only be as) that would satisfy what comes next in the pattern (which is only <code>b</code>). It’s thus valid for a backtracking engine to transform how it processes <code>a*b</code> to instead be the equivalent of how it processes <code>(?&gt;a*)b</code>. And the .NET regex engine has been capable of such transformations since .NET 5. This can result in massive improvements to throughput. With backtracking, waving my hands, we effectively need to execute everything after the backtracking construct for each possible position we could backtrack to. So, for example, with <code>\w*SOMEPATTERN</code>, if the <code>w*</code> successfully initially consumes 100 characters, we then possibly need to try to match <code>SOMEPATTERN</code> up to 100 different times, as we may need to backtrack up to 100 times and re-evaluate <code>SOMEPATTERN</code> each time we give back one of the things initially matched. If we instead make that <code>(?&gt;\w*)</code>, we eliminate all but one of those! That <strong>makes improvements to this ability to automatically transform backtracking constructs to be non-backtracking possibly massive improvements in performance, and practically every release of .NET since .NET 5 has increased the set of patterns that are automatically transformed. .NET 10 included.</strong>&rdquo;</div></blockquote><p>There are several detailed examples of 5x–6x improvements in performance for relatively common-looking regular expressions. Stephen Toub <em>loves</em> writing about very-specific regular-expression examples. Like, each paragraph is a blog post just on its own. Needless to say, this section is, at the same time, fascinating, extremely detailed, and eminently uncitable (because it would just entail citing pages of detail that is all necessary to understand the optimization). The improvements are impressive and incredibly well-described. Go check out that section if you like regular expressions and mathematical analysis (equivalence of expressions, reduction of solution space). The additional beauty is that the regular-expression evaluators are all source-generated C#, so it&rsquo;s much, much easier to evaluate what&rsquo;s going on than with the assembly-level discussions in the JIT discussion, for example.</p>
<p>As a final example, here is the level of holistic analysis we&rsquo;re talking about.</p>
<blockquote class="quote quote-block "><div>&ldquo;Unfortunately, the helper that emits that <code>IndexOf</code> call was passed the wrong node from the pattern: it was being passed the object representing the <code>(?:.|\n)</code> any-set rather than the <code>&ldquo;*/&rdquo;</code> literal, which resulted in it emitting the equivalent of <code>IndexOfAnyInRange((char)0, &lsquo;\uFFFF&rsquo;)</code> rather than the equivalent of <code>IndexOf(&ldquo;*/&rdquo;)</code>. Oops. It was still functionally correct, in that the <code>IndexOfAnyInRange</code> call would successfully match the first character and the loop would re-evaluate from that location, but that means that <strong>rather than efficiently skipping using SIMD over a bunch of positions that couldn’t possibly match, we were doing non-trivial work for each and every position along the way.</strong>&rdquo;</div></blockquote><p>As in the IO section above, some of the optimizations come in the form of analyzers that recommend an optimization that the user can apply rather than something that the runtime can do automatically.</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] the .NET 10 SDK includes a new analyzer related to Regex. <strong>It’s oddly common to see code that determines whether an input matches a Regex written like this: Regex.Match(…).Success. While functionally correct, that’s much more expensive than Regex.IsMatch(…).</strong> For all of the engines, Regex.Match(…) requires allocating a new Match object and supporting data structures (except when there isn’t a match found, in which case it’s able to use an empty singleton); in contrast, IsMatch doesn’t need to allocate such an instance because it doesn’t need to return such an instance (<strong>as an implementation detail, it may still use a Match object, but it can reuse one rather than creating a new one each time</strong>).&rdquo;</div></blockquote><h3>MemoryExtensions</h3><blockquote class="quote quote-block "><div>&ldquo;These overloads all parallel existing methods, but <strong>remove the <code>IEquatable&lt;T&gt;</code> (or <code>IComparable&lt;T&gt;</code>) constraint on the generic method parameter and accept an optional <code>IEqualityComparer&lt;T&gt;?</code> (or <code>IComparer&lt;T&gt;</code>).</strong> When no comparer or a default comparer is supplied, they can fall back to using the same vectorized logic for relevant types, and otherwise can provide as optimal an implementation as they can muster, based on the nature of <code>T</code> and the supplied comparer.&rdquo;</div></blockquote><p>This part is very interesting because you see how the improvements to <code>MemoryExtensions</code> led to <code>SearchValues</code> being faster, which, in turn, led to methods like <code>Normalize</code> and <code>Contains</code> being faster (especially when working with <code>strings</code> that are automatically treated as <code>Spans</code> wherever possible).</p>
<h3>JSON</h3><p>A good method to know is <code>RemoveAll()</code>, which accepts a lambda to filter for the elements to remove. If, instead of looping over the items and calling <code>RemoveAt(n)</code>, you write <code>_arr.RemoveAll(static n =&gt; n!.GetValue&lt;int&gt;() % 2 == 0)</code>, you get a huge performance benefit because <code>RemoveAll()</code> adjusts the underlying buffer only once rather than on each call to remove each individual item.</p>
<blockquote class="quote quote-block "><div>&ldquo;With JSON being used as an encoding for many modern protocols, streaming large JSON payloads has become very common. And for most use cases, it’s already possible to stream JSON well with <code>System.Text.Json</code>. However, in previous releases there wasn’t been a good way to stream partial string properties; string properties had to have their values written in one operation. If you’ve got small strings, that’s fine. <strong>If you’ve got really, really large strings, and those strings are lazily-produced in chunks, however, you ideally want the ability to write those chunks of the property as you have them, rather than needing to buffer up the value in its entirety.</strong> dotnet/runtime#101356 augmented Utf8JsonWriter with a <code>WriteStringValueSegment</code> method, which enables such partial writes. […] These modern protocols often transmit large blobs of binary data within the JSON payloads. Typically, these blobs end up being Base64 strings as properties on some JSON object. Today, <strong>outputting such blobs requires Base64-encoding the whole input and then writing the resulting bytes or chars in their entirety into the <code>Utf8JsonWriter</code>. To address that, dotnet/runtime#111041 adds a <code>WriteBase64StringSegment</code> method to <code>Utf8JsonWriter</code>.</strong>&rdquo;</div></blockquote><h3>Cryptography</h3><blockquote class="quote quote-block "><div>&ldquo;A ton of effort went into cryptography in .NET 10, almost entirely focused on post‑quantum cryptography (PQC). <strong>PQC refers to a class of cryptographic algorithms designed to resist attacks from quantum computers, machines that could one day render classic cryptographic algorithms like Rivest–Shamir–Adleman (RSA) or Elliptic Curve Cryptography (ECC) insecure by efficiently solving problems such as integer factorization and discrete logarithms.</strong> With the looming threat of <strong>“harvest now, decrypt later” attacks</strong> (where a well-funded attacker idly captures encrypted internet traffic, expecting that they’ll be able to decrypt and read it later) and the multi-year process required to migrate critical infrastructure, the transition to quantum‑safe cryptographic standards has become an urgent priority. In this light, <strong>.NET 10 adds support for ML-DSA (a National Institute of Standards and Technology PQC digital signature algorithm), Composite ML-DSA (a draft Internet Engineering Task Force specification for creating signatures that combine ML-DSA with a classical crypto algorithm like RSA), SLH-DSA (another NIST PQC signature algorithm), and ML-KEM (a NIST PQC key encapsulation algorithm).</strong>&rdquo;</div></blockquote><h3>Conclusion</h3><p>Overall, this is another amazing document—a <em>book</em>—that is edited to an incredibly high quality. I didn&rsquo;t notice any grammatical, formatting errors, or typos (maybe a missing `?` on <code>IComparer&lt;T&gt;</code> in <span class="quote-inline">&ldquo;These overloads all parallel existing methods, but remove the <code>IEquatable&lt;T&gt;</code> (or <code>IComparable&lt;T&gt;</code>) constraint on the generic method parameter and accept an optional <code>IEqualityComparer&lt;T&gt;?</code> (or <strong class="highlight"><code>IComparer&lt;T&gt;</code></strong>).&rdquo;</span> or when he wrote <span class="quote-inline">&ldquo;frequently-requested&rdquo;</span> (the hyphen is only correct with adjectives, not adverbs).</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5529</guid>
    <title><![CDATA[The idea of MCP: "Tea. Earl grey. Hot."]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5529</link>
    <pubDate>Sat, 31 May 2025 22:36:05 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">31. May 2025 22:36:05 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://raz.sh/blog/2025-05-02_a_critical_look_at_mcp">A Critical Look at MCP</a> by <cite>Rasmus Holm</cite> (<cite><a href="http://raz.sh/">Raz Blog</a></cite>) discussing many of the drawbacks of MCP as it is currently conceived. One of them is the push to build everything in Python, which is a dynamic language that&rsquo;s better-designed than JavaScript, but isn&rsquo;t a lot better at helping users write maintainable code.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;Am I being pretentious/judgmental in thinking that people in AI only really know Python, and the &ldquo;well, it works on my computer&rdquo; approach is still considered acceptable? This should be glaringly obvious to anyone that ever tried to run anything from Hugging Face.</p>
<p>&ldquo;If you want to run MCP locally, wouldn&rsquo;t you prefer a portable language like Rust, Go, or even VM-based options such as Java or C#?&rdquo;</p>
</div></blockquote><p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5529/star_trek_tea_earl_grey_hot.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5529/star_trek_tea_earl_grey_hot_tn.jpg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5529/star_trek_tea_earl_grey_hot.jpg">Captain Jean-Luc Picard</a></span></span>I&rsquo;ve been having discussions with people at work about MCP. This post made me think that I haven&rsquo;t been clear about my attitude toward it. I think it would be amazing if we could pose natural language queries to machines and have them do things for us. Absolutely. Who doesn&rsquo;t want to just order <a href="https://youtu.be/Xx4Tpsk_fnM">&ldquo;Tea. Earl grey. Hot.&rdquo;</a>?</p>
<p>My doubts are more specific to MCP itself, technically, as a protocol. This article is highly technical, but it boils down to: MCP is such a hype-y protocol right now and it&rsquo;s so technically shaky that we have a responsibility to not just grab the first damned thing that shows up and make it the standard.</p>
<p>We did that with JavaScript and it took 2 years until it was everywhere and over 20 years until it was an actual professional tool. I&rsquo;m an old man and, looking back, very often our industry is just stepping on rakes <a href="https://youtu.be/2WZLJpMOxS4">that are <em>right there</em></a>.</p>
<p>I just to clarify that I&rsquo;m pushing back on the <em>implementation</em> not the <em>idea</em>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5535</guid>
    <title><![CDATA[CSS is a collection of layout algorithms]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5535</link>
    <pubDate>Fri, 30 May 2025 16:44:47 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. May 2025 16:44:47 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5535/css.png"><img src="https://www.earthli.com/data/news/attachments/entry/5535/css_tn.png" alt=" " class=" align-right"></a>This is a nice explanation of how CSS is a declarative language, where you describe the metadata of your styles. The <em>layout algorithm</em> determines which property values affect the size and position of the element. Generally the properties <code>position</code> and <code>display</code> properties determine which layout algorithm is used for a given element. The layouts are,</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/o-95kJ0eyzQ" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=o-95kJ0eyzQ">CSS makes sense when you realize it&#039;s a collection of algorithms</a> by <cite>Kevin Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span>	</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Introduction">Normal flow layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected by default)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_inline_layout">Inline layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected by default for inline elements)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible_box_layout">Flexible box layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected with <code>display: flex</code>)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout">Grid layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected with <code>display: grid</code>)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_inline_layout">Inline layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected with <code>display: grid</code>)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout">Multi-column layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected with <code>display: grid</code>)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout">Positioned layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected with <code>display: grid</code>)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Floats">Flow layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected <code>float: left</code> or <code>float: right</code>)</li></ul><p>Most properties work the same in all layouts. Some properties only have an effect in a specific layout mode, e.g., <code>grid-template-columns</code> is ignored if the layout is not <em>grid</em>. Other properties are interpreted differently or completely ignored depending on layout mode, e.g., <code>width</code> and <code>margin</code> are ignored in the <em>inline layout</em>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5518</guid>
    <title><![CDATA[A good explainer of how the core concept of CSS is layout]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5518</link>
    <pubDate>Fri, 23 May 2025 07:37:01 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">23. May 2025 07:37:01 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This is a nice ~13-minute explanation of how CSS is a declarative language, where you describe the metadata of your styles. The <em>layout algorithm</em> determines which property values affect the size and position of the element.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/o-95kJ0eyzQ" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=o-95kJ0eyzQ">CSS makes sense when you realize it&#039;s a collection of algorithms</a> by <cite>Kevin Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span>	</p>
<p>Generally the properties <code>position</code> and <code>display</code> properties determine which layout algorithm is used for a given element. The layouts are,</p>
<p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5518/kevin_powell.jpeg"><img src="https://www.earthli.com/data/news/attachments/entry/5518/kevin_powell_tn.jpeg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5518/kevin_powell.jpeg">Kevin Powell</a></span></span></p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Introduction">Normal flow layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected by default)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_inline_layout">Inline layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected by default for inline elements)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible_box_layout">Flexible box layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected with <code>display: flex</code>)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout">Grid layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected with <code>display: grid</code>)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_inline_layout">Inline layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected with <code>display: grid</code>)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout">Multi-column layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected with <code>display: grid</code>)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout">Positioned layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected with <code>display: grid</code>)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Floats">Flow layout</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (selected <code>float: left</code> or <code>float: right</code>)</li></ul><p>Most properties work the same in all layouts. Some properties only have an effect in a specific layout mode, e.g., <code>grid-template-columns</code> is ignored if the layout is not <em>grid</em>. Other properties are interpreted differently or completely ignored depending on layout mode, e.g., <code>width</code> and <code>margin</code> are ignored in the <em>inline layout</em>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5516</guid>
    <title><![CDATA[Refactoring a dead-simple progress-bar function]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5516</link>
    <pubDate>Mon, 19 May 2025 11:07:51 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">19. May 2025 11:07:51 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. May 2025 08:35:28 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I just saw a neat code example from <a href="https://github.com/MinBZK/woo-besluit-broncode-digid-app/blob/master/Source/DigiD.iOS/Services/NFCService.cs#L182">a Dutch government project</a> (function starting at line 182). The commentator who posted it at <a href="https://old.reddit.com/r/csharp/comments/1kpzcnm/what_is_the_c_idiom_for_assigning_a_value_to/mt2u0s8/">Reddit</a> wrote,</p>
<blockquote class="quote quote-block "><div>&ldquo;Some people laughed at it and suggested all kind of clever one liners to replace it, but to me, that if statement is perfect. The intent is immediately clear and bugs are easy to spot. This is the kind of code you want in critical apps.&rdquo;</div></blockquote><p>Here&rsquo;s the code.</p>
<pre class=" "><code>private static string GetPercentageRounds(double percentage)
{
    if (percentage == 0)
        return "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪";
    if (percentage &gt; 0.0 &amp;&amp; percentage &lt;= 0.1)
        return "🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪";
    if (percentage &gt; 0.1 &amp;&amp; percentage &lt;= 0.2)
        return "🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪";
    if (percentage &gt; 0.2 &amp;&amp; percentage &lt;= 0.3)
        return "🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪";
    if (percentage &gt; 0.3 &amp;&amp; percentage &lt;= 0.4)
        return "🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪";
    if (percentage &gt; 0.4 &amp;&amp; percentage &lt;= 0.5)
        return "🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪";
    if (percentage &gt; 0.5 &amp;&amp; percentage &lt;= 0.6)
        return "🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪";
    if (percentage &gt; 0.6 &amp;&amp; percentage &lt;= 0.7)
        return "🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪";
    if (percentage &gt; 0.7 &amp;&amp; percentage &lt;= 0.8)
        return "🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪";
    if (percentage &gt; 0.8 &amp;&amp; percentage &lt;= 0.9)
        return "🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪";

    return "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵";
}</code></pre><p>This is a cool example because it demonstrates how easy it is to understand the return value when you use a separate constant for each &ldquo;progress bar&rdquo; increment instead of using something like <code>new string('🔵', 5)</code>, which, as we&rsquo;ll see below, doesn&rsquo;t even compile.</p>
<p>Still, all but the &#xfb01;rst condition needlessly checks the lower-bound already guaranteed by the previous step. At the very least, we can reduce it to the following:</p>
<pre class=" "><code>private static string GetPercentageRounds(double percentage)
{
    if (percentage == 0)
        return "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪";
    if (percentage &lt;= 0.1)
        return "🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪";
    if (percentage &lt;= 0.2)
        return "🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪";
    if (percentage &lt;= 0.3)
        return "🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪";
    if (percentage &lt;= 0.4)
        return "🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪";
    if (percentage &lt;= 0.5)
        return "🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪";
    if (percentage &lt;= 0.6)
        return "🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪";
    if (percentage &lt;= 0.7)
        return "🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪";
    if (percentage &lt;= 0.8)
        return "🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪";
    if (percentage &lt;= 0.9)
        return "🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪";

    return "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵";
}</code></pre><p>I would elect to go further, preserving the clarity in constants (or maybe a comment) to avoid repetition in the code.</p>
<p>First, let&rsquo;s write a few tests with NUnit.</p>
<pre class=" "><code>[TestCase(0.00, "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪")]
[TestCase(0.10, "🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪")]
[TestCase(0.11, "🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪")]
[TestCase(0.19, "🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪")]
[TestCase(0.20, "🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪")]
[TestCase(0.30, "🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪")]
[TestCase(0.40, "🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪")]
[TestCase(0.50, "🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪")]
[TestCase(0.60, "🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪")]
[TestCase(0.70, "🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪")]
[TestCase(0.80, "🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪")]
[TestCase(0.90, "🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪")]
[TestCase(1.00, "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵")]
public void TestBubbles(double percentage, string expectedOutput)
{
    var actualOutput = GetPercentageRounds(percentage);

    Assert.That(actualOutput, Is.EqualTo(expectedOutput));
}</code></pre><p>First, let&rsquo;s just re&#xfb02;ect that now it&rsquo;s <em>the tests</em> that document how the API works! That means that now we don&rsquo;t have to lean so hard on the examples being obvious in the code itself. We can optimize the code for maintainability because the test o&#xfb00;ers the high-level explanation. When I refactor this code, I&rsquo;m not removing the in-code documentation—I&rsquo;ve simply <em>moved</em> it to the test.</p>
<p>Next, let&rsquo;s give in to our refactoring instincts and see if a shorter formulation of the algorithm is also understandable. The algorithm is now:</p>
<ol>
<li>Build constant bu&#xfb00;ers for <code>empty</code> and <code>&#xfb01;lled</code>.</li>
<li>Calculate the portion of each of these bu&#xfb00;ers to include in the result (<code>&#xfb01;lledCount</code> and <code>emptyCount</code>).</li>
<li>Copy the correct number of characters from the bu&#xfb00;ers using the C# range-operator.</li></ol><pre class=" "><code>private static string GetPercentageRounds(double percentage)
{
    const string empty = "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪";
    const string filled = "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵";

    var filledCount = (int)Math.Floor(percentage * 10);
    var emptyCount = 10 - filledCount;

    return filled[..filledCount] + empty[..emptyCount];
}</code></pre><p>This doesn&rsquo;t work, though!</p>
<p>The tests fail. For example, the test for <code>0.8</code> returns &ldquo;🔵🔵🔵🔵⚪⚪&rdquo; instead of &ldquo;🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪&rdquo;. What&rsquo;s going on?</p>
<p>We would get another hint as to what is going on if we were to refactor the constant declarations to use each symbol only once. For example, I could create the string with a special constructor, as shown below.</p>
<pre class=" "><code>var empty = new string ('⚪', 10);
var filled = new string ('🔵', 10);</code></pre><p>This avoids repeating the symbol several times but it&rsquo;s probably also not as clear what&rsquo;s happening. It also no longer uses constants—initialized once and stored in the app—so we&rsquo;re allocating new strings each time. We could declare them as <code>static</code> instance variables so that they are allocated only once. However, that would also mean that we don&rsquo;t declare them <em>locally</em> in the method, which again decreases readability.</p>
<p>On top of that, though, the second initialization doesn&rsquo;t even compile!</p>
<p><span style="width: 402px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/5516/compile_error_with_unicode_char.png" alt=" " style="width: 402px"></span><span class="auto-content-caption">🔵 is not a single character</span></span></p>
<p>Strings are encoded in UTF-16 (the standard for .NET). [1] In this encoding, the &ldquo;⚪&rdquo; is represented with one byte, while &ldquo;🔵&rdquo; is represented with <em>two bytes</em>. That knowledge, together with knowing that the range operator works with bytes, explains why we only got <em>half</em> as many &#xfb01;lled-in symbols as expected.</p>
<p>Knowing this, we can revert to the original constants and &#xfb01;x the algorithm as follows (code-change is <strong class="highlight">highlighted</strong>).</p>
<pre class=" "><code>private static string GetPercentageRounds(double percentage)
{
    const string empty = "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪";
    const string filled = "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵";

    var filledCount = (int)Math.Floor(percentage * 10);
    var emptyCount = 10 - filledCount;

    return filled[..(<strong class="highlight">2 *</strong> filledCount)] + empty[..emptyCount];
}</code></pre><p>OK. Now it&rsquo;s working. We now have two questions:</p>
<ol>
<li>Can we avoid the &ldquo;hack&rdquo; for UTF-16 in our calculation?</li>
<li>The code is now more maintainable; is the code still as understandable as before?</li></ol><p>Let&rsquo;s tackle the &#xfb01;rst one. It turns out that there is a standard way of indexing by <em>grapheme</em> but you have to opt in to it by using a <code>StringInfo</code> object, which o&#xfb00;ers a method named <code>SubstringByTextElements()</code>.</p>
<pre class=" "><code>private static string GetPercentageRounds(double percentage)
{
    const string empty = "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪";
    const string filled = "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵";

    var filledCount = (int)Math.Floor(percentage * 10);
    var emptyCount = 10 - filledCount;

    return <strong class="highlight">new StringInfo(filled).SubstringByTextElements(0, filledCount)</strong> + new StringInfo(empty).SubstringByTextElements(0, emptyCount);
}</code></pre><p>Now our code is no longer making assumptions about how many bytes represent our empty and &#xfb01;lled symbols. But is it better? No. It is absolutely less legible than even the previous version. It also allocates two new <code>StringInfo</code> objects ever time it executes.</p>
<p>Is it even necessary? <em>Also no.</em></p>
<p>Why wouldn&rsquo;t it be necessary? In the <em>general</em> case, we have to stay &#xfb02;exible and make sure that we&rsquo;re extracting the correct number of <em>graphemes</em> (not characters), but <em>we don&rsquo;t have a general case here.</em> We have two constant strings in a known encoding. We know that we can index by byte into the <code>empty</code> string and we know that we can index by two bytes into the <code>filled</code> string. These are constants. They will not change. We can <em>make assumptions based on that.</em></p>
<p>That means, after this little excursion, that we&rsquo;ll <em>use our original version</em> but we will also <em>no longer consider it a hack.</em></p>
<p>This takes us to the &#xfb01;nal point: is the new version more legible than the original? I think that it is. At &#xfb01;rst blush, the original looks like it&rsquo;s very self-explanatory—you can <em>see</em> how the progress bar is built—but you also have many more points of logic to check to verify that it&rsquo;s actually working as expected. While you can use the test I&rsquo;ve de&#xfb01;ned above to check all of the logic, there are many more conditions to check when something goes wrong. We measure the number of paths through a piece of logic as <a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity">cyclomatic complexity</a> (<cite><a href="http://en.wikipedia.org/">Wikipedia</a></cite>). The lower the better.</p>
<p>We have learned that, when you program in the original way, you may actually save time! The original formulation didn&rsquo;t have to concern itself with encodings because it wasn&rsquo;t slicing strings. The original programmer didn&rsquo;t even need to be aware that some characters are encoded with multiple bytes whereas others are encoded with a single byte. They didn&rsquo;t even have to know what a byte was at all!</p>
<p>Food for thought.</p>
<p>As almost always, there isn&rsquo;t a &ldquo;best solution&rdquo; for all situations. There is a solution that minimizes drawbacks for the given requirements, but not for <em>all possible requirements</em>. If one of the requirements were: the reader need not know what a byte is, then the original solution would be more appropriate.</p>
<p>The &#xfb01;nal version below has lower cyclomatic complexity, uses constants to indicate what the result will actually look like, and explains its algorithm reasonably well, if you understand percentages. I&rsquo;ve included a comment to explain why we double the number of bytes to select from <code>filled</code>.</p>
<pre class=" "><code>private static string GetPercentageRounds(double percentage)
{
    const string empty = "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪";
    const string filled = "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵";

    var filledCount = (int)Math.Floor(percentage * 10);
    var emptyCount = 10 - filledCount;

    <strong class="highlight">// Each 🔵 is two bytes in UTF-16</strong>
    return filled[..(2 * filledCount)] + empty[..emptyCount];
}</code></pre><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5516_1_body" class="footnote-number">[1]</span> Yes, you can use the <code>u8</code> prefix to make <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-11.0/utf8-string-literals">UTF-8</a> (<cite><a href="http://learn.microsoft.com/">Microsoft Learn</a></cite>), but that doesn't help because the symbols we want to use are multi-byte graphemes in that encoding as well.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5514</guid>
    <title><![CDATA[An LLM use case with function-calling]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5514</link>
    <pubDate>Sun, 18 May 2025 21:58:25 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. May 2025 21:58:25 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://martinfowler.com/articles/function-call-LLM.html">Function calling using LLMs</a> by <cite>Kiran Prakash</cite> writes,</p>
<blockquote class="quote quote-block "><div>&ldquo;It’s important to emphasize that when using function calling, <strong>the LLM itself does not execute the function. Instead, it identifies the appropriate function, gathers all required parameters, and provides the information in a structured JSON format.</strong> This JSON output can then be easily deserialized into a function call in Python (or any other programming language) and executed within the program’s runtime environment.&rdquo;</div></blockquote><p>This is an approach that works very well when you don&rsquo;t have a testing environment: build a plan, evaluate validity of the plan, and then apply the plan after verification. You should also be able to slice the work into sub-tasks to make verification more reliable. This is the approach I took for a PowerShell script that runs against an ADOS instance: it&rsquo;s production data, so you really want to be sure what is going to be executed.</p>
<p>In the implementation, you can see how the code he writes prepares the query to the LLM in a structured way with the required context in an attempt to guide the result. Happily, he <em>begins</em> by writing unit tests!</p>
<p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5514/function_calling.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5514/function_calling_tn.webp" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5514/function_calling.webp">Function-calling with an LLM</a></span></span>This is another good step-by-step example of working with an LLM, but for a different task: it&rsquo;s using an LLM as an interpreter for the user&rsquo;s input. It&rsquo;s basically a way of adding a natural-language &ldquo;search-like&rdquo; interface to an app without forcing the user to structure their input, without developing an UI, and without writing a parser. The advantage is that you get a way of querying a potentially large API surface in a way that in more amenable to more users.</p>
<p>I think of an example from Markus Schenkel from Cudos, who talked about using an MCP plugin for working with a CAD/CAM program—apps that notoriously have dozens of toolbars and thousands of functions. He could formulate his &ldquo;novice&rdquo; request as text, and the LLM, together with the mapping to tool functionality, made relatively good guesses about what he was trying to do. It often took a few attempts—but he was able to accomplish his task, whereas he would have either given up or had to invest a lot more time to get it done otherwise.</p>
<p>I think this is great for products that are in proof-of-concept stage, so that you don&rsquo;t iterate on UIs too early in the design process. But we also have to be aware that we have UIs for a <em>reason</em>. Once there&rsquo;s a well-established set of use cases and functionality, then it&rsquo;s unclear that making users continue to use a command-line interface where they compose text is better than a GUI.</p>
<p>At any rate, the article is filled with detail and code (in Python) for using an LLM in the way described above. There&rsquo;s a section on refactoring at the end, a comparison to the rules-engine-based approach that this technique seeks to replace, and also a comparison of function-calling with MCP.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5511</guid>
    <title><![CDATA[A subtle failure to pattern-match null in C#]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5511</link>
    <pubDate>Sun, 18 May 2025 13:58:53 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. May 2025 13:58:53 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5511/csharp-icon-clr.png"><img src="https://www.earthli.com/data/news/attachments/entry/5511/csharp-icon-clr_tn.png" alt=" " class=" align-right"></a>The article <a href="https://ayende.com/blog/202403-B/the-null-check-that-didnt-check-for-nulls">The null check that didn&rsquo;t check for nulls</a> by <cite>Oren Eini</cite> (<cite><a href="http://ayende.com/">Ayende</a></cite>) points out an interesting and subtle difference in code-generation, depending on whether you use the <code>var</code> keyword. Using <code>var</code> in pattern-matching might lead to a pattern that <em>looks</em> like it checks for <code>null</code> but <em>doesn&rsquo;t</em>. You can see and play with a <a href="https://sharplab.io/#v2:D4AQDABCCMAsDcBYAUCmkAqBTAzgF2gAoAZAS3wB50A+CfAJxwEoUBvFCTiUgM0IZzdBAbQBuAQ3p0Aui2RcI7eQq4gA7HSTLOAXw6qN6AHQApAPakAdoQBEAGnt08jJlr2oP6CNnwAmEuR4VNBgtAJySgq8/M6C5BDCXjiy+pyRKpzqmqkQ7gpZxuZWtg52Ti5uKFWeId64eADMAZQ05cxsOdECQgmsOjJyCukZWThaCnkGUCGmFtb2juFuQA==">live example</a> (<cite><a href="http://sharplab.io/">SharpLab.IO</a></cite>) but I&rsquo;ve replicated the examples below.</p>
<p>This is the problematic example:</p>
<pre class=" "><code>string Test1(List&lt;string&gt; strs)
{
    if(strs is [var s])
    {
        return s;
    }
    return string.Join(",", strs);
}</code></pre><p>It&rsquo;s basically saying that the pattern should match anything that&rsquo;s a collection with one element. Since the type is obvious from the method signature&rsquo;s parameter <code>strs</code>, we use <code>var</code> instead of <code>string</code>. That generates the following code.</p>
<pre class=" "><code>internal static string &lt;Main&gt;$&gt;g__Test1|0_0(List&lt;string&gt; strs)
{
    if (strs != null &amp;&amp; strs.Count == 1)
    {
        return strs[0];
    }
    return string.Join(",", strs);
}</code></pre><p>Note that it returns the first element <em>without checking it for <code>null</code></em>.</p>
<p>If you change the <code>var</code> to <code>string</code>, which, as noted above, is redundant, then the generated code includes a null-check.</p>
<pre class=" "><code>string Test2(List&lt;string&gt; strs)
{
    if(strs is [string s])
    {
        return s;
    }
    return string.Join(",", strs);
}</code></pre><p>This is the generated code for the example above.</p>
<pre class=" "><code>internal static string &lt;Main&gt;$&gt;g__Test2|0_1(List&lt;string&gt; strs)
{
    if (strs != null &amp;&amp; strs.Count == 1)
    {
        string text = strs[0];
        if (text != null)
        {
            return text;
        }
    }
    return string.Join(",", strs);
}</code></pre><p>If you instead use <code>{ }</code> to indicate that you want to match a non-null object, then you also get the null-check.</p>
<pre class=" "><code>string Test3(List&lt;string&gt; strs)
{
    if(strs is [{} s])
    {
        return s;
    }
    return string.Join(",", strs);
}</code></pre><p>This is the generated code for the example above. It is the same as the second example that uses <code>string</code> for the matched parameter.</p>
<pre class=" "><code>internal static string &lt;Main&gt;$&gt;g__Test3|0_2(List&lt;string&gt; strs)
{
    if (strs != null &amp;&amp; strs.Count == 1)
    {
        string text = strs[0];
        if (text != null)
        {
            return text;
        }
    }
    return string.Join(",", strs);
}</code></pre>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5509</guid>
    <title><![CDATA[Zed shows off how to work with AI agents]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5509</link>
    <pubDate>Sun, 18 May 2025 13:53:10 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. May 2025 13:53:10 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://zed.dev/blog/fastest-ai-code-editor">Zed: The Fastest AI Code Editor</a> by <cite>Richard Feldman</cite> (<cite><a href="http://zed.dev/">Zed</a></cite>) includes a great description and video that shows off the behavior of their new &ldquo;agent&rdquo; feature.</p>
<blockquote class="quote quote-block "><div>&ldquo;The entire Zed code editor is open source under GPL version 3, and scratch-built in Rust all the way down to handcrafted GPU shaders and OS graphics API calls. <strong>Zed&rsquo;s new AI capabilities are also open-source</strong>, just like the rest of the editor, so you can see exactly what the new Agent Panel is doing under the hood.&rdquo;</div></blockquote><p>This editor is very, very smooth and more powerful than a standard Visual Studio Code. It&rsquo;s also so much faster. However … it&rsquo;s currently MacOS and Linux-only. The <a href="https://zed.dev/windows">Windows version is in an early-access phase</a>.</p>
<p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5509/_agent_finished_notification.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5509/_agent_finished_notification_tn.webp" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5509/_agent_finished_notification.webp">&#039;Agent finished&#039; notification</a></span></span>Even if you can&rsquo;t use the editor, the ~5-minute video at the beginning of the post is absolutely what I&rsquo;ve been looking for: how do you use these tools <em>for real</em>. The video demonstrates the following:</p>
<ul>
<li>Using the inline-completion to make small edits</li>
<li>Using the chat-AI agent (the tool has access to many actions in the editor).
<li><div>Running a larger request/action against a large code base (they use the code of Zed itself, written in Rust).<ul>
<li>The request is to make the number of most recently used values in a list configurable via settings.</li>
<li>The settings object already exists.</li>
<li>The list already exists.</li>
<li>It&rsquo;s hard-coded to six elements right now.</li></ul></div></li>
<li>Viewing the steps taken in running the request.</li><li><div class=" "><p>Reviewing and adjusting the proposed changes.</p>
<blockquote class="quote quote-block "><div>&ldquo;The diff is fully editable, so you can easily make changes to whatever the model came up with. It supports multicursor editing, language server integrations, and all the speed you love from the rest of Zed.&rdquo;</div></blockquote></div></li>
<li>Noting that one of the proposed changes is something that even a senior developer might have forgotten to do in a first attempt at the feature (updating settings</li>
<li>Final review in a Git diff.</li></ul><p>This is hands-down the best demonstration I&rsquo;ve seen of extending a workflow comprising what the author nicely describes as <em>deterministic</em> tools—I&rsquo;ve been calling them <em>analysis-based</em> tools—with AI-based tools (and agents). The section on <a href="https://zed.dev/blog/fastest-ai-code-editor#what-does-it-cost">costs</a> is remarkably fair and open.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5065</guid>
    <title><![CDATA[How pattern-matching in C# is lowered]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5065</link>
    <pubDate>Sun, 27 Apr 2025 11:53:33 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">27. Apr 2025 11:53:33 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5065/pattern-matching-in-c-sharp.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5065/pattern-matching-in-c-sharp_tn.webp" alt=" " class=" align-right"></a>A while back, I wrote <a href="https://www.earthli.com/news/view_article.php?id=4657">Stop trying so hard to use pattern-matching</a>. I stand by everything i wrote there. I was recently mentoring a very clever programmer who&rsquo;s new to C# but has cut his teeth on Rust. We were discussing <code>switch</code> <em>statements</em> vs. <code>switch</code> <em>expressions</em>. Which pattern-matching features can you use where? Which features can you combine?</p>
<p>The article <a href="https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/pattern-matching">Tutorial: Use pattern matching to build type-driven and data-driven algorithms</a> (<cite><a href="http://learn.microsoft.com/">Learn Microsoft</a></cite>) offers a good introduction. Pattern-matching on objects is lovely (and its been available since <a href="https://devblogs.microsoft.com/dotnet/whats-new-in-csharp-7-0/">C# 7.0</a> [1] (2017)). The version they were using still used &ldquo;switch statements&rdquo;. There&rsquo;s another level called &ldquo;switch expressions&rdquo; (available since <a href="https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/">C# 9</a> (2020)) that they could have used if they were returning a value. The article <a href="https://www.thomasclaudiushuber.com/2021/02/25/c-9-0-pattern-matching-in-switch-expressions/">C# 9.0: Pattern Matching in Switch Expressions</a> by <cite>Thomas Claudius Huber</cite> provides the following example,</p>
<pre class=" "><code>string favoriteTask = obj switch
{
  Developer dev when dev.YearOfBirth == 1980 =&gt; $"{dev.FirstName} listens to metal",
  Developer dev =&gt; $"{dev.FirstName} writes code",
  Manager _ =&gt; "Create meetings",
  _ =&gt; "Do what objects do",
};</code></pre><p>Speaking of syntactic sugar, you can check out what the compiler would generate using the <a href="https://sharplab.io">SharpLab.IO</a>. Throw in any compiling code on the left, and you get the &ldquo;lowered&rdquo; version on the right.</p>
<p>If you throw in the example from above with a bit of extra code to make it compile,</p>
<pre class=" "><code>using System;

public class C
{
  public void M(object obj)
  {
    string favoriteTask = obj switch
    {
      Developer { YearOfBirth: &gt;= 1980 and &lt;= 1989 and not 1984 } dev
        =&gt; $"{dev.FirstName} listens to heavy metal while coding",
      Developer dev =&gt; $"{dev.FirstName} writes code",
      Manager _ =&gt; "Create meetings",
      _ =&gt; "Do what objects do",
    };

  }

  private class Developer
  {
    public int YearOfBirth { get; }
    public string FirstName { get; } = string.Empty;
  }

  private class Manager { }
}</code></pre><p>You can see that the generated logic is quite straightforward. The snippet below elides the generated code for the <code>Developer</code> and <code>Manager</code> classes. It&rsquo;s not how I would have written it manually, but I bet it&rsquo;s pretty efficient.</p>
<pre class=" "><code>[NullableContext(1)]
public void M(object obj)
{
    Developer developer = obj as Developer;
    string text;
    if (developer == null)
    {
        text = ((!(obj is Manager)) ? "Do what objects do" : "Create meetings");
    }
    else
    {
        int yearOfBirth = developer.YearOfBirth;
        if (yearOfBirth &gt;= 1980 &amp;&amp; yearOfBirth &lt;= 1989 &amp;&amp; yearOfBirth != 1984)
        {
            Developer developer2 = developer;
            text = string.Concat(developer2.FirstName, " listens to heavy metal while coding");
        }
        else
        {
            text = string.Concat(developer.FirstName, " writes code");
        }
    }
    string text2 = text;
}</code></pre><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5065_1_body" class="footnote-number">[1]</span> We&rsquo;re on <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-13">C# 13</a> in April 2025, with <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14">C# 14</a> in the works for November, 2025.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5050</guid>
    <title><![CDATA[Angular is pretty specialized]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5050</link>
    <pubDate>Mon, 21 Apr 2025 11:25:50 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Apr 2025 11:25:50 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5050/angular.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5050/angular_tn.webp" alt=" " class=" align-right"></a>I recently had a conversation about the pros and cons of using Angular and I found this year-old article that I&rsquo;d prepared from my notes but never published. The article <br>
<a href="https://software-engineering-corner.zuehlke.com/two-way-binding-between-signals-and-query-params">Two-way binding between Signals and Query Params</a> by <cite>Julio Castro</cite> (<cite><a href="http://software-engineering-corner.zuehlke.com/">Software Engineering Corner by Z&uuml;hlke Engineers</a></cite>) includes the following code snippet.</p>
<blockquote class="quote quote-block "><div><pre class=" "><code>@Component({
  selector: "app-root",
  standalone: true,
  imports: [AsyncPipe],
  template: `
    &lt;h1&gt;Signals Demo&lt;/h1&gt;
    &lt;p&gt;Your first name is: {{ firstName$ | async }}&lt;/p&gt;
  `,
})
export class AppComponent {
  private activatedRoute = inject(ActivatedRoute);

  firstName$ = this.activatedRoute.queryParams.pipe(
    map((allQueryParams) =&gt; allQueryParams["firstName"])
  );
}</code></pre></div></blockquote><p>I cannot describe how gross I think Angular code is. <em>None</em> of this is &ldquo;using the platform&rdquo;. This is all JavaScript-first. It&rsquo;s all custom, untyped, string-matching, gobbledygook. The <code>firstName$</code> in the template isn&rsquo;t checked. There are no type-safe views. [1] What the hell does <code>| async</code> do? I&rsquo;m sure it&rsquo;s convenient, but this is more obtuse-looking than modern React.</p>
<p>The injection is also just magic that you have to know about. And why is it injected differently than the <code>AsyncPipe</code>? There are probably good reasons for it, <em>in Angular</em>, but it looks pretty slapdash and ad=hoc as an API. It&rsquo;s like there&rsquo;s a different symbol or character or concept for every possible thing. The <code>imports</code> is in a custom place. It&rsquo;s all packed into a <code>@Component</code> decorator that does a bunch of magic for you to build what is probably a web component (but I&rsquo;m not sure). They wrapped every single possible API in something custom to Angular.</p>
<p>I hope I&rsquo;m wrong, but this is so unappealing.</p>
<p>Reading a bit further and we see an example where some of the noise—e.g., the <code>async</code> pipe—has been removed <em>because of the magic of <strong>signals</strong></em>.</p>
<p>If you&rsquo;re learning Angular, you&rsquo;re not learning anything portable about web-programming. You won&rsquo;t know HTML, you won&rsquo;t know CSS, you won&rsquo;t even necessarily know JavaScript or the browser APIs. You don&rsquo;t use the platform. It&rsquo;s a shame because the platform is already so powerful. In the old days, you needed a framework to shield you from the differences. Nowadays, the platform is more than well-specified, -supported, and -implemented to just write to directly. Learning the platform API is just as easy as learning whatever I&rsquo;m seeing in Angular.</p>
<p>In fairness to the article, though, it&rsquo;s well-written and offers some good techniques for making the best of a bad situation if you have to work in Angular. 🙃</p>
<p>But then there&rsquo;s this.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;Since we are accessing the value of the <code>allQueryParams</code> signal in the effect, it will run every time this signal gets updated, which happens every time Angular emits a new value in the <code>activatedRoute.queryParams</code> observable.</p>
<p>&ldquo;Inside the effect, we are just updating the value of our <code>queryParamValue</code> signal. For that, notice that we need to pass the <code>allowSignalWrites: true</code> option. This is necessary because updating signals in effects could lead to infinite loops and unexpected and intricate situations in general.&rdquo;</p>
</div></blockquote><p>This is the same kind of black magic for real-life situations as you see in React these days. I&rsquo;m still a fan of using MobX for the state model, then attaching it to pure reactive web components. I&rsquo;m still deciding whether that will scale to what I need, but I&rsquo;m more and more convinced that none of the huge frameworks are the way to go. They&rsquo;re just so much wrapping and bizarre APIs that feel legacy before they&rsquo;re even officially released.</p>
<p>I&rsquo;m not going to copy it in here but the final version of the read/write signal service based on query-parameter values is 41 lines of hairball code. Do I know how much code it would be to achieve something similar outside of Angular? No. No, I don&rsquo;t. I just know that if I ended up having to learn how to do it and write it—and even if it ended up being more code—I would have learned the general platform and built a service that can work in any web site, not just one framework.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5050_1_body" class="footnote-number">[1]</span> A colleague confirmed for me just last week that this is still the case, even in the latest versions of Angular.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5076</guid>
    <title><![CDATA[Balancing user experience and performance in a web page]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5076</link>
    <pubDate>Mon, 21 Apr 2025 11:17:49 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Apr 2025 11:17:49 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5076/optimize_loading_speed.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5076/optimize_loading_speed_tn.webp" alt=" " class=" align-right"></a>This video is just under 30 minutes and provides a lot of useful tips about how to optimize web pages. It&rsquo;s almost a year old, but a lot of the optimizations are good to know, even though they won&rsquo;t apply to most pages out there. It&rsquo;s good to know how the browser works and which heuristics it uses to determine what can be optimized. Knowing these things helps you avoid accidentally formulating your web pages in ways that slow things down unnecessarily. You&rsquo;ll be less likely to suffer under load.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/cmtfM4emG5k" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=cmtfM4emG5k">Optimizing INP: A deep dive</a> by <cite>Chrome for Developers</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The author goes through several optimizations.</p>
<ul>
<li>He starts by showing how to turn on the &ldquo;mid-tier mobile&rdquo; testing mode, which uses fast 3G and slows the CPU down 4x. This makes it easier to spot problems on a developer-class desktop/laptop.</li>
<li>He then shows how to set up and use the profiler, zooming in and out of the extremely rich data recorded for every interaction.</li>
<li>He discovers and removes a polyfill that&rsquo;s no longer needed. It turns out that that version of polyfill was broken and always active—regardless of whether the feature was supported natively.</li>
<li>Another fix was to remove the background blur when making an element <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert"><code>inert</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) because it was engaging the GPU and causing a much longer paint when the browser had to animate the drop-shadow moving across the blurred element.</li>
<li>Another fix involved simply moving an interaction away from the initial event handler by executing it in a timer instead. He used a dead-simple debouncing technique to ensure that only the most recent task would be executed.</li>
<li>Another fix was to remove complex logic for avoiding setting the <code>display</code> property on a DOM element. The solution there is to simply let the browser do its thing; it&rsquo;s much more optimized than you think. The code that was trying to avoid touching the DOM was much slower than actually setting a DOM property.</li>
<li>Another fix was to defer and chunk appending results as well as setting styling for found terms by using <code>async</code>.</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5098</guid>
    <title><![CDATA[Swift protocol extensions for C#]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5098</link>
    <pubDate>Mon, 21 Apr 2025 11:06:20 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Apr 2025 11:06:20 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5098/extension_syntax_in_c_14.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5098/extension_syntax_in_c_14_tn.webp" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5098/extension_syntax_in_c_14.webp">Extension syntax in C#14</a></span></span>Since this feature is being touted for C# 14—this time it&rsquo;s coming for real!—I thought it would be good to refresh what I&rsquo;d already learned about it. The title is a bit hyperbolic but it&rsquo;s quite an interesting feature. It&rsquo;s basically <code>protocol extension</code> from Swift for C#. It&rsquo;s .NET&rsquo;s answer to extending extension methods to properties and, probably,  operators. You can&rsquo;t add state, as far as I can tell. But that isn&rsquo;t so surprising.</p>
<p>The video below discuss the proposal as it looked for C#13. The pages <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14#extension-members">What&rsquo;s new in C# 14: Extension members</a> and <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/extension">Extension declaration (C# Reference)</a> offer more insight into the current shape of the feature. It seems like they mean it this time and that it will land in November 2025.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/ueO5Cb3Emcw" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=ueO5Cb3Emcw">The Insane C# 13 Feature That Changes Everything</a> by <cite>Nick Chapsas</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>What it primarily is, though, is further work on making it easier to transition APIs. We got the first batch of support with default interface implementations. This feature will allow to smooth migrations even more. They will also allow us to &ldquo;add&rdquo; properties to types that then introduce their own version of those properties in future versions but that&rsquo;s OK, I think. It means that every added property will be a potential breaking change for someone but maybe it will make us start categorizing breaking changes.</p>
<p>There are <code>implicit</code> extensions, which are pretty much a new way of defining extension methods, but with support for proprties. The following example shows how the property <code>IsLead</code> will be available for any <code>Person</code> without modifying that type. This doesn&rsquo;t seem much different than existing extension methods, other than support for properties, where the <code>this</code> keyword stands in for the parameter that would otherwise have been passed in a classic extension method.</p>
<pre class=" "><code>public implicit extension PersonExtension for Person
{
    public bool IsLead
        =&gt; this.Organization
            .Teams
            .Any(team =&gt; team.Lead == this);
}</code></pre><p>There are also <code>explicit</code> extensions, which are a way of specifying extensions to types that are neither implemented nor inherited, but are instead given to a type without coercion. That is, you can define a type that can be applied to another type (e.g., <code>Lead</code> for <code>Person</code> in the example below), which makes more methods and properties available. It&rsquo;s kind of confusing without an example.</p>
<pre class=" "><code>public explicit extension Lead for Person
{
    public IEnumerable&lt;Team&gt; Teams 
        =&gt; this.Organization
            .Teams
            .Where(team =&gt; team.Lead == this);
}

var person = new Person();
var personTeams = person.Teams; // <span class="error">Compile error</span>
Lead lead = person;
var leadTeams = lead.Teams; // <strong class="highlight">OK</strong></code></pre><p>While this might look like a cast, it&rsquo;s not, because <code>Person</code> doesn&rsquo;t implement <code>Lead</code>—it&rsquo;s <em>extended</em> by <code>Lead</code> in code that isn&rsquo;t necessarily associated with the code that defines <code>Person</code>.</p>
<p>In the latest syntax, the example above would look a bit different but the idea is the same. It looks like they&rsquo;ve simplified it a bit.</p>
<pre class=" "><code>public static class PersonExtension
{
    extension(Person source)
    {
        public bool IsLead
        =&gt; source.Organization
            .Teams
            .Any(team =&gt; team.Lead == this);;
    }
}</code></pre><ul>
<li>There a talk called <a href="https://build.microsoft.com/en-US/sessions/689e5104-72e9-4d02-bb52-77676d1ec5bc?source=sessions">What’s new in C# 13</a> by <cite>Mads Torgersen and Dustin Campbell</cite> (<cite><a href="http://build.microsoft.com/">Microsoft Build</a></cite>) for which you have to register. The video will probably come out later on YouTube, though.</li>
<li>There&rsquo;s the original <a href="https://github.com/dotnet/csharplang/issues/5497">[Proposal]: Extensions #5497</a> (<cite><a href="http://github.com/">GitHub</a></cite>)</li>
<li>The most informative link (so far) is <a href="https://devblogs.microsoft.com/dotnet/dotnet-build-2024-announcements/#c-13:%7E:text=best%20concrete%20type.-,Extension%20types,-Extension%20types%20aren%E2%80%99t#extension-types">.NET Announcements and Updates from Microsoft Build 2024</a> by <cite>.NET Team</cite> (<cite><a href="http://devblogs.microsoft.com/">Microsoft Dev Blogs</a></cite>)</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5118</guid>
    <title><![CDATA[A good intro to .NET Aspire from the 2024 Build Conference]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5118</link>
    <pubDate>Mon, 21 Apr 2025 10:54:46 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Apr 2025 10:54:46 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This is another 46-minute, 10-month-old video from the last Build conference that I found extremely helpful in explaining what .NET Aspire is and what it&rsquo;s good for.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/jVILDZtuUrI" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=jVILDZtuUrI">Demystify cloud-native development with .NET Aspire | BRK181</a> by <cite>Microsoft Developer</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Damian Edwards and David Fowler do a soup-to-nuts demonstration of Aspire. It basically lets you configure your multi-project, distributed projects with code rather than with YAML (e.g. <code>dockercompose.yml</code>). Instead, it writes the files for you and handles the deployment to Docker. This lets you much more easily create and configure things like email servers (for registration workflows), queues, databases, etc. Some of the resources run in Docker containers, some run on Azure if you want. There is a dashboard with deep telemetry, with very nice graphs showing how each service participates in a given request.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5115</guid>
    <title><![CDATA[Toub and Hanselmann at the Build Conference 2024]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5115</link>
    <pubDate>Mon, 21 Apr 2025 10:46:39 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Apr 2025 10:46:39 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This 46-minute presentation by Scott Hanselman and Stephen Toub is ten months old but is still worth watching. I note below that one of the more significant things Toub shows is not any sort of programming wizardry, but <em>column-selection in a text editor</em>. Half of the things that people use AI for can be solved with column-select and judicious copy/paste.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/TRFfTdzpk-M" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=TRFfTdzpk-M">&#039;Highly Technical Talk&#039; with Hanselman and Toub | BRK194</a> by <cite>Microsoft Developer</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Another fantastic &ldquo;deep dive&rdquo; with these two: this time they&rsquo;re optimizing the Humanizer library on-the-fly, on-stage, during a session. This feels nearly completely improvised. Kudos to these two gen-Xers, doing an old-school presentation of just plain programming bravura with no frills.</p>
<p>At <strong>38:20</strong>, Toub shows how to use column-select to make changes, which wows the audience. I guess it&rsquo;s really not such a well-known feature, but it&rsquo;s an incredible productivity booster. Toub uses the mouse to select when he could have just used the keyboard to select the lines with <kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>down</kbd> or by selecting the space and starting double-quote, then <kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>.</kbd> to select subsequent matches. After that, he used the mouse again to select the end of the lines, but he could have just left the lines selected from before and hit <kbd>End</kbd> to jump to the end of all the lines. It&rsquo;s good that he showed it but, as in previous videos, he&rsquo;s a bit more of a &ldquo;mouser&rdquo; than I am.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5489</guid>
    <title><![CDATA[Getting Docker in the path on MacOS]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5489</link>
    <pubDate>Mon, 21 Apr 2025 08:15:12 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Apr 2025 08:15:12 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I couldn&rsquo;t call Docker from the command line. I had installed Docker a long time ago, but had just restored from a <em>Time Machine</em> backup, so my system was new but the applications had been restored. That meant that Docker <em>had recorded</em> that the executables had been sym-linked to the right folder (<code>/usr/local/bin</code>) but those links were part of the old, dead system.</p>
<p>Long story short, go to the settings, as shown below. If you&rsquo;re in the situation that I was in, in which the app was out of sync with the system, then you&rsquo;ll have to change something to get the app to apply the settings again.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5489/docker_settings.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5489/docker_settings.webp" alt=" " style="width: 560px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5489/docker_settings.webp">Docker Settings</a></span></span></p>
<p>You can try to simply switch from <code>User</code> to <code>System</code>, click <code>Apply &amp; Restart</code> but that didn&rsquo;t work for me. It never asked for my password or confirmation. However, I found the instructions in this answer to <a href="https://stackoverflow.com/a/78834693">docker-compose command not available for mac</a> (<cite><a href="http://stackoverflow.com/">StackOverflow</a></cite>), which gave the tip to change other things on the page to force Docker to make the update.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;I fixed it by going to <code>Docker app -&gt; settings -&gt; Advanced</code></p>
<p>&ldquo;In advanced I had to check off:&rdquo;</p>
<ul>
<li><code>Allow the default Docker socket to be used (requires password)</code></li>
<li><code>Allow privileged port mapping (requires password)</code></li></ul><p>&ldquo;Click <code>Apply &amp; Restart</code></p>
<p>&ldquo;And enable again options:&rdquo;</p>
<ul>
<li><code>Allow the default Docker socket to be used (requires password)</code></li>
<li><code>Allow privileged port mapping (requires password)</code></li></ul>&ldquo;Click <code>Apply &amp; Restart</code>&rdquo;</div></blockquote><p>If that <em>still</em> doesn&rsquo;t work, then check whether you actually have a <code>/usr/local/bin</code> folder. Docker fails silently when the folder doesn&rsquo;t exist. If you don&rsquo;t have it, use an administrator and <code>sudo</code> to create the folder and try the procedure above again.</p>
<p>That did the trick for me.</p>
<p>If you&rsquo;d like to link the tools to your user&rsquo;s path (<code>$HOME/.docker/bin</code>) instead, then follow the instructions in this answer to <a href="https://stackoverflow.com/a/78834693">Setting PATH environment variable in OSX permanently</a> (<cite><a href="http://stackoverflow.com/">StackOverflow</a></cite>) that show you how to modify the paths for your system.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5189</guid>
    <title><![CDATA[Toub's 234-page tour-de-force on performance in .NET 9]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5189</link>
    <pubDate>Sun, 20 Apr 2025 23:03:54 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Apr 2025 23:03:54 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5189/stephen_toub.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5189/stephen_toub_tn.jpg" alt=" " class=" align-right"></a>The <s>article</s>book <a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-9/">Performance Improvements in .NET 9</a> by <cite>Stephen Toub</cite> (<cite><a href="http://devblogs.microsoft.com/">.NET Blog</a></cite>) was published about six months ago. It contains a tremendous amount of interesting information, which I&rsquo;ve attempted to summarize below, following the document structure in the original.</p>
<h3>Tier 0</h3><blockquote class="quote quote-block "><div>&ldquo;Another tier 0 boxing example is dotnet/runtime#90496. There’s a hot path method in the async/await machinery: <code>AsyncTaskMethodBuilder&lt;TResult&gt;.AwaitUnsafeOnCompleted</code> (see <a href="https://devblogs.microsoft.com/dotnet/how-async-await-really-works/">How Async/Await Really Works in C#</a> for all the details). It’s really important that this method be optimized well, but it performs various type tests that can end up boxing in tier 0. In a previous release, that boxing was deemed too impactful to startup for async methods invoked early in an application’s lifetime, so <code>[MethodImpl(MethodImplOptions.AggressiveOptimization)]</code> was used to opt the method out of tiering, such that it gets optimized from the get-go. But that itself has downsides, because if it skips tiering up, it also skips dynamic PGO, and thus the optimized code isn’t as good as it possibly could be. So, <strong>this PR specifically addresses those type tests patterns that box, removing the boxing in tier 0, enabling removing that <code>AggressiveOptimization</code> from <code>AwaitUnsafeOnCompleted</code>, and thereby enabling better optimized code generation for it.</strong>&rdquo;</div></blockquote><h3>Loops</h3><blockquote class="quote quote-block "><div>&ldquo;In .NET 8, as part of the work to improve dynamic PGO, a more powerful graph-based loop analyzer was added that was able to recognize many more loops. For .NET 9 with dotnet/runtime#95251, <strong>that analyzer was factored out so that it could be used for generalized loop reasoning.</strong> And then with PRs like dotnet/runtime#96756 for loop alignment, dotnet/runtime#96754 and dotnet/runtime#96553 for loop cloning, dotnet/runtime#96752 for loop unrolling, dotnet/runtime#96751 for loop canonicalization, and dotnet/runtime#96753 for loop hoisting, <strong>many of these loop-related optimizations have now been moved to the better scheme.</strong> All of that means that more loops get optimized.&rdquo;</div></blockquote><h3>ARM SVE</h3><blockquote class="quote quote-block "><div>&ldquo;There are multiple ways such an ISA impacts .NET, and in particular the JIT. The JIT needs to be able to be able to work with the ISA, understand the associated registers and be able to do register allocation, be taught about encoding and emitting the instructions, and so on. <strong>The JIT needs to be taught when and where it’s appropriate to use these instructions, so that as part of compiling IL down to assembly, if operating on a machine that supports SVE, the JIT might be able to pick SVE instructions for use in the generated assembly.</strong> And the JIT needs to be taught how to represent this data, these vectors, to user code. All of that is a huge amount of work, especially when you consider that <strong>there are thousands of operations represented. What makes it even more work is hardware intrinsics.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Designing and enabling the SVE support is a monstrous, multi-year effort</strong>, and while the support is functional and folks are encouraged to take it for a spin, it’s not yet baked enough for us to be 100% confident the shape won’t need to evolve (for .NET 9, it’s also restricted to hardware with a vector width of 128 bits, but that restriction will be removed subsequently). Hence, <code>[Experimental]</code>.&rdquo;</div></blockquote><h3>AVX512</h3><blockquote class="quote quote-block "><div>&ldquo;So the values are <code>0 1 1 0 1 0 0 0</code>, which we read as the binary <code>0b01101000</code>, which is <code>0x68</code>. That byte is used as a “control code” to the <code>vpternlog</code> instruction to encode which of the 256 possible truth tables that exist for any possible (deterministic) Boolean combination of those inputs is being chosen. <strong>This PR then teaches the JIT how to analyze the tree structures produced by the JIT to recognize such sequences of Boolean operations, compute the control code, and substitute in the use of the better instruction.</strong> Of course, the JIT isn’t going to do the enumeration I did above; turns out there’s a more efficient way to compute the control code, performing the same sequence of operations but on specific <code>byte</code> values instead of <code>Booleans</code>.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;This is beneficial for a variety of reasons, including less data to store, less data to load, and <strong>if the register containing this state needed to be spilled</strong> (meaning something else needs to be put into the register, so the value currently in the register is temporarily stored in memory), <strong>reloading it is similarly cheaper.</strong>&rdquo;</div></blockquote><p>All the considerations are mind-boggling. Does it fit in a cache line? How many registers does it use? Is it colocated with similar data? Is the data aligned on a boundary?</p>
<h3>Vectorization</h3><blockquote class="quote quote-block "><div>&ldquo;Of course, you may then wonder, why wasn’t <code>bool.TryFormat</code> reverted to use the simpler code? The unfortunate answer is that this optimization only currently applies to <code>array</code> targets rather than span targets. That’s because there are alignment requirements for performing these kinds of writes, and <strong>whereas the JIT can make certain assumptions about the alignment of arrays, it can’t make those same assumptions about spans, which can represent slices of something else at unaligned boundaries.</strong> This is now one of the few cases where arrays are better than spans; typically span is as good or better. But I’m hopeful it will be improved in the future.&rdquo;</div></blockquote><h3>Object Stack Allocation</h3><blockquote class="quote quote-block "><div>&ldquo;The hardest part of stack allocating objects is ensuring that it’s safe. If a reference to the object were to escape and end up being stored somewhere that outlived the stack frame containing the stack-allocated object, that would be very bad; when the method returned, those outstanding references would be pointing to garbage. So, <strong>the JIT needs to perform escape analysis to ensure that never happens, and doing that well is extremely challenging.</strong>&rdquo;</div></blockquote><p>This is the case where you have to be exceedingly clever in order to not have to let pessimism kill the feature entirely. That is, if you can&rsquo;t prove enough, then you end up having to assume that escape is possible in too many cases—and the optimization ends up applying much less than you&rsquo;d hoped it would.</p>
<h3>VM</h3><blockquote class="quote quote-block "><div>&ldquo;The .NET runtime provides many services to managed code. There’s the GC, of course, and the JIT compiler, and then there’s a whole bunch of functionality around things like <strong>assembly and type loading, exception handling, configuration management, virtual dispatch, interop infrastructure, stub management</strong>, and so on. All of that functionality is generally referred to as being part of the <strong>coreclr virtual machine (VM).</strong>&rdquo;</div></blockquote><h3>Mono</h3><blockquote class="quote quote-block "><div>&ldquo;We frequently say “the runtime,” but <strong>in reality there are currently multiple runtime implementations in .NET.</strong> “coreclr” is the runtime thus far referred to, which is the default runtime used on Windows, Linux, and macOS, and for services and desktop applications, but there’s also “mono,” which is mainly used when the form factor of the target application requires a small runtime: by default, <strong>it’s the runtime that’s used when building mobile apps for Android and iOS today, as well as the runtime used for Blazor WASM apps.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;[…] <strong>when targeting WASM, the interpreter has a form of PGO where after methods have been invoked some number of times and are deemed important, it’ll generate WASM on-the-fly to optimize those methods.</strong> This tiering gets better in .NET 9 with dotnet/runtime#92981, which enables keeping track of which methods tiered up, and if the code is running in a browser, <strong>storing that information in the browser’s cache for subsequent runs.</strong> When the code then runs subsequently, it can incorporate the previous learnings to tier up better and more quickly.&rdquo;</div></blockquote><h3>Threading / <code>Debugger.NotifyOfCrossThreadDependency</code></h3><blockquote class="quote quote-block "><div>&ldquo;When you’re debugging a .NET process and you break in the debugger, it pauses all threads in the debuggee process so that nothing is making forward progress while you examine state. However, .NET debuggers, like the one in Visual Studio, <strong>support invoking properties and methods in the debuggee while debugging.</strong> That can be a big problem if the functionality being invoked relies on one of those paused threads to do something, e.g. if the property you access tries to take a lock that’s held by another thread or tries to <code>Wait</code> on a <code>Task</code>. To mitigate problems here, the <code>Debugger.NotifyOfCrossThreadDependency</code> method exists. Functionality that relies on another thread to do something can call <code>NotifyOfCrossThreadDependency</code>; if there’s no debugger attached, it’s a nop, but if there is a debugger attached, this signals the problem to the debugger, which can then react accordingly. <strong>The Visual Studio debugger reacts by stopping the evaluation but then by offering an opt-in option of “slipping” all threads, unpausing all threads until the evaluated operation completes</strong>, at which point all threads will be paused again, thereby again trying to mitigate any problems that might occur from the cross-thread dependency.&rdquo;</div></blockquote><h3>VM</h3><blockquote class="quote quote-block "><div>&ldquo;The <a href="https://github.com/dotnet/runtime/blob/main/docs/design/specs/Memory-model.md">official .NET memory model</a> has now been documented. However, <strong>some of the practices that were being employed in the core libraries (due to defensive coding or uncertainty of the memory model or out-of-date requirements) are no longer necessary.</strong> One of the main tools available for folks coding at a level where memory model is relevant is the <code>volatile</code> keyword / the <code>Volatile</code> class.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Marking fields or operations as <code>volatile</code> can come with an expense</strong>, depending on the circumstance and the target platform. For example, it can restrict the C# compiler and the JIT compiler from performing certain optimizations.&rdquo;</div></blockquote><h3>Reflection</h3><blockquote class="quote quote-block "><div>&ldquo;Delegates in .NET are “multicast,” meaning a single delegate instance might actually represent multiple methods to be invoked; this is how .NET events are implemented. If I invoke a delegate, the delegate implementation handles invoking each constituent method, sequentially, in turn. But what if I want to customize the invocation logic? Maybe I want to wrap each individual method in a <code>try</code>/<code>catch</code>, or maybe I want to track the return values from all of the methods rather than just the last, or some such behavior. To achieve that, <strong>delegates expose a way to get an array of delegates, one for each method that’s part of the original.</strong>&rdquo;</div></blockquote><p>There are a lot of long chapters on number- and text-processing, which is fascinating but not eminently quotable. You can really see how so many of the various improvements build on each other to finally offer incredible speed improvements (e.g. <code>Quaternion.Cosh()</code>).</p>
<p>So many operations have been improved to reduce allocations to zero while reducing time to a few percent of the previous time, all often with even more code defined in C# rather in the JIT as native code (see <a href="https://github.com/dotnet/runtime/pull/98623">Move memset/memcpy helpers to managed impl #98623</a> for an extreme example that touched 68 files in 48 commits). I find this to be quite elegant. It shows that the investment in the new C# constructs are paying off because it allows framework developers to build faster and better primitives without escaping to a different language and runtime. This, in turn, allows other skilled developers to benefit from the same. Not only that, but managed code is accessible to the GC whereas native code is not.</p>
<p>It&rsquo;s very clear how .NET and C# are being positioned to take over numeric and text processing from Python and C++/C. Everything is being made more generic and funneled to vectorized types, which, in turn, map to the most optimal set of instructions for the myriad supported scenarios, like AOT, ARM, WASM, x64, x86, etc. It&rsquo;s quite an incredible effort.</p>
<p>All of these things combine to make your regular expressions and text searches faster, even if you stick to the existing APIs. In some cases, there are new APIs to use, but not too many. Instead, the beauty of .NET 9 is that it will just make everything so much more efficient—faster and with fewer allocations and GC churn—without programmers having to do a thing. A true feat of engineering.</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] it’s important to recognize that many of the changes discussed thus far implicitly accrue to <code>Regex</code>. <code>Regex</code> already uses <code>SearchValues</code>, and so improvements to <code>SearchValues</code> benefit <code>Regex</code> (it’s one of my favorite things about working at the lowest levels of the stack: <strong>improvements there have a multiplicative effect, in that direct use of them improves, but so too does indirect use via intermediate components that instantly get better as the lower level does</strong>).&rdquo;</div></blockquote><h3>DFA Limits</h3><p>There is a ton of detail about the specifics of regular-expression optimization—enough to make your head spin. Like this:</p>
<blockquote class="quote quote-block "><div>&ldquo;The non-backtracking implementation works by constructing a finite automata, which can be thought of as a graph, with the implementation walking around the graph as it consumes additional characters from the input and uses those to guide what node(s) it transitions to next. <strong>The graph is built out lazily, such that nodes are only added as those states are explored, and the nodes can be one of two kinds: DFA (deterministic) or NFA (non-deterministic).</strong> DFA nodes ensure that for any given character that comes next in the input, there’s only ever one possible node to which to transition. Not so for NFA, where at any point in time there’s a list of all the possible nodes the system could be in, and moving to the next state means examining each of the current states, finding all possible transitions out of each, and treating the union of all of those new positions as the next state. <strong>DFA is thus much cheaper than NFA in terms of the overheads involved in walking around the graph, and we want to fall back to NFA only when we absolutely have to, which is when the DFA graph would be too large</strong>: some patterns have the potential to create massive numbers of DFA nodes. Thus, there’s a threshold where once that number of constructed nodes in the graph is hit, new nodes are constructed as NFA rather than DFA. In .NET 8 and earlier, that limit was somewhat arbitrarily set at 10,000. For .NET 9 as part of this PR, <strong>analysis was done to show that a much higher limit was worth the memory trade-offs, and the limit was raised to 125,000, which means many more patterns can fully execute as DFA.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>The inner matching loop is the hot path for a matching operation: read the next character, look up its minterm, follow the corresponding edge to the next node in the graph, rinse and repeat.</strong> Performance of the engine is tied to efficiency of this loop. These PRs recognized that there were some checks being performed in that inner loop which were only relevant to a minority of patterns. For the majority, <strong>the code could be specialized such that those checks wouldn’t be needed in the hot path.</strong>&rdquo;</div></blockquote><h3>Span, Span, and more Span</h3><blockquote class="quote quote-block "><div>&ldquo;The introduction of <code>Span&lt;T&gt;</code> and <code>ReadOnlySpan&lt;T&gt;</code> back in .NET Core 2.1 have revolutionized how we write .NET code (especially in the core libraries) and what APIs we expose (see <a href="https://www.youtube.com/watch?v=5KdICNWOfEQ">A Complete .NET Developer’s Guide to Span</a> if you’re interested in a deeper dive.) <strong>.NET 9 has continued the trend of doubling-down on spans as a great way to both implicitly provide performance boosts and also expose APIs that enables developers to do more for performance in their own code.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;One of the really nice optimizations the C# compiler added several years back was the ability to recognize when a new <code>byte</code>/<code>sbyte</code>/<code>bool</code> array was being constructed, filled with only constants, and directly assigned to a <code>ReadOnlySpan&lt;T&gt;</code>. In such a case, <strong>it would recognize that the data was all blittable and could never be modified, so rather than allocating an array and wrapping a span around it, it would blit the data into the assembly and then just construct a span around a pointer into the assembly data with the appropriate length.</strong>&rdquo;</div></blockquote><p>This is a wonderful optimization. Clever in a way that only a systems programmer would invent.</p>
<blockquote class="quote quote-block "><div><pre class=" "><code>foreach (Range r in clientSecWebSocketProtocol.AsSpan().Split(','))
{
    if (clientSecWebSocketProtocol.AsSpan(r).Trim().Equals(acceptProtocol, StringComparison.OrdinalIgnoreCase))
    {
        return true;
    }
}</code></pre>&ldquo;In doing so, <strong>it becomes allocation-free, as this <code>Split</code> doesn’t need to allocate a <code>string[]</code> to hold results and doesn’t need to allocate a string for each segment</strong>: instead, it’s returning a <code>ref struct</code> enumerator that yields a <code>Range</code> representing each segment. The caller can then use that <code>Range</code> to slice the input. It’s yielding a <code>Range</code> rather than, say, a <code>ReadOnlySpan&lt;T&gt;</code>, to enable the splitting to be used with original sources other than spans and be able to get the segments in the original form.&rdquo;</div></blockquote><p>There is such a strong focus on <code>structs</code> and <code>refs</code> to make allocation-free code. And now we see how they leverage the recently introduced <code>Range</code> to provide indexes into a sequence that the calling code can decide how to extract. This offers maximum flexibility to the caller, as the algorithm isn&rsquo;t making any costly decisions for it.</p>
<p>In this case, he&rsquo;s discussing how they&rsquo;ve made it relatively easy and intuitive to write code that searches a string without any allocations. The sequence doesn&rsquo;t allocate, examining the chunk as a span doesn&rsquo;t allocate, even the <code>Trim()</code> on a <code>Span</code> doesn&rsquo;t allocate anything.</p>
<h3>LINQ</h3><p>There is a long chapter on LINQ optimizations that boils down to having cleaned up a ton of internal implementation to consolidate on a common base class for customer iteration-combinations like <code>Where</code>/<code>First</code>, <code>Where</code>/<code>OrderBy</code>, etc. Instead of testing for interfaces, it can now test for a single base class and perform a virtual rather than an interface dispatch (which is cheaper). This massive cleanup has the dual benefit of having made many, many LINQ operations 10, 20, and even 100 times faster—and many of them (if not most) are now completely allocation-free. Reducing allocations reduces churn in the GC, which also makes the app faster.</p>
<h3>Core Collections</h3><p>There is also a long chapter on dictionary optimizations. In particular, you can now store data in a dictionary with <code>string</code> keys but request an <em>alternate</em> view on the dictionary that lets you work with it as if it used <code>ReadOnlySpan&lt;char&gt;</code>, which can <em>drastically</em> reduce allocations as the spans you have don&rsquo;t need to be converted to strings simply in order to do the lookups and stores. The changes apply to <code>HashSets</code> as well.</p>
<h3>Compression</h3><p>This is less about compression and more about the general philosophy and tactics underlying performance optimization in .NET (and, presumably, any runtime).</p>
<blockquote class="quote quote-block "><div>&ldquo;It’s an important goal of the core .NET libraries to be as platform-agnostic as possible. Things should generally behave the same way regardless of which operating system or which hardware is being used, excepting things that really are operating system or hardware specific (e.g. we purposefully don’t try to paper over casing differences of different file systems). To that end, <strong>we generally implement as much as possible in C#, deferring down to the operating system and native platform libraries only when necessary.</strong>&rdquo;</div></blockquote><h3>Networking</h3><blockquote class="quote quote-block "><div>&ldquo;dotnet/runtime#99364 <strong>changes the synchronization mechanism from using a pure lock-based scheme to a more opportunistic concurrency scheme that employs a first-layer of lockless synchronization.</strong> There’s now still a lock, but for the hot path it’s avoided as long as there are connections in the pool by using a <code>ConcurrentStack&lt;T&gt;</code>, such that renting is a <code>TryPop</code> and returning is a <code>Push</code>. <strong><code>ConcurrentStack&lt;T&gt;</code> itself uses a lock-free algorithm, that’s a lot more scalable than a lock.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<code>UrlEncode</code> had a complicated scheme where it would UTF8-encode into a newly-allocated <code>byte[]</code>, percent-encode in place in that (thanks to the ability to reinterpret cast with spans), and then use the resulting chars to create a new string. <strong>Instead, <code>string.Create</code> can be used, with all of the work done in-place in the buffer generated for that operation.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;[…] updated <code>UrlEncodeToBytes</code>, using stack space instead of allocation for smaller inputs, and <strong>using <code>SearchValues&lt;byte&gt;</code> to optimize the search for invalid bytes.</strong>&rdquo;</div></blockquote><p>You can really see how the changes made over the last several versions allow a literal horde of open-source programmers to optimize the hell out of hot paths in the .NET library. Use <code>Spans</code> and <code>ReadOnlySpans</code> and <code>ref structs</code> and <code>readonly ref structs</code> to avoid allocations, allocate on the stack wherever you can when you can&rsquo;t avoid allocations, return enumerators instead of allocating array results, use highly optimized building blocks like <code>SearchValues</code> and <code>ConcurrentStack</code>, which employ lock-free algorithms or include custom implementations for common patterns. It all adds up to being able to just write performant code by default, writing in a legible, maintainable, and concise high-level API that is carefully marshaled down to the processor by the compiler and/or the JIT to super-efficient IL and assembler code. You can visualize your code being analyzed and then <a href="https://youtu.be/xw5ErADiuec?t=371">sorted like Plinko chips</a> until it finally lands in the processor cache as instructions.</p>
<h3>Profiling with Benchmark.Net</h3><blockquote class="quote quote-block "><div>&ldquo;There’s another very handy nuget package, <em>Microsoft.VisualStudio.DiagnosticsHub.BenchmarkDotNetDiagnosers</em>, which contains additional “diagnosers” for BenchmarkDotNet. <strong>Diagnosers are one of the main extensibility points within BenchmarkDotNet, enabling developers to perform additional tracking and analyses over benchmarks.</strong> You’ve already seen me use some, including the built-in <code>[MemoryDiagnoser(false)]</code> and <code>[DisassemblyDiagnoser]</code>; there are other built-in ones we haven’t used in this post but that are helpful in various situations, like <code>[ThreadingDiagnoser]</code> and <code>[ExceptionDiagnoser]</code>, but diagnosers can come from anywhere, and the aforementioned nuget package provides several more. <strong>The purpose of those diagnosers is to collect and export performance traces that Visual Studio’s performance tools can then consume.</strong> In my case, I want to collect a CPU trace, so as to understand where CPU consumption is going, so I added a [CPUUsageDiagnoser] attribute to my Tests class&rdquo;</div></blockquote><h3>Lock-free programming</h3><p>What does lock-free programming look like? You replace a <code>lock</code> with an atomic compare/exchange operation, usually in a loop (that&rsquo;s why they&rsquo;re sometimes called &ldquo;spin locks&rdquo;).</p>
<blockquote class="quote quote-block "><div><pre class=" "><code>lock (this)
{
    _delta += value;
}</code></pre>&ldquo;it used an interlocked operation to perform the addition atomically. Here <code>_delta</code> is a <code>double</code>, and there’s no Interlocked.Add that works with <code>double</code> values, so instead the standard approach of using a loop around an <code>Interlocked.CompareExchange</code> was employed.&rdquo;<pre class=" "><code>double currentValue;
do
{
    currentValue = _delta;
}
while (Interlocked.CompareExchange(ref _delta, currentValue + value, currentValue) != currentValue);</code></pre></div></blockquote><h3>Cache lines</h3><p>Finally, an optimization that takes CPU cache lines into account. I hadn&rsquo;t seen anything else that low-level so far.</p>
<blockquote class="quote quote-block "><div>&ldquo;In this benchmark, one thread is incrementing <code>_values[0]</code> and the other thread is incrementing either <code>_values[1]</code> or <code>_values[31]</code>. That index is the only difference, yet the one accessing <code>_values[31]</code> is several times faster than the one accessing <code>_values[1]</code>. That’s because there’s contention here even if it’s not obvious in the code. The contention comes from the fact that the hardware works with memory in groups of bytes called a “cache line.” <strong>Most hardware has caches lines of 64 bytes. In order to update a particular memory location, the hardware will acquire the whole cache line. If another core wants to update that same cache line, it’ll need to acquire it. That back and forth results in a lot of overhead.</strong> It doesn’t matter if one core is touching the first of those 64 bytes and another thread is touching the last, from the hardware’s perspective there’s still sharing happening. <strong>“False sharing.”</strong> Thus, the <code>Counter</code> fix is using padding around the double values to try to space them out more so as to <strong>minimize the sharing that limits scalability.</strong>&rdquo;</div></blockquote><p>👏 File that under something I understand but would never have programmed.</p>
<blockquote class="quote quote-block "><div>&ldquo;In the two benchmarks, we can see that the number of instructions executed is almost the same between when false sharing occurred <code>(Index == 1)</code> and didn’t <code>(Index == 31)</code>, but <strong>the number of cache misses is more than three times larger in the false sharing case</strong>, and reasonably well correlated with the time increase. When one core performs a write, that invalidates the corresponding cache line in the other core’s cache, such that the other core then needs to reload the cache line, resulting in cache misses.&rdquo;</div></blockquote><h3>Conclusion</h3><blockquote class="quote quote-block "><div>&ldquo;There are multiple forms of performance improvements covered throughout the post. <strong>Some of the improvements you get completely for free just by upgrading the runtime</strong>; the implementations in the runtime are better, and so when you run on them, your code just gets better, too. <strong>Some of the improvements you get completely for free by upgrading the runtime and recompiling</strong>; the C# compiler itself generates better code, often taking advantage of newer surface area exposed in the runtime. And other improvements are new features that, in addition to the runtime and compiler utilizing, you can utilize directly and make your code even faster. <strong>Educating about those capabilities and why and where you’d want to utilize them is important to me.</strong> But beyond the new features, the techniques employed in making all of the rest of the optimizations throughout the runtime are often more broadly applicable. <strong>By learning how these optimizations are applied in the runtime, you can extrapolate and apply similar techniques to your own code, making it that much faster.</strong>&rdquo;</div></blockquote><p>And that is much appreciated, Stephen. Having seen the available tools, I feel much better equipped to not only write but be able to advise on writing performant code.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5188</guid>
    <title><![CDATA[Junior code is insidious]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5188</link>
    <pubDate>Sun, 20 Apr 2025 22:54:49 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Apr 2025 22:54:49 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5188/highlightanythingthatseemsstupid.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5188/highlightanythingthatseemsstupid_tn.webp" alt=" " class=" align-right"></a>The article <a href="https://thedailywtf.com/articles/enumerated-science">Enumerated Science</a> by <cite>Remy Porter</cite> (<cite><a href="http://thedailywtf.com/">Daily WTF</a></cite>) describes a train wreck of a code example. It suitably illustrates why we really have to question whether scientists/juniors/etc. should really be writing code with so little training. If they wrote text this poorly, they&rsquo;d be laughed out of their profession. Somehow, it&rsquo;s perfectly fine to write code like this.</p>
<blockquote class="quote quote-block "><div><pre class=" "><code>index = 0
for index, fname in enumerate(img_list):
    data = np.load(img_list[index])
    img = data[0][:,:]
    img_title 'img'+str(index).zfill(4)+'.jpg'
    cv2. imwrite(img_title, img)
    index = index + 1</code></pre></div></blockquote><p>The article points out all of the mistakes but I&rsquo;ll summarize them here.</p>
<ul>
<li>Why does the code ignore the iteration item declared in <code>fname</code>? Instead, the code re-indexes into the array being iterated with <code>img_list[index]</code>. Like, why bro? You already had it! You know what <code>img_list[index]</code> is? It&rsquo;s <code>fname</code>, bro.</li>
<li>Why does the code bother calculating a complicated new filename that has nothing to do with the original filename? Why is the filename called <code>img_title</code>? It&rsquo;s not a title; it&rsquo;s a filename.</li>
<li>Why does the code increment the <code>index</code>? It has no effect, does it? Or is it possible that this algorithm skips every other item? Honestly, why does Python even allow modification of the iterator variables? They should be <code>const</code>/immutable exactly so you can avoid doing something distracting like this.</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5344</guid>
    <title><![CDATA[Web optimization: preload vs. fetchpriority]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5344</link>
    <pubDate>Sun, 20 Apr 2025 22:43:58 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Apr 2025 22:43:58 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This is a nearly 50-minute video about certain optimizations that used to be useful but which, in modern browsers, often get in the way of heuristic optimizations that browsers apply automatically.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/p0lFyPuH8Zs" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=p0lFyPuH8Zs">How browsers REALLY load Web pages</a> by <cite>We Love Speed / Robin Marx</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<blockquote class="quote quote-block "><div>&ldquo;Preload should be applied with <em>surgical precision</em>&rdquo;<ul>
<li>Specific edge cases (you <strong>really</strong> know what you&rsquo;re doing)
<li><div>If the resource <strong>isn&rsquo;t in the HTML</strong><ul>
<li>Fonts</li>
<li>Dynamic LCP images</li>
<li>JS imports</li></ul></div></ul></div></blockquote><p>Basically, he said if you&rsquo;re using <code>preload</code>, you&rsquo;re almost certainly doing it wrong. For example, you can use <code>fetchpriority=high</code> on an <code>img</code> instead, and get the same performance benefit in the current crop of browsers.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/5344/optimize_loading_speed.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5344/optimize_loading_speed_tn.webp" alt=" " class=" align-right"></a>These kinds of optimizations aren&rsquo;t for most web sites. Most web sites have much larger performance problems than can be addressed with <code>fetchpriority</code> and <code>preload</code> optimizations. The one place where it&rsquo;s still useful is for preloading fonts, which is a good idea for everyone.</p>
<p>While those two settings affect how the browser loads resources during the initial load o a page, setting <code>loading=lazy</code> on a resource takes it out of the initial load, so it puts it into a different part of the page-rendering (it&rsquo;s loaded on demand, only when needed, e.g., when you scroll down to it).</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5467</guid>
    <title><![CDATA[Guide to being a good person and programmer]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5467</link>
    <pubDate>Sun, 20 Apr 2025 22:35:18 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Apr 2025 22:35:18 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5467/matrix.webp"><img src="https://www.earthli.com/data/news/attachments/entry/5467/matrix_tn.webp" alt=" " class=" align-right"></a>The article <a href="https://endler.dev/2025/best-programmers/">The Best Programmers I Know</a> by <cite>Matthias Endler</cite> seems almost too good to be true. NGL I feel seen. I have cited heavily from it, highlighting the parts I find especially interesting. At the end are a few pallid notes from me, but the meat of this article is the quote.</p>
<blockquote class="quote quote-block "><div><ul>
<li>Read the Reference</li>
<li>Know Your Tools Really Well</li>
<li>Read The Error Message</li>
<li><div class=" "><p>Break Down Problems</p>
<p>If you work as a professional developer, that is the bulk of the work you get paid to do: breaking down problems. <strong>If you do it right, it will feel like cheating: you just solve simple problems until you’re done.</strong><br>
&nbsp;</p>
</div></li>
<li><div class=" "><p>Don’t Be Afraid To Get Your Hands Dirty</p>
<p>[…] read a lot of code and they are not afraid to touch it. They <strong>never say “that’s not for me” or “I can’t help you here.”</strong> Instead, they just start and learn. Code is just code. They can just <strong>pick up any skill that is required with time and effort.</strong> Before you know it, <strong>they become the go-to person in the team for whatever they touched.</strong> Mostly because they were the only ones who were not afraid to touch it in the first place.<br>
&nbsp;</p>
</div></li>
<li><div class=" "><p>Always Help Others</p>
<p>Great engineers are in high demand and are always busy, but <strong>they always try to help.</strong> That’s because they are <strong>naturally curious and their supportive mind is what made them great engineers in the first place.</strong> It’s a sheer joy to have them on your team, because <strong>they are problem solvers.</strong><br>
&nbsp;</p>
</div></li>
<li><div class=" "><p>Write</p>
<p><strong>Most awesome engineers are well-spoken and happy to share knowledge.</strong></p>
<p>The best have <strong>some outlet for their thoughts: blogs</strong>, talks, open source, or a combination of those.</p>
<p>I think there is a <strong>strong correlation between writing skills and programming.</strong> All the best engineers I know have <strong>good command over at least one human language – often more.</strong> Mastering the way you write is mastering the way you think and vice versa. A person’s writing style says so much about the way they think. If it’s confusing and lacks structure, their coding style will be too. If it’s concise, educational, well-structured, and witty at times, their code will be too.</p>
<p><strong>Excellent programmers find joy in playing with words.</strong><br>
&nbsp;</p>
</div></li>
<li><div class=" "><p>Never Stop Learning</p>
<p><strong>If there is a new tool they haven’t tried or a language they like, they will learn it.</strong> This way, they always stay on top of things […] <strong>the best engineers don’t follow trends, but they will always carefully evaluate the benefits of new technology.</strong> If they dismiss it, they can tell you exactly <em>why</em>, when the technology would be a good choice, and what the alternatives are.<br>
&nbsp;</p>
</div></li>
<li>Have Patience</li>
<li><div class=" "><p>Never Blame the Computer</p>
<p><strong>No matter how erratic or mischievous the behavior of a computer seems, there is <em>always</em> a logical explanation</strong>: you just haven’t found it yet!</p>
<p>The best keep digging until they find the reason. They might not find the reason immediately, they might never find it, but they never blame external circumstances.</p>
<p>With this attitude, they are able to make incredible progress and learn things that others fail to. <strong>When you mistake bugs for incomprehensible magic, magic is what it will always be.</strong><br>
&nbsp;</p>
</div></li>
<li><div class=" "><p>Don’t Be Afraid to Say “I Don’t Know”</p>
<p><strong>The best candidates said “Huh, I don’t know, but that’s an interesting question! If I had to guess, I would say…”</strong> and then they would proceed to deduce the answer. That’s a sign that you have the potential to be a great engineer.<br>
&nbsp;</p>
</div></li>
<li><div class=" "><p>Keep It Simple</p>
<p>Clever engineers write clever code. <strong>Exceptional engineers write simple code.</strong></p>
<p>That’s because most of the time, <strong>simple is enough. And simple is more maintainable</strong> than complex.</p>
</div></li></ul></div></blockquote><p>I disagree with the <span class="quote-inline">&ldquo;Don’t Guess&rdquo;</span> one, in that I think &ldquo;guessing&rdquo;—forming a hypothesis—is the crux of scientific investigation. I think what the author probably meant was to &ldquo;don&rsquo;t leave a guess unproven.&rdquo;</p>
<p>An addendum to the &ldquo;magic&rdquo; one above is that you should also know when to cut bait, i.e., when it&rsquo;s not worth anyone&rsquo;s time to find out what the real reason was. This can happen in one-off scripts, or in tight-deadline situations. Sometimes, you have to back-burner an investigation and either never bring it back to the front burner or learn the lesson at a later time.</p>
<p>But, yes, every problem solved is a bit of experience. It&rsquo;s all worth it. A couple of decades of doing that and you might really have something.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5454</guid>
    <title><![CDATA[Maddy Mondaquila (new .NET Aspire PM) talks programming tools]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5454</link>
    <pubDate>Sun, 06 Apr 2025 21:06:03 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">6. Apr 2025 21:06:03 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This is a wide-ranging, occasionally delightfully foul-mouthed, and brutally honest interview with PM Maddy Mondaquila of Microsoft. Kudos to them for letting their best people do these kinds of informative and insightful interviews.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/yil7UVeOx4Q" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=yil7UVeOx4Q">MAUI Lead Leaves to Work on .NET Aspire (and interview with Maddy Mondaquila)</a> by <cite>Nick Chapsas</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>At <strong>45:57</strong>,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] yesterday Dave [Fowler] and I were fighting about if the Visual Studio <code>.gitignore</code> is getting dumber and he was like, &lsquo;who cares about that? Why would anyone care about that?&rsquo; And I was, like, it&rsquo;s 400 lines, dude. Like, we&rsquo;re ignoring things from […] code-coverage tools that were deprecated five years ago. And then, finally, I start sending him screenshots, and he&rsquo;s, like, wait, why is that in there? Why is that in there?&rdquo;</div></blockquote><p>At <strong>49:00</strong>,</p>
<p>I absolutely loved the shout-out to &ldquo;A Year without Santa Claus&rdquo;. The plot summary was both accurate and possibly better than the actual movie (except for the musical number, which is worth the price of admission). I&rsquo;m going to remember that Heat Miser vs. Cold Miser analogy. [1] Working in a company where most people didn&rsquo;t grow up in the U.S. will make it an uphill battle to use it effectively, but I will not be discouraged.</p>
<p>At <strong>51:49</strong>,</p>
<blockquote class="quote quote-block "><div><p>&ldquo;<span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5454/maddy_mondaquila.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5454/maddy_mondaquila_tn.jpg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5454/maddy_mondaquila.jpg">Maddy Mondaquila</a></span></span>The more I&rsquo;ve gotten to understand what customers are doing and talk to people and seeing the convoluted things that people do to develop an app, the more … I think I probably say once a week. <strong>I don&rsquo;t know how anyone ships software. I don&rsquo;t know how any of this stuff runs. This is all crazy to me, because everything is duct-taped together.</strong> Like, it is terrifying and you onboard someone and it takes like two weeks to get them to be able to run the app on their device.</p>
<p>&ldquo;<strong>Like, what are we doing? What are we doing as a society? This is embarrassing.</strong></p>
<p>&ldquo;We should be able to do more than this and so that&rsquo;s the thing about Aspire that excites me. We&rsquo;re not trying to blackbox anything, right? We&rsquo;re not trying to say, &lsquo;oh, you use this and then your vendor-locked into this thing.&rsquo; It&rsquo;s very much, like, <strong>we&rsquo;re just trying to help you get off the ground and then you can grow out of it.</strong></p>
<p>&ldquo;I had done a lot with App Center […] and my fundamental issue with it […] was that you couldn&rsquo;t grow up into a big-girl Azure service, is what I used to say. Like, once you hit the limits of apps, you had to start over and I was like, with Firebase or something, everything&rsquo;s actually just <code>gcp</code> and when you&rsquo;re ready you go into a big-girl [service], Google&rsquo;s like, you&rsquo;re ready, you move on.</p>
<p>&ldquo;And so, Aspire was built with that in mind. Like, if you use Aspire for orchestration and then you use the client Integrations to do your databases, then at some point you&rsquo;re, like, you know what? I actually don&rsquo;t like the way that they&rsquo;re setting this up. I&rsquo;m going to do it my own way. You don&rsquo;t rip anything out. You just keep going. </p>
<p>&ldquo;And so that was like a really really big sell for me early. And then deployment was a whole other world that I did not understand and <strong>the more I&rsquo;ve looked at it, I don&rsquo;t, … again, I don&rsquo;t know how anyone gets anything done. DevOps is insane.</strong> […] trying to bring that theory of, like, grow-out-able-ness instead of just replacing into deployment has been a very, very fun challenge to try and like tease apart.&rdquo;</p>
</div></blockquote><p>At <strong>1:11:26</strong>,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] we were talking to the Dutch police force and they are a completely polyglot shop so they have people running every language and there was one Java guy that came and and he was, like, so, like .NET&rsquo;s, like, open-source and stuff now? And I was, like, yeah. And he was, like, but, like, really, like, it doesn&rsquo;t have any ecosystem around it? And I was like what? <em>YES</em> and, like. <strong>there are real, like, expert, smart developers out there who just have no idea.</strong>&rdquo;</div></blockquote><p>This nearly deliberate ignorance about other programming languages, about tooling, about technique—it&rsquo;s pervasive. There are people who care, and really want to find better combinations of tools and techniques to do their jobs better, to do <em>what they love</em> better. But there are just as many who just can&rsquo;t even begin to imagine that there are other languages out there, that there are <em>newer versions</em> of the language they use available, with features that would actually be useful to them. These features are provably useful. They make your code more resilient, readable, and maintainable. They do not care. They don&rsquo;t even know that they don&rsquo;t care. They stopped learning a long time ago. Their curiosity is stunted.</p>
<p>It&rsquo;s a pleasure watching people like Maddy and Nick discussing something that they&rsquo;re passionate about. I&rsquo;m passionate about that thing too, but it&rsquo;s mostly because I understand that there is a good way of doing something—writing tests with MSTest and their bog-standard assertion library and no test-case-generation infrastructure—and a <em>better</em> way of doing something—writing tests with NUnit and their elegant assertion library, excellent error messages, and myriad ways of producing test cases. On the other hand, I keep a watchful eye on .NET&rsquo;s new testing infrastructure that allows you to pre-compile unit tests as executables. This works for NUnit, too, so it&rsquo;s a win all around.</p>
<p>That&rsquo;s just one example but it sets the tone. People can&rsquo;t explain why they don&rsquo;t think they need ReSharper. They might not! But they have no idea why. They can&rsquo;t explain why they use VSC instead of WebStorm. They have <em>no idea</em> that the latter actually supports a useful multi-file renaming refactoring whereas VSC still struggles to do a useful rename <em>within a single file.</em></p>
<p>Everyone should be <em>appalled</em> and <em>bitterly disappointed</em> but, instead, they <em>don&rsquo;t even notice</em>. They have no idea what they&rsquo;re missing. So they don&rsquo;t miss it. No wonder LLMs could catch up so quickly.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5454_1_body" class="footnote-number">[1]</span> I love Heat Miser and Cold Miser, but I really like something I remember a coworker of mine saying decades ago, when I still worked in New York. When two guys would be arguing and spiraling out of control, he would drawl in a southern twang that he&rsquo;d never lost, <span class="quote-inline">&ldquo;now, now, girls; you&rsquo;re both pretty.&rdquo;</span> I can&rsquo;t use that among non-native speakers either.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5439</guid>
    <title><![CDATA[tsc is going native]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5439</link>
    <pubDate>Sun, 16 Mar 2025 12:21:36 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Mar 2025 12:21:36 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://devblogs.microsoft.com/typescript/typescript-native-port/">A 10x Faster TypeScript</a> by <cite>Anders Hejlsberg</cite> (<cite><a href="http://devblogs.microsoft.com/">Microsoft</a></cite>) includes the following text, as well as a link to the video below,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] we’ve begun work on a native port of the TypeScript compiler and tools. The native implementation will drastically improve editor startup, reduce most build times by 10x, and substantially reduce memory usage. By porting the current code-base, <strong>we expect to be able to preview a native implementation of <code>tsc</code> capable of command-line type-checking by mid-2025, with a feature-complete solution for project builds and a language service by the end of the year.</strong>&rdquo;</div></blockquote><p>This port is going to be available very, very soon, probably within the next three months. That&rsquo;s quite ambitious.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/pNlq-EVld70" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=pNlq-EVld70">A 10x Faster TypeScript</a> by <cite>Anders Hejlsberg</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The discussion <a href="https://old.reddit.com/r/dotnet/comments/1j94cxe/c_vs_go_concurrency_model/">C# vs. Go Concurrency Model</a> (<cite><a href="http://old.reddit.com/">Reddit</a></cite>) led me to <a href="https://news.ycombinator.com/item?id=43332830">A 10x Faster TypeScript</a> (<cite><a href="http://news.ycombinator.com/">HackerNews</a></cite>), which included a reference to <a href="https://github.com/microsoft/typescript-go/discussions/411">Why Go? #411</a> (<cite><a href="http://github.com/">GitHub</a></cite>), which explains why Go was chosen,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] the most important aspect is that we need to keep the new codebase as compatible as possible, both in terms of semantics and in terms of code structure. <strong>We expect to maintain both codebases for quite some time going forward. Languages that allow for a structurally similar codebase offer a significant boon for anyone making code changes because we can easily port changes between the two codebases.</strong> In contrast, languages that require fundamental rethinking of memory management, mutation, data structuring, polymorphism, laziness, etc., might be a better fit for a ground-up rewrite, but we&rsquo;re undertaking this more as a port that maintains the existing behavior and critical optimizations we&rsquo;ve built into the language. <strong>Idiomatic Go strongly resembles the existing coding patterns of the TypeScript codebase, which makes this porting effort much more tractable.</strong>&rdquo;</div></blockquote><p>The following image, included by a commentator, demonstrates quite nicely how idiomatically similar Go and TypeScript can be.</p>
<p><span style="width: 653px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5439/go_vs._typescript_code.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5439/go_vs._typescript_code.jpg" alt=" " style="width: 653px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5439/go_vs._typescript_code.jpg">Go vs. Typescript code</a></span></span></p>
<p>If you read the rest of the justification, the similarities extend to the guts of the respective runtimes and their approach to memory-management and concurrency, but the visual illustration makes it much clearer that this is a port and <em>not</em> a rewrite.</p>
<p>A C# version—with its slightly different concurrency model and also a focus on byte-code rather than native code—would have involved much more change than this.</p>
<p>A version in Rust would have the focus on native-code generation but would have been a complete rewrite, as a lot of the concurrency and data-sharing possible in JavaScript would have to be explicitly allowed or worked around, something that you can&rsquo;t always (or completely) hide with helper functions. The additional guarantees required in Rust to ensure safety would have to appear explicitly. Sure, you&rsquo;d have the safety then, but it&rsquo;s important to remember that, when you&rsquo;re doing a migration, you should make sure you focus on one migration at a time.</p>
<p>Going from TypeScript to Go will improve some type-safety (though probably not even much) and massively improve speed with a native target. If you want the additional safety of Rust, then you&rsquo;d do a separate migration step from Go to Rust.</p>
<p>There is another, longer interview video here:</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/10qowKUW82U" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=10qowKUW82U">TypeScript is being ported to Go | interview with Anders Hejlsberg</a> by <cite>Michigan TypeScript</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The interviewer is the guy who just published <a href="https://github.com/MichiganTypeScript/typescript-types-only-wasm-runtime">TypeScript types can run DOOM</a>.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5438</guid>
    <title><![CDATA[Pointers for large files and repositories in Git]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5438</link>
    <pubDate>Sun, 16 Mar 2025 12:17:16 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Mar 2025 12:17:16 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://old.reddit.com/r/git/comments/1j8mumh/how_to_add_files_to_a_large_repository/">How to Add files to a Large Repository?</a> (<cite><a href="http://old.reddit.com/">Reddit</a></cite>)</p>
<p>Git has opt-in support for handling large files.</p>
<ul>
<li>Use the <a href="https://git-scm.com/docs/git-clone#Documentation/git-clone.txt-code--depthltdepthgtcode"><code>–depth</code></a> option to control how much history to clone (good for pipelines, where you&rsquo;re usually only interested in the tip, so <code>depth 1</code>)</li>
<li>Whereas <code>depth</code> controls how much you <em>clone</em> (size of the <code>.git</code> folder), <a href="https://git-scm.com/docs/git-sparse-checkout"><code>sparse-checkout</code></a> controls the size of your working tree. </li>
<li><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5438/git_logo.png"><img src="https://www.earthli.com/data/news/attachments/entry/5438/git_logo_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5438/git_logo.png">git logo</a></span></span>Use <a href="https://git-lfs.com/">LFS (Large File Storage)</a> to store files. This will not remove large files from existing commits. This feature is seamless to enable and well-supported throughout the ecosystem.</li>
<li>Once you&rsquo;ve set up LFS for future commits, you can consider removing large files from already-existing commits using something like <a href="https://rtyley.github.io/bfg-repo-cleaner/">BFG</a> and then re-adding them with LFS.</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5432</guid>
    <title><![CDATA[Narrowing types to avoid primitive obsession]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5432</link>
    <pubDate>Sun, 16 Mar 2025 00:09:48 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Mar 2025 00:09:48 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Recently, I saw that the following error had been fixed in a code review.</p>
<p><span style="width: 719px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5432/classic_primitive_obsession.png"><img src="https://www.earthli.com/data/news/attachments/entry/5432/classic_primitive_obsession.png" alt=" " style="width: 719px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5432/classic_primitive_obsession.png">Classic primitive obsession error</a></span></span></p>
<p>The error shown above is an example of a <a href="https://en.wikipedia.org/wiki/Design_smell">design smell</a> called <a href="https://enterprisecraftsmanship.com/posts/functional-c-primitive-obsession/">Primitive Obsession</a>. This is where code is &ldquo;obsessed&rdquo; with primitives, in that it uses a much &ldquo;wider&rdquo; type than is actually acceptable.</p>
<p>Whereas C++ has a <code>typedef</code>, TypeScript and Delphi Pascal have a <code>type</code>, C# has … nothing simple. The <a href="https://enterprisecraftsmanship.com/posts/functional-c-primitive-obsession/">linked article</a> describes a hand-coded version for making &ldquo;narrower&rdquo; types (e.g., <code>MeanLength</code> or <code>ShortFiber</code>). Our go-to generated-source guru <a href="https://andrewlock.net/">Andrew Lock</a> describes a solution that uses the <a href="https://andrewlock.net/updates-to-the-stronglytypedid-library/">StronglyTypedId</a> package, but also links to a series from 2020 by Thomas Levesque that <a href="https://thomaslevesque.com/2020/10/30/using-csharp-9-records-as-strongly-typed-ids/">uses records</a>.</p>
<p>It looks like you can use something like <code>public record MeanLength(int Value);</code> to succinctly define a narrower type. While it&rsquo;s <em>nice</em> that C# autogenerates all the necessary machinery (equals, hashCode, etc.) for the record, it&rsquo;s also <em>unfortunate</em> that it&rsquo;s necessary, as we&rsquo;re usually just trying to disambiguate two <code>ints</code> without further validation or restriction.</p>
<p>Also, I&rsquo;m not recommending you leverage the type system to avoid primitive confusion in every code base! I&rsquo;m just noting that the error that arose is so common that it not only has a name, but that there are well-defined solutions for avoiding that class of problems using the type system.</p>
<p>Before you start messing with these types in a language like C#—where, as noted, you don&rsquo;t have a simple type-disambiguation mechanism—you need to have everyone in the team on board. Many programmers will consider them to be too heavy-handed (they suspect it affects performance somehow, and aren&rsquo;t willing to trade any potential and unproven performance drawback anywhere for increased type-safety). Those are usually the same programmers who write code with <em>a ton</em> of primitive obsession and <em>zero</em> automated tests, so take their critique for what it&rsquo;s worth.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5420</guid>
    <title><![CDATA[Who's going to fix the bad projects?]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5420</link>
    <pubDate>Sat, 15 Mar 2025 14:50:10 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Mar 2025 14:50:10 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://blog.jim-nielsen.com/2025/get-better-doing-a-bad-job/">Can You Get Better Doing a Bad Job?</a> by <cite>Jim Neilsen</cite> cites Woody Harrelson as saying, <span class="quote-inline">&ldquo;I think when you do your job badly you never really get better at your craft.&rdquo;</span></p>
<p>Of course that&rsquo;s true on the surface: If you manage to avoid learning anything else, then you will only ever get better at doing a bad job. The author expands on this point as follows,</p>
<blockquote class="quote quote-block "><div>&ldquo;Experience is a hard teacher. Perhaps, from a technical standpoint, my skillset didn’t get any better. But <strong>from an experiential standpoint, my judgement got better.</strong> I learned to avoid (or try to re-structure) work that’s being carried out in a way that doesn’t align with its own purpose and essence.&rdquo;</div></blockquote><p>I agree with the highlighted bit especially. Any experience can be &ldquo;good&rdquo; because there is always room for seeing how you can make something useful in the midst of madness, how you can extract enjoyment out of even a poorly managed project. You can hone your programming skills; you can hone your diplomatic skills; you can learn how to turn it around. Maybe. At the worst, you learn how <em>not</em> to turn it around.</p>
<p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5420/dumpster_fire.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5420/dumpster_fire_tn.jpg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5420/dumpster_fire.jpg">Dumpster fire</a></span></span>But then he writes that he <span class="quote-inline">&ldquo;learned to avoid (or try to re-structure)&rdquo;</span> work that he doesn&rsquo;t like. This is fine, but I would flip those two, to read &ldquo;I learned to try to restructure (or, in the worst case, avoid),&rdquo; in order to emphasize that <em>someone</em> should be trying to impart order to chaos—it might as well be you, if you&rsquo;re so damned smart.</p>
<p>If everyone were <em>avoiding</em> bad projects, then where would good projects come from? Does everyone think that they&rsquo;re so precious that good projects <em>have to be prepared for them</em> before they&rsquo;ll even consider participating?</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3016</guid>
    <title><![CDATA[James Mickens is back with more]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3016</link>
    <pubDate>Thu, 13 Mar 2025 09:41:39 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Mar 2025 09:41:39 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><span style="width: 180px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3016/james_mickens.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/3016/james_mickens_tn.jpg" alt=" " style="width: 180px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3016/james_mickens.jpg">James Mickens</a></span></span>I recently stumbled upon some <a href="http://blogs.msdn.com/b/oldnewthing/archive/2013/12/24/10484402.aspx">Essays from the funniest man in Microsoft Research</a> by <cite>Raymond</cite> (<cite><a href="http://blogs.msdn.com/">Old New Thing</a></cite>). He is such a funny writer that this article, against convention and like the one before it (<a href="https://www.earthli.com/news/view_article.php?id=2904">Brilliant articles by the funniest guy at Microsoft</a>), will consist mostly of citations rather than an even mix of citations and paraphrasing that I naturally consider to be much more lucid and pithy. I quote at length to do the material justice, for documentation and to ensure that you all download the PDFs to see if there is more where that came from (there is). All emphases have been added.</p>
<p>He has since moved on to teach at Harvard University and is publishing things like <a href="https://mickens.seas.harvard.edu/wisdom-james-mickens">The Wisdom of James Mickens</a> there. That one&rsquo;s about,</p>
<blockquote class="quote quote-block "><div>&ldquo;Sometimes, when a professor goes on sabbatical, that professor will create a great book or sculpture, or commence upon a tour of the world to propagate some transcendental vision about the stars or aesthetics or our relationship to the divine. I myself spent my sabbatical writing a heavy metal album called “Ten Times Your Master: A King in Every Corner.” The ostensible conceit behind the album is that I, James Mickens, have gone missing, and the heavy metal community has formed a five-person tribute band called Ten Times Your Master to cover my songs. In reality, I, James Mickens, have not gone missing at all, and in fact am at the height of my powers, having created five distinct musical aliases to record a tribute album to myself, James Mickens.&rdquo;</div></blockquote><p>Which, you have to admit, is one of the most uniquely funny and interesting things that you&rsquo;ve read in a while.</p>
<p><small class="notes">The notes below stem from a draft I wrote in 2014 and have only now published 11 years later. I have not altered them in any way because, well, I haven&rsquo;t gotten any smarter, so who am I to correct my past self?</small></p>
<p><a href="http://research.microsoft.com/en-us/people/mickens/ToWashItAllAway.pdf">To Wash It All Away</a> by <cite>James Mickens</cite> (<cite><a href="http://research.microsoft.com/">Microsoft Research</a></cite>) (PDF) discusses the delusions of web programming:</p>
<blockquote class="quote quote-block "><div><p>&ldquo;A modern Web page is a catastrophe. It’s like a scene from one of those apocalyptic medieval paintings that depicts what would happen if Galactus arrived: people are tumbling into fiery crevasses and lament- ing various lamentable things and hanging from playground equipment that would not pass OSHA safety checks. This kind of stuff is exactly what you’ll see if you look at the HTML, CSS, and JavaScript in a modern Web page. Of course, no human can truly “look” at this content, because a Web page is now like V’Ger from the first “Star Trek” movie, a piece of technology that we once understood but can no longer fathom, a thrashing leviathan of code and markup written by people so untrust- worthy that they’re not even third parties, they’re fifth parties who weren’t even INVITED to the party</p>
<p>&ldquo;In a rational universe, a single uncaught excep- tion would terminate a program, and if a program continued to execute after throwing such an exception, we would know that Ragnarok is here and Odin is not happy. In the browser world, ignoring uncaught exceptions is called “Wednesday, and all days not called ‘Wednesday.’” The JavaScript event loop is quite impervious to conventional notions of software reliabil- ity, so if an event handler throws an exception, the event loop will literally pretend like nothing happened and keep running. This ludicrous momentum continues even if, in the case of the seventh error, the Web page tries to call init() on an object that has no init() method. You should feel uncomfortable that a Web page can disagree with itself about the existence of initialization routines, but the page is still allowed to do things with things. Such a dramatic mismatch of expectations would be unacceptable in any other context.</p>
<p>&ldquo;it would definitely be horrible if your browser’s scripting lan- guage combined the prototype-based inheritance of Self, a quasi-functional aspect borrowed from LISP, a structured syntax adapted from C, and an aggressively asynchronous I/O model that requires elaborate callback chains that span multiple generations of hard-working Americans. OH NO I’VE JUST DESCRIBED JAVASCRIPT.</p>
<p>&ldquo;JavaScript is dynamically typed, and its aggressive type co- ercion rules were apparently designed by Monty Python. For example, 12 == “12” because the string is coerced into a num- ber. This is a bit silly, but it kind of makes sense. Now consider the fact that null == undefined. That is completely janky; a reference that points to null is not undefined—IT IS DEFINED AS POINTING TO THE NULL VALUE. And now that you’re warmed up, look at this: “\r\n\t” == false. Here’s why: the browser detects that the two operands have different types, so it converts false to 0 and retries the comparison. The operands still have different types (string and number), so the browser coerces “\r\n\t” into the number 0, because somehow, a non-zero number of characters is equal to 0. Voila—0 equals<br>
0! AWESOME. </p>
<p>&ldquo; I obviously get what I deserve if my JavaScript library redefines native prototypes in a way that breaks my own code. However, a single frame in a Web page contains multiple JavaScript libraries from multiple origins, so who knows what kinds of horrendous prototype manipulations those heathen libraries did before my library even got to run. This is just one of the reasons why the phrase “JavaScript secu- rity” causes Bibles to burst into flames.</p>
<p>&ldquo;Some JavaScript libraries intention- ally begin with an initial semicolon, to ensure that if the library is appended to another one (e.g., to save HTTP roundtrips during download), the JavaScript parser will not try to merge the last statement of the first library and the first statement of the second library into some kind of semicolon-riven statement party. <strong>Such an initial semicolon is called a “defensive semico- lon.” That is the saddest programming concept that I’ve ever heard, and I am fluent in C++.</strong></p>
<p>&ldquo;I could go on and on about the reasons why JavaScript is a cancer upon the world. I know that there are people who like JavaScript, and I hope that these people find the mental health services that they so desperately need. I don’t know all of the answers in life, but I do know all of the things which aren’t<br>
the answers, and JavaScript falls into the same category as Scientology, homeopathic medicine, and making dogs wear tiny sweaters due to a misplaced belief that this is what dogs would do if they had access to looms and opposable thumbs.</p>
<p>&ldquo;The first log entry says that the browser executed a downloaded file as JavaScript, even though the MIME type of the file was text/html. Here’s a life tip: when you’re confused about what something is, DON’T EXECUTE IT TO DISCOVER MORE CLUES. This is like observing that your next-door neighbor is a creepy, bedraggled man with weird eyes, and then you start falling asleep on his doorstep using a chloroform rag as a pillow, just to make sure that he’s not going to tie you to a radiator and force you to paint tiny figurines. Here’s how your life story ends: YOU ARE A PAINTER OF TINY FIGURINES.&rdquo;</p>
</div></blockquote><p><a href="http://research.microsoft.com/en-us/people/mickens/thisworldofours.pdf">This World of Ours</a> by <cite>James Mickens</cite> (<cite><a href="http://research.microsoft.com/">Microsoft Research</a></cite>) (PDF) discusses the delusions of passwords, cryptography and security research:</p>
<blockquote class="quote quote-block "><div>&ldquo;Basically, you’re either dealing with Mossad or not-Mossad. If your adversary is not-Mossad, then you’ll probably be fine if you pick a good pass- word and don’t respond to emails from ChEaPestPAiNPi11s@ virus-basket.biz.ru. If your adversary is the Mossad, YOU’RE GONNA DIE AND THERE’S NOTHING THAT YOU CAN DO ABOUT IT. The Mossad is not intimidated by the fact that you employ https://. If the Mossad wants your data, they’re going to use a drone to replace your cellphone with a piece of uranium that’s shaped like a cellphone, and when you die of tumors filled with tumors, they’re going to hold a press conference and say “It wasn’t us” as they wear t-shirts that say “IT WAS DEFI- NITELY US,” and then they’re going to buy all of your stuff at your estate sale so that they can directly look at the photos of your vacation instead of reading your insipid emails about them. In summary, https:// and two dollars will get you a bus ticket to nowhere. Also, SANTA CLAUS ISN’T REAL. When it rains, it pours.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Even worse than the PGP acolytes are the folks who claim that we can use online social networks to bootstrap a key infra- structure. Sadly, the people in an online social network are the same confused, ill-equipped blunderhats who inhabit the phys- ical world. Thus, social network people are the same people who install desktop search toolbars, and who try to click on the monkey to win an iPad, and who are willing to at least enter- tain the notion that buying a fortune-telling app for any more money than “no money” is a good idea. These are not the best people in the history of people, yet somehow, I am supposed to stitch these clowns into a rich cryptographic tapestry that supports key revocation and verifiable audit trails. One time, I was on a plane, and a man asked me why his laptop wasn’t working, and I tried to hit the power button, and I noticed that the power button was sticky, and I said, hey, why is the power button sticky, and he said, oh, IT’S BECAUSE I SPILLED AN ENTIRE SODA ONTO IT BUT THAT’S NOT A PROBLEM RIGHT? I don’t think that this dude is ready to orchestrate cryptographic operations on 2048-bit integers.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;I realize that, in an ideal world, I would recycle my trash, and contribute 10% of my income to charity, and willingly accept the cognitive overhead of finegrained security labels. However, pragmatists understand that I will spend the bulk of my disposable income on comic books, and instead of recycling, I will throw all of my trash into New Jersey.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Similarly, we know that IFC research should not focus on what would happen if I somehow used seventeen types of labels to describe three types of variables. Instead, IFC research should focus on what will happen when I definitely give all my variables The God Label so that my program compiles and I can return to my loved ones.&rdquo;</div></blockquote><p>This is the enduring problem of security. This is what always happens when the people charged with providing security aren&rsquo;t well-versed enough to handle the complexity of the chore. Our job as framework developers is to make a system that is as simple as possible, but no simpler. Sometimes, initial efforts miss the mark. Sometimes, there is no way to feasibly bridge the gap between what users&rsquo; capabilities and the complexity of the tasks that they have to solve.</p>
<blockquote class="quote quote-block "><div>&ldquo;The worst part about growing up is that the world becomes more constrained. As a child, it seems completely reasonable to build a spaceship out of bed sheets, firecrackers, and lawn fur- niture; as you get older, you realize that the S.S. Improbable will not take you to space, but instead a lonely killing field of fire, Child Protective Services, and awkward local news interviews, not necessarily in that order, but with everything showing up eventually.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div><p>&ldquo;Security research is the continual process of discovering that your spaceship is a deathtrap. However, as John F. Kennedy once said, “SCREW IT WE’RE GOING TO THE MOON.” I cannot live my life in fear because someone named PhreakusMaximus at DefConHat 2014 showed that you can induce peanut allergies at a distance using an SMS message<br>
and a lock of your victim’s hair. If that’s how it is, I accept it and move on. <strong>Thinking about security is like thinking about where to ride your motorcycle: the safe places are no fun, and the fun places are not safe.</strong>&rdquo;</p>
</div></blockquote><p>A sample from <a href="https://mickens.seas.harvard.edu/tenure-announcement">Tenure announcement: April 2019</a> by <cite>James Mickens</cite> (<cite><a href="http://mickens.seas.harvard.edu/">Harvard School of Engineering &amp; Applied Sciences</a></cite>):</p>
<p>James Mickens’s Harvard tenure announcement is unorthodox. He’s basically trash-talking to his enemies, who can no longer touch him. Some samples:</p>
<blockquote class="quote quote-block "><div>&ldquo;My seventh-favorite enemy is obviously Alan Fontaine of Iowa State University. I know that you’re reading this, Alan, because you keep inviting me to NSF panels even though I mailed you a glitter bomb that was shaped like me mailing you a glitter bomb. Your theories on Muppet physiology are childish and naïve, and I viciously refute them in my upcoming article “Parasitic Infections of Muppet Gastrointestinal Hand Holes.&ldquo; I wish you the best when you lose your endowed professorship and are forced to teach at a lower-tier institution that can’t even afford real Muppets and has to use oven mitts with faces drawn on them.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;On that page, I used my grandfather’s charcoal pencil to draw a picture of myself dunking a basketball over your confused, athletically-incompetent body;&rdquo;</div></blockquote>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5408</guid>
    <title><![CDATA[And another thing about MVVM]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5408</link>
    <pubDate>Sat, 22 Feb 2025 19:59:32 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">22. Feb 2025 19:59:32 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">22. Feb 2025 19:59:58 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I recently wrote <a href="https://www.earthli.com/news/view_article.php?id=5289">Real quick on MVVM</a> and now I see that a good colleague and friend has written his own <a href="https://ajone239.github.io/2025/02/15/mvvm-understanding.html">MVVM understandings</a> by <cite>Austin Jones</cite> (<cite><a href="http://ajone239.github.io/">Austin&#039;s Journey for Meaning</a></cite>). His piece got me thinking again about how the concept is a good start but isn&rsquo;t really sufficient.</p>
<h2>Justifying the view model</h2><p>Somewhere near the beginning, he writes,</p>
<blockquote class="quote quote-block "><div>&ldquo;The View Model’s function is separate from the Model. Abstraction requires discipline to not let two pieces of code that do the same thing <em>become</em> the same thing, purely out of convenience. Things that operate together should be functionally coupled, not just that same code.&rdquo;</div></blockquote><p>While I deeply appreciate the sentiment, I think that (A) most people are going to be unconvinced that they need additional complexity for such a vague goal, and (B) there are more concrete reasons to keep them separate. In <a href="https://www.earthli.com/news/view_article.php?id=5289">Real quick on MVVM</a>, I posited a simple example, repeated below.</p>
<pre class=" "><code>record Person(
  string FirstName,
  string LastName,
  Company Company,
  DateTime BirthDate);</code></pre><p>The view model might want to expose:</p>
<pre class=" "><code>int Age =&gt; DateTime.Now.Year − _model.BirthDate.Year;

string FullName =&gt; $"{_model.FirstName} {_model.LastName}";

Company Company { get; }

IReadOnlyList&lt;Company&gt; AvailableCompanies { get; }</code></pre><p>The <code>AvailableCompanies</code> is for the drop-down menu.</p>
<p>The data in the model is a different <em>shape</em> than that required by the view. This happens <em>quite quickly</em> and <em>quite often</em>. Anyone who tries to &ldquo;cheat&rdquo; by using a type as both a model and view model will quickly be writing spaghetti code.</p>
<p>It is the view-model&rsquo;s job to marshal data to and from its own shape to that of the model. It is decidedly <em>not</em> the model&rsquo;s job to do that, because it <em>exposes</em> data, while one or more views might display it in different ways. Perhaps another view is showing the birthdate directly, in which case <em>that</em> view model would simply pass the value through unmodified.</p>
<h2>Thinking through an example</h2><blockquote class="quote quote-block "><div>&ldquo;Most logic seems to fall into the View Model as your business logic rules are often mirrored by presentation rules. E.g. a button has to be disabled if the user hasn’t met some requirement.&rdquo;</div></blockquote><p>It may seem too picky but I would instead use the verb <em>reflect</em> instead of <em>mirror</em>, to say that the view model exposes properties that <em>reflect</em> the state in the model. Just off the top of my head, I can imagine that each component of the architecture has unique duties, as illustrated in the example below,</p>
<ul>
<li>A <strong>model</strong> contains several properties that must adhere to certain rules in order to be saved.</li>
<li>A validation <strong>service</strong> determines whether those rules have been satisfied, returning a list of zero or more validation results.</li>
<li>A <strong>view model</strong> exposes the most recent list of validations as a property, as well as a property called <code>readyToSubmit</code>. The view model triggers the service to calculate a new list of validations when the view <em>notifies</em> it that a relevant change has been made.</li>
<li>A <strong>view</strong> binds the validations as it sees fit—either attaching properties directly to the controls that will display their values and allow users to manipulate them, as well as exposing the list of validations to the user in some way—as well as binding the <code>Enabled</code> property of the submission button to the <code>readyToSubmit</code> property.</li></ul><p>This is just a simple example but we can see that the model is just a data container. In classic OO, the service would have been part of those objects. However, it&rsquo;s far more flexible to keep the model as a set of &ldquo;dumb&rdquo; DTOs and to keep the logic in the service. This makes it much easier to replace the validation logic in specific cases, without touching the data layer, which doesn&rsquo;t need to change.</p>
<p>The view model does the work of managing calls to the validation service as well as retaining the results as long as the view needs them. The view model doesn&rsquo;t know anything about buttons. It doesn&rsquo;t need to know that they can be enabled or disabled. That&rsquo;s the view&rsquo;s job, which deals with the actual representations presented to the user.</p>
<p>This makes the view model, in turn, flexible enough to be used with alternate representations. For example, we can imagine a view or view model that simply auto-saves when <code>readyToSubmit</code> is <code>true</code>, so it would have been a shame to have named that property <code>saveButtonEnabled</code> because it would have been an awkward fit for the hypothetical second view.</p>
<h2>Benefits</h2><p>As you can well imagine, it&rsquo;s incredibly easy to test systems built in this way, as you can very easily construct the data/model that you want and test something like the validation service. You can also very easily build on top of that to verify that the view model updates and notifies as expected. You can even bind to its properties to verify that a potential view would have received the expected notifications.</p>
<p>The view doesn&rsquo;t have more logic in it than <em>binding</em>. Views are more finicky to test—although it&rsquo;s not impossible or even especially difficult with practice, its it&rsquo;s also not usually necessary. For most problems that crop up, your tests eliminate the possibility that the bug is anywhere other than the view, so you quickly find where the incorrect binding. Obviously, if errors like this are chronic—or if you have very complex views—then you&rsquo;ll want to test the view with end-to-end tests. Just remember that testing the view usually requires the most effort, results in the slowest tests, and provides the least benefit, so you should really be doing those last, if at all.</p>
<h2>Conclusion</h2><p>My colleague&rsquo;s example focuses more on how the service layer pertains to persistence, for loading and storing models. I wanted to provide an example that doesn&rsquo;t have anything to do with persistence but shows that there is non-persistence logic that obviously—at least in hindsight—doesn&rsquo;t belong anywhere but in the service layer.</p>
<p>I&rsquo;ve been working with this type of abstraction since at least 2002, when I started working on the Atlas framework at Opus Software AG, which was written in Delphi Pascal. We didn&rsquo;t call it MVVM but we had a very clear separation between the <em>object model</em>, the <em>view model</em>, and <em>renderers</em>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5409</guid>
    <title><![CDATA[Avoiding completely failed estimates]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5409</link>
    <pubDate>Sat, 22 Feb 2025 11:54:02 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">22. Feb 2025 11:54:02 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5409/estimate_scrabble.jpg"><img title="Estimate Scrabble" src="https://www.earthli.com/data/news/attachments/entry/5409/estimate_scrabble_tn.jpg" alt=" " class=" align-left"></a>The relatively short post <a href="https://www.cosive.com/blog/my-washing-machine-refreshed-my-thinking-on-software-effort-estimation">My Washing Machine Refreshed My Thinking on Software Effort Estimation</a> by <cite>Chris Horsley</cite> (<cite><a href="http://www.cosive.com/">Cosive</a></cite>) is kind of interesting, in that it&rsquo;s a cautionary tale about being overconfident about your estimates. As the title suggests, his was a real-world task where he&rsquo;d assumed that a tenth iteration would go just as smoothly. He draws some good conclusions but for what I think might be the wrong reasons.</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] <strong>while 90% of the project will be the same, there&rsquo;s going to be one critical difference between the last 5 projects and this project that seemed trivial at the time of estimation</strong> but will throw off our whole schedule. It could be one or all of:&rdquo;<ol>
<li>Our <strong>well-used task-running framework</strong> we were going to use for a relatively small part of the system <strong>is totally unmaintained now</strong> and we&rsquo;d have to fork it to make it fit for purpose again.</li>
<li><strong>Our entire development tooling ecosystem was obsoleted 18 months after the last time we did this</strong>, so we&rsquo;re going to be learning the sharp edges of a whole new toolchain from scratch.</li>
<li><strong>We find that our OS version has moved on and no longer supports key requirements for our existing dependencies</strong>, requiring rethinking or developing from scratch.</li>
<li>We need our infrastructure stack to <strong>use one component we&rsquo;ve never used before and it doesn&rsquo;t work anything like we expected.</strong></li></ol></div></blockquote><p>The things that he lists as stuff that you generally don&rsquo;t think about are exactly the kinds of things that you should keep in mind when doing an estimate, though! Like, if you&rsquo;ve been doing estimates and any of these things are a surprise to you, then you&rsquo;ve just been <em>LARPing</em> at estimates.</p>
<p>Even when you copy/paste an existing solution to a similar problem, you have to consider the context in which the original was developed and the degree to which that context might be different this time around. It&rsquo;s not easy but it&rsquo;s <em>your job</em> to be aware of limitations and concessions at all times. Always consider that the passage of time <em>is part of the context</em>.</p>
<p>It too so long to set up his washing machine because he&rsquo;s a rank amateur at doing that, despite having done it so many times. He got lucky the first nine times because literally nothing that could go wrong went wrong. He thought that his experience promoted him to a senior-level position but he was still a junior-level <em>monteur</em>. On his tenth time, everything went wrong and he was totally blindsided by it—but only because he&rsquo;d learned nothing about the system he was working on.</p>
<p>He didn&rsquo;t learn, for example, what his requirements or environmental expectations were nor that he should quickly check to verify that they were satisfied before he started.</p>
<p>It&rsquo;s as if he&rsquo;d gone downstairs to check his car&rsquo;s oil but hadn&rsquo;t brought his house keys with him because the door to the garage had always been propped before. When he had to go back upstairs to get his house keys, that was considered a blindsiding showstopper that you couldn&rsquo;t have accounted for.</p>
<p>Even after the first setback, he didn&rsquo;t sit back to take stock of the situation and plan his <em>next few steps</em> rather than just his <em>next step</em>. That&rsquo;s the classic misinterpretation of agile: it doesn&rsquo;t mean you should turn your brain off in planning. It doesn&rsquo;t mean you shouldn&rsquo;t do any long-term planning. It means that you should always be prepared to <em>change your plan</em>. It means that you should take a <em>little time</em> to plan for the immediately foreseeable work. That doesn&rsquo;t mean that you&rsquo;re suddenly doing waterfall! It means you&rsquo;re <em>filling your backlog</em>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5389</guid>
    <title><![CDATA[Tacking against the winds of Copilot]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5389</link>
    <pubDate>Sun, 16 Feb 2025 08:45:32 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Feb 2025 08:45:32 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The tweet <a href="https://x.com/karpathy/status/1886192184808149383">&rdquo;Programming&rdquo;</a> by <cite>Andrej Karpathy</cite> (<cite><a href="http://x.com/">Twitter</a></cite>) is what some people are calling the future of programming—with the loudest claiming that it&rsquo;s <em>already here</em> and that <em>you&rsquo;re all missing the boat</em> if you&rsquo;re not programming like this.</p>
<blockquote class="quote quote-block "><div>&ldquo;There&rsquo;s a new kind of coding I call &ldquo;vibe coding&rdquo;, where you fully give in to the vibes, embrace exponentials, and forget that the code even exists. <strong>It&rsquo;s possible because the LLMs (e.g. Cursor Composer w Sonnet) are getting too good. Also I just talk to Composer with SuperWhisper so I barely even touch the keyboard.</strong> I ask for the dumbest things like &ldquo;decrease the padding on the sidebar by half&rdquo; because I&rsquo;m too lazy to find it. I &ldquo;Accept All&rdquo; always, I don&rsquo;t read the diffs anymore. When I get error messages I just copy paste them in with no comment, usually that fixes it. The code grows beyond my usual comprehension, I&rsquo;d have to really read through it for a while. Sometimes the LLMs can&rsquo;t fix a bug so I just work around it or ask for random changes until it goes away. <strong>It&rsquo;s not too bad for throwaway weekend projects, but still quite amusing. I&rsquo;m building a project or webapp, but it&rsquo;s not really coding − I just see stuff, say stuff, run stuff, and copy paste stuff, and it mostly works.</strong>&rdquo;</div></blockquote><p>The people who claim that this represents the future of all human engineering effort are mostly fools and mountebanks, who are either not software developers or engineers, or who claim that they are, but never really understood what we do.</p>
<p>Karpathy is, at least, very explicit that he&rsquo;s doing this for &ldquo;throwaway&rdquo; projects. He is building, at best, prototypes and, at worst, inscrutable toys that don&rsquo;t do what he wants, and he&rsquo;s not going to bother trying to fix them.</p>
<p>This style only works because Karpathy <em>already kind of knows how to program</em> and <em>he&rsquo;s smart</em>. This style will not make someone magically able to produce anything other than a crude facsimile of what has already been produced before. They will likely get stuck in myriad cul-de-sacs where the LLM avows very confidently that something will work and it will not work—sometimes subtly, sometimes overtly.</p>
<p>The other day, I was confronted three times with outright inaccurate, or simply outdated or inapplicable suggestions from Copilot. I did not request these suggestions; they were introduced by colleagues during reviews and collaboration.</p>
<h2>Clinging to the past</h2><p>In one case, someone asked in a PR whether we really could eliminate the framework declaration in <code>app.config</code> files.</p>
<pre class=" "><code>&lt;configuration&gt;
  &lt;startup&gt;
      &lt;supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /&gt;
   &lt;/startup&gt;
&lt;/configuration&gt;</code></pre><p>The Microsoft documentation still confidently declares that you need to include this declaration but says nothing about why it&rsquo;s not included in any of its starter templates.</p>
<p>Copilot therefore confidently writes that you absolutely need the declaration for reasons that might have been somewhat applicable in 2009, or maybe even 2012.</p>
<p>The app in question works with .NET Framework 4.8, a version that has been available for three years. There is no follow-up version in sight. A 4.x version of the framework has been included on all versions of Windows for years. The app doesn&rsquo;t run with a lower version. It already declares this in the <code>&lt;TargetFramework&gt;</code> element of the project file.</p>
<p>We don&rsquo;t need to artificially pin the version with an outdated mechanism. The version of the framework give in the project file is not only sufficient, but adding  an outdated alternative that says something slightly different but will be ignored is distracting, to say the least. It&rsquo;s a recipe for configuration cargo cults and future goose chases, which is why I threw it out. Copilot would chirpily encourage people to put it right back in, and to waste time fine-tuning it.</p>
<h2>Simplistic and incorrect</h2><p>In another case, a colleague was having trouble upgrading Entity Framework from using the <code>System.Data.SqlClient</code> to using the <code>Microsoft.Data.SqlClient</code> instead. There was an error where a registration wasn&rsquo;t being honored and the app couldn&rsquo;t find the new provider. </p>
<p>The Copilot solution was to confidently recommend adding a whole bunch of crap that wouldn&rsquo;t solve the problem in any sane manner—and couldn&rsquo;t. It just amounted to vague instructions to include the EF framework—which my colleague was obviously already doing.</p>
<p>The solution to the problem was going to have to be more subtle, but my colleague was getting lost in the weeds of trying to figure out the subtlety underlying what Copilot might possibly mean with its naive suggestion.</p>
<p>I am continually amazed by how much leeway people give these LLM tools, very optimistically assuming that a given tool &ldquo;understood&rdquo; the intent and is suggesting a brilliant solution that will reveal itself if only the <em>developer</em> can rise to the occasion.</p>
<p>When I was called in, I read the error message and it was pretty clear that something in the system was overriding the settings we wanted to use. It turned out that there was a reference to the old data provider in one of the core libraries that we&rsquo;d upgraded. </p>
<p>Instead, we ended up focusing on the fact that the EF support took a default dependency on a relatively old 5.x component but the latest version was 6.x. The suspicion was that perhaps something would work better in 6.x. When my colleague added the newer version to all projects, things started working again, so apparently a bug had been fixed. But which bug?</p>
<p>While it was good to have a workaround, adding the reference everywhere was an awkward solution. So my colleague took a small timebox to investigate further</p>
<p>He eventually discovered—without Copilot—that there was a registration for the old data provider buried in our library code. Removing that single line of configuration in the base library solved the error. Including another registration shouldn&rsquo;t cause the configuration to ignore subsequent registrations of other data providers, though. I think that the 5.x version wasn&rsquo;t capable of properly managing multiple, registered data providers but that the 6.x version could. When the library was forced to use a newer version, everything worked again.</p>
<p>The maintainable solution that we ended up using was:</p>
<ol>
<li>Remove the unwanted configuration entry in the base library.</li>
<li>Add a single reference to the newer version of the transient library to ensure that we were using the 6.x version—with the bug fix that we technically no longer needed—in all consumers of the library. This step wasn&rsquo;t even strictly necessary but there&rsquo;s no harm in it. We marked the package-inclusion with a reason and a link to the work item that was tracking the work and included a write-up of what had happened.</li></ol><h2>A solution that doesn&rsquo;t exist</h2><p>Finally, I had updated a build-pipeline template to accept a new parameter: <code>OutputFolder</code>, which was to default to a value based on the value of another parameter <code>SolutionFolder</code>. The following solution feels like a natural way of expressing this intent.</p>
<pre class=" "><code>parameters:
    SolutionFolder: ''
    OutputFolder: '${{ parameters.SolutionFolder }}\Output'</code></pre><p>This is what it looked like in the actual template:</p>
<p><span style="width: 578px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5389/this_is_not_allowed.png"><img src="https://www.earthli.com/data/news/attachments/entry/5389/this_is_not_allowed.png" alt=" " style="width: 578px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5389/this_is_not_allowed.png">Copilot&#039;s bold suggestion</a></span></span></p>
<p>However, if you try it, you will get an error message saying that &ldquo;A template expression is not allowed in this context&rdquo;:</p>
<p><span style="width: 461px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5389/template_expression_not_allowed.png"><img src="https://www.earthli.com/data/news/attachments/entry/5389/template_expression_not_allowed.png" alt=" " style="width: 461px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5389/template_expression_not_allowed.png">Template Expression not allowed</a></span></span></p>
<p>According to the machines—the screenshot below is DuckDuckGo, which is based on ChatGPT by default—it will cheerily tell you that you can totally do exactly what you clearly can&rsquo;t do.</p>
<p><span style="width: 656px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/5389/ai_thinks_prameters_can_reference_each_other.png" alt=" " style="width: 656px"></span><span class="auto-content-caption">AI thinks parameters can reference each other</span></span></p>
<p>This is the <a href="https://thecloudtheory.github.io/posts/handling-default-parameter-value-in-azure-devops/">cloud theory link</a> referenced in the screenshot. There&rsquo;s nothing in there that has anything to do with the question or its answer. The post is about Azure pipelines but it&rsquo;s a pretty banal article that explains the basics and it will utterly waste your time if you were looking for a definitive answer on how to reference parameters from one another, as the LLM claims is possible.</p>
<blockquote class="quote pullquote align-right right" style="width: 12em"><div><p>The best-case scenario is a <em>mediocre</em> solution that works.</p>
<p>The worst-case scenario is a productive-looking rabbit-hole that leads nowhere.</p>
</div></blockquote><p>This is my worry about this whole LLM-based tool thing: it&rsquo;s wasting people&rsquo;s time and making them inefficient. The best-case scenario is if it manages to give them a <em>mediocre</em> solution that works. The worst-case scenario is that they get routed down a productive-looking rabbit-hole that leads nowhere but which they can then claim that had been productive because they&rsquo;d been doing &ldquo;work&rdquo; and who can blame them if it was the LLM that started them on that path?</p>
<p>How do you fix this for real? You use the solution that I came up with after quickly learning from <a href="https://github.com/microsoft/azure-pipelines-agent/issues/2737">Allow parameter defaults to be calculated based on other parameters #2737</a> on GitHub that the feature I was looking for had never been implemented.</p>
<p>I used a variable and <a href="https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops#coalesce">coalesce</a>, as shown below.</p>
<pre class=" "><code>variables:
    defaultOutputPath: '${{parameters.SolutionFolder}}/Output'
    templateOutputFolder: ${{ coalesce(parameters.OutputFolder, defaultOutputPath) }}</code></pre><p>Curious, though, I went to Copilot to find out what it would suggest (assuming that Copilot is a bit more advanced than the default ChatGPT used by DuckDuckGo). As usual, it returned a lot of boilerplate text that may or may not have actually corresponded to the code it provided. I didn&rsquo;t bother reading most of it and just kept the code examples.</p>
<div class="chart"><h3 class="chart-title">🧐 1️⃣ prompt</h3><div class="chart-body">azure yaml use parameter in default for another parameter</div></div><div class="chart"><h3 class="chart-title">🤖 1️⃣ answer</h3><div class="chart-body"><pre class=" "><code>parameters:
  − name: repositoryName
    type: string
    default: ''

  − name: sonarQubeProjectKey
    type: string
    default: ''

jobs:
  − job: SetDefaults
    steps:
      − script: |
          echo "##vso[task.setvariable variable=sonarQubeProjectKey]com.company.${{ parameters.repositoryName }}"
        displayName: 'Set SonarQube Project Key'</code></pre></div></div><p>This is an impenetrable and unmaintainable disaster that uses a script to write a variable to the job&rsquo;s terminal, which also sets it in the pipeline environment as a side-effect. Why would you do it that way when you just need a local variable? I already know what the solution is, so I know that I can keep prompting instead of wasting my time trying out this version, which I think might work but which is <em>not elegant, legible, or particularly maintainable.</em>.</p>
<div class=" align-right right" style="font-size: 500%">🎰</div><p>That&rsquo;s the advantage of being a senior developer: I will know a good answer when I see it, so the LLM can save me time as I pull the slot-machine arm until it comes up sevens.</p>
<p>In the brusque style I typically use with LLMs, I pressed on.</p>
<div class="chart"><h3 class="chart-title">🤨 2️⃣ prompt</h3><div class="chart-body">Not even close. Try harder.</div></div><div class="chart"><h3 class="chart-title">🤖 2️⃣ answer</h3><div class="chart-body"><pre class=" "><code>parameters:
  − name: repositoryName
    type: string
    default: 'default-repo'

  − name: sonarQubeProjectKey
    type: string
    default: ''

variables:
  − name: sonarQubeProjectKey
    value: ${{ parameters.sonarQubeProjectKey != '' &amp;&amp; parameters.sonarQubeProjectKey || 'com.company.' + parameters.repositoryName }}

jobs:
  − job: Build
    steps:
      − script: |
          echo "SonarQube Project Key: $(sonarQubeProjectKey)"
        displayName: 'Display SonarQube Project Key'</code></pre></div></div><p>That&rsquo;s a bit better. Now there&rsquo;s a variable declaration, even though it still uses the unfortunate old-style name/value syntax that is not super-intuitive. It also uses a bizarre bastardization of the <code>||</code> operator to <em>coalesce</em> to a default value if it&rsquo;s not set. I&rsquo;m not an expert on pipeline-expression syntax but the placement of the <code>&amp;&amp;</code> looks pretty wonky.</p>
<p>As with the first answer, I didn&rsquo;t even bother trying to see if that one-liner mess even compiles, to say nothing of getting me what I want. Even if it works, it&rsquo;s an impenetrable and unmaintainable line that no-one will ever dare touch again.</p>
<p>Since I already knew the answer, I told it straight-up how I wanted it to write the expression.</p>
<div class="chart"><h3 class="chart-title">😒 3️⃣ prompt</h3><div class="chart-body">Use coalesce</div></div><div class="chart"><h3 class="chart-title">🤖 2️⃣ answer</h3><div class="chart-body"><pre class=" "><code>parameters:
  − name: repositoryName
    type: string
    default: 'default-repo'

  − name: sonarQubeProjectKey
    type: string
    default: ''

variables:
  sonarQubeProjectKey: $[coalesce(parameters.sonarQubeProjectKey, 'com.company.' + parameters.repositoryName)]

jobs:
  − job: Build
    steps:
      − script: |
          echo "SonarQube Project Key: $(sonarQubeProjectKey)"
        displayName: 'Display SonarQube Project Key'</code></pre></div></div><p>It&rsquo;s unclear why it&rsquo;s using <a href="https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&amp;tabs=yaml%2Cbatch#runtime-expression-syntax">Runtime expression syntax</a> instead of the more-standard <a href="https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&amp;tabs=yaml%2Cbatch#macro-syntax-variables">Macro syntax variables</a>. It doesn&rsquo;t matter, though because, according to the documentation (and as far I knew already), you have to use the <a href="https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&amp;tabs=yaml%2Cbatch#template-expression-syntax">Template expression syntax</a> when referencing template parameters (which we most certainly are—it&rsquo;s right there in the question).</p>
<p>Is it complicated that there&rsquo;s a table as well as a section called <a href="https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&amp;tabs=yaml%2Cbatch#what-syntax-should-i-use">What syntax should I use?</a> that explains which form to use where and what to watch out for? Yes, it is. But I don&rsquo;t make the rules. I just play by them. </p>
<blockquote class="quote pullquote align-left left" style="width: 10em"><div>The tool of the future that you&rsquo;re a fool and knave for not using because junior devs super-powered by it will blow by your ancient ass if you don&rsquo;t learn how to use it</div></blockquote><p>Copilot, on the hand, is not constrained by petty rules, and would have cheerily helped a less-savvy developer piss away an entire afternoon if not a couple of days chasing phantom errors, trying desperately to get the code produced by the <em>genius machine</em> to work as advertised. The thing about pipeline scripts is…you have to execute them in the cloud. The turnaround time is murder.</p>
<p>Let&rsquo;s take a quick peek at my version, the one I had before we starting playing around with <em>the tool of the future that you&rsquo;re a fool and knave for not using because junior devs super-powered by it will blow by your ancient ass if you don&rsquo;t learn how to use it</em>.</p>
<pre class=" "><code>variables:
    defaultOutputPath: '${{parameters.SolutionFolder}}/Output'
    templateOutputFolder: ${{ coalesce(parameters.OutputFolder, defaultOutputPath) }}</code></pre><p>Succinct, easy to read, with useful variable names. Easy, peasy, lemon-squeezy. Also, it works! That sets it apart from the Copilot suggestions above.</p>
<p>The only trouble I had in the PR was that my reviewer didn&rsquo;t know what the coalesce function did…and the <a href="https://dict.leo.org/german-english/coalesce?side=both">top German translation</a> was for <em>Verbinden</em>, which means to link, tie, or join. That meant he thought it was a synonym for <code>concatenate</code>, which it most certainly is not. It was a good learning opportunity, where I reminded him of the <code>coalesce</code> function in SQL, as well as the <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator">null-coalescing operators</a>—<code>??</code> and <code>??=</code>—in C#.</p>
<p>Look, the world is complicated, human languages and creations are messy, and a  glorified <a href="https://en.wikipedia.org/wiki/List_of_The_Price_Is_Right_pricing_games#Plinko">Plinko machine</a> like an LLM doesn&rsquo;t seem quite yet cut out for helping us navigate it.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5370</guid>
    <title><![CDATA[Building sites with HTML and CSS]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5370</link>
    <pubDate>Sat, 15 Feb 2025 23:00:21 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Feb 2025 23:00:21 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This is a 40-minute discussion about the combining the latest technologies, like scroll-snapping, scroll-driven animations, anchoring, etc. to produce responsive, progressive, animated, modern, and very fast sites without any JavaScript at all. </p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/kOwLG3Nc5eM" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=kOwLG3Nc5eM">Pure CSS Scroll Spy Table of contents − No JavaScript Required!</a> by <cite>Kevin Powell &amp; Adam Argyle</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<h2>Carousels</h2><p>Adam uses it all to build carousels, which is fine for demos and proving the power of the technologies, but … I&rsquo;m not a fan. While our two hosts mention that Netflix comprises <em>only</em> carousels, they don&rsquo;t really discuss that Netflix is also a deeply unsatisfying experience for finding content.</p>
<h2>Slow adoption rate</h2><p><a href="https://www.earthli.com/data/news/attachments/entry/5370/css.png"><img src="https://www.earthli.com/data/news/attachments/entry/5370/css_tn.png" alt=" " class=" align-right"></a>They finish up with an interesting discussion of how quickly changes are introduced and the absolutely legitimate reasons why adoption of some features is so slow. It&rsquo;s often difficult for developers to be aware that a feature exists and also to be aware that it would be a solution for the problem that they&rsquo;re having. There&rsquo;s also the fact that most developers and product owners will allow the scope of the familiar to limit their vision of what is possible.</p>
<p>You really need people who stay on top of these things and can say that yes, it is possible to animate this now, or it is possible to eliminate a ton of cruft here, and also to be aware of whether that feature is available on all target platforms, or whether it can be made optional with progressive enhancement, or … it&rsquo;s a very complicated, complex thing to handle. It takes years before a feature is just known and accepted. Often, it takes a new generation of programmers who&rsquo;ve grown up with that feature to know how to use it.</p>
<h2>Forget about yesterday&rsquo;s cruft!</h2><p>Just think: today, you can build responsive, progressive, fast, pretty, and accessible web sites with no layout hacks and no JavaScript. Everything just works. But you haven&rsquo;t always been able to do that, so there is a large percentage of the web-developer community that is not aware that this is the case because they stopped paying attention a while ago and are stuck on the feature set that they know.</p>
<p>At best, they&rsquo;re aware that a feature exists but wasn&rsquo;t ready for primetime when they last checked, even though they&rsquo;ve not checked in a while. Even if they&rsquo;re aware of it, they might not have the time or budget to use it in existing projects, where everything has already been tested. Who&rsquo;s going to risk ripping out a ton of custom code to replace it with two lines of CSS, when you have to test everything all over again?</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5283</guid>
    <title><![CDATA[A roundup of .NET 9 release videos]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5283</link>
    <pubDate>Sat, 15 Feb 2025 21:48:49 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Feb 2025 21:48:49 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Apr 2025 11:18:08 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In November of 2024, Microsoft released a <em>lot</em> of videos about .NET to accompany the release of .NET 9. I watched/listened to a <em>lot</em> of these, with varying levels of attention paid. When something caught my attention, I took notes. These videos are roughly in the other than I watched them, although I reserved the right to shuffle them about a bit to improve grouping.</p>
<dl><dt class="field"><a href="#ai">AI</a></dt>
<dd><ol>
<li><a href="#sanderson">AI Building Blocks − A new, unified AI layer by Steve Sanderson</a></li>
<li><a href="#Discover">Discover the Latest GitHub Copilot Features for .NET Developers in Visual Studio</a></li>
<li><a href="#Building">Building and scaling cloud-native, intelligent applications on Azure and .NET</a></li></ol></dd>
<dt class="field"><a href="#aspire-section">Aspire</a></dt>
<dd><ol>
<li><a href="#Aspire">What&rsquo;s new in .NET Aspire</a></li></ol></dd>
<dt class="field"><a href="#asp-section">ASP.NET</a></dt>
<dd><ol>
<li><a href="#Bulletproof">Bulletproof ASP.NET Core APIs: The OWASP API Security Top Ten</a></li>
<li><a href="#Blazor">What&rsquo;s New for ASP.NET Core &amp; Blazor in .NET 9</a></li>
<li><a href="#Exploring">Exploring the New Fluent UI Blazor Library: Next-Gen Web Components and Architectural Innovations</a></li>
<li><a href="#I">I Confronted Microsoft About Blazor&rsquo;s Future</a></li>
<li><a href="#HybridCache">Introducing HybridCache in ASP.NET Core</a></li>
<li><a href="#Redis">Easily Improve Web Application Performance using .NET 9 Caching and Redis</a></li>
<li><a href="#Clean">Clean Architecture with ASP.NET Core 9</a></li>
<li><a href="#New">New tools in Visual Studio for Web API developers</a></li></ol></dd>
<dt class="field"><a href="#desktop-section">Desktop</a></dt>
<dd><ol>
<li><a href="#Modern">Modern WinForms Development with .NET 9</a></li>
<li><a href="#MVVM">MVVM Building Blocks for WinUI and WPF Development</a></li>
<li><a href="#How">How Fidelity uses .NET MAUI for Cross-platform desktop</a></li>
<li><a href="#Cross">Cross-Platform Magic: Transforming WPF Apps with Avalonia XPF</a></li></ol></dd>
<dt class="field"><a href="#general-section">General</a></dt>
<dd><ol>
<li><a href="#Advanced">Advanced Pattern Matching in C#</a></li>
<li><a href="#Testing">Testing.Platform, the new way to run .NET tests</a></li>
<li><a href="#Modernising">Modernising Legacy .NET Codebases with NDepend</a></li>
<li><a href="#F">F# − Nullable Reference Types</a></li>
<li><a href="#Embedding">Embedding Python libraries in .NET services and applications</a></li></ol></dd>
</dl><h2 id="ai">AI</h2><p><span style="width: 560px; display: table" id="sanderson"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/qcp6ufe_XYo" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=qcp6ufe_XYo">AI Building Blocks − A new, unified AI layer</a> by <cite>Steve Sanderson</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The API looks very approachable and straightforward to use. I wish that they would stop papering over the inaccurate responses, though.</p>
<p>At about <strong>17;45</strong>, he writes that the additional pair of socks has been added to the cart and that it&rsquo;s <span class="quote-inline">&ldquo;gone up in the way that it should.&rdquo;</span> Except that&rsquo;s not what the response showed. The response showed the total number of pairs of socks in the cart, yes, but it showed the price only for the additional pair of socks that was added in the last step. It noted that this was the case but it was quite confusing to show the total number of items in the cart and then write <span class="quote-inline">&ldquo;the total price for that pair is&rdquo;</span>, which would confuse a reader into thinking that it was the total for the cart, unless they read carefully. Using language like &ldquo;total&rdquo; for a single item is confusing, if not misleading.</p>
<p>This is the kind of stuff that would ordinarily be cleaned up in a final product but it&rsquo;s doubtful that this kind of stuff will be cleaned up in AI-generated prototypes that are scaled up to production, especially since people that will know how to fix it might become rarer. It will be deemed &ldquo;good enough&rdquo; and the inexorable erosion of software quality will continue.</p>
<p>Also, Sanderson had GitHub Copilot running during the entire demo and he pretty much completely ignored all of its suggestions, choosing instead to copy/paste pre-written snippets. This is fine, of course! It&rsquo;s just that, … why didn&rsquo;t he just turn off the annoying prompts that constantly plastered completely irrelevant information into his video? It was quite distracting.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="Discover"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/iYDRmh5-D7U" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=iYDRmh5-D7U">Discover the Latest GitHub Copilot Features for .NET Developers in Visual Studio</a> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>I suppose this is future of programming? In this video, you can watch a young person ask an AI to add <code>usings</code> because you have no idea what they are and don&rsquo;t know that the IDE could just add them for you automatically. She described everything as <span class="quote-inline">&ldquo;awesome&rdquo;</span> and thought that the interaction loop was super-intuitive and easy to use, as she typed out natural-language command after natural-language command to try to get the machine to do what a programmer could have done in seconds with analysis-based tools.</p>
<p>I suppose if you want to program without knowing anything about the technologies, then this is probably going to get you a little bit further. Maybe. It was pretty painful to watch, though, like someone claiming that they were building a house by throwing wood at bags of cement and hoping for the best.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="Building"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/LFQ0qCiKL_Y" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=LFQ0qCiKL_Y">Building and scaling cloud-native, intelligent applications on Azure and .NET</a> by <cite>dotnet | Scott Hunter &amp; Paul Yuknewicz</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This is a longer presentation—almost an hour—that goes in-depth on converting an ASP.Net Web application first to an <em>Azure Function</em>, and then adding a .NET Aspire Host project to not only coordinate communication between the front-end client and the <em>Function</em> project, but also to facilitate deployment directly to a <em>Cloud Container</em>.</p>
<p>Hunter explains the different between <code>WithReference()</code>, which indicates that a service depends on another service being started and <code>WaitFor()</code>, which extends the reference to indicate that a service should <em>wait</em> until a health-check of its dependency indicates success before declaring itself available. If you think about it, almost all references are important in his way, but .NET Aspire still makes the distinction to give your app flexibility in starting up. If you have two service that depend on each other, they can&rsquo;t each wait for each other, or you might be a deadlock (unless the health-check can return success before the service itself is ready).</p>
<p>On top of that, there is a method called <code>WithExternalHttpEndpoints()</code>, which they describe as <span class="quote-inline">&ldquo;doing the right thing&rdquo;</span> and setting up a virtual private network in the cloud container so that only the web client has access to the Azure Function endpoint. <span class="quote-inline">&ldquo;It&rsquo;s network-isolated by default, which is one of the features of container apps, which is the default way of publishing in an Aspire application.&rdquo;</span> This is very cool and seems a lot easier than writing a bunch of custom Bicep code.</p>
<p>The web client can now access the Azure Function at the alias that it assigned in the .NET Aspire host project&rsquo;s configuration. That configuration is all written in C#, with a nice fluent API. I&rsquo;m a little disappointed that they don&rsquo;t use a shared C# constant to reference the unique strings, but nobody in any of the .NET Aspire demos seems to do that, preferring to ride the ragged edge of disaster with copy/pasted identifiers.</p>
<p>Getting back to the demo: He shows how it&rsquo;s published to Azure, using <em>Managed Identity</em>. The .NET Aspire dashboard shows the remote resources with full logging available, also available and published to Azure. It&rsquo;s the same dashboard as you would use locally.</p>
<p>Everything they demonstrated is available in several solutions, all listed in <a href="https://gist.github.com/paulyuk/316cf37d31c08ddb6df38e905c0b3d76">Samples for Building and Deploying Cloud Native Intelligent Apps</a> by <cite>Paul Yuknewicz</cite> (<cite><a href="http://gist.github.com/">GitHub Gist</a></cite>).</p>
<p>They say, <span class="quote-inline">&ldquo;All you do is clone the repo, and then you do <code>azd init</code> and <code>azd up</code> and they&rsquo;re super-easy to get in the cloud and try yourself.&rdquo;</span> It will deploy the resources into your subscription and region of choice. There are <em>detailed</em> instructions for each example, e.g., <a href="https://github.com/Azure-Samples/azure-functions-openai-aisearch-dotnet">azure-functions-openai-aisearch-dotnet</a> (RAG example).</p>
<p>Paul goes into this example in more detail, examining the Bicep scripts (which I&rsquo;m not sure whether they&rsquo;re hand-written or generated by .NET Aspire). They cover how to build an embedding for RAG and how much support there is in .NET now for making this kind of thing easy. They use a standard HTTP body as input but discuss many other potential input streams (queues, etc.), all of which are just as easily supported by default.</p>
<p>I learned that &ldquo;agenting&rdquo; is just the cool new term for allowing an LLM to use &ldquo;tools&rdquo;. It&rsquo;s also called &ldquo;skilling&rdquo; (adding &ldquo;skills&rdquo;). The most approachable epithet is the least-cool-sounding one: &ldquo;function-calling&rdquo;, which at least explains what it does. So &ldquo;agenting&rdquo; is empowering an LLM to execute tools in order to enhance results.</p>
<p>Like many of the other videos, they use the <a href="https://learn.microsoft.com/en-us/aspnet/core/test/http-files?view=aspnetcore-9.0">.http Files</a> feature to store recipes of calls to make against an HTTP server.</p>
<p>When their demo doesn&rsquo;t initially work, you see how Microsoft also has a locked-down network that they have to work around. They very smoothly transitioned to Scott discussing security initiatives that Microsoft has taken and is taking to lock things down by default for new applications, including those generated by customers. Secure by default. They then smoothly transition back to the demo, for which Paul has reset his network to a working state. Nice job.</p>
<p>The funny thing about some of these demos, though, is that they used an LLM to find out what time it is in New York City…and everyone held their breath to see if it would get it right. It took about 10 seconds to figure it out. That&rsquo;s laughable on its face, but the point is that it&rsquo;s now quite easy to set up a powerful tool to round-trip to an LLM running securely in Azure, built with access to custom functions (agenting) and custom data (RAG). Subsequent demos are more impressive.</p>
<p>At <strong>40:00</strong>, Paul addresses why it&rsquo;s interesting to solve problems in this way: you can scale up quickly to much higher data volumes without changing the architecture or implementation at all. This is great but you want to remember the aphorisms, &ldquo;you&rsquo;re not Google&rdquo; and &ldquo;you don&rsquo;t have big data.&rdquo; In this case, though, an argument can be made that these technologies are the right way to build it when its small <em>and</em> when its large. The support and abstractions are good enough that you don&rsquo;t have to choose a a non-scalable solution early in the process to save money.</p>
<p>On the subject of ignoring warnings in code, though, Paul had a typo in the word &ldquo;cacluated&rdquo; that Visual Studio showed him and he <em>still</em> hadn&rsquo;t bothered to quick-fix it, even though the entire world would be seeing it.</p>
<p>The final example is showing how to use a &ldquo;blog trigger&rdquo;, which is a function that reacts when new data is added to an Azure blob container. When you drop a PDF into it, it uses standard, available recognition tools to analyze the document and then funnel that content to the LLM (which is not great at &ldquo;cracking&rdquo; PDFs provided as context on its own). These dependent tasks are captured as &ldquo;activities&rdquo;, which are composed as part of a &ldquo;durable function&rdquo;, which is essentially a high-level abstraction on top of potentially distributed calls.</p>
<p>This is the part that Paul called &ldquo;orchestration&rdquo; at the beginning of this section. It&rsquo;s not orchestration like Kubernetes (although possibly related, way down at the low level), it&rsquo;s orchestration of high-level activities and representing them as a single function call that takes an indeterminate amount of time. Paul demonstrates how much tooling and web-based observability there is available for debugging and monitoring solutions.</p>
<blockquote class="quote quote-block "><div>&ldquo;Again, this is Functions, so you can do this at scale. You can send <em>million</em> of documents.&rdquo;</div></blockquote><p>It just costs money, but you&rsquo;re not otherwise limited by the architecture if you build it with these concepts, this architecture, and these building blocks.</p>
<h2 id="aspire-section">Aspire</h2><p><span style="width: 560px; display: table" id="Aspire"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/fiePiEc1qcU" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=fiePiEc1qcU">What&#039;s new in .NET Aspire</a> by <cite>Damian Edwards and Maddy Montaquila</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This addition to the .NET ecosystem continues to impress me. While this video demonstrates only .NET Aspire, the previous video (<a href="#Building">Building and scaling cloud-native, intelligent applications on Azure and .NET</a>) also made heavy use of Aspire. Many of the videos would include Aspire, actually.</p>
<h2 id="asp-section">ASP.NET</h2><p><span style="width: 560px; display: table" id="Bulletproof"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/ZDIB0uYHDBU" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=ZDIB0uYHDBU">Bulletproof ASP.NET Core APIs: The OWASP API Security Top Ten</a> by <cite>dotnet / Christian Wenz</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This is a very useful introduction to common security issues and how to address them. He talks about how to program by default so that the issues never come up.</p>
<p>At around <strong>19:00</strong>, he even discusses how to build a threat model. He kind of backs into describing it by talking about the types of risks for which you might need processual mitigations. That is, the threat model talks about something like &ldquo;the system allows a single user to book multiple seats for themselves on a plane&rdquo; and then talks about (A) whether you even want to mitigate this and (B) which kinds of mitigations would work against it.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="Blazor"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/2xXc1hNwp0o" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=2xXc1hNwp0o">What&#039;s New for ASP.NET Core &amp; Blazor in .NET 9</a> by <cite>dotnet / Daniel Roth</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This was pretty informative, overall. I wish he&rsquo;d spent a bit more time on <code>HybridCache</code>, which seems like a big win.</p>
<p>Oh, hey, look at that: there&rsquo;s a video for it, called <a href="#HybridCache">Introducing HybridCache in ASP.NET Core</a>.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="Exploring"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/w8BKS1a8MnU" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=w8BKS1a8MnU">Exploring the New Fluent UI Blazor Library: Next-Gen Web Components and Architectural Innovations</a> by <cite>dotnet / Vincent Baaij &amp; Denis Voituron</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This library is quite nice and seems to offer a good basis on which to start projects. It&rsquo;s interesting, though, how people just <em>say</em> things that they&rsquo;ve heard. Denis said at one point that Playwright will be integrated soon in order to improve &ldquo;code quality&rdquo;, which is absolutely not what tests do. Tests do the second thing he mentioned: &ldquo;avoid regression.&rdquo; If you have tests, your code can be any old quality. The tests don&rsquo;t care, as long as they&rsquo;re green.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="I"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/2uLGXe95kTo" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=2uLGXe95kTo">I Confronted Microsoft About Blazor&#039;s Future</a> by <cite>Nick Chapsas &amp; Daniel Roth</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>I mean, honestly, can you just write &ldquo;interviewed&rdquo; instead of &ldquo;confronted&rdquo;? Do we really have to write everything as if it were a title in a Fleet Street broadsheet? It&rsquo;s a friendly interview.</p>
<ul>
<li>They discussed the difference between .NET LTS and non-LTS versions. There is no difference in quality.</li>
<li><strong>Why wasn&rsquo;t there so much Blazor news this year?</strong> The .NET 8 release was so huge that they spent a lot of time in the first half of the year after the release simply stabilizing that release, and then focused on quality improvements in .NET 9. There is a big feature that consolidates the different ways of using Blazor into a more uniform concept.</li>
<li><strong>Who&rsquo;s using Blazor?</strong> How big is it? Year-over-year growth is high but the overall usage numbers are still kind of low, relative to other frameworks, like the by-now ancient WebForms, ASP.Net MVC, ASP.Net Core, etc.</li>
<li><strong>Is Blazor going to go the way of Silverlight?</strong> No, it&rsquo;s the recommended way to develop web sites on .NET. Nick gave a good intro here, talking about how good WebForms actually was—taking aside <code>ViewState</code>—but that frameworks like Next.JS are still re-inventing what WebForms had already offered and pawning it off as a revelation. It&rsquo;s kind of how most of the server-side frameworks now just look like PHP.</li>
<li><div>.NET Aspire has a super-short support cycle; it goes obsolete with the first point release. You have to upgrade it rather aggressively to stay in-support. It&rsquo;s not part of the .NET release. It&rsquo;s out-of-band. It&rsquo;s super-useful but it&rsquo;s a bunch of tools and wiring without much of its own API. It makes sense to keep support cycles short because, while it&rsquo;s been released for others because it&rsquo;s so damned useful, it&rsquo;s also acknowledged that the surface will potentially change quite a bit as more and more real-world use cases appear.<div class=" "><p><strong>Why do we even need Blazor?</strong> Microsoft isn&rsquo;t using it anywhere, is it? The problem that Blazor solves is trying to build a web site with a team that doesn&rsquo;t know any of the languages, tooling, or paradigms of front-end development. For the vast majority of web sites, you really don&rsquo;t need full-fledged React or Angular or Svelte. While there are developers who can legitimately live in both worlds, Blazor is for those for whom a good web site is good enough.</p>
<p>You can make anything in Blazor, of course, but it really helps you get to a standard, good-enough view (especially with Blazor Fluent UI) that covers so much of the software being built. Roth describes how the client-side world is such a different beast and that spinning developers up to be productive and happy in that world takes a lot of time, money, and resources.</p>
<p>It&rsquo;s a fair point. Many people just can&rsquo;t wrap their heads around that style of development. It&rsquo;s too alien to them. I would venture to say that most web developers aren&rsquo;t very good at software-development, don&rsquo;t really understand the environment or their tools, and are just cargo-culting their way to freedom and happiness.</p>
<p>It&rsquo;s why we&rsquo;ve had so many RAD dev environments, it&rsquo;s why we have so many frameworks. Even after a good 20 years of development churn, things are still churning. There is almost no consensus on how to address the plethora of non-functional requirements in clients: accessibility, compatibility, graceful degradation, progressive enhancement, etc. The best philosophy seems to be PWA and probably an MPA not an SPA for <em>apps</em>, which is not most web sites. Most web sites are mostly static. So the common web frameworks are ill-suited to those kinds of pages. Etc. Etc. <span class="quote-inline">&ldquo;Blazor lets me get more with less. I can&rsquo;t afford to hire a full-time front-end developer.&rdquo;</span></p>
</div></div></li>
<li><strong>Why is .NET trying to do everything?</strong> Isn&rsquo;t that a recipe for being mediocre in most things? <span class="quote-inline">&ldquo;I think it&rsquo;s fair to say that there are parts of the .NET stack that have … more strengths than other parts.&rdquo;</span> I think that there&rsquo;s a real need at Microsoft for doing a lot of things in all areas. MS needs to develop web sites, needs to develop mobile apps, needs to develop cloud-based apps, etc. They&rsquo;re going to develop at this scale anyway. We can be happy that this workman&rsquo;s version of these tools are available, and cross-platform. Apple makes some amazing technology that only works on their hardware and on their systems and they don&rsquo;t have a cloud. .NET runs on AWS, GCP, Azure, etc. .NET runs on ARM, x86, Linux, Windows, MacOS, etc. The base library is incredibly well-designed.</li>
<li><strong>How big is the Blazor team?</strong> There are six full-time devs. It sits atop other parts, like SignalR, which has two full-time devs. The actual framework is six engineers. He mentions that the community does some heavy-lifting here as well.</li>
<li><strong>Who&rsquo;s using Blazor?</strong> Roth mentions some customers, and then talks about how it&rsquo;s used in a lot of places internally at Microsoft. They don&rsquo;t use Blazor for Teams, Office365, large customer-facing products. Those use React. A lot of that is historical, because Blazor has only been around for 5 years. They used to use Script#, which was a transpiler for C# to JavaScript, but then they moved to React. A ton of the recent, internal LOB-style products use Blazor. That&rsquo;s what it&rsquo;s for. Smaller teams use Blazor and there are thousands of devs who use Blazor at Microsoft.</li>
<li><div class=" "><p><strong>Is there anything public-facing that uses Blazor?</strong> Very little. The Aspire Dashboard is one of the only things. Part of that reason is <span class="quote-inline">&ldquo;technology fit&rdquo;</span>. Blazor is very good for internal LOB that runs on a known set of devices and capabilities. Think Office, though: they need to be able to run on anything. That&rsquo;s a completely different proposition because it constrains you more. You need more control of the stack. A high-level solution like Blazor doesn&rsquo;t save you time there; it costs you time. For products that need to be optimized in terms of download-size and speed, etc., then you probably should use JavaScript directly. </p>
<p>They recommend Blazor if it fits your scenarios. Otherwise, use ASP.Net Core with a JS front-end. He made the comparison to using Node on the server. It&rsquo;s not the optimal thing for performance, but it might match your team best. But you can scale the server-side with money. You can&rsquo;t scale the client-side.</p>
<p>Roth agrees: if you have millisecond-initial-download constraints, then Blazor isn&rsquo;t for you. He does say that you&rsquo;d be surprised how many apps <em>aren&rsquo;t</em> like that. </p>
<p>I&rsquo;m not surprised. He says that even the heavyweight Blazor server model, which is basically PHP-style, if we&rsquo;re honest, then you can support dozens of thousands of concurrent users on a single, modestly sized VM. Most apps have expectations of hundreds of concurrent users, at most. Being server-based will restrict your interactivity if you rely on it too much with server-based stuff. For forms and LOB, though? It&rsquo;s <em>fine</em>. You&rsquo;re not Facebook. Relax.</p>
</div></li>
<li><strong>How many people use the web-assembly stuff instead?</strong> Quite a few, actually. The server-side Blazor is slightly more popular, though. They&rsquo;re both growing at about the same speed. .NET 10 plans to invest more in the server-side version. They need to solve some problems about server-side state: hydration strategies for longer-lived processes and workflows.</li>
<li><strong>What if you had to make an app for millions of users?</strong> If it&rsquo;s B2B or LOB, then consider Blazor. Start with Server-side, then move to interactive server-rendering on the client, move to WASM-based to push individual islands to the client where necessary. If it&rsquo;s customer-facing, then it&rsquo;s going to be .NET on the backend and a JavaScript front-end (he doesn&rsquo;t say &ldquo;React&rdquo;, notably). I think MS engineers are also seeing the value in writing to the web platform, using JavaScript. He doesn&rsquo;t even say TypeScript, because they&rsquo;re so close these days. It would be amazing if browsers allowed the syntax directly so we didn&rsquo;t have to transpile anymore. There&rsquo;s a <a href="https://github.com/tc39/proposal-type-annotations">proposal</a> for this.</li>
<li><strong>Yeah, but which platform would you use if you couldn&rsquo;t use Blazor?</strong> TypeScript because static typing is awesome. He mentioned that the Angular 18 release was <span class="quote-inline">&ldquo;pretty compelling&rdquo;</span>. I personally looked into it based on this and couldn&rsquo;t figure out what he was talking about; it looked like an incremental upgrade to me.</li>
<li><div class=" "><p>Daniel asked <strong>what about server-side rendering?</strong> Would you look at Next.JS? SSR? Server-side components? Nick says Next.JS but I don&rsquo;t agree. I think their solutions, just like Remix, about which I&rsquo;ve also read quite a bit. Their solutions get … complicated at scale, with their attempts to paper over the difference between client and server parts without being forced to know where anything is running tending to be quite leaky abstractions. I&rsquo;ve read quite a bit about Remix and Next.JS and, in both of those, I&rsquo;ve seen where cracks show that people deeply familiar with the technology think &ldquo;aren&rsquo;t so bad&rdquo; but that&rsquo;s only because they know that it <em>used to be so much worse.</em></p>
<p>Daniel says <span class="quote-inline">&ldquo;Look around at what is going to be around for a while. Everybody has to plan for the longevity of their career.&rdquo;</span> This is so sad, though. We don&rsquo;t get anything great from people &ldquo;planning for the longevity of their career.&rdquo; We get cool things from people who just can&rsquo;t help but try to make something better, to make something cool, to make something to help themselves, that interests them.</p>
<p>Dude, React is a hype. Most people are using it poorly. You get to leaky abstractions in the first two days of teaching, where you have to tell people how to avoid horrible performance with <code>useMemo()</code> and <code>useCallback()</code>. They&rsquo;re working on a compiled version of React, which is just where <em>Svelte</em> has always been.</p>
</div></li>
<li><div class=" "><p><strong>What&rsquo;s next for Blazor?</strong> Roth talks about SSR a lot. Interaction between SSR and client-side, etc. Performance and caching. I think Blazor will be a better, more well-thought-out and much less ad-hoc approach to SSR than Next.JS and Remix have gotten.</p>
<p>Why? Because the people that Microsoft has and the culture that they have tend to produce really good APIs. That&rsquo;s just a fact. Multi-threading feature is on the radar again. They&rsquo;re going to try again, but it&rsquo;s not committed yet. Security is the #1 push right now, though. So if Blazor has work to do there, then that takes priority. This will result in a more secure stack for users of Blazor as well.</p>
</div></li>
<li><strong>If you had to work with a different back-end language, what would you use?</strong> Daniel responded <span class="quote-inline">&ldquo;Python&rdquo;</span>. Nick said <span class="quote-inline">&ldquo;Kotlin&rdquo;</span>, which he says is how JetBrains fixed Java by making it C#. I would take another look at Swift, which I haven&rsquo;t used for anything real since version 5. Or maybe finally do something in Rust, just to see where the tooling is at.</li></ul><p><hr></p>
<p><span style="width: 560px; display: table" id="HybridCache"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/rjMfDUP4-eQ" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=rjMfDUP4-eQ">Introducing HybridCache in ASP.NET Core</a> by <cite>dotnet / Marc Gravell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This video covers Redis, HybridCache, and <strong>stampede-protection</strong>.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="Redis"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/vpFz9xJulDk" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=vpFz9xJulDk">Easily Improve Web Application Performance using .NET 9 Caching and Redis</a> by <cite>dotnet / Catherine Wang &amp; Matt Soucoup</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Moar caching. Pretty good.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="Clean"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/zw-ZtB1BNl8" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=zw-ZtB1BNl8">Clean Architecture with ASP.NET Core 9</a> by <cite>dotnet / Steve Smith (ardalis)</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>I follow this guy&rsquo;s blog and find many of his articles to be a bit basic. It feels like he&rsquo;s writing just enough articles to keep his Microsoft MVP badge. In this video, though, he is <em>en fuego</em>, absolutely <em>ripping</em> through a whirlwind introduction to clean architecture, with some demos and some code. You can find the sample projects in <a href="https://github.com/NimblePros/eShopOnWeb">NimblePros / eShopOnWeb</a> (<cite><a href="http://github.com/">GitHub</a></cite>) and <a href="https://github.com/ardalis/CleanArchitecture">ardalis / CleanArchitecture</a> (<cite><a href="http://github.com/">GitHub</a></cite>).</p>
<p>He also very quickly demonstrates how to use the new API window to submit requests to the running server; this replaces external tools like Postman, keeping you within Visual Studio (or Rider, which has supported this for even longer).</p>
<p>In his full-tilt presentation, he also mentions using <a href="https://www.papercut-smtp.com/">Papercut-SMTP</a>, which is <span class="quote-inline">&ldquo;a 2-in-1 quick email viewer AND built-in SMTP server (designed to receive messages only).&rdquo;</span> This is ideal for local devs to test emailing code and can be easily integrated and started with .NET Aspire.</p>
<p>After having generated a solution using his clean-architecture template, he says that <span class="quote-inline">&ldquo;this is the slowest part … opening the new solution in Visual Studio,&rdquo;</span> but this is really unfair because the solution is restoring and doing everything in the background, while he&rsquo;s clicking around in the solution explorer. Previous versions of Visual Studio would never have allowed this. He even launches the product and is browsing around in the Aspire Dashboard and the web server&rsquo;s OpenAPI front-end within seconds. It&rsquo;s an impressive demo.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="New"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/uKm1ho881gk" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=uKm1ho881gk">New tools in Visual Studio for Web API developers</a> by <cite>dotnet / Sayed Ibrahim Hashimi</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Sayed starts off with a good overview of the basics of <a href="https://learn.microsoft.com/en-us/aspnet/core/test/http-files?view=aspnetcore-9.0">.http files</a>, which showed up with .NET 8 and allow you to keep sets of API calls for testing, much in the way that people have been using Postman or Insomnia. The new feature is that .http files can now store values in variables for transferring results from one call to others. He uses Visual Studio but, as I&rsquo;ve noted elsewhere, Rider has supported them for even longer than Visual Studio.</p>
<p>He also shows a not-quite-ready-for-primetime-but-coming-soon feature of Visual Studio called the <em>Endpoints Explorer</em>, which is a sort of Swagger/OpenAPI browser available as a Visual Studio panel.</p>
<h2 id="desktop-section">Desktop</h2><p><span style="width: 560px; display: table" id="Modern"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/1ZjCGdmQl_g" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=1ZjCGdmQl_g">Modern WinForms Development with .NET 9</a> by <cite>dotnet / Merrie McGaw &amp; Klaus Loffelmann</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This was quite an interesting video, in that it really drives home that WinForms is here to stay. The community pushed hard to make a lot of the code base expose and use nullability. Microsoft has also improved performance in <code>System.Drawing</code> and replaced all interop with code generated by <a href="https://github.com/microsoft/CsWin32">CSWin32</a>. There is also improved support on base UI objects for asynchronous calls like <code>Form.ShowAsync</code> and so on. </p>
<p>I like that his demo to show text in a color-mode-aware manner failed because he was creating the brush with the right color but he wasn&rsquo;t assigning it anywhere. How do I know he wasn&rsquo;t using it anywhere? Because Visual Studio had grayed out the instance variable to which he had initialized his brush. He&rsquo;d assigned the brush but hadn&rsquo;t actually assigned it to be used by any control. This is why you configure and then pay attention to the warnings and suggestions in your IDE, folks. It really does help you solve otherwise pretty hairy problems. In this case, I was able to diagnose his problem just from a brief flash of less than a second of him scrolling through his file.</p>
<p>It hurts me so much to watch people click toolbar buttons to comment/uncomment code. Seriously, you&rsquo;re fired.</p>
<p>So, cool video but this guy really shows how outdated some WinForms developers are. 😹</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="MVVM"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/83UVWrfYreU" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=83UVWrfYreU">MVVM Building Blocks for WinUI and WPF Development</a> by <cite>dotnet / Sergio Pedri &amp; XAML Llama</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>I learned that the latest preview version of the MVVM Community toolkit is already using partial properties—which are new to C# 12 in .NET 9—to help you write even less code for your view models. Also, you can use <code>x:Bind</code> instead of <code>x:Binding</code> to have a <em>compile-time</em>, reflection-free binding, which has much better support for code-completion, inspections, etc.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="How"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/kn-nmFsaMHc" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=kn-nmFsaMHc">How Fidelity uses .NET MAUI for Cross-platform desktop</a> by <cite>dotnet / David Ortinau, Matthew Faust, &amp; Kevin Bieri</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This is a pretty impressive demo of what is now possible with Maui. They&rsquo;re using Telerik controls. The neat thing about this Maui app is that it runs on MacOS as well. They talk about WebViews a lot—and painting to the canvas—so it also runs in a browser. He does discuss how using SkiaSharp is a valuable place to seek performance but that you are almost certainly going to make usability or accessibility concessions. Use source generators, not reflection. Interestingly, they mention how you can speed things up with Windows Defender by signing assemblies with &ldquo;HSM methodology&rdquo;, which is something to look into, I think.</p>
<p>I just can&rsquo;t help but think that it isn&rsquo;t any faster or better-looking than the trading app that I was lucky enough to be able to build for Peak6 back in 2010–2013. That one was a multi-threaded Winforms app that connected to a data hose that shoveled tons of data toward the app—dozens to hundreds of thousands of refreshed data rows per second—in dozens of open windows and portals. Each of the grids showed data in grouped, tiered, aggregated, and heat-mapped views. When it really got going, you had 40+ open windows on eight screens, all updating in real-time. Close the app and re-open it and it came right back where  it was. it was very, very colorful.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="Cross"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/v2YnWgiNqL0" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=v2YnWgiNqL0">Cross-Platform Magic: Transforming WPF Apps with Avalonia XPF</a> by <cite>dotnet / Mike James</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This is a great look at Avalonia, which is a very interesting migration path from the Windows-only WPF to a multi-platform approach that doesn&rsquo;t involve rewriting everything in Maui or Blazor.</p>
<p>With Avalonia, you can either port from WPF, primarily changing the styles to use the more CSS-style styling of Avalonia. Because of this feature, though, an Avalonia app can relatively easily be deployed to a web application. He discusses a community project <a href="https://github.com/BAndysc/AvaloniaVisualBasic6">Avalonia Visual Basic 6</a> by <cite>BAndysc</cite> (<cite><a href="http://github.com/">GitHub</a></cite>), which you can <a href="https://bandysc.github.io/AvaloniaVisualBasic6/">browse in a demo</a>.</p>
<p>It runs in a browser, it runs on all desktop platforms—including Linux, which Maui doesn&rsquo;t support.</p>
<p>On top of that, it also supports something called Avalonia XPS, which is a complete replacement for the WPF rendering engine, so you can &ldquo;port&rdquo; an app just by changing the SDK uses in the project files. That&rsquo;s it. He demonstrates it live and it works extremely quickly and seamlessly. Of course, if you have P/Invokes or a lot of custom rendering—or external components that aren&rsquo;t compatible—then you&rsquo;ll have to do more work. But it&rsquo;s a huge step forward to getting WPF apps running on other platforms.</p>
<p>For charts, he mentions that <a href="https://www.scichart.com/">SciChart</a> is the &ldquo;best&rdquo; charting library for WPF and that it is compatible with Avalonia. They use the XPS layer to <a href="https://www.scichart.com/blog/running-scichart-wpf-on-linux-its-possible-heres-how/">provide support for Linux platforms</a>.</p>
<p>His final demo shows a WPF app (the calculator) running with XPS but <em>targeting a web browser</em>. This is wild. I had completely underestimated Avalonia.</p>
<h2 id="general-section">General</h2><p><span style="width: 560px; display: table" id="Advanced"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/W-f9MHB-5TQ" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=W-f9MHB-5TQ">Advanced Pattern Matching in C#</a> by <cite>dotnet / Oli Sturm</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>At about <strong>8:30</strong>, he shows a nice usage of switch expressions with range expressions to make a recursive summing function.</p>
<pre class=" "><code>static int Sum(Span&lt;int&gt; l) =&gt; l switch {
    [] =&gt; 0,
    [var x, .. var xs] =&gt; × + Sum(xs)
};</code></pre><p>Nice!</p>
<p>There were a lot of interesting examples in this video. The final one for refactoring a red-black tree was really cool. It&rsquo;s funny how bad these people are at demos, though. He showed us that he had 513 tests running and passing in 0.5s. Then he says that the passing tests is the only thing that&rsquo;s important. Um, no, it&rsquo;s also important that rebalancing is done in a reasonable amount of time, so we should also keep an eye on the time the tests take with any refactored implementation.</p>
<p>To demonstrate that the tests actually test the code he&rsquo;s going to refactor, he wiped out the enter implementation and re-ran the tests. But they didn&rsquo;t run because he was no longer returning a value from his method, so it didn&rsquo;t even compile. He blew right by that and said &ldquo;see, the tests don&rsquo;t run.&rdquo; Um, no, the program no longer compiles and you haven&rsquo;t proven anything about the connection between the implementation you&rsquo;re going to refactor and the tests.</p>
<p>All that aside, though, it&rsquo;s quite an elegant solution that looks just like the original Haskell code. It&rsquo;s not legible at a glance but is a very succinct representation that uses the standard style for these kinds of things.</p>
<p><span style="width: 612px; display: table" id="Red"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5283/red-black-tree-in-c-sharp.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5283/red-black-tree-in-c-sharp.jpg" alt=" " style="width: 612px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5283/red-black-tree-in-c-sharp.jpg">Red-black tree in C#</a></span></span></p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="Testing"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/9Jz47Ze9LOI" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=9Jz47Ze9LOI">Testing.Platform, the new way to run .NET tests</a> by <cite>dotnet / Jakub Jares</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The Testing.Platform is very nice. It promotes test suites to first-class citizens, built as executable files without any reflection-based assembly-scanning at runtime. Instead, the source generator scans and generates code for running the tests. It also supports a &ldquo;watch&rdquo; mode (called &ldquo;hot reload&rdquo;, of course), which lets you keep the tests running as a separate app. It&rsquo;s much faster and more reliable, it&rsquo;s AOT-friendly, etc. etc.</p>
<p>When it was initially introduced in January of 2024, the only drawback was that you could only use it with MSUnit. That&rsquo;s changed! At <strong>23:00</strong>, he shows how to enable and run NUnit-based and XUnit-based tests with Testing.Platform. I really, really like how MS-based projects like this embrace open and non-Microsoft standards: the testing platform is to replace VSTest, which only ran on Windows. Testing.Platform is platform-agnostic and testing-framework-agnostic, bringing its Reflection-free, AOT-capable, runtime-stable approach for everyone.</p>
<p>He demonstrates running a solution with NUnit, XUnit, and MSUnit tests running as a standalone, collectively with <code>dotnet run</code>, and in <em>Visual Studio</em>. <a href="https://www.jetbrains.com/help/rider/Reference__Options__Tools__Unit_Testing__VSTest.html">Rider / VSTest</a> writes <span class="quote-inline">&ldquo;JetBrains Rider can run tests from any custom test framework that uses VSTest <strong>or Microsoft.Testing.Platform.</strong>&rdquo;</span> <a href="https://www.jetbrains.com/help/resharper/Reference__Options__Tools__Unit_Testing__VSTest.html">ReSharper / VSTest</a> writes <span class="quote-inline">&ldquo;ReSharper can run tests from any custom test framework that uses VSTest <strong>or Microsoft.Testing.Platform.</strong>&rdquo;</span></p>
<p>Good news all around. This thing is ready to be used!</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="Modernising"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/7Qm-6tFSd4Y" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=7Qm-6tFSd4Y">Modernising Legacy .NET Codebases with NDepend</a> by <cite>dotnet / Goh Chun Lin</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>I really like the tool NDepend and I was quite interested to see how Lin used it to upgrade a codebase from .NET Standard 2.1 to target .NET 8, and then .NET 9. He&rsquo;s from Singapore so he was not easy for me to understand—but he definitely knows what he&rsquo;s doing.</p>
<p>This video reminded me of a time about 9-10 years ago when I was really heavily using the tool to modernize the Quino code-base, which had grown quite organically and was proving difficult to use for only web servers, especially those running on Linux. We made our own journey from .NET Framework 4.7.2 to .NET Standard 1.0 (didn&rsquo;t work at all), then to .NET Standard 2.0 (success!). I continued to use the tool for the next five years.</p>
<p>Here is a list of related articles, which I argue go into more depth on how to use NDepend than the video does. NDepend hasn&rsquo;t changed a significant amount in 10 years—it was an incredibly powerful tool then, and it still is. I haven&rsquo;t used it much at my new job at Uster but time will tell.</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=3058">2014: The Road to Quino 2.0: Maintaining architecture with NDepend (part I)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3064">2014: The Road to Quino 2.0: Maintaining architecture with NDepend (part II)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3167">2015: Splitting up assemblies in Quino using NDepend (Part I)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3169">2015: Iterating with NDepend to remove cyclic dependencies (Part II)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3546">2018: The Road to Quino 2.0: Maintaining architecture with NDepend (part I)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3670">2019: Finding deep assembly dependencies</a></li></ul><p><hr></p>
<p><span style="width: 560px; display: table" id="F"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/MPHzwVWKruk" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=MPHzwVWKruk">F# − Nullable Reference Types</a> by <cite>dotnet | Petr &amp; Tom&aacute;&scaron; Gro&scaron;up</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This is by far the nerdiest video in the entire series. It&rsquo;s chock-full of interesting information about F#, with a focus on the new support for <code>null</code>, which it has in order to better interoperate with .NET modules built in other languages that <em>do</em> support <code>null</code>. F# is a functional language and uses <em>options</em>. However, Tomáš demonstrates how this is not sufficient when working with data coming in from outside of the F# system. The feature piggybacks on the <code>|</code>-operator to allow <code>| null</code> in any type definition. </p>
<p>Most of the rest of the presentation shows how the new feature integrates with options, pattern-matching, generic types, etc. There are analyzers in the compiler that help your code shed &ldquo;nullness&rdquo; as soon as possible, leaving most of your F# code without nulls, <em>as God intended.</em></p>
<p>Tomáš calls &ldquo;shadowing&rdquo; a feature, which is being a bit generous. It&rsquo;s a nice trick to declare a &ldquo;new&rdquo; version of the incoming argument that has a type narrowed by a null-check function call. Languages like TypeScript and C# actually have a &ldquo;feature&rdquo; in which the type is narrowed without variable-shadowing. It amounts to the same thing, though. I suppose F#&rsquo;s version is less gimmicky and implicit, but shadowing is frowned upon in so many other places, because it&rsquo;s super-confusing when done inadvertently. Using shadowing to narrow a type is a clear use case but it will also prevent analysis from being able to preclude accidental shadowing.</p>
<p>This video is mostly just an F# tutorial, though. At the end, a guy named Kinfey pops in to tell Tomáš that he better wrap things up. It&rsquo;s quite unprofessional but also quite funny.</p>
<p><hr></p>
<p><span style="width: 560px; display: table" id="Embedding"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/Dk-MPeSxv18" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=Dk-MPeSxv18">Embedding Python libraries in .NET services and applications</a> by <cite>dotnet | Anthony Shaw &amp; Aaron Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>This isn&rsquo;t the most organized demo, and they don&rsquo;t really show how to set things up but it does show how integration of Python into .NET is much simplified by source generators that generate bindings for marshaling data to and from Python. </p>
<p>Not only that but .NET Aspire is indispensable for configuring a system like this, not only for tying together the moving parts—PostgreSql, Python API, web front-end—but also for monitoring not only the startup but also API executions, which you can track in a nice process-graph for each request (shown below).</p>
<p><span style="width: 683px; display: table" id="NET"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5283/dotnet_aspire_for_csnakes_python.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5283/dotnet_aspire_for_csnakes_python.jpg" alt=" " style="width: 683px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5283/dotnet_aspire_for_csnakes_python.jpg">.NET Aspire for CSnakes / Python</a></span></span></p>
<p>It even shows how the chart is rendered in Python, returned as bytes to C# and then rendered into the body of the response directly (basically sending back an image rendered in Python without conversion).</p>
<p>Unlike previous attempts like IronPython, this approach uses .NET Aspire to simplify integration of Python projects and code without changing it. It just integrates it, like taking care of setting up the PostgreSql database and then passing the connection string to the Python code.</p>
<p>Anthony discusses at the end how the common data types used in Python ML processing (tensors, etc.) are all supported in an efficient manner, allowing you to pass buffers back and forth from Python to .NET and offloading code like web servers and GUIs to .NET development while benefitting from existing Python libraries.</p>
<p>I imagine that this is just an interim solution until the .NET ecosystem catches up more with Python—which it is definitely going to do, if it hasn&rsquo;t largely done so already.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5390</guid>
    <title><![CDATA[Mads Torgerson on union types, existential types, and C# missteps]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5390</link>
    <pubDate>Tue, 11 Feb 2025 22:39:11 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Feb 2025 22:39:11 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This is a nearly 100-minute-long interview and discussion about programming-language design and evolution. It gets deep into the weeds on very specific and relatively advanced language features. While a feature may eventually feel quite simple to use, the considerations about how to design it and how to fit it into the landscape of the rest of the language can be very, very complex. There are a lot of moving parts to consider in a language, runtime, community, and ecosystem as established as .NET and C#.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/T9UqIkuGnuo" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=T9UqIkuGnuo">The Exciting Future of C# with Mads Torgersen</a> by <cite>Nick Chapsas</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<h2>Existential Types</h2><p>At about <strong>45:00</strong>, Mads describes a higher-level typing system that allows for &ldquo;hiding&rdquo; some generic-type parameters.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;There are various features that are related but not quite the same. There are &lsquo;associated types&rsquo; in some languages and there&rsquo;s what one scholar calls &lsquo;abstract types&rsquo; [I think he meant &lsquo;existential types&rsquo;], which might be my favorite version of the feature, which are kind of an alternative to generics or a kind of generics.</p>
<p>&ldquo;The really short version is they help you not have so damn many type arguments all the time, yeah? Okay; essentially think of it as a class. Instead of a class having a type parameter saying, I&rsquo;m an animal with a type argument saying which kind of food it eats…that means <strong>every time you talk about animals, you have to pass type arguments around. That&rsquo;s really annoying because what kind of food it eats is inherent to it. It shouldn&rsquo;t be like something on the outside; it should be a member, saying my food type is [whatever]</strong> … </p>
<p>&ldquo;…and if you do that, then you can kind of tamp down on a lot of the…sometimes you just end up in generics overload, or passing the same stuff around. And every one of these related types has a type argument for which particular implementation of the other related interfaces it is using and <strong>they all carry the same five type arguments around all the time.</strong></p>
<p>&ldquo;So that would be a feature, if we can get it right, and if we can work it into the runtime, and it&rsquo;s limited—and we are occasionally talking about it—that <strong>could be a really really beautiful and quite impactful addition to C#.</strong>&rdquo;</p>
</div></blockquote><p>It is described in detail in <a href="https://github.com/dotnet/csharplang/discussions/8711">Proposal: Existential types for interfaces and abstract types #8711</a> (<cite><a href="http://github.com/">GitHub</a></cite>). While Mads&rsquo;s description of it made my ears perk up, the proposal does a better job of explaining it.</p>
<p>An interface might look like this:</p>
<pre class=" "><code>interface ICounter&lt;protected T&gt;
{
    T Start { get; }
    void Next(T current);
    bool Done { get; }
}</code></pre><p>Describing the visibility of the generic parameter with the keyword <code>protected</code> is part of the proposal.</p>
<p>Since the parameter is protected, external users would use the interface without the generic parameter, like this:</p>
<pre class=" "><code>void M(ICounter ic)
{
    var × = ic.Start;
    while (!ic.Done)
    {
        × = ic.Next(x);
    }
}</code></pre><p>Only an implementation is required to provide a type parameter:</p>
<pre class=" "><code>class Counter : ICounter&lt;int&gt;
{
     int Start =&gt; 0;
     int Next(int current) =&gt; current + 1;
     bool Done =&gt; current == 42;
}</code></pre><h2>Type unions</h2><p>At <strong>58:00</strong>, they discuss what something like &ldquo;discriminated unions&rdquo; or &ldquo;tagged unions&rdquo; would look like in a decidedly object-oriented language like C#.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;<strong>Mads:</strong> We arrived at this degree of clarity around what our options are. The type unions—use of the word &lsquo;types&rsquo; there reflects that one conclusion that we reached is that, in C, unions should be &lsquo;unions of types&rsquo;. If you look at F# or other functional languages, discriminated unions are not unions of types. They&rsquo;re unions of something with a name, a tag-discriminator, whatever you want to call it, the tagged unions that can then be deconstructed to give you values of one or more types. So <strong>the different options are like &lsquo;named options&rsquo; but they&rsquo;re not things in and of their own right. They&rsquo;re just a means to get to what&rsquo;s inside.</strong></p>
<p>&ldquo;In C#, one thing that we agree on is that that has to change. It has to be that the things are types. So you don&rsquo;t have to pattern on a union and get an <code>A</code> or you get a dog and immediately you have to decompose it into how many legs it has and and what it eats. You know what its name is. You can carry it around as a dog. It makes sense in its own right and it can be its own object. So <strong>that&rsquo;s essentially trying to take an object-oriented view on what discriminated unions would look like in C#.</strong></p>
<p>&ldquo;<strong>Nick:</strong> Fundamentally, <strong>discriminated unions are a very functional-programming-like concept</strong> and they don&rsquo;t fit in a language that already has inheritance right? Because the idea is <strong>it&rsquo;s their version of inheritance.</strong></p>
<p>&ldquo;<strong>Mads:</strong> Exactly.&rdquo;</p>
</div></blockquote><h2>Design mistakes in C#</h2><p>At <strong>01:22:00</strong>, Nick asks what are Mads&rsquo;s three least-favorite/most-hated features of C#, things that he wishes had never gone in or that, in a better world, he would remove. </p>
<ol>
<li><strong>Events</strong>, because they should never have been a language feature. They should have been a runtime/library feature, at most.</li>
<li><strong>Delegates</strong>, because they were forced to be collection types because of events. Their execution dynamics are indeterminate (because of ordering) and they actually break covariance (kind of like arrays).</li>
<li><strong>Void</strong> should have been a type (as it is in <em>Typescript</em> and <em>Eiffel</em>). Its being a language feature means that they bifurcate all other support, like requiring a distinction between <code>Func</code> and <code>Action</code>.</li>
<li><strong>dynamic</strong> is a pretty great feature <em>academically</em> but the value of the feature ended up being much less than they&rsquo;d hoped. <span class="quote-inline">&ldquo;Performance-wise, it&rsquo;s a disaster. There&rsquo;s a whole bunch of infrastructure to maintain it. It doesn&rsquo;t carry its own weight.&rdquo;</span></li></ol><h2>Nullability</h2><p>The final part of the discussion is about nullability-checking in the compiler, and its limitations and strengths. <span class="quote-inline">&ldquo;The point is that it&rsquo;s so much better than nothing.&rdquo;</span> The feature makes you think about what even should be allowed to be <code>null</code>.</p>
<p>My advice is to avoid returning or accepting <code>null</code> unless you absolutely can&rsquo;t avoid it. Don&rsquo;t ruin your API, of course, but be absolutely sure that <code>null</code> needs to be an option. It is much easier to write code to APIs that never return <code>null</code>. Consider using sentinel objects instead. The feature in C# has gotten a lot better and is very good now. <code>init</code> and <code>required</code> properties helped finalize the feature.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5358</guid>
    <title><![CDATA[CSS: Popovers and anchors]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5358</link>
    <pubDate>Mon, 27 Jan 2025 13:49:06 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">27. Jan 2025 13:49:06 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://fullystacked.net/portal/">Do JavaScript frameworks still need portals?</a> by <cite>Ollie Williams</cite> (<cite><a href="http://fullystacked.net/">Fully Stacked</a></cite>) explains a bit more about the relationship between <code>dialog</code>, <code>popover</code>, and <code>anchor</code> as well as how these elements have made &ldquo;portal&rdquo; support in frameworks obsolete. The following ~20-minute video shows how to use only CSS and HTML to position and display elements, regardless of their nesting in the document.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/DNXEORSk4GU" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=DNXEORSk4GU">CSS Popover + Anchor Positioning is Magical</a> by <cite>Kevin Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The main example uses <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_anchor_positioning">CSS anchor positioning</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>), <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/position-try">position-try</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:popover-open">:popover-open</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>). You can use <code>position-try</code> to direct the browser to adjust the appearance of the popover when there isn&rsquo;t enough &ldquo;space&rdquo; on-screen at its default position. You can also animate everything.</p>
<p><span style="width: 227px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5358/popover_menu.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5358/popover_menu.jpg" alt=" " style="width: 227px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5358/popover_menu.jpg">Popover menu</a></span></span></p>
<pre class=" "><code>.user-button {
  padding: 0;
  border-radius: 100vw;
  aspect-ratio: 1;
  <strong class="highlight">anchor-name: --profile-button;</strong>
}

.profile-menu {
  <strong class="highlight">position: absolute;
  position-anchor: --profile-button
  top: anchor (bottom) ;
  right: anchor(right);</strong>
  margin: 0;
  inset: auto;
  margin-block-start: 6px;
}

<strong class="highlight">.profile-menu:popover-open {
  display: grid;
}</strong>

@position-try --bottom {
  inset: unset;
  top: anchor(bottom);
  right: anchor(right);
}</code></pre>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5304</guid>
    <title><![CDATA[Angular 19 sounds ... complicated?]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5304</link>
    <pubDate>Mon, 23 Dec 2024 12:35:30 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">23. Dec 2024 12:35:30 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Some of the features described in the video below sound pretty interesting but they also sounds super-complicated, with deferred-loading, hydration, signals, and event/replay all combined with decisions about whether something loads on the client or the server or whether it&rsquo;s initially built on the server but then enhanced on the client and then run independently from the server, … </p>
<p>I understand that a lot of this technology is for optimizing large web sites, but It&rsquo;s honestly questionable who can actually take advantage of it. That&rsquo;s always been the problem with trying to massively optimize your web applications as if you were Google. It&rsquo;s nice that this stuff is available; it&rsquo;s unfortunate that so much of it has to be opt-in because the cognitive load required to use it well is very, very high. It&rsquo;s the same experience I&rsquo;ve had in React. When teaching it, you get into the weeds on performance and <code>useMemo()</code> and <code>useCallback</code> and profiling very quickly, which makes it…not really a beginners library.</p>
<p>Take a look at the video, though. Maybe something piques your interest. Be warned, though, the presentation style is…interesting, to say the least. It&rsquo;s got a &ldquo;definitely not robots&rdquo; vibe to it. More below the video.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/JvkX2_46gUY" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=JvkX2_46gUY">Angular v19 Developer Event</a> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Man, I thought some of the recent MS .NET videos seemed less-than-professional but those were downright <em>charming</em> compared to whatever this thing from Google is. All of the people featured in this video are so stiff, so obviously touched-up and coifed, that it&rsquo;s throwing me off.</p>
<ul>
<li>The guys are hold their arms on-camera so that you can see that they go to the gym.</li>
<li>Everyone does that super-annoying &ldquo;I&rsquo;ve taken an oration course and have learned to artificially move my hands to emphasize my points.&rdquo; that people who are definitely not robots do.</li>
<li>The one (only?) lady&rsquo;s diction reveals to me that she definitely filmed her segment a dozen times.</li></ul><p>The &ldquo;jokes&rdquo; fall so flat that I can&rsquo;t even imagine which audience would think this is funny.This video feels like it belongs in a high school. Every line is scripted. There&rsquo;s no spontaneity and it&rsquo;s not good. I&rsquo;m used to presenters who act much more naturally than this; even people like Kevin Powell and Nick Chapsas are still obviously performing, it doesn&rsquo;t feel like a &ldquo;don&rsquo;t do drugs&rdquo; PSA put on by parents.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5305</guid>
    <title><![CDATA[Using calc-size in CSS]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5305</link>
    <pubDate>Mon, 23 Dec 2024 12:24:31 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">23. Dec 2024 12:24:31 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The following video shows not only when and how to use <code>calc-size()</code>, it also mixes in advice on generating timing functions for animations, sprinkles CSS variables throughout, and even uses <code>overflow: clip</code> combined with an absolutely positioned element to reveal more content without disturbing the layout.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/WhS4xRSIjws" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=WhS4xRSIjws">Animate and do math on things like height: auto with interpolate-size and calc-size()</a> by <cite>Kevin Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The syntax for <code>calc-size()</code> is, as Kevin says, <span class="quote-inline">&ldquo;weird&rdquo;</span>; you have to pass two parameters: the first is the name of the logical size you&rsquo;d like to use, while the second parameter is a formula that uses the placeholder <code>size</code>, which accepts the value of the first parameter. In a sense you are passing the argument, along with a lambda that accepts that argument.</p>
<p>The following CSS sets the inline (horizontal in LTR and RTL) size of an element to be whatever the intrinsic size of the element would have been, given the size of its children, plus <code>3rem</code> (where <code>rem</code> is the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/length#rem">font size of the root element</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>)).</p>
<pre class=" "><code>inline-size: calc-size(max-content, size + 3rem);</code></pre><p>This video accompanies <a href="https://12daysofweb.dev/2024/calc-size-and-interpolate-size/">Kevin&rsquo;s article</a> for the <a href="https://12daysofweb.dev/2024/">12 days of code 2024</a>, if you&rsquo;d rather read about it, with more code examples.</p>
<p>&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5306</guid>
    <title><![CDATA[How to apply EF migrations]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5306</link>
    <pubDate>Mon, 23 Dec 2024 12:20:02 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">23. Dec 2024 12:20:02 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The picture and title are, as usual, clickbait-y, because apparently people don&rsquo;t click on videos that sound educational unless you promise them ground-breaking learnings. Still, I don&rsquo;t hate the player; I hate the game. But it&rsquo;s the world we have.</p>
<p>The video is quite informative and is 90% not the guy pictured. Instead, it&rsquo;s another guy called Gui Ferrera, who is quite competent.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/StBf3-M5WdM" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=StBf3-M5WdM">The Correct Way to Run Database Migrations in EF Core</a> by <cite>Nick Chapsas / @gui.ferreira</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>He starts by explaining how to deploy migrations in production—you don&rsquo;t just run them, as you would in development. Why not? Because, if you run the migrations as part of your application startup, then your application implicitly has permissions to modify the database schema—permissions that you are unlikely to revoke or downgrade.</p>
<p>As an alternative, you can use the <code>dotnet-ef</code> tool to generate an <code>ef migrations bundle</code> (he names the file <code>efbundle</code>), which is an executable that you can then just run, using the pipeline secret that has administrator access to the target database. This executable runs separately and is only in charge of migrating the database to a particular version. Your application will run and fail if the schema is not correct, which is the desired behavior. If it is correct, your application will run with a database user with much lower permissions—at the very least, it won&rsquo;t be able to issue DDL commands.</p>
<p>The <code>bundle</code> option generates a binary; there is also a <code>script</code> option, which generates SQL. This is pretty neat and there&rsquo;s even a flag called <code>idempotent</code>, which allows you to generate a script that will ensure that previous migrations have been applied before continuing with subsequent migrations.</p>
<p>The implementation isn&rsquo;t as obviously straightforward as it advertises itself. There must be limitations for custom-migration behavior that uses program logic. I know, because Quino [1] had a very similar feature and, although we could generate SQL for some user customizations to the migration process, there was no way to support everything.</p>
<p>It&rsquo;s nice to see how solid the EF migrations story has gotten, even though I think the design still suffers when switching branches. You need much more developer discipline to keep your local database usable and in-sync. Anecdotally, I hear that most developers just trash their local database all the time, and rely much more on seeding functions to restore the state. You tend to lose your local ad-hoc-created data and it takes a bit more time, but it works with EF.</p>
<p>It&rsquo;s actually not a bad alternative since it forces you to focus more on the seeding function, which will also benefit you while writing tests. For prototyping, though, there was nothing as fast as Quino or Atlas [2], both of which, instead of using a metadata table in the database, read the database schema, compared against the application model and applied custom migrations to address differences.</p>
<p>Ferrera finished up with by-now standard advice for adding required columns (and other, similar types of breaking changes): you have to add the column as nullable with a default in the first migration, then get rid of the unwanted default value and nullability in a subsequent migration. You can only remove an unwanted field once the deployed application isn&rsquo;t using it. That is, you have to drop the column for the deployed version <em>after</em> the version that no longer needs the column. Otherwise, you run the risk of breaking the application that is still running against that database (especially if you have multiple clients/API servers running against the same database instance).</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5306_1_body" class="footnote-number">[1]</span> Quino was a metadata-based ORM/database migrator written in C# that I worked on for years at Encodo Systems AG.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5306_2_body" class="footnote-number">[2]</span> Atlas was a metadata-based ORM/databse migrator written in Delphi Pascal that I worked on for years at Opus Software AG, before I helped found Encodo.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5279</guid>
    <title><![CDATA[Are you doing the Advent of Code?]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5279</link>
    <pubDate>Sun, 08 Dec 2024 21:32:28 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Dec 2024 21:32:28 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>No. No, I&rsquo;m not.</p>
<p>I was briefly considering it because two good programmer friends [1] of mine asked me, and it seemed like it might be kind of fun to compare our solutions.</p>
<p>But … 24 days, man.</p>
<p>I&rsquo;ve got other things to do. Like, a lot of other things to do.</p>
<p>I am not in any way bored or looking for things to do.</p>
<p>I&rsquo;m not even lacking in programming projects that I could be working on.</p>
<p>I&rsquo;m teaching a JavaScript class right now, for which I&rsquo;m constantly refining the examples and project code, trimming the sails for the particular people in the current class.</p>
<p>I&rsquo;ve got a whole web site to which I&rsquo;ve been meaning to do a bunch of tweaks. I&rsquo;m just now getting the time to get around to it; I certainly don&rsquo;t need to prioritize arbitrary programming tasks.</p>
<p>I&rsquo;ve got a ton of stuff to write that interests me more than writing code for a problem that looks for all the world like a job-interview assessment assignment. I just finished up a 48-page summary of my week&rsquo;s reading and writing in <a href="https://www.earthli.com/news/view_article.php?id=5276">Links and Notes for November 29th, 2024</a>. I&rsquo;ve got a stack of book reviews a mile high that I&rsquo;ve not given up on. Yet. Those kinds of things takes time—and it&rsquo;s important to me, much more so than the aforementioned programming exercises. </p>
<p>So, no, I&rsquo;m not doing advent of code. I&rsquo;d like to compare solutions with my friends, but not enough to reshuffle all of my priorities.</p>
<p>I also wonder who came up with the advent of code? All of the time that people spend every day working on these arbitrary examples is good training, I guess. But training for what? Job interviews? It&rsquo;s all time that they&rsquo;re not spending on other creative projects or spending on open-source projects. I&rsquo;m not trying to knock it at all—becoming a good programmer means just <em>putting in the <strong>time</strong></em>.</p>
<p>But the question is what are putting in your time on? When I was the same age as one of my (much younger) friends, I poured all of my time into building a web site—that I&rsquo;m still using every single day a quarter of a century later.</p>
<p>The featured sponsor for December 8th is <em>Optiver</em>, which says it codes <span class="quote-inline">&ldquo;sub-nanosecond trading systems&rdquo;</span>, whatever the hell that means. So, they&rsquo;re trying to find people to make fast trading systems. Just. Stop. We need brilliant coders to be building software useful to society, not to billionaires. Those things are pretty much diametrically opposed. Let&rsquo;s take a closer look at the list of sponsors.</p>
<p><span style="width: 640px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5279/apple_1984_ad.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5279/apple_1984_ad.jpg" alt=" " style="width: 640px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5279/apple_1984_ad.jpg">Apple 1984 Ad</a></span></span></p>
<ul>
<li>Jane Street (trading)</li>
<li>A bunch of online training-course providers…</li>
<li>Accenture (formerly <em>Anderson Consulting</em> before they had to rename themselves after the <em>Enron</em> debacle, but don&rsquo;t worry, they&rsquo;re far, far larger than ever, having failed upward as expected).</li>
<li>JPMorgan Chase (&lsquo;nuff said)</li>
<li>Lighttricks (AI company…🙄)</li>
<li>Ahrefs (&ldquo;indexing&rdquo; company, but almost certainly a funnel for AI content)</li>
<li>Shopify (they own the world of online storefronts, having homogenized that part of the world for us; thanks)</li>
<li>Jump Trading</li>
<li>American Express</li>
<li>Bank of America</li>
<li>ING Bank</li>
<li>…and a bunch of other, smaller things</li></ul><p>It doesn&rsquo;t look great, if I&rsquo;m being honest.</p>
<p>Anyway, I&rsquo;m doing a meta advent of code, in which I just work on as much stuff as I can, but of my own choosing and on my own schedule.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5279_1_body" class="footnote-number">[1]</span> One of whom is painstakingly and entertainingly detailing his brilliant solutions in Rust on <a href="https://ajone239.github.io/">his blog</a>.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5289</guid>
    <title><![CDATA[Real quick on MVVM]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5289</link>
    <pubDate>Sat, 07 Dec 2024 22:50:43 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">7. Dec 2024 22:50:43 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>A little while back, someone wrote <a href="https://old.reddit.com/r/csharp/comments/1gqjtel/i_cant_wrap_my_head_around_mvvm/">I can&rsquo;t wrap my head around MVVM</a> (<cite><a href="http://old.reddit.com/">Reddit</a></cite>), asking for help. I answered with a short example, reproduced below.</p>
<blockquote class="quote abstract "><div><abbr title="too long; didn't read">tl;dr</abbr>: Use the <a href="https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/">MVVM Toolkit</a> and try JetBrains ReSharper or Rider for more IDE assistance for binding and fixing up views. [1]</div></blockquote><p>The concept is that:</p>
<ul>
<li>the (M)odel describes your data in the shape you want to store it, process it, etc.</li>
<li>a (V)iew describes the elements of the UI.</li>
<li>a (V)iew(M)odel mediates between these two &ldquo;shapes&rdquo;.</li></ul><p><a href="https://www.earthli.com/data/news/attachments/entry/5289/mvvm.png"><img src="https://www.earthli.com/data/news/attachments/entry/5289/mvvm.png" alt=" " style="width: 578px"></a></p>
<p>Why do we need this? Why not just bind the view directly to the model?</p>
<p>Consider a simple person:</p>
<pre class=" "><code>record Person(
  string FirstName,
  string LastName,
  Company Company,
  DateTime BirthDate);</code></pre><p>The view model might want to expose:</p>
<pre class=" "><code>int Age =&gt; DateTime.Now.Year − _model.BirthDate.Year;

string FullName =&gt; $"{_model.FirstName} {_model.LastName}";

Company Company { get; }

IReadOnlyList&lt;Company&gt; AvailableCompanies { get; }</code></pre><p>The <code>AvailableCompanies</code> is for the drop-down menu.</p>
<p>So that&rsquo;s why there are two models. We don&rsquo;t want to pollute the data model with view-specific properties. Each view gets its own view model and you can have multiple views/viewModels on the same model. Nice.</p>
<p>The *mechanics* of binding the view to an object has nothing to do with MVVM. It&rsquo;s *binding*, which is done by magic. This magic is made a lot easier if you use the <a href="https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/">MVVM Toolkit</a>. The latest versions use source generators so you can actually *see* the magic binding code (in separate source-generated files).</p>
<p>I would also try JetBrains ReSharper or Rider because either of those tools provides a lot more code-completion, hints, warnings, and fixup assistance than a bare Visual Studio does.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5289_1_body" class="footnote-number">[1]</span> I just saw in a .NET 9 release video that <a href="https://learn.microsoft.com/en-us/windows/apps/develop/data-binding/function-bindings"><code>x:bind</code></a> is a better alternative to the classic <code>binding</code>, which has better compiler and code-completion support (because it generates sources rather than using reflection). I haven&rsquo;t had a chance to investigate yet, though.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5272</guid>
    <title><![CDATA[Writing elegant code]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5272</link>
    <pubDate>Wed, 04 Dec 2024 22:22:42 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Dec 2024 22:22:42 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I watched this video analyzing a chunk of code, in the hopes of refactoring it.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/KWjAaG-meJQ" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=KWjAaG-meJQ">Always Return Early in Your Code | Code Cop #024</a> by <cite>Nick Chapsas</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The original code is the laughably overblown example below.</p>
<pre class=" "><code>public List&lt;int&gt; ProcessData(List&lt;int&gt; data)
{
  if (data != null)
  {
    if (data.Count &gt; 0)
    {
      var processedData = new List&lt;int&gt;();
      foreach (var d in data)
      {
        processedData.Add(d * 2);
      }
      return processedData;
    }
    else
    {
      return new List&lt;int&gt;();
    }
  }
  else
  {
    return null;
  }
}</code></pre><p>Nick rewrote it as the following:</p>
<pre class=" "><code>List&lt;int&gt; ProcessData(List&lt;int&gt;? data)
{
  if (data is not { Count &gt; 0 })
  {
    return []:
  }

  return data.Select(d =&gt; d * 2). ToList();
}</code></pre><p>Nick&rsquo;s is OK, but I don&rsquo;t understand why he bothers to check for <code>Count &gt; 0</code> when <code>Select()</code> already short-circuits on this case.</p>
<p>@DmitryKandiner rewrote it as the following:</p>
<pre class=" "><code>List&lt;int&gt; ProcessData(List&lt;int&gt;? data) =&gt; data?.Select(d =&gt; d * 2).ToList() ?? [];</code></pre><p>This is really short and avoids the unnecessary length-check but it still deals with nullable code, which is silly. There is no need for this function to handle possibly <code>null</code> input data.</p>
<p>I commented the following:</p>
<p>We can also drop the null-check if we have nullability enabled (which any modern project should). Also, I prefer defining APIs with enumerables rather than lists, but if the design insists, I would do it with two methods. This gives callers the <em>option</em> of building lists but doesn&rsquo;t require them to do so.</p>
<pre class=" "><code>List&lt;int&gt; ProcessList(List&lt;int&gt; data)
{
    return ProcessSequence(data).ToList();
}

IEnumerable&lt;int&gt; ProcessSequence(IEnumerable&lt;int&gt; data)
{
    return data.Select(d =&gt; d * 2);
}</code></pre><p>To which @swozzares replied that I could eliminate the <code>return</code> by using <code>=&gt;</code> (called an &ldquo;expression body&rdquo;). So I updated the sample with:</p>
<pre class=" "><code>List&lt;int&gt; ProcessList(List&lt;int&gt; data)
  =&gt; ProcessSequence(data).ToList();

IEnumerable&lt;int&gt; ProcessSequence(IEnumerable&lt;int&gt; data)
  =&gt; data.Select(d =&gt; d * 2);</code></pre><p>And I might as well include the test:</p>
<pre class=" "><code>[Test]
public void TestProcessSequence()
{
    List&lt;int&gt; input = [1, 2, 3, 4, 5];
    List&lt;int&gt; expected = [2, 4, 6, 8, 10]; 
    
    Assert.That(ProcessList(input), Is.EqualTo(expected));
    Assert.That(ProcessSequence(input), Is.EqualTo(expected));
}</code></pre><p>Someone named @Me_myself_and_I took offense to my comment that projects should be using nullability.</p>
<blockquote class="quote quote-block "><div>&ldquo;Except that there are a lot of projects that pre-date that.  Its good for new projects sure, but probably not worth the effort to refactor and re-test existing large projects.  Devs really need to learn to think about existing systems and long-term maintainability not just new code.&rdquo;</div></blockquote><p>I think we should be clear about the context. The commentator&rsquo;s argument is the same one I would make when I work on a legacy project. I think we should take care to show that, if you started a project in C# in the last five years, you shouldn&rsquo;t be checking for null everywhere anymore. If you turned off nullable checks, then, yeah, you&rsquo;ll still have to check for it. But you should be designing null-free APIs— where null is not allowed by default.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5248</guid>
    <title><![CDATA[You're probably doing code reviews incorrectly]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5248</link>
    <pubDate>Mon, 11 Nov 2024 12:12:33 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Nov 2024 12:12:33 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://www.stefanjudis.com/blog/processes-and-rules-make-code-review-less-intimidating/">Processes and rules make code review less intimidating</a> by <cite>Stefan Judis</cite> writes,</p>
<blockquote class="quote quote-block "><div>&ldquo;<a href="https://www.earthli.com/data/news/attachments/entry/5248/highlight_anything_you_think_seems_stupid.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5248/highlight_anything_you_think_seems_stupid_tn.jpg" alt=" " class=" align-right"></a><strong>Code reviews are, by nature, intimidating. Sometimes even brutal.</strong> If you&rsquo;ve been in the game for long enough, you probably experienced the following: you worked hard on a feature, you&rsquo;re proud of yourself and open the PR to be praised and land your changes, and then… it rains comments, suggestions and nitpicks. And if it&rsquo;s really bad, you&rsquo;re forced to take multiple feedback and clean-up rounds. It sucks.&rdquo;</div></blockquote><p>Oh, wow.</p>
<p>Why are people treating writing code like individual school assignments?</p>
<p>That is absolutely not how to effectively use code reviews. That is absolutely not how to work in a team. Teams work together, not against each other.</p>
<p>Why are you putting your heart and soul into your solution? Why is it &ldquo;your&rdquo; solution? Is this how y&rsquo;all were raised? You know, where you prefer being the star genius in your own story, where you managed to get the perfect solution on the first try? Like, you&rsquo;re the superhero, brilliant, engineer, billionaire playboy?</p>
<p>And then, you learn that you aren&rsquo;t, and you&rsquo;re shattered.</p>
<p>But you know what? You&rsquo;re on a team that&rsquo;s willing to look at what you made and really try to make it better. Maybe they will make it better! Or maybe they won&rsquo;t. Both are good! If they do … then it&rsquo;s better. That&rsquo;s a win. If they don&rsquo;t, well, then, you&rsquo;ve gotten some evidence that supports your theory that what you&rsquo;ve written really is good and will work.</p>
<p>Up until someone looks at it, you only had a hypothesis that your solution was good enough. You suspected it because you had some code and you had some tests (yes you did, otherwise you have <em>no</em> right to be offended about code-review comments). That&rsquo;s a <em>hypothesis</em>.</p>
<p>You know who else does reviews to verify theories and hypotheses? <em>Scientists.</em></p>
<p>Quit your whining. Quit your bullshit.</p>
<p>If you&rsquo;re treating code reviews like a gladiator arena, as if you were going on <em>Shark Tank</em> or <em>The Voice</em>, then <em>you&rsquo;re doing it wrong.</em></p>
<p>The best software is written by a team. It is collaborative. Maybe one person is writing all of the actual text, but there are other <em>minds</em> that contribute advice and feedback that hones the final product.</p>
<p>You know what <em>that</em> sounds like? A writer and one or more editors or proofreaders.</p>
<p>This is how professionals work. Fix your process. Fix your expectations. Fix your fragile ego. Seek validation in a less self-destructive manner.</p>
<p>The author proposes a fix. It&rsquo;s a technical solution, so it&rsquo;s not great.</p>
<p>He could have suggested that people do &ldquo;live reviews&rdquo; instead of PRs because most people are too lazy or incapable to write critical comments that are also <em>constructive</em>. This is sadly often the case because learning how to write and how to empathize is a lot of work. You could start with empathizing, about which more below.</p>
<p>Instead, he writes about an insipid system where shittily aggressive review comments like <span class="quote-inline">&ldquo;this is not worded correctly&rdquo;</span> are somehow made better by prepending the text <span class="quote-inline">&ldquo;suggestion:&rdquo;</span>.</p>
<p>No. It does not make it better.</p>
<p>Why not? Well, for starters, because the text is not formulated as a <em>suggestion</em>. There is only an implicit suggestion that the reviewer would have worded it correctly. This is passive-aggressive time-wasting behavior. On top of that, <em>everything in a code review is a suggestion</em> unless the power dynamic in your team is so severely skewed that we need to be having a different conversation.</p>
<p>The comment should read something like, <span class="quote-inline">&ldquo;I think that something like &ldquo;… …&rdquo; would be a clearer way of writing that.&rdquo;</span></p>
<p>Or, maybe, you could establish a <em>rapport</em> with the people reviewing your code so you&rsquo;re not pants-shittingly terrified that you&rsquo;re going to lose mana when you do one. Maybe you could—gasp!—even be friends. This would help establish a human connection often summarized as <em>empathy</em> wherein the reviewer would consider for a brief moment how a comment might look to the other side and adjust it accordingly, in a manner that is totally not like how robots would do it.</p>
<p>If you&rsquo;ve established that code reviews are collaboration and not a gladiator arena where &ldquo;two enter and one leaves&rdquo;, then the reviewer can be more concise without wasting a lot of time writing curlicue sentences. If you <em>don&rsquo;t</em> have this rapport, then, yes, I&rsquo;m afraid you&rsquo;re going to have to be…what&rsquo;s the word?…<em>polite.</em></p>
<p>If you can&rsquo;t be polite, then, at the very least, you should write review comments that don&rsquo;t need review comments of their own. You&rsquo;re going to have to follow the rules of <em>error messages</em>. As detailed in <a href="https://developer.apple.com/design/human-interface-guidelines/alerts">Alerts</a> (<cite><a href="http://developer.apple.com/">Apple HIG</a></cite>),</p>
<blockquote class="quote quote-block "><div>&ldquo;Avoid using an alert merely to provide information. People don’t appreciate an interruption from an alert that’s <strong>informative, but not actionable.</strong>&rdquo;</div></blockquote><p>Any review comment has to be both <em>informative</em> and <em>actionable</em>. The comment in question—<span class="quote-inline">&ldquo;this is not worded correctly&rdquo;</span>—is <em>neither</em>. It just vaguely points at something and says &ldquo;you suck.&rdquo; It&rsquo;s clearly attached to a specific line but doesn&rsquo;t indicate what&rsquo;s wrong with it. Even if it said specifically what&rsquo;s wrong, it doesn&rsquo;t suggest how to fix it.</p>
<p>An error message from a piece of unthinking software can&rsquo;t go quite that far—unless it&rsquo;s a spellchecker or grammar-checker!—but an <em>actual, empathetic human</em> in the role of a <em>collaborator</em> can! That <em>person</em> could formulate a suggestion for how to rewrite it so that the review for that line might end after only <em>one cycle</em>. And, as a bonus, it doesn&rsquo;t end with anyone crying and curled into the fetal position under their desk.</p>
<p>Even if you have an informative and actionable comment, we still come to another downside: they&rsquo;re still not very efficient. The most efficient way of reviewing code is to do it synchronously or &ldquo;live&rdquo;, where the collaborators can discuss and improve the code <em>on the fly, <strong>together</strong></em> maybe—and here me out here—even <em>before</em> you&rsquo;ve even pushed anything! Imagine!</p>
<p>If you&rsquo;re stuck using PRs and web UIs to communicate, then writing comments like the one in question just wastes everyone&rsquo;s time. The submitter either will assume what the commentator meant and try again—NOPE, STILL WRONG—or they will have to write &ldquo;what do you mean?&rdquo; or &ldquo;how would you have written it?&rdquo; This is useless churn. Just write your reformulation with your comment. Remember, you&rsquo;re a <em>collaborator</em>. You&rsquo;re not just trying to get through this review as quickly as possible. It&rsquo;s part of your <em>job</em>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5200</guid>
    <title><![CDATA[C# vs. TypeScript type-narrowing and coercion]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5200</link>
    <pubDate>Sun, 10 Nov 2024 22:33:55 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">10. Nov 2024 22:33:55 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I was working with a colleague to get the properties that have a particular attribute. The original formulation returned the properties then got the attributes <em>again</em>, plucking the first one off of the list and asserting that it exists to convince the compiler that everything&rsquo;s OK. We know it exists because otherwise we wouldn&rsquo;t have returned the property—but the computer doesn&rsquo;t know that.</p>
<p>Ok, it works but it&rsquo;s not efficient or elegant. Is there some way to build this so we allocate minimally and don&rsquo;t have to use the null-forgiving (&ldquo;dammit&rdquo;) operator?</p>
<p>I proposed the following formulation. The null-forgiving operator bugs me a bit because I feel like TypeScript would have determined that <code>attribute</code> could no longer be <code>null</code>. C#/Roslyn doesn&rsquo;t do that.</p>
<pre class=" "><code>private static IEnumerable&lt;(PropertyInfo PropertyInfo, TAttribute Attribute)&gt; GetPropertiesAndAttributes&lt;TAttribute&gt;(Type type)
{
    return
        from prop in type.GetProperties()
        let attribute = prop.GetCustomAttributes(typeof(TAttribute), false).FirstOrDefault() as TAttribute
        where attribute != null
        select (prop, attribute!);
}</code></pre><p>My collaborator prefers the non-query syntax for Linq, so he rewrote it as follows.</p>
<pre class=" "><code>private static IEnumerable&lt;(PropertyInfo PropertyInfo, TAttribute Attribute)&gt; GetPropertiesAndAttributes&lt;TAttribute&gt;(Type type)
{
    return packetType
        .GetProperties()
        .Where(prop =&gt; prop.GetCustomAttributes(typeof(TAttribute), false).Length != 0)
        .Select(propInfo =&gt; (propInfo, propInfo.GetCustomAttribute&lt;TAttribute&gt;()!));
}</code></pre><p>I really don&rsquo;t like that it calls both <code>GetCustomAttributes()</code> and <code>GetCustomAttribute()</code>, so I looked into how to do emulate <code>let</code> with chained-method syntax. I found <a href="https://stackoverflow.com/questions/1092687/code-equivalent-to-the-let-keyword-in-chained-linq-extension-method-calls">Code equivalent to the &lsquo;let&rsquo; keyword in chained LINQ extension method calls</a> (<cite><a href="http://stackoverflow.com/">StackOverflow</a></cite>) and rewrote the code as follows.</p>
<pre class=" "><code>private static IEnumerable&lt;(PropertyInfo PropertyInfo, TAttribute Attribute)&gt; GetPropertiesAndAttributes&lt;TAttribute&gt;(Type type)
{
    return packetType
        .GetProperties()
        .Select(propInfo =&gt; (propInfo, attribute: propInfo.GetCustomAttributes(typeof(TAttribute), false).FirstOrDefault() as TAttribute))
        .Where(t =&gt; t.attribute != null)
        .Select(t =&gt; (t.propInfo, t.attribute!));
}</code></pre><p>I still can&rsquo;t get rid of the second <code>Select()</code> because the type of the first <code>Select()</code> is</p>
<pre class=" "><code>(PropertyInfo PropertyInfo, TAttribute<strong class="highlight">?</strong> Attribute)</code></pre><p>rather than </p>
<pre class=" "><code>(PropertyInfo PropertyInfo, TAttribute Attribute)</code></pre><p>As in the other formulations, we still need the null-forgiving operator to coerce the type. In the final formulation, it&rsquo;s much clearer that this is only required for the compiler because the check that <code>attribute</code> is not <code>null</code> is made on the immediately preceding line.</p>
<p>I was curious about TypeScript, though, C# only supports narrowing conversions for inbuilt primitives. Typescript is fancier. I used <a href="https://www.typescriptlang.org/play/">TypeScript Playground</a> for the examples below.</p>
<p>Here&rsquo;s where we stand with C#, rewritten in TypeScript:</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/5200/0_numbers_null_error.png" alt=" "></p>
<p>At this point, TypeScript is making the same complaint as the C# compiler would.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/5200/1_numbers_null_error_message.png" alt=" "></p>
<p>However, if you remove <code>null</code> values from the result, TypeScript recognizes that and automatically narrows the type to <code>number[]</code> from <code>(number | null)[]</code>.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/5200/2_numbers_converted.png" alt=" "></p>
<p>I just realized that, while this example is interesting, I hadn&rsquo;t replicated the example from C# because I wasn&rsquo;t using tuples.<br>
 <br>
So, let&rsquo;s try again and see how far TypeScript gets.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/5200/0_tuples_two_dimensional_array_default.png" alt=" "></p>
<p>We already have a problem because TypeScript represents tuples with square brackets, which means that this could be an array of two-element tuples or a two-dimensional array. TypeScript defaults to the latter.<br>
 <br>
We fix that with an explicit type.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/5200/1_tuples_correct_no_nulls.png" alt=" "></p>
<p>If I assign <code>null</code> to <code>b</code> in one element, we have a problem, as expected.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/5200/2_tuples_null_element_is_invalid.png" alt=" "></p>
<p>We fix that by adjusting the type of the local variable to be <code>[a: number, b: number | null]</code>.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/5200/3_tuples_return_type_conversion_error.png" alt=" "></p>
<p>Now, we have the type-conversion error on the result.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/5200/4_tuples_return_type_conversion_error_message.png" alt=" "></p>
<p>We fix that the same way as we do in C#, with a <code>Select</code>, which is called <code>map</code> in TypeScript/JavaScript.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/5200/5_tuples_coerced.png" alt=" "></p>
<p>Since TypeScript doesn&rsquo;t allow you to directly address tuple elements like C# does, we have to &ldquo;destructure&rdquo; the elements with <code>const [a, b] = x)</code>. So, we have the same thing as in C#, where we allocate &ldquo;new&rdquo; tuples for the result. What we don&rsquo;t have is a <code>!</code> at the end because TypeScript recognizes the type-narrowing. Clever compiler.</p>
<p>Of course, TypeScript <em>can</em> do this because it&rsquo;s just transpiling to JavaScript, which plays very fast and loose with types anyway. In C#, the compiler has to make decisions about the shape of the memory it uses, so a <code>Nullable&lt;int&gt;</code> is going to have a different representation than an <code>int</code>. If you want to go from the former to the latter, then you have to define a conversion operator, either an <code>explicit</code> one or an <code>implicit</code> one. Or, as we did, you have to create a new tuple, which entails an allocation. Unfortunate, but unavoidable.<br>
 <br>
In JavaScript, that&rsquo;s not the case, at least until it&rsquo;s run through a JIT, in which case other heuristics would have indicated how to most efficiently shape the storage for that particular instance.<br>
 <br>
If that sentence doesn&rsquo;t make sense and you have a follow-up question, then me-from-ten-years-ago is here to offer more in the article <a href="https://www.earthli.com/news/view_article.php?id=3057">Optimizing compilation and execution for dynamic languages</a>, which summarizes a much-longer document written about the WebKit JavaScript engine.</p>
<p>My colleague, who is always game to play with language features, had the good idea to try it with <code>filter()</code>.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/5200/2024-10-18_15_36_24-window.png" alt=" "></p>
<p>This confirmed for us that the TypeScript checker doesn&rsquo;t actually know anything about the effects of the methods <code>filter</code> and <code>map</code>. It&rsquo;s just that the narrowing happens in the closure passed to the <code>map</code> version, so it can determine that there is no way that <code>b</code> will ever be <code>null</code> when the closure exits. Since it doesn&rsquo;t know the semantics of <code>filter</code>, it doesn&rsquo;t know that it actually does that too.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5252</guid>
    <title><![CDATA[CSS Typography is really good now!]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5252</link>
    <pubDate>Sun, 10 Nov 2024 22:18:20 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">10. Nov 2024 22:18:20 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I not unexpectedly very much enjoyed this somewhat-rambling 59-minute course on controlling font features from CSS. It&rsquo;s really quite amazing and wonderful what you can do declaratively these days.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/WdBNYcWG0Yg" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=WdBNYcWG0Yg">CSS Typography Crash Course</a> by <cite>Kevin Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>To begin, Roel Nieskens takes a long look at variable fonts, which can be manipulated via both standard CSS properties, like <code>font-weight</code>, as well as using <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings"><code>font-variation-settings</code></a>, all of which can be animated. Variable fonts support a much more granular range of values for <code>font-weight</code> than traditional fonts, all without downloading anything other than the initial font file.</p>
<p>You can use the <a href="https://wakamaifondue.com/">Wakamaifondue</a> site to determine which features a specific font has, as well as to play with the values along these axes. The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings#registered_and_custom_axes">standard axes</a> are mapped to CSS properties, like <code>font-stretch</code>, <code>font-style: oblique + angle</code>, <code>font-style: italic</code>, and <code>font-optical-sizing</code>. All of this can also be animated, with the font being able to influence the animation as well.</p>
<p>The demonstrations are quite impressive, especially since it&rsquo;s all manipulated using a CSS feature that is <a href="https://caniuse.com/variable-fonts">widely available across major browsers</a>.</p>
<p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5252/css_is_magical.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5252/css_is_magical_tn.jpg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5252/css_is_magical.jpg">CSS is magical</a></span></span>The next section covers colored fonts, which can contain multiple palettes, each with multiple colors. You can use CSS to override the colors but not directly with <code>color</code>. Instead, you define <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@font-palette-values">@font-palette-values</a> to choose a different palette or to override individual colors in a palette. All of this can rely on variables, be animated, and so on, with optimized updates as provided for everything else in a modern web browser.</p>
<p>Next up, he showed how to set <code>font-variant-numeric</code> to <code>tabular-nums</code> to make the font render numbers so that they line up vertically for <em>tabular</em> display. The font has to support this feature but nearly all of them do. This is a good default for table cells. He also shows <code>font-variant-caps</code> and <code>font-variant-numeric</code> to <code>diagonal-fractions</code>, as well as controlling an OpenType feature called &ldquo;scientific inferiors&rdquo;, which will subscript numbers, as in chemical formulae, by setting <code>font-feature-settings</code> to <code>&ldquo;sinf&rdquo;</code>.</p>
<p>Finally, he talks about standard units like <code>cap</code> (the <span class="quote-inline">&ldquo;the nominal height of capital letters&rdquo;</span>, according to <a href="https://css-tricks.com/css-length-units/">CSS Length Units</a> (<cite><a href="http://css-tricks.com/">CSS Tricks</a></cite>)). He shows how to do a &ldquo;true&rdquo; <code>vertical-align: middle</code> by setting <code>margin-top</code> to <code>calc(1ex − 1cap)</code>, which centers without lending so much weight to the descender or ascender.</p>
<blockquote class="quote quote-block "><div>&ldquo;Typography is full of details that nobody notices until they&rsquo;re broken or they&rsquo;ve gone away.&rdquo;</div></blockquote><p>I, for one, welcome the high-powered typography features that will let web pages finally look as good as printed output, like magazines and newspapers, where many of these techniques have been used for decades, if not centuries.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5253</guid>
    <title><![CDATA[Delimiting multiple CSS classes]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5253</link>
    <pubDate>Sun, 10 Nov 2024 11:04:34 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">10. Nov 2024 11:04:34 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5253/css3_logo.png"><img src="https://www.earthli.com/data/news/attachments/entry/5253/css3_logo_tn.png" alt=" " class=" align-right"></a>While investigating <a href="https://chartscss.org/docs/usage/#component-classes">Charts.css</a>, I learned that you can throw unrecognized special characters like square brackets or pipes into CSS class references and its just fine. So you can use them to separate longer lists of classes. For more information, see <a href="https://piccalil.li/blog/cube-css/#grouping">Cube CSS: grouping</a> by <cite>Andy Bell</cite> (<cite><a href="http://piccalil.li/">Piccalilli</a></cite>).</p>
<p>So, you can write:</p>
<pre class=" "><code>&lt;article 
class="[ card ] [ section box ] [ bg-base color-primary ]"&gt;
&lt;/article&gt;</code></pre><p>or</p>
<pre class=" "><code>&lt;article class="card | section box | bg-base color-primary"&gt;
…
&lt;/article&gt;</code></pre><p>and it works just fine, while being more legible. Charts.css uses it to group related classes:</p>
<pre class=" "><code>&lt;table 
class="charts-css 
[ line ] 
[ multiple ] 
[ show-heading ] 
[ show-labels labels-align-start ] 
[ hide-data reverse-data data-spacing-5 ] 
[ show-primary-axis show-data-axes ] "&gt;
  …
&lt;/table&gt;</code></pre>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5220</guid>
    <title><![CDATA[More Stephen Toub: Array Pools]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5220</link>
    <pubDate>Sun, 10 Nov 2024 08:36:04 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">10. Nov 2024 08:36:04 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In this otherwise excellent video, I found myself very much wishing that Toub had written at least a single test for the <code>ArrayPool</code> implementation that he built in this video. Still, check out the selected citation below to get a feeling for how they consider performance implications—there are no easy answers, there is only testing and benchmarking.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/bw7ljmvbrr0" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=bw7ljmvbrr0">Deep .NET: Let&#039;s Build Our Own ArrayPool with Stephen Toub and Scott Hanselman</a> by <cite>dotnet</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>At <strong>34:45</strong>,</p>
<blockquote class="quote quote-block "><div><p>&ldquo;<strong>Hanselmann:</strong> For folks that may not know what NUMA is: so NUMA is this <em>non-uniform memory access</em> that the computer knows that, like, this CPU is near this memory and…that memory over there, we&rsquo;re going to consider that remote memory. And it&rsquo;s all meant to reduce latency. Is that right?</p>
<p>&ldquo;<strong>Toub:</strong> Yeah and this definitely factors into things like the GC, right? And even with threadpool scheduling: you want to put the work where the data is.</p>
<p>&ldquo;<strong>Hanselmann:</strong> Put the work where the data is. Yes.</p>
<p>&ldquo;<strong>Toub:</strong> Otherwise, you spend all your time moving stuff around and thrashing your cache.</p>
<p>&ldquo;<strong>Hanselmann:</strong> …and moving things around at different layers of abstraction. Because you would not want to move between NUMA nodes. You don&rsquo;t want CPU zero to be looking at memory one over there. But then there&rsquo;s the higher-level question of &lsquo;is the adding of an array pool to my application going to cause memory fragmentation or do I just trust the GC to handle that?&rsquo; It&rsquo;s a constant series of trade-offs. Like, did the complexity I added give me the performance that I wanted or did I just make things more complicated.</p>
<p>&ldquo;<strong>Toub:</strong> Well, it&rsquo;s a great example of where you know I mentioned at the beginning there&rsquo;s a lot of complexity with pools. And this is a great example of it, If you&rsquo;re running on a core over here and you use an object that was last used over here, right? Are you better off using that object? Or are you better off just asking the GC to give you a new one? That&rsquo;s going to be allocated in memory that&rsquo;s very closely associated with where you are. So these pools aren&rsquo;t always wins.&rdquo;</p>
</div></blockquote>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5265</guid>
    <title><![CDATA[CSS Magician Roman Komarov plays with sibling-count and sibling-index]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5265</link>
    <pubDate>Sat, 09 Nov 2024 17:32:09 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">9. Nov 2024 17:32:09 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://kizu.dev/tree-counting-and-random/">Possible Future CSS: Tree-Counting Functions and Random Values</a> by <cite>Roman Komarov</cite> (<cite><a href="http://kizu.dev/">Kizu.Dev</a></cite>) is another mathematical master class in using CSS variables and calculations to get at values like &ldquo;sibling count&rdquo; and &ldquo;sibling index&rdquo;, two values that are in a future proposal for <a href="https://www.w3.org/TR/css-values-5/#tree-counting">CSS Values and Units Module Level 5</a> (<cite><a href="http://www.w3.org/">w3C</a></cite>).</p>
<p>The final demo looks like this, with randomly laid out items squared up into equal columns and rows where possible, all done with only CSS.</p>
<p><span style="width: 617px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5265/stacking_and_squaring_up_grid_items.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5265/stacking_and_squaring_up_grid_items.jpg" alt=" " style="width: 617px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5265/stacking_and_squaring_up_grid_items.jpg">Stacking and squaring up grid items</a></span></span></p>
<p>Here&rsquo;s a taste of the code for getting a random value in CSS,</p>
<pre class=" "><code>.random-example {
  &amp; li {
    --random-part-from-sibling:
      pow(var(--sibling-index), 3)
      -
      pow(var(--sibling-index), 2)
      +
      var(--sibling-index);
    --random-part-from-count: var(--children-count);
    --random-limit: var(--closest-prime);
    --random-value: calc(
      mod(
        var(--random-part-from-sibling)
        *
        var(--random-part-from-count)
        *
        var(--seed, 0)
        ,
        var(--random-limit)
      )
      /
      var(--random-limit)
    );
  }
}</code></pre><p>You should really see the <a href="https://kizu.dev/tree-counting-and-random/">original article</a> for the interactive demos. As always, it&rsquo;s stunning how quickly the browser CSS and layout engine e&#xfb03;ciently updates values, invalidating only the parts that are a&#xfb00;ected, even with deeply nested calculations. I went through the article in Opera Beta on an M1 MacBook Pro (from 2020), with a relatively new version of Chromium and it was smooth as silk, with no CPU spikes and no sluggishness (as Komarov indicated might happen in Safari).</p>
<p>He &#xfb01;rst de&#xfb01;nes the sibling-count and sibling-index functions, then builds randomness on top of those. He uses this toolkit to build grids that know how many items they have so that he can keep the grid <a href="https://kizu.dev/tree-counting-and-random/#square-ish-layout">a square</a> with random transforms and coloring. Finally, he even <a href="https://kizu.dev/tree-counting-and-random/#stacking">stacks them</a>, with random overlapping and z-order control.</p>
<p>Finally, he links some amazing CSS demos where people built things that could use this functionality in CSS (but have had to make do with JS for now). See <a href="https://codepen.io/thebabydino/pens/popular">Ana Tudor&rsquo;s many examples</a> or <a href="https://una.im/radial-menu/">Una Kravets&rsquo;s radial menu</a>, or <a href="https://codepen.io/amit_sheen/pens/popular">Amit Sheen&rsquo;s demos</a>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5234</guid>
    <title><![CDATA[IAsyncEnumerable for and by dummies]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5234</link>
    <pubDate>Sat, 09 Nov 2024 17:25:46 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">9. Nov 2024 17:25:46 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This isn&rsquo;t a terrible video on <code>IAsyncEnumerable</code> but it&rsquo;s also not nearly as high-level and fast-paced as I&rsquo;m come to expect from the <em>.NET Deep Dive</em> series, which is no-muss/no-fuss with Stephen Toub. Those are much better than this one but, if you&rsquo;re not grokking what <code>IAsyncEnumerable</code> is good for from the documentation or examples, maybe this one-hour video will help. If you&rsquo;re lucky, it will make you feel better about your own skills as a programmer.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/FbzZJ0pgobg" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=FbzZJ0pgobg">On .NET Live: Supercharge .NET with IAsyncEnumerables: Efficient Data Streams</a> by <cite>dotnet / Chase Aucoin</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Maybe I&rsquo;m just super-smart but I can&rsquo;t understand why so many of Microsoft&rsquo;s .NET videos spend time discussing the <code>_</code> separators in numbers. Hanselmann <em>always</em> points it out whenever Toub uses them in a longer constant like e.g., <code>10_000_000</code>.</p>
<p>Whereas it seems blindingly f&rdquo;&amp;king obvious what they&rsquo;re for, Cam Soper in this video just <em>had</em> to ask about them, presumably because, even though he almost certainly knows what they are, he thinks that the audience for a video about <code>IAsyncEnumerables</code> would also be unable to intuit what those symbols might be.</p>
<p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5234/highlight_anything_you_think_seems_stupid.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5234/highlight_anything_you_think_seems_stupid_tn.jpg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5234/highlight_anything_you_think_seems_stupid.jpg">Highlight anything you think seems stupid</a></span></span>So, they get three people involved in a discussion about thousands separators. It&rsquo;s a waste of time. OMG, I started writing this rant at what I thought was the end of the &ldquo;basic C# syntax&rdquo; discussion but I was <em>wrong</em>. They continued for thirty more seconds, with a fourth person chiming in. <span class="quote-inline">&ldquo;C# 7; I just verified.&rdquo;</span> Congrats, guys! We solved it!</p>
<p>The next thing we got to do was watch the async guru use <em>Task Manager</em> to do memory profiling. Have these guys never heard of <em>Benchmark.Net</em>? Or are they just trying to make other developers feel better about themselves?</p>
<p>I am fascinated that they don&rsquo;t explain the mechanism behind the <code>IAsyncEnumerable</code> at all. Chase just talks about it as it were magic rather than an enumerable that returns a sequence of <code>Tasks</code>. The magic is in the <em>enumerable</em> part, which allows an algorithm to avoid creating all of the data in memory at once.</p>
<p>The example at <strong>57:00</strong> with <a href="https://learn.microsoft.com/en-us/dotnet/api/system.io.pipes?view=net-8.0">System.IO.Pipes</a>, <code>System.Text.Json</code>, and <code>IAsyncEnumerable</code> was quite nice, though. It shows the power of the piping abstraction (which lies below streams). It&rsquo;s a pity they didn&rsquo;t get into that more but maybe a follow-up video by Stephen Toub is in the offing.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5233</guid>
    <title><![CDATA[A quick look at .NET Aspire]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5233</link>
    <pubDate>Sat, 09 Nov 2024 12:33:37 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">9. Nov 2024 12:33:37 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://learn.microsoft.com/en-us/dotnet/aspire/get-started/aspire-overview">.NET Aspire</a> is a newly introduced tool for building distributed solutions that run just as easily locally as they do in the cloud. This video explains how this is a boon for integration testing.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/bPIu6PZW41Q" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=bPIu6PZW41Q">End-to-end integration testing with .NET Aspire</a> by <cite>dotnet / Aaron Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The concept is very nice and seems to greatly simplify building integration tests. Kudos and thanks for the introduction.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/5233/spaghetti-code.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5233/spaghetti-code_tn.jpg" alt=" " class=" align-right"></a>Still, my hair was standing on end with some of the &ldquo;fast and loose&rdquo; programming in this video, though. I know that people will argue that you have to take a direct path to get it working quickly, but I feel that this degrades programming practice, especially when it comes from an &ldquo;official&rdquo; source like Microsoft.</p>
<p>There are things like:</p>
<ul>
<li>Defining the service-initialization code in the tests, then explaining that it&rsquo;s to ensure that it&rsquo;s the &ldquo;same as that used by the server&rdquo;. You know how else to do that? Use common initialization code in static helper methods (or whatever).</li>
<li>Copy/pasting the service-initialization code from test to test</li>
<li>Copy/pasting the <code>HTTPClient</code> code</li>
<li>Copy/pasting the <code>record</code> definition, as if that won&rsquo;t ever bite you in the butt.</li>
<li>Manually adding &ldquo;usings&rdquo; (Can&rsquo;t you just get the IDE to do that?)</li></ul><p>On top of that, the integration tests could have been a lot simpler than they looked if he&rsquo;d first explained how to set up some common code. Or, perhaps even better, if he&rsquo;d taken a couple of minutes afterwards to show how to refactor the common code to helper methods (one of which could even be used in the main application so that the app setup is shared with the tests). If he&rsquo;d used a few more IDE features to speed up coding, he might even have gotten it all in in the same amount of time.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5254</guid>
    <title><![CDATA[Don't return await unless you have to]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5254</link>
    <pubDate>Fri, 08 Nov 2024 23:08:10 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Nov 2024 23:08:10 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I finally got around to verifying that the defining dependent async methods like the following one is wasteful.</p>
<pre class=" "><code>public async Task&lt;bool&gt; N()
{
   return await M();
}</code></pre><p><a href="https://www.earthli.com/data/news/attachments/entry/5254/async-await.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5254/async-await_tn.jpg" alt=" " class=" align-right"></a>A less-contrived example looks like this:</p>
<pre class=" "><code>using System.Threading.Tasks;
public class C {
    public Task&lt;bool&gt; M() 
    {
        return Task.FromResult(false);
    }
    
    public async Task&lt;bool&gt; N() 
    {
        return await M();
    }
    
    public async void RunIt()
    {
        var result = await N();
    }
}</code></pre><p>This yields something like the following lowered C# code in <a href="https://sharplab.io/">SharpLab.IO</a>. Note that there are two state machines.</p>
<pre class=" "><code>public Task&lt;bool&gt; M()
{
    return Task.FromResult(false);
}

[AsyncStateMachine(typeof(&lt;N&gt;d__1))]
[DebuggerStepThrough]
public Task&lt;bool&gt; N()
{
    &lt;N&gt;d__1 stateMachine = new &lt;N&gt;d__1();
    stateMachine.&lt;&gt;t__builder = AsyncTaskMethodBuilder&lt;bool&gt;.Create();
    stateMachine.&lt;&gt;4__this = this;
    stateMachine.&lt;&gt;1__state = -1;
    stateMachine.&lt;&gt;t__builder.Start(ref stateMachine);
    return stateMachine.&lt;&gt;t__builder.Task;
}

[AsyncStateMachine(typeof(&lt;RunIt&gt;d__2))]
[DebuggerStepThrough]
public void RunIt()
{
    &lt;RunIt&gt;d__2 stateMachine = new &lt;RunIt&gt;d__2();
    stateMachine.&lt;&gt;t__builder = AsyncVoidMethodBuilder.Create();
    stateMachine.&lt;&gt;4__this = this;
    stateMachine.&lt;&gt;1__state = -1;
    stateMachine.&lt;&gt;t__builder.Start(ref stateMachine);
}</code></pre><p>If you write the equivalent code without the <code>await</code> in the <code>N</code> method:</p>
<pre class=" "><code>using System.Threading.Tasks;
public class C {
    public Task&lt;bool&gt; M() 
    {
        return Task.FromResult(false);
    }
    
    public Task&lt;bool&gt; N() 
    {
        return M();
    }
    
    public async void RunIt()
    {
        var result = await N();
    }
}</code></pre><p>…then you get the following lowered C#. Note that now there is only one state machine.</p>
<pre class=" "><code>public Task&lt;bool&gt; M()
{
    return Task.FromResult(false);
}

public Task&lt;bool&gt; N()
{
    return M();
}

[AsyncStateMachine(typeof(&lt;RunIt&gt;d__2))]
[DebuggerStepThrough]
public void RunIt()
{
    &lt;RunIt&gt;d__2 stateMachine = new &lt;RunIt&gt;d__2();
    stateMachine.&lt;&gt;t__builder = AsyncVoidMethodBuilder.Create();
    stateMachine.&lt;&gt;4__this = this;
    stateMachine.&lt;&gt;1__state = -1;
    stateMachine.&lt;&gt;t__builder.Start(ref stateMachine);
}</code></pre>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5251</guid>
    <title><![CDATA[Manim: a bespoke animation editor and engine]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5251</link>
    <pubDate>Fri, 08 Nov 2024 22:58:15 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Nov 2024 22:58:15 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/5251/manim-linear-transformation-3d.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5251/manim-linear-transformation-3d_tn.jpg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/5251/manim-linear-transformation-3d.jpg">Manim − linear transformation in 3d</a></span></span>This is a fun video that demonstrates an API, runtime, and IDE called <a href="https://github.com/3b1b/manim">Manim</a> that lets you interactively build 3-D animations. It&rsquo;s like a game-engine editor [1] in which you build your scenes by calling APIs in Python. There&rsquo;s an interactive Python terminal, a rendering area, and a text editor.</p>
<p>It&rsquo;s quite nicely done and he&rsquo;s put it to good use over the years, building hundreds, if not thousands, of videos with it.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/rbu7Zu5X1zI" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=rbu7Zu5X1zI">How I animate 3Blue1Brown | A Manim demo with Ben Sparks</a> by <cite>3Blue1Brown</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The API is quite high-level and robust but it&rsquo;s so clear how limited the Python syntax is. He&rsquo;s very quick with it, but he also knows the whole API by heart. He barely ever used code-completion, so I thought there wasn&rsquo;t any. But then I saw him hover a few APIs to show the expected parameters. I wonder how much time a novice would spend with interpreter errors. Still, once you&rsquo;ve gotten used to it, it seems to be pretty efficient. Python&rsquo;s interpreter speed will never be a problem. In particular, the API for integrating formulae via embedded TeX is pretty neat. It even supports identifying manipulable elements from the rendered version for further animation.</p>
<p>His style of mixing functions and code and variable definitions makes sense for the types of projects he makes. There is going to be very little re-use between these projects. Anything that needs to be reused would eventually be added to Manim itself. He doesn&rsquo;t seem to see the need for shared libraries. The code is basically throwaway. It takes more time to define common, well-generalized functions than it would to just quickly rewrite it, ready for specialization within that project.</p>
<p>As when watching Kevin Powell ask an LLM about CSS without any idea about how LLMs work, watching Grant Sanderson discuss workarounds for &ldquo;bugs&rdquo; without any decent background in languages, scopes, functions, and closures. It&rsquo;s kind of exasperating watching people &ldquo;reinvent&rdquo; computer science without even thinking that there might be prior art—especially clever people.</p>
<p>Good for Grant for making this video, though, because I think he realized that there&rsquo;s a lot of room to grow in programming skills. He&rsquo;s already noticed that LLMs aren&rsquo;t going to help him code in Manim—because he&rsquo;s an expert and the LLM is definitely not; there is no way it will be able to help him.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5251_1_body" class="footnote-number">[1]</span> It kind of reminds me of the good old days when I was working with the <a href="https://www.earthli.com/quake/maps.php">Quake III level editor</a>. The API and tools are very bespoke and very powerful.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5168</guid>
    <title><![CDATA[C# 13 improvements]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5168</link>
    <pubDate>Sun, 15 Sep 2024 23:18:39 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Sep 2024 23:18:39 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The final document of <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-13">What&rsquo;s new in C# 13</a> (<cite><a href="http://learn.microsoft.com/">Microsoft Learn</a></cite>) is available. There are no major changes for most end users; the changes listed are interested for library and framework developers—especially those interested in writing highly performant code, e.g., Microsoft in its BCL and ASP.NET.</p>
<ol>
<li>Completely unsurprisingly, the <code>params</code> keyword now also applies to <code>IEnumerable&lt;T&gt;</code> (as well as many descendants) as well as <code>Span&lt;T&gt;</code> and <code>ReadOnlySpan&lt;T&gt;</code>.</li>
<li>There&rsquo;s now an official <code>Lock</code> object that, when used instead of the standard <code>object</code>, can lead to more efficient locking code. The .NET runtime and BCL have already starting using this <code>ref struct</code> everywhere.</li>
<li>I am not kidding when I say that the third &ldquo;feature&rdquo; in the list is that <code>\e</code> is now an accepted escape sequence in all strings. It represents <code>ESCAPE</code>. Um, ok.</li>
<li>Method group and method-group calculation has been improved to more closely follow that for overload resolution, allowing Roslyn to better determine a unique type and to extend where <code>var</code> can be safely used.</li>
<li>You can now use the &ldquo;from the end&rdquo; index operator, <code>^</code> in object and collection initializer expressions. Again, this is an improvement that seems like it makes it easier to write input arrays for numeric (data analysis) or tokenizing (LLM) operations.</li>
<li><div class=" "><blockquote class="quote quote-block "><div><p>&ldquo;In C# 13, async methods can declare ref local variables, or local variables of a <code>ref struct</code> type. However, those variables can&rsquo;t be accessed across an await boundary. Neither can they be accessed across a yield return boundary.</p>
<p>&ldquo;[…] You can safely use types like <code>System.ReadOnlySpan&lt;T&gt;</code> […]</p>
<p>&ldquo;In the same fashion, C# 13 allows <code>unsafe</code> contexts in iterator methods. However, all <code>yield return</code> and <code>yield break</code> statements must be in safe contexts.&rdquo;</p>
</div></blockquote></div></li>
<li><code>ref structs</code> can now implement interfaces but it&rsquo;s hard to see the utility because <span class="quote-inline">&ldquo;[t]o ensure ref safety rules, a ref struct type can&rsquo;t be converted to an interface type.&rdquo;</span> Um, ok?</li>
<li>The language now supports the <code>allows ref struct</code> (anti-)generic constraint. <span class="quote-inline">&ldquo;This enables types such as <code>System.Span&lt;T&gt;</code> and <code>System.ReadOnlySpan&lt;T&gt;</code> to be used with generic algorithms […]&rdquo;</span> The compiler ensures that the generic code complies with all the rules implied by allowing this more specialized construct.</li>
<li>Finally, <span class="quote-inline">&ldquo;you can declare partial properties and partial indexers&rdquo;</span>. Expanding support for <code>partial</code> enables more flexibility in code produced by source generators.</li></ol>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5008</guid>
    <title><![CDATA[Wrapping text the hard way]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5008</link>
    <pubDate>Sun, 18 Aug 2024 19:39:05 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. Aug 2024 19:39:05 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The work journal <a href="https://gist.github.com/simonw/dfb7e53c2737a069c5782401c6999ad5">2024-03-27T16:03:51 conversation: 01ht0afgwryks5fepkvvm0kn28</a> by <cite>Simon Willison</cite> (<cite><a href="http://gist.github.com/">GitHub</a></cite>) describes the author&rsquo;s process of using AI prompting to write a console text-wrapping algorithm.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/5008/algorithm.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5008/algorithm_tn.jpg" alt=" " class=" align-right"></a>He prompted with <span class="quote-inline">&ldquo;JavaScript that takes a big string of text and word wraps it at the specified width, adding newlines where necessary.&rdquo;</span> The answers meandered around a solution space that seemed over-engineered and not particularly fruitful—the answers all used regular expressions, which seems kind of like overkill, when you&rsquo;re really only trying to detect a single character. A simple parser would be more effective, easier to understand,,debug, and maintain, and is more likely to be performant.</p>
<p>The original wrapping code was:</p>
<pre class=" "><code>function wordWrap(text, width) {
  const regex = new RegExp(`(?![^\\n]{1,${width}}$)([^\\n]{1,${width}})\\s`, 'g');
  return text.replace(regex, '$1\n');
}</code></pre><p>Things got hairy when Willison asked for a solution that includes an indent before each wrapped line. It&rsquo;s honestly hard to tell whether the example will actually do that, largely because of the non-obvious regular expressions (which make use of negative lookahead assertions).</p>
<pre class=" "><code>function wordWrap(text, width, indent = '') {
  const regex = new RegExp(`(?![^\\n]{1,${width}}$)([^\\n]{1,${width}})\\s`, 'g');
  return text.replace(regex, `$1\n${indent}`).replace(/^/gm, indent);
}</code></pre><p>When Willison noted that the indent appears everywhere but at the front of the text, the proposed code was:</p>
<pre class=" "><code>function wordWrap(text, width, indent = '') {
  const regex = new RegExp(`(?![^\\n]{1,${width}}$)([^\\n]{1,${width}})\\s`, 'g');
  return indent + text.replace(regex, `$1\n${indent}`);
}</code></pre><p>This looks promising, as the eye is drawn to the <code>indent +</code> at the beginning of the answer. If you look carefully, though, you&rsquo;ll see that the second call to <code>replace()</code> has gone missing. </p>
<p>This is dangerous, right? Imagine if you didn&rsquo;t have sufficient tests for this code? You can&rsquo;t really understand it, it looks vaguely right, and pieces that used to work are randomly dropped in responses to &ldquo;refinement prompts&rdquo;. He tried a few more times, but kept losing rather than gaining fidelity in the response, with one or more corner-cases no longer being supported.</p>
<p>When he told it to stop using regular expressions, it responded with:</p>
<pre class=" "><code>function wordWrap(text, width, indent = '') {
  const lines = [];
  let currentLine = '';

  text.split('\n').forEach(line =&gt; {
    if (line === '') {
      lines.push('');
    } else {
      line.split(' ').forEach(word =&gt; {
        if (currentLine.length + word.length &lt;= width) {
          currentLine += (currentLine ? ' ' : '') + word;
        } else {
          lines.push(indent + currentLine);
          currentLine = word;
        }
      });
      lines.push(indent + currentLine);
      currentLine = '';
    }
  });

  return lines.join('\n');
}</code></pre><p>This actually seems better—and Willison claims it works—but it still seems only OK. There is a lot of allocation in this response, as well as a failure to separate concerns.</p>
<p>There are a few pieces to this request:</p>
<ol>
<li>Split the string into paragraphs</li>
<li>Wrap each paragraph to lines of a given width, including an optional prefix on each line</li></ol><p>You can play with his version at <a href="https://observablehq.com/@simonw/wrap-text-at-specified-width">Wrap text at specified width</a> by <cite>Simon Willison</cite> (<cite><a href="http://observablehq.com/">Observable</a></cite>)</p>
<p>When I threw the code into WebStorm and added a test, I discovered that it doesn&rsquo;t wrap at the desired width.</p>
<ul>
<li>It fails to take the length of the indent into account when wrapping the text.</li>
<li>It doesn&rsquo;t sanity-check that the indent isn&rsquo;t bigger than the desired wrap length.</li></ul><p>At least the algorithm doesn&rsquo;t fall into the pathological trap when a word is too long on it&rsquo;s own to fit within the desired width, which would result in an infinite loop.</p>
<p>I noodled around with a solution that uses generators to avoid allocation until you actually snip text. The algorithm looks like this:</p>
<ul>
<li>Pass in a text, desired width, and indent.</li>
<li>Get a generator for all line breaks.</li>
<li>Get a generator for all word breaks in a line.</li>
<li>Yield a generator for all line spans.</li>
<li>Yield a generator from that for all lines.</li></ul><p>This strategy ensures that there are no substring allocations until you actually need them. You can get the first line or two lines without allocating more than the substrings for those lines. There are no substrings allocated to find word breaks, as the algorithm outlined above does.</p>
<p>Is it a more complex algorithm? Of course. Is it relatively easy to understand, especially with the requisite tests? Yes. Does it do its job much more efficiently? Absolutely.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5012</guid>
    <title><![CDATA[Tactics for automated testing]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5012</link>
    <pubDate>Sat, 17 Aug 2024 16:27:26 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Aug 2024 16:27:26 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://dunnhq.com/posts/2024/prefer-test-doubles-over-mocking/">Prefer test-doubles over mocking frameworks</a> by <cite>Steve Dunn</cite> writes,</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>This is testing implementation and not behaviour. Your SUT called something and there is likely an observable side-effect of that. Test the side-effect and not that a particular method was called.</strong> If the code is refactored (e.g. you change the implementation but not the behaviour), then your test that checked that a method was called will likely break, but your test that tested the behaviour should remain unchanged and should still pass.&rdquo;</div></blockquote><p>I think we have to be more careful here. Sometimes you want to test the implementation, no? If you look at the simplest test double that he&rsquo;s written in the article, shown below, you can see that there is an implicit assumption that would have to be tested: that is, that the <code>Get</code> method in the test-double accurately represents the actual implementation.</p>
<p>This is the interface to be tested.</p>
<pre class=" "><code>public interface IProductRepository
{
    void Store(Product product);
    Product Get(int id);
}</code></pre><p>This is the test using the test double:</p>
<pre class=" "><code>[Fact]
public void Using_test_doubles()
{
    var repo = new InMemoryProductRepository();

    var sut = new ProductService(repo);

    sut.OnboardNewProduct(123, "Product 123");

    repo.DidStore(123).Should().BeTrue();
}</code></pre><p>Note that the test calls a test-double-only method called <code>DidStore()</code>, which is assumed to have been implemented as expected. A naive implementation would just return <code>true</code>. Since this is a test double, there are no tests verifying that it doesn&rsquo;t always return true. Shouldn&rsquo;t the test instead verify that the product is not stored first—i.e., <code>repo.Get(123)</code> returns <code>false</code>—before calling <code>OnboardNewProduct(123, …)</code> and then testing <code>repo.Get(123)</code> again to verify that it returns <code>true</code>?</p>
<p>The following is the implementation of the test-double.</p>
<pre class=" "><code>public class InMemoryProductRepository : IProductRepository
{
    private readonly List&lt;Product&gt; _products = new();

    public void Store(Product product) =&gt; _products.Add(product);
    public Product Get(int id) =&gt;  _products.FirstOrDefault(p =&gt; p.Id == id);

    // This is not part of the interface, but is useful for testing
    public bool DidStore(int id) =&gt; Get(id) is not null;
}</code></pre><p>If you leave the test as formulated, there is literally no guarantee that anything changed at all. The author is simply assuming that <code>Store</code> adds a product <em>because he can see that it does.</em></p>
<p>The author wasn&rsquo;t quite clear why his mock-based implementation isn&rsquo;t good, though. He proposed the code below.</p>
<pre class=" "><code>[Fact]
public void Using_mocks()
{
    var repo = Substitute.For&lt;IProductRepository&gt;();
    var sut = new ProductService(mock);

    sut.OnboardNewProduct(123, "Product 123");

    repo.Received().Store(Arg.Is&lt;Product&gt;(p =&gt; p.Id == 123));
}</code></pre><p>Do you see how he checked whether the <code>Store()</code> method had been called rather than testing whether <code>Get(123)</code> returns <code>true</code>? He had to do that because the mock would always return <code>false</code> unless the author had also set up the <code>Get()</code> method to return <code>true</code> if the method were to be called with <code>123</code>. Why wouldn&rsquo;t he do this? Because he&rsquo;d then have just been testing the mock. However, if you look closely at the previous example, the author is also just testing his test-double.</p>
<p>I have another problem with the statement above: sometimes I very much want to verify that a specific method is being called. I&rsquo;m not trying to verify the behavior of the test-double; I&rsquo;m trying to verify the behavior of the <em>actual implementation</em>.</p>
<p>If, for whatever reason, I can&rsquo;t use the actual implementation, then I want to verify that a certain method was called <em>because e.g., I know that that method calls a system API directly.</em> That is, I trust that the system API will do what it says on the tin. I&rsquo;m able to verify manually that the parameters to the method are passed on to the API faithfully. I can&rsquo;t call the API in the test suite—maybe it&rsquo;s a call to the <em>Windows Registry</em> or maybe it&rsquo;s accessing a USB stick that doesn&rsquo;t exist in CI—but I can get <em>as close as possible</em>. If something still goes wrong, then I know that I just have to examine the one line of code in the actual implementation. In that way, I&rsquo;ve verified a fact about the system that means something.</p>
<p>This comes up often enough in more complex component graphs, where you&rsquo;ve had a bug that, under certain circumstances, a certain notification is not sent. In that case, you might be unable to verify that the message arrives—as we do by testing <code>Get(123)</code> above—because the actual message would go through an online proxy like Apple and would end up on a mobile device somewhere, and maybe you don&rsquo;t want to build the testing infrastructure that mocks a receiving device that you can check. It wouldn&rsquo;t help you because you&rsquo;d <em>just be testing the test-double implementation anyway.</em></p>
<p>Instead, you would trigger a high-level API that, eventually, bubbles through several layers until the notifier is triggered with a certain message. In that case, an efficient and effective test would be to test that the <code>INotifier.Send()</code> method was called with the expected parameters.</p>
<p>Even in the author&rsquo;s example, there is presumably an external data store of some sort that is being mocked. I&rsquo;m not actually interested in testing whether that data store interprets my command to store correctly. I&rsquo;m going to assume that it does <em>because it&rsquo;s not my code.</em>. [1] What I want to confirm is <em>that I sent the command to the store.</em> That is, I want to verify that a particular method was called with particular parameters. Perhaps I&rsquo;ll use a snapshot test to verify that the generated SQL is correct. Then I don&rsquo;t have to actually run the SQL against the database every time.</p>
<p>In the author&rsquo;s case, he&rsquo;s calling a method on one interface and verifying that a property of another interface has changed. He is testing the interplay of those two components. That he used test-double doesn&rsquo;t help at all—it&rsquo;s because the test-double was written correctly that the test means anything. And there are no tests to verify that the test-double actually does what he assumes it is doing.</p>
<p>While I agree that test-doubles have their place, I think that mocking frameworks can also be very helpful. That&rsquo;s why I don&rsquo;t like rules like &ldquo;test behavior not implementation&rdquo;. I prefer to consider it a <em>guideline</em>, so that I can remember to write high-level, well-abstracted tests where possible but I can also just test that a certain method on a certain component will be executed.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5012_1_body" class="footnote-number">[1]</span> If that promise is broken, then I will have to reevaluate. I could write a test to verify that the external component works as expected—just in case it breaks again—I could find a more reliable external component, I could fix the current external component, or some combination of these..</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5011</guid>
    <title><![CDATA[Upgrading to nullability in C#]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5011</link>
    <pubDate>Fri, 16 Aug 2024 03:38:49 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Aug 2024 03:38:49 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/5011/interrobang.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5011/interrobang_tn.jpg" alt=" " class=" align-right"></a>The <a href="https://blog.maartenballiauw.be/talk/2024/01/21/bringing-csharp-nullability-into-existing-code.html">Talk − Bringing C# nullability into existing code</a> by <cite>Maarten Balliauw</cite> is a 66-slide deck that I summarize as follows:</p>
<ul>
<li>The C# nullability feature is for build- and design-time. It does not enforce anything at runtime. That means that you still have to check parameters for <code>null</code>.</li>
<li>The C# nullability feature is available to solutions working with .NET Framework and .NET.</li>
<li>For .NET Framework, you have to explicitly set the <code>&lt;LanguageVersion&gt;</code> to <code>8.0</code> (however, there are a bunch of cons associated with doing this, as the runtime library itself is not annotated). [1]</li>
<li>The presentation shows how to enable and disable for the whole solution, project, or an individual code region.</li>
<li>For new solutions, enable at the solution level.</li>
<li>For small solutions, enable at the solution level and just work through it.
<li><div>For large solutions, enable project-by-project or file-by-file—or even class-by-class.<ul>
<li><span class="quote-inline">&ldquo;Start at the center and work outwards.&rdquo;</span></li>
<li>While <code>?</code> suffices in most cases, consider annotations to improve your own APIs</li>
<li>Consider redesigning APIs that return <code>null</code> (use the <code>bool TryGet&lt;T&gt;(…, out T)</code> pattern or return a &ldquo;null&rdquo; object instead).</li>
<li>Avoid allowing <code>null</code> parameters (these force a decision on the implementation that is often better handled by the caller).</li>
<li>Don&rsquo;t use <code>!</code> except temporarily</li>
<li>Don&rsquo;t use suppression except temporarily</li>
<li>Start with types that aren&rsquo;t depended on a lot. Those are easy.</li>
<li>Take types with lots of dependents one-by-one.</li></ul></div></ul><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_5011_1_body" class="footnote-number">[1]</span> <p>For more information, see <a href="https://endjin.com/blog/2020/07/dotnet-csharp-8-nullable-references-supporting-older-runtimes">C# 8.0 nullable references: supporting older runtimes</a> by <cite>Ian Griffiths</cite>, published in July of 2021. Also, the article <a href="https://medium.com/@joni2nja/consider-using-c-8-with-the-net-framework-9dceb20647c5">Consider using C# 8 with the .NET Framework</a> cites from <a href="https://devblogs.microsoft.com/dotnet/building-c-8-0/">Building C# 8.0</a> by Mads Torgersen. Both of those articles are from 2018.</p>
<blockquote class="quote quote-block "><div>&ldquo;using C# 8.0 is only supported on platforms that implement .NET Standard 2.1&rdquo;</div></blockquote><p>.NET Framework doesn&rsquo;t implement .NET Standard 2.1</p>
<p>However, the StackOverflow post <a href="https://stackoverflow.com/questions/56651472/does-c-sharp-8-support-the-net-framework">Does C# 8 support the .NET Framework?</a> goes into some detail about <em>which</em> features of C# 8.0 <em>could</em> be supported under .NET Framework. That post notes that <em>syntax-only</em> changes will continue to work, which makes sense. As long as you use a newer compiler that understands the syntax, the lowered code and subsequent generated IL will be compatible with the .NET Framework runtime. That&rsquo;s what syntax-only means: no new functionality was required in the runtime in order to support the generated output.</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#static-local-functions">Static local functions</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#using-declarations">Using declarations</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#null-coalescing-assignment">Null-coalescing assignment</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#readonly-members">Readonly members</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#disposable-ref-structs">Disposable ref structs</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#positional-patterns">Positional patterns</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#tuple-patterns">Tuple patterns</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#switch-expressions">Switch expressions</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#nullable-reference-types">Nullable reference types</a> are also supported, but the new <a href="http://learn.microsoft.com/en-us/dotnet/csharp/nullable-attributes">nullable attributes</a> required to design the more complex nullable use cases are not. However, according to <a href="https://endjin.com/blog/2020/07/dotnet-csharp-8-nullable-references-supporting-older-runtimes) (from July 2020">C# 8.0 nullable references: supporting older runtimes</a>, there&rsquo;s a <a href="https://www.nuget.org/packages/Nullable/">Nullable Nuget package</a>. Be aware, though, that the .NET Framework is not itself annotated, so you will probably see spurious warnings when the compiler can&rsquo;t tell that a result can never be null.</li></ul><p>That&rsquo;s a lot of features, actually!</p>
<p>The StackOverflow post linked above lists them quite well, and <a href="https://stu.dev/csharp8-doing-unsupported-things/">C# 8.0 and .NET Standard 2.0 − Doing Unsupported Things</a> has some more information about which level of change each C# 8.0 feature requires.</p>
<p>That said,</p>
<blockquote class="quote quote-block "><div>&ldquo;The C# 8/.NET Framework combination is not officially supported by Microsoft. It is, they say, for experts only.&rdquo;</div></blockquote></div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5125</guid>
    <title><![CDATA[Ignoring files with .gitignore]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5125</link>
    <pubDate>Sun, 07 Jul 2024 21:18:27 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">7. Jul 2024 21:18:27 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <h2>Introduction</h2><p>This article defines concepts like <em>repository</em> and <em>working tree</em> and then discusses how you can use <code>.gitignore</code> files to determine the files and folders that Git considers during operations.</p>
<h2>Concepts</h2><p><a href="https://www.earthli.com/data/news/attachments/entry/5125/git-logo.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5125/git-logo_tn.jpg" alt=" " class=" align-right"></a>From a command line, you can run <code>git init</code> in any folder to make any folder a Git repository. Doing so creates a <code>.git</code> folder with a database and configuration files for the local repository. Git considers any folder that contains a <code>.git</code> folder with these configuration and database files in it to be a Git repository.</p>
<p>The <em>working tree</em> of such a folder is all files and subfolders in that folder other than the <code>.git</code> folder.</p>
<p>Any non-trivial repository will contain at least some files that should not be committed to the Git repository. Commonly, these are build artifacts produced from the source files that <em>are</em> included in the repository.</p>
<h2><code>.gitignore</code></h2><p>A repository may include multiple <code>.gitignore</code> files. From the <a href="https://git-scm.com/docs/gitignore">official documentation]</a>:</p>
<blockquote class="quote quote-block "><div>&ldquo;Patterns read from a .gitignore file in the same directory as the path, or in any parent directory (up to the top-level of the working tree), with patterns in the higher level files being overridden by those in lower level files down to the directory containing the file. These patterns match relative to the location of the <code>.gitignore</code> file.&rdquo;</div></blockquote><p>Git determines whether a given file is included in the working tree by collecting the patterns from any <code>.gitignore</code> file anywhere in that file&rsquo;s path. Patterns defined &ldquo;closer&rdquo; to the file override those defined &ldquo;farther&rdquo; away.</p>
<p>For example,</p>
<pre class=" "><code>[Root]
  📄 .gitignore
  📁 ProductMedia
     📁 Win10
        📁 Content
           📄 .gitignore
           📁 Deploy
              📁 Control
                 📄 .gitignore
                 📄 readme.txt
</code></pre><p>Git determines whether <code>readme.txt</code> is included in the working tree by collecting the rules from files in the following order:</p>
<ul>
<li><code>.gitignore</code></li>
<li><code>ProductMedia/Win10/Content/.gitignore</code></li>
<li><code>ProductMedia/Win10/Content/Deploy/Control/.gitignore</code></li></ul><h2>Patterns</h2><div class="caution ">This section provides a brief overview with examples for common and more advanced cases that have been needed at Uster. For more information, see <a href="https://git-scm.com/docs/gitignore#_pattern_format">all supported patterns</a> in the official documentation.</div><p>A <code>.gitignore</code> file contains zero or more <em>patterns</em>.</p>
<ul>
<li>Each pattern excludes the affected files from the working tree</li>
<li>Each pattern affects only files in the sub-tree defined by the sub-folder in which the pattern is declared.</li>
<li>Each pattern is interpreted <em>relative</em> to its containing folder (i.e., the <em>root folder</em> for a pattern is its declaration folder).</li></ul><p>The following examples illustrate common patterns.</p>
<p>The column &ldquo;Disables subsequent patterns&rdquo; indicates whether subsequent patterns that target files in the ignored sub-tree will have an effect. As <a href="#difference-between-%60/%60-and-%60/*%60">detailed below</a>, the presence of a trailing <code>*</code> determines whether Git considers subsequent rules. This only becomes relevant for <a href="#re-including-deeply-nested-files">re-including deeply nested files</a>.</p>
<dl><dt class="field"><code>obj/</code></dt>
<dd><div class=" "><p>All files in any folder named <code>obj</code> anywhere in the sub-tree of the current folder or any sub-folder thereof. </p>
<p>Disables subsequent pattern: <em>Yes</em></p>
</div></dd>
<dt class="field"><code>/obj/</code></dt>
<dd><div class=" "><p>All files in the <em>root folder</em> named <code>obj</code> or any sub-folder thereof.</p>
<p>Disables subsequent pattern: <em>Yes</em></p>
</div></dd>
<dt class="field"><code>/obj/*</code></dt>
<dd><div class=" "><p>All files in the <em>root folder</em> named <code>obj</code> or any sub-folder thereof.</p>
<p>Disables subsequent pattern: <em>No</em></p>
</div></dd>
<dt class="field"><code>*.bin</code></dt>
<dd><div class=" "><p>All files ending in <code>.bin</code> anywhere in the sub-tree of the current folder.</p>
<p>Disables subsequent pattern: <em>Yes, but irrelevant</em></p>
</div></dd>
<dt class="field"><code>src/*/out/bin</code></dt>
<dd><div class=" "><p>All files in any path named <code>out/bin</code> found in any single sub-folder of any folder named <code>src</code> anywhere in the sub-tree of the current folder.</p>
<p>Disables subsequent pattern: <em>Yes</em></p>
</div></dd>
<dt class="field"><code>src/**/out/bin</code></dt>
<dd><div class=" "><p>All files in any path named <code>out/bin</code> found anywhere in any combination of sub-folders of the sub-tree of any folder named <code>src</code> anywhere in the sub-tree of the current folder.</p>
<p>Disables subsequent pattern: <em>Yes</em></p>
</div></dd>
</dl><h3>Re-including files</h3><p>You can also <em>re-include</em> files with the <code>!</code> operator. For example, you might want to exclude everything in a folder but a single configuration file.</p>
<p>The following example ignores everything in the <code>/out</code> folder <em>except for</em> the file <code>settings.json</code>.</p>
<pre class=" "><code>/out
!/out/settings.json</code></pre><h3>Difference between <code>/</code> and <code>/*</code></h3><p>As very nicely explained in the answer on StackOverflow <a href="https://stackoverflow.com/a/5534865/178874">.gitignore exclude folder but include specific subfolder</a>, </p>
<blockquote class="quote quote-block "><div><ul>
<li>The pattern <code>dir/</code> excludes a directory named <code>dir</code> and (implicitly) everything under it. With <code>dir/</code>, Git will never look at anything under <code>dir</code>, and thus will never apply any of the &ldquo;un-exclude&rdquo; patterns to anything under <code>dir</code>.</li>
<li>The pattern <code>dir/*</code> says nothing about <code>dir</code> itself; it just excludes everything under <code>dir</code>. With <code>dir/*</code>, Git will process the direct contents of <code>dir</code>, giving other patterns a chance to &ldquo;un-exclude&rdquo; some bit of the content (<code>!dir/sub/</code>).</li></ul></div></blockquote><p>For example, the following patterns ignore all files in <code>obj</code> and <code>bin</code> folders but files named <code>readme.md</code> in those folders should be included. The following patterns achieve this for <code>obj</code> but not for <code>bin</code> folders (because the missing <code>*</code> prevents Git from considering the rule re-including <code>readme.md</code> for <code>bin</code> folders).</p>
<pre class=" "><code>/obj/*
!/obj/Readme.md
/bin/
!/bin/Readme.md</code></pre><p>This distinction is highly relevant for the next section.</p>
<h3>Re-including deeply nested files</h3><div class="caution ">As linked above, the answer on StackOverflow <a href="https://stackoverflow.com/a/5534865/178874">.gitignore exclude folder but include specific subfolder</a> was invaluable in determining how to do accomplish the task below.</div><p>Suppose we have a folder structure as shown below.</p>
<pre class=" "><code>[Root]
  📁 Folder1
  📁 Folder2
  📁 Folder3
  📁 ProductMedia
      📁 Win10
         📁 Content
           📄 Other files…
           📁 Deploy
             📁 Control
               📄 CustomerSettings.ini
               📄 Bootstrap.ini
               📄 Settings.xml
               📄 Other files…
           📁 Folder1
           📁 Folder2
           📁 Folder3
           📁 Other folders…
      📁 Win11
         📁 Content
           📄 Other files…
           📁 Deploy
             📁 Control
               📄 CustomerSettings.ini
               📄 Bootstrap.ini
               📄 Settings.xml
               📄 Other files…
             📁 Folder1
             📁 Folder2
             📁 Folder3
             📁 Other folders…
           📁 Folder1
           📁 Folder2
           📁 Folder3
           📁 Other folders…</code></pre><p>We want the patterns that will ignore everything in any files in the <code>Content</code> folder of any sub-folder of <code>ProductMedia</code> except for the <code>CustomerSettings.ini</code>, <code>Bootstrap.ini</code>, and <code>Settings.xml</code> files under the path <code>Content/Deploy/Control/</code> of any sub-folder of <code>ProductMedia/</code>.</p>
<p>You might think that the following would do the trick:</p>
<pre class=" "><code><span class="comment"># Ignore everything in the "Content" folder of any subfolder of "ProductMedia"</span>
ProductMedia/*/Content/*

<span class="comment"># Except for the specified files under the path "Content/Deploy/Control/"</span>
!ProductMedia/*/Content/Deploy/Control/CustomerSettings.ini
!ProductMedia/*/Content/Deploy/Control/Bootstrap.ini
!ProductMedia/*/Content/Deploy/Control/Settings.xml</code></pre><p>Microsoft Copilot certainly thought so. This does not have the intended effect.</p>
<p>The pattern correctly uses the <code>*</code> to indicate that Git should continue processing patterns for sub-trees of the excluded folder. It also correctly ensures that the rule applies both to <code>Win10</code> and <code>Win11</code> folders by using a <code>*</code>.</p>
<p>However, while patterns affecting the path <code>Content</code> will be considered, those affecting <code>Content/Deploy</code> or any sub-folder thereof <em>will not</em>.</p>
<p>The trick, as outlined in the <a href="https://stackoverflow.com/a/5534865/178874">StackOverflow answer</a>, is to re-include, then exclude each individual sub-folder in the path, as shown below.</p>
<pre class=" "><code><span class="comment"># We ignore the generated "Content" subfolders in the ProductMedia folder</span>
ProductMedia/**/Content/*                    <span class="comment"># Allow subsequent processing</span>
# Except for certain configuration files
!ProductMedia/**/Content/Deploy/             <span class="comment"># Include "Deploy", allowing subsequent processing</span>
ProductMedia/**/Content/Deploy/*             <span class="comment"># Ignore everything in "Deploy"</span>

!ProductMedia/**/Content/Deploy/Control/     <span class="comment"># Include "Content", allowing subsequent processing</span>
ProductMedia/**/Content/Deploy/Control/*     <span class="comment"># Ignore everything in "Content"</span>

<span class="comment"># Finally, include the desired individual files</span>

!ProductMedia/**/Content/Deploy/Control/CustomSettings.ini
!ProductMedia/**/Content/Deploy/Control/Bootstrap.ini
!ProductMedia/**/Content/Deploy/Control/Settings.xml</code></pre><p>This pattern of re-including, then re-excluding each sub-folder suffices to allow Git to consider the file patterns at the end, while still ignoring all other files in any sub-trees that would otherwise have been included.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5081</guid>
    <title><![CDATA[Building RegEx from scratch with Stephen Toub]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5081</link>
    <pubDate>Sat, 18 May 2024 21:21:32 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. May 2024 21:21:32 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This is another excellent 1-hour tour of another complex corner of .NET. Toub describes and shows how the source-generated RegEx engine works.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/ptKjWPC7pqw" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=ptKjWPC7pqw">Deep Dive into RegEx with Stephen Toub</a> by <cite>dotnet / Scott Hanselmann</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<ul>
<li>The generated source is human-readable and debuggable.</li>
<li>It is well-commented.</li>
<li>It updates in real-time as you change the expression.</li>
<li>It includes XML documentation that describes the regular expression in plain English.</li>
<li>They rewrote the compiler in .NET 7 to not only better support source generators, but also to be able to emit not only IL, but source code. They rebuilt the emitter to allow more leeway in code-generation—the first generation emitted C# that looked very much like IL.</li>
<li>They have a gigantic test-suite that they culled from open-source code. 4M expressions deduplicated down to about 20,000 unique expressions that they have in the test suite and that they run against all four RegEx engines to verify that nothing runs pathologically long or with excessive memory.</li>
<li>There is an analyzer that tries very hard to eliminate greediness. It seeks atomicity. Fascinating.</li>
<li>At <strong>47:00</strong>, he shows a great example of a regex that requires backtracking, which can lead to pathological, exponential performance. These engines support back-references, which are powerful. They can be super-fast for matches, but they have very bad worst-case behavior that may end up in DDOS behavior. In .NET, you can set a timeout on your regular-expression evaluation to avoid this. You can also set a global timeout. You can also turn off back-tracking. If it can produce the engine to evaluate the expression, then it will evaluate in linear time. If it cannot, it&rsquo;s probably a compile-time error if you&rsquo;re using source generators, which is quite nice.</li>
<li>They also examine an email-address RegEx, which takes Toub into showing how the generated source uses the <code>SearchValues</code> variants, which are a highly-optimized way of searching text, with dozens of algorithms that it chooses by analyzing the input string. They have SIMD/Vector/Arm Intrinsics support where possible and are exactly the kind of optimization that a framework like .NET can offer, but that an app developer would never have time to make.</li></ul><p>💙 Stephen Toub. He&rsquo;s absolutely brilliant. Mad props to Scott Hanselmann for reining him in and providing a great sparring partner.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5075</guid>
    <title><![CDATA[Building async/await from scratch with Stephen Toub]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5075</link>
    <pubDate>Sat, 18 May 2024 21:17:22 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. May 2024 21:17:22 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This is another video from Stephen Toub that is just chock/full of useful information.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/R-z2Hv-7nxk" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=R-z2Hv-7nxk">Writing async/await from scratch in C# with Stephen Toub</a> by <cite>dotnet</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>At <strong>27:30</strong>, they start to discuss about the nomenclature of <code>Task</code> and how it differs from an <code>Action</code>. It&rsquo;s funny that neither of them mentioned that <em>tasks</em> in .NET are called <em>promises</em> pretty much everywhere else (JavaScript, Java, etc.). Some libraries also use the word <em>future</em>. For more information, see <a href="https://en.wikipedia.org/wiki/Futures_and_promises">Futures and promises</a> (<cite><a href="http://en.wikipedia.org/">Wikipedia</a></cite>).</p>
<p>As he&rsquo;s building everything, it is really astonishing to note that Hanselmann has to tell Toub that you can have <em>Visual Studio</em> generate methods for you. How does he not know that? When he did it, he then used the mouse to select &ldquo;Find References&rdquo; from the shortcut menu instead of just pressing <kbd>F12</kbd>. When he got to the method, he said <span class="quote-inline">&ldquo;Oh, it didn&rsquo;t implement it,&rdquo;</span> as if disappointed that Copilot hadn&rsquo;t botshit a version in there for him. He was going to write it himself anyway, but it was telling that he&rsquo;s gotten so accustomed to Copilot just filling in implementation.</p>
<p>A little while later, he&rsquo;s learned the new tool, telling Hanselmann that he&rsquo;s going to use his <span class="quote-inline">&ldquo;trick&rdquo;</span> to create the method.</p>
<p>At around <strong>52:30</strong>, he implemented a <code>try</code>/<code>catch</code> to <span class="quote-inline">&ldquo;be a good citizen&rdquo;</span> and accepted what Copilot had recommended for him, but it didn&rsquo;t match <em>what he said he was writing</em>. He said <span class="quote-inline">&ldquo;so we always set the task result&rdquo;</span> but the code that he/Copilot wrote <em>returned</em> from the <code>catch</code>, which means that the task result isn&rsquo;t going to be set when there is an exception. Now I don&rsquo;t know which one he meant: what he said he wanted to write (did he misspeak?) or what he actually wrote (which Copilot wrote for him and he might have automatically accepted).</p>
<p>Since he has no tests whatsoever, this is exactly the kind of subtle bug that might go undetected for quite a while, as it&rsquo;s in the exception-handling code. It might also be quite difficult to diagnose.</p>
<p>When he wrote the exact same thing again at <strong>1:00:00</strong>, he seemed to indicate that what it wrote was OK: i.e., it either sets the exception or it sets the result.</p>
<p>At <strong>56:00</strong>, he gets to the point of trying to get to the synchronous calling style supported by <code>await</code> and builds his own logic. It works, but it still can&rsquo;t be used with the <code>await</code> keyword. He quickly implements a <code>TaskAwaiter</code> and voila! 🧙‍♂️ it works! His very own implementation of the <em>Task</em> pattern that integrates with the compiler.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5074</guid>
    <title><![CDATA[Building LINQ from scratch with Stephen Toub]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5074</link>
    <pubDate>Sat, 18 May 2024 21:11:44 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. May 2024 21:11:44 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This is a great interview with the master of performance-optimization in .NET Stephen Toub. If you&rsquo;re relatively well-versed in C#, .NET, and Linq, then you can just jump to the second video (linked below). I actually watched the second one first. I didn&rsquo;t feel like I&rsquo;d missed anything.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/xKr96nIyCFM" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=xKr96nIyCFM">Deep Dive on LINQ with Stephen Toub</a> by <cite>dotnet</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Stephen Toub&rsquo;s the guy who writes the 100+-page release notes on performance. See the following links.</p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-5/">Performance Improvements in .NET 5</a> (46 pages)</li>
<li><a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/">Performance Improvements in .NET 6</a> (109 pages)</li>
<li><a href="https://devblogs.microsoft.com/dotnet/performance_improvements_in_net_7/">Performance Improvements in .NET 7</a> (170 pages)</li>
<li><a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/">Performance Improvements in .NET 8</a> (235 pages)</li>
<li>…more to come.</li></ul><p>In this video, at <strong>26:00</strong>, Scott flubbed the joke. It doesn&rsquo;t really matter but, according to the article <a href="https://martinfowler.com/bliki/TwoHardThings.html">Two Hard Things</a> by <cite>Martin Fowler</cite>, the original saying was:</p>
<div><div class="auto-content-block"><blockquote class="quote quote-block "><div>&ldquo;There are only two hard things in Computer Science: cache invalidation and naming things.&rdquo;</div></blockquote></div><div class="auto-content-caption">&mdash;<cite>Phil Karlton</cite></div></div><p>This was &ldquo;upgraded&rdquo; to:</p>
<div><div class="auto-content-block"><blockquote class="quote quote-block "><div>&ldquo;There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors.&rdquo;</div></blockquote></div><div class="auto-content-caption">&mdash;<cite>Leon Bambrick</cite></div></div><p>At <strong>33:00</strong>, Toub talks about how the <code>Current</code> property of <code>IEnumerable</code> is not checked for nullability because … it can technically always be null, but we also don&rsquo;t use it that much and we don&rsquo;t want the compiler yelling at you for possibly-null access when the item type is a value type (for example) or a non-nullable reference type. See the <a href="https://github.com/dotnet/runtime/blob/2ad47cd52ebe57c1b4c2e28f95cc4eed6fcb354d/src/libraries/System.Private.CoreLib/src/System/Collections/IEnumerator.cs#L25">code</a> for the annotation and more comments.</p>
<p>At <strong>49:00</strong>, they discuss the use of <code>goto</code>, where Hanselmann says, <span class="quote-inline">&ldquo;there&rsquo;s the kind that you can see; and there are the kind that are hidden,&rdquo;</span> which I feel like he fumbled as well. I think what he meant was that there are <em>implicit <code>gotos</code></em> everywhere. A <code>goto</code> maps to an assembler <code>jmp</code>, so every <code>if</code> has an implicit <code>goto</code>. The <code>break</code> statement inside of a <code>case</code> block of a <code>switch</code> statement <em>jumps</em> (or <em>goes to</em>) the end of the <code>switch</code> block.</p>
<p>You should be careful about using <code>goto</code>—i.e., it&rsquo;s a code smell—but sometimes it&rsquo;s the clearest and most concise way of expressing intent. In their case, they used it to &ldquo;fall through&rdquo; from one <code>case</code> statement to the next with <code>goto case 2</code>.</p>
<p>I feel the same way about <code>goto</code> as I do about the <code>continue</code> keyword in a loop. I like to write all of my loops in a consistent and idiomatic manner. That means I use <code>break</code>. So, for me, using <code>continue</code> is a code smell, but sometimes it&rsquo;s the most elegant way of expressing the intent.</p>
<p>At about <strong>55:00</strong>, Hanselmann shows Toub how to use <em>Winget</em> to install <em>SysInternals</em> and then to use <em>ZoomIt</em> for presentations. This was a nice bonus that probably a lot of viewers didn&rsquo;t know: (A) <em>Zoomit</em> is a poor tool compared to <kbd>Ctrl</kbd> + mouse-scroll on MacOS, but it&rsquo;s better than nothing and (B) running <em>Winget</em> from PowerShell is a pretty powerful install-and-update tool on Windows.</p>
<p>In this presentation, I notice that Toub doesn&rsquo;t use the &ldquo;extract variable&rdquo; refactoring either. I&rsquo;m not sure whether something like that is available in VS. He also installs packages with the VS NuGet interface rather than just adding the package reference manually in the project file. I note other inefficiencies in his coding style in the notes to the second video below. He&rsquo;s fast! …but he could be even faster.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/W4-NVVNwCWs" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=W4-NVVNwCWs">An even DEEPER Dive into LINQ with Stephen Toub</a> by <cite>dotnet</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>At about <strong>22:00</strong>, he mentions something interesting that makes me change my opinion about the type to use for private variables. I&rsquo;d always used interfaces to keep it clear which API my implementations depended on. This included list variables, which I would type as <code>IList&lt;IBase&gt;</code> instead of <code>List&lt;IBase&gt;</code>. Toub says that the second formulation is better for performance because the compiler doesn&rsquo;t have to deal with virtual dispatch—it can just call the functions of <code>List</code> directly.</p>
<p>This makes me realize that it&rsquo;s a good reason to use <code>var</code>. When you use <code>var</code> with <code>new</code>, the resulting type of the local variable will automatically be the &ldquo;right&rdquo; type for performance. The same goes for <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/target-typed-new">target-typed <code>new</code> expressions</a>, which force you to use a non-interface type for fields.</p>
<div class="caution "> 👉 There are inspections in <em>Visual Studio</em>, <em>ReSharper</em>, and <em>Rider</em> that help you shape your private APIs for optimal performance.</div><p>At <strong>27:00</strong>, they talk about the IDE features for tracking change and inspection states—the colorful splotches of color in the left and right gutters and on the vertical scroll bar. First of all, Toub doesn&rsquo;t know left from right, but he&rsquo;s a genius so we&rsquo;ll grant him that. Second of all, neither he nor Hanselmann really understands what the file-state markings are.</p>
<p>The IDE tracks not only unsaved changes but also <em>uncommitted changes</em>. That&rsquo;s why there is so much green in the gutter on the left <em>and</em> the right: because Toub had rewritten much of the file since the last commit but he&rsquo;s been saving the file the entire time. It&rsquo;s an important distinction to make for understanding what&rsquo;s going on. The right-hand side of the right-hand gutter shows inspections: suggestions, warnings, and errors.</p>
<p>It was interesting to see that, since Toub uses Visual Studio without ReSharper, he instinctively used the mouse to copy/paste the name of the constructor from the class after he&rsquo;d renamed the class. That is, he&rsquo;d renamed the class and, in order to fix the constructor being named incorrectly, he copy/pasted with the mouse. With ReSharper, he could have just pressed <kbd>Alt</kbd> + <kbd>Enter</kbd> and selected the quick-fix called &ldquo;This is a constructor&rdquo;, which just renames the method to the name of the containing class.</p>
<p>I could see several places where he used the mouse rather than being able to stay on the keyboard, letting the IDE do his work for him. For example, he also copy/pasted the name of the iterator class again in order to use the more highly specialized version—but he could have just started typing to have the auto-complete suggest the right type. Or he could have used multiple clipboards to paste the type name that he&rsquo;d just copied before (when he&rsquo;d fixed the constructor).</p>
<p>When the type of the actual argument no longer matched the formal argument, he copy/pasted <em>again</em> to get the more specific type. Here, he could have also asked ReSharper to show variables in scope with an appropriate type. It would have shown only <code>array</code> and been done with it. No mouse, no copy/pasting, no moving away from the keyboard, no guesswork.</p>
<p>At about <strong>35:00</strong> or so, shit gets real, as Toub starts hand-optimizing the code for his iterator. He does some obvious stuff first, removing iterator complexity that is no longer needed when the iterator has to handle only fixed-length and integer-indexable arrays. Next, though, he does a neat trick with a <code>uint</code> cast that ensures that a check for <code>i &lt; source.Length</code> will never be true, even if <code>i</code> is less than <code>0</code> (because <code>(uint)-1</code> wraps to approximately 2 × <code>int.Max</code>, so it will never be less than <code>Length</code>. After that, he talks about how the jitter can use that condition to avoid the automated bounds-checking that comes with .NET&rsquo;s managed code by default when indexing the array.</p>
<p>So the cast to <code>uint</code> not only avoids a branch, it also avoids the <em>hidden</em> cost of bounds-checking. Nice! 👏 After running the benchmark again, we can see that he&rsquo;s rebuilt the optimizations available in C# by default. Very nice! 👏 👏 This is why running against a newer runtime and library may increase the performance ⏱ of your own code. Toub mentions that these types of optimizations are great, but they have to balance the value of the optimization versus the additional code to maintain as well as the size of the runtime assemblies.</p>
<p>At <strong>49:00</strong>, he mentions that the size issue also affects Native AOT, since AOT can&rsquo;t take advantage of PGO or anything else that the jitter has available to eliminate unnecessary code. AOT doesn&rsquo;t have as much information available, so it can&rsquo;t optimize away as much code. That is, if it can&rsquo;t guarantee that only the array-optimized version is called, then it has to keep <em>all</em> of the versions, increasing the binary size. There are also vector-optimizations and SIMD-optimizations that may have to be included. For more information, see <a href="https://www.earthli.com/news/view_article.php?id=4895">AOT, JIT, and PGO in .NET</a>.</p>
<p>The extremely detailed chapter overview.</p>
<pre class=" " style="font-size: smaller">00:00:00 Deep Dive into Implementing Iteration in Programming
00:01:50 Understanding the Implementation and Functionality of Custom Iterators in Link
00:07:45 Discussing Optimization Strategies and Array Specialization in Programming
00:10:43 Understanding the Use of Sharp Lab and Compiler Optimization in C
00:15:20 Discussing Optimizations in Link Methods in Programming
00:16:39 Understanding SIMD and its Application in Computer Processing
00:20:12 Discussion on Code Analysis and Optimization Techniques in Software Development
00:23:46 Discussing and Implementing Iteration-Based and Manual Arrays in Programming
00:30:30 Exploring Compiler Optimizations and State Management in Programming
00:37:04 Exploring Hyper and Micro Optimization in Programming
00:40:11 Exploring Code Optimizations and Trade-offs in Programming
00:45:41 Discussing the Challenges and Implications of Optimizations in Software Performance
00:47:54 Discussing the Implementation and Optimization of Select in Programming
00:51:49 Discussion on Programming Syntax and Benchmarks
00:54:41 Implementing and Discussing Iteration Code in Programming
00:57:12 Understanding the Functionality and Implementation of C# Compiler Keywords
01:02:42 Improving Functionality and Performance of Manual Implementation of Iteration Methods
01:08:39 Exploring the Optimization and Implementation of Select Operators in Programming
01:12:57 Understanding and Optimizing Iteration Operations in Programming
01:18:09 Implementing and Utilizing LINQ Programming: A Two-Parter</pre>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5049</guid>
    <title><![CDATA[It's 2024. How's it going, JavaScript?]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5049</link>
    <pubDate>Wed, 24 Apr 2024 22:40:21 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">24. Apr 2024 22:40:21 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This video is from a great channel, which published a lot of great videos a while back. They covered pretty much everything already, but circled back to JavaScript for 2024.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/aWfYxg-Ypm4" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=aWfYxg-Ypm4">Interview with Senior JS Developer 2024</a> by <cite>Programmers are also human</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Some choice quotes from the video.</p>
<blockquote class="quote quote-block "><div>&ldquo;We push on save.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;2024 is the year of the serverlesslessness.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;They say that every year, but this year they’re out of VC funding.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Don&rsquo;t write this down, next week all of this is gonna change.&rdquo;</div></blockquote><p>This guy just keeps knocking it out of the park. Pretty much everything he mentioned exists and is as described.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/5049/javascript_2024_framework_usage.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/5049/javascript_2024_framework_usage_tn.jpg" alt=" " class=" align-left"></a><a href="https://www.earthli.com/data/news/attachments/entry/5049/javascript-framework-is-more-popular.png"><img src="https://www.earthli.com/data/news/attachments/entry/5049/javascript-framework-is-more-popular_tn.png" alt=" " class=" align-right"></a></p>
<p>&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=5031</guid>
    <title><![CDATA[Avoid primary constructors in C# (for now)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=5031</link>
    <pubDate>Wed, 17 Apr 2024 11:01:32 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Apr 2024 11:01:32 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Apr 2024 11:14:05 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <div class="caution "><strong>tl;dr:</strong> avoid C# 12's primary constructors for classes except for very small, simple classes, in which case you should consider using a <code>record</code> instead.</div><p>The following video discusses the downsides of the current implementation of primary constructors:</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/IABO8O9cZOw" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=IABO8O9cZOw">The C# 12 Feature You Shouldn&rsquo;t Use, Yet</a> by <cite>Nick Chapsas</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>To sum up:</p>
<ul>
<li>Primary constructors don&rsquo;t have a <code>readonly</code> backing field; you can still assign to it within the type.</li>
<li>You can&rsquo;t control the visibility of the generated property or backing field.</li>
<li>You can&rsquo;t throw exceptions, except in a field-initializer, which isn&rsquo;t as obvious or clean as doing so from within a standard constructor</li></ul><p>Nick contrasts the C# implementation with the language feature in Kotlin, which allows all modifiers in the declaration, but has the same problem that the class definition can get pretty wordy.</p>
<p>The article <a href="https://blog.jetbrains.com/dotnet/2023/11/23/primary-constructors-using-csharp-12-in-rider-and-resharper/">Primary Constructors – Using C# 12 in Rider and ReSharper</a> by <cite>Matthias Koch</cite> (<cite><a href="http://blog.jetbrains.com/">JetBrains Blog</a></cite>) describes another ugly phenomenon: <em>double capture</em>.</p>
<blockquote class="quote quote-block "><div><p>Let’s consider the following example:</p>
<pre class=" "><code>public class Person(int age)
{
    // initialization
    public int Age { get; set; } = age;
    // capture
    public string Bio =&gt; $"My age is {age}!";
}</code></pre>In this class, the parameter <code>age</code> is exposed both through the <code>Age</code> and <code>Bio</code> property. As a result, the object stores the state of <code>age</code> twice! For reference types, a double capture leads to an increased memory footprint and possibly even memory leaks. In our concrete example, you will observe the following unintended behavior:<pre class=" "><code>var p = new Person(42);
p.Age.Dump();   // Output: 42
p.Bio.Dump();   // Output: My age is 42!
p.Age++;
p.Age.Dump();   // Output: 43
p.Bio.Dump();   // Output: My age is 42! // !!!!</code></pre></div></blockquote>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4978</guid>
    <title><![CDATA[Fighting with Fowler on Continuous Integration]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4978</link>
    <pubDate>Mon, 18 Mar 2024 10:56:49 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. Mar 2024 10:56:49 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. Mar 2024 11:18:01 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/4978/continuous-integration-2-1838591166.png"><img title="CI" src="https://www.earthli.com/data/news/attachments/entry/4978/continuous-integration-2-1838591166_tn.png" alt=" " class=" align-right"></a>The article <a href="https://martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a> by <cite>Martin Fowler</cite> makes many interesting points. It is a compendium of know-how about CI by one of the industry heavyweights, who&rsquo;s been using it for a long time.</p>
<p>While I found a lot of what he had to say interesting, I did wonder how applicable CI is for the kinds of teams that I know and work with. He makes several statements toward that end that pretty severely limit the applicability of what he calls &ldquo;true CI&rdquo; for many, if not most, teams.</p>
<p>I think he should have started his article with a very clear delineation for which kinds of organizations this kind of process is appropriate or efficient. In leaving it out, he seems to suggest that it&rsquo;s the best for everyone, but at the end of the article, he lists what are, for me, quite severe restrictions. For example,</p>
<ul>
<li><span class="quote-inline">&ldquo;Continuous Integration is more suited for team <strong>working full-time on a product</strong> […]&rdquo;</span></li>
<li><span class="quote-inline">&ldquo;[…] <strong>elite teams</strong> deployed to production more rapidly, more frequently, and had a dramatically lower incidence of failure when they made these changes.&rdquo;</span></li>
<li><span class="quote-inline">&ldquo;If a team attempts Continuous Integration <strong>without a strong test suite</strong>, they will run into all sorts of <strong>trouble</strong>&rdquo;</span></li></ul><p>I don&rsquo;t get the impression that Fowler is discussing a dream scenario toward which one works, but rather what he considers to be the absolute minimum process that anyone should be utterly embarrassed about themselves for not already having. I didn&rsquo;t see a single sentence in this 40-page, at-times repetitive document about how to actually get there from here—or whether that&rsquo;s really appropriate for many projects that people who read Martin Fowler might be working on.</p>
<p>I wonder about the wisdom of prioritizing integration seemingly above all else.</p>
<p>Below are citations from the long paper, with my comments interleaved.</p>
<blockquote class="quote quote-block "><div>&ldquo;This contrast isn&rsquo;t the result of an expensive and complex tool. The essence of it lies in <strong>the simple practice of everyone on the team integrating frequently, at least daily</strong>, against a controlled source code repository. This practice is called “Continuous Integration” (or it’s called “Trunk-Based Development”).&rdquo;</div></blockquote><p>He says this a lot, but I never hear about the costs. Is there no amount of time lost on integrations that is too high a price? Is there no task that he doesn&rsquo;t break down into a million pieces in order to accommodate this style of work? Is there no efficiency lost by making each task into 1-hour chunks of coding that the entire team then integrates? Is that what we&rsquo;re doing now?</p>
<blockquote class="quote quote-block "><div>&ldquo;This will consist of both altering the product code, and also adding or changing some of the automated tests. During that time I run the automated build and tests frequently. <strong>After an hour or so I have the moon logic incorporated and tests updated.</strong>&rdquo;</div></blockquote><p>I&rsquo;m quite fed up with reading this kind of optimistic bulls%!t. What kind of programmers are these who can accomplish major work in one hour? Or are the tasks that Fowler can conceive of all so simple that they can be accomplished in an hour? I&rsquo;m very suspicious about these kinds of statements. It reminds me of game developers in the 90s talking about how they&rsquo;d &ldquo;written the whole engine in a weekend&rdquo;, but then the game still took five more years to deliver.</p>
<blockquote class="quote quote-block "><div>&ldquo;Some people do keep the build products in source control, but I consider that to be a smell − an indication of a deeper problem, usually an inability to reliably recreate builds. <strong>It can be useful to cache build products, but they should always be treated as disposable, and it&rsquo;s usually good to then ensure they are removed promptly so that people don&rsquo;t rely on them when they shouldn&rsquo;t.</strong>&rdquo;</div></blockquote><p>Sure. But—priorities. Your product is not the pipeline. It&rsquo;s your product. You can&rsquo;t make everything a slave to the process. Remember to fix that which you can fix quickly, but to focus on your own priorities. Don&rsquo;t polish a build so that Martin Fowler is happy, if it&rsquo;s going to make your customers wait a lot longer for their release.</p>
<blockquote class="quote quote-block "><div>&ldquo;The tests act as an automated check of the health of the code base, and while tests are the key element of such an automated verification of the code, many programming environments provide additional verification tools. Linters can detect poor programming practices, and ensure code follows a team&rsquo;s preferred formatting style, vulnerability scanners can find security weaknesses. Teams should evaluate these tools to include them in the verification process.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div><p>&ldquo;Everyone Pushes Commits To the Mainline Every Day</p>
<p>&ldquo;No code sits unintegrated for more than a couple of hours.&rdquo;</p>
</div></blockquote><p>This feels completely divorced from reality, but maybe I just &ldquo;don&rsquo;t get it.&rdquo;</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>If everyone pushes to the mainline frequently, developers quickly find out if there&rsquo;s a conflict between two developers. The key to fixing problems quickly is finding them quickly.</strong> With developers committing every few hours a conflict can be detected within a few hours of it occurring, at that point not much has happened and it&rsquo;s easy to resolve. <strong>Conflicts that stay undetected for weeks can be very hard to resolve.</strong>&rdquo;</div></blockquote><p>I agree with the last sentence, but at what cost? It feels like you&rsquo;re going to spend so much time committing and integrating. How is finding out if you have conflicts the highest-priority task your team has?</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>Full mainline integration requires that developers push their work back into the mainline.</strong> If they don&rsquo;t do that, then other team members can&rsquo;t see their work and check for any conflicts.&rdquo;</div></blockquote><p>Who finishes anything non-trivial in an hour? I can&rsquo;t escape the feeling that one-hour chunks is almost too granular, that this size was chosen because it aids integration. While that&rsquo;s a noble goal, I wonder how appropriate it is for many tasks, and to what degree the shape of the process affects the size of the solution set.</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>Since there&rsquo;s only a few hours of changes between commits, there&rsquo;s only so many places where the problem could be hiding.</strong> Furthermore since not much has changed we can use Diff Debugging to help us find the bug.&rdquo;</div></blockquote><p>But don&rsquo;t you waste time hunting bugs that would have gone away by themselves if the process weren&rsquo;t so frenetic? If you rebase everything, then you&rsquo;ll still encounter every integration conflict. If you merge, though, you can skip many of those interim integrations because subsequent changes might have obviated prior ones that might have caused conflicts.</p>
<p>Instead of testing occasional version, you end up testing absolutely everything you do as if it were a release candidate. I&rsquo;m not convinced that there&rsquo;s no downside to that. I feel like it&rsquo;s a waste of time if applied so mindlessly.</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>Often people initially feel they can&rsquo;t do something meaningful in just a few hours</strong>, but we&rsquo;ve found that mentoring and practice helps us learn.&rdquo;</div></blockquote><p>I don&rsquo;t know who you&rsquo;re working with, but I wonder how useful is that? How useful is it to tailor your entire process to ruthlessly chopping up your work into tiny segments? What if that&rsquo;s not how some people work? What if they can&rsquo;t learn? Fire &lsquo;em?</p>
<blockquote class="quote quote-block "><div>&ldquo;Continuous Integration can only work if the mainline is kept in a healthy state. Should the integration build fail, then it needs to be fixed right away. As Kent Beck puts it: <strong>“nobody has a higher priority task than fixing the build”.</strong>&rdquo;</div></blockquote><p>You goal ends up being running to run the process, rather than to build the product. This sounds more and more like a cult.</p>
<blockquote class="quote quote-block "><div>&ldquo;If the secondary build detects a bug, that&rsquo;s a sign that the commit build could do with another test. <strong>As much as possible we want to ensure that any later-stage failure leads to new tests in the commit build that would have caught the bug</strong>, so the bug stays fixed in the commit build.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>A team should thus automatically check for new versions of dependencies and integrate them into the build</strong>, essentially as if they were another team member. This should be done frequently, usually <strong>at least daily</strong>, depending on the rate of change of the dependencies.&rdquo;</div></blockquote><p>This seems like another thing that becomes a higher priority than building the product itself. Daily dependency check seems like overkill, but it&rsquo;s automated, so who cares? He&rsquo;s just running builds all the time, like we don&rsquo;t have a climate crisis. </p>
<blockquote class="quote quote-block "><div>&ldquo;if we rename a database field, we first create a new field with the new name, then write to both old and new fields, then copy data from the exisitng old fields, then read from the new field, and only then remove the old field. We can reverse any of these steps, which would not be possible if we made such a change all at once. <strong>Teams using <em>Continuous Integration</em> often look to break up changes in this way, keeping changes small and easy to undo.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Virtual environments make it much easier than it was in the past to do this. <strong>We run production software in containers, and reliably build exactly the same containers for testing, even in a developer&rsquo;s workspace.</strong> It&rsquo;s worth the effort and cost to do this, the price is usually small compared to hunting down a single bug that crawled out of the hole created by environment mismatches.&rdquo;</div></blockquote><p>I agree with this part, without qualification. At least as a goal.</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>Being able to automatically revert also reduces a lot of the tension of deployment, encouraging people to deploy more frequently and thus get new features out to users quickly.</strong> Blue Green Deployment allows us to both make new versions live quickly, and to roll back equally quickly if needed, by shifting traffic between deployed versions.&rdquo;</div></blockquote><p>What about data schemas? What about if you don&rsquo;t have a product that deploys on a web server or app store? I understand that there <em>are</em> solutions to this, but I wonder how great a fit they are to many teams? If your team is accustomed to SQL programming—or if you already have a suite of products that use SQL databases—then how worthwhile to your business is it to prioritize moving away from SQL to a local DB like <a href="https://www.sqlite.org/index.html">SQLite</a>, a NoSQL document store like <a href="https://ravendb.net/">RavenDB</a>, or even to a completely different back-end like <a href="https://redplanetlabs.com/">Rama</a>?</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>Continuous Integration effectively eliminates delivery risk.</strong> The integrations are so small that they usually proceed without comment. An awkward integration would be one that takes more than a few minutes to resolve.&rdquo;</div></blockquote><p>It sounds like very much like it <em>prioritizes</em> eliminating delivery risk over all else. It is only applicable to products built in this way from the beginning.</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>Having to put work on a new feature aside to debug a problem found in an integration test [or] feature finished two weeks ago saps productivity.</strong>&rdquo;</div></blockquote><p>So does constantly integrating, though! It can be noise. It&rsquo;s like the noise of micro-reviewing AI responses. You have to figure out the sweet spot for your team and iterate toward that goal, always ensuring that your team can deliver even if the dream process is not already in place. Make a diagram of all the facets and discuss a plan for your project. Pragmatic. Realistic.</p>
<p>I don&rsquo;t get the impression that Fowler is discussing a dream scenario toward which one works, but rather what he considers to be the absolute minimum process that anyone should be utterly embarrassed about themselves for not already having. I didn&rsquo;t see a single sentence in this 40-page, at-times repetitive document about how to actually get there from here—or whether that&rsquo;s really appropriate for many projects that people who read Martin Fowler might be working on.</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>They found that elite teams deployed to production more rapidly, more frequently, and had a dramatically lower incidence of failure when they made these changes.</strong> The research also finds that teams have higher levels of performance when they have three or fewer active branches in the application’s code repository, merge branches to mainline at least once a day, and don’t have code freezes or integration phases.&rdquo;</div></blockquote><p>What if you don&rsquo;t have an elite team?</p>
<blockquote class="quote quote-block "><div>&ldquo;A two week refactoring session may greatly improve the code, but result in long merges because everyone else has been spending the last two weeks working with the old structure. This raises the costs of refactoring to prohibitive levels. <strong>Frequent integration solves this dilemma by ensuring that both those doing the refactoring and everyone else are regularly synchronizing their work.</strong>&rdquo;</div></blockquote><p>Some refactoring can&rsquo;t just be done in mini bites like that. Sometimes, you work on a POC that takes more time to verify. Now what? Throw it away and build it from scratch in bite-sized pieces? Or integrate a long-lived branch, which is <em>verboten</em>?</p>
<p>I&rsquo;m working on a sweeping change to the way solutions are configured. It involves changing packages and versions in four different solutions. Should I have merged to master everywhere and involved the whole team in my project? That sounds stupid. Sure, it takes longer to verify and integrate in one big chunk, but it has the advantage that it didn&rsquo;t make upgrading the solution format the number-one priority for all developers for a sprint or two.</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] teams that spend a lot of effort keeping their code base healthy deliver features faster and cheaper. <strong>Time invested in writing tests and refactoring delivers impressive returns in delivery speed</strong>, and Continuous Integration is a core part of making that work in a team setting.&rdquo;</div></blockquote><p>For non-legacy projects. Continuous delivery can only really work for web-based products or apps. A lot of other products have to be deployed to processes that aren&rsquo;t as easy to update five times a day.</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>Continuous Integration is more suited for team working full-time on a product</strong>, as is usually the case with commercial software. But there is much middle ground between the classical open-source and the full-time model. We need to use our judgment about what integration policy to use that fits the commitment of the team.&rdquo;</div></blockquote><p>That is the first time that he&rsquo;s conceded that maybe there are use cases to which this whole article doesn&rsquo;t apply very well.</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>If a team attempts Continuous Integration without a strong test suite, they will run into all sorts of trouble</strong> because they don&rsquo;t have a mechanism for screening out bugs. If they don&rsquo;t automate, integration will take too long, interfering with the flow of development.&rdquo;</div></blockquote><p>No kidding. You need some <em>serious</em> test coverage to continuously integrate and deploy. I also wonder about the size of the product you can legitimately do this. Can you imagine if your test suite takes ten minutes to run and you integrate three or four times per day? Can you imagine how much time you&rsquo;re not developing software because you&rsquo;re integrating someone else&rsquo;s code? I understand that this happens eventually, but I wonder about the wisdom of prioritizing integration seemingly above all else.</p>
<blockquote class="quote quote-block "><div>&ldquo;Continuous Integration is about integrating code to the mainline in the development team&rsquo;s environment, and Continuous Delivery is the rest of the deployment pipeline heading to a production release.&rdquo;</div></blockquote><p>This is a good definition and I wonder that he rewrote this whole essay and didn&rsquo;t put this right at the top.</p>
<blockquote class="quote quote-block "><div>&ldquo;Continuous Integration ensures everyone integrates their code at least daily to the mainline in version control. <strong>Continuous Delivery then carries out any steps required to ensure that the product is releasable</strong> to product[ion] whenever anyone wishes. Continuous Deployment means the product is automatically released to production whenever it passes all the automated tests in the deployment pipeline.&rdquo;</div></blockquote><p>Also excellent definitions that make the distinction clear. <em>Continuous Delivery</em> is the one that many teams could strive for, even if they will never be able to do <em>Continuous Delivery</em>. The question is: at what cost?</p>
<blockquote class="quote quote-block "><div>&ldquo;Those who do Continuous Integration deal with this by <strong>reframing how code review fits into their workflow.</strong>&rdquo;</div></blockquote><p>Well, that&rsquo;s an interesting statement. Integration trumps review? Get your code in there and review later? Trust in your tests? Are you kidding me? You should review design, as well as implementation. If everyone&rsquo;s coding and committing and pushing in hours, when do they review? Is the idea to have people communicate with each other only when they&rsquo;ve already built something?</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4976</guid>
    <title><![CDATA[Web Interop 2024]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4976</link>
    <pubDate>Sun, 11 Feb 2024 22:33:58 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Feb 2024 22:33:58 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://webkit.org/blog/14955/the-web-just-gets-better-with-interop/">The web just gets better with Interop 2024</a> by <cite>Jen Simmons</cite> (<cite><a href="http://webkit.org/">Webkit Blog</a></cite>) writes,</p>
<blockquote class="quote quote-block "><div><p>&ldquo;<a href="https://www.earthli.com/data/news/attachments/entry/4976/interop_2024.jpg"><img title="Interop 2024" src="https://www.earthli.com/data/news/attachments/entry/4976/interop_2024.jpg" alt=" " class=" align-right" style="width: 200px"></a>The Interop project aims to improve interoperability by encouraging browser engine teams to look deeper into specific focus areas. Now, for a third year, <a href="https://www.apple.com">Apple</a>, <a href="https://bocoup.com/blog/interop-2024">Bocoup</a>, <a href="https://web.dev/blog/interop-2024">Google</a>, <a href="https://www.igalia.com/2024/interop-2024-launches.html">Igalia</a>, <a href="https://blogs.windows.com/msedgedev/2024/02/01/microsoft-edge-and-interop-2024/">Microsoft</a>, and <a href="https://hacks.mozilla.org/2024/02/announcing-interop-2024/">Mozilla</a> pooled our collective expertise and selected a specific subset of automated tests for 2024.</p>
<p>&ldquo;Some of the technologies chosen have been around for a long time. Other areas are brand new. <strong>By selecting some of the highest priority features that developers have avoided for years because of their bugs, we can get them to a place where they can finally be relied on.</strong>&rdquo;</p>
</div></blockquote><p>When we complain about features that remain unimplemented in browsers, we also have to acknowledge that there’s only so much you can do with a given team. There are problems that are technically easier to solve than others. When we complain, we’re actually more concerned about the <em>prioritization</em> of issues. We want to be able to influence what gets fixed when, rather than just having to passively hope that the manufacturer eventually gets around to it.</p>
<p>That where the <a href="https://wpt.fyi/results/?label=experimental&amp;label=master&amp;aligned">Web Platform Tests</a> come in. The <a href="https://wpt.fyi/interop-2024?stable">Interop 2024</a> project follows on iterations from <a href="https://wpt.fyi/interop-2023">2023</a>, <a href="https://wpt.fyi/interop-2022">2022</a>, and <a href="https://wpt.fyi/interop-2021">2021</a>, when it all started.</p>
<p>Last year was a banner year. For CSS <span class="quote-inline">&ldquo;Subgrid, Container Queries, <code>:has()</code>, Motion Path, CSS Math Functions, inert and <code>@property</code> are now supported in every modern browser.&rdquo;</span> For JavaScript, we got <span class="quote-inline">&ldquo;Improved Web APIs include Offscreen Canvas, Modules in Web Workers, Import Maps, Import Assertions, and JavaScript Modules&rdquo;</span> across all modern browsers.</p>
<p>These are all super-important features. E.g., <em>Import Assertions</em> for JSON import and <em>Modules in Web Workers</em>, which allows modern and modular programming, making it much easier to offload work, as one would with code running directly on modern operating systems.</p>
<p>What&rsquo;s on the schedule for 2024?</p>
<ul>
<li>Although there was a lot of progress made on CSS nesting last year, it&rsquo;s back on the radar this year to finalize the implementations.</li>
<li><code>@property</code> will similarly be more polished, as the percentage support is still quite low in many browsers.</li>
<li>It&rsquo;s great to see accessibility improvements for many of these features—like how <code>sub-grids</code> or <code>display: contents</code> affect element order—as this means that we will get sites that are automatically accessible, as long as we build our sites logically.</li>
<li>Improvements to <code>IndexedDB</code> will make it easier to write powerful local-first applications (even though something like <a href="https://automerge.org/blog/2023/11/06/automerge-repo/">Automerge</a> might be a better fit for apps offering concurrent or collaborative editing).</li>
<li>Browser- and standards-level support for <code>popover</code> with <em>anchors</em> is long overdue, as making usable tooltips and popups is an area fraught with custom code and half-baked solutions. It&rsquo;s nice to see this become an area where you&rsquo;ll no longer need custom JavaScript.</li>
<li><em>Relative Color Syntax</em> continues the excellent trend of allowing us to write CSS without the support of a CSS preprocessor. With relative colors, dark/light theming support, CSS nesting, and CSS variables, I can&rsquo;t think of a reason I would use a CSS preprocessor anymore. I know some people have used them for so much more, but I&rsquo;ve not done so, so my needs are already covered, even without this extension that allows conversion between colorspaces.</li>
<li><code>@starting-style</code> will fill a gap in CSS that finally allows sites to indicate how an element will transition from or to <code>display: none</code>.</li></ul><p>See the original article for much more detail.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4922</guid>
    <title><![CDATA[SourceLink and external sources]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4922</link>
    <pubDate>Mon, 08 Jan 2024 09:50:50 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Jan 2024 09:50:50 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">9. Jan 2024 11:04:29 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I published a very similar version of the following article in the DevOps Wiki at <a href="https://dev.azure.com/ustertechnologies">Uster Technologies AG</a>. Since nearly all of that post is general knowledge that I would have been happy to find before I started my investigations, I&rsquo;m sharing it here.</p>
<h2>Overview</h2><p>When we think about navigating or debugging our code, we usually focus on the code we&rsquo;ve written ourselves—local sources in our file system. IDEs have classically focused on being able to debug and navigate this code.</p>
<p>More and more, though, we&rsquo;re also interested in navigating and debugging our versioned and compiled dependencies:</p>
<ul>
<li>Internal NuGet packages</li>
<li>External NuGet packages</li>
<li>The Base Class Library (BCL)</li></ul><p>Most of these are available as source code. We would ideally like to be able to navigate and debug that code just as easily as we can our own.</p>
<p>The following sections define file types and terminology, and then explain how these concepts apply to debugging and navigation for external sources. You can also just jump to the sections on <a href="#producing-packages">producing</a> or <a href="#consuming-packages">consuming</a> packages (especially as relates to <a href="#authentication-fails">authentication for private sources</a>).</p>
<h2>Diagram</h2><p>The following diagram provides an overview of the process of obtaining external packages, along with their symbols and source files. It looks quite complicated, but accommodates the flexibility required by various stakeholders.</p>
<p><span style="width: 651px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4922/symbol_and_source_acquisition_diagram.png"><img src="https://www.earthli.com/data/news/attachments/entry/4922/symbol_and_source_acquisition_diagram.png" alt=" " style="width: 651px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4922/symbol_and_source_acquisition_diagram.png">Symbol and source acquisition diagram</a></span></span></p>
<h2>File types</h2><p>There are several types of files associated with debugging and navigation:</p>
<dl><dt class="field"><code>DLL</code></dt>
<dd>The executable code generally only includes executable code (instructions). It can include debugging information, but this is relatively rare.</dd>
<dt class="field"><code>PDB</code></dt>
<dd>The &ldquo;program database&rdquo; contains the symbol information for the executable code, which allows the debugger to map instructions back to the source code.&lt;br&gt;&lt;br&gt;This includes aliases (symbols), file positions, and any other necessary mappings, including references to source code files.&lt;br&gt;&lt;br&gt;Although invented by Microsoft, the PDB is an industry-standard, platform-independent, and language-independent format. See, e.g., <a href="https://llvm.org/docs/PDB/index.html">LLVM&rsquo;s The PDB File Format documentation</a> or <a href="https://en.wikipedia.org/wiki/Program_database">the Wikipedia entry</a>.</dd>
<dt class="field"><code>XML</code></dt>
<dd>The optionally generated XML documentation. Some IDEs can use this file to enhance the developer experience while browsing the source code.</dd>
<dt class="field"><code>*.cs</code></dt>
<dd>The original source code</dd>
</dl><h2>Design Considerations</h2><p>It&rsquo;s reasonable to ask why this process is so complex.</p>
<h3>Why can&rsquo;t the <code>nupkg</code> just include the <code>PDB</code> and the <code>*.cs</code> files?</h3><p>The system was designed for use cases where most sources were closed. That has changed, but the system still reflects the original design choices. The PDB files can also add about 30% to the size of the package. The original use cases preferred to avoid using 30% more space for package downloads that didn&rsquo;t need the debugging information.</p>
<h3>Why aren&rsquo;t sources included in the PDB?</h3><p>Again, historically, the use cases were for providing improved stack traces with symbols, but not to provide access to closed sources. Even if the sources are partially open, access may be restricted to only some users of the packages or symbols. Having the IDE request the sources separately allows an additional authorization phase.</p>
<h3>What about open-source?</h3><p>The defaults still reflect the original use cases, which actually represent fewer and fewer packages as time goes on.</p>
<p>These answers aren&rsquo;t particularly satisfying if your use case happens to be &ldquo;make a package that has symbols for excellent stack traces and sources for excellent debugging&rdquo;. At least we now have IDEs that know how to work with this system and there is a lot of automation for <a href="#producing-packages">producing packages</a> with the desired symbol and source-code support.</p>
<h2>Terminology</h2><h3>Debugging</h3><p>A developer <em>debugs</em> source code by interrupting execution of a program—either manually or by setting <em>breakpoints</em>—and then <em>stepping</em> through the instructions, examining the contents of symbols (variables) to investigate the runtime behavior and operation of the system.</p>
<p>The debugger uses the <code>PDB</code> to allow <em>source-level debugging</em>, i.e. debugging in the original source code. While debugging in &ldquo;lower&rdquo; formats is possible, it&rsquo;s not nearly as reliable as being able to step through the code in the original source code, using the original symbols.</p>
<p>How does the debugger obtain the <code>PDB</code> for a given <code>DLL</code>?</p>
<ul>
<li>First it searches in the same directory. This is by far the most common location where symbols will be found.</li>
<li>Next, it searches on all known &ldquo;symbol servers&rdquo; in the order that they&rsquo;re declared. All <code>DLLs</code> and <code>PDBs</code> have unique identifiers that make it possible to request and download the correct file.</li></ul><p>Once the debugger has the PDB, it has everything it needs—except the source code.</p>
<h3>Local sources</h3><p>If the PDB was generated locally, then it most likely references the source files that are still in the same locations in the file system as when it was built. In that case, the debugger easily finds the source files because they&rsquo;re just at the paths that are directly referenced by the <code>PDB</code>.</p>
<p>If the PDB was not generated locally or the source-code paths do not match, then there are other tricks to find the source files. <em>Visual Studio</em> allows you to set &ldquo;Directories containing source code&rdquo; for the &ldquo;Debug Source Files&rdquo;</p>
<p><span style="width: 589px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4922/solution_debugging_options.png"><img src="https://www.earthli.com/data/news/attachments/entry/4922/solution_debugging_options.png" alt=" " style="width: 589px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4922/solution_debugging_options.png">Solution Debugging Options</a></span></span></p>
<h3>External sources</h3><p>If the sources aren&rsquo;t available locally, e.g., for a <em>NuGet</em> package, then there is a system called <a href="https://github.com/dotnet/sourcelink">SourceLink</a> that is extremely well-supported in the .NET world that makes it possible to easily download the source files that generated a <code>DLL</code> and that are referenced by its <code>PDB</code>.</p>
<p>Things to be aware of:</p>
<ul>
<li>The package must have been built with <em>SourceLink</em> enabled (see <a href="#producing-packages">producing packages</a>).</li>
<li>The sources must be available for download in a known format and structure (e.g., <em>Azure Git Repos</em>).</li>
<li>The IDE must know how to download, cache, and use the sources for debugging or navigation.</li></ul><p>If the package does not support <em>SourceLink</em>, but the sources are available, then you can download the sources locally and use the solution-level mapping above to tell the debugger where the source files are. You can also just point the debugger to the top-level folder when it asks for the file&rsquo;s location, in which case the debugger makes the entry for you.</p>
<h3 id="navigation">Navigation</h3><p>A developer <em>navigates</em> by requesting the source code for a symbol. For example, if the declared type of a variable in an open source file is the class <code>Setting</code>, then the developer can ask the IDE to show the source of <code>Setting</code> by <kbd>Ctrl</kbd> + clicking, by pressing <kbd>F12</kbd> in <em>Visual Studio</em>, or by pressing <kbd>Ctrl</kbd> + <kbd>B</kbd> in <em>Rider</em>.</p>
<p>As with debugging, navigating local sources is straightforward, since the sources are in the local file system. For symbols in NuGet packages, the IDE has to be clever enough to download, cache, and use the sources.</p>
<p><em>Visual Studio</em> on its own does not support navigating to external sources via <a href="#sourcelink">SourceLink</a>. Instead, it always decompiles external sources, as shown in the example below.</p>
<p><span style="width: 464px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4922/visual_studio_decompiles_external_sources_on_navigation.png"><img src="https://www.earthli.com/data/news/attachments/entry/4922/visual_studio_decompiles_external_sources_on_navigation.png" alt=" " style="width: 464px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4922/visual_studio_decompiles_external_sources_on_navigation.png">Visual Studio decompiles external sources on navigation</a></span></span></p>
<p>If you have <em>ReSharper</em> installed, then the default setting is to try as hard as possible to avoid showing a decompiled version.</p>
<p>You can also add &ldquo;Folder Substitutions&rdquo; in the &ldquo;Advanced Symbol options…&rdquo; for navigating to &ldquo;External Sources&rdquo;. The option does not seem to be available in Rider.</p>
<p><span style="width: 757px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4922/resharper_external_source_options.png"><img src="https://www.earthli.com/data/news/attachments/entry/4922/resharper_external_source_options.png" alt=" " style="width: 757px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4922/resharper_external_source_options.png">ReSharper External Source Options</a></span></span></p>
<h3 id="sourcelink">SourceLink</h3><p><em>SourceLink</em> is a system that provides source files for external sources like NuGet packages for debugging or navigation. In order for this to work, you must be able to provide external sources or the client is not properly configured for debugging.</p>
<p>See <a href="#troubleshooting">below for troubleshooting information</a>, especially as relates to <a href="#authentication-fails">authentication</a> for packages and source code pulled from authenticated locations.</p>
<h3>Decompiled code</h3><p>A <em>decompiled</em> version of the source code is a reconstruction of the original source from the instructions and information in the <code>DLL</code> and <code>PDB</code>. When sources cannot be located for a given symbol, <em>Visual Studio</em>,  <em>ReSharper</em>, and <em>Rider</em> will produce a decompiled version as a fallback.</p>
<p>This is often good enough to be able to read the code reasonably well, but it leaves certain common constructs in their &ldquo;lowered&rdquo; format. E.g., calls to extension methods appear as static-method calls rather than as targeted on the first parameter.</p>
<p>This can make debugging difficult, as the instructions don&rsquo;t match the mapping. <em>Rider</em> has support for patching the PDB on-the-fly to allow more comfortable debugging of decompiled sources. This is, however, a fallback solution for external packages over which you have no control. It&rsquo;s best to configure your packages to publish with symbols and sources available to IDEs that support them, as shown in the next section.</p>
<h2 id="producing-packages">Producing packages</h2><p>The documentation to <a href="https://learn.microsoft.com/en-us/visualstudio/debugger/how-to-improve-diagnostics-debugging-with-sourcelink?view=vs-2022">Enable debugging and diagnostics with Source Link</a> is thorough and tells you all you need to know about all of the options.</p>
<p>If you&rsquo;re working with Azure DevOps Services, you should include the following package reference:</p>
<pre class=" "><code>&lt;ItemGroup&gt;
  &lt;PackageReference Include="Microsoft.SourceLink.AzureRepos.Git" Version="8.0.0" PrivateAssets="All"/&gt;
&lt;/ItemGroup&gt;</code></pre><p>With this, you&rsquo;re all set. The package is published to the <em>Azure Artifacts</em>, with a corresponding <code>snupkg</code> available on the Azure symbol server and sources available via the repository URL (subject to authorization; see <a href="#authentication-fails">below</a> for troubleshooting).</p>
<h3>Additional Properties</h3><p>You can set a few <em>optional</em> properties, detailed below. Most projects won&rsquo;t need to set these, but they are included to spare you the research if you see them in code examples, either in your institution&rsquo;s code or online. As noted, the only line you need is the package reference shown above.</p>
<dl><dt><a href="https://github.com/dotnet/sourcelink/blob/main/docs/README.md#embedallsources">EmbedAllSources</a></dt>
<dd>Embeds all project source files into the generated PDB</dd>
<dt><a href="https://github.com/dotnet/sourcelink/blob/main/docs/README.md#embeduntrackedsources">EmbedUntrackedSources</a></dt>
<dd>Embeds anything that&rsquo;s not included in source control (kind of unclear what they&rsquo;re talking about here, though); included in <code>IncludeSymbols</code></dd>
<dt><a href="https://github.com/dotnet/sourcelink/blob/main/docs/README.md#publishrepositoryurl">PublishRepositoryUrl</a></dt>
<dd>Ensures that the URL of the repository supplied by the CI server or retrieved from source control manager is available in the package information. This is off by default to prevent discovery of private URLS, but it doesn&rsquo;t really matter for packages published from private sources, as they are protected by Azure DevOps (or whatever) authorization.</dd>
<dt><a href="https://learn.microsoft.com/en-us/nuget/create-packages/symbol-packages-snupkg">IncludeSymbols</a></dt>
<dd>Indicates that the PDB should be generated and included either with the package (if <code>DebugType</code> is set to <code>embedded</code>) or in a separate symbol package (if <code>SymbolPackageFormat</code> is set to <code>snupkg</code>). This is implied when the NuGet package <a href="https://www.nuget.org/packages/Microsoft.SourceLink.AzureRepos.Git">Microsoft.SourceLink.AzureRepos.Git</a> is included, as shown below.</dd>
<dt><a href="https://learn.microsoft.com/en-us/nuget/create-packages/symbol-packages-snupkg">SymbolPackageFormat</a></dt>
<dd>Indicates which package format to use. This is set to <code>snupkg</code> when the NuGet package <a href="https://www.nuget.org/packages/Microsoft.SourceLink.AzureRepos.Git">Microsoft.SourceLink.AzureRepos.Git</a> is included, as shown below.</dd>
</dl><p>See the <a href="https://github.com/dotnet/sourcelink?tab=readme-ov-file#using-source-link-in-net-projects">SourceLink documentation</a> for more details. Among other details, they also note that projects that target .NET 8 no longer need to include this support explicitly because Azure Repos are supported by default, as detailed in the <a href="https://github.com/dotnet/sourcelink">readme for the SourceLink project</a>.</p>
<blockquote class="quote quote-block "><div>&ldquo;If your project uses .NET SDK 8+ and is hosted by the above providers (GitHub, Azure Repos, GitLab, BitBucket) it does not need to reference any Source Link packages or set any build properties.&rdquo;</div></blockquote><h3>Conditional packaging</h3><p>You can also include the packaging conditionally in the <code>Directory.Build.Targets</code>, as shown below.</p>
<pre class=" "><code>&lt;ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "&gt;
  &lt;PackageReference Include="Microsoft.SourceLink.AzureRepos.Git" Version="8.0.0" PrivateAssets="All"/&gt;
&lt;/ItemGroup&gt;</code></pre><p>See the appendix for <a href="#direction-build-props-and-directory-build-targets"><code>Directory.Build.Props</code> and <code>Directory.Build.Targets</code></a> for more information about which variables and directives are respected in which file.</p>
<h2 id="consuming-packages">Consuming packages</h2><h3>For debugging</h3><p>If a package has SourceLink enabled and you have access to the online repository from which it was built, then to seamlessly debug into that source code, ensure the following:</p>
<ul>
<li><a href="#disable-_just-my-code_">Disable Just My Code</a></li>
<li><a href="#is-it-available%3F">Check that the PDB is available</a></li></ul><h3>For navigation</h3><p>As <a href="#navigation">noted above</a>, Visual Studio doesn&rsquo;t support navigating via <a href="#sourcelink">SourceLink</a>. To browse external sources with <em>JetBrains</em> tools, ensure the following:</p>
<ul>
<li><a href="#is-it-available%3F">Check that the PDB is available</a></li>
<li><a href="#authentication-fails">Set up Authentication</a></li></ul><h3 id="troubleshooting">Troubleshooting</h3><h4>Symbols not loaded</h4><h5 id="disable-_just-my-code_">Disable <em>Just My Code</em></h5><p>Once you&rsquo;re sure that the <a href="https://www.earthli.com/Documentation/Tools/NuGet/NuGet-FAQ#why-doesn%27t-sourcelink-work%3F">package supports SourceLink</a>, then you should also make sure that the <a href="https://learn.microsoft.com/en-us/visualstudio/debugger/just-my-code?view=vs-2022">Just My Code</a> setting is <em>disabled</em>.</p>
<p>When <em>Just My Code</em> is enabled, the debugger skips over any code that doesn&rsquo;t correspond to source code in one of the local projects.</p>
<h5 id="is-it-available%3F">Is it available?</h5><ul>
<li>Does the package you&rsquo;ve downloaded actually include symbols (a <code>.pdb</code> file next to the <code>.dll</code> file)?</li>
<li>If the <code>PDB</code> is not included with the package, is it available on a <a href="https://learn.microsoft.com/en-us/visualstudio/debugger/specify-symbol-dot-pdb-and-source-files-in-the-visual-studio-debugger?view=vs-2022#where-the-debugger-looks-for-symbols">Symbol Server</a>?</li>
<li>If it is included, is it being copied into the output folder with the <code>DLL</code>?</li></ul><p>If it&rsquo;s available in the package, but is not being copied to the output folder, then if you&rsquo;re using .NET 7.0 SDK or higher, you can use the build property named <a href="https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#copydebugsymbolfilesfrompackages"> CopyDebugSymbolFilesFromPackages</a>.</p>
<pre class=" "><code>&lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "&gt;
  &lt;CopyDebugSymbolFilesFromPackages&gt;true&lt;/CopyDebugSymbolFilesFromPackages&gt;
&lt;/PropertyGroup&gt;</code></pre><h5>Manually load the module</h5><p>Verify that the symbols for the module you&rsquo;re trying to debug have been loaded. If they aren&rsquo;t loaded, you can try to <a href="https://learn.microsoft.com/en-us/visualstudio/debugger/specify-symbol-dot-pdb-and-source-files-in-the-visual-studio-debugger?view=vs-2022#load-symbols-while-debugging">load symbols while debugging</a>. For more details and a screenshot, see <a href="https://learn.microsoft.com/en-us/visualstudio/debugger/just-my-code?view=vs-2022#just-my-code-debugging">Just My Code debugging</a>.</p>
<h4>Decompiling rather than downloading</h4><p>If you&rsquo;re trying to navigate in code, but ReSharper or Rider keeps decompiling instead of getting the sources from <a href="#sourcelink">SourceLink</a>, then check your <a href="https://www.jetbrains.com/help/resharper/Reference__Options__Tools__External_Sources.html">External Sources</a> settings in ReSharper or Rider. Verify that the tool is configured to check for external sources <em>before</em> it tries decompiling.</p>
<p>If the IDE is having trouble <a href="#authentication-fails">authenticating</a>, then you will usually see a decompiled version instead. Sometimes the code is so close to the original that it&rsquo;s hard to tell; scroll to the top to see if it includes the &ldquo;decompiled by JetBrains…&rdquo; header.</p>
<p>Once the IDE has decompiled a source file, it will continue to use this cached copy until you close the tab, or sometimes you have to close and re-open the project. If you&rsquo;re troubleshooting your way through this setup, then you can temporarily disable decompilation as a fallback, which avoids producing the unwanted source-code variant in the first place.</p>
<h4 id="authentication-fails">Authentication fails</h4><p><em>Visual Studio</em> uses the authentication associated with the logged-in user that you use to enable the IDE. This can be in a weird state if you&rsquo;ve recently changed your password or your authentication token is stale or in a non-refreshable state. Try logging out and back in.</p>
<p><em>JetBrains</em> tools (<em>Rider</em>, <em>ReSharper</em>, <em>DotPeek</em>, etc.), on the other hand, need to be given a <em>token</em>.</p>
<h5>Configure from the notification</h5><p>If the tool shows a notification indicating that authentication has failed, then do the following:</p>
<ul>
<li>Click <code>Configure</code> on the notification to show a dialog
<li><div>In the resulting dialog, set:<ul>
<li><em>User name</em> to your Azure login, e.g., <code>john.doe@example.com</code></li>
<li><em>Token</em> to an <a href="https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&amp;tabs=Windows">Azure PAT</a> (click for instructions on how to create one)</li>
<li>Press the <code>Test</code> button to verify that it works (you should see <code>OK 200</code>)</li>
<li>Press <code>Ok</code> to save the credentials</li></ul></div></ul><h5>Bug in <em>JetBrains</em> tools</h5><p>However, there is a bug whereby <em>JetBrains</em> tools fail to show a notification or offer a way to enter credentials. [1] That&rsquo;s going to look something like this:</p>
<p><span style="width: 302px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4922/download_never_completes.png"><img src="https://www.earthli.com/data/news/attachments/entry/4922/download_never_completes.png" alt=" " style="width: 302px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4922/download_never_completes.png">Download never completes</a></span></span></p>
<p>It claims that it can download the source, but it never completes. You have to cancel the dialog. If you then look at the ReSharper Output, then you&rsquo;ll see something like this:</p>
<p><span style="width: 951px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4922/non-ok_http_status_code.png"><img src="https://www.earthli.com/data/news/attachments/entry/4922/non-ok_http_status_code.png" alt=" " style="width: 951px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4922/non-ok_http_status_code.png">Non-OK HTTP status code</a></span></span></p>
<p>The relevant text is at the end of the third line, which indicates that the request for the source file returned a &ldquo;Non-OK HTTP status code&rdquo;.</p>
<pre class=" "><code>PdbNavigator: Searching for 'Example.Core.AppConfig.AppConfigKeyAttribute' type sources in C:\Users\john.doe\.nuget\packages\example.core.appconfig\4.1.0\lib\netstandard2.0\Example.Core.AppConfig.pdb
PdbNavigator: File names (1) are inferred for type Example.Core.AppConfig.AppConfigKeyAttribute
PdbNavigator: Downloader: https://dev.azure.com/example/example.Core/_apis/git/repositories/Example.Core.LabInstruments/items?api-version=1.0&amp;versionType=commit&amp;version=8b34c2aa672facd47e835c27152f695fa796a408&amp;path=/Example.Core/DotNetStandard/Example.Core.AppConfig/AppConfigKeyAttribute.cs -&gt; Non-OK HTTP status code</code></pre><h5>Configure from the <em>Credentials Manager</em></h5><p>The most reliable way to fix this is to create the credentials in the <em>Credential Manager</em>. Be aware that you will need to <a href="https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&amp;tabs=Windows">create an Azure PAT (personal access token)</a>.</p>
<ul>
<li>Open <em>Credentials Manager</em></li>
<li>Switch to <code>Windows Credentials</code></li>
<li>Scroll until you see <code>JetBrains SourceLink https://dev.azure.com/exampleOrganization</code></li></ul><p><span style="width: 602px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4922/jetbrains_entry_in_credentials_manager.png"><img src="https://www.earthli.com/data/news/attachments/entry/4922/jetbrains_entry_in_credentials_manager.png" alt=" " style="width: 602px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4922/jetbrains_entry_in_credentials_manager.png">JetBrains entry in Credentials Manager</a></span></span></p>
<p>If you don&rsquo;t have this entry, then that&rsquo;s the problem. If you have it, but you still can&rsquo;t get the sources, then edit the entry to have valid credentials.</p>
<p>To create or edit the record, do the following from the <em>Credentials Manager</em>:</p>
<ul>
<li><div class=" "><p>Press <code>Add a generic credential</code></p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4922/create_generic_credentials.png"><img src="https://www.earthli.com/data/news/attachments/entry/4922/create_generic_credentials.png" alt=" " style="width: 441px"></a></p>
</div></li>
<li><div>In the resulting form, set:<ul>
<li><em>Internet or network address</em> to <code>JetBrains SourceLink https://dev.azure.com/exampleOrganization</code></li>
<li><em>User name</em> to your Azure login, e.g., <code>john.doe@example.com</code></li>
<li><em>Password</em> to an <a href="https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&amp;tabs=Windows">Azure PAT</a> (click for instructions on how to create one)</li></ul></div></ul><p>  </p>
<div class="caution "> 💡 There is no need to restart the <em>JetBrains</em> tools. You will immediately be able to load sources from <a href="#sourcelink">SourceLink</a> once valid credentials exist.</div><h2>Alternative: referencing projects, not packages</h2><p>As you can see above, although publishing a package is relatively straightforward, there are quite a few stumbling blocks on the way to consuming the package for navigation and debugging. Once you have everything set up and working, it&rsquo;s great, but … there is still one other drawback.</p>
<p>You can&rsquo;t edit the code for packages.</p>
<p>This is not optimal. Optimally, we&rsquo;d like to <em>quickly</em> verify that change to an upstream code would address an issue in downstream code without having to generate new packages. It would be great to just edit the upstream code as if it were part of your downstream solution until you&rsquo;re sure that the change would address your downstream issue. At that point, you can copy the changes back to the upstream solution (where the dependency is produced), add tests, and produce a new version, being pretty certain that the change is effective.</p>
<p>The shortest possible developer-feedback loop with code in external packages is: </p>
<ul>
<li>Determine that you need to make a change to code in an external package</li>
<li>Open the solution for that package</li>
<li>Make the change</li>
<li>Build the assembly</li>
<li>Drop it into your output folder (along with the <code>PDB</code>)</li>
<li>Build and run your solution with the updated code</li></ul><p>If your package has dependencies or your change in the external package&rsquo;s solution touches multiple packages, then you can do the following:</p>
<ul>
<li>Build packages for the solution locally</li>
<li>Set up a NuGet source that points to that folder</li>
<li>Update to the newer versions of the packages and restore from that source</li>
<li>Build and run your solution with the updated code</li></ul><p>If it get too complicated to do locally, then you can always commit, push, and have the CI generate new versions of your packages (hopefully with a prerelease version, e.g., <code>3.2.4-preview2</code>)</p>
<p>The solutions outlined above have a reasonable turnaround time, but sometimes you want to pretend that the external packages are just internal projects instead. This basically entails:</p>
<ul>
<li>Downloading the project or projects corresponding to the packages that you want to be able to edit</li>
<li>Including those projects into your solution</li>
<li>Replacing the external package-references with project references</li></ul><p>At that point, you can edit, debug, and navigate the code as if it were your own. </p>
<p>See the &ldquo;Project Munging with Tools &amp; PowerShell&rdquo; section of <a href="https://blog.inedo.com/nuget/how-to-debug-nuget-packages-the-painless-way/">How to Debug NuGet Packages with Symbols and Source Link Painlessly</a> for a PowerShell script that can help you automate part of this.</p>
<h2 id="directory-build-props-and-directory-build-targets">Directory.Build.Props and Directory.Build.Targets</h2><p>MSBuild supports including common configuration in project files. While earlier versions required all configuration to be included explicitly, modern versions include configuration files with special names automatically, greatly simplifying common configuration <em>and</em> reducing clutter in project files.</p>
<h3>Mechanics</h3><p>If the file is named <code>Directory.Build.Props</code> or <code>Directory.Build.Targets</code>, it is picked up automatically and included for all projects in that folder or any subfolder. If you use a different name, then you have to explicitly reference that file from a project or from another <code>*.props</code> or <code>*.targets</code> file. If you choose your own name, you don&rsquo;t have to use the <code>Build.Properties</code> or <code>Build.Targets</code> convention, but it&rsquo;s strongly recommended, to avoid confusion.</p>
<h4>Directory.Build.Props</h4><p>You can use a <a href="https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory?view=vs-2022#directorybuildprops-and-directorybuildtargets">Directory.Build.Properties</a> file to include settings for all projects in a folder or set of subfolders.</p>
<p>For example, the following package reference can and should be included in <code>Directory.Build.Props</code>:</p>
<pre class=" "><code>&lt;PackageReference Include="Microsoft.SourceLink.AzureRepos.Git" Version="8.0.0" PrivateAssets="All"/&gt;</code></pre><h4>Directory.Build.Targets</h4><p>If you want to include settings conditionally based on build configuration (e.g., <code>Configuration</code> or <code>Platform</code>), then you&rsquo;ll have to use the <a href="https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory?view=vs-2022#directorybuildprops-and-directorybuildtargets">Directory.Build.Targets</a> file, which has access to those variables.</p>
<pre class=" "><code>&lt;ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "&gt;
  &lt;PackageReference Include="Microsoft.SourceLink.AzureRepos.Git" Version="8.0.0" PrivateAssets="All"/&gt;
&lt;/ItemGroup&gt;</code></pre><h3>Rules-of-thumb</h3><ul>
<li>Once you&rsquo;re using the SDK-style format for project files [2], you can aggressively consolidate common settings in a <code>Directory.Build.Props</code> file at the root of the solution.</li>
<li>If you have groups of projects to which different settings should be applied, then consider splitting those off into corresponding subfolders (e.g., &ldquo;Tests&rdquo;) so that you can apply those common settings with a configuration file that applies only to that folder.</li>
<li>If you can&rsquo;t or don&rsquo;t want to move projects into subfolders, then you can create a custom `props` file and manually include it in the project files that need it.</li></ul><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4922_1_body" class="footnote-number">[1]</span> After having figured out a workaround, I felt well-equipped enough to file a bug with JetBrains: <a href="https://youtrack.jetbrains.com/issue/RSRP-495517/ReSharper-does-not-ask-for-authentication-when-browsing-to-source-from-symbol-files-in-assembly-explorer">ReSharper does not ask for authentication when browsing to source from symbol files in assembly explorer</a>. After a couple of days, the responsible developer changed the status from &ldquo;triage&rdquo; to &ldquo;open&rdquo; and he <em>linked a two-year-old bug report to it</em>: <a href="https://youtrack.jetbrains.com/issue/RIDER-61280/Pdb-files-cannot-be-downloaded-from-Azure-DevOps-Symbol-Server">Pdb files cannot be downloaded from Azure DevOps Symbol Server</a>. Would you like to guess who wrote that bug report? Yours truly. I knew I&rsquo;d had trouble in this area before, but I&rsquo;d completely forgotten that I&rsquo;d reported the bug in such detail. It&rsquo;s still open. Maybe they&rsquo;ll finally address it.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4922_2_body" class="footnote-number">[2]</span> This also works for the older project format, but it&rsquo;s hard to keep <em>Visual Studio</em> from repopulating properties in that format. You can use the SDK-style format for nearly all projects these days. The conversion is worth it.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4889</guid>
    <title><![CDATA[Learning how to use GenAI as a programming tool]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4889</link>
    <pubDate>Sat, 30 Dec 2023 22:46:09 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. Dec 2023 22:46:09 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/4889/generative_ai_tools.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4889/generative_ai_tools_tn.jpg" alt=" " class=" align-right"></a>The article <a href="https://martinfowler.com/articles/exploring-gen-ai.html">Exploring Generative AI</a> by <cite>Birgitta B&ouml;ckeler</cite> (<cite><a href="http://martinfowler.com/">MartinFowler.com</a></cite>) is chock-full of helpful tips from eight newsletters totaling 25 pages that she wrote throughout 2023. I include some of my own thoughts, but most of this article consists of citations.</p>
<p>A lot of my analysis and notes boils down to: you need to know what you&rsquo;re doing to use these tools. They can help you build things that you don&rsquo;t understand, but it&rsquo;s not for medium- or long-term solutions. I&rsquo;ve written a lot more about the need for expertise in <a href="https://www.earthli.com/news/view_article.php?id=4871">How important is human expertise?</a></p>
<blockquote class="quote quote-block "><div><p>&ldquo;<strong>The following are the dimensions of my current mental model of tools that use LLMs (Large Language Models) to support with coding.</strong></p>
<p>&ldquo;Assisted tasks&rdquo;</p>
<ul>
<li><strong>Finding information</strong> faster, and in context</li>
<li><strong>Generating code</strong></li>
<li><strong>“Reasoning” about code</strong> (Explaining code, or problems in the code)</li>
<li><strong>Transforming code into something else</strong> (e.g. documentation text or diagram)</li></ul>&ldquo;These are the types of tasks I see most commonly tackled when it comes to coding assistance, although there is a lot more if I would expand the scope to other tasks in the software delivery lifecycle.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;In this particular case of a very common and small function like median, I would even consider using generated code for both the tests and the function. The tests were quite readable and it was easy for me to reason about their coverage, plus they would have helped me remember that I need to look at both even and uneven lengths of input. However, <strong>for other more complex functions with more custom code I would consider writing the tests myself, as a means of quality control. Especially with larger functions, I would want to think through my test cases in a structured way from scratch, instead of getting partial scenarios from a tool, and then having to fill in the missing ones.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;The tool itself might have the answer to what’s wrong or could be improved in the generated code − <strong>is that a path to make it better in the future, or are we doomed to have circular conversation with our AI tools?</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;[…] generating tests could give me ideas for test scenarios I missed, even if I discard the code afterwards. And <strong>depending on the complexity of the function, I might consider using generated tests as well, if it’s easy to reason about the scenarios.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>For the purposes of this memo, I’m defining “useful” as “the generated suggestions are helping me solve problems faster and at comparable quality than without the tool”.</strong> That includes not only the writing of the code, but also the review and tweaking of the generated suggestions, and dealing with rework later, should there be quality issues.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div><ul>
<li>[…]</li>
<li><em>Boilerplate:</em> Create boilerplate setups like an ExpressJS server, or a React component, or a database connection and query execution.</li>
<li><em>Repetitive patterns:</em> It helps speed up typing of things that have very common and repetitive patterns, like creating a new constructor or a data structure, or a repetition of a test setup in a test suite. <strong>I traditionally use a lot of copy and paste for these things, and Copilot can speed that up.</strong></li></ul></div></blockquote><p>Interesting. I&rsquo;ve just always used the existing templates or made my own expansion templates. At least then it makes exactly what I want—and even leaves the cursor in the right position afterwards.</p>
<p>Another thought I had is that the kind of programmer that this helps doesn&rsquo;t use any generalization for common patterns. Otherwise, the suggestions wouldn&rsquo;t be useful because they can&rsquo;t possibly take advantage of those highly specialized patterns. Or maybe they can, if they&rsquo;re included in the context. It seems unlikely, if only because the sample size is too small to be able to influence the algorithm sufficiently. But maybe enough weight can be given to the immediate context to make that work somehow.</p>
<p>At that point, though, you&rsquo;re just spending all of your time coaxing your LLM copilot into building the code that you already knew you wanted. This practice seems like it would end up discouraging generalization and abstraction—unless it can grok your API (as I&rsquo;ve noted above).</p>
<p>This is an age-old problem that is maybe solved, once and for all. The problem is that when you generalize a solution, it becomes much easier, more efficient, and more economical to maintain, but it can end up being more difficult to understand. If the API is well-made and addresses a problem domain with a complexity that the programmer is actually capable of understanding, then the higher-level API may be easier to use, and perhaps even maintain.</p>
<p>However, a non-generalized solution is sometimes easier for a novice or less-experienced programmer to understand and extend. It&rsquo;s questionable whether you&rsquo;d want your code being extended and maintained by someone who barely—or doesn&rsquo;t—understand it, but that situation is sometimes thrust on teams and managers.</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>This autocomplete-on-steroids effect can be less useful though for developers who are already very good at using IDE features, shortcuts, and things like multiple cursor mode.</strong> And beware that when coding assistants reduce the pain of repetitive code, <strong>we might be less motivated to refactor.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>You can use a coding assistant to explore some ideas when you are getting started with more complex problems, even if you discard the suggestion afterwards.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;The larger the suggestion, the more time you will have to spend to understand it, and the more likely it is that you will have to change it to fit your context. <strong>Larger snippets also tempt us to go in larger steps, which increases the risk of missing test coverage, or introducing things that are unnecessary.</strong>&rdquo;</div></blockquote><p>On the other hand,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] when you do not have a plan yet because you are less experienced, or the problem is more complex, then a larger snippet might help you get started with that plan.&rdquo;</div></blockquote><p>This is not unlike using StackOverflow or any other resource. There&rsquo;s no getting around knowing what you&rsquo;re doing, at least a little bit. You can&rsquo;t bootstrap without even a bootstrap.</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>Experience still matters. The more experienced the developer, the more likely they are to be able to judge the quality of the suggestions, and to be able to use them effectively.</strong> As GitHub themselves put it: “It’s good at stuff you forgot.” This study even found that “<strong>in some cases, tasks took junior developers 7 to 10 percent longer with the tools than without them</strong>.”&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Using coding assistance tools effectively is a skill that is not simply learned from a training course or a blog post.</strong> It’s important to use them for a period of time, experiment in and outside of the safe waters, and <strong>build up a feeling for when this tooling is useful for you, and when to just move on and do it yourself.</strong>&rdquo;</div></blockquote><p>This is just like any other tool. There is no shortcut to being good at something complex. The only tasks for which there are shortcuts are the non-complex ones. In that case, you should be asking yourself why your solutions involve so much repetitive programming.</p>
<blockquote class="quote quote-block "><div>&ldquo;We have found that having the right files open in the editor to enhance the prompt is quite a big factor in improving the usefulness of suggestions. However, <strong>the tools cannot distinguish good code from bad code.</strong> They will inject anything into the context that seems relevant. (According to this reverse engineering effort, GitHub Copilot will look for open files with the same programming language, and use some heuristic to find similar snippets to add to the prompt.) <strong>As a result, the coding assistant can become that developer on the team who keeps copying code from the bad examples in the codebase.</strong>&rdquo;</div></blockquote><p>That will be so much fun, especially if you can get an echo chamber of lower-skilled programmers approving each other&rsquo;s pull requests. 😉</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>We also found that after refactoring an interface, or introducing new patterns into the codebase, the assistant can get stuck in the old ways.</strong> For example, the team might want to introduce a new pattern like “start using the Factory pattern for dependency injection”, but the tool keeps suggesting the current way of dependency injection because that is still prevalent all over the codebase and in the open files. <strong>We call this a poisoned context , and we don’t really have a good way to mitigate this yet.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Using a coding assistant means having to do small code reviews over and over again.</strong> Usually when we code, our flow is much more about actively writing code, and implementing the solution plan in our head. This is now sprinkled with reading and reviewing code, which is cognitively different, and also something most of us enjoy less than actively producing code. <strong>This can lead to review fatigue, and a feeling that the flow is more disrupted than enhanced by the assistant.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<em>Automation Bias</em> is our tendency “to favor suggestions from automated systems and to ignore contradictory information made without automation, even if it is correct.” <strong>Once we have had good experience and success with GenAI assistants, we might start trusting them too much.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;[…] once we have that multi-line code suggestion from the tool, it can feel more rational to spend 20 minutes on making that suggestion work than to spend 5 minutes on writing the code ourselves once we see the suggestion is not quite right.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Once we have seen a code suggestion, it’s hard to unsee it, and we have a harder time thinking about other solutions.</strong> That is because of the <em>Anchoring Effect</em>, which happens when “an individual’s decisions are influenced by a particular reference point or ‘anchor’”. so while coding assistants’ suggestions can be great for brainstorming when we don’t know how to solve something yet, <strong>awareness of the Anchoring Effect is important when the brainstorm is not fruitful, and we need to reset our brain for a fresh start.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>The framing of coding assistants as pair programmers is a disservice to the practice</strong>, and reinforces the widespread simplified understanding and misconception of what the benefits of pairing are.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Pair programming however is also about the type of knowledge sharing that creates collective code ownership, and a shared knowledge of the history of the codebase.</strong> It’s about sharing the tacit knowledge that is not written down anywhere, and therefore also not available to a Large Language Model. <strong>Pairing is also about improving team flow, avoiding waste, and making Continuous Integration easier.</strong> It helps us practice collaboration skills like communication, empathy, and giving and receiving feedback. And it provides precious opportunities to bond with one another in remote-first teams.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;LLMs rarely provide the exact functionality we need after a single prompt. So iterative development is not going away yet. Also, LLMs appear to “elicit reasoning” (see linked study) when they solve problems incrementally via chain-of-thought prompting. <strong>LLM-based AI coding assistants perform best when they divide-and-conquer problems, and TDD is how we do that for software development.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Some examples of starting context that have worked for us:&rdquo;<ul>
<li><strong>ASCII art mockup</strong></li>
<li><strong>Acceptance Criteria</strong>
<li><div>Guiding Assumptions such as:<ul>
<li><strong>“No GUI needed”</strong></li>
<li><strong>“Use Object Oriented Programming” (vs. Functional Programming)</strong></li></ul></div></ul></div></blockquote><blockquote class="quote quote-block "><div>&ldquo;For example, if we are working on backend code, and Copilot is code-completing our test example name to be, “given the user… clicks the buy button ” , <strong>this tells us that we should update the top-of-file context to specify, “assume no GUI”</strong> or, “this test suite interfaces with the API endpoints of a Python Flask app”.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Copilot often fails to take “baby steps”. For example, when adding a new method, the “baby step” means returning a hard-coded value that passes the test. To date, we haven’t been able to coax Copilot to take this approach.&rdquo;</div></blockquote><p>Knowing a bit about how LLMs work, there&rsquo;s no way you really could train it to do TDD, because it&rsquo;s an iterative process. It doesn&rsquo;t know what TDD is, nor does the way it&rsquo;s built have any mechanism for learning how to do it. Nor does it know what coding is, for that matter. It&rsquo;s just a really, really good guesser. Everything it does is hallucination. It&rsquo;s just that some of it is useful.</p>
<blockquote class="quote quote-block "><div>&ldquo;As a workaround, we “backfill” the missing tests. While this diverges from the standard TDD flow, we have yet to see any serious issues with our workaround.&rdquo;</div></blockquote><p>Changing how you program because of the tool is something you should do deliberately. This is a slippery slope.</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>For implementation code that needs updating, the most effective way to involve Copilot is to delete the implementation and have it regenerate the code from scratch.</strong> If this fails, deleting the method contents and writing out the step-by-step approach using code comments may help. Failing that, the <strong>best way forward may be to simply turn off Copilot momentarily and code out the solution manually.</strong>&rdquo;</div></blockquote><p>Jaysus. That&rsquo;s pretty grim.</p>
<blockquote class="quote quote-block "><div>&ldquo;The common saying, “garbage in, garbage out” applies to both Data Engineering as well as Generative AI and LLMs. Stated differently: higher quality inputs allow for the capability of LLMs to be better leveraged. In our case, TDD maintains a high level of code quality. This <strong>high quality input leads to better Copilot performance than is otherwise possible.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;Model-Driven Development (MDD). We would come up with a modeling language to represent our domain or application, and then describe our requirements with that language, either graphically or textually (customized UML, or DSLs). <strong>Then we would build code generators to translate those models into code, and leave designated areas in the code that would be implemented and customized by developers.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>That unreliability creates two main risks: It can affect the quality of my code negatively, and it can waste my time.</strong> Given these risks, quickly and effectively assessing my confidence in the coding assistant’s input is crucial.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;<strong>Can my IDE help me with the feedback loop? Do I have syntax highlighting, compiler or transpiler integration, linting plugins? Do I have a test, or a quick way to run the suggested code manually?</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;I have noticed that in CSS, <strong>GitHub Copilot suggests flexbox layout to me a lot.</strong> Choosing a layouting approach is a big decision though, so I would want to consult with a frontend expert and other members of my team before I use this.&rdquo;</div></blockquote><p>That&rsquo;s because you care about architecture. Review was always important, but more so when code is being written by something you never hired.</p>
<blockquote class="quote quote-block "><div>&ldquo;How long-lived will this code be? <strong>If I’m working on a prototype, or a throwaway piece of code, I’m more likely to use the AI input without much questioning than if I’m working on a production system.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;[…] <strong>it’s also good to know if the AI tool at hand has access to more information than just the training data.</strong> If I’m using a chat, I want to be aware if it has the ability to take online searches into account, or if it is limited to the training data.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;To mitigate the risk of wasting my time, one approach I take is to give it a kind of ultimatum. <strong>If the suggestion doesn’t bring me value with little additional effort, I move on.</strong> If an input is not helping me quick enough, <strong>I always assume the worst about the assistant</strong>, rather than giving it the benefit of the doubt and spending 20 more minutes on making it work.&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;GitHub Copilot is not a traditional code generator that gives you 100% what you need. But <strong>in 40-60% of situations, it can get you 40-80% of the way there, which is still useful.</strong> When you adjust these expectations, and give yourself some time to understand the behaviours and quirks of the eager donkey, you’ll get more out of AI coding assistants.&rdquo;</div></blockquote>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4895</guid>
    <title><![CDATA[AOT, JIT, and PGO in .NET]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4895</link>
    <pubDate>Fri, 15 Dec 2023 13:15:17 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Dec 2023 13:15:17 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The latest video by Nick Chapsas has a more-than-usually clickbait-y headline. The &ldquo;big&rdquo; problem that NativeAOT has, is that it&rsquo;s 4% slower during runtime than the JIT-compiled version.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/gJcPqdbKF90" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=gJcPqdbKF90">NativeAOT in .NET 8 Has One Big Problem</a> by <cite>Nick Chapsas</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>That doesn&rsquo;t seem like such a big problem to me, when the point of AOT is to improve cold-start times for applications launched on-demand. For that use-case, AOT shines. It&rsquo;s over 4x faster on startup than the JIT-compiled version. It&rsquo;s incredibly impressive that JIT-compilation takes less than 1/10 of a second, but it&rsquo;s still 4x slower than AOT.</p>
<p><span style="width: 400px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4895/aot_vs_jit.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4895/aot_vs_jit.jpg" alt=" " style="width: 400px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4895/aot_vs_jit.jpg">Spider graph of AOT vs. JIT</a></span></span></p>
<p>So, you get the app started 4x fast, but it then performs 4% more slowly than the non-AOT version. It really depends on the use-case, but it&rsquo;s great for the common one of starting a server to answer a function call—think Azure Functions or AWS Lambdas—and then shutting down again, possibly immediately.</p>
<p><a href="https://www.linkedin.com/in/damianpedwards/">Damian P Edwards</a> (Principal Architect at Microsoft) commented on the post,</p>
<blockquote class="quote quote-block "><div><p>&ldquo;[There are a] few things that cause the slightly lower performance in native AOT apps right now. First (in apps using the web SDK) is <strong>the new DATAS Server GC mode.</strong> This new GC mode uses far less memory than traditional ServerGC by dynamically adapting memory use based on the app&rsquo;s demands, but in this <strong>1st generation it impacts the performance slightly.</strong> The goal is to remove the performance impact and enable DATAS for all Server GC apps in the future.</p>
<p>&ldquo;Second is CoreCLR in .NET 8 has <strong>Dynamic PGO enabled by default, which allows the JIT to recompile hot methods with more aggressive optimizations</strong> based on what it observes while the app is running. Native AOT has static PGO with a default profile applied and by definition can never have Dynamic PGO.</p>
<p>&ldquo;Thirdly, <strong>JIT can detect hardware capabilities (e.g. CPU intrinsics) at runtime</strong> and target those in the code it generates. Native AOT however defaults to a highly compatible target instruction set which won&rsquo;t have those optimizations but you can specify them at compile time based on the hardware you know you&rsquo;re going to run on.</p>
<p>&ldquo;Running the tests in [the] video with DATAS disabled and native AOT configured for the target CPU could improve the results slightly.&rdquo;</p>
</div></blockquote><p>To summarize:</p>
<ol>
<li>The DATAS GC mode is in-use for AOT, but still being fine-tuned.</li>
<li><div class=" "><p>An AOT-compiled app cannot benefit from <em>dynamic</em> <a href="https://en.wikipedia.org/wiki/Profile-guided_optimization">PGO</a>. It benefits from <em>static</em> PGO, but cannot recompile itself on-the-fly because it doesn&rsquo;t have a JIT compiler to do so.</p>
<p>The JIT-compiled app can dynamically recompile what it observes as performance hotspots with more highly optimized code. I wrote a bit about how Safari does something similar for JavaScript in <a href="https://www.earthli.com/news/view_article.php?id=3057">Optimizing compilation and execution for dynamic languages</a>—although for JavaScript, dynamic recompilation is sometimes necessary for backing out of an incorrect assumption about what type a variable is going to have.</p>
</div></li>
<li><div class=" "><p>As well, a JIT-compiled app can take actual hardware capabilities into account, while an AOT-compiled app necessarily targets a static hardware profile.</p>
<p>The generic hardware profile is going to be extremely conservative about capabilities because if it assumes a capability that doesn&rsquo;t exist, the app simply won&rsquo;t run. Choosing a hardware profile for AOT that matches the target hardware would boost performance.</p>
</div></li></ol><p>I guess that was more of a rephrasing, rather than a summary.</p>
<p>Anyway, another commenter asked,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] would it be possible in the future for a JIT application with Dynamic PGO that has run for a while and has made all kinds of optimizations to then create a &ldquo;profile&rdquo; of sorts that could be used by the Native AOT compiler to build an application that is both fast in startup time and highly optimized for a given workload?&rdquo;</div></blockquote><p>Yes. That should be possible. It&rsquo;s unclear what sort of extra performance boost this would give, especially if you&rsquo;d already fine-tuned the target hardware profile—which is the first thing you should do. I could imagine adding this sort of profiling as a compilation step, though. You always have to be careful, though, whenever you&rsquo;re running something in production that is different than what you&rsquo;ve tested. We put a lot of faith in the JIT and dynamic PGO, don&rsquo;t we?</p>
<p>I wanted to also note that, at the end of the video, Chapsas showed Microsoft&rsquo;s numbers, which confirm the performance drop, <em>but also show an over 50% reduction in working set!</em> Dude! How do you not mention that!? The app uses less than half of the memory and runs almost as fast? Yes, please! That&rsquo;s a huge win for people paying for cloud-based services. </p>
<p>For once, I&rsquo;m somewhat surprised to see how naive Nick&rsquo;s take is—that a 4% drop in performance is at-all significant, especially when the &ldquo;slow&rdquo; version is still processing 50,000 requests per second in a performance-constrained environment. He did mention a trade-off, but was very excited to tell people that AOT is <em>slower</em> during runtime.</p>
<p>There are always trade-offs and you should be very aware of the actual non-functional requirements for your application before you decide whether to use a technology or not. For 99.9% of the applications, the 4% drop in performance vis á vis a JIT-compiled version won&rsquo;t be the deciding factor. When it&rsquo;s accompanied by a working set that&rsquo;s only ½ the size, then it becomes an even more attractive target.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4897</guid>
    <title><![CDATA[How to replace "warnings as errors" in your process]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4897</link>
    <pubDate>Fri, 15 Dec 2023 11:52:23 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Dec 2023 11:52:23 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">27. Jan 2025 14:25:10 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>A build started started failing after a commit. However, the errors had nothing to do with the changes in the commit. A little investigation revealed that the cloud agent had started using a newer version of the build tool that included an expanded set of default warnings. These warnings started appearing first on CI because developers hadn&rsquo;t had the chance to update their tools yet.</p>
<p>The &ldquo;warnings as errors&rdquo; setting turned what would have been a build with a few extra warnings into a failing build that prevented a developer from being able to apply completely unrelated changes. The setting allowed new, unrelated, and irrelevant warnings to push their way to the top of the priority queue.</p>
<p>👉 <abbr title="too long; didn't read">tl;dr</abbr>:  I don&rsquo;t think we should use the &ldquo;errors as warnings&rdquo; setting anymore. You can get the same benefit —and even more—by using newer, more finer-grained configuration options.</p>
<h2>What are we trying to accomplish?</h2><p>This section wasn&rsquo;t included in my original draft of this essay. It only occurred to me under the shower that this is the <em>real</em> reason why I wrote a ten-page essay to answer a teammate&rsquo;s question in a PR review.</p>
<p>In hindsight, it&rsquo;s obvious: to answer whether we should re-enable the &ldquo;warnings as errors&rdquo; setting, we should first think about what doing so would accomplish. What need does it fulfill?</p>
<p>The rest of this essay meanders drunkenly along a path toward what I hope is a reasonable answer.</p>
<h2>My team doesn&rsquo;t care about warnings</h2><p>I understand the sentiment. You&rsquo;re in a team that never, or rarely, looks at warnings. You&rsquo;ve given up on teaching them how to look at warnings and keep them fixed. Fine. You just make every warning an error and now they absolutely have to fix everything. Problem solved.</p>
<h2>My team now only cares about warnings</h2><p>Except it isn&rsquo;t, is it? Not really.</p>
<blockquote class="quote pullquote align-right right" style="width: 10em"><div>It’s like forcing people to wash their dishes while they’re still eating their meal.</div></blockquote><p>What you&rsquo;ve now done is ensured that your team will be constantly fixing errors that aren&rsquo;t really errors at times when they wouldn&rsquo;t want or need to be doing so. It’s like forcing people to wash their dishes while they’re still eating their meal. [1]</p>
<p>Don&rsquo;t make me waste time pretty-printing code that I&rsquo;m still writing! How annoying is it when you can&rsquo;t run a test because your comment has an extra line below it? Are you kidding me? [2]</p>
<h2>My team is not homogenous [3]</h2><p>When the runtime changes or any external dependencies change, you&rsquo;ll have to fix all of the new warnings because you&rsquo;re making them into errors. Instead of leaving yourself time to properly address the warnings, it immediately becomes your highest priority because <em>you can no longer work.</em></p>
<p>The practice leaves your team in a position where it might lose the runtime lottery, When the runtime changes, you won&rsquo;t have control which person will be forced have to make those fixes so they can continue working. It may be the wrong person in your team, someone who’s going to choose the quickest way to get compiling again rather than the best way to incorporate the new errors and warnings and inspections.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4897_1_body" class="footnote-number">[1]</span> I added this sentence added on January 1st, 2025 because I thought of it sometime over winter break and though it was a good mental image.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4897_2_body" class="footnote-number">[2]</span> There are ways to configure formatting automatically to reduce incidences of these. Those ways are discussed a bit below.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4897_3_body" class="footnote-number">[3]</span> I added this section on January 1st, 2025 as well.</div><h2>How much do you trust your team?</h2><p>If your team <em>does</em> care about warnings, then, … why do you need to make them errors?</p>
<p>Before handcuffing developers with a setting, think about whether there isn&rsquo;t a trust problem first. Are you addressing a symptom rather than the cause?</p>
<p>While it&rsquo;s possible that applying handcuffs is the best possible solution in your case, consider that there are other solutions along a spectrum that goes from &ldquo;enforcing discipline&rdquo; to &ldquo;relying on individual discipline&rdquo;.</p>
<p>Any feature that&rsquo;s enforced at all times will end up hampering efficiency and flexibility in some cases, while any feature that&rsquo;s left up to developers is liable to not be applied consistently.</p>
<p>The job of the person setting up code-style configuration is to thread that needle, tailoring the configuration for the team and solution at hand.</p>
<p>If you have a lot of solutions and teams, then you also get to consider the maintenance overhead of having too many custom configurations. In that case, you might want to make a few standard bundles that group teams and solutions, like &ldquo;legacy&rdquo;, &ldquo;modern&rdquo;, &ldquo;junior team&rdquo;, etc.</p>
<p>You don&rsquo;t have to name them like that, but the name should give you an idea of how loose or restrictive the settings would be.</p>
<h2>Let the CI do it, then</h2><p>I don&rsquo;t have time for all of that. Let&rsquo;s just run them on the CI. Warnings as errors in the cloud FTW!</p>
<p>Now you&rsquo;re allowing team members to push all the way up to the server before they realize that they have errors. Granted, they&rsquo;re actually warnings, but you can&rsquo;t merge to master until you fix them, so, yeah, they&rsquo;re errors. This isn&rsquo;t less annoying.</p>
<p>But, but, but, what if they&rsquo;re, like, real warnings? Like &ldquo;possible <code>NullReferenceException</code>&rdquo; or something like that? That&rsquo;s a good point, sure. </p>
<p>But, in most cases, it&rsquo;s something more like &ldquo;extra line found at end of file&rdquo;, &ldquo;space missing after parenthesis&rdquo;, &ldquo;method can be made private&rdquo;, &ldquo;class should be internal&rdquo;, etc.</p>
<p>There are better—more automated—ways of addressing some of those, which we&rsquo;ll discuss below.</p>
<h2>The CI is not necessarily stable</h2><p>Also, what if some warnings start appearing in your CI because of a tooling change? That can never happen, though, right? Because you&rsquo;ve locked down <em>all</em> of your tool versions so that it can never happen? No? You didn&rsquo;t do that? You&rsquo;re using &ldquo;latest&rdquo;? Why?</p>
<blockquote class="quote pullquote align-right right" style="width: 12em"><div>The people building the tools are pretty clever, so we want to know what new things they have to tell us about our code.</div></blockquote><p>Oh, right. Because it makes sense. If you lock down your tool versions, you run the very real risk of not knowing when your build will stop running with more-modern tools. You run the risk of it having been years since you last changed anything in your build and your being stuck with those settings and old tools … until they&rsquo;re obsolete or no longer available on your build server.</p>
<p>It&rsquo;s better to use &ldquo;latest&rdquo; and have an occasional spike of warnings than to just never know where you stand with newer toolchains. Locking down tool versions leads to things like DevOps having to set up on-site build agents with Visual Studio 2010 on them for certain projects.</p>
<p>OK, so we want to use latest tools, but that means that we might also get new warnings. These are a good thing! The people building the tools are pretty clever, so we want to know what new things they have to tell us about our code.</p>
<h2>The future broke the build</h2><p>What we don&rsquo;t want is for those new things to break builds that used to be running just fine.</p>
<p>This usually shows up when someone pushes new commits, runs the CI, and sees that they&rsquo;re getting errors that they didn&rsquo;t see locally. WTH? &ldquo;<em>My code</em> didn&rsquo;t cause those errors?&rdquo;</p>
<p>The drawback here is this is (A) annoying and (B) it&rsquo;s very possible that the new errors are a distraction at this point in time. The person&rsquo;s bug fix may be important, but the new warnings have now bumped themselves to the top of the priority queue!</p>
<p>And what if the person whose build has failed isn&rsquo;t well-qualified to address these new warnings? Well, then they get to bump the new warnings to the top of someone else&rsquo;s priority queue! Probably a more senior developer. Fun for all!</p>
<p>What&rsquo;s the solution then? Well, if you realize that the new warnings appeared because of a tool change, then I suppose you should try to pin the tool version on the CI, with all of the drawbacks outlined above.</p>
<p>That&rsquo;s assuming that the person to whom this happens is (A) capable of figuring this out and (B) knows how to pin the tool version. And (C) we don&rsquo;t really like that solution, for the reasons outlined above.</p>
<h2>What were the requirements again?</h2><p>What about if we think again about what we&rsquo;re trying to accomplish with &ldquo;warnings as errors&rdquo;?</p>
<p>Thinking…🤔🤔🤔…</p>
<dl><dt>The system must allow individual configuration of severity.</dt>
<dd>We want <em>certain</em> warnings to be errors.</dd>
<dt>The system must not require all team members be capable of configuring it.</dt>
<dd>We want clever tool people to configure things for maximum developer comfort, warning visibility with everyone having to become a clever tool person (which isn&rsquo;t generally possible).</dd>
<dt>The system must be configurable per solution.</dt>
<dd><div class=" "><p>Each solution should be able to decide what is an error and what is a warning and what is a suggestion. You can&rsquo;t make &ldquo;possible null-reference exception&rdquo; an error in some legacy solutions without completely killing forward progress.</p>
<p>We want warnings to indicate potential problems, but be careful about forcing a solution to address all of them immediately. It&rsquo;s more realistic to create tasks to slowly eliminate warnings, only switching a setting to an error later, to prevent future transgressions.</p>
</div></dd>
<dt>The system must have a versioned configuration.</dt>
<dd>We want the configuration to grow with the project, so older versions have their own configuration, with which they can still be run when needed.</dd>
<dt>The system should use default settings wherever possible</dt>
<dd>No matter how clever your own team&rsquo;s tool person is, the people who designed the whole thing are probably even better. Apply configuration changes knowingly and judiciously.</dd>
<dt>The system should not force a developer to change priorities unnecessarily.</dt>
<dd><div class=" "><p>If the developer is focused on something, they shouldn&rsquo;t be forced to switch modes and prioritize formatting. Use gentle, visible hints, unless it&rsquo;s really, really relevant to what they&rsquo;re working on.</p>
<p>For example, a possible <code>NullReferenceException</code> is something to be avoided, but is it really an error in all code? It&rsquo;s definitely a <em>warning</em>, but if the developer knows that it doesn&rsquo;t matter <em>right now</em>, then they should be able to ignore it, no? </p>
<p>I mean, they haven&rsquo;t even <em>committed it</em> yet (as far as you know 😉). Maybe they have a breakpoint to see how the heck that variable could be <code>null</code> in the first place and they were just going to bounce the <abbr title="Extended Instruction Point">EIP</abbr> past the crash anyway. <abbr title="You Only Live Once">YOLO</abbr>.</p>
<p>Anyway, we want to be really careful about how pushy we are with the IDE configuration. We want to strike a balance between missing actual problems and decreasing efficiency. We don&rsquo;t want the developer above to have to write a suppression—or, even worse, do some other, ad-hoc short-circuit of inspections—in order to keep working.</p>
</div></dd>
<dt>The system should be future-proof</dt>
<dd>We don&rsquo;t want running builds to stop running just because we&rsquo;ve upgraded tools, but made no changes to the tools. This won&rsquo;t always be possible but, in this case, the &ldquo;warnings as errors&rdquo; setting is a pretty obvious <a href="https://en.wiktionary.org/wiki/footgun">footgun</a>.</dd>
<dt>The system should provide developers everything they need locally to avoid CI failure</dt>
<dd><div class=" "><p>Something should fail only on CI as a last resort. That is, a developer must have tools that make it relatively easy to pass CI. This includes being able to see all warnings in the solution, whether warnings would fail the CI, or having an easy way to apply formatting to all files, if incorrect formatting would fail the build.</p>
<p>We want to avoid a process that leads to half of our commits being called &ldquo;fix formatting&rdquo; and &ldquo;remove warnings&rdquo;.  So, we should consider things like having the IDE auto-reformat files on save.</p>
</div></dd>
<dt>The system should discourage allowing inspection violations to be committed</dt>
<dd><div class=" "><p>Inspections should be applied and made visible as quickly as possible, to give the developer the opportunity to produce conforming code from the get-go. The path of least resistance should result in committing code that will also pass CI.</p>
<p>We don&rsquo;t want to encourage &ldquo;noisy&rdquo; commits that &ldquo;fix up&rdquo; formatting or other inspection violations. We would rather have a high signal-to-noise ratio in our commits. We want compact, descriptive commits—so we don&rsquo;t want bug-fix commits to include formatting changes to other parts of the file, if we can avoid it.</p>
</div></dd>
</dl><p>Looking at these requirements, we have to conclude that the &ldquo;warnings as errors&rdquo; configuration option is an absolute cudgel that we had to use in the old days because we didn&rsquo;t have fine-tuned control of the inspection-configuration.</p>
<h2>We are no longer in the dark ages</h2><p>Can we do better today, with modern tools?</p>
<p>Absolutely, we can! Most modern IDEs support <code>.editorconfig</code>, which allows fine-tuned configuration of both code-style and formatting, especially for languages like C# and TypeScript/JavaScript. The wide variety of JetBrains, Intellij-based tools use it as well, e.g. <a href="https://www.jetbrains.com/help/pycharm/configuring-code-style.html#import-export-schemes">PyCharm</a>, <a href="https://www.jetbrains.com/help/webstorm/configuring-code-style.html#configuring-code-style-for-a-lan">WebStorm</a>, or <a href="https://www.jetbrains.com/help/phpstorm/configuring-code-style.html#import-export-schemes">PHPStorm</a>. Visual Studio understands it. Visual Studio Code understands it.</p>
<p>Of course, the devil is in the details and, the degree to which code-inspection configuration applies from one IDE to another depends very much on the level of standardization for that language and environment. The .NET/C# world has a high degree of standardization, which is very helpful.</p>
<h2>Using EditorConfig</h2><p>EditorConfig allows you to control almost anything you can think of about your code style or formatting. These are called <em>inspections</em>, each of which you can configure with an inspection-specific value and a severity to assign when the inspection is triggered.</p>
<p>For example:</p>
<pre class=" "><code>dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
dotnet_style_prefer_auto_properties = true:silent</code></pre><p>The two inspections above should be relatively obvious. In both cases, the preferred setting is configured, but the severity is &ldquo;silent&rdquo;, so the IDE doesn&rsquo;t complain about it.</p>
<p>What&rsquo;s the point of configuring a preference and then not showing it to the developer?</p>
<p>Ah, because the developer is the not the only one modifying the code.</p>
<p>Excuse me?</p>
<h2>The IDE also writes code</h2><p>Don&rsquo;t forget that the IDE will auto-format the code when requested. The IDE also writes code when it refactors anything. It needs to know how to format the code that it&rsquo;s inserting or modifying.</p>
<p>The IDE uses the configuration in the EditorConfig to determine how to format the code. Your tools guy can configure the EditorConfig to conform to the style that the solution / team wants to use. When the code is auto-formatted or refactored, everything should end up looking just the way they wanted it.</p>
<h2>How to apply &ldquo;silent&rdquo; inspections?</h2><p>If you have a &ldquo;silent&rdquo; severity, that means it&rsquo;s something that you don&rsquo;t want the team wasting time with during development. However, if no-one ever auto-formats the code, then those inspections will never be applied.</p>
<p>You should consider the process by which your solution will be made to conform with silent inspections in the EditorConfig.</p>
<dl><dt>Visible inspections</dt>
<dd><div class=" "><p>If the inspection severity is <code>suggestion</code> or higher [4], then the developer sees an indicator in the code  when the file is open.</p>
<p>Suggestions, warnings, and errors are shown in the build output, as well. Of course, the developer can disable showing warnings and messages (where suggestions appear) in the error-list pane, but you can&rsquo;t control everything—and you shouldn&rsquo;t try.</p>
<p>Give your developers the tools and configuration to be efficient and produce good code, but try not to be too pushy about when they do it.</p>
</div></dd>
<dt>Invisible inspections</dt>
<dd><div class=" "><p>If the inspection severity is <code>silent</code> or <code>none</code>, then the inspection setting is only used by auto-formatting and refactoring tools.</p>
<p>In this case, you&rsquo;ll have to consider <em>when</em> will your code be formatted? Do your developers occasionally auto-format files? Do they auto-format on save? Is there a step in the CI that auto-formats everything before compilation? If so, does it commit those changes? Or does the CI reject for formatting warnings?</p>
<p>If you have silent inspections, be honest about when they&rsquo;re going to be applied. If you don&rsquo;t have a plan, then they will be applied seemingly randomly when someone inadvertently triggers the hotkey for auto-formatting a file [5], which may lead to unpleasant surprises and/or messy commits.</p>
</div></dd>
</dl><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4897_4_body" class="footnote-number">[4]</span> <p>There is a bit of a mismatch with using .EditorConfig versus the JetBrains-native configuration: <a href="https://www.jetbrains.com/help/resharper/Code_Analysis__Configuring_Warnings.html#editorconfig">JetBrains tools support an additional severity level called &ldquo;Hint&rdquo;</a>, which is generally shown as a green squiggly line rather than the blue one for warnings. However, if you set the severity to &ldquo;hint&rdquo;, Visual Studio interprets it as a warning, showing it as such in both the IDE and in the build output.</p>
<p>On top of that, JetBrains seems to think that the <code>silent</code> option is called <code>none</code>, although it seems to understand <code>silent</code> well enough.</p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4897_5_body" class="footnote-number">[5]</span> Probably because of historical reasons, there is a difference between Visual Studio&rsquo;s <em>Format Document</em> (<kbd>Ctrl</kbd> + <kbd>K</kbd>, <kbd>D</kbd>), ReSharper/Rider&rsquo;s <em>Reformat Code</em> (<kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>Enter</kbd>), and ReSharper/Rider&rsquo;s <em>Cleanup Code</em> (<kbd>Ctrl</kbd> + <kbd>E</kbd>, <kbd>C</kbd>). I can&rsquo;t tell you exactly which inspections are considered in which mode, but I&rsquo;ve listed them in order of &ldquo;number of changes they seem to make to the code&rdquo;, with Visual Studio&rsquo;s native command seeming to make the fewest changes.</div><h2>Code Style vs. Formatting</h2><p>Let&rsquo;s clear up the distinction between these two main groups of inspections.</p>
<dl><dt>Code style</dt>
<dd>A code-style inspection expresses a preference for something that affects semantic content. That is, applying the fix for the inspection may change the code in a way that makes it compile differently or may lead to it not compiling at all. Even something as subtle as using <code>var</code> instead of an explicit type can, in very rare cases, lead to code that no longer compiles. By now, many IDE tools are generally clever enough to avoid even suggesting such a change, but it can still happen.</dd>
<dt>Formatting</dt>
<dd>A formatting inspection expresses a preference that affects only syntactic content. That is, applying the fix for the inspection will change the appearance, but will not change how the code compiles. Consistent formatting is very important for direct readability of the code, but also to avoid spurious differences in files when inspecting commits. The fewer differences there are, the less likely it is that conflicts appear when merging or rebasing.</dd>
</dl><h2>Local vs. CI</h2><p>So we&rsquo;ve examined inspections in detail and talked a lot about setting severity to optimize the developer feedback loop i.e., we don&rsquo;t want to mess with a developer&rsquo;s priority queue unless absolutely necessary.</p>
<p>But aren&rsquo;t there some things that we might allow a developer to do locally but not allow to pass CI? That&rsquo;s where the &ldquo;warnings as errors&rdquo; setting ensured that the CI never passed, even if the developer forgot to check something locally. For example, it&rsquo;s important to have consistent formatting before attempting a merge.</p>
<p>There are other ways to encourage and support proper coding practices, though.</p>
<dl><dt>Auto-formatting files</dt>
<dd>Most IDEs have an option to run formatting or code cleanup automatically when files are saved. Consider setting this option in your solution. Developers will become accustomed to having the IDE lightly reformat even their WIP code and they will always have correctly formatted files.</dd>
<dt>Local pre-commit hooks</dt>
<dd><div class=" "><p>Pre-commit hooks can run locally, running global formatting on the code base before a developer can commit. This is kind of touchy, as sometimes developers are just committing a <abbr title="Work in progress">WIP</abbr> to avoid losing their changes. It would be annoying if you had to clean up your formatting just to commit those.</p>
<p>You could include auto-formatting in the commit hook, but it&rsquo;s probably better to set up auto-formatting in the IDE.</p>
</div></dd>
<dt>Server pre-commit hooks</dt>
<dd><div class=" "><p>Instead of a local pre-commit hook, you can configure a pre-commit hook on the server. This hook could cause a push to be rejected if its head commit doesn&rsquo;t conform to certain conditions.</p>
<p>But…isn&rsquo;t that what the CI is for? Well, kind of, but the CI runs only <em>after</em> the commits have landed on the server. It&rsquo;s prefereable to have the developer fix commits locally before being able to push, again, to avoid &ldquo;fix formatting&rdquo; and &ldquo;cleanup warnings&rdquo; commits.</p>
<p>You could choose which branch patterns to run these on.</p>
</div></dd>
</dl><p>My recommendation is to lean as heavily as possible on IDE configuration before getting lost in the weeds with commit hooks.</p>
<h2>Avoiding ugly or &ldquo;noisy&rdquo; commits</h2><p>As soon as we start talking about &ldquo;fixes&rdquo; for warnings or formatting, we&rsquo;re talking about &ldquo;noisy&rdquo; commits. If we enforce inspections more strictly on CI than we do locally, then there will be more &ldquo;fixup&rdquo; commits.</p>
<p>OK, so what do we do about them?</p>
<p>Squash &lsquo;em!</p>
<p>Right? Right?</p>
<p>🫠</p>
<p>Kind of. Look, the PR machinery allows you to merge, rebase, squash-merge, or squash-rebase. That&rsquo;s OK, but it&rsquo;s not great. A lot of times, you&rsquo;ll have four commits that are descriptive and semantically relevant, describing changes that were made, as well as a few commits that address problems that either came up in CI or as part of the review. Don&rsquo;t you think you should squash those into the four commits and make a clean history instead of just squashing the whole lump into one big hairball?</p>
<p>Or do you think that each PR should have only one commit, equating a branch with a commit (as e.g. plugins like <a href="https://graphite.dev/">Graphite</a> positively encourage)? I recently wrote <a href="https://www.earthli.com/news/view_article.php?id=4900">PRs suck. Stop trying to fix them.</a> that also touches on the workflow outlined below.</p>
<p>You see how tool configuration affects everything? You have to think about how your team builds PRs, how they review PRs, how they repair PRs after review—or whether they even use PRs.</p>
<p>I would encourage a more real-time review culture, where possible.</p>
<ol>
<li>Set up the tools so a developer has a good chance of committing conforming code</li>
<li>When a developer has a set of commits they want to push, they ask another team member to review, live, explaining what they did.</li>
<li>The live reviewer can point out any issues in the code and they can repair them <em>together</em>, all without wasting time writing and reading review comments.</li>
<li>Those repairs can be squashed into the appropriate commits before anything&rsquo;s pushed to the server.</li>
<li>Once on the server, the CI runs. If something still fails, the original developer can squash in fixes and force-push [6] to keep the commits in the PR clean.</li>
<li>You can create a PR to note the integration to master, but then its mostly a formality.</li></ol><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4897_6_body" class="footnote-number">[6]</span> <p>What&rsquo;s the problem? Don&rsquo;t you trust your team members to decide what to do with their own highly ephemeral feature branches?</p>
<p>Allowing force-push encourages team members to regularly pushing to the server to back up their work, but still care about what the commit history looks like. Allowing force-push allows your team members to revise their commit history until it tells a coherent story, even if they&rsquo;ve already pushed. See <a href="https://www.earthli.com/news/view_article.php?id=3864">Rebase Considered Essential</a> for a longer discussion on rewriting commit history.</p>
</div><h2>Configuring your solution</h2><p>Phew! So, what have we learned?</p>
<ul>
<li>There is no one-size-fits-all solution.</li>
<li>Errors are priority interrupts. The developer cannot execute until an error is fixed. Be judicious about which inspections you promote to errors.</li>
<li>&ldquo;warnings as errors&rdquo; is an inelegant configuration option that promotes <em>any</em> warning to an error. That&rsquo;s not very judicious at all. It has been replaced by a much more flexible and granular system in EditorConfig.</li>
<li>Encourage a culture in your team that pays attention to warnings. There will always be team members who do more than others. That&rsquo;s just life. Don&rsquo;t force those team members least equipped to deal with them to address warnings by making them errors. Baby steps.</li>
<li>Silent inspections will only be applied when the tools apply them, e.g., with auto-formatting or refactoring. Consider when those inspections will be applied.</li>
<li>Keep what&rsquo;s executed locally as close as possible to what&rsquo;s executed in CI</li>
<li>Consider how you want your whole process to work, right up through integration to the trunk/main/master.</li></ul><p>If that all sounds like a lot, well—it is. Building clean, maintainable code is a complex undertaking. There are a lot of tools that can help, but you have to put some time into thinking how you want to use them, and then into configuring them so they help you instead of getting in your way.</p>
<p>It&rsquo;s a delicate balancing act: to give developers the best chance of (A) producing conforming code in the first place and (B) avoiding &ldquo;noisy&rdquo; commits, while (C) not hitting them with priority interrupts irrelevant to what they&rsquo;re working on. There will be tradeoffs.</p>
<h2>Sharing or copying configuration?</h2><p>Once you&rsquo;ve set up a couple of solutions, you can just copy/paste the configuration to others as a starting point. Remember, though, that solutions are usually pretty unique. Only consider generalizing or packaging a configuration if you&rsquo;ve considered that,</p>
<ul>
<li>It will be more difficult for solutions that use the package to override settings that turn out not be as standard as you thought.</li>
<li>It will be more time-consuming to make changes to the configuration because you have to roll out a new version—e.g., when the underlying tools change—with potentially multiple stakeholder solutions.</li>
<li>This extra work may discourage solutions from improving the shared configuration. Instead, it will languish, with all users annoyed by the same inconsistencies, but no-one willing to do the work to address them.</li></ul><p>For these reasons, each solution having its own copy of the configuration is probably better. They can just copy/paste—the horror!—improvements where appropriate. If you&rsquo;re worrying about configurations drifting out-of-sync, schedule a work item every few sprints that evaluates and possibly re-syncs configurations.</p>
<h2>Conclusion</h2><p>There are always trade-offs. Improving code-quality is an incremental process. So is configuring the tools that support that process. It gets easier with practice. Good luck!</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4900</guid>
    <title><![CDATA[PRs suck. Stop trying to fix them.]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4900</link>
    <pubDate>Fri, 15 Dec 2023 11:37:03 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Dec 2023 11:37:03 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Dec 2023 11:58:51 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I read through the article <a href="https://graphite.dev/blog/your-github-pr-workflow-is-slow">Your GitHub pull request workflow is slowing everyone down</a> (<cite><a href="http://graphite.dev/">Graphite.Dev</a></cite>) with great interest because I, too, am not thrilled about how PRs work. While I agree with the problems Graphite see with PRs, I think they miss other problems—and I don&rsquo;t like their solution very much.</p>
<h2>PRs are, apparently, HUGE</h2><blockquote class="quote quote-block "><div>&ldquo;The single most important bottleneck is PR size − large PRs can make code reviews frustrating and ineffective. <strong>The average PR on GitHub has 900+ lines of code changes.</strong> For speed and quality, PRs should be maintained under 200 lines—with 50 lines being ideal. To put this in perspective, where giant <strong>500+ line PRs take around 9 days to get merged on average, tiny PRs under 100 lines can make it from creation to landing within hours.</strong>&rdquo;</div></blockquote><p>Holy shit! The average is 900 lines? That&rsquo;s already using the system completely incorrectly. That&rsquo;s so wild. It absolutely confirms my theory that PRs are a terrible way of committing code. I already thought they were terrible just because of the limited UI and lack of introspection of what the code you&rsquo;re reviewing <em>actually does</em>.</p>
<p>PRs don&rsquo;t encourage starting and running the change to verify that it actually works as advertised. You&rsquo;re not using any of the tools that you use to develop code to review it. How silly is that? If you load changes into an IDE, you can see how many warnings there are, see if the layout shifts when you format the document, etc. Why would you want to review in a completely different environment? As Robin Williams once eloquently put it, <a href="https://www.youtube.com/watch?v=iuanrhbAOxA">It&rsquo;s like masturbating with an oven mitt.</a> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>).</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4900/prworkflow.png"><img src="https://www.earthli.com/data/news/attachments/entry/4900/prworkflow.png" alt=" " style="width: 512px"></a></p>
<p>Not only that, but people probably aren&rsquo;t looking at individual commits, so they&rsquo;re just reviewing 900+ lines at once. The fewer people there are looking at individual commits, the fewer people there will be who make good, individual commits. This is a shame because it would counteract the awfulness of reviewing code in the PR web-UI, at least a little bit.</p>
<h2>PR web UIs are not good for reviews</h2><p>There are far better and more efficient ways of reviewing code than with PR web UIs. Reviewing through a PR web UI should be a fallback that you only use when nothing else is possible.</p>
<p>If you&rsquo;re in the same time zone and working on the same schedule as the rest of your team, there is absolutely no reason why you should you be using the PR web UI instead of real-time reviews of local commits.</p>
<p>What the current PR machinery does is fool remote, async teams into thinking that they&rsquo;re reviewing code efficiently. A face-to-face, real-time review will be much more efficient and yield much higher-quality code.</p>
<p>I honestly can&rsquo;t believe the high pain threshold that some developers have.</p>
<p>If the developer hasn&rsquo;t pushed yet, then:</p>
<ol>
<li>Review with the person who wrote it.</li></ol><p>If the developer has pushed and is not available for real-time review, then:</p>
<ol>
<li>Pull.</li>
<li>Open the branch in SmartGit.</li>
<li>Examine the commits.</li>
<li>Launch the solution/project.</li>
<li>Run the tests locally.</li>
<li><div class=" "><p>Apply your own commits instead of review notes wherever possible.</p>
<p>Yes, you can do this! Why not? You&rsquo;re both on the same team. It&rsquo;s a shared code base, not someone&rsquo;s personal zen garden. Instead of explaining what you would want changed, just make your suggestion in the form of a commit. It&rsquo;s often more efficient than writing prose.</p>
</div></li>
<li>Add review notes in SmartGit (synced with GitHub, Azure, GitLab, etc.) or use the PR Web UI to add review notes.</li></ol><p>You can thank me later.</p>
<h2>Errors slip in</h2><blockquote class="quote quote-block "><div>&ldquo;<strong>Problems can easily get hidden between the diffs, and reviewers often make assumptions instead of testing to avoid feeling overwhelmed.</strong> One particularly interesting finding is that as the size of a PR increases (by number of files changed), the amount of time reviewers spend on each file decreases significantly (for PRs with 8 or more files changed).&rdquo;</div></blockquote><p>Obviously! But it&rsquo;s good to measure—this was my intuition. PRs don&rsquo;t encourage local testing or verification in an environment similar to that which the original developer used.</p>
<h2>Dumbing down Git</h2><blockquote class="quote quote-block "><div>&ldquo;<strong>By default, every PR is restricted to only 1 commit of &lt;200 lines, keeping changes tightly scoped.</strong> This forces developers to consciously limit work to related changes—the registration endpoint PR can&rsquo;t sneak in unrelated styling tweaks.&rdquo;</div></blockquote><p>Yikes! I don&rsquo;t like the sound of that. So you make multiple PRs rather than one PR with multiple smaller commits? Why don&rsquo;t you just review commits rather than one giant blob? Do you really need to corral each commit into its own branch and PR to force yourselves to actually make useful commits?</p>
<p>Yeeess? 🧐</p>
<blockquote class="quote quote-block "><div>&ldquo;Stacking centers around breaking down big feature work into chains of smaller pull requests. Each PR is typically limited to 1 commit focused on an isolated change. <strong>This restriction guides developers to consciously make only a single change, squashing and rebasing along the way, instead of cluttering the PR with random unnecessary commits like &ldquo;typo fixes&rdquo;.</strong>&rdquo;</div></blockquote><p>This is yet another technique invented to accommodate teams that don&rsquo;t trust each other, or that contain people who, if they can&rsquo;t be trained to do better—or don&rsquo;t understand what better is—probably shouldn&rsquo;t be programming yet. Instead of teaching team members how to use their tools, they impose an arbitrary rule. What a kindergarten.</p>
<h2>Integrate all the time!?</h2><blockquote class="quote quote-block "><div>&ldquo;Unlike Git workflows, where it is easy to neglect staying updated, <strong>Graphite centers your workflow around continually integrating with the current mainline state.</strong>&rdquo;</div></blockquote><p>Yikes! I don&rsquo;t love the sound of that, either. Doesn&rsquo;t that force you to spend more time on integration that you might have spent working? I understand you don&rsquo;t want to have long-lived branches, but now you&rsquo;re just shooting to the other extreme, forcing integration on every pull.</p>
<p>It&rsquo;s not bad as long as the integrations are automatic, but might not be appropriate for developers who aren&rsquo;t great at resolving merge conflicts. Even if they know how to deal with them well, might they not waste time resolving conflicts integrating a version of their code that wasn&rsquo;t at all ready to be integrated?</p>
<p>I understand that this feature follows from the logic of &ldquo;if you integrate more often, then integration is easier,&rdquo; but, again, you&rsquo;re taking agency out of developers&rsquo; hands, implicitly not trusting your team members. I don&rsquo;t like it.</p>
<p>If you have several stacked commits, I wonder how much shuffling there is in the working tree (causing unwanted IDE reloads) during the integration cascade. Are they somehow integrating without touching the working tree? I don&rsquo;t know that that&rsquo;s possible.</p>
<p>Go ahead and work on the main branch if you want—I do it all the time—but this should be more of a choice than it sounds like it is.</p>
<h2>I remember this…</h2><blockquote class="quote quote-block "><div>&ldquo;<strong>This command will add your changes and create a new branch in one motion.</strong> You can then continue iterating by creating and stacking additional branches:&rdquo;</div></blockquote><p>Ah, I see now. They&rsquo;ve reinvented <a href="https://wiki.mercurial-scm.org/MqTutorial">Mercurial&rsquo;s patch queues</a>. Everything old is new again.</p>
<p>A really bright and good friend of mine <a href="https://arrenbrecht.ch/mercurial/pbranch/intro.htm">added an extension to Mercurial&rsquo;s <code>mq</code></a> decades ago that sounds like it works the same. I remember discussing the technique with him as he was developing it.</p>
<h2>Conclusion</h2><p>I&rsquo;m a bit worried about two things:</p>
<ol>
<li>The one-commit-per-branch thing</li>
<li>The auto-integration-cascade</li></ol><blockquote class="quote quote-block "><div>&ldquo;By cleaning up your PR commit history, you ensure a clear and concise main branch history that makes it easy to see exactly what’s changed over time.&rdquo;</div></blockquote><p>By enforcing one commit per branch, you dumb everything down.</p>
<p>It does seem that, instead of acknowledging that PR supremacy is stupid, Graphite doubles down, strips branches of most of their functionality by equating them to commits, and uses multiple PRs to force people to review by commit. It seems like a waste.</p>
<p>But, hey, maybe I need to actually try it. I might be missing something.</p>
<p>Still, instead of adding another tool, I think you should use git <em>better</em>.</p>
<ul>
<li>Set up your local tools—or in-cloud IDEs, whatever—to support building the kind of code you want. See <a href="https://www.earthli.com/news/view_article.php?id=4897">How to replace “warnings as errors” in your process</a> for more information.</li>
<li>Encourage your team members to learn how to use those tools.</li>
<li>Have a review culture centered on real-time reviews where quick fixes and changes can be made before you&rsquo;ve even pushed anything. This cultivates a culture of respect for commits.</li>
<li>Use PRs only to &ldquo;stamp&rdquo; a set of changes and merge them to the trunk.</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4811</guid>
    <title><![CDATA["Developer experience" is rarely a requirement]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4811</link>
    <pubDate>Thu, 30 Nov 2023 21:23:21 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. Nov 2023 21:23:21 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. Nov 2023 21:43:00 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://bricolage.io/some-notes-on-local-first-development/">Some notes on Local-First Development</a> by <cite>Kyle Matthews</cite> (<cite><a href="http://bricolage.io/">Bricolage</a></cite>) focuses on a very good trend in app development, but focuses a bit too much on what he calls DX, or developer experience.</p>
<blockquote class="quote quote-block "><div>&ldquo;I see “local-first” as shifting reads and writes to an embedded database in each client via“sync engines” that facilitate data exchange between clients and servers. […] The benefits are multiple:&rdquo;<ul>
<li><strong>Simplified state management for developers.</strong></li>
<li>Built-in support for real-time sync, offline usage, and multiplayer collaborative features.</li>
<li>Faster (60 FPS)</li>
<li>CRUD</li>
<li>More robust applications for end-users.</li></ul></div></blockquote><p>I don&rsquo;t want to read too much into it, but he did mention end-users only in the last bullet point.</p>
<p>I think the author is focusing too much on the tech and too little on the value. DX is great and all, but it&rsquo;s about the UX, no? Every app would benefit from realtime updates if it&rsquo;s cheap and easy to build. Almost every app is multiplayer, if you think about it a bit.</p>
<blockquote class="quote quote-block "><div>&ldquo;For almost any real-time use case, I’d choose replicated data structures over raw web sockets as they <strong>give you a much simpler DX</strong> and robust guarantees that clients will get updates.&rdquo;</div></blockquote><p>No, my friend. You&rsquo;ve come to the right conclusion for the wrong reason.</p>
<p>If the tech is solid, if it doesn&rsquo;t negatively influence debuggability or traceability, if it&rsquo;s predictable, if operations can be correlated, if you don&rsquo;t end up limiting your functionality to fit the framework—then go for it.</p>
<p>What I mean is that it&rsquo;s important that the thought process that leads to the correct conclusion serves all stakeholders. If you&rsquo;re only doing things because they&rsquo;re better for developers, then, eventually, you&rsquo;re going to be deciding against the users.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4811/flips_table.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4811/flips_table_tn.jpg" alt=" " class=" align-left"></a>Be aware of the trade-offs, and be sure all of the stakeholders can live with them. What does good DX translate to for other stakeholders? Easier maintenance? Less complexity? Easier onboarding? The DX is really mostly secondary unless you&rsquo;re making a framework, in which case it might matter. No-one cares about DX for real-world products. I love good DX, but I&rsquo;m a developer! As a developer with a lot of experience, I&rsquo;m forced to admit that it&rsquo;s not at all a <em>primary</em> goal. Having good DX might <em>lead to other desirable things</em>, but that doesn&rsquo;t make it directly desirable. Don&rsquo;t forget that.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4807</guid>
    <title><![CDATA[Handling long-running projects]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4807</link>
    <pubDate>Wed, 08 Nov 2023 21:50:04 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Nov 2023 21:50:04 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This is a brilliant interview, in that Oren Eini just talks for about 40 minutes, answering pretty much just one or two questions.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/BDbhhZoL2jw" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=BDbhhZoL2jw">Oren Eini on Building Projects that Endure</a> by <cite>Technology and Friends</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>At one point (I forget where), he says,</p>
<blockquote class="quote quote-block "><div>&ldquo;I don&rsquo;t like unit tests.&rdquo;</div></blockquote><p>Agreed. I <del>like</del>love automated tests. They&rsquo;re indispensable. But I think unit tests are only useful when you want to focus on a failing integration test. David rightly points out that they&rsquo;re really good for pinpointing where a problem actually happens, but Eini says that they also <span class="quote-inline">&ldquo;hinder change&rdquo;</span> because, by their nature, they lock down a lot of the design and implementation.This is absolutely true.</p>
<p>Just to be clear: I think of anything that&rsquo;s not a unit test as an integration test. I generally like &ldquo;smaller&rdquo; integration tests.</p>
<p>It&rsquo;s probably better to just be agile about it and write them when the situation requires it, i.e., when the cause behind a failing integration test is proving difficult to pin down—or when you&rsquo;ve determined the cause and you want a direct proof that you&rsquo;ve fixed the underlying problem.</p>
<p>Ir requires discipline to realize when you need to write more unit tests in order to help pinpoint which component involved in a failing integration test is causing the problem. If you preemptively write all of the unit tests, you&rsquo;re wasting time that could be better spent elsewhere.</p>
<p>I have had no small amount of success with a large test suite that was mostly integration tests. It ran relatively quickly (10 minutes for 10,000 tests on a reasonably classed developer desktop) and helped me survive three major refactorings.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4808</guid>
    <title><![CDATA[Architecture is about intent]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4808</link>
    <pubDate>Tue, 24 Oct 2023 22:39:45 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">24. Oct 2023 22:39:45 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The following video is a talk by Robert Martin &ldquo;Uncle Bob&rdquo;, one of the graybeards worth listening to. This video from 2011 is wide-ranging and contains a lot of brilliant advice. It&rsquo;s stuff that we&rsquo;ve known for a long time now, but every generation of programmers needs to re-learn these things about every 5-10 years. You usually can&rsquo;t stop people from just reinventing the wheel because who wants to watch videos of or read blog posts written by old dudes, ammirite?</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/WpkDN78P884" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=WpkDN78P884">Ruby Midwest 2011 − Keynote: Architecture the Lost Years by Robert Martin</a> by <cite>Robert C. Martin</cite> in 2011 (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>At <strong>10:00</strong>, he talks about how the top-level architecture of most applications reflects the <em>framework</em> used to implement the <em>web-delivery mechanism</em> rather than the purpose of the application itself. In his example, he shows how a Ruby-on-Rails application is immediately recognizable as such, but that you have literally <em>no idea</em> what the application does.</p>
<p>He urges us to consider what this implies about our priorities as architects and developers. It means that we are much more concerned with the technology than with the functionality. This is not good.</p>
<p>He contrasts it with a high-level. 2-d blueprint of the first floor of a church, where the intent is obvious: it&rsquo;s a church (he says). Of course, inferring that it&rsquo;s a <em>church</em> involves applying the appearance of the diagram to a given <em>context</em>—e.g., a very western one—but the point is clear: the standard, top-level view of the design of a church screams out that it&rsquo;s a church. It says nothing about how the church is to be built—or has been built—it says what it <em>is</em>. </p>
<blockquote class="quote quote-block "><div>&ldquo;Architecture is about intent.&rdquo;</div></blockquote><p>Just to be clear: this presentation is from 12 years ago, and we&rsquo;re still confronted with the same concepts—still confronted with the same failure to remember these precepts. Our frameworks still push themselves to the fore.</p>
<p>This is, in a way, the problem with LLM-generated code: we are already <em>terrible</em> at expressing the intent of our software in a way that makes it maintainable and qualitative. We are already mostly terrible at designing and building things in a way that satisfy the nearly-always-implicit non-functional requirements, like maintainability, usability, performance, etc.</p>
<p>And now we&rsquo;re asking another piece of software, whose workings we can&rsquo;t yet fathom, but which we know we&rsquo;ve built by feeding it all of these terrible versions of software, and asking it to write software for us. All of the theory that we&rsquo;ve developed about how to build software will not be respected, except by luck, if the neural net is feeling like that&rsquo;s a high-probability next token.</p>
<p>On the one hand, I have to admit that this doesn&rsquo;t sound much different from how software is built today, except that the human builders are potentially capable of following rules, whereas the software-based builders are less trainable. Again, though, we have decades of experience showing that, while people are <em>ostensibly</em> trainable, they are not necessarily <em>practically</em> trainable, at least in the general case for the general type of person who takes part in this field of endeavor we call <em>programming</em>.</p>
<p>Which leaves us with the question: have we achieved the maximum potential in software development? We already knew everything we needed to know about how to do it decades ago. What is missing is the will to do it that way. It&rsquo;s definitely possible to train people to do it that way. The hangup is, as always, the <em>cost</em>, specifically, the cost-benefit ratio. The perceived benefit of better software is usually far less than the perceived (initial) cost.</p>
<p>And we always perceive only the initial cost because we are super-bad at long-term thinking about complex problems like building software.</p>
<p>At <strong>34:00</strong>, Uncle Bob says</p>
<blockquote class="quote quote-block "><div>&ldquo;There&rsquo;s gotta be some better way to do this. […] This is just 3270 programming poisoned with all sorts of crud. How many languages do you have to do know to write a web application? Well, there&rsquo;s some programming language, but that&rsquo;s incidental! You&rsquo;ve gotta know HTML and CSS and JS and Zazzle and Dazzle and … and, you know, the guy over here&rsquo;s going: &lsquo;let&rsquo;s build communities by leveling people up. Leveling them up! I mean, what we&rsquo;re going to do is hand them a … OK, now, hold this hammer. Ok? Good. You got that hammer? Now, here&rsquo;s another one. Hold that hammer too. Now I&rsquo;ve got a big barrel you&rsquo;ve got to hold on your head. We are not helping our cause with this truly terrible mechanism that we have adopted.&rdquo;</div></blockquote><p>At <strong>41:00</strong>, he says</p>
<blockquote class="quote quote-block "><div>&ldquo;The database is a detail.&rdquo;</div></blockquote><p>This reminds me of <a href="https://www.earthli.com/news/view_article.php?id=4790">The UI is an afterthought, a detail</a>, an article I wrote recently [1] about a 7-year-old video I watched that expressed the same sentiments about external systems that Martin is expressing in his 12-year-old video.</p>
<blockquote class="quote quote-block "><div>&ldquo;That&rsquo;s what architecture is: find some place to draw a line and then make sure every dependency that crosses that line <em>goes in the same direction</em>.&rdquo;</div></blockquote><p>At <strong>55:45</strong>, he says,</p>
<blockquote class="quote quote-block "><div>&ldquo;There&rsquo;s an interesting case of the database—the thing that&rsquo;s <em>so</em> incredibly important—and yet, we took that decision and we just deferred it off the end of the world and then, when somebody needed it, we shimmed it in in a day. Because our architecture had done something right. What is the hallmark of a really good architecture? <strong>A good architecture allows major decisions to be deferred.</strong>&rdquo;</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;A good architecture maximizes the number of decisions <em>not</em> made.&rdquo;</div></blockquote><p>At <strong>1:00:50</strong>, he says,</p>
<blockquote class="quote quote-block "><div>&ldquo;How do you keep the beast under control? <strong>You need a suite of tests you trust with your life.</strong> You must never look at that suite of tests and think &lsquo;you know? I don&rsquo;t think I really tested everything?&rsquo; As soon as you think that, you&rsquo;ve lost it. <strong>Because now you&rsquo;re afraid of your code.</strong> The reason we write our tests first is so that we know, that every single line of code we wrote <em>was because of a failing test</em> that we wrote. So that we know that every single decision that we made <em>is tested</em>. So that then, we can pull up that code on our screen and say &lsquo;Oh my God, that looks like a mess&rsquo;—and <em>clean it!</em>…<strong>without any fear.</strong>&rdquo;</div></blockquote><p>Great talk. Add it to the pile of things that we know—or should know—better, but don&rsquo;t.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4827</guid>
    <title><![CDATA[Woefully unqualified "programmers"]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4827</link>
    <pubDate>Wed, 11 Oct 2023 21:15:00 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Oct 2023 21:15:00 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">6. Mar 2024 07:35:06 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>As I was reading the absolute train wreck of a unit test in <a href="https://thedailywtf.com/articles/testing-with-a-lisp">Testing with a Lisp</a> (<cite><a href="http://thedailywtf.com/">Daily WTF</a></cite>), the song &ldquo;What the fuck is going on?&rdquo; popped into my head, like it always does when I see that a programmer not only didn&rsquo;t understand the assignment, not only doesn&rsquo;t know how to program, but also doesn&rsquo;t know that they don&rsquo;t know how to program.</p>
<p>They are living their best life because they don&rsquo;t think that &ldquo;knowing how to program&rdquo; is required in order to be a programmer. Neither does their boss or team, I guess.</p>
<p>That&rsquo;s when the music starts to play in my head, and I think of little blind Dillon playing football because a very non-PC friend [1] sent me that video so many years ago.</p>
<p>Am I going to link the video? Of course I am. Because I&rsquo;m a terrible person. [2]</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/QhKI_ncKgm8" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=QhKI_ncKgm8">BLIND KID PLAYING FOOTBALL WHAT THE FUCK IS GOING ON</a> by <cite>RelentingPeach</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>And this is the test from the article above.</p>
<pre class=" "><code>test("Returned objects arguments immutable (a b)", function() {
  var result = lispParser("(a b)");
  expect(3);
  ok(typeof(result) === 'object', "result is an object");
  var children = result.arguments;
  var newValue = 2;
  var firstChild = children[0];
  if (children[0] == newValue) {
    firstChild = ++newValue;
  }
  notEqual(result.arguments[0], newValue, "Underlying array was immutable");
  equal(result.arguments[0], firstChild, "Underlying array was immutable");
});</code></pre><p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4827/highlight_anything_you_think_seems_stupid.png"><img src="https://www.earthli.com/data/news/attachments/entry/4827/highlight_anything_you_think_seems_stupid_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4827/highlight_anything_you_think_seems_stupid.png">Highlight anything you think seems stupid</a></span></span>Nothing about that test makes any sense. It will always pass. It is, in its own way, a work of art. It is the JavaScript equivalent of Chomsky&rsquo;s <a href="https://en.wikipedia.org/wiki/Colorless_green_ideas_sleep_furiously">Colorless green ideas sleep furiously</a> (<cite><a href="http://en.wikipedia.org/">Wikipedia</a></cite>), an example of a sentence that is <span class="quote-inline">&ldquo;grammatically well-formed, but semantically nonsensical&rdquo;</span>.</p>
<p>Honestly, this looks worse than anything I&rsquo;ve seen my students try to write. They usually have enough shame that they don&rsquo;t bother filling in an answer if they really have no idea what&rsquo;s going on.</p>
<p>I&rsquo;m also wondering, of course, whether this is the work of an AI—or the bastard child of a poseur-programmer and an AI. The future is bright.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4827_1_body" class="footnote-number">[1]</span> All kidding aside, I love this kid&rsquo;s confidence. It&rsquo;s off the charts. I hope karma was gentle with him.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4827_2_body" class="footnote-number">[2]</span> It was the same person who sent me the little cartoon I&rsquo;ve included.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4805</guid>
    <title><![CDATA[Technology-independent software-development courses]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4805</link>
    <pubDate>Thu, 05 Oct 2023 13:48:10 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">5. Oct 2023 13:48:10 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">10. Oct 2023 06:22:28 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I was recently asked something like the following question, which I am citing with a few minor edits.</p>
<blockquote class="quote quote-block "><div><p>We would like to do a course about SW development with Python, preferably an online course, so that we can start at our own pace.</p>
<p>We don’t want a Python course, but would instead like a course more about SW development. It would be great if it were in Python because we are comfortable with it.</p>
<p>The interesting topics would be:</p>
<ul>
<li>object-oriented programming</li>
<li>functional programming</li>
<li>design patterns</li>
<li>good coding practices</li></ul><p>As well as other important topics such as:</p>
<ul>
<li>Testing</li>
<li>Documenting</li>
<li>Version control</li>
<li>Working in a team with version control</li></ul><p>The course doesn’t have to contain all these topics. It can be also several courses or it can be toy-projects from somewhere.</p>
</div></blockquote><h2>Learning how to develop software</h2><p>I have very little familiarity with courses as I&rsquo;ve usually been tasked with figuring out how to do things before others have gotten to it. Of late, I&rsquo;ve been teaching courses, not taking them.</p>
<p>So, how did I learn what I know about software development? When I started writing software, there was nothing available online, outside of a bunch of GeoCities pages (one of which was mine). MSDN was on CDs or local help files.</p>
<p>I read some books, OOSC and OOSC2, as well as the Gang of Four&rsquo;s Design Patterns. I can&rsquo;t remember what else, but that&rsquo;s partly how I leveled up my skills. I had the great fortune of being able to build and work on large frameworks, from which I drew many lessons. I worked with very good people, who challenged me and taught me a lot.</p>
<p>Nowadays, I use DuckDuckGo as my online reference. I have developed a relatively advanced skill at searching for what I&rsquo;m looking for. I very often get it within minutes. I almost never use videos.</p>
<p>a primary skill in software development is to be able to imagine what you should be looking for. That is, you don&rsquo;t have to know how to do everything without looking it up, but you do have to imagine that it might exist.</p>
<p>For example, I don&rsquo;t know how to write automated tests in Python, but I know that it should be possible. I know that I should figure that out very early in my experiments with Python. I know what to expect from an automated-testing environment. I know which settings to look for and expect.</p>
<p>That kind of knowledge transfers from one language or development environment to another. I know that I code-completion makes me faster, I know that I would like to avoid runtime errors—how can I best use Python to achieve those ends?</p>
<h2>Online Courses</h2><p>I took a quick look around for online courses, but was not immediately convinced that I am equipped to be able to distinguish between scams and actually worthwhile courses. Does the course even mention general software-development principles? How much time is allocated to that?</p>
<h4>Udemy</h4><p>The <a href="https://www.udemy.com/course/learn-python-3-with-software-engineering-concepts/">Complete Software Engineering Course with Python</a> (<cite><a href="http://www.udemy.com/">Udemy</a></cite>) looks as follows:</p>
<p><span style="width: 734px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4805/udemy-software-course.png"><img src="https://www.earthli.com/data/news/attachments/entry/4805/udemy-software-course.png" alt=" " style="width: 734px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4805/udemy-software-course.png">Udemy Python Software Course</a></span></span></p>
<ul>
<li>Only about 1% of students even bothered to rate the course</li>
<li>The pricing fees high pressure and scammy</li>
<li>The course descriptions are barely in English</li></ul><p>What about general programming?</p>
<p><span style="width: 351px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4805/software-engineering.png"><img src="https://www.earthli.com/data/news/attachments/entry/4805/software-engineering.png" alt=" " style="width: 351px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4805/software-engineering.png">Udemy Software Engineering Lecture: 9.5 minutes</a></span></span></p>
<p>Just over nine minutes? And you can&rsquo;t even be bothered to describe it in something approaching well-written English? No, thanks.</p>
<h4>PluralSight</h4><p>The course <a href="https://www.pluralsight.com/courses/learning-programming-abstractions-python">Learning To Program − Part 2: Abstractions</a> (<cite><a href="http://www.pluralsight.com/">PluralSight</a></cite>) looks a bit more professional, but it still has some quirks (especially for $29 per month).</p>
<p><span style="width: 407px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4805/pluralsight_details.png"><img src="https://www.earthli.com/data/news/attachments/entry/4805/pluralsight_details.png" alt=" " style="width: 407px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4805/pluralsight_details.png">PluralSight Details</a></span></span></p>
<ul>
<li>Overall more professional than Udemy, but also seems to have been incompletely translated from French</li>
<li>Still, there&rsquo;s definitely more time dedicated to core concepts</li></ul><p>There is an <a href="https://www.pluralsight.com/redeemlink/genericV4?redemptionId=7a28c861-d736-41d3-842a-28a97d8e5714&amp;mac=368c7cca1cac8158bae0da91fa137b5d01891402f7f7119a10a6a8be938da98a">assessment</a> that you can take, but you have to sign up first.</p>
<p><span style="width: 221px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4805/pluralsight_assessment.png"><img src="https://www.earthli.com/data/news/attachments/entry/4805/pluralsight_assessment.png" alt=" " style="width: 221px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4805/pluralsight_assessment.png">PluralSight Assessment</a></span></span></p>
<p>Maybe PluralSight is able to tell you which courses you need, but I doubt it will err on the &ldquo;you need fewer courses&rdquo; side.</p>
<h2>Dometrain</h2><div class="caution ">Update on 2023-10-06: added the section below</div><p>I&rsquo;ve recently heard from a source I&rsquo;ve been watching for a while that this course is quite good for C# developers: <a href="https://dometrain.com/course/from-zero-to-hero-test-driven-development-tdd-csharp/">From Zero to Hero: Test-Driven Development in C#</a> by <cite>Guilherme Ferreira</cite>. The person recommending it releases quite interesting/advanced videos on YouTube and has <a href="https://dometrain.com/author/nick-chapsas/#my_workshops">his own range of courses at DomeTrain</a>.</p>
<h2>How should software-development be taught?</h2><p>How would I teach basic software-development principles? I would probably start with very abstract principles that try to answer the classic questions for &ldquo;use cases&rdquo;:</p>
<ul>
<li><strong>Requirements:</strong> What are you trying to achieve?</li>
<li><strong>Actors:</strong> Who is trying to achieve it?</li>
<li><strong>Stakeholders:</strong> Are there other points of view than just the actor&rsquo;s?</li></ul><h2>Which language?</h2><p>A question people tend to start with is: which programming language should I use?</p>
<p>That&rsquo;s the wrong question.</p>
<p>The applicability of programming languages to fields differ widely, but most languages have a large overlap in functionality. Where they differ is in the degree of runtime or library support for specific tasks.</p>
<p>For example, Python famously has a lot of libraries for number-crunching and data-analysis (although I feel that this advantage is grossly exaggerated) whereas it&rsquo;s terrible for writing Windows GUI applications. C#/.NET has excellent web and desktop technology support. The Python runtime is notoriously slow (with essential libraries written in C++) whereas .NET is known as a very performant cross-platform runtime.</p>
<p>Do you see how quickly the conversation turns from &ldquo;what can the language do?&rdquo; to &ldquo;what can the standard runtime/libraries/environment do?&rdquo; That&rsquo;s because you can do most tasks with most languages.</p>
<p>Instead, we want to think about this at a higher level. We want to,</p>
<ul>
<li><em>maximize useful</em> expressiveness while <em>minimizing harmful</em> expressiveness. </li>
<li>accommodate <em>inherent</em> complexity without introducing <em>accidental</em> complexity. </li>
<li>express our intent <em>explicitly</em> in our programs.</li>
<li>be able to <em>discover and eliminate assumptions</em></li>
<li>get compilation errors or warnings, <em>not runtime errors.</em></li></ul><h2>Developer discipline</h2><p>Programming languages exist on several spectra. One of these is &ldquo;the degree of developer discipline required to use the language effectively and safely.&rdquo;</p>
<p>What does that mean? For example, Python and JavaScript have a dynamic type system. While there are mechanisms, practices, and IDE support that you can use to set up guardrails missing in the language, but they are <em>optional</em> and Idiomatically written code in both of these languages tends not to use any of it. It&rsquo;s the wild west, for the most part, with a lot of assumptions that nothing will ever go wrong.</p>
<p>More strict languages force you to consider all possibilities before your program even compiles or runs. For example, Haskell and Rust are famously picky. If you have a function that returns a value under certain conditions, those languages will make you explicitly indicate what to return when those conditions don&rsquo;t hold. Forgiving languages will just use some default value, usually <code>null</code> or <code>undefined</code>.</p>
<p>This is called &ldquo;happy path&rdquo; programming because you only write the code for the hoped-for path through your use case. For example, the user selects a valid file with the expected data format with an acceptable length with no validation or processing errors, generating a data file to which the initiating user has access. </p>
<ul>
<li>Did the user click cancel? Not handled.</li>
<li>Was the file missing? Not handled.</li>
<li>Was the file in an unexpected encoding? Not handled.</li>
<li>Did the file fail to validate? Not handled.</li>
<li>Was the data empty? Not handled.</li>
<li>Did processing crash? Not handled.</li>
<li>Was the generated output not accessible to the user? Not handled.</li></ul><p>Writing programs in this fashion is a dangerous thing to do with a strict language, and it&rsquo;s even worse to do in a lax language.  </p>
<p>Even the simplest software has many, many branches. The less your language or compiler or IDE reminds you of them, the more you have to fill that gap with developer discipline.</p>
<h2>Important language/runtime/IDE features</h2><p>To get more concrete, some good questions to consider are:</p>
<ul>
<li>Can you clearly describe and use types? (implicitly typed ≥ explicitly typed ≥ dynamically typed)</li>
<li>Are types statically checked? (yes &gt; no)</li>
<li>Can you primarily work with early binding? E.g., how strongly idiomatic are virtual/late bindings?</li>
<li>Are data and operations idiomatically merged or separate? Is there support for pure data structures (e.g. records vs. classes)</li>
<li>What about discriminated unions? Range types? Can you avoid <em>primitive obsession</em>?</li>
<li>Can you declare non-nullable references?</li>
<li>Can you designate functions as pure?</li>
<li>Is a functional programming style supported?</li>
<li>Is there a way to make data or records immutable?</li>
<li>To what degree can you optimize performance where needed?</li>
<li>How does error-handling work?</li>
<li>How concise can you be? What kind of abstraction mechanisms are there? Do you have to write a lot of boilerplate?</li>
<li>How does I/O work? Is it a second-class citizen? (I.e., does the language enforce purity so hard that it make it a pain to read from a file? I&rsquo;m looking at you, Haskell and Elm)</li>
<li>What is the asynchronous programming model?</li>
<li>How good are the error messages?</li></ul><p>If these don&rsquo;t make any sense to you, don&rsquo;t worry. But they are questions that are important when you&rsquo;re choosing a tool for building software.</p>
<h2>Intent &amp; handling events</h2><p>The whole point of a programming language is to <em>express intent</em>. You indicate what you intend to happen when a given event occurs.</p>
<p>An programmer expresses an intent by writing that, &ldquo;when this thing happens, I <em>intend</em> for this other thing to happen.&rdquo;</p>
<p>For example,</p>
<ul>
<li>When a filename is provided on the command line, read the contents of the file in a given encoding, process it as lines of text, and save the results to another file.</li>
<li>When the user clicks the screen in a particular place when the program is in a particular state (e.g., over a button displayed in a dialog box), then execute an operation.</li>
<li>When an HTTP request arrives, then read the body, process it, and return an HTTP response with the results</li>
<li>When a sensor triggers an interrupt, then change a GUI readout from red to green</li>
<li>When the system sends a shutdown message, then close and flush all logs</li></ul><h2>Questions to consider</h2><p>How do we choose a programming language? You&rsquo;re not just choosing a programming language, you&rsquo;re also implicitly deciding which subset of language features to use. This is predicated, of course, on knowing about these features. It&rsquo;s best to inform yourself about what your language/libraries/runtime (let&rsquo;s call it a <em>software-development tool</em>) can do for you—or find someone who is well-informed to help.</p>
<p>For each feature, you should ask yourself: how useful is it? Does it help me achieve my task?</p>
<p>Let&rsquo;s take a look at high-level features of a software-development tool that may be important.</p>
<dl><dt class="field">Maintainability</dt>
<dd><ul>
<li>By whom? What level of programmer?</li>
<li>How much will a certain part need to change?</li></ul></dd>
<dt class="field">Comprehensibility</dt>
<dd><ul>
<li>By whom? What level of programmer?</li>
<li>Are you applying the &ldquo;rule of least power&rdquo;? That is, are you using the simplest, most effective tool in your arsenal? To know this, you have to expand your arsenal … and then use it judiciously</li>
<li>Low syntax noise</li></ul></dd>
<dt class="field">Discoverability</dt>
<dd><ul>
<li>Can you use the IDE and code-completion to learn the API?</li>
<li>How much documentation do you need?</li>
<li>How much on-boarding would a new developer need?</li>
<li>How easy would it be to hand off to another person or team?</li></ul></dd>
<dt class="field">Learnability</dt>
<dd><ul>
<li>Even if not especially discoverable, how learnable is the code?</li>
<li>Are the patterns consistent?</li>
<li>Is the API clear?</li></ul></dd>
<dt class="field">Strictness / Correctness</dt>
<dd>Error-free is strongly encouraged or enforced</dd>
<dt class="field">Complexity</dt>
<dd>Inherent vs. Accidental</dd>
<dt class="field">Idiomatic</dt>
<dd>Is it written in a way that other programmers of this language or framework can easily understand?</dd>
<dt class="field">Testability</dt>
<dd><ul>
<li>Can you write semantically useful tests?</li>
<li>Is it easier to write a test than to debug?</li></ul></dd>
<dt class="field">Debuggability</dt>
<dd><ul>
<li>Can your debugger set a breakpoint on all of the important bits?</li>
<li>Can you even debug it? </li>
<li>Is there too much magic?</li>
<li>Is there so much generalization that you can&rsquo;t figure out what&rsquo;s going on?</li></ul></dd>
<dt class="field">Observability</dt>
<dd><ul>
<li>Is there sufficient logging to figure out what&rsquo;s going on without debugging? (This is important once the product is in the field.)</li>
<li>What about error-handling? Are <em>problems</em> separated from <em>errors</em>? [1]</li>
<li>Can the developer predict what&rsquo;s happening and measure it?</li>
<li>How&rsquo;s your telemetry?</li>
<li>Could the software be monitored if needed?</li></ul></dd>
<dt class="field">Performance</dt>
<dd><ul>
<li>Does it need to be fast?</li>
<li>All of it? Or just parts?</li></ul></dd>
</dl><p>For code designed to be reusable (libraries, frameworks), you can also consider:</p>
<dl><dt class="field">Completeness</dt>
<dd>degree to which the definition/API captures all facets of the problem domain</dd>
<dt class="field">Expressiveness</dt>
<dd>Concise and precise</dd>
<dt class="field">Flexibility</dt>
<dd>Applicability to different problem domains</dd>
</dl><p>Which of the features above matters more depends on what you&rsquo;re building. A one-off script doesn&rsquo;t need to satisfy many of these features. A full-blown application that needs to be maintained for 10-20 years by different teams has to be much, much more careful.</p>
<h2>Other articles</h2><p>This isn&rsquo;t the first time I&rsquo;ve written about these ideas, so I&rsquo;ve included links to other, similar articles below.</p>
<h4>General Programming Practices</h4><p>These articles discuss the topic of software-development on a similar level to the discussion above.</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=2154">Elegant Code vs.(?) Clean Code</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3356">Programming-language Features: How much is too much?</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4552">Applying the rule of least power in practice</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3856">Framework Design: Programming Paradigms and Idioms</a></li></ul><p>The articles below are more recent, are more-or-less on the same level, but are also more targeted.</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=4622">How to evaluate dependencies</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4556">To crash or not to crash; that is the question</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4657">Stop trying so hard to use pattern-matching</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4790">The UI is an afterthought, a detail</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4771">On the usefulness of containers like Docker</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4372">The “Hustle” culture in Software Development</a></li></ul><h2><a href="https://www.earthli.com/news/view_article.php?id=4430">Encodo White papers archive</a></h2><p>These white papers were written from 2006 to 2019 when I was still employed at <a href="https://encodo.ch">Encodo Systems AG</a>. They expand on recommended practices of specific facets of software development. They are presented in reverse-chronological order, but can be read in any order.</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=4436">DI, IOC and Containers</a> (2019)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4435">Clean and Safe Code</a> (2019)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4434">Testing as First-Class Citizen</a> (2019)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4433">Code Reviews</a> (2017)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4432">Document Everything</a> (2017)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4431">Continuous Integration and Delivery</a> (2017)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4429">Component-based Design</a> (2006)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4428">Design by Contract</a> (2006)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=4427">Test-driven Development</a> (2006)</li></ul><h2>Videos</h2><p>This is a YouTube playlist I&rsquo;ve maintained for years that I continuously update whenever I watch a video that I think would be interesting for other developers. It&rsquo;s only technology videos, but it&rsquo;s pretty eclectic (i.e., it&rsquo;s language- and technology-agnostic).</p>
<p><a href="https://www.youtube.com/playlist?list=PLaAuYwHbW13oWFVJBDlOPPThpizvkyGOo">Developer suggestions</a> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</p>
<h2>Conclusion</h2><p>Pace yourself. You can&rsquo;t have everything all at once. Programming takes wisdom. Wisdom takes time. It takes practice. It comes, or it doesn&rsquo;t. It takes different forms.</p>
<p>As <a href="https://www.rilke.de/briefe/160703.htm">Rainer Maria Rilke wrote in 1903</a> [2],</p>
<blockquote class="quote quote-block "><div>&ldquo;Forschen Sie jetzt nicht nach den Antworten, die Ihnen nicht gegeben werden können, weil Sie sie nicht leben könnten. Und es handelt sich darum, alles zu leben. Leben Sie jetzt die Fragen. Vielleicht leben Sie dann allmählich, ohne es zu merken, eines fernen Tages in die Antwort hinein.&rdquo;</div></blockquote><p>Good luck.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4805_1_body" class="footnote-number">[1]</span> See <a href="https://joeduffyblog.com/2016/02/07/the-error-model/">The Error Model</a> by <cite>Joe Duffy</cite>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4805_2_body" class="footnote-number">[2]</span> h/t to Ömer for making me aware of this great piece of writing.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4556</guid>
    <title><![CDATA[To crash or not to crash; that is the question]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4556</link>
    <pubDate>Wed, 04 Oct 2023 21:54:06 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:54:06 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">Note: I found this old draft containing my response to a colleague.</small></p>
<p>I 100% agree with you, in general. I absolutely want to know immediately when an assumption I&rsquo;ve made does not hold.</p>
<p>But…😁</p>
<p>The degree to which I&rsquo;m willing to crash depends on whose consistency I&rsquo;m basing my assumptions on. When I call a method in my code from another method in my code, I&rsquo;m absolutely going to assert that an argument is not null. I can control that. My IDE will tell me when I might be passing <code>null</code>. That is definitely a programming error.</p>
<p>When I&rsquo;m getting external input (e.g. from the Windows registry), I&rsquo;m a bit more cautious because I&rsquo;m less sure about how solid my assumption is. I know what the documentation <em>says</em> but a lifetime of programming has taught me that some things (like the Windows registry) are going to work exactly as expected on my (modern) developer machine, but are going to fail mysteriously on a (perhaps less modern) machine in (for me) completely unpredictable ways.</p>
<p>Therefore, I&rsquo;m a bit careful about is what I&rsquo;m willing to pay to find errors. The primary purpose of a program is to bring value to the customer/user.  I want to improve my program for more situations, but how am I going to find out in which situations it doesn&rsquo;t work?</p>
<p>I can test, of course, but some things will only ever happen in the field. If it happens in the field, then I&rsquo;m using the customer&rsquo;s/user&rsquo;s time to help me fix my program (they benefit, of course, but not for free). Can I soften the blow to the user of having to help me improve the program <em>without sacrificing consistency or accuracy?</em></p>
<p>Sometimes, the answer is a resounding <em>no</em>. The program absolutely cannot continue if e.g., the reference to the data it needs to work on is <code>null</code>. That&rsquo;s a no-go. There&rsquo;s no rescuing the program from that or completing any other useful work.</p>
<p>In the case of this tool, if it crashes, the user no longer gets a report. Would they have been able to get <em>some</em> of the report if it hadn&rsquo;t crashed? In this case, yes. All of the other checks could be run. The checks that crashed would show as &ldquo;failed&rdquo; with the exception message. That seems to me to be better than skipping all subsequent checks when one crashes.</p>
<p>I can even continue to hope that the user then reports the mysterious error message they got for one of the reports! <em>Die Hoffnung stirbt zuletzt!</em></p>
<p>I&rsquo;m delighted to discuss programming and error-handling philosophy in person next week!</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4430</guid>
    <title><![CDATA[Encodo White Papers Archive]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4430</link>
    <pubDate>Wed, 04 Oct 2023 21:36:27 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:36:27 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">This article is a copy of the white papers and process description that I wrote for Encodo Systems while I still worked there. I&rsquo;ve preserved a copy of it here and in the linked articles.</small></p>
<p>Through our many years of experience building software, we&rsquo;ve accumulated methodologies and principles that lead to quality software.</p>
<ul>
<li>The experience and know-how we bring to our consulting services also make us excellent partners in development-process consulting.</li>
<li>We have experience in reviewing existing software and proposing changes to improve its reliability and stability.</li>
<li>Not only can we build great software for you, we can help your development teams improve their current software and teach them how to write better software in the future.</li></ul><p>Listed below are our methodologies.</p>
<dl><dt><a href="https://www.earthli.com/news/view_article.php?id=4436">DI, IOC and Containers</a> (2019)</dt>
<dd>Applications are graphs of components, each with dependencies and inputs and outputs. DI and IOC are a simple and powerful way of building testable, flexible and easily replaced components.</dd>
<dt><a href="https://www.earthli.com/news/view_article.php?id=4435">Clean and Safe Code</a> (2019)</dt>
<dd>A large part of writing good, clean code is to <em>restrict</em> your options. Avoid nullable data. Avoid mutable data. Avoid state. Code is not a poem: it&rsquo;s actually preferable if it all looks the same and seems &ldquo;easy&rdquo; and &ldquo;obvious&rdquo;.</dd>
<dt><a href="https://www.earthli.com/news/view_article.php?id=4434">Testing as First-Class Citizen</a> (2019)</dt>
<dd>Use tests to execute your code. Automate them to guard against future changes. Make testing easy for developers by building nice integration suites. Tests are <em>code</em>.</dd>
<dt><a href="https://www.earthli.com/news/view_article.php?id=4433">Code Reviews</a> (2017)</dt>
<dd>Finished code is reviewed before it is committed. Reviews make sure that the other parts of the design process were followed (documentation, tests, etc.) and that errors are fixed as quickly as possible.</dd>
<dt><a href="https://www.earthli.com/news/view_article.php?id=4432">Document Everything</a> (2017)</dt>
<dd>Software without documentation is not maintainable. Good naming conventions, logical designs and well-built tests help make code self-documenting. High-level tutorials explain how the different components are intended to work together.</dd>
<dt><a href="https://www.earthli.com/news/view_article.php?id=4431">Continuous Integration and Delivery</a> (2017)</dt>
<dd>Low-overhead releases lead to faster turnaround and higher quality. Automated (or nightly) builds pinpoint software errors before they can become problems.</dd>
<dt><a href="https://www.earthli.com/news/view_article.php?id=4429">Component-based Design</a> (2006)</dt>
<dd>Components encapsulate specifications. Software is designed to balance reuse and abstraction against the project goals, all the while optimizing maintainability.</dd>
<dt><a href="https://www.earthli.com/news/view_article.php?id=4428">Design by Contract</a> (2006)</dt>
<dd>The specifications are built right into the code. Software publishes its assumptions instead of leaving its contract implicit.</dd>
<dt><a href="https://www.earthli.com/news/view_article.php?id=4427">Test-driven Development</a> (2006)</dt>
<dd>Tests are a central part of building software. All component features have application-independent tests which can be run automatically and throughout development.</dd>
</dl>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4436</guid>
    <title><![CDATA[Encodo White Papers: DI, IOC and Containers (2019)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4436</link>
    <pubDate>Wed, 04 Oct 2023 21:36:20 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:36:20 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Apr 2025 12:59:29 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Encodo keeps the <a href="https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)">SOLID</a> principles in mind when designing software.</p>
<h2>DI &amp; IOC</h2><p>We implement the Inversion of Control (I) pattern with the dependency-injection pattern (D) to allow for a large amount of flexibility in how an application is composed. We&rsquo;ve applied this principle throughout the Quino framework and use it in our products as well.</p>
<p>What does this mean? It means that the product or framework doesn&rsquo;t make any decisions about which <em>exact</em> components to use. Instead, it indicates the API Surface (interface) that it expects in the form of injected components. That is, the responsibility for deciding which component to use lies not with the <em>lowest level</em> of the software stack, but with the <em>highest level</em>.</p>
<p>This inversion means that the application entry point configures the object graph (i.e. which objects will be used). That makes it much easier to isolate and test individual components, especially where those components would depend on native- or web-only functionality in production.</p>
<p>See the <a href="https://www.earthli.com/users/marco/docs/documents/encodo/Presentations/2018-02-19-tech-talk-master/index.html">How do I DI?</a> presentation from February 2018 for more information.</p>
<h2>Principles</h2><p>In order to make good use of this pattern, an application should adhere to the following rules:</p>
<ul>
<li>Prefers <em>composition</em> over inheritance, exposing <em>clear dependencies</em>.</li>
<li>Refers to dependencies via <em>interface</em> or protocol types with as small a <em>surface area</em> as possible.</li>
<li>Obtains dependencies through <em>injection</em>, preferably via the constructor.</li></ul><p>Components built in this manner are agnostic in their implementation. They can be composed by an application as it sees fit.</p>
<h2>Components</h2><p>An application is a graph of components, each with one responsibility (S) and zero or more dependencies, injected via the constructor. Components are composed with other components to build higher-level functionality (O). They are also unaware of the other components&rsquo; implementations and can be replaced with other implementations (L).</p>
<p>Components make software flexible:</p>
<ul>
<li>Products can <em>replace</em> any component without changing anything else</li>
<li>Products can <em>inject</em> any component without pulling in more functionality than needed</li></ul><h2>Declaration &amp; Implementation</h2><p>Components have a very clear purpose (S) indicated through an <em>interface</em>. In most cases, we use an actual &ldquo;interface&rdquo; language construct to clearly define the API surface and to not limit a product in its implementation (e.g. with an abstract base class).</p>
<ul>
<li>Prefer <em>composition</em> to inheritance, exposing clear <em>dependencies</em></li>
<li>Reference dependencies via <em>interface</em> (or type or protocol, depending on language) with as small a <em>surface area</em> as possible</li>
<li>Obtain dependencies through <em>injection</em>, preferably in the constructor</li></ul><p>Most components have a single method, amounting to a functional interface and allowing composition with lambdas. While TypeScript has this feature (as does Java), C# does not. We end up defining a lot of single-method classes that implement a single interface. It&rsquo;s more code than we&rsquo;d like, but it&rsquo;s purely structural syntax and doesn&rsquo;t introduce additional complexity.</p>
<p>See the <a href="https://docs.encodo.ch/quino/master/docs/architecture/interfaces_and_implementations.html">Interfaces, base classes and virtual methods</a> in the Quino conceptual documentation for more information and on and examples of patterns that we use.</p>
<h2>Containers</h2><p>Although it&rsquo;s possible for applications to manually create an object graph (the composition root), we prefer to use an IOC Container.</p>
<p>The container provides two services:</p>
<ul>
<li><strong>Registration:</strong> Applications declare the object or type and the lifetime (generally singleton) to use for interfaces</li>
<li><strong>Requests:</strong> Applications request objects, which the IOC creates—injecting other registered objects, as necessary—or retrieves, depending on lifetime. A container can create transient objects even for unregistered types.</li></ul><p>The container introduces the following restriction:</p>
<ul>
<li>A concrete type may have many constructors, but only one may be public</li></ul><p>The lifetime of an application is as follows:</p>
<ul>
<li>Collect registrations in the IOC Container</li>
<li>Create composition root with the IOC Container</li>
<li>Apply method to composition root</li></ul><p>See the <a href="https://docs.encodo.ch/quino/master/docs/architecture/application.html">Quino Application Configuration</a> for more information about application lifecycle. The blog article <a href="https://encodo.com/latest/developer-blogs/quino-2-starting-up-an-application-in-detail/">Starting up an application, in detail</a> is a bit older, but provides more detail on how Quino integrates the IOC into the startup.</p>
<p>In the long example below, we will first look at how composition even without a container is very powerful. Then we&rsquo;ll look at how a container can improve on that.</p>
<h2>Example</h2><p>Although we generally use C# or TypeScript in our work, these examples were originally written to introduce Swift developers to an iOS framework that we wrote.</p>
<p>We will first look at how composition even without a container is very powerful. Then we&rsquo;ll look at how a container can improve on that.</p>
<h3>Step One: A limited robot simulator</h3><p>Let&rsquo;s take a look at an example of an application that looks OK at first, but turns out not to be very flexible.</p>
<p>Note: The example is small, so some of the steps will feel like over-engineering. It&rsquo;s a good point, but the principles shown here apply just as well for larger systems.</p>
<p>The following example defines a simulator that can move a robot along a route, defined by movements. The robot starts at a given location and can travel at a fixed speed.</p>
<pre class=" "><code>enum Direction
{
  case north
  case south
  case east
  case west
}

struct Movement
{
  let direction: Direction
  let distance: Int
}

struct Point
{
  var x: Int
  var y: Int
}

class FastRobot
{
  var speed = 2
  var location: Point = Point(x: 0, y: 0)
  let movements: [Movement] = [Movement(direction: .north, distance: 1)]

  func move()
  {
    for movement in movements
    {
      let distance = speed * movement.distance
      switch (movement.direction)
      {
      case .north:
        location.y += distance
      case .south:
        location.y -= distance
      case .east:
        location.x += distance
      case .west:
        location.x -= distance
      }
    }
  }
}

class Simulator
{
  func run()
  {
    FastRobot().move()
  }
}</code></pre><p>As mentioned above, this implementation looks well-written, but what if we wanted to verify that the robot ended up at the right location? Let&rsquo;s try that below.</p>
<h3>Step Two: Running the limited robot</h3><pre class=" "><code>Simulator().run()

// Now what?</code></pre><p>It turns out that we can&rsquo;t test anything in this application. We can fix this by applying the patterns outlined in the first section.</p>
<h3>Step Three: Decouple the robot from the simulator</h3><p>First, let&rsquo;s tackle the Simulator interface:</p>
<pre class=" "><code>class Simulator
{
  func run(robot: FastRobot)
  {
    robot.move()
  }
}

let robot = FastRobot()
Simulator().run(robot: robot)

XCTAssertEqual(robot.location.x, 0)
XCTAssertEqual(robot.location.y, 2)</code></pre><p>Now we can test that the robot is working as expected.</p>
<p>The robot is still quite hard-coded, as is the simulator&rsquo;s relationship to the robot. The robot must be a <code>FastRobot</code> and it can only move along a fixed route.</p>
<h3>Step Four: Reduce the robot &ldquo;surface&rdquo;</h3><p>We&rsquo;ll first decouple the Simulator from a direct dependence on the FastRobot.</p>
<pre class=" "><code>protocol IRobot
{
  func move()
}

class Robot : IRobot
{
  // As above
}

class Simulator
{
  func run(robot: IRobot)
  {
    robot.move()
  }
}</code></pre><p>Now the simulator only knows about the protocol <code>IRobot</code>, which has a very small surface area. It&rsquo;s still too small to be very useful.</p>
<h3>Step Five: Make the robot configurable</h3><p>Instead of hard-coding everything, we can compose the robot out of parts. Examining the algorithm, we see three parts that could be externalized:</p>
<ul>
<li>The robot&rsquo;s <em>speed</em> is currently fixed. We could make a component that is responsible for calculating the speed of the robot.</li>
<li>The robot&rsquo;s <em>route</em> is also fixed. We could make a component to represent the route as well.</li>
<li>Finally, the robot&rsquo;s <em>initial position</em> is also fixed. We could make that configurable as well.</li></ul><p>Let&rsquo;s first externalize all of the hard-coded values out of the <code>FastRobot</code> into a generic <code>Robot</code> class.</p>
<pre class=" "><code>class Robot : IRobot
{
  let speed: Int
  var location: Point
  let movements: [Movement]

  init(speed: Int, location: Point, movements: [Movement])
  {
    self.speed = speed
    self.location = location
    self.movements = movements
  }

  func move()
  {
    for movement in movements
    {
      let distance = speed * movement.distance
      switch (movement.direction)
      {
      case .north:
        location.y += distance
      case .south:
        location.y -= distance
      case .east:
        location.x += distance
      case .west:
        location.x -= distance
      }
    }
  }
}</code></pre><p>Now we can create a <code>Robot</code>, injecting all of the initial conditions.</p>
<pre class=" "><code>let origin = Point(x: 0, y: 0)
let route = [Movement(direction: .north, distance: 1)]
let robot = Robot(speed: 2, location: origin, movements: route)

Simulator().run(robot: robot)

XCTAssertEqual(robot.location.x, 0)
XCTAssertEqual(robot.location.y, 2)</code></pre><p>The same assertions hold as before, but the <code>Robot</code> class is much more generalized. We can now test the robot&rsquo;s movement algorithm with various combinations of origin, speed and route.</p>
<p>At this point, we&rsquo;ve made the robot and simulator composable and testable. Now we want to have a look at how we can separate the configuration from the usage.</p>
<h3>Using a container to build objects</h3><p>We&rsquo;re not nearly done, though. What does this all have to do with a service provider? That&rsquo;s where the <em>inversion</em> part comes in.</p>
<p>In the very first example, the <code>Simulator</code> was responsible for creating the robot. This made it impossible to test whether the robot did what it was supposed to do.</p>
<p>So we passed the robot in as a parameter to <code>run()</code>, making the caller responsible for creating the robot instead of the <code>Simulator</code>.</p>
<p>This is fine, as long as the caller is the top-level part of the program, responsible for <em>composing</em> the objects that will be used. However, what if the direct caller doesn&rsquo;t know how to do that? Or, put another way, what if the caller <em>should not</em> be doing that?</p>
<p>What if the caller is a button handler in a UI? Would we want the button handler—or the UI that contains it—to be responsible for constructing the robot or its initial conditions?</p>
<p>This is where the container comes in: we want to register all of the types and instances that we want to use in one place. This configuration can be retrieved at any later point without knowing any more than the interface that&rsquo;s required.</p>
<p>This takes us full circle to the original code, except, instead of creating the <code>Simulator</code> directly, we want to get it from a container, called a <code>provider</code> in the following examples.</p>
<pre class=" "><code>let simulator = provider.resolve(ISimulator.self)

simulator.run()

let robot = provider.resolve(IRobot.self)

XCTAssertEqual(robot.location.x, 0)
XCTAssertEqual(robot.location.y, 2)</code></pre><p><small class="notes">Note: For reasons of simplicity, we assume that all objects in the container are singletons.</small></p>
<h3><span id="step_6">Step Six</span>: Configure the container</h3><p>Let&rsquo;s take the configurable code above and translate it to a container. Here the <code>registrar</code> is the configurable part and the <code>provider</code> is the part that can be used to retrieve objects based on that configuration. The <code>registrar</code> is sometimes called the composition root.</p>
<p><small class="notes">Note: We use the syntax for the Swift IOC, but the examples are hopefully clear enough in their intent.</small></p>
<p>In the example below, we register singletons for each of the objects we want the container to be able to create, <code>Point</code>, <code>Int</code>, <code>[Movement]</code>, <code>IRobot</code> and <code>Simulator</code>.</p>
<pre class=" "><code>let registrar = ServiceRegistrar()
  .registerSingle(Int.class) { _ in 2 }
  .registerSingle(Point.class) { _ in Point(x: 0, y: 0) }
  .registerSingle([Movement].class) { _ in [Movement(direction: .north, distance: 1)] }
  .registerSingle(IRobot.class) { p in Robot(
    speed: p.resolve(Int.class), 
    location: p.resolve(Point.class),
    movements: p.resolve([Movement].class)
  )}
  .registerSingle(Simulator.class) {p in Simulator(p.resolve(IRobot.class))}</code></pre><p>This is a decent start, but many of the registrations above have no semantic meaning, like <code>Int</code> and <code>Point</code> and <code>[Movement]</code>. For these, it&rsquo;s better to use higher-level abstractions.</p>
<h3>Step Seven: using higher-level abstractions</h3><p>We need to define three abstractions—called <code>IOrigin</code>, <code>IRoute</code> and <code>IEngine</code>—with implementations. The <code>IRobot</code> interface also needs to be redesigned to use them.</p>
<pre class=" "><code>protocol IRoute
{
  var movements: [Movement] { get }
}

protocol IOrigin
{
  var point: Point { get }
}

protocol IEngine
{
  var speed: Int { get }
}

protocol ISimulator
{
  func run()
}

class Simulator : ISimulator
{
  var robot: IRobot

  init (_ robot: IRobot)
  {
    self.robot = robot
  }

  func run()
  {
    robot.move()
  }
}

struct StandardRoute : IRoute
{
  var movements: [Movement] = [Movement(direction: .north, distance: 1)]
}

struct StandardOrigin: IOrigin
{
  var point: Point = Point(x: 0, y: 0)
}

struct FastEngine : IEngine
{
  var speed: Int = 2
}

class Robot : IRobot
{
  var location: Point!
  let engine: IEngine
  let route: IRoute

  init(_ engine: IEngine, _ origin: IOrigin, _ route: IRoute)
  {
    self.engine = engine
    self.route = route

    location = origin.point
  }

  func move()
  {
    for movement in route.movements
    {
      let distance = engine.speed * movement.distance
      switch (movement.direction)
      {
      case .north:
        location.y += distance
      case .south:
        location.y -= distance
      case .east:
        location.x += distance
      case .west:
        location.x -= distance
      }
    }
  }
}</code></pre><p>We&rsquo;ve created concrete objects for our standard parameters. An added bonus of the improved semantics is that we can rewrite the <code>init</code> for <code>IRobot</code> so that it no longer expects argument labels—because the parameter are now clear without further explanation.</p>
<p>Now we can take another crack at the configuration using these new types. This time, we&rsquo;ll define an <code>extension</code> of the <code>IServiceRegistrar</code> that we can use again below.</p>
<pre class=" "><code>extension IServiceRegistrar
{
  func useSimulator() -&gt; IServiceRegistrar
  {
    return self
      .registerSingle(IEngine.class) { _ in FastEngine() }
      .registerSingle(IOrigin.class) { _ in StandardOrigin() }
      .registerSingle(IRoute.class) { _ in StandardRoute() }
      .registerSingle(IRobot.class) { p in Robot(
        p.resolve(IEngine.class), 
        p.resolve(IOrigin.class), 
        p.resolve(IRoute.class)
      )}
      .registerSingle(ISimulator.class) {p in Simulator(p.resolve(IRobot.class))}
  }
}</code></pre><p>We&rsquo;ve now configured a system that knows how to create our simulator along with all of its dependencies. You can see that if the <code>ISimulator</code> type is resolved from the container, it will,</p>
<ol>
<li>create a <code>Simulator</code>, which</li>
<li>resolves the <code>IRobot</code>, which</li>
<li>resolves the <code>IEngine</code>, <code>IOrigin</code> and <code>IRoute</code></li></ol><h3>Step Eight: Changing the speed</h3><p>An application can now change the speed of the robot without knowing anything else about the simulator, simply by changing the <code>IEngine</code> that&rsquo;s used.</p>
<pre class=" "><code>class SlowEngine : IEngine
{
  var speed: Int = 1
}

let provider = ServiceRegistrar()
  .useSimulator()
  .registerSingle(IEngine.class) { _ in SlowEngine() }
  .commit()</code></pre><p>As well, any location in the application can either use the <code>IRobot</code> or the <code>ISimulator</code> without having to know anything about how either of the concrete objects are constructed. The simulator might be much more complicated than the very simple one defined above. The robot might do much more when asked to move.</p>
<h3>Step Nine: Using a factory</h3><p>What if we wanted to let the robot decide how fast it is, depending on what kind of robot it is? Or what if we want to separate the speed from being fixed in the <code>IEngine</code>?</p>
<p>What we need is a way to create transient objects that require parameters that are not available in the provider. These are types like <code>Int</code>, <code>String</code>, etc., as we had in <a href="#step_6">Step Six</a> above.</p>
<p>The example below shows a very simple usage of the factory pattern. Instead of having a single <code>IEngine</code> for the whole application, we want to provide settings that the robot uses to get its engine.</p>
<p>The code below sketches the new types and shows how the robot would use them.</p>
<pre class=" "><code>protocol IEngineFactory
{
  func createEngine(speed: Int)
}

protocol IRobotSettings
{
  var speed: Int
}

class Robot : IRobot
{
  init(_ engineFactory: IEngineFactory, _ settings: IRobotSettings, _ origin: IOrigin, _ route: IRoute)
  {
    self.engine = _engineFactory.createEngine(settings.speed)

    // …
  }
}</code></pre><p>You&rsquo;ll note that we didn&rsquo;t declare any new properties. The robot still just has an engine, but asks the factory to create it based on a speed, rather than having the provider inject its singleton.</p>
<p>The robot&rsquo;s speed can now be configured without replacing the entire implementation.</p>
<pre class=" "><code>let settings = provider.resolve(IRobotSettings.self)

settings.speed = 10;

let simulator = provider.resolve(ISimulator.self)

simulator.run()

let robot = provider.resolve(IRobot.self)

XCTAssertEqual(robot.location.x, 0)
XCTAssertEqual(robot.location.y, 10)</code></pre>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4435</guid>
    <title><![CDATA[Encodo White Papers: Clean and Safe Code (2019)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4435</link>
    <pubDate>Wed, 04 Oct 2023 21:36:13 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:36:13 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>These are the two core principles that guide how we write code:</p>
<ul>
<li><strong>KISS:</strong> Keep It Simple, Stupid</li>
<li><strong>YAGNI:</strong> You Ain&rsquo;t Gonna Need It</li></ul><h2>KISS</h2><p>This first principle is a constant reminder to ourselves to avoid the seductive call of cleverness. Most code does not need to be clever. Very occasionally, it is necessary to implement something with real flair, that requires explanation.</p>
<p>The best code, though, requires no explanation. The best code gets its job done in a very boring way, using the same patterns to achieve different ends. The best code is instantly recognizable to those who know the patterns. The best code doesn&rsquo;t raise any questions. The best code doesn&rsquo;t need comments. The best code is obvious and, yet, does amazing things—like fulfill requirements in a stable, predictable, testable, customizable and high-performance manner.</p>
<p>It&rsquo;s kind of obvious: The lower the complexity, the easier it is to reason about systems. The easier it is to reason about a system, the easier it is to <em>prove</em> that either certain things can&rsquo;t happen or will always happen. It should be obvious where to add a customization—because there&rsquo;s only one place that it could logically go. It should be obvious where a bug lies—because there&rsquo;s only one place it could have originated.</p>
<p>The best code is readable and understandable not only by the original programmer, but also by another programmer—even if that&rsquo;s the original programmer, six months later.</p>
<h2>YAGNI</h2><p>We&rsquo;d be lying if we said that we <em>never</em> write code that we don&rsquo;t need, but we keep this principle in mind whenever we build code. There&rsquo;s a bit more wiggle room when building <em>frameworks</em> vs. <em>products</em>. It&rsquo;s easier to determine whether a feature is appropriate for a product than to do the same for a framework. Who knows how a framework might be used?</p>
<p>Encodo does have a framework named Quino. The point of a framework is to support the development of products that use it. It&rsquo;s not easy to predict what those products might need, even when you&rsquo;re focused only on features that your framework is supposed to provide. However, a framework or library has a purpose and it shouldn&rsquo;t stray from it.</p>
<p>Just as an example: Does Quino provide a remote data driver? Yes, because products have used it and the feature fits into the strategy of metadata-supported data. Is there an XML transport protocol? No, because no-one needed it. Do we support any kind of object? Not out of the box, we don&rsquo;t. You can register your own converters, but it&rsquo;s not a generalized protocol.</p>
<p>At the very least, we stay away from throwing in everything but the kitchen sink—just in case a product that uses Quino might need it. Be prepared for anything, but build only what you need.</p>
<h2>Other Principles</h2><p>We apply the following principles to avoid unneeded complexity.</p>
<ul>
<li>Separate state from logic</li>
<li>Use immutable data</li>
<li>Use non-nullable references</li>
<li>Avoid side-effects</li>
<li>Compose functional components</li>
<li>Use singletons</li></ul><h3>Separate state from logic</h3><p>From the article <a href="http://www.cs.otago.ac.nz/staffpriv/ok/Joe-Hates-OO.htm">Why OO Sucks</a> by <em>Joe Armstrong</em> (inventor of Erlang).</p>
<blockquote class="quote quote-block "><div>&ldquo;State is the root of all evil. In particular, functions with side effects should be avoided.&rdquo;</div></blockquote><p>The sentiment in the title is a bit strong, but its not unfair. OO programming mixes data with operations, leading to more complexity than required by the task.</p>
<p>Most applications need <em>some</em> state. That state should be isolated from most components. State should be stored in dumb objects and passed around.</p>
<p>A component without state is purely functional, drastically simplifying the things that could possibly happen to it. Its output is completely determined by its inputs. It does not introduce any threading issues beyond those inherent in its input.</p>
<h3>Use immutable data</h3><p>A component avoids a whole class of issues if it cannot make changes to the data that flows through it. As with state, restrict mutability to only certain components.</p>
<p>For example, transient objects like DTOs or ORM objects are mutable because it makes the program logic much more understandable</p>
<p>Another example is stateless singletons with configuration settings. instead of using a single component with mutable properties, define the configuration in a settings component. This has several advantages:</p>
<ul>
<li>The settings is a dumb &ldquo;state&rdquo; object (single responsibility)</li>
<li>The service is a stateless singleton (single responsibility)</li>
<li>A product can replace the service independently of the settings (and vice versa)</li>
<li>Service implementations don&rsquo;t repeat boilerplate code to manage properties</li></ul><h3>Use non-nullable references</h3><p>If references are guaranteed to be non-null, whole swaths of checking code fall away and make the component much simpler. As with immutability, there are far fewer possibilities of what can happen to non-nullable code.</p>
<p>TypeScript supports a null-checking mode. C# supports one as well, starting with C#8. For older versions of C#, use the JetBrains Annotations along with ReSharper to enable real-time/compile-time null-checking.</p>
<h3>Avoid side-effects</h3><p>A method should either change state or it should return data. This is the idea behind CQRS (Command-Query-Separation Principle). That said, we employ a weaker version where only visible state really counts.</p>
<p>Techniques like lazy-initialization and caching retrieved data are generally OK. Technically, those behaviors have non-visible state in the sense that they affect performance, but are still OK if used carefully.</p>
<h3>Compose functional components</h3><p>We use C# and TypeScript—wonderful OO languages with strong functional support—but we&rsquo;re using less and less of what OO has to offer.</p>
<p>Virtual methods are a code smell. Instead, use smaller, testable components with a single purpose. If it&rsquo;s easier to test, it&rsquo;s easier to replace where necessary. Smaller components are more focused and easier to replace without duplicating code.</p>
<p>If logic is separated from data, and services are injected or passed as parameters, then there is less and less need for base classes with many helper functions or virtual/protected methods.</p>
<h3>Use singletons</h3><p>If state just flows through a component, then that component can be a singleton, avoiding needless allocation.</p>
<p>It&rsquo;s a lot easier to reason about an application that comprises a graph of singletons with transient data flowing through it.</p>
<p>Inject factories to create transient services (e.g. a remote-method caller that captures state).</p>
<h2>Conclusion</h2><p>As you can see, we put a lot of thought and care into our development practices and patterns. We try really hard to work in a way that ends up with quality software: stable, maintainable, extensible, testable and, most importantly, does what it&rsquo;s supposed to.</p>
<p>For more information about specific development patterns, please see the <a href="https://docs.encodo.ch/quino/master/docs/architecture/readme.html">architecture section of the Quino conceptual documentation</a>. There are sections on <a href="https://docs.encodo.ch/quino/master/docs/architecture/interfaces_and_implementations.html">interfaces, base classes and virtual methods</a>, <a href="https://docs.encodo.ch/quino/master/docs/architecture/provider.html">providers</a>, <a href="https://docs.encodo.ch/quino/master/docs/architecture/toolkits.html">tools &amp; toolkits</a>, <a href="https://docs.encodo.ch/quino/master/docs/architecture/task_specific_interfaces.html">task-specific interfaces</a> and much more.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4434</guid>
    <title><![CDATA[Encodo White Papers: Testing as first-class citizen (2019)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4434</link>
    <pubDate>Wed, 04 Oct 2023 21:36:07 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:36:07 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Tests are code. Writing tests is not a &ldquo;step&rdquo;—it is part of writing the code itself. The component is nothing without its tests.</p>
<p>It should be easy to verify any requirement with a test. The tests should tell the story of the requirements.</p>
<p>A developer can test any component in isolation (unit testing) or can test the component in the constellation in which it normally exists (integration testing).</p>
<h2>Tests are code</h2><p>Just so we&rsquo;ve said it: tests are not a place to use a different coding style or different coding practices than in &ldquo;regular&rdquo; code. Choose your frameworks wisely. It should be easy to write powerful, elegant and easily understood tests. Build your own support code and libraries where needed. Apply the same coding principles as you would with the code being tested. You have to maintain testing code just like any other code.</p>
<p>We discuss below that we prefer integration tests to unit tests—that only works if you provide a way to write high-performance integrated tests without repeating a lot of code.</p>
<h2>Unit Tests and Mocking</h2><p>Unit tests are very easy to write for properly written components. With a proper infrastructure, such tests can just as easily be executed in an integrated environment. In such cases, there is generally no need to invest time (and incur maintenance debt) writing two sets of tests.</p>
<p>Automated tests will sometimes replace components and dependencies with <em>fake</em> or <em>mocked</em> objects, in order to isolate and test only a component&rsquo;s logic without incurring the costs of configuring and setting up unrelated components.</p>
<p>If integration testing is too complicated or too slow, then a web of unit tests may suffice. In most cases, though, this doesn&rsquo;t apply and we avoid mocking entirely and test components directly in common, integrated settings.</p>
<p>For example, if a component is commonly used as part of a database-based application, then it is more effective to test that component in such a scenario, rather than expending effort in isolating the component in order to have a &ldquo;true&rdquo; unit test.</p>
<p>With only unit tests, there is a danger that the component works, but only as tested, not as actually used.</p>
<h2>Testing configuration</h2><p>Often, these problems arise in component <em>configuration</em>. A unit test will pass in carefully prepared (and sometimes faked) dependencies and run all-green.</p>
<p>However, an integration test will check that the configuration code <em>also</em> works. That is, that the component is configured correctly for products that use it and not just in the tests that verify its behavior.</p>
<p>Mocks and fakes must be used judiciously, otherwise you end up either testing only the mock or you end up hiding certain classes of problems, as discussed in more detail below.</p>
<h2>Missed opportunities</h2><p>Imagine a UI list that validates and saves entries when the focus changes. This list might work just fine in a test, where notifications and side-effects as a result of saving are disabled with mocks.</p>
<p>This is no longer the real-world situation, though. What happens if one of the notifications would have led to a reload of the list or a state-change in one or more objects? What if the list only saves an object it is is marked as &ldquo;changed&rdquo; but that the spurious event resets that status in integration? This kind of interaction—this kind of <em>bug</em>—represents exactly the kind of thing we would miss when testing the list in too isolated a manner.</p>
<p>Because we&rsquo;ve mocked away too much—because we focused too tightly on a unit test of the list—we&rsquo;ve missed a bug that will come up in production instead.</p>
<h2>Writing tests</h2><p>While we don&rsquo;t practice strict TDD at Encodo, we do write tests from the very beginning.</p>
<p>It&rsquo;s really the only way to test the code that you&rsquo;re writing, isn&rsquo;t it? What are you going to do instead? Fire up the web server each time you want to throw data at a controller? Use a browser or Postman to fire those requests? Or are you starting a desktop UI and clicking around and typing? Or did you hack together a little console application in order to debug code?</p>
<p>Stop doing all of those things. Use a testing environment instead, so your product acquires a growing stable of automated, repeatable regression tests. It will become second nature to write tests to verify requirements about the components you write.</p>
<p>As we said above: the tests are part of the component.</p>
<h2>Coverage</h2><p>A point made above is that unit tests are useful but they&rsquo;re often not complete. Unit tests can fool you with excellent <em>syntactic coverage</em> but sub-standard <em>functional coverage</em>. We have many tools to measure the former, but only experience to measure the latter.</p>
<p>Sure, you&rsquo;ve covered all of the lines, but did you actually choose a representative set of inputs? Are you making the right assertions? Did you actually test the requirements?</p>
<h2>Expectations</h2><p>One technique that we use a lot is <em>expectation</em> files (called <em>snapshots</em> in some frameworks). Instead of writing several (sometimes, dozens of) assertions, we format output to text and then compare it against the text produced by the previous, presumably correct test run.</p>
<p>The idea is to detect when something has <em>changed</em>. We use this in Quino to verify log output during certain operations, or to verify queries or generated SQL or model structure or lists of data. Expectation files increase the depth and robustness of tests while at the same time making it extremely efficient to write and maintain such tests.</p>
<p>An expectation (or snapshot) is updated automatically when it changes and shows up as a difference in source control. If the change is expected, the developer commits it.</p>
<h2>Experience counts</h2><p>It takes a lot of experience to write just the right number and kind of tests. You don&rsquo;t want to write too many tests: it&rsquo;s code you have to maintain, after all. Also, it can be confusing when the same problem crops up in multiple places in different fixtures.</p>
<p><em>Some</em> components should have unit tests as well as integration tests. For other components, unit tests are redundant because the integration tests cover everything already. Experience guides you in deciding what to write first, what to keep, and what to throw away.</p>
<h2>Too many tests?</h2><p>It is possible to have too many tests. If you&rsquo;re not aware in which layer your code resides, you might end up running the same code in multiple scenarios, when that component behaves the same regardless.</p>
<p>For example, if you&rsquo;re testing how expressions are mapped to a database, then that test should definitely run against every supported database. If you&rsquo;re testing how a high-level query composes those expressions <em>before</em> they get to the mapper, then you only really need to run it against one database in integration.</p>
<h2>Conclusion</h2><p>No-one wants to admit to releasing untested software. And no-one really wants to do manual testing. Automating tests reduces turnaround time for changes and enhancements. It also increases confidence for quick turnarounds when going to manual testing or production.</p>
<p>Unit tests are good, but prefer coverage in integration tests so that you have the best guarantee that your tests are running your code in a way that emulates the production environment as closely as possible.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4432</guid>
    <title><![CDATA[Encodo White Papers: Document Everything (2017)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4432</link>
    <pubDate>Wed, 04 Oct 2023 21:36:01 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:36:01 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Good documentation is part of every piece of quality software. What do we mean by &ldquo;good&rdquo;, though? Or &ldquo;documentation&rdquo;, for that matter? Quality software <em>should</em> be self-explanatory, but don&rsquo;t be fooled into thinking that you don&rsquo;t need to write documentation.</p>
<h2>Actors &amp; Use Cases</h2><p>Documentation has an audience. Before writing anything, consider who you&rsquo;re writing it for. What are the possible audiences?</p>
<h3>Evaluators</h3><p>Evaluators are interested in what your software does, how it interacts with other software, its performance characteristics, system requirements, the product roadmap, open issues and so on. If you don&rsquo;t document your software sufficiently, an evaluator won&rsquo;t purchase it in the first place.</p>
<p>By &ldquo;purchase&rdquo;, we mean that an evaluator will decide to use your software. This applies not only to commercial projects, but also to open-source freeware or even internal company software, be it a potentially time-saving Excel spreadsheet, a set of common UI or server components or an enterprise-wide multi-tier application.</p>
<h3>Installers</h3><p>Installers are interested in the basic installation options/paths and how to get from purchase/download to running. Here you need to find a balance between getting them up and running quickly, but also informing them that there is more to your product than just the standard rollout. They need to know that they can get set up efficiently but also that they&rsquo;re not locked in to a single way of doing things (unless that&rsquo;s what you&rsquo;re selling).</p>
<h3>Customizers</h3><p>Customizers are advanced installers: they want to know how to tweak or customize an installation to meet their special needs. These are often the same people as installers, but</p>
<h3>New Users</h3><p>New users are going to use installed/customized software. They want to not only know what your software does, but how they can use it for these standard tasks. They are interested in underlying concepts in both the application domain and the user experience. They need both introductory and high-level documentation, with meticulous, step-by-step instructions. These users are likely to navigate documentation in a progressive manner, reading from beginning to end.</p>
<h3>Everyday/experienced Users</h3><p>Everyday/experienced users aren&rsquo;t generally interested in introductory documentation. They are interested in how to become more efficient with your software. They will jump around in the documentation, using a search function to find what they need.</p>
<h3>Extenders</h3><p>Extenders are users—usually developers—who will be using your software as a building block, integrating it with other software or extending it to meet their needs. These users are interested in command-line options as well as descriptions of available APIs. If the API surface is larger, then functionality should be grouped and examples included to demonstrate how to use the various calls in common workflows.</p>
<h3>Developers</h3><p>Last but not least, you have to document for developers. That means writing your code and documenting it in a way that is understandable not only to you but other members of your team. Future members of your team, will also need to get up to speed. As is often the case, you yourself will be one of those future developers, when you come back to a project or product after a longer absence. Your future you will definitely thank you for leaving well-documented clues.</p>
<h2>How to get started</h2><p>Wow! That seems like quite a lot of documentation to write. It is. As with anything else, you&rsquo;ll have to prioritize. We can make a list of the various documentation types we have at our disposal and identify the actors that would use them.</p>
<ul>
<li>Description/purpose (evaluators)</li>
<li>System requirements (evaluators, installers)</li>
<li>Readme (evaluators, installers, customizers, extenders)</li>
<li>Concepts (all users)</li>
<li>Tutorials (users, extenders)</li>
<li>Training Videos (users, extenders)</li>
<li>Error messages (users, developers, extenders)</li>
<li>Command-line help (installers, customizers, extenders)</li>
<li>Code documentation (developers, extenders)</li>
<li>Log messages (developers, extenders)</li>
<li>Issues/stories/bugs/todos/roadmap (evaluators, developers, extenders)</li></ul><p>As you can see, we consider anything that helps <em>actors</em> to understand the software to be documentation. That means that writing useful error and logging messages is <em>also</em> an important way of documenting the product. Similarly, a clearly defined roadmap with stories/bugs/todos provides context for evaluators and developers. All of these forms of documenting a product can save everyone a lot of time, money and confusion by offering context-sensitive documentation right where it&rsquo;s needed.</p>
<p>This extends to everything in your software or product: the best documentation is a good design. If the UX is more intuitive or command-line help is clear or the APIs are consistent and well-organized, that can go a very long way already. There is less need for extensive tutorials explaining each and every task when the product documents itself.</p>
<p>For example, if you name an API <code>getUsers()</code> and an input variable <code>includeAdministratorUsers</code>, then you don&rsquo;t need to write much more than &ldquo;Gets a list of users, optionally including administrators.&rdquo;</p>
<p>For those reasons and many others, we recommend getting started early with documentation. If look at the list above, that&rsquo;s kind of obvious advice.</p>
<ul>
<li>If you don&rsquo;t know the purpose or the concepts, then you shouldn&rsquo;t be building the product yet.</li>
<li>You need to document how to set up and install the product or your own developers won&rsquo;t be able to work.</li>
<li>If error and log messages are obscure, your developers and supporters will lose a lot of time and money on issues and bugs.</li></ul><p>Most importantly, the simple act of trying to describe what you are making will lead to a better product. You&rsquo;ll often find that, as you document, you&rsquo;ll notice things that could be done better or more intuitively or more consistently or more easily. The simple act of trying to explain what you&rsquo;re making leads to a better product. If you find it relatively quick and easy to write documentation, then there&rsquo;s a good chance that you&rsquo;ve managed to build quality software.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4431</guid>
    <title><![CDATA[Encodo White Papers: Continuous Integration and Delivery (2017)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4431</link>
    <pubDate>Wed, 04 Oct 2023 21:35:54 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:35:54 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>An important part of the software process is the final step: delivery.</p>
<p>If you can&rsquo;t get your software into your customer&rsquo;s hands, then what&rsquo;s the point of writing it at all?</p>
<h2>Goals</h2><p>There are several at-times cross-cutting goals. In descending order of importance, they are:</p>
<ul>
<li>Improve reliability and quality of releases</li>
<li>Improve efficiency of the release process</li>
<li>Improve testing feedback loop</li>
<li>Improve efficiency of the development process</li></ul><h2>Definition</h2><p>There are several aspects to continuous integration and delivery:</p>
<ul>
<li><strong>Build:</strong> create testable artifacts</li>
<li><strong>Test:</strong> execute automated tests on a clean machine, separate from any developer&rsquo;s environment</li>
<li><strong>Package:</strong> create deployable artifacts (may be same as build output)</li>
<li><strong>Deploy:</strong> deploy artifacts to target environments (e.g. Dev, Staging, UAT or Production)</li></ul><h2>Benefits</h2><p>As expected, working in an organized manner with increased automation has clear benefits.</p>
<ul>
<li>An excellent protocol of which software version contains which changes</li>
<li>Automated and centralized archiving of versions</li>
<li>Improved code &amp; configuration quality as all code is tested on a non-developer machine</li>
<li>Practice makes perfect: if you&rsquo;re delivering during the entire life of the project, then the final delivery is much more predictable and far less stressful</li></ul><h2>Limitations</h2><p>There are obviously limitations as well. The most immediate one is infrastructure investment: you have to set up build servers or purchase them in the cloud. You also have to make your process work with automated builds and possibly retrain personnel to work with it.</p>
<p>You have to plan your project and you have to have patience on the part of all stakeholders. You have to train everyone on the team to <em>not even consider</em> releasing a version of the software from a developer PC.</p>
<p>Setup and maintenance of build agents takes time and effort, especially over longer periods of time. Operating systems are upgraded, core components changed, build systems upgraded. All of these things will cause the build to fail on a given agent, even though nothing is actually wrong with the product. Here again, though, the agent will act as a canary in the coalmine for your development team. More often than not, the build-server failure will alert the team to avoid a feature that would have other wise cost them time to integrate before it&rsquo;s ready.</p>
<h2>Deployment types</h2><p>The type of deployment depends on the product.</p>
<p>For desktop software, you need to build an installer or a compressed archive that users can execute and install. Mobile or UWP applications must be built and then delivered to app stores for installation. Web servers and sites can be deployed directly to in-house servers or into the cloud (e.g. AWS or Azure).</p>
<p>These deployment types are for the end users, but there are many more releases than that. Developers need to test their changes locally. Testers need to get these versions in order to provide feedback in a timely manner. We think of all of these releases as part of the build infrastructure, not just the continuous-integration server delivering an end-product.</p>
<h2>Requirements</h2><ul>
<li><strong>Clean, predictable versioning:</strong> preferably semantic versioning, which means that you can support alpha, beta, RC and other pre-release versions</li>
<li><strong>Scripted packaging:</strong> there can be no manual steps in the entire release process</li>
<li><strong>Infrastructure:</strong> One or more agents for executing builds, either hosted locally or in the cloud</li>
<li><strong>Knowhow:</strong> Knowledge of how to configure builds and deployments, preferably distributed among multiple team members (even if access is limited to IT)</li></ul><h2>Experience</h2><p>At Encodo, we have experience with various systems for various types of software. We started off using Jenkins but moved to JetBrains TeamCity several years ago. Web projects have their own packaging and testing mechanisms (e.g. WebPack, Mocha) that integrate into almost any build infrastructure. We&rsquo;ve also used Fastlane combined with Test Flight for mobile deployment. Our main expertise lies with configuration of .NET deployments paired with TeamCity.</p>
<h2>Recommendations</h2><ul>
<li>Use the same tools on the build server as your developers do. That is, if you use .NET with R# and the NUnit test runner, then use those same tools on your build server. In this case, TeamCity is a good fit for many of our projects.</li>
<li>Avoid writing too many custom scripts for the build server. The build server will need to perform some extra tasks (like clearing databases), but make sure that those scripts are in the code repository and can be executed and tested locally as well. This decreases debugging time in the CI environment.</li>
<li>If you do have to write scripts for the build server, consider whether you can use the same scripts on local developer machines. For example, Encodo uses a lot of NAnt scripts to clean, build, deploy and package solutions. We use those scripts locally as well on the build server. This increases the likelihood that an issue with the scripts will be detected locally rather than only on the build server (where it&rsquo;s generally more difficult and time-consuming to address).</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4428</guid>
    <title><![CDATA[Encodo White Papers: Design by Contract (2006)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4428</link>
    <pubDate>Wed, 04 Oct 2023 21:35:48 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:35:48 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Design by Contract is a software engineering practice in which software requirements and promises − the &ldquo;Contract&rdquo; − are explicitly written into the code. The code is, at the same time, better documented, more reliable and easier to test against. Encodo uses this technique to ensure software quality.</p>
<h2>A brief overview of contracts</h2><p>A software contract is composed of several components: preconditions, postconditions and invariants. Preconditions are what a component requires of a client, whereas postconditions are what a component guarantees to a client. In object-oriented programming, these contracts are attached to method calls in a class. Invariants are a list of conditions that must always be true for software. An invariant is typically attached directly to a class; the runtime checks the class invariant when entering and exiting a method call.</p>
<p>Popular programming languages, like Java, C#, Delphi Pascal and others, lack the language constructs needed to express these contracts. However, these languages contain assertion constructs, which allow one to roughly describe the contracts. The section on emulating contracts in other languages section shows the most common technique.</p>
<p>Eiffel is a language whose inventor, Bertrand Meyer, pioneered Design by Contract. It includes rich support for expressing contracts, is similar to Pascal in syntax and will be used for the examples below. The FAQ offers more information on why we chose Eiffel for our examples.</p>
<h2>Using contracts</h2><p>The best way to show how the use of contracts affects software is with an example. Imagine a database connection class with a method <code>Open</code>. This opens a connection to the database, allocating resources for it and failing if the request is refused.</p>
<div class="chart"><h3 class="chart-title">Listing 1 - Initial definition</h3><div class="chart-body"><pre class=" "><code>Open is
  do
    – Execute code to open the connection here
  end</code></pre></div></div><p>Any procedural programming language is capable of formulating the code above. However, what happens if <code>Open</code> is called twice in a row on the same connection? One way to handle this is to simply ignore subsequent calls to <code>Open</code>.</p>
<div class="chart"><h3 class="chart-title">Listing 2 - Ignoring subsequent calls</h3><div class="chart-body"><pre class=" "><code>Open is
  do
    if not IsOpen then
      – Execute code to open the connection here
    end
  end</code></pre></div></div><p>This is not optimal, for several reasons:</p>
<ul>
<li>Clients that misbehave by repeatedly calling a powerful function like <code>Open</code> will never know they are doing so.</li>
<li>Clients that lack the original source will have no idea that the check is already made and will check again, needlessly muddying their code and wasting performance.</li>
<li>The function fails to open the connection silently, which is an extremely dangerous way of responding to a non-standard condition.</li></ul><p>Another way to respond is to accept that this might happen, but making it non-silent, logging the occurrence to some sort of logging mechanism.</p>
<div class="chart"><h3 class="chart-title">Listing 3 - Logging subsequent calls</h3><div class="chart-body"><pre class=" "><code>Open is
  do
    if not IsOpen then
      – Execute code to open the connection here
    else
      – Log a warning
    end
  end</code></pre></div></div><p>This is slightly better and an entirely appropriate solution in some cases. However, the connection is quite a low-level component; it should not be responsible for deciding what to do about repeated calls to <code>Open</code>. We can use a contract to push the responsibility onto the client.</p>
<div class="chart"><h3 class="chart-title">Listing 4 - Precondition</h3><div class="chart-body"><pre class=" "><code>Open is
  require
    not IsOpen
  do
    – Execute code to open the connection here
  end</code></pre></div></div><p>The require clause contains optionally named boolean expressions. If one evaluates to false, a precondition violation is signaled. The violator can immediately be pinpointed and repaired to conform to the contract (by adding a check for <code>IsOpen</code> before calling <code>Open</code>). What are the benefits?</p>
<ul>
<li>A client has a list of conditions that must be satisfied before calling a routine. The interface is clear.</li>
<li>A routine has a way of devolving responsibility for certain conditions onto its clients.</li></ul><p>The contract for this routine is not complete, as it has only published its requirements, but said nothing about guarantees. Given the name of the function, we would expect it to have the following postcondition:</p>
<div class="chart"><h3 class="chart-title">Listing 5 - Postcondition</h3><div class="chart-body"><pre class=" "><code>Open is
  require
    not IsOpen
  do
    – Execute code to open the connection here
  ensure
    IsOpen
  end</code></pre></div></div><p>The function is now completely defined, having explicitly detailed its requirements and guarantees. The postcondition often looks quite superfluous: the code for opening the connection is right above it, isn&rsquo;t it?</p>
<p>Not necessarily.</p>
<p>If the function is <code>deferred</code> (<code>abstract</code> in Java and Pascal, <code>virtual</code> in C-style languages), the implementation is in a descendent. The pre- and postconditions apply to the redefinitions as well. This allows a base class to very precisely define its interface with other classes without making any decisions about implementation.</p>
<div class="chart"><h3 class="chart-title">Listing 6 - Deferred implementation</h3><div class="chart-body"><pre class=" "><code>Open is
  require
    not IsOpen
  deferred
  ensure
    IsOpen
  end</code></pre></div></div><p>The precondition can only be expanded in a descendent, whereas the postcondition can only be further constrained. That is, a descendent cannot define the precondition to be not <code>IsOpen</code> and <code>DatabaseExists</code>. A client with a reference to the ancestor class sees only the ancestor precondition and cannot be forced to conform to a contract defined in a descendent.</p>
<p>Likewise, the postcondition cannot be redefined to be <code>IsOpen</code> or <code>ActionFailed</code>. The original interface has already decided that if the database cannot be opened, the implementation must raise an exception. A client with a reference to the ancestor class does not have access to the <code>ActionFailed</code> feature and cannot accept this as a valid postcondition.</p>
<p>The descendent adjusts the precondition in a function like this:</p>
<div class="chart"><h3 class="chart-title">Listing 7 - Extending a contract</h3><div class="chart-body"><pre class=" "><code>Open is
  require else
    AutoCloseIfOpened
  do
    – Execute code to open the connection here
  ensure then
    not CompactOnOpen or DatabaseIsCompacted
  end</code></pre></div></div><p>This descendent has expanded the precondition to allow a caller to call <code>Open</code> repeatedly only if <code>IsOpen</code> is false (inherited precondition) or if the <code>AutoCloseIfOpened</code> option has been set. Likewise, it has further constrained the postcondition to promise that, in addition to <code>IsOpen</code> being true (inherited postcondition), the database will be compacted if the <code>CompactOnOpen</code> option is set.</p>
<h2>Emulating Contracts in other Languages</h2><p>So, that&rsquo;s Eiffel. How can other languages express contracts without the proper language constructs? As mentioned above, almost all modern languages include an assert function, which accepts a boolean expression and raises an exception if it is false. This function can emulate pre- and postconditions, but class invariants are largely impractical in languages without some form of pre-processor (a search for Design by Contract in C++ turns up several such libraries). Here&rsquo;s Listing 5 written in Delphi Pascal:</p>
<div class="chart"><h3 class="chart-title">Listing 8 - Emulating a contract</h3><div class="chart-body"><pre class=" "><code>procedure Open;
  begin
    Assert( not IsOpen );
    // Execute code to open the connection here
    Assert( IsOpen );
  end {Open};</code></pre></div></div><p>Note how the contract is expressed in the implementation body; this makes contract inheritance difficult. The following pattern illustrates a single level of contract inheritance (which prevents descendants from removing contracts by not calling inherited methods):</p>
<div class="chart"><h3 class="chart-title">Listing 9 - Emulating Contract inheritance</h3><div class="chart-body"><pre class=" "><code>procedure Open;  // Not overridable
  begin
    Assert( not IsOpen );
    DoOpen;
    Assert( IsOpen );
  end;

procedure DoOpen; virtual; abstract;</code></pre></div></div><p>Under this pattern, descendants are required to implement <code>DoOpen</code> and cannot alter <code>Open</code> (Delphi methods are by static by default − equivalent to <code>final</code> in Java, <code>sealed</code> in C# or <code>frozen</code> in Eiffel). There are naturally drawbacks to this approach, especially when compared to the rich contract syntax available in Eiffel*, but the technique is sufficient for many of the desired contracts.</p>
<p><small class="notes">See the further reading below to learn about using old in postconditions and expressing class invariants</small></p>
<h2>FAQ</h2><h3>Question 1</h3><blockquote class="quote quote-block "><div>&ldquo;Why is there no <code>try .. finally</code> to ensure that the postcondition is checked in Listing 8?&rdquo;</div></blockquote><p>A postcondition is only guaranteed when the function exits successfully. In the example, it is perfectly legitimate for <code>Open</code> to fail because of an external connection problem. The precondition only guarantees that the connection is not open, not that it can be opened. Such guarantees are useless because they involve performing the action in order to check that the action can be performed.</p>
<p>The function should raise an exception if it cannot open the connection, avoiding evaluation of the postcondition and resulting in an acceptable error condition. An implementation that fails silently will cause a postcondition violation, which is an unacceptable error condition.</p>
<p>Using a <code>try .. finally</code> construct to force evaluation of the postcondition under all circumstances would result in both the desired error (connection could not be opened) and a postcondition violation, which is not correct.</p>
<h3>Question 2</h3><blockquote class="quote quote-block "><div>&ldquo;What if there is an exit or return statement in Listing 8?&rdquo;</div></blockquote><p>Question 1 proposed a using a <code>try .. finally</code> construct to ensure that the postcondition was always executed. As you can see from the answer, this has undesirable side effects. The simple answer is not to use instructions that break the normal instruction flow (e.g. exit or break). The usefulness of such constructs is debatable and the drawbacks are high (especially, as shown above, when the instruction avoids checking contracts).</p>
<p>This exposes the weakness of languages without explicit contract constructs — it requires discipline to avoid bad practices. Relying purely on discipline invites error. However, it is better than nothing at all.</p>
<h2>Further Reading</h2><ul>
<li><a href="http://archive.eiffel.com/doc/oosc/">Object-oriented Software Construction</a></li>
<li><a href="http://www.eiffel.com/developers/presentations/">Eiffel.com Presentations</a></li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4433</guid>
    <title><![CDATA[Encodo White Papers: Code Reviews (2017)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4433</link>
    <pubDate>Wed, 04 Oct 2023 21:35:39 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:35:39 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>A healthy and active review culture is essential for any team interested in building quality software. At Encodo, we&rsquo;ve been doing reviews for a long time. They&rsquo;ve become an essential part of everything we do:</p>
<ul>
<li>Analysis</li>
<li>Estimates</li>
<li>Design</li>
<li>Architecture
<li><div>Coding<ul>
<li>Style</li>
<li>Performance</li>
<li>Coverage</li>
<li>Security</li></ul></div></li>
<li>Deployment</li>
<li>And more…</li></ul><h2>Definition</h2><p>What we mean by review is not a formal process at all. It is simply that you prepare work you&rsquo;ve done for an informal presentation to a team member. Explaining what you&rsquo;ve done in a review is often a good way of collecting your thoughts—you should be able to explain what you&rsquo;ve done. Getting a review from a colleague is an efficient and productive way of making sure you can do that.</p>
<h2>Limitations</h2><p>While there are many reasons to do reviews, we&rsquo;ve also learned that reviews can&rsquo;t do everything.</p>
<ul>
<li>They&rsquo;re not very efficient at distributing know-how. A review helps another, well-versed team member learn what you&rsquo;ve done, but it won&rsquo;t help non-team members get on-board.</li>
<li>If the reviewer has to learn too much from the review, then they cannot perform a useful review. They can be, at best, a sounding board.</li>
<li>For similar reasons, a review is not a good way of mentoring junior team members.</li></ul><h2>Benefits</h2><ul>
<li>The quality of anything that you expect to review with someone automatically increases. Just knowing that you will have to tell someone what you did and why increases the likelihood that you think about the solution clearly and consider potential questions.</li>
<li>A major benefit of getting a review is that it makes you check and prepare your own work. You&rsquo;ll often notice that there&rsquo;s still work to be done all on your own—even if the reviewer doesn&rsquo;t say one word.</li>
<li>When you&rsquo;ve spent a long time on a problem, a fresh perspective as offered by a reviewer may offer an alternative solution. Often we&rsquo;re so deeply involved in a solution that we don&rsquo;t notice when we&rsquo;ve diverged from the requirements and are just making more work for ourselves.</li>
<li>When applied to very early stages, like analysis or estimates, the savings in time, money and manpower can be enormous.</li></ul><h2>Scheduling</h2><p>It&rsquo;s important to get reviews often enough to avoid wasting time and effort but <em>not so often</em> that your work or the reviewer&rsquo;s work grinds to a halt. It&rsquo;s all about balance.</p>
<p>A good rule of thumb is about one review per task. If your task is longer than a day, then think about how to break up that work into phases in order to get a review of earlier phases.</p>
<p>That way, you&rsquo;re more likely to catch issues before building on top of mistakes.</p>
<h2>Synchronous versus Asynchronous</h2><p>Encodo prefers live, face-to-face reviews.</p>
<p>This is the most efficient manner of reviewing as neither party has to prepare anything other than the work to be reviewed. Issues that come up can often be handled immediately—and such issues are far more likely to be mentioned and fixed. While in-person reviews are superior, video-chat/shared-desktop reviews work quite well, too.</p>
<p>If that&rsquo;s not possible, then we have also used tool-based, asynchronous reviews, such as pull requests with review software. However, we find these to be not only less efficient but also less likely to find as many issues.</p>
<p>With a live code review, it&rsquo;s relatively easy to ask the submitter to reorder, split or squash commits. It&rsquo;s also easier to point out and quickly fix stylistic issues (like naming or interface usage, etc.). Because the turnaround time is much faster, a reviewer is far more likely to point out smaller fixes that would improve code quality, maintainability and so on.</p>
<p>However, in an asynchronous review, a reviewer must decide what is most important. Is it worth rejecting the whole pull request if it&rsquo;s 95% correct with a few details? Do you reject it and ask the submitter to fix up spacing or formatting or missing documentation? Do you really write down every last little thing you would have said? Do you reject it and hope that the submitter understands all of your notes? Or do you accept it and just fix those things up yourself? How many iterations do you go through?</p>
<p>We prefer synchronous, face-to-face reviews because they&rsquo;re much more efficient. Misunderstandings can be cleared up quickly, iterating until the submitter and reviewer find a consensus.</p>
<h2>Rules of Thumb</h2><ul>
<li>A review should not consist of more than 200 lines of code</li>
<li>A review should not last longer than an hour</li>
<li>One reviewer is usually enough; if necessary, pull it at most two reviewers</li>
<li>For non-code, use your judgment to determine an appropriate amount of reviewable work</li></ul><h2>Getting Faster</h2><p>We encourage reviews everywhere because we know how to make them faster.</p>
<ul>
<li>Use your IDE to help submitters improve their code before they ask for a review. Formatting, code-style preferences and other issues can be eliminated from review if the tools enforce them.</li>
<li>Start by focusing on the changes made (diffs) and expanding from there if further context is needed. If the reviewer was chosen well, then that context is often already available</li>
<li>Review related commits en masse rather than individually</li>
<li>Smaller, focused commits are much easier to explain and to review</li>
<li>Spend less time on commits that are purely refactoring (trust your tools and your tests)</li>
<li>Practice makes perfect!</li></ul><h2>Getting Better</h2><p>Both the reviewer and the submitter need to practice. A reviewer should practice diplomacy and formulate critique in a way that it will be accepted. A submitter must keep an open mind and prepare good arguments or justification for the code. Both sides should stay positive. A review shouldn&rsquo;t be a competition: it&rsquo;s about producing high-quality code together, as a team.</p>
<p>Encodo has done presentations on reviews, in both English and German.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4429</guid>
    <title><![CDATA[Encodo White Papers: Component-based Design (2006)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4429</link>
    <pubDate>Wed, 04 Oct 2023 21:35:31 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:35:31 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">This article is part of an <a href="https://www.earthli.com/news/view_article.php?id=4430">archive of Encodo White Papers</a>.</small></p>
<p>What is the best approach when designing a new application, be it a small tool or an end-user application?</p>
<h2>Build a Prototype?</h2><p>Many developers jump straight into a prototype, in order to get a feel for how the application will work. While prototypes are good for demonstrations, they are dangerous: in projects with tight time or budget constraints, the temptation to simply &ldquo;build out&rdquo; the prototype becomes irresistible. This leads to applications with nice user interfaces (hereafter called UI), but inflexible and difficult-to-follow implementations.</p>
<h2>Build Components</h2><p>A better first step is to list the requirements and assign them to possible components. This doesn&rsquo;t have to be a long or complete evaluation of the requirements; a few minutes is enough to come up with enough ideas to get started coding. These non-UI components are a natural fit for testing environments and are more likely to define a clean, sensible API (Application Programming Interface). Once the core logic has been built and tested, a prototype can easily be built on top of it.</p>
<p>To summarize, the component-based approach is important for the following reasons:</p>
<ul>
<li>It maintains business logic in clearly-defined units</li>
<li>It improves testability of business logic</li>
<li>It improves portability and reuse</li>
<li>It avoids spreading core logic throughout event handlers, which is a common practice in RAD (Rapid Application Development) environments</li></ul><h2>RAD considered harmful</h2><p>A good UI library is a wonderful thing, allowing clean-looking, well-integrated applications to be built in a very short time. However, the allure of this style of programming is dangerous, as it quickly leads to applications without a clearly defined API, which leads to extensibility and maintenance issues.</p>
<p>These systems entice programmers into working &ldquo;backwards&rdquo;, building their application logic around events generated by the UI. The first generation of RAD environments were notorious for mixing UI and business code. The latest generations make use of libraries with &ldquo;code-behind&rdquo; built right in, automatically supporting core/UI separation in both web or classic UI application.</p>
<p>This separation of core logic and UI events makes is commonly called the MVC or Model-View-Controller pattern.</p>
<h2>What is MVC?</h2><p>MVC is the official name for the technique described above, in which functionality is contained in a model (M), which communicates state changes to a view (V) through some form of update mechanism. The controller (C) represents user input and applies changes to the model.</p>
<p>In many UI libraries, the view and controller layers are merged, making it much easier to apply the pattern to smaller projects. View components are typically bound to model components using the Observer pattern: the view &ldquo;listens&rdquo; for changes in the model and reacts accordingly.</p>
<h2>Designing with Components</h2><p>Consider a tool which processes text files and generates output of some kind (perhaps PDF or CSV). The actual task doesn&rsquo;t matter − this is the kind of tool that is often written in a seat-of-the-pants fashion, with the excuse that it is &ldquo;faster&rdquo; to get it done this way. Let&rsquo;s take a component-based approach and see what we get.</p>
<p>What are the components of the system?</p>
<ul>
<li><strong>Transformer</strong> − Takes an input, applies one or more actions and generates an output</li>
<li><strong>Actions</strong> − Performs an operation on data</li>
<li><strong>Importers</strong> − Readers for various input formats; convert to a format the transformer understands</li>
<li><strong>Exporters</strong> − Writers for various output formats; converts from the transformer format</li>
<li><strong>Plugin Registry</strong> − Registration for recognized input and output formats</li>
<li><strong>Options/Preferences</strong> -Global options for the system</li></ul><h2>Analyzing the Component-based Design</h2><p>This list took only a few minutes to write and could have been written by anyone familiar with the project. The list contains only domain knowledge — there is no implementation-specific data. Having written down the requirements, we see that there is a need for an internal data representation, which will be used by the importers, exporters and actions. This is a facet of the design that might have gone unnoticed during prototyping, but would have been expressed implicitly nonetheless.</p>
<h3>Is it overdesigned?</h3><p>The list of features above is not an &ldquo;over-design&rdquo;, but rather an explicit expression of the specifications. While an implementation can avoid using importer, exporter and action components, these concepts are part of the design nonetheless: an implementation without tehm is simply more difficult to describe, understand and extend.</p>
<p>With a little bit of thought, we have designed a system that will scale to multiple import and export formats and even support multiple transformations. Writing the application in this way may involve marginally more initial work, but will result in a far more testable, extensible and reusable framework, decreasing maintenance and support time.</p>
<h3>Does it slow development?</h3><p>Another popular argument is the perceived reduction in programming efficiency. Applications or tools of the &ldquo;throwaway&rdquo; kind will take longer to develop when using a clean programming model. Whereas that may be true in the very short term, the majority of an application&rsquo;s life span is spent in support and maintenance, which takes more time and energy if the application is poorly designed.</p>
<p>Though a throwaway prototype may be available marginally quicker, it will be of poorer quality. In addition, subsequent applications cannot benefit from its code. The biggest loss comes in the form of functionality, improvements or bug fixes which are never even attempted because the code is not in a maintainable or testable state.</p>
<h3>How does the UI work?</h3><p>Realization of this design at the core level is not so difficult. Even though the application initially only has one importer and one exporter, it doesn&rsquo;t take much more to define an API that supports multiple plugins. Writing the tests for these components is likewise trivial. The opposite is true in the UI: building an interface to manage and configure all of the functionality that was easily written into the model is prohibitive.</p>
<p>There is no reason, however, that the UI has to express all of the details of the underlying model; the application, as specified, need only expose enough functionality in the UI to be able to import and export. The UI stays remarkably simple, but can be easily and quickly extended to offer more features, if desired. Since the model has automatic tests, it can be assumed to be stable and it is easier to accurately estimate the time required to build the new GUI elements.</p>
<h2>Analyzing the Prototype-based Design</h2><p>The standard, quick-prototyping approach would have started coding a main form with some input fields, building the transformation code directly into the form itself. Options and preferences would have likely been encapsulated with a few controls on the main form, which, in turn, would have been responsible for loading and storing them.</p>
<p>The design sketched above would be expressed implicitly and partially, at best. An application written without these concepts in mind will not be worth refactoring. If the code is re-used at all, it is typically copied to a new project and modified there, resulting in multiple copies of nearly the same code. Fixes and enhancements to one will not necessarily appear in the other.</p>
<p>A prototype that is considered &ldquo;throwaway&rdquo;, but grows into an application, does not benefit from any of the following:</p>
<ul>
<li>It is easier to document the clearly defined API of a model; good documentation allows multiple developers to support or upgrade the application</li>
<li>Reuse across multiple applications</li>
<li>It is far easier to refactor and repurpose model code that lends itself to test-driven development</li></ul><h2>Extending the Application</h2><p>It&rsquo;s obvious from the design above that it can be extended to support multiple importers, exporters and actions. The initial application was assumed to be a GUI which did not expose all of the functionality available in the model. The GUI can be made more powerful, exposing more of the underlying functionality. The extensibility of the design is clear. What about reuse?</p>
<h3>A command-line version</h3><p><small class="notes">The examples below are in Delphi Pascal.</small></p>
<p>In a traditional prototype, command-line support is bolted on to the same application, because the required code is buried in UI structures. Such a command line application will involve something like:</p>
<div class="chart"><h3 class="chart-title">Listing 1 - Hacking the GUI Application</h3><div class="chart-body"><pre class=" "><code>if command = 'C' then begin
  { Create the main form first, so it is 
    treated as the main form by the system, then 
    hide both forms so they don't appear in front 
    of the command line. 
  }
  form:= MainForm.Create;
  form.Visible:= False;
  prefsForm:= PrefsForm.Create;
  prefsForm.Visible:= False;
  prefsForm.LoadOptions;
  form.EdtFileToUse.Text:= parameterFromCommandLine;
  form.BtnConvertClick( nil );
  form.Close; // Close main form to quit application
end;</code></pre></div></div><p>Using the elements of the model from the component-based design, we could build a separate application, whose main loop is logical and readable:</p>
<div class="chart"><h3 class="chart-title">Listing 2 - Logical and readable</h3><div class="chart-body"><pre class=" "><code>if command = 'C' then begin
  options:= ToolOptions.Create;
  options.Load;
  try
    try
      converter:= FileConverter.Create( options );
      converter.Convert( parameterFromCommandLine );
    finally
      FreeAndNil( converter );
    end;
  finally
    FreeAndNil( options );
  end;
end;</code></pre></div></div><p>The second version addresses the requirements in a much clearer, more maintainable fashion. On top of that, the implementation in the GUI application would have a similar pattern. The code above could go into an event handler, passing text from an input control instead of an argument from the command line. The following code assumes that the converter and options from the command line example above are globally available:</p>
<div class="chart"><h3 class="chart-title">Listing 3 - A clean GUI implementation</h3><div class="chart-body"><pre class=" "><code>procedure MainForm.BtnConvertClick( Sender: Object );
begin
  Converter.Convert( EdtFileToUse.Text );
end;</code></pre></div></div><h2>Conclusions</h2><p>With a small amount of time invested at the beginning, one can define any application in terms of UI-independent components. An application that was designed in this way lends itself to ready reuse. Applications that use these components need only be concerned with delivering input to a clearly defined API. Fixes and updates to the core components will be reflected in all applications.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4427</guid>
    <title><![CDATA[Encodo White Papers: Test-driven Development (2006)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4427</link>
    <pubDate>Wed, 04 Oct 2023 21:33:33 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:33:33 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Most people in the software industry have heard of test-driven development — it has become a buzzword with several possible meanings.</p>
<h2>The Problem with Unit Testing</h2><p>One of the more negative associations is the notion of unit testing. Unit testing traditionally involves writing a test for each and every routine in a unit or class, to ensure that it does what it claims. This practice has, of late, declined in popularity — mostly because of the sheer mindlessness of maintaining complete coverage of an ever-growing API.</p>
<h2>Component Testing to the rescue</h2><p>Another form of testing is to write tests for components of a system, ensuring functionality on a higher level than that of the routine. Tests of this kind tend to encapsulate use cases, which are far more closely related to the way in which clients (actual users or other software) make use of an API. Naturally, use cases for extremely low-level components will end up testing individual routines, just as unit testing does.</p>
<p>Writing the component tests is not tedious and, in fact, helps tremendously in determining whether a piece of software is complete or not. They can be viewed as software implementations of the requirements documents or specifications. Proper application of Component-based Design makes it quite simple to build tests for the majority of an application&rsquo;s functionality.</p>
<h2>Testing in the code</h2><p>A far better tool for ensuring consistency at the lowest level, where unit testing traditionally comes into play, is Design by Contract. This practice involves including verification mechanism directly in the software, so that violations of software contracts can be pinpointed and quickly repaired.</p>
<p>The most important element of any testing strategy is to stick with it. When a defect is found, the first step is to create a test to replicate the problem. The next is to fix the error so the problem no longer occurs, but all the other tests still work. Finally, any missing contracts that may have helped pinpoint the problem sooner should be added.</p>
<p>Once the test suite runs through without problems, the software is ready for release testing.</p>
<h2>The final step: Release Testing</h2><p>Automated testing is a fantastic way of guaranteeing baseline software quality, but it is not the last step before releasing a product. For server software or software with a command-line interface only, the test suite can provide an extremely high-level of coverage (approaching 100%). Software which interacts with humans, however, requires a manual testing regimen to verify that the software functions as desired for all forms of input. Whichever parts of the testing chain cannot be automated (UI testing is notoriously difficult) should be documented in detail to ensure reproducibility between releases.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4790</guid>
    <title><![CDATA[The UI is an afterthought, a detail]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4790</link>
    <pubDate>Thu, 07 Sep 2023 11:02:51 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">7. Sep 2023 11:02:51 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/3J9EJrvqOiM" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=3J9EJrvqOiM">Complexity: Divide and Conquer!</a> by <cite>Michel Weststrate</cite> on May 7, 2017 (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<blockquote class="quote quote-block "><div>&ldquo;Can we make our UI dumb enough to make our app usable without it?&rdquo;</div></blockquote><p>The video demonstrates navigating through a simple e-commerce site. Then, he shows how the app can be driven from the console by calling the APIs directly—upon which the URL and UI all update automatically. That is, the logic is not in the UI.</p>
<p>He then demonstrates that he can drive the web site <em>without a UI</em> by deleting the rendering to React DOM entirely. He can still manipulate the console API to perform the same operations because the logic is all defined completely independent of the UI. Of course, this is the same command-line interface that can be used in the automated tests, which means that the entire product can be tested without a UI at all.</p>
<p>I&rsquo;m becoming increasingly convinced that neither React nor Angular is the way to go. Both React and Angular mix logic into the UI, putting the UI front and center. This is wrong. Additionally, Angular suffers from a complete inability to speed up the development lifecycle because it&rsquo;s so strongly tied to WebPack.</p>
<p>I&rsquo;ve used Redux before and the boilerplate becomes prodigious. I&rsquo;ve used the React reducers as well, and it&rsquo;s a bit better, but still doesn&rsquo;t feel very natural. I&rsquo;ve used <a href="https://www.npmjs.com/package/mobx/v/5.13.0">MobX</a> but long before its current incarnation where it really seems to &ldquo;just work&rdquo; as a store of state and reactive programming logic.</p>
<p>The <code>when</code> construct (see <strong>16:37</strong> in the video), which takes a predicate and an action, is a very neat concept that allows you to define exactly how your application reacts to state changes without burying it all in the components.</p>
<blockquote class="quote quote-block "><div>&ldquo;If the view is to be purely derived from the state, then routing should affect state, not the derived component tree.&rdquo;</div></blockquote><p>Therefore, a url-change is an action like any other, modifying the state and letting MobX handle notifying all interested parties. Once you&rsquo;ve gotten that far, you don&rsquo;t even need a UI-specific routing library because you can just configure any router to direct URLs to the store API—which will automatically update the UI. The UI (e.g., React) doesn&rsquo;t have to have anything to do with routing. A route change triggers an action, which changes the state. The UI reacts. The UI does not do anything with the route—it just triggers actions.</p>
<p>A reactive non-UI component ensures that the route stays in-sync with the state by <em>reacting</em> to changes in the state. In most cases, you can just create a value that calculates what the URL should be, based on the state. This could get complicated, of course, but it&rsquo;s also completely separate from the rest of the application logic and can be thoroughly tested. We can also use the <code>when</code> construct outlined above to simply listen for changes to the calculated URL and update the browser&rsquo;s location and history. This way, the management of the history and URL is not entwined with the rest of the application logic. It&rsquo;s just reacting to state changes, like everything else.</p>
<p>Working like this results in automated tests that work naturally and look very much like Playwright tests—but completely without UI and using semantically meaningful constructs. The UI is an afterthought (as <a href="https://michel.codes/blogs/ui-as-an-afterthought">Michel himself wrote in 2019</a>). Playwright is nice, but it&rsquo;s a <em>last resort</em> when you&rsquo;ve already botched the job of writing your code in a more testable manner. It&rsquo;s a nice check that the UI is properly wired to the logic of the application, but should not be used to verify application behavior—simply to verify UI behavior.</p>
<p>This all goes very much in the direction of <a href="https://martinfowler.com/articles/images/humble-dialog-box/TheHumbleDialogBox.pdf">The Humble Dialog Box</a> by <cite>Martin Fowler</cite> in 2002, which shows that we&rsquo;ve known how to build software correctly for over 20 years—and we keep getting distracted by &ldquo;the new shiny&rdquo;, thinking that we can somehow start with the UI and still get maintainable software.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4771</guid>
    <title><![CDATA[On the usefulness of containers like Docker]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4771</link>
    <pubDate>Sun, 27 Aug 2023 03:32:42 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">27. Aug 2023 03:32:42 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://blog.ploeh.dk/2023/07/17/works-on-most-machines/">Works on most machines</a> by <cite>Mark Seemann</cite> (<cite><a href="http://blog.ploeh.dk/">Ploeh Blog</a></cite>) argues provocatively that containers are a fallback for poorly written software.</p>
<blockquote class="quote quote-block "><div>&ldquo;When you have general-purpose software, though, do you really need containers?&rdquo;</div></blockquote><p>Well, yes. The point isn&rsquo;t that you need a container to paper over software that isn&rsquo;t sufficiently generic: it&rsquo;s to avoid fixing incompatibilities that have nothing to do with your target deployment systems.</p>
<p>I think the author is thinking too much of highly general-purpose software whereas the majority of software doesn&rsquo;t need to run everywhere and anywhere.</p>
<p>If it&rsquo;s built for the cloud, it&rsquo;s going to run in a container anyway. If it&rsquo;s built for a specific device, it&rsquo;s going to run on that device.</p>
<p>In that case, why not just run that software at the developer side in the same environment? That way, you can avoid wasting a ton of time fixing problems that are related to how it runs in development rather than production.</p>
<blockquote class="quote quote-block "><div>&ldquo;Ultimately, you may need to query the environment about various things, but in functional programming, querying the environment is impure, so you push it to the boundary of the system. Functional programming encourages you to explicitly consider and separate impure actions from pure functions. This implies that the environment-specific code is small, cohesive, and easy to review.&rdquo;</div></blockquote><p>It implies it, but it in no way guarantees it. The author is also forgetting about the quality of the developer that is likely to be building the solution.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4771/spaghetticode.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4771/spaghetticode_tn.jpg" alt=" " class=" align-right"></a>In this post, he assumes that the developer uses enough tests to thoroughly test the system—even to the point where he is able to determine where a solution isn&rsquo;t sufficiently generalized yet. He assumes that the developer uses methodology like functional programming to separate pure from impure code, and that the developer is good enough to do all of this in a way that is both efficient and leads to a finished product.</p>
<p>This is not at all a guarantee—or even a likelihood—in the real world.</p>
<p>In the real world, developers are not reaching for the stars—even if they had the capabilities, which many do not, they&rsquo;re often not given the time to do things correctly—they are just trying to get it done.</p>
<p>If they can &ldquo;cheat&rdquo; by restricting the world of possible environments—rather than accommodating their software to environments it will never encounter in production—then why not?</p>
<p>It&rsquo;s actually an engineering problem. If you&rsquo;re going to make something that has to work well underwater, the only reason it needs to work out of water is <em>because it makes it easier to work on</em>, not because you think it&rsquo;s worth the time making it function properly when in air. If you can make it just as easy to work on underwater than you it is in air, then <em>you would just do that instead.</em> Wouldn&rsquo;t you? Why waste your time and your company&rsquo;s when there&rsquo;s a lot of other, more important work to do?</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4739</guid>
    <title><![CDATA[ImageSharp vs. SkiaSharp]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4739</link>
    <pubDate>Tue, 30 May 2023 22:04:15 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. May 2023 22:04:15 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Sep 2023 13:14:50 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I watched a great video about image-manipulation using an AWS lambda function.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/aLozGWQa2Cc" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=aLozGWQa2Cc">Working With Images Like a Pro in .NET</a> by <cite>Nick Chapsas</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>I was curious about the imaging library he was using and searched for <code>ImageProcessingContext</code> (because I saw it in his code). That led me to <em>ImageSharp</em>, after which I searched for comparisons to the cross-platform library used in <a href="https://learn.microsoft.com/en-us/dotnet/maui/">Maui</a> (<cite><a href="http://learn.microsoft.com/">MSDN</a></cite>).</p>
<p>That led me to the issue <a href="https://github.com/dotnet/Microsoft.Maui.Graphics/discussions/443">SkiaSharp vs ImageSharp</a> (<cite><a href="http://github.com/">GitHub</a></cite>), which noted that,</p>
<blockquote class="quote quote-block "><div>&ldquo;Note that JimBobSquarePants, the creator of ImageSharp, contributed some interesting discussion in #47.&rdquo;</div></blockquote><p>I read/waded through that whole issue thread and commented the following: </p>
<div class="caution ">tl;dr: Maui.Graphics uses SkiaSharp because it is a 2D-rendering library rather than just an image-manipulation library.</div><p><a href="https://www.earthli.com/data/news/attachments/entry/4739/7n78fw.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4739/7n78fw.jpg" alt=" " class=" align-right" style="width: 340px"></a>For future readers: The discussion itself is not very interesting, but the conclusion is. The title of the issue is <a href="https://github.com/dotnet/Microsoft.Maui.Graphics/issues/47">Basic premise of the library is based upon a fallacy and harms existing projects.</a> (<cite><a href="http://github.com/">GitHub</a></cite>) (referring to Maui.Graphics), which doesn&rsquo;t feel super-constructive (and wasn&rsquo;t). There are long screeds about how harmful MS is for everything OSS. The final comment is worth reading, as it explains that it turns out that the harshness of the issue title was completely unwarranted (as admitted by the original poster). Good conclusion; typically unproductive Internet discussion.</p>
<p>There is no conflict. Skia&rsquo;s support for images is weaker than ImageSharp&rsquo;s <em>but</em> it allows using GPU rendering on supported platforms whereas ImageSharp is for in-memory data (CPU-bound).</p>
<p>In the <a href="https://github.com/dotnet/Microsoft.Maui.Graphics/issues/47">referenced issue</a> itself, I commented,</p>
<blockquote class="quote quote-block "><div><p>&ldquo;That&rsquo;s wonderful. While I&rsquo;m happy to learn that the issue was resolved, is there any way that we can pin this comment to the top so that future readers don&rsquo;t have to wade through the 80% catfight in the middle?</p>
<p>&ldquo;I was linked to this issue while researching Skia vs. ImageSharp and found the initial question and a couple of responses interesting, then waded through 80% chest-thumping, then finally got to this comment that essentially says &ldquo;hey, we actually talked to each other and it turns out it was a tempest in a teapot&rdquo;, which is what I was hoping to learn.&rdquo;</p>
</div></blockquote><p>I just got a response today:</p>
<blockquote class="quote quote-block "><div>&ldquo;No way to pin comments, but I added a link to that comment from the initial issue description.&rdquo;</div></blockquote><p>Nice! 👌❤️‍🔥</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4709</guid>
    <title><![CDATA[Working with Git Submodules]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4709</link>
    <pubDate>Tue, 28 Mar 2023 22:15:01 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">28. Mar 2023 22:15:01 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <h2>Introduction</h2><p>The intended audience of this document is people interested in knowing which commands to execute to update submodules. The initial analysis section is intended for people interested in knowing how the commands work and what their strengths/weaknesses are.</p>
<p>The inspiration for this documentation was that I was wondering whether submodules were always cloned with <em>detached heads</em> and if there were some way to avoid that. The short answers to these questions are, respectively, &ldquo;yes&rdquo; and &ldquo;no&rdquo;.</p>
<p>Skip to the <a href="#useful-commands">examples below</a> to just see the commands and their effects.</p>
<p>At the end of the document are <a href="#links">links to pages</a> referenced to produce this documentation.</p>
<h2>Terminology</h2><p>In the discussion below, the term <em>superproject</em> refers to the <em>root</em> repository that contains submodule references. It comes from the git documentation where they make the distinction because submodules can be nested. Suppose, we have multiple nesting, as shown below.</p>
<pre class=" "><code>📁 A
  📁 B
    📁 C</code></pre><ul>
<li><code>A</code> is the <em>root</em> repository of both <code>B</code> and <code>C</code></li>
<li><code>A</code> is the <em>superproject</em> of <code>B</code></li>
<li><code>B</code> is the <em>superproject</em> of <code>C</code></li></ul><h2>Where do submodules go?</h2><p>Submodules are stored <em>inside</em> another repository.</p>
<p>For a simple we would see the following:</p>
<pre class=" "><code>📁 A
  📁 .git
    📁 modules
      📁 B
        📄 config (worktree = ../../../B)
  📁 B
    📄 .git (points to ../.git/modules/B)</code></pre><p>The submodule&rsquo;s <code>git</code> folder is stored in the superproject&rsquo;s <code>git</code> folder and is replaced by a file that references the new location. The submodule uses the <a href="https://www.earthli.com/Documentation/Tools/Git/Git-Trainings#session-3%3A-submodules%2C-interactive-rebase%2C-forensics">worktrees</a> feature to check out to a different folder.</p>
<h3>Can I share a local copy of a submodule?</h3><p>No. Storing the working tree of the submodule outside of the repository is not supported.</p>
<p>Why would you want to do that anyway?</p>
<p>One use case is that you have two repositories, each of which includes the same submodule, as shown below.</p>
<pre class=" "><code>📁 A
  📁 B
📁 C
  📁 B</code></pre><p>Instead of using two copies, you might think you could make the superprojects refer to the <em>same</em> copy of the submodule.</p>
<pre class=" "><code>📁 A (refers to ../B)
📁 B
📁 C (refers to ../B)</code></pre><ul>
<li>The advantage would be that changes made to <code>A</code> would immediately be available in <code>C</code></li>
<li>However, it would no longer be possible to make <code>A</code> and <code>C</code> refer to different commits</li></ul><p>Whereas you can <a href="https://stackoverflow.com/a/37151960/178874">manually move a submodule outside of the repository</a> <em>after you&rsquo;ve cloned it</em>, you cannot configure a superproject&rsquo;s submodules in a way that Git will be able to <code>clone</code> properly. If you try it, you&rsquo;ll probably get an error message like,</p>
<pre class=" "><code>fatal: No url found for submodule path 'SUBMODULE.NAME' in .gitmodules</code></pre><p>The next section explains how you can share local commits for testing.</p>
<h3>Testing submodule changes in multiple projects</h3><p>Assume, as above, that there are two copies of the submodule, B<sup>A</sup> and B<sup>C</sup>. Suppose there are commits in B<sup>A</sup> that have been tested with <code>A</code>, but should also be tested with <code>C</code>.</p>
<p>One way to test <code>C</code> would be to push the commits in B<sup>A</sup> and then pull them from B<sup>C</sup>. That involves a round-trip to the server, which is not optimal, but relatively straightforward.</p>
<p>Another way to test <code>C</code> would be to add the local B<sup>A</sup> as a <em>remote</em> to B<sup>C</sup> and then <em>check out</em> the commit from B<sup>A</sup> directly.</p>
<p>To set up a remote called <code>B_A</code> in B<sup>C</sup>, execute:</p>
<pre class=" "><code>git remote add B_A ../../A/B</code></pre><p>The testing flow would be, roughly,</p>
<ul>
<li>Test changes to submodule B<sup>A</sup> in <code>A</code></li>
<li>Create commit <code>#1</code> in B<sup>A</sup></li>
<li>Fetch from <code>B_A</code> into B<sup>C</sup></li>
<li>Check out commit <code>#1</code> in B<sup>C</sup></li>
<li>Test changes in <code>C</code></li>
<li>Repeat as needed</li></ul><h2>What to expect when cloning with submodules</h2><p>A clone of a superproject (a repository with submodules) fetches submodules only when required (e.g. when <code>–recurse-submodules</code> is included). If submodules are fetched, then git sets the checked-out commit in each submodule to the commit ID specified for that module in the superproject. This makes sense because that is the correct commit to use. However, this also means that, after a clone, all submodules will be in a <em>detached head</em> state.</p>
<p>On an initial clone, git creates a local branch in the superproject corresponding to the checked-out branch in the clone command (either the default branch or the branch specified in the <code>-b</code> option, if included). </p>
<p>Git does not create local branches in any of the submodules. Git assumes that you will be working in the root repository and not in the submodules. The checked-out branch in the submodule is irrelevant to the superproject.</p>
<p>If you want to work in (one or more of) the submodules anyway, then you have to create a local branch for yourself and check it out.</p>
<p>The <em>detached head</em> situation is not &ldquo;weird&rdquo; but &ldquo;entirely expected&rdquo; and &ldquo;working as designed&rdquo;. All <em>detached head</em> means is that a commit ID has been checked out rather than a named, local branch. </p>
<p>If, however, you want the submodule to be checked out to the same branch as that checked out in the superproject (e.g. <em>main</em>), then the way to address that is to call <code>git switch main</code> in the submodule repository.</p>
<p>This will have no effect on the superproject if the <em>main</em> branch in the submodule repository is at the same commit ID as the one pointed to by the superproject. If it is not, then switching to the <em>main</em> branch in the submodule repository will show up as a change in the superproject (the change being that the submodule repository is now pointing to a different commit). To accept that change in the superproject, simply <code>git add</code> the submodule folder and commit the change.</p>
<h2><span id="what-does-%60--remote-submodules%60-do%3F">What does <code>–remote-submodules</code> do?</span></h2><p>The <code>–remote-submodules</code> option does the following (according to the official documentation):</p>
<blockquote class="quote quote-block "><div>&ldquo;Git will use the status of the submodule&rsquo;s remote-tracking branch to update the submodule, rather than the superproject&rsquo;s recorded SHA-1 (i.e. &ldquo;commit ID&rdquo;)&rdquo;</div></blockquote><p>That means that using this parameter may cause changes in the working tree of the superproject if the remote-tracking branch in the submodule repository does not point to the same commit as that referenced by the superproject. </p>
<h3>&ldquo;Tracking&rdquo; a branch in a submodule</h3><p>The basic submodule registration looks like this in the .gitmodules file.</p>
<pre class=" "><code>[submodule "SharedRepo"]
    path = SharedRepo
    url = git@ssh.dev.azure.com:v3/ustertechnologies/uster.quantum/PoC.IMHSharedRepo</code></pre><p>If you don&rsquo;t plan on using <code>–remote-submodules</code>, then that&rsquo;s all you need.</p>
<p>However, if you want to set up your git submodules so that the superproject knows which branch it should &ldquo;track&rdquo; in the submodule, use the following configuration:</p>
<pre class=" "><code>[submodule "SharedRepo"]
    path = SharedRepo
    url = git@ssh.dev.azure.com:v3/ustertechnologies/uster.quantum/PoC.IMHSharedRepo
    branch = .
    update = rebase</code></pre><p>Note that the branch name is &ldquo;.&rdquo;. This tells git to use the same branch name as that which is checked out in the superproject (if it exists; if it doesn&rsquo;t, then git does nothing further). This allows you to set up the <code>.gitmodules</code> once and it works as expected for all branches. Otherwise, you run the risk of merging in a <code>.gitmodules</code> file that references a specific feature branch (for example) and you end up syncing with that feature branch by accident if you call submodule update with <code>–remote</code>. </p>
<p>The update action indicates how git should get to the desired commit if it needs to make a change. Again, this only applies if you explicitly tell git to use the head commit for the given branch on the remote instead of just using whichever commit is already referenced locally.</p>
<h3>A remote-update example</h3><p>A superproject will see an update if it <em>follows</em> a branch in the submodule (as outlined in the preceding section) and that branch in the submodule has gained new commits since the last time the superproject was updated (i.e. the superproject still references a commit in the submodule that does not correspond to the current <code>HEAD</code> of the branch in the submodule).</p>
<p>Using the <code>–remote-submodules</code> option is a way of cloning a superproject, but also updating its submodules to the latest commits instead of just checking out whatever is referenced in the superproject. It is a useful way of cloning a superproject with the latest commits in not only the superproject&rsquo;s repository, but also all submodules. However, you are then not only checking out the <em>current</em> state of the repository, but also requesting updates to the referenced submodules.</p>
<p>This only works if the submodule reference specifies a branch, though. If it doesn&rsquo;t, then git has no way of knowing which branch in the submodule repository it should update to. As noted above, setting this branch doesn&rsquo;t mean that git will create a local branch in the submodule with that name and check it out; it just means that it will change the commit ID referenced by the superproject for that submodule if the commit referenced by that branch in the submodule is different than the commit currently referenced by the superproject.</p>
<p>Phew! We now know enough to determine the commands to use.</p>
<h2><span id="useful-commands">Useful Commands</span></h2><p>We now have the base knowledge to work with git and submodules using the command line. This will be useful for e.g. setting up agents.</p>
<p>Imagine we have two repositories</p>
<ul>
<li>Repository <em>A</em> has a <em>main</em> branch that tracks the <em>main</em> branch of submodule <em>B</em> (currently commit <em>ID1</em>)</li>
<li>The <em>main</em> branch in <em>B</em> points to commit <em>ID1</em></li>
<li>Repository <em>A</em> has a <em>feature/setup</em> branch that tracks the <em>feature/setup</em> branch of submodule <em>B</em> (currently commit <em>ID2</em>)</li></ul><p>The examples will use something like the following diagram to show results. The bold indicates the commit and branch that are checked out. A bold commit with a non-bold branch name indicates a <em>detached head</em>.</p>
<p>The diagram below shows the situation outlined above, with <em>main</em> checked out. </p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4709/original.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4709/original.jpg" alt=" " style="width: 495px"></a></p>
<h3>Clone with submodules</h3><p>To clone a repository with submodules and check out the default branch in the superproject, execute the following:</p>
<pre class=" "><code>git clone –recurse-submodules &lt;URL&gt;</code></pre><p>This results in:</p>
<ul>
<li>The superproject is cloned and checked out to the default branch</li>
<li>Each submodule is cloned and checked out to the commit referenced in the respective submodule definition</li>
<li>Submodules are in <em>detached head</em> state because git does not create local branches in submodules</li></ul><p>Using the example from the start of this section, after executing this command, we will see:</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4709/clone_with_submodules.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4709/clone_with_submodules.jpg" alt=" " style="width: 495px"></a></p>
<p>No change from the example is expected.</p>
<h3>Clone with submodules (and check out a branch)</h3><p>To do the same as above, but check out a particular branch, execute the following:</p>
<pre class=" "><code>git clone -b feature/setup –recurse-submodules &lt;URL&gt;</code></pre><p>This results in the same as above, but the superproject is checked out to &ldquo;feature/setup&rdquo;. Using the example from the start of this section, after executing this command, we will see:</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4709/clone_with_submodules_and_check_out_branch.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4709/clone_with_submodules_and_check_out_branch.jpg" alt=" " style="width: 431px"></a></p>
<h3>Update submodules after cloning</h3><p>To update submodules after an initial clone (not necessary immediately after a clone, of course), execute the following:</p>
<pre class=" "><code>git submodule update</code></pre><p>This results in:</p>
<ul>
<li>No changes to the superproject</li>
<li>Missing submodules are cloned</li>
<li>All submodules are checked out to the commit referenced in the respective submodule definition</li></ul><p>Submodules where a change to the checked-out commit is required are in detached head state. If no change is made, then the submodule remains at which detached commit or branch was previously checked out</p>
<p>As with an initial clone, this command <em>does not</em> update any references to submodule commits.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4709/clone_with_submodules.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4709/clone_with_submodules.jpg" alt=" " style="width: 495px"></a></p>
<h3>Clone with submodules and update remote references</h3><p>To not only clone a superproject and all of its submodules, but to also update references to those submodule&rsquo;s latest HEADs (as outlined in the <a href="#what-does-%60--remote-submodules%60-do%3F">remote-submodules section</a> above), execute the following:</p>
<pre class=" "><code>git clone –recurse-submodules –remote-submodules &lt;URL&gt;</code></pre><p>This results in:</p>
<ul>
<li>The superproject is cloned and checked out to the default branch</li>
<li>Each submodule is cloned and checked out to the latest commit on the branch referenced in the respective submodule definition</li>
<li>Submodules are in <em>detached head</em> state because git does not create local branches in submodules</li></ul><p>If, for example, the remote branch <em>main</em> in repository <em>B</em> had been updated to <em>BID2</em>, then the reference from <em>A</em> to <em>B</em> would also have been updated to <em>BID2</em>:</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4709/clone_with_submodules_and_update_references.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4709/clone_with_submodules_and_update_references.jpg" alt=" " style="width: 433px"></a></p>
<h3>Update submodules to remote references</h3><p>To update submodules after an initial clone <em>and</em> update references (as outlined in the <a href="#what-does-%60--remote-submodules%60-do%3F">remote-submodules section</a> above), execute the following:</p>
<pre class=" "><code>git submodule update –remote</code></pre><p>This results in:</p>
<ul>
<li>No changes to the superproject</li>
<li>Missing submodules are cloned</li>
<li>All submodules are checked out to the latest commit on the branch referenced in the respective submodule definition</li>
<li>Submodules where a change to the checked-out commit is required are in detached head state. If no change was made (i.e. the remote commit for that branch in the submodule is still the same commit as that referenced by the superproject), then the submodule remains either with a detached commit or whichever branch was already checked out</li></ul><p>As when calling clone with <code>–remote-submodules</code>, this command updates submodule references. Therefore, if the remote branch <em>main</em> in repository <em>B</em> had been updated to <em>ID3</em>, then we would expect to see <em>A</em> referencing that commit in <em>B</em>.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4709/clone_with_submodules_and_update_references.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4709/clone_with_submodules_and_update_references.jpg" alt=" " style="width: 433px"></a></p>
<h2><span id="links">Links</span></h2><p>The following links were helpful in writing this documentation:</p>
<ul>
<li><a href="https://stackoverflow.com/questions/18770545/why-is-my-git-submodule-head-detached-from-master">Why is my Git Submodule HEAD detached from master?</a></li>
<li><a href="https://stackoverflow.com/questions/20794979/git-submodule-is-in-detached-head-state-after-cloning-and-submodule-update">Git submodule is in &ldquo;detached head&rdquo; state after cloning and submodule update</a></li>
<li><a href="https://stackoverflow.com/questions/3965676/why-did-my-git-repo-enter-a-detached-head-state">Why did my Git repo enter a detached HEAD state?</a></li>
<li><a href="https://stackoverflow.com/questions/1777854/how-can-i-specify-a-branch-tag-when-adding-a-git-submodule">How can I specify a branch/tag when adding a Git submodule?</a></li>
<li><a href="https://git-scm.com/docs/git-clone">git clone</a></li>
<li><a href="https://git-scm.com/docs/git-submodule">git submodule</a></li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4705</guid>
    <title><![CDATA[Extracting subtitles from an mkv with ffmpeg]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4705</link>
    <pubDate>Fri, 17 Mar 2023 07:22:46 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Mar 2023 07:22:46 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I&rsquo;d watched an excellent movie [1] that was primarily in German but had some English parts, with hard-coded English subtitles and soft German subtitles plastered on top of that. I wanted to cite a bunch of interesting sections, so I looked for the subtitles online. Only the English subtitles are available, which I didn&rsquo;t want. I liked the German formulation and wanted to cite that.</p>
<p>Well, I have the subtitles: they&rsquo;re just trapped in the <code>mkv</code> file. I figured that there was some way of extracting them, but a search turned up a lot of pre-compiled and sketchy-looking software whose veracity I couldn&rsquo;t adequately validate. I want the subtitles, but I don&rsquo;t want to get a virus or crypto-locked.</p>
<p>I got a good hint to use <code>ffmpeg</code> from <a href="https://www.reddit.com/r/PleX/comments/eqxfmf/how_to_extract_srt_files_from_mkv_file/ff12htd/">How to Extract .SRT Files From MKV File</a> (<cite><a href="http://www.reddit.com/">Reddit</a></cite>). It suggested something like,</p>
<pre class=" "><code>ffmpeg -i FILENAME.mkv -map 0:s:0 german.srt</code></pre><p>Once I&rsquo;d installed <code>ffmpeg</code> with <a href="https://brew.sh/">Homebrew</a>, I was able to extract a subtitle stream. Unfortunately, it was kind of short, so I&rsquo;d grabbed the wrong stream.</p>
<p>Part of the output of the command above is a list of available streams, shown below.</p>
<pre class=" ">Stream #0:0: Video: h264 (Main), … (default)
    Metadata:
      DURATION        : 01:25:55.332000000
  Stream #0:1(ger): Audio: aac (LC), 48000 Hz, stereo, fltp (default)
    Metadata:
      title           : Stereo
      DURATION        : 01:25:55.285000000
  Stream #0:2(ger): Subtitle: ass
    Metadata:
      title           : German forced
      DURATION        : 01:03:24.130000000
  Stream #0:3(ger): Subtitle: ass
    Metadata:
      title           : German
      DURATION        : 01:25:43.890000000
  Stream #0:4(ger): Subtitle: ass
    Metadata:
      title           : German SDH
      DURATION        : 01:25:43.890000000</pre><p>The <a href="https://ffmpeg.org/ffmpeg.html#Stream-selection"><code>ffmepg</code> documentation</a> isn&rsquo;t particularly illuminating on the <code>-map</code> option, but I finally figured out that the parameter is something like:</p>
<ol>
<li>The first position seems to be the file selector (you can specify multiple inputs with multiple <code>-i</code> options</li>
<li>The second position seems to select the <em>type</em> of stream, where <code>s</code> indicates subtitles (I intuit this because it looks like <code>p</code> indicates <em>programs</em>, according to <a href="https://stackoverflow.com/questions/35667457/ffmpeg-how-to-chose-a-stream-from-all-stream">FFMPEG: How to chose a stream from all stream</a> [sic])</li>
<li>The third position selects the index of the stream within that <em>type</em></li></ol><p>Armed with this information, I was able to select the second subtitle stream, which is the full German subtitles rather than just the German subtitles for the English parts.</p>
<pre class=" "><code>ffmpeg -i FILENAME.mkv -map 0:s:1 german.srt</code></pre><p>This gave me the desired subtitles in seconds.</p>
<p>Happily, I have what I want and I didn&rsquo;t have to install any sketchy tools that were installed in an unvetted binary. Instead, I&rsquo;m comfortable installing the well-known tool <code>ffmpeg</code> using the well-known package manager <code>brew</code>.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4705_1_body" class="footnote-number">[1]</span> The movie was <a href="https://www.imdb.com/title/tt11664272/?ref_=fn_al_tt_1">Oeconomia</a> (<cite><a href="http://www.imdb.com/">IMDb</a></cite>), which is, honestly, must-see viewing for everyone. Every single person should see this movie, to learn how the macro-level economy really works and how we&rsquo;re being used.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4655</guid>
    <title><![CDATA[You're already testing; now automate it.]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4655</link>
    <pubDate>Sun, 05 Mar 2023 21:23:29 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">5. Mar 2023 21:23:29 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">3. Oct 2025 06:45:54 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <h2>Introduction</h2><p>Testing is any form of validation that verifies a product. That includes not only structured validation using checklists, test plans, etc. but also informal testing, as when engineers click their way through a UI, emit values in debugging output to a console, or perform operations on hardware.</p>
<p><em>Automated testing</em> is common for software, as regression-style tests that execute both locally and in CI. This includes unit, integration, and end-to-end tests.</p>
<p>The following discussion focuses primarily on <em>software-testing</em> but hopefully contains some insights and information relevant to other engineering disciplines (e.g., embedded and hardware developers).</p>
<h2>The testing mindset</h2><p>Testing is primarily a mindset.</p>
<p>Thinking about what you&rsquo;re building in the terms outlined above can help you to determine how and what you&rsquo;re actually going to build. It will help you focus,</p>
<ul>
<li>going from &ldquo;this would be a nice feature&rdquo; 🤩</li>
<li>to &ldquo;how would I test it?&rdquo; 🤨</li>
<li>to &ldquo;who would actually use it?&rdquo; 🙄</li>
<li>to, perhaps, &ldquo;it would be neat, but no-one needs it. It&rsquo;s not a requirement.&rdquo; ✋</li>
<li>or, &ldquo;the use case is clear and here is how I would test it.&rdquo; 👌</li></ul><p>You should think of writing tests not as something you <em>have</em> to do, but rather as something you <em>want</em> to do.</p>
<ul>
<li>How else do you prove that what you&rsquo;ve made actually works?</li>
<li>What does <em>&ldquo;it works&rdquo;</em> mean?</li>
<li>Which <em>use cases</em> are covered?</li>
<li>How do you answer these questions without tests?</li>
<li>What do we mean by <em>writing</em> tests?</li></ul><p>Let&rsquo;s define some of this jargon—use cases? &ldquo;it works&rdquo;, etc.—before we continue.</p>
<h2>Why do we test?</h2><p>It&rsquo;s a bit of a provocative question, perhaps, but it makes sense to ask about anything into which you&rsquo;re going to invest time and money.</p>
<p>So, let&rsquo;s start a bit further back.</p>
<p>❓ What would we like to do?</p>
<blockquote class="quote quote-block "><div>&ldquo;We would like to build a <em>product</em> of high <em>quality</em>&rdquo;</div></blockquote><p>❓ What&rsquo;s a product?</p>
<blockquote class="quote quote-block "><div>&ldquo;A <em>product</em> is an implementation of a set of <em>requirements</em>.&rdquo;</div></blockquote><p>❓ Then what&rsquo;s a requirement?</p>
<blockquote class="quote quote-block "><div>&ldquo;A <em>requirement</em> is a collection of <em>use cases</em>.&rdquo;</div></blockquote><p>❓ OK, fine. What&rsquo;s a use case?</p>
<blockquote class="quote quote-block "><div>&ldquo;A <em>use case</em> comprises a set of initial conditions, an action, a set of inputs, and an expected output.&rdquo;</div></blockquote><p>❓ What is quality?</p>
<blockquote class="quote quote-block "><div>&ldquo;A product that satisfies its <em>requirements</em> is of higher <em>quality</em> than one that does not.&rdquo;</div></blockquote><p>❓ How can I know that my product has the desired quality?</p>
<blockquote class="quote quote-block "><div>&ldquo;We <em>test</em> <em>use cases</em> for a version of a <em>product</em> to determine <em>quality</em>.&rdquo;</div></blockquote><p>❓ How can I know when my product has enough tests?</p>
<blockquote class="quote quote-block "><div>&ldquo;When all of the <em>use cases</em> are <em>covered</em>.&rdquo;</div></blockquote><p>❓ What if I change the product after I&rsquo;ve tested it?</p>
<blockquote class="quote quote-block "><div>&ldquo;Then you have to test all of the use cases again.&rdquo;</div></blockquote><p>❗ What the heck? That&rsquo;s boring! I don&rsquo;t have time for that!</p>
<blockquote class="quote quote-block "><div>&ldquo;It&rsquo;s called regression-testing. There&rsquo;s no way around it.&rdquo;</div></blockquote><p>❓ What if I know that I&rsquo;ve only changed a tiny thing?</p>
<blockquote class="quote quote-block "><div>&ldquo;You might be able to get away with it. But that&rsquo;s where 🕷 <em>bugs</em> come from.&rdquo;</div></blockquote><p>❗ I can&rsquo;t afford to test everything manually every time I make a change!</p>
<blockquote class="quote quote-block "><div>&ldquo; That&rsquo;s why you automate as many tests as you can.&rdquo;</div></blockquote><p>❗ Running the tests ties up my local machine! I can&rsquo;t work.</p>
<blockquote class="quote quote-block "><div>&ldquo;Run tests in another environment (e.g., in the cloud)&rdquo;</div></blockquote><h3>Conclusions</h3><ul>
<li>A <em>product of quality</em> includes <em>tests</em>.</li>
<li>A <em>product</em> is considered <em>untested</em> if it has changed since it was last <em>tested</em>.</li>
<li><em>Regression-testing</em> is unavoidable.</li>
<li>Automated tests improve <em>efficiency</em> and <em>reliability</em></li>
<li>Using a separate environment improves <em>robustness</em></li></ul><h2>Introduction to methodologies</h2><p>We&rsquo;ve established both that testing is a mindset and that it is necessary to building high-quality products.</p>
<p>We should keep in mind that the <em>goal</em> is to have a well-tested product with as many of these tests as possible being automated. The question is: how close to the goal state do you stay <em>during development?</em></p>
<h3>Developer feedback loop</h3><p>In other words, what does the development-feedback loop look like?</p>
<p>The goal of the development-feedback loop is to shorten the time between a change and its verification. In practice, this often manifests as &ldquo;knowing as soon as possible when you&rsquo;ve broken something.&rdquo; The longer it takes from change to verification, the more likely it is that multiple changes will be verified at once. Root-cause analysis becomes more difficult.</p>
<p>That&rsquo;s why manual tests are undesirable: they are far less likely to be run/applied in a timely manner, increasing the number of changes that have occurred since the last time tests were run.</p>
<p>So, the longer you wait to define tests, the longer your product remains untested. The longer you wait to <em>automate</em> tests, the longer you must do manual testing to verify behavior.</p>
<p>With that idea in mind, let&rsquo;s consider the spectrum of methodologies. At one end, there&rsquo;s <a href="https://en.wikipedia.org/wiki/Test-driven&lt;i">development&rdquo;&gt;TDD</a>, where you write the tests <em>first</em>, letting them fail and <em>then</em> writing the implementation. At the other, there&rsquo;s writing all of your acceptance tests once you&rsquo;ve finished the product.</p>
<h4>Test-driven Design</h4><p>Always writing the tests first is just one extreme, and one that scares a lot of people away from automated testing. As with any dogma, strict adherence is unlikely to be efficient.</p>
<p>Sometimes, you&rsquo;ll need to try out an implementation to see if it&rsquo;s even feasible or want to play with an API to see how it feels before you write a ton of tests for it. You don&rsquo;t want to go too long without testing that you haven&rsquo;t broken something, but you also don&rsquo;t want to write tests for code that you&rsquo;re going to throw away in an hour anyway.</p>
<p>Tests are only one part of the array of techniques a developer can use to verify a product. As discussed in more detail below, a strong type system, linting, and static-code analysis of all kinds help verify a product.</p>
<p>We should always be aware of which parts are necessary <em>during which phases</em>. If certain tools take longer to verify code, consider whether they need to be executed all the time, or perhaps just when pushing to a remote, or before merging into the master branch.</p>
<h4>Acceptance-tests at the end</h4><p>If you wait until you&rsquo;ve finished the product to write all of your tests, you will still have a well-tested product, but you will not have benefited from testing during development.</p>
<p>Being able to test as you go improves your efficiency tremendously, as you&rsquo;re not constantly fighting with things that are mysteriously breaking. Instead, you&rsquo;re usually able to pin the blame on <em>the most recent change you&rsquo;ve made.</em></p>
<p>A product of nontrivial complexity can be written more reliably and quickly if there are tests. It also becomes possible for one team member to write the tests while another provides the implementation that satisfies it.</p>
<h4>A balanced approach</h4><p>The spectrum in between is where most developers live, writing tests as they go, but not always <em>before</em> they&rsquo;ve implemented something.</p>
<p>It&rsquo;s understandable that there will always be certain tests that are difficult, if not impossible to automate. However, the document that follows will provide some tools for extracting the testable bits from the untestable ones to increase <em>coverage</em>. Anything that can be tested automatically can be executed by all team members all the time, as well by pipelines in the cloud.</p>
<h2>You&rsquo;re already testing!</h2><p>You&rsquo;re almost certainly already testing.</p>
<p>You might be clicking through the UI or emitting statements in a command-line application, but you&rsquo;re verifying your code <em>somehow</em>. I mean … you are, right? RIGHT?</p>
<p>I&rsquo;m kidding. Of course you&rsquo;re not just writing code, building it, and committing it. You&rsquo;re validating it somehow.</p>
<p>That&rsquo;s testing.</p>
<h3>A list of validations</h3><p>If you&rsquo;re really good, you might even keep a list of these validations. Once you have a list, then,</p>
<ol>
<li>You don&rsquo;t have to worry about forgetting to do them in the future</li>
<li>Even someone with no knowledge of the system can perform validation</li></ol><p>This is fine, but it&rsquo;s still a manual process. A manual process carries with it the following drawbacks:</p>
<ol>
<li>It gets quite time-consuming, especially as the list of validations grows
<li><div>You&rsquo;re highly unlikely to perform the validations often enough<ul>
<li>It&rsquo;s much easier to fix a mistake if you learn about it relatively soon after you made it</li></ul></div></li>
<li><div>You&rsquo;re also unlikely to add <em>all</em> of the validations you need<ul>
<li>Generally, you won&rsquo;t validate smaller &ldquo;facts&rdquo; and will focus on high-level stuff</li></ul></div>You&rsquo;re much more likely to make mistakes in manual testing</li>
<li>A manual validation process can&rsquo;t be run as part of CI or CD</li></ol><h3>Automating the list</h3><p>Automated testing means that you <em>codify</em> those validations.</p>
<div class="caution ">😒 Great! I have tests! How the heck do I <em>codify</em> them?</div><p>Don&rsquo;t panic. Almost any code can be tested. In fact, if you can&rsquo;t get at it with a test, then you might have found an architectural problem.</p>
<p>See? Automating tests will even help you write better code!</p>
<div class="caution ">🤨 How do I get started?</div><p>Just start somewhere. It doesn&rsquo;t matter where. Don&rsquo;t worry about coverage. Just get the feeling for writing a proof about a facet of your code. Any bit of logic can—and should—be tested.</p>
<p>What if you still don&rsquo;t know where to begin? Ask someone for help! Don&rsquo;t be shy. It&rsquo;s in everyone&rsquo;s best interest for a project to have good tests. You want everyone&rsquo;s code to have tests so you know <em>right away</em> when you&rsquo;ve broken something in a completely unrelated area. This is a good thing!</p>
<h2>Goals</h2><div class="caution ">🤸‍♀️ Developers should be excited to use tests to prove that their code works.</div><h3>Tests should be quick and easy (maybe even fun) to write</h3><p>A project should provide support for mocking devices and external APIs, or for using test-specific datasets.</p>
<h3>Tests should be reasonably fast</h3><p>A reasonably fast test suite will tend to be run more often. We would like a developer to notice a broken test right after the change that broke it, preferably even before pushing it.</p>
<h3>Avoid debugging tests in CI</h3><p>Tests a developer runs locally should almost always work in CI. Failing tests in CI should also fail locally.</p>
<h2>Guidelines</h2><div class="caution ">🤨 Don&rsquo;t be pedantic.</div><p>For example,</p>
<ul>
<li><div>Don&rsquo;t get obsessed with automating <em>everything</em>.<ul>
<li>Get the low-hanging fruit first, and leave the rest to manual testing.</li>
<li>See where you stand.</li>
<li>If you haven&rsquo;t automated enough, iterate until done. 🔄</li></ul></div></li>
<li><div>Don&rsquo;t forbid mocking in integration tests and don&rsquo;t force mocking in unit tests.<ul>
<li>In fact, stop worrying about whether it&rsquo;s a unit or an integration and just <em>write useful tests</em> that <em>prove useful things</em> about your code.</li></ul></div></li>
<li><a href="https://stackoverflow.blog/2022/11/03/multiple-assertions-per-test-are-fine/">Stop requiring only one assertion per unit test: Multiple assertions are fine</a></li></ul><h3>Figure out where you stand</h3><p>The following questions should help you evaluate for yourself where you are on your automated-testing journey.</p>
<ul>
<li>How much automated testing have you done?</li>
<li>Do you write automated tests now?</li>
<li>Do you feel confident that you can verify your work with automated tests?</li>
<li>Do you understand the limitations?</li>
<li>Do you understand how system architecture can affect testability?</li></ul><h3>Tests should be useful</h3><p>We never want anyone in a team to get the impression that we&rsquo;re writing tests just to write tests. We write tests because they help us write better code and because it feels good to be able to prove that something that was working continues to work. You should feel more efficient and productive and feel like you&rsquo;re producing higher-quality code.</p>
<ul>
<li>Tests should confirm use cases</li>
<li>Tests should prove something about your code that you think is worth proving.</li>
<li>Tests should confirm behavior that either is how the code <em>currently</em> works or how it <em>should</em> work.</li>
<li>Tests should help you write better code from the get-go.</li>
<li>Every bug that you need to fix is de-facto a use case that needs a test.</li></ul><h3>Code Coverage &amp; Reviews</h3><p>How do you know when there are &ldquo;enough&rdquo; automated tests?</p>
<p>Don&rsquo;t get distracted by trying to achieve a specific coverage percentage. The most important thing is that the major use cases are covered.</p>
<p>If software is stable and there is &ldquo;only&rdquo; 40% test-coverage, then maybe there is a lot of code that rarely or never gets used? In that case, you might want to think about removing code that you don&rsquo;t need rather than to waste time writing tests for code that never runs.</p>
<p>New code, though, should always have automated tests. A <strong>code reviewer</strong> should verify that new functionality is being tested.</p>
<h2>Types of tests</h2><dl><dt class="field">Unit</dt>
<dd><div class=" "><p>Cover a single unit, mocking away other dependencies where needed.<br>
    <br>
    Useful for verifying simple logic like calculated properties or verifying the results of service methods with given inputs.<br>
  </p>
</div></dd>
<dt class="field">Integration</dt>
<dd><div class=" "><p>Cover multiple units, possibly mocking unwanted dependencies<br>
  <br>
  Useful for verifying behavior of units in composition, as they will be used in the end product. The goal is to cover as much as possible without resorting to more costly end-to-end tests<br>
  </p>
</div></dd>
<dt class="field">End-to-End</dt>
<dd><div class=" "><p>Also called <em>UI Tests</em>, these tests verify the entire stack for actual customer use cases<br>
  <br>
  Very useful, but generally require more maintenance as they tend to be more fragile. Essential for verifying UI behavior not reflected in a programmatic model. Can work with snapshots (e.g. error label is in red)<br>
  </p>
</div></dd>
<dt class="field"></dt>
</dl><h2>Approach</h2><p>The article <a href="https://kentcdodds.com/blog/write-tests">Write tests. Not too many. Mostly integration.</a> describes a pragmatic approach quite well. Instead of the classic &ldquo;testing pyramid&rdquo;, it suggests a &ldquo;testing trophy&rdquo;.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4655/testing_trophy.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4655/testing_trophy.jpg" alt=" " style="width: 340px"></a></p>
<p>This style of development has the following aims:</p>
<ol>
<li>Verify as much as possible <em>statically</em>, with linting and analyzers</li>
<li>Make <em>integration tests</em> cheaper because they prove more about your system than <em>unit tests</em></li>
<li>Prove as much as possible outside of <em>end-to-end tests</em> because they&rsquo;re expensive and brittle</li></ol><h2>Analysis</h2><div class="caution ">Remember that everything you use has to work both locally and in CI.</div><h3>Static-checking</h3><p>A project should include analyzers and techniques so that the compiler helps make many tests unnecessary. For example, if you know that a parameter or result can never be <code>null</code>, then you can avoid a whole slew of tests.</p>
<p>Developers should only spend time writing tests that verify semantic aspects that can&rsquo;t be proven by the compiler.</p>
<h4>Null-reference analysis in .NET</h4><p>The .NET world provides many, many analyzers and tools to verify code quality. One of the most important things a project can do is to improve null-checking. The best way to do this is to upgrade to C# 8 or higher and enable <a href="https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references">null-reference analysis</a>. The <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/configure-language-version">default language for .NET Framework is going to stay C# 7.3</a>, but <br>
you can <a href="https://www.infoq.com/articles/CSharp-8-Framework/">enable null-reference analysis for .NET Framework</a> quite easily.</p>
<p>Another option is to use the <a href="https://www.nuget.org/packages/JetBrains.Annotations/">JetBrains Annotations NuGet package</a>, which provides attributes to indicate whether parameters or results are nullable.</p>
<p>The preferred way, though, is to use the by-now standard nullability-checking available in .NET.</p>
<p>Doing neither is not a good option, as it will be very difficult to avoid null-reference exceptions.</p>
<h3>Unit-testing</h3><p>Unit tests are very useful for validating <em>requirements</em> and <em>invariants</em> about your code.</p>
<p>These are the easiest tests to write and will generally be the first ones that you will write.</p>
<p>A requirement or an invariant may be specified in the story itself, but it can be .anything that you know about the code that&rsquo;s important. It&rsquo;s up to the developer and the reviewer(s) to determine which tests are necessary. It gets easier with experience—and it doesn&rsquo;t take long to get enough experience so that it&rsquo;s no longer so intimidating.</p>
<h4>Unit-testing example</h4><p>Just as a quick example in .NET, consider the following code,</p>
<pre class=" "><code>public bool IsDiagnosticModeRunning
{
    get =&gt; _isDiagnosticModeRunning;
    set
    {
        _isDiagnosticModeRunning = value;
        _statusManager.InstrumentState = value ? InstrumentState.DiagnosticMode : InstrumentState.Ready;
    }
}</code></pre><p>Here we see a relatively simple property with a getter and a setter. However, we also see that there is an invariant in the implementation: that the <code>_statusManager.InstrumentState</code> is synced with it.</p>
<p>Using many of the <a href="#tools-and-techniques">techniques described below</a>, we could write the following test:</p>
<pre class=" "><code>[DataRow(true, InstrumentState.DiagnosticMode)]
[DataRow(false, InstrumentState.Ready)]
[TestMethod]
public void TestIsDiagnosticModeRunning(bool running, InstrumentState expectedInstrumentState)
{
    var locator = CreateLocator();
    var instrumentControlService = locator.GetInstance&lt;IInstrumentControlService&gt;();
    var statusManager = locator.GetInstance&lt;IStatusManager&gt;();

    Assert.AreNotEqual(expectedInstrumentState, statusManager.InstrumentState);

    instrumentControlService.IsDiagnosticModeRunning = running;

    Assert.AreEqual(expectedInstrumentState, statusManager.InstrumentState);
}</code></pre><p>Here, we&rsquo;re using MSTest to create a parameterized test that,</p>
<ul>
<li>creates the IOC</li>
<li>gets the two relevant services from it</li>
<li>Verifies that the state is not already set to the expected state (in which case the test would succeed even if the tested code doesn&rsquo;t do anything)</li>
<li>Sets the property to a given value</li>
<li>Verifies that the state is correct for that value</li></ul><p>We now have code that validates two <em>facts</em> about the system. Should something change where these facts are no longer true, the tests will fail, giving the developer a chance to analyze the situation.</p>
<ul>
<li>Was the change inadvertent or deliberate?</li>
<li>Are the facts still correct? Does the test need to be updated?</li></ul><p>If you&rsquo;re addressing a bug-fix, though, you might be able to <em>prove</em> that you&rsquo;ve fixed the bug with a unit test, but it&rsquo;s also likely that you&rsquo;ll have to write an integration test instead.</p>
<h3>Integration-testing</h3><p>Unit tests have their place, but they are far too emphasized in the testing pyramid. The testing pyramid comes from a time when writing integration tests was much more difficult than it (theoretically) is today.</p>
<p>The &ldquo;theoretically&rdquo; above means that the ability to write integration tests as efficiently as unit tests is contingent on a project offering proper tools and support.</p>
<p>One common complaint about integration tests vis à vis unit tests is that they run more slowly. Another is that they take longer to develop. Ideally, a project provides support to counteract both of these tendencies.</p>
<p>To this end, then, a project should offer base and support classes that make common integration tests easy to set up and quick to execute:</p>
<ul>
<li>Interacting with a database</li>
<li>Setting up a known database schema</li>
<li>Getting to a clean dataset</li>
<li><a>Mocking</a> the database</li>
<li>Mocking other external dependencies in a project (e.g. loading configuration from an endpoint, sending emails, sending modifications to endpoints)</li></ul><p>There are many different ways to solve this problem, each with tradeoffs. For example, a project can load dependencies in Docker containers, either created and started manually (see <a href="https://josef.codes/testing-your-asp-net-core-application-using-a-real-database/">Testing your ASP.NET Core application − using a real database</a>) or even dynamically with a tool like the <a href="https://github.com/testcontainers/testcontainers-dotnet">Testcontainers NuGet package</a>.</p>
<h3>Comparing Unit and Integration tests</h3><p>A drawback to unit tests is that, while they can test an individual component well, it&rsquo;s really the big picture that we want to test. We want to test scenarios that correspond to actual use cases rather than covering theoretical call stacks. It&rsquo;s not that the second part <em>isn&rsquo;t</em> important, but that it&rsquo;s not <em>as</em> important.</p>
<p>Given limited time and resources, we would prefer to have integration tests that also cover a lot of the same code paths that we would have covered with unit tests, rather than to have unit tests, but few to no integration tests.</p>
<p>This, however, leads directly to…</p>
<p>The advantage of a unit test over an integration test is that when it fails, it&rsquo;s obvious which code failed. An integration test, by its very nature, involves multiple components. When it fails, it might not be obvious which sub-component caused the error.</p>
<p>If you find that you have integration tests failing and it takes a while to figure out what went wrong, then that&rsquo;s a sign that you should bolster your test suite with more unit tests.</p>
<p>Once an integration test fails <em>and</em> one or more unit tests fail, then you have the best of both worlds: you&rsquo;ve been made aware that you&rsquo;ve broken a use case (integration test), but you also know which precise behavior is no longer working as before (unit test).</p>
<h2>Tools and Techniques</h2><h3>Tests are Code</h3><p>Testing code is just as important as product code. Use all of the same techniques to improve code quality in testing code as your would in product code. Clean coding, good variable names, avoid copy/paste coding—all of it applies just as much to tests.</p>
<p>There are two main differences:</p>
<ul>
<li>You don&rsquo;t need to document tests</li>
<li>You don&rsquo;t have to write tests for tests. :-)</li></ul><h3>Writing testable code</h3><p>This is a big, big topic, of course. There are a few guidelines that make it easier to write tests—or to avoid having to write tests at all.</p>
<p>As noted above, code that can be validated by the compiler (static analysis) doesn&rsquo;t need tests. E.g. you don&rsquo;t have to write a test for how your code behaves when passed a <code>null</code> parameter if you just <em>forbid it</em>. Likewise, you don&rsquo;t have to re-verify that types work as they should in statically typed languages. We can trust the compiler.</p>
<p>Here are a handful of tips.</p>
<ul>
<li>Prefer composition to inheritance</li>
<li>A functional programming style is very testable</li>
<li>An IOC Container is very helpful</li>
<li>Avoid nullable properties, results, and parameters</li>
<li>Avoid mutable data</li>
<li>Interfaces are much easier to fake or mock; use those wherever you can</li>
<li>Generally, the <a href="https://en.wikipedia.org/wiki/SOLID">SOLID</a> (<cite><a href="http://en.wikipedia.org/">Wikpedia</a></cite>) principles are a decent guide</li></ul><p>See the following articles for more ideas.</p>
<ul>
<li><a href="https://github.com/mvonballmo/CSharpHandbook/blob/master/4_design.md">C# Handbook Chapter 4: Design (2017)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=2996">Questions to consider when designing APIs: Part I (2014)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=2997">Questions to consider when designing APIs: Part II (2014)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3487">Why use an IOC? (hint: testing) (2019)</a></li></ul><h3>Parameterized Tests</h3><p>Investigate your testing library to learn how to write multiple tests without having to write a lot of code. In the MSTests framework, you can use <code>DataRow</code> to parameterize a test. In NUnit, <code>TestCase</code> does the same thing, and <code>Value</code> allows you to provide parameter values for a list of tests that are the Cartesian product of all values.</p>
<h3>Mocking/Faking</h3><p>Use mocks or fakes to exclude a subsystem from a test. What would you want to exclude? While you will want to make some tests that include database access or REST API calls, there are a lot of tests where you&rsquo;re proving a fact that doesn&rsquo;t depend on these results.</p>
<h4>Focus on what you&rsquo;re testing</h4><p>For example, suppose a component reads its configuration from the database by default. A test of that component may simply want to see how it reacts with a given input to a given method. Where the configuration came from is irrelevant to that particular test. In that case, you could mock away the component that loads the configuration from the database and instead use a fake object that just provides some standard values.</p>
<h4>Test error conditions</h4><p>Another possibility is to fake an external service to see how your code reacts when the service returns an error or an ambiguous response. Without mocks, how would you test how your code reacts when a REST endpoint returns 503 or 404? Without a mock, how would you force the purely external endpoint to give a certain code? You really can&rsquo;t. With a mock, though, you can replace the service and return a 404 response for a specific test. This is quite a powerful technique.</p>
<h4>How to fake?</h4><p>As noted above, it&rsquo;s much, much easier to use fake objects if you&rsquo;ve consistently used interfaces. You can just create your own implementation of the interface whose standard implementation you want to replace, give it a fake implementation (e.g. returning <code>false</code> and empty string and <code>null</code> for methods and properties) and then use that class as the implementation.</p>
<h4>Faking/mocking libraries</h4><p>If you have interfaces that perform a single task (single-responsibility principle), then it doesn&rsquo;t take too much effort to write the fake object by hand. However, it&rsquo;s much easier to use a library to create fake objects—and there are other benefits as well, like tracking which methods were called with which parameters. You can assert on this data collected by the fake object.</p>
<p>For .NET, a great library for faking objects is <a href="https://fakeiteasy.github.io/">FakeItEasy</a>.</p>
<p>With a fake object, you can indicate which values to return for a given set of parameters without too much effort. Similarly, you can use the same API to query how often these methods have been called. This allows you to verify, for example, that a call to a REST service <em>would have been made</em>. This is a powerful way of proving facts about your code without having to actually interact with external services.</p>
<h4>An example</h4><p>The following code configures a fake object for <code>ITestUnitConfigurationService</code> that returns default data for all properties, except for <code>Configuration</code> and <code>GetTestUnitParameterValues()</code>, which are configured to return specific data.</p>
<pre class=" "><code>private static ITestUnitConfigurationService CreateFakeTestUnitConfigurationService()
{
    var result = A.Fake&lt;ITestUnitConfigurationService&gt;();

    var testUnitParameters = CreateTestUnitParameters();
    var testUnitConfiguration = new TestUnitConfiguration(testUnitParameters);

    A.CallTo(() =&gt; result.Configuration).Returns(testUnitConfiguration);

    var testUnitParameterValues = CreateTestUnitParameterValues();

    A.CallTo(() =&gt; result.GetTestUnitParameterValues()).Returns(testUnitParameterValues);

    return result;
}</code></pre><p>In the test, we could get this fake object back out of the IOC (for example) and then verify that certain methods have been called the expected number of times.</p>
<pre class=" "><code>var testUnitConfigurationService = locator.GetInstance&lt;ITestUnitConfigurationService&gt;();

A.CallTo(() =&gt; testUnitConfigurationService.Configuration).MustHaveHappenedOnceExactly();
A.CallTo(() =&gt; testUnitConfigurationService.GetTestUnitParameterValues()).MustHaveHappenedOnceExactly();</code></pre><h3>Snapshot-testing</h3><p>You can avoid writing a ton of assertions and a ton of tests with snapshot testing.</p>
<p>For example, imagine you have a test that generates a particular view model. You want to verify 30 different parts of this complex model.</p>
<p>You <em>could</em> navigate the data structure, asserting the 30 values individually.</p>
<p>That would be pretty tedious, though, and lead to fragile and hard-to-maintain testing code.</p>
<p>Instead, you could emit that structure as text and save it as a <em>snapshot</em> in the repository. If a future code change leads to a different snapshot, the test fails and the developer that caused the failure would have to approve the new snapshot (if it&rsquo;s an expected or innocuous change) or fix the code (if it was inadvertent and wrong).</p>
<p>The upside is that large swaths of assertions are reduced to a simple snapshot assertion. The downside is that the test might break more often for spurious reasons. Generally, you can avoid these spurious reasons by being judicious about how your format the snapshot,</p>
<uL>
<li>Avoid timestamps or data that changes over time</li>
<li>Avoid using output methods that are too likely to change over time  </li></uL><p>See the documentation for the <a href="https://swisslife-oss.github.io/snapshooter/">Snapshooter NuGet package</a>.</p>
<h3>End-to-end Testing</h3><p>There have been many solutions to the problem of automated testing of web UIs over the years. The one many know is <a href="https://www.lambdatest.com/selenium">Selenium</a>, but tools like <a href="https://www.cypress.io/">Cypress</a>, <a href="https://testcafe.io/">TestCafe</a>, <a href="https://pptr.dev/">Puppeteer</a> and <a href="https://playwright.dev/">Playwright</a> have largely replaced it. The <a href="https://webdriver.io/">WebdriverIO</a> library </p>
<p>Before choosing a tool, you&rsquo;ll want to consider what your requirements are:</p>
<ul>
<li>Tests should run quickly</li>
<li>Headless/command-line support for integrating into CI builds</li>
<li>A GUI for running tests is a plus</li>
<li>Traceability of tests</li>
<li>Snapshot-testing</li>
<li>Debugging, including rewinding through the UI events</li></ul><p>The current front-runner for end-to-end testing is <a href="https://playwright.dev/dotnet/">Playwright</a>, an open-source cross-browser, cross-platform, cross-language testing framework.</p>
<ul>
<li>Video: <a href="https://youtu.be/jF0yA-JLQW0">What&rsquo;s new in Playwright 1.32</a> shows the new <em>UI Mode</em> in action (see the <a href="https://github.com/microsoft/playwright/releases/tag/v1.32.0">release notes</a>; screenshot below)</li>
<li>!<a href="https://www.earthli.com/.attachments/image-83c94c5b-b517-4e8b-907e-5791bb6e4cc2.png =400x">image.png</a></li>
<li>Video: <a href="https://youtu.be/sRjN-CU_Lg4">&ldquo;Playwright can do this?&rdquo; — Microsoft meetup March 2023</a> (see masking for visual regression at 00:18:00)</li>
<li><a href="https://github.com/microsoft/playwright">GitHub</a></li>
<li><a href="https://learn.microsoft.com/en-us/microsoft-edge/playwright/">Example</a></li></ul><h3>Planner / Executor Pattern</h3><p>This pattern is particularly useful when you have a bunch of <em>steps</em> to execute. Instead of executing the steps as you go, you build a <em>plan</em> that describes how those steps would be executed and return that as the result of the <em>planner</em> phase. You can test this plan very easily without worrying about how to mock away the <em>mutating</em> part of the code.</p>
<p>For example, suppose you want to sync an online data source with a local configuration. The classic way would be to do something like the following:</p>
<pre class=" "><code>var items = GetItemsFromServer();
foreach (var item in items)
{
  var itemData = GetItemDataFromServer(item);
  if (string.IsNullOrEmpty(itemData.Text))
  {
    SetStandardText(item, itemData);
    SaveItemToServer(item);
  }
}</code></pre><p>With so little logic, there&rsquo;s really no way to question this setup, is there? But think about what happens if there are more decisions to make, more data to retrieve, more data to update on the server. As this logic increases in complexity, the mutating code becomes ever more deeply embedded in read-only logic. That read-only logic ends up being the lion&rsquo;s share of the code that you want to test, but you have to step very lightly to avoid making changes on the server. You can, of course, mock away services, to make sure that nothing is communicated back to the server, but there is another way.</p>
<p>What if you were to consider the set of operations as phases?</p>
<ol>
<li>A <em>planning</em> phase where the program gathers all of the information that it needs to determine which commands to execute in order to &ldquo;repair&rdquo; the situation.</li>
<li>A much shorter and simpler <em>execution</em> phase where the program loops over the plan and applies it.</li></ol><p>This approach has several advantages:</p>
<ul>
<li>There are fewer questions about how to handle exceptions that occur while applying the plan. You don&rsquo;t have to worry about what happens when a mutation occurs deep within the planning logic.</li>
<li>It&rsquo;s easier to test the meat of the logic because the output is a plan that you can <em>snapshot</em> or otherwise verify.</li>
<li>You have the user-friendly option to present the user with a detailed plan of what will happen before applying any changes.</li>
<li>You can even store the plan to execute later, e.g., after it has been audited by a separate team.</li></ul><p>Once again, we have a pattern that not only makes testing easier, but it makes the entire architecture more robust, opening up possibilities that you wouldn&rsquo;t have with the straightforward pattern (which would be harder to test).</p>
<p>To finish up this section, let&rsquo;s take a quick look what that could look like in pseudocode.</p>
<pre class=" "><code>var items = GetItemsFromServer();
var commands = new Commands();
foreach (var item in items)
{
  var itemData = GetItemDataFromServer(item);
  if (string.IsNullOrEmpty(itemData.Text))
  {
    var command = CreateCommand(
      "Set standard text for {item}", 
      () =&gt; {
        SetStandardText(item, itemData);
        SaveItemToServer(item);
      }
    ) 
  }
}

// Present commands to the user; store the commands for later, or execute them…
// This is where tests would verify the commands generated from a given set of 
// item data.

foreach (var command in commands)
{
  try
  {
    command.Apply();
  }
  catch
  {
    // Log error and continue?
  }
}</code></pre><p>Instead of executing the command immediately, we store what we would want to do with a closure and a description. We can do whatever we want with those commands; executing this is one option, but you can see how useful it would also be for verifying that the logic is correct in tests.<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4660</guid>
    <title><![CDATA[Hiding folders in Azure DevOps Code Wikis]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4660</link>
    <pubDate>Wed, 18 Jan 2023 10:09:22 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. Jan 2023 10:09:22 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/4660/azure-devops-3628645-3029870.png"><img src="https://www.earthli.com/data/news/attachments/entry/4660/azure-devops-3628645-3029870.png" alt=" " class=" align-right" style="width: 128px"></a>It is currently not possible to hide individual folders or files in an Azure DevOps Code Wiki. Folders and files beginning with a <code>.</code> are hidden by default, but you can&rsquo;t influence the structure other than by reordering pages with a <code>.order</code> file in an individual folder.</p>
<p>The topic <a href="https://developercommunity.visualstudio.com/t/hide-folders-that-do-not-contain-markdown-files/366069">Hide folders that do not contain Markdown files</a> (<cite><a href="http://developercommunity.visualstudio.com/">Microsoft Developer Community</a></cite>) discusses extending this functionality.</p>
<p>I replied with the following:</p>
<p><hr></p>
<p>There are a lot of good suggestions here.</p>
<p>Changing the name of the folder or file in order to hide it (e.g., by prepending the name with <code>.</code>) is not a practical solution. Wikis based on, e.g., .NET solutions cannot just change the names of folders that would be empty in the Wiki.</p>
<p>Although I think that hiding empty folders by default seems like a good idea, I also understand that clicking an empty folder shows the UI that allows a user to create a page for an empty folder, so hiding that folder would also remove functionality from the online UI.</p>
<p>I think that many code-based Wikis wouldn&rsquo;t mind losing this functionality, but we probably need a top-level Code Wiki option here where you can decide whether to show or hide empty folders by default.</p>
<p>That takes care of the default behavior, which would cover a lot of use cases for &ldquo;cleaning up&rdquo; the wiki&rsquo;s structure.</p>
<p>However, if you elect <em>not</em> to hide folders by default, or if you just want to hide another file or folder, how can we support that requirement? I would suggest two mechanisms:</p>
<ul>
<li>As suggested above, a <code>.wikiignore</code> file that allows globbing à la Git would be powerful (e.g., it would allow you to ignore all <code>Properties</code> folders in all project folders in .NET solutions).</li>
<li>We could extend the <code>.order</code> file to support <code>!</code>, which would hide the folder or file from being displayed. This feature would technically also cover all use cases covered by a <code>.wikiignore</code> file, but would involve quite a bit more work to support (i.e., you would have to add a <code>.order</code> file to every <code>Properties</code> folder instead of just configuring once, in a root file).</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4657</guid>
    <title><![CDATA[Stop trying so hard to use pattern-matching]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4657</link>
    <pubDate>Sun, 15 Jan 2023 11:10:38 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Jan 2023 11:10:38 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In the article <a href="https://dateo-software.de/blog/tuples-in-csharp">Why tuples in C# are not always a code smell</a> by <cite>Dennis Fr&uuml;hauff</cite> (<cite><a href="http://dateo-software.de/">dateo. Coding Blog</a></cite>), the author writes the following code for calculating a discount.</p>
<p>The requirements are as follows:</p>
<blockquote class="quote quote-block "><div><ul>
<li>Premium customers get 20% off.</li>
<li>Gold customers get 30% off.</li>
<li>Regular customers, when they are students (&lt; 25 years), get 10% off.</li>
<li>Regular adult customers get no discount.</li>
<li>All regular customers get 15% off during happy hour (3 to 8 p.m.).</li></ul></div></blockquote><h2>The author&rsquo;s original version</h2><pre class=" "><code>public decimal CalculateDiscount(Customer customer, DateTime time)
{
    if (customer.CustomerType == CustomerType.Gold)
    {
        return 0.3m;
    }
    else if (customer.CustomerType == CustomerType.Premium)
    {
        return 0.20m;
    }
    else
    {
        if (time.Hour is &gt; 15 and &lt; 20)
        {
            return 0.15m;
        }

        if (customer.Age &lt; 25)
        {
            return 0.1m;
        }
        else
        {
            return 0m;
        }
    }

    return 0m;
}</code></pre><p>He doesn&rsquo;t like this code, and neither do I. But we have different reasons.</p>
<h2>The author&rsquo;s pattern-matching version</h2><p>The author rewrites the code above with pattern-matching, to make it <span class="quote-inline">&ldquo;pretty much look like the business rules stated above&rdquo;</span>.</p>
<p>His final version looks like this:</p>
<pre class=" "><code>public decimal CalculateDiscount(Customer customer, DateTime time)
{
    return (IsStudent(customer), IsHappyHour(time), customer.CustomerType) switch
    {
        (_,         _, CustomerType.Gold)    =&gt; 0.3m,
        (_,         _, CustomerType.Premium) =&gt; 0.2m,
        (_,      true, CustomerType.Regular) =&gt; 0.15m,
        (true,  false, CustomerType.Regular) =&gt; 0.10m,
        (false, false, CustomerType.Regular) =&gt; 0.0m
    };
}

public bool IsStudent(Customer customer) =&gt; customer.Age &lt; 25;
public bool IsHappyHour(DateTime datetime) =&gt; datetime.Hour is &gt; 15 and &lt; 20;</code></pre><p>I strongly disagree that this looks like the original business requirements. In order to figure out who gets a 15% discount, you have to figure out what the first two boolean fields of the tuple indicate, so you look at the ad-hoc-instantiated tuple (which is created only in order to pattern-match on it), where you can see from the local-method names that they indicate whether the customer is a student and whether the sale was made during happy hour, respectively.</p>
<p>I have a few issues with this version;</p>
<ul>
<li>As noted above, it is not easily legible</li>
<li>I am not sure about the allocation or efficiency of this code</li>
<li>The extra formatting required (aligning the <code>_</code> placeholders) makes it look difficult to maintain</li></ul><h2>Cleaning up the original without pattern-matching</h2><p>I would tackle this differently, and with classic means. First of all, my main problem with the original version is that it&rsquo;s made unnecessarily long and cluttered by including <code>else</code> statements after <code>returns</code>. Get rid of those and you&rsquo;ll get rid of indenting and all of a sudden, the original code looks remarkably legible. It&rsquo;s also 100% clear that there are no allocations and we don&rsquo;t have to worry our pretty heads about the efficiency of code generated for either  <code>if</code> and <code>return</code> statements or for simple comparisons.</p>
<pre class=" "><code>public decimal CalculateDiscount(Customer customer, DateTime time)
{
    if (customer.CustomerType == CustomerType.Gold)
    {
        return 0.3m;
    }
  
    if (customer.CustomerType == CustomerType.Premium)
    {
        return 0.20m;
    }

    if (time.Hour is &gt; 15 and &lt; 20)
    {
       return 0.15m;
    }

    if (customer.Age &lt; 25)
    {
       return 0.1m;
    }

    return 0m;
}</code></pre><h2>Improving semantics</h2><p>How much clearer would you like that to be? I suppose we could add some local methods to add some semantics to the comparisons.</p>
<pre class=" "><code>public decimal CalculateDiscount(Customer customer, DateTime time)
{
    if (IsLevel(CustomerType.Gold))
    {
        return 0.3m;
    }
  
    if (IsLevel(CustomerType.Premium))
    {
        return 0.20m;
    }

    if (IsHappyHour())
    {
       return 0.15m;
    }

    if (IsStudent())
    {
       return 0.1m;
    }

    return 0m;

    bool IsLevel(CustomerType customerType) =&gt; customer.CustomerType == customerType;
    bool IsStudent() =&gt; customer.Age &lt; 25;
    bool IsHappyHour() =&gt; time.Hour is &gt; 15 and &lt; 20;
}</code></pre><p>To make up for the fact that we lost all of that delicious pattern-matching and those tuples from the author&rsquo;s version, we&rsquo;re using <em>local methods</em>. Is this an improvement? Overall, I think so. The first version was already pretty good, but now we&rsquo;ve improved the semantics by taking the guesswork out of the magic numbers. The <code>IsHappyHour</code> method is definitely an improvement. The <code>IsStudent</code> also imparts more knowledge about what the magic age of 25 means. Also, we&rsquo;ve managed to separate the calculation of the rebate from the determination of the conditions that affect the rebate.</p>
<h2>Pattern-matching: take two?</h2><p>Can we do anything with pattern-matching, though? Can we use pattern-matching in a way that&rsquo;s more legible than the version proposed by the author?</p>
<p>What about this?</p>
<pre class=" "><code>public static decimal CalculateDiscount(this Customer customer, DateTime time)
{
    return (customer, time) switch
    {
        ({ CustomerType: CustomerType.Gold }, _) =&gt; 0.3m,
        ({ CustomerType: CustomerType.Premium }, _) =&gt; 0.2m,
        (_, { Hour: &gt; 15 and &lt; 20}) =&gt; 0.15m,
        ({ Age: &lt; 25 }, _) =&gt; 0.1m,
        _ =&gt; 0m
    };
}</code></pre><p>OK. That&rsquo;s not as bad as the author&rsquo;s version. It doesn&rsquo;t allocate a tuple <em>just to be able to use a tuple</em>, for starters. But is it more legible than the previous version? Not at all. We could, of course, improve the formatting to align all of the return statements, but that&rsquo;s also no fun to maintain.</p>
<p>The real issue with the pattern-matching solution is that we can no longer use local functions to improve semantics. The only thing we could do would be to add an <code>IsStudent</code> property directly to the class (<a href="https://github.com/dotnet/csharplang/discussions/5498">extension properties are still being discussed</a> (<cite><a href="http://github.com/">GitHub</a></cite>)). We cannot improve the semantics of the pattern-matching on <code>DateTime</code> because that type is not under our control.</p>
<p>In conclusion, as with anything else in programming, you should be judicious in where you use the new and shiny features, always considering whether they&rsquo;re actually helping improve your code.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4647</guid>
    <title><![CDATA[You should be using a GUI for Git]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4647</link>
    <pubDate>Wed, 11 Jan 2023 21:21:28 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Jan 2023 21:21:28 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/4647/git-icon-logo.png"><img src="https://www.earthli.com/data/news/attachments/entry/4647/git-icon-logo_tn.png" alt=" " class=" align-right"></a>I&rsquo;ve seen this <a href="https://old.reddit.com/r/git/comments/105r7wp/noob_question_does_anyone_use_things_like_git_gui/">Noob question: Does anyone use things like git gui?</a> by <cite>Collekt</cite> (<cite><a href="http://old.reddit.com/">Reddit</a></cite>) again and again.</p>
<blockquote class="quote quote-block "><div>&ldquo;Just curious as I&rsquo;m learning and getting familiar with git. Do real production teams use any kind of tools for git like &ldquo;git gui&rdquo; or others? Or does everyone just use it from command line? Thanks for any insight. :)&rdquo;</div></blockquote><p>You almost certainly have several use cases for your source control:</p>
<ul>
<li>clone/push/pull</li>
<li>commit</li>
<li>amend/squash/rebase interactive</li>
<li>merge</li>
<li>diff</li>
<li>code forensics (log/blame, cross-reference, find changes)</li>
<li>work with submodules</li></ul><p>The command-line isn&rsquo;t the most efficient or least error-prone for any of these tasks.</p>
<p>For example—something you do every day—a good GUI client will let you very quickly navigate diffs in your working tree with only a few arrow-key presses. You can&rsquo;t beat that with the command line. </p>
<p>And, once you have to <strong>merge</strong> … you&rsquo;ll want a more powerful view on things than you&rsquo;re going to get from command-line tools. Of course, it&rsquo;s <em>possible</em> to merge on the command-line! I&rsquo;m just saying it&rsquo;s more error-prone and not as efficient—especially for most developers. There are probably a couple of <a href="https://en.wikipedia.org/wiki/John_Henry_(folklore)">John Henrys</a> out there, but c&rsquo;mon.</p>
<p>It&rsquo;s great that the command-line exists! It allows us to build UIs on top of it. It allows us to integrate anything we&rsquo;d like into a headless process like CI/CD.</p>
<p>However, you&rsquo;re going to be more efficient with a good GUI. There are pros/cons to the various UIs. I&rsquo;ve landed quite firmly on <a href="https://www.syntevo.com/smartgit/">SmartGit</a> after an evaluation of all of the other tools (in no particular order: Tower, VS, VSCode, GitLens, Kraken, GitExtensions, GitHub Desktop, SourceTree, Git GUI).</p>
<p>Why an external rather than an integrated Git client?</p>
<ul>
<li>Uniformity regardless of IDE</li>
<li>Hotkeys are more intuitive (in-IDE source-control tends to end up with strange hotkeys)</li>
<li>Ability to integrate a good merging tool (e.g. BeyondCompare)</li>
<li>etc.</li></ul><p>Why an integrated rather than external Git client?</p>
<ul>
<li>inline change markers</li>
<li>inline history/blame</li>
<li>etc.</li></ul><p>You can use both, of course! Use whatever helps you be more accurate and efficient and happy.</p>
<p>Visual Studio Code&rsquo;s default source control is very limited (no code forensics to speak of), so be careful of defaulting to that one. Visual Studio is getting better all the time, though. Still feels a bit weird for me, but it&rsquo;s 10x better than it was a couple of versions ago.</p>
<p>Of course, YMMV, but please don&rsquo;t continue to believe in the myth that using a command line is somehow a requirement to being a &ldquo;real&rdquo; developer. Developers who only use the command line are probably wasting time, probably making mistakes they shouldn&rsquo;t, almost certainly missing out on powerful enhancements to their workflow.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4637</guid>
    <title><![CDATA[Terminology for CSS values]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4637</link>
    <pubDate>Sun, 11 Dec 2022 22:53:38 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Dec 2022 22:53:38 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/4637/image_(3).jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4637/image_(3)_tn.jpg" alt=" " class=" align-right"></a>The article <a href="https://www.otsukare.info/2022/10/25/css-values-definitions">&rdquo;Thousand&rdquo; Values of CSS</a> by <cite>Karl Dubost</cite> (<cite><a href="http://www.otsukare.info/">Otsukare</a></cite>) clarifies the definitions for the various types of value in CSS. While there aren&rsquo;t a <em>thousand</em> different kinds of value in CSS, there are quite a few. Each has its <em>raison d&rsquo;être</em>.</p>
<p>The article is informative, but lists the values in what I consider to be an unintuitive order. I&rsquo;ve changed the order and consolidated a bit. Each term links to the W3C documentation [1] and each definition starts with the official description, a layman&rsquo;s translation, and a simple code example.</p>
<p>Click to jump to the definition or read them in order to learn how they build on each other.</p>
<ul>
<li><a href="#initial">Initial value</a></li>
<li><a href="#declared">Declared value</a></li>
<li><a href="#cascaded">Cascaded value</a></li>
<li><a href="#specified">Specified value</a></li>
<li><a href="#computed">Computed value</a></li>
<li><a href="#used">Used value</a></li>
<li><a href="#actual">Actual value</a></li>
<li><a href="#resolved">Resolved value</a></li></ul><dl><dt><span id="initial"><a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#initial-values">Initial value</a> (<cite><a href="http://w3c.github.io/">W3C</a></cite>)</span></dt>
<dd><div class=" "><blockquote class="quote quote-block "><div>&ldquo;Each property has an <em>initial value</em>, defined in the property’s definition table. &rdquo;</div></blockquote><p>I.e. the initial value could also be called the default value, as defined in the specification.</p>
<pre class=" "><code>p {
  <strong class="highlight">/* the initial value of <code>color</code> is <code>black</code> */</strong>
}</code></pre></div></dd>
<dt><span id="declared"><a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#declared">Declared value</a> (<cite><a href="http://w3c.github.io/">W3C</a></cite>)</span></dt>
<dd><div class=" "><blockquote class="quote quote-block "><div>&ldquo;Each property declaration applied to an element contributes a <em>declared value</em> for that property associated with the element.&rdquo;</div></blockquote><p>I.e. the declared value is the one that you&rsquo;ve directly assigned to a property in a CSS element.</p>
<pre class=" "><code>p {
  color: red; <strong class="highlight">/* declared value is <code>red</code> */</strong>
}</code></pre></div></dd>
<dt><span id="cascaded"><a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#cascaded">Cascaded value</a> (<cite><a href="http://w3c.github.io/">W3C</a></cite>)</span></dt>
<dd><div class=" "><blockquote class="quote quote-block "><div>&ldquo;The <em>cascaded value</em> represents the result of the cascade: it is the declared value that wins the cascade (is sorted first in the output of the cascade). If the output of the cascade is an empty list, there is no cascaded value.&rdquo;</div></blockquote><p>I.e. the cascaded value is the declared value that sorts first in the list generated by the  cascade of declared values that apply to that element.</p>
<pre class=" "><code>p {
  color: red; <strong class="highlight">/* declared value is <code>red</code> */</strong>
}

p {
  color: green; <strong class="highlight">/* declared and cascaded value is <code>green</code> */</strong>
}</code></pre></div></dd>
<dt><span id="specified"><a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#specified">Specified value</a> (<cite><a href="http://w3c.github.io/">W3C</a></cite>)</span></dt>
<dd><div class=" "><blockquote class="quote quote-block "><div>&ldquo;The <em>specified value</em> is the value of a given property that the style sheet authors intended for that element. It is the result of putting the cascaded value through the defaulting processes, guaranteeing that a specified value exists for every property on every element.&rdquo;</div></blockquote><p>I.e., the specified value is the cascaded value, or the default value for that property, if there are no cascaded values.</p>
<pre class=" "><code>p {
  color: red; <strong class="highlight">/* declared value is <code>red</code> */</strong>
}

p {
  color: green; <strong class="highlight">/* declared, cascaded, and selected value is <code>red</code>. */</strong>

  <strong class="highlight">/* Also, the selected value for, e.g., <code>margin-left</code> is <code>0</code>
     because that's the default, and no value was specified.  */</strong>
}</code></pre></div></dd>
<dt><span id="computed"><a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#computed">Computed value</a> (<cite><a href="http://w3c.github.io/">W3C</a></cite>)</span></dt>
<dd><div class=" "><blockquote class="quote quote-block "><div>&ldquo;The <em>computed value</em> is the result of resolving the specified value as defined in the “Computed Value” line of the property definition table, generally absolutizing it in preparation for inheritance.&rdquo;</div></blockquote><p>I.e., the computed value is the specified value, but converted to absolute units (e.g., <code>2em</code> converts to <code>32px</code> if the <code>font-size</code> is <code>16px</code>), or to a special value like <code>auto</code>.</p>
<pre class=" "><code>html {
  font-size: 16px;
}

p {
  font-size; 2em <strong class="highlight">

  /* declared, cascaded, and selected value are <code>2em</code>,
     but computed value is <code>32px</code>. */

  /* computed value of <code>width</code> is <code>auto</code> because there is no declared
     value, so the selected value is the initial value. */</strong>
}</code></pre></div></dd>
<dt><span id="used"><a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#used">Used value</a> (<cite><a href="http://w3c.github.io/">W3C</a></cite>)</span></dt>
<dd><div class=" "><blockquote class="quote quote-block "><div>&ldquo;The <em>used value</em> is the result of taking the computed value and completing any remaining calculations to make it the absolute theoretical value used in the formatting of the document.&rdquo;</div></blockquote><p>I.e., the used value is the computed value, but special values are converted based on context. E.g., a computed value of <code>width: auto</code> will have a used value of <code>width: 100px</code> if the parent container is <code>100px</code> wide.</p>
<pre class=" "><code>body {
  width: 100px;
}

p {
  width; auto <strong class="highlight">

  /* declared, cascaded, selected, and computed value are <code>2em</code>,
     but used value is <code>100px</code>. */</strong>
}</code></pre></div></dd>
<dt><span id="actual"><a href="https://w3c.github.io/csswg-drafts/css-cascade-5/#actual">Actual value</a> (<cite><a href="http://w3c.github.io/">W3C</a></cite>)</span></dt>
<dd><div class=" "><blockquote class="quote quote-block "><div>&ldquo;A used value is in principle ready to be used, but a user agent may not be able to make use of the value in a given environment. For example, a user agent may only be able to render borders with integer pixel widths and may therefore have to approximate the used width. Also, the font size of an element may need adjustment based on the availability of fonts or the value of the <code>font-size-adjust</code> property. The <em>actual value</em> is the used value after any such adjustments have been made.&rdquo;</div></blockquote><p>I.e., the actual value is the used value, but adjusted as necessary for the output device.</p>
<pre class=" "><code>p {
  border-width: 1.1px; <strong class="highlight">

  /* declared, cascaded, selected, computed, and used value 
     are <code>1.1px</code>, but actual value is <code>1px</code>. */</strong>
}</code></pre></div></dd>
<dt><span id="resolved"><a href="https://w3c.github.io/csswg-drafts/cssom-1/#resolved-values">Resolved value</a> (<cite><a href="http://w3c.github.io/">W3C</a></cite>)</span></dt>
<dd><div class=" "><p>Despited the name, the value returned by the <code><a href="https://w3c.github.io/csswg-drafts/cssom-1/#dom-window-getcomputedstyle">getComputedStyle()</a></code> method will be either the computed or the used value, depending on the type of property. The result of this method is called the <em>resolved value</em>.</p>
<pre class=" "><code>body {
  width: 100px;
}

p {
  width; auto
}</code></pre><pre class=" "><code>const p = document.querySelector('p')[0];
const <strong class="highlight">resolvedValue</strong> = window.getComputedStyle(p).width;

<strong class="highlight">/* resolvedValue == 100px */</strong></code></pre></div></dd>
</dl><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4637_1_body" class="footnote-number">[1]</span> The W3C documentation lists the terms in the intuitive order, but is quite extensive and technical. The summary in this article is, I hope, easier to understand.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4622</guid>
    <title><![CDATA[How to evaluate dependencies]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4622</link>
    <pubDate>Sun, 04 Dec 2022 22:11:39 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Dec 2022 22:11:39 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>As software developers, we are constantly making the decision between <em>make</em> or <em>buy</em>.</p>
<p>Deciding to <em>make</em> something carries with it the obligation to design, develop, test, document, and support it. You&rsquo;ll have everything under your control, but you&rsquo;ll also have to do everything yourself.</p>
<p>If a component is not part of your project&rsquo;s <em>core functionality</em>, then it&rsquo;s often a good idea to look around and see if you can find someone who&rsquo;s already built that functionality. Optimally, the component you find will be free and open-source and will have been built by a team whose aim was to provide exactly that functionality.</p>
<p>Because they&rsquo;ve focused on <em>their</em> task, it&rsquo;s more likely to be a robust solution to your problem that what you would write yourself (focused, as you hopefully are, on <em>your</em> task). Their solution might go a bit too far (see &ldquo;Size/Focus&rdquo;), but that might be fine too (see &ldquo;Extensibility&rdquo;).</p>
<p><em>Is</em> the component good, though? What do we mean by &ldquo;good&rdquo;? How can we tell? How do we go about sizing up a dependency?</p>
<h2>Facets</h2><p>The following table outlines various facets to consider.</p>
<h2>Legal</h2><dl><dt class="field">License</dt>
<dd>See the <a href="https://utch.usternet.com/departments/RD/Global%20Software/Forms/AllItems.aspx?RootFolder=%2fdepartments%2fRD%2fGlobal%20Software%2fOSSPolicy&amp;FolderCTID=0x0120007BCBD1FD5E6DF149A35D12376C7C922E">Uster OSSPolicy</a> for compliance information</dd>
<dt class="field">Cost</dt>
<dd>Free? One-time fee? Per-seat license?</dd>
</dl><h2>Organizational</h2><dl><dt class="field">Maturity</dt>
<dd>How long has the product been around?</dd>
<dt class="field">Activity</dt>
<dd>When was the last commit? The last release?</dd>
<dt class="field">Maintenance Status</dt>
<dd>Is the project actively maintained? How long is the issue list? Are bugs addressed? </dd>
<dt class="field">Popularity</dt>
<dd>How many stars? Is it widely used?</dd>
<dt class="field">Community</dt>
<dd>Do questions get answered? Is there help on StackOverflow?</dd>
<dt class="field">Reputation</dt>
<dd>Are there known issues with the product or maintainers?</dd>
</dl><h2>Technical</h2><dl><dt class="field">Documentation</dt>
<dd>Is it sufficient? Are there good examples or tutorials?</dd>
<dt class="field">Configuration</dt>
<dd>Can you just include the package? How is the configuration? Does it follow platform standards?</dd>
<dt class="field">Size / Focus</dt>
<dd>Does it do one thing well? Or many other things you don&rsquo;t need?</dd>
<dt class="field">Extensibility</dt>
<dd>How easy is it to extend the package for additional use cases? Will that matter to your project?</dd>
<dt class="field">Efficiency / Performance</dt>
<dd>For this you have to know your non-functional requirement</dd>
<dt class="field">Portability</dt>
<dd>Does it work on all target platforms and run-times? Are there unreasonable restrictions?</dd>
<dt class="field">Transitive Dependencies</dt>
<dd>What are its dependencies? Are those reasonable?</dd>
<dt class="field">Quality</dt>
<dd>What sort of impression does the project make overall? How does the code look?</dd>
</dl><h2>References</h2><ul>
<li><a href="https://www.justinhoward.org/a-dependency-checklist">A Dependency Checklist</a> by <cite>Justin Howard</cite> in April 2021</li>
<li><a href="https://betterprogramming.pub/how-to-choose-the-right-dependencies-for-your-project-310cdbbcb05e#2e34">How to Choose the Right Dependencies for Your Project</a> by <cite>Jamie Bullock</cite> in January 2020</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4607</guid>
    <title><![CDATA[C# 11 Features]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4607</link>
    <pubDate>Mon, 21 Nov 2022 22:48:57 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Nov 2022 22:48:57 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">7. Dec 2022 22:47:43 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The articles <a href="https://blog.okyrylchuk.dev/twelve-csharp-11-features">Twelve C# 11 Features</a> by <cite>Oleg Kyrylchuk</cite> and <a href="https://devblogs.microsoft.com/dotnet/welcome-to-csharp-11/">Welcome to C# 11</a> by <cite>Mads Torgersen</cite> (<cite><a href="http://devblogs.microsoft.com/">Microsoft .NET Blog</a></cite>) provide an excellent overview with examples of new features in C# 11, available with .NET 7.0.</p>
<p>I include my own notes below.</p>
<h2>Interesting and obviously useful</h2><p>&ldquo;Obvious&rdquo; to me, at least. The terms link to examples in one of the articles linked above.</p>
<dl><dt><a href="https://devblogs.microsoft.com/dotnet/welcome-to-csharp-11/#utf-8-string-literals">Native UTF-8 Strings</a></dt>
<dd>You can now append <code>u8</code> to the end of a literal string to make it <a href="https://devblogs.microsoft.com/dotnet/welcome-to-csharp-11/#utf-8-string-literals">UTF-8</a> instead of the system-standard UTF-16. For example, <code>&ldquo;Test string&rdquo;u8</code> will be encoded by the compiler as UTF-8 and will have the type <code>ReadOnlySpan&lt;byte&gt;</code>.</dd>
<dt><a href="https://devblogs.microsoft.com/dotnet/welcome-to-csharp-11/#raw-string-literals">Raw Strings (Here-Doc)</a></dt>
<dd><div class=" ">C# finally supports &ldquo;here documents&rdquo; (which have been supported in other languages like <a href="https://perlmaven.com/here-documents">Perl</a> or <a href="https://www.phptutorial.net/php-tutorial/php-heredoc/">PHP</a> for a long time). In C#, they&rsquo;re called <a href="https://devblogs.microsoft.com/dotnet/welcome-to-csharp-11/#raw-string-literals">raw string literals</a> and,<ul>
<li>they begin and end with at least three double-quotes</li>
<li>can be multi-line</li>
<li>can contain unescaped everything (unless you have three double-quotes in a row, in which case, you just add more double quotes to the fences at the beginning and end)</li>
<li>support interpolation</li>
<li>and also automatically trim left indenting.</li></ul><p>Finally, you can just pass a formatted and indented JSON into C# code, interpolate some variables, and do it all without escaping anything! [1]</p>
</div></dd>
<dt><a href="https://devblogs.microsoft.com/dotnet/welcome-to-csharp-11/#abstracting-over-static-members">Abstracting over static members</a></dt>
<dd><div class=" "><blockquote class="quote quote-block "><div>&ldquo;In fact .NET 7 comes with a new namespace <code>System.Numerics</code> chock-full of math interfaces, representing the different combinations of operators and other static members that you’d ever want to use. […] All the numeric types in .NET now implement these new interfaces – and you can add them for your own types too! So it’s now easy to write numeric algorithms once and for all – abstracted from the concrete types they work on – instead of having forests of overloads containing essentially the same code.&rdquo;</div></blockquote><p>See <a href="https://blog.okyrylchuk.dev/twelve-csharp-11-features#heading-static-abstract-members-in-interfaces">here</a> for an example of using generic parameters in <code>operators</code>, or <a href="https://blog.okyrylchuk.dev/twelve-csharp-11-features#heading-generic-math">Generic Math</a> for an example that uses some of the new interfaces, like <code> IAdditionOperators</code> and <code>ISubtractionOperators</code>.</p>
<p>In that vein, there are a lot more interfaces that support generalized computation, like <a href="https://learn.microsoft.com/en-us/dotnet/api/system.ispanparsable-1?view=net-7.0">ISpanParsable&lt;TSelf&gt; Interface</a>, which <span class="quote-inline">&ldquo;[d]efines a mechanism for parsing a span of characters to a value.&rdquo;</span></p>
</div></dd>
<dt><a href="https://devblogs.microsoft.com/dotnet/welcome-to-csharp-11/#required-members">Required members</a></dt>
<dd><div class=" "><blockquote class="quote quote-block "><div>&ldquo;Another ongoing theme that we’ve been working on for several releases is improving object creation and initialization. C# 11 continues these improvements with required members.&rdquo;</div></blockquote></div></dd>
<dt><a href="https://blog.okyrylchuk.dev/twelve-csharp-11-features#heading-generic-attributes">Generic Attributes</a></dt>
<dd>You can now make attributes generic <em>and</em> use a generic constraint to limit which types may be passed as type parameters (enforced by the compiler, rather than at runtime). E.g. <code>[Generic&lt;MyType&gt;]</code> declared an attribute of type <code>GenericAttribute</code> parametrized with <code>MyType</code>.</dd>
<dt><a href="https://blog.okyrylchuk.dev/twelve-csharp-11-features#heading-extended-nameof-scope">Extended <code>nameof</code> Scope</a></dt>
<dd>This seems like a small one, but it&rsquo;s a welcome improvement. You can now use <code>nameof</code> with <span class="quote-inline">&ldquo;method parameter[s] in an attribute on the method or parameter declaration.&rdquo;</span></dd>
<dt><code>StringSyntaxAttribute</code></dt>
<dd><strong class="highlight">[Added on 03.12.2022]</strong> This one is not technically part of C#—it&rsquo;s actually included in .NET 7—but it&rsquo;s worth an honorable mention. You can now decorate a parameter to indicate the string-syntax that it supports. This allows IDEs to provide string-syntax-specific code-completion, highlighting, and error-handling. A good example is, of course, for <em>regular expression patterns</em>. While Rider and ReSharper have provided this support for certain constructors and methods (e.g. <code>RegEx</code> or <code>DateTime.Format</code>), this is a welcome standardization that gives your own APIs the same star treatment. The post <a href="https://bartwullems.blogspot.com/2022/12/net-7-stringsyntaxattribute.html">What does the StringSyntaxAttribute do?</a> includes a list of the syntaxes supported out-of-the-box. The post <a href="https://www.alwaysdeveloping.net/dailydrop/2022/03/28-stringsyntaxattribute/">StringSyntaxAttribute for syntax highlighting</a> provides examples and screenshots.</dd>
</dl><h2>Niche Additions</h2><p>A few that seem a bit dubious, but are, I guess, welcome additions, and will be useful to someone are,</p>
<dl><dt><a href="https://blog.okyrylchuk.dev/twelve-csharp-11-features#heading-list-patterns">List patterns</a></dt>
<dd>You can do some wild matching with these (i.e. <code>numbers is [_, &gt;= 2, _, _]</code> returns <code>true</code> if <code>numbers</code> is a four-element list where the second element is greater than or equal to 2.</dd>
<dt><a href="https://blog.okyrylchuk.dev/twelve-csharp-11-features#heading-newlines-in-string-interpolation-expressions">Newslines in string-interpolation patterns</a></dt>
<dd>I guess it&rsquo;s nice that you can format complex variables inside an interpolated string, but I still think that you should just make a local variable instead. That would be more readable, in any case.</dd>
<dt><a href="https://blog.okyrylchuk.dev/twelve-csharp-11-features#heading-auto-default-structs">Auto-default Structs</a></dt>
<dd>This will allow you to define structs without being so pedantic about defining the constructor.</dd>
<dt><a href="https://blog.okyrylchuk.dev/twelve-csharp-11-features#heading-an-unsigned-right-shift-operator">Unsigned Right-shift Operator</a></dt>
<dd>I know I&rsquo;m almost certainly not going to use this one, but it nicely rounds out the support offered with the new <code>System.Numerics</code> interfaces and the increased generality offered by abstracting over static members (linked above).</dd>
<dt><a href="https://blog.okyrylchuk.dev/twelve-csharp-11-features#heading-file-scoped-types">File-scoped types</a></dt>
<dd>This seems kind of like an analog to unexported types declared in TypeScript, but I don&rsquo;t really see myself using them very much until we get the <a href="https://www.earthli.com/news/view_article.php?id=4553">type declaration from TypeScript</a> as well.</dd>
<dt><a href="https://stevetalkscode.co.uk/regex-source-generator">Source-generated regular expressions</a></dt>
<dd><div class=" "><p>This feature leverages the <a href="https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview">source-generation</a> that&rsquo;s been available since <a href="https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/">.NET 5</a> to avoid JIT for regular expressions by generating code for it directly. It&rsquo;s really great to see the .NET team getting mileage out of the features they&rsquo;re adding (I&rsquo;m sure this isn&rsquo;t a coincidence).</p>
<p>For another example of source-generation, see <a href="https://www.meziantou.net/generate-pinvoke-code-for-win32-apis-using-a-source-generator.htm">Generating PInvoke code for Win32 apis using a Source Generator</a> by <cite>G&eacute;rald Barr&eacute;</cite> (<cite><a href="http://www.meziantou.net/">Meziantou&#039;s Blog</a></cite>), which explains how to use Microsoft&rsquo;s NuGet package <code>Microsoft.Windows.CsWin32</code> to easily generate source for any Win32 API or type—no more writing this stuff manually!</p>
</div></dd>
</dl><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4607_1_body" class="footnote-number">[1]</span> <p>Check out the following animation of converting an escaped string to a raw string in Rider (from the post <a href="https://blog.jetbrains.com/dotnet/2022/12/07/rider-2022-3/">Rider 2022.3: Support for .NET 7 SDK, the Latest From C#11, Major Performance Improvements, and More!</a> by <cite>Sasha Ivanova</cite> (<cite><a href="http://blog.jetbrains.com/">The .NET Tools Blog</a></cite>):</p>
<p><img src="https://blog.jetbrains.com/wp-content/uploads/2022/12/cs-to-raw-strings.gif" alt=" " style="width: 500px"></p>
</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4571</guid>
    <title><![CDATA[Waterfall vs. Agile vs. "Wagile"]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4571</link>
    <pubDate>Tue, 20 Sep 2022 21:45:20 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Sep 2022 21:45:20 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://itnext.io/agile-projects-have-become-waterfall-projects-with-sprints-536141801856">Agile Projects Have Become Waterfall Projects With Sprints</a> by <cite>Ben Hosking</cite> (<cite><a href="http://itnext.io/">ITNext</a></cite>) argues that a lot of projects using agile aren&rsquo;t agile at all, but are <span class="quote-inline">&ldquo;more like waterfall projects with upfront requirements, fixed deadlines, sprints and 2 weekly demos.&rdquo;</span></p>
<p>Overall, I understand where the author is coming from, but I found the tone pretty overwhelmingly negative. I can only imagine what the author has seen to have put them in such a dark place. 😐</p>
<p>I thought that this was an interesting comment in the article:</p>
<blockquote class="quote quote-block "><div>&ldquo;You cannot create fixed deadlines unless you know all the requirements and guarantee no requirements are changed.&rdquo;</div></blockquote><p>However, you <em>can</em> create fixed deadlines (the world kind of expects them sometimes, e.g. when you&rsquo;re preparing for a conference that happens <em>on a specific day</em>), but then you have to be willing to adjust on <em>what</em> will be delivered on that day.</p>
<p>Agile started out in a world where a <em>partial</em> product could be delivered and <em>still have value</em>. That is not the case with all projects. Thus, the designations <abbr>MVP</abbr> (Minimum Viable Product) and <abbr>MMP</abbr> (Minimum Marketable Product).</p>
<p>Even agile projects have to be honest about what the minimum time frame is for an MVP, though. Where some projects have an advantage is that they can iterate in smaller increments <em>after that</em>, but also can deliver useful, though <em>nonviable</em> pieces as artifacts of iterations. There are some projects where it&rsquo;s more difficult to carve out such deliverables.</p>
<p>Although there is always work that has been planned and successfully accomplished and documented, it&rsquo;s sometimes hard to measure or see progress until a larger amount of work has been done. I suppose that&rsquo;s the art of planning and measuring.</p>
<p>Here, it&rsquo;s also useful for technical team members or more technically oriented teams to learn how to consider administrative, planning, design, and documentation work as just as useful as producing technical artifacts (be they physical or virtual).</p>
<p>A waterfall process doesn&rsquo;t help figure out what to do when the delivery cannot be completed on time. It (generally) has no plan for what to drop if you can&rsquo;t deliver on time. Also, it doesn&rsquo;t really have any ideas for what to do when new things &ldquo;crop up&rdquo;. An agile process is supposed to help you triangulate toward a version of the product that can actually be delivered by the target date—or help you better (and sooner) predict whether it&rsquo;s even possible to deliver anything useful by that date.</p>
<p>I think you have to be honest about which projects really can be run in an agile way—but then also make sure that they take advantage of agility to be bolder than they have been.</p>
<p>Release early, release often, think about what your MVP is, all of those things are good to take from the agile process. As far as the &ldquo;ceremony&rdquo; of the process goes: I have always found value in the review and retros.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4552</guid>
    <title><![CDATA[Applying the rule of least power in practice]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4552</link>
    <pubDate>Fri, 02 Sep 2022 04:28:25 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">2. Sep 2022 04:28:25 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Some asked <a href="https://old.reddit.com/r/web_design/comments/wvel18/is_there_a_js_library_that_animates_the_text_word/">is there a js library that animates the text word by word like shown?</a> by <cite>DemDavors</cite> (<cite><a href="http://old.reddit.com/">Reddit</a></cite>). </p>
<p>A bunch of people answered &ldquo;just do it with CSS!&rdquo; and one or two recommend using <a href="https://greensock.com/gsap/">GSAP</a> (Green Sock Animation Platform). I&rsquo;d just heard about that library in the following instructive video and had had a chance to investigate how it works.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/8q_05PUYv1o" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=8q_05PUYv1o">FLIP animations | HTTP 203</a> by <cite>Google Chrome Developers</cite></span></span></p>
<p>I&rsquo;d like to expand on the comments recommending to use the &ldquo;rule of least power&rdquo;. They are absolutely correct, but you have to consider the entire task:</p>
<ul>
<li>Learning <em>how</em> to use CSS for this task</li>
<li>Writing maintainable CSS to execute this task</li></ul><p>For those who already know how to do this and are trying to limit JS as much as possible then, by all means, use CSS only.</p>
<p>For anyone else, &ldquo;least power&rdquo; means using CSS where possible, but not necessarily excluding JS if doing so improves maintainability, enhances developer speed and accuracy, and reduces errors.</p>
<p>If you look at what GSAP does, it generally maps a high-level JS animation API to CSS animations and transitions. The concession you&rsquo;ve made is to include animations using a relatively thin layer of JavaScript. That thin layer, though, is a change in technology (more power), which ensures that the animations will no longer work if JavaScript is disabled. <em>However</em>, you&rsquo;re actually using CSS animations under the hood, benefiting from the high-level and highly optimized implementations in the browser. So you&rsquo;ve lost flexibility as far as user agents is concerned, but the performance is the same, and you&rsquo;ve probably saved time debugging and tweaking the implementation.</p>
<p>That might be a better balance for those developers who would have no idea how to animate the given example with native CSS. If they did that, they would have to first learn how to do it, taking up a lot of time, to say nothing of that they might end up creating a suboptimal implementation, both performance- and maintenance-wise.</p>
<p>Telling someone to &ldquo;just use CSS&rdquo; is <em>technically</em> correct, but also sounds a lot like answering &ldquo;just use pipes&rdquo; when someone asks how to install a toilet. There&rsquo;s a bit of detail missing there.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4553</guid>
    <title><![CDATA[New feature for C#: Anchored types]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4553</link>
    <pubDate>Fri, 02 Sep 2022 04:27:24 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">2. Sep 2022 04:27:24 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I recently answered the question <a href="https://old.reddit.com/r/csharp/comments/wvmh4a/what_features_from_other_languages_would_you_like/">What features from other languages would you like to see in C#?</a> by <cite>BatteriVolttas</cite> (<cite><a href="http://old.reddit.com/">Reddit</a></cite>)</p>
<p>I think <a href="https://www.eiffel.org/doc/eiffel/ET-_Inheritance#Anchored_Declarations">Anchored Declarations</a> and <a href="https://www.eiffel.org/doc/eiffel/ET-_Inheritance#Qualified_Anchored_Declarations">Qualified Anchored Declarations</a> from Eiffel would be very useful.</p>
<p>I like the name &ldquo;anchored&rdquo; because you&rsquo;re anchoring the type of one thing to another. Instead of using <code>int</code> throughout a class, you can just make e.g. a field named <code>_id</code> be an <code>int</code> and then make all other types (e.g. for the parameter passed to a method) refer to the anchor with <code>like _id</code> or <code>typeof _id</code>.</p>
<p>If the type of the field ever needs to change, you only need to update one place. It&rsquo;s more expressive because the alternative is to explicitly write the type of the parameter, whereas that was never what was going on. The method doesn&rsquo;t decide what the type is; we&rsquo;re just used to _syncing_ it to the type of the field _manually_ because there is no way to express the relationship in most languages we&rsquo;re using.</p>
<p>Here&rsquo;s an example:</p>
<pre class=" "><code><strong>class</strong> A
{
  <em>int</em> Status { <strong>get</strong>; <strong>set</strong>; } = 0;
  <strong>like</strong> Status PriorStatus { <strong>get</strong>; }

  <em>void</em> Start(<strong>like</strong> Status s) {}
  <em>void</em> Stop(<strong>like</strong> Status s) {}
}</code></pre><p>The syntax is similar to how <code>ref</code> and <code>out</code> work now, but looking at it takes a bit of getting used to, especially for the property declaration. </p>
<p>TypeScript has this feature, with the <a href="https://www.typescriptlang.org/docs/handbook/2/typeof-types.html">typeof</a> operator, but they don&rsquo;t name it. TypeScript has two advantages here: it places the type after the variable name, which feels a bit more natural when the type is expressed with multiple words, <em>and</em> TypeScript has implicit return types, so you don&rsquo;t have to write the type at all in many cases. </p>
<p>Because of the implicit typing, TypeScript has technically had anchored types all along!</p>
<pre class=" "><code><strong>class</strong> A
{
    status: <em>int</em> = 0;

    // The implicit type here is derived from "status",
    // which "anchors" the type of the function to that field.
    get priorStatus() { return status; }

    // Here we're obliged to restrain the type explicitly
    <em>void</em> Start(s: <strong>typeof</strong> status) {}
    <em>void</em> Stop(s: <strong>typeof</strong> status) {}
}</code></pre><p>As of TypeScript 4.7, it <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#typeof-on-private-fields">supports qualified anchored declarations</a> on private fields as well.</p>
<p>Someone suggested in a response that generics might fill this bill already.</p>
<p>In a way, yes, that&rsquo;s true. I could define the whole class with a generic type argument and then create a derived type that fixes the type argument to <code>int</code>.</p>
<pre class=" "><code><strong>class</strong> A&lt;TStatus&gt;
  <strong>where</strong> TStatus : <em>INumber</em>
{
  TStatus Status { get; set; } = TStatus.Zero;

  TStatus PriorStatus { get; }

  <em>void</em> Start(TStatus s) {}
  <em>void</em> Stop(TStatus s) {}
}

<strong>class</strong> IntA : A&lt;int&gt; {}</code></pre><p>We have to use the newest features from C# 11 in order to be able to initialize the value to <code>0</code>. If it were a value that maps to a non-mathematical concept (e.g. additive or multiplicative identity), then we wouldn&rsquo;t be able to use the generic approach.</p>
<p>It feels a bit like misuse of generics, though, when I just wanted a shorthand for letting one type reference another. As I wrote, TypeScript already allows this and seems to have found it a useful addition to generics (you can probably implement it under-the-hood with the same code in the compiler).</p>
<p>I feel the same way about the missing <code>type</code> declaration from TypeScript (or the very similar, but less powerful <code>typedef</code> from C or Pascal).</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4475</guid>
    <title><![CDATA[Quick CSS: text-decoration]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4475</link>
    <pubDate>Mon, 21 Mar 2022 22:50:55 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Mar 2022 22:50:55 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://css-tricks.com/when-to-avoid-css-text-decoration-shorthand/">When to Avoid the text-decoration Shorthand Property</a> by <cite>&Scaron;ime Vidas</cite> (<cite><a href="http://css-tricks.com/">CSS Tricks</a></cite>) makes a couple of interesting points. Basically, you have a <em>lot</em> of control over how underlines are drawn on text.</p>
<ul>
<li>Modern browsers allow you to tweak the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration"><code>text-decoration: underline</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-thickness"><code>text-decoration-thickness</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-underline-offset"><code>text-underline-offset</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>)</li>
<li>Use the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:any-link"><code>:any-link</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) to select links that actually have an <code>href</code> attribute rather than selecting <em>all</em> links.</li>
<li>The CSS property <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration"><code>text-decoration</code> is a <cite>shorthand</cite> property, which means that setting it overwrites all of the properties that it might represent (including the underline thickness).</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>)</li></ul><p>The article doesn&rsquo;t mention these, but,</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-skip"><code>text-decoration-skip</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) controls how to underline whitespace</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-skip-ink"><code>text-decoration-skip-ink</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) controls whether a text decoration (underline or overline) can touch the ascenders or descenders of glyphs. </li></ul><p>The following text has the style <code>text-decoration: underline .4em; text-underline-offset: .4em</code>. Note that it doesn&rsquo;t affect the bounding box.</p>
<div class="caution " style="text-decoration: underline .4em; text-underline-offset: .4em">squabbling</div><p>The following text has the style <code>text-decoration: underline; text-decoration-skip: spaces; text-decoration-skip-ink: all</code>. Note that <code>text-decoration-skip</code> only works with Safari at the time of writing.</p>
<div class="caution " style="text-decoration: underline; text-decoration-skip: spaces; text-decoration-skip-ink: all">squabbling with boggling</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4372</guid>
    <title><![CDATA[The "Hustle" culture in Software Development]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4372</link>
    <pubDate>Mon, 24 Jan 2022 17:20:05 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">24. Jan 2022 17:20:05 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Have you noticed that there is more and more content available to help you learn how to program? For every topic under the sun, there seems to be a blog article or video of superficially reasonable quality. For every question on StackOverflow, there&rsquo;s an effusive answer with examples.</p>
<p>This is all pretty great, honestly.</p>
<p>However, with the increase in content. there is also the need to be able to wade through it.</p>
<p>How old is that StackOverflow answer? How appropriate is the answer to your particular question? Are there other solutions? Maybe easier ones? Maybe more modern ones? Has this solution to this particular problem been addressed in more recent versions? This isn&rsquo;t new, of course. You should have been asking yourself questions like this for quite a while with these so-called expert-community sites. </p>
<p>However, now, we&rsquo;re also inundated with content from people hustling to make a living as professional, freelance, advice-givers online. This is not a bad thing, necessarily. It&rsquo;s great that the unsung masters that formerly only provided value inside of a single company are bringing their didactic abilities to the world. That&rsquo;s not all that they&rsquo;re doing, though.</p>
<p>Those who are on a subscriber model <em>have</em> to publish content in order to keep their subscribers. They don&rsquo;t even necessarily have to produce anything of lasting value—they just have to produce <em>something</em>. They just have to retain and/or grow their subscriber base. This leads to nice-looking, but ultimately useless &ldquo;fluff&rdquo; content that rehashes an old concept with a few flashy graphics or an accompanying video. And the videos! Many of them take 15 minutes to explain a concept that you could describe adequately in a paragraph and a code example.</p>
<p>The Microsoft MVP bloggers are very conspicuous these days: there are many who are publishing an article or two per week &ldquo;explaining&rdquo; a C# 10 feature that has already been explained to death in dozens of other high-profile articles—to say nothing of the article <a href="https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/">Welcome to C# 10</a> by <cite>Kathleen Dollard</cite> (<cite><a href="http://devblogs.microsoft.com/">Microsoft Dev Blogs</a></cite>), which comes straight from the horse&rsquo;s mouth, is wonderfully written, and, honestly, says all there needs to be said about these features.</p>
<p>But, if you search for &ldquo;C# 10&rdquo;, there is a flood of repetitive and, sometimes, outdated, information on C# 10. And these authors are all still churning out the articles. They&rsquo;re doing it for the clicks, for the ad-views, for the subscribers. It&rsquo;s a living. I get it. But, overall, it contributes to a very muddled picture that makes it difficult for people looking for advice and assistance.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4422</guid>
    <title><![CDATA[CSS Speedrun]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4422</link>
    <pubDate>Sat, 22 Jan 2022 12:22:44 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">22. Jan 2022 12:22:44 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>If you want to test or hone your CSS skills, check out the <a href="https://css-speedrun.netlify.app/">CSS Speedrun</a>. It lets you warm up with a relatively easy &ldquo;intro&rdquo;, then takes you through ten levels. Generally, each level tests a different feature of CSS (usually a specific selector). The final question (pictured) makes you combine what you&rsquo;ve learned or used from other levels.</p>
<p>The image below is from my second time through. The first time through I needed about nine minutes; the next morning, I got through much more quickly. I guess I&rsquo;d learned something. 🎉 for me.</p>
<p><span style="width: 481px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4422/css_speedrun.png"><img src="https://www.earthli.com/data/news/attachments/entry/4422/css_speedrun.png" alt=" " style="width: 481px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4422/css_speedrun.png">CSS Speedrun results (second time through)</a></span></span></p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4421</guid>
    <title><![CDATA[TIL: nth-of-type() and na+b in CSS]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4421</link>
    <pubDate>Fri, 21 Jan 2022 11:12:46 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Jan 2022 11:12:46 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I&rsquo;ve known about <code>nth-child(n)</code> for a long time. It selects the nth child from a structure if that child happens to match the given tag. You can always select the nth child by omitting the tag.</p>
<p>For example, <code>div :nth-child(2)</code> (two selectors) will match the second child of any div, regardless of type. However, <code>div span:nth-child(2)</code> will only match if the second child is also a span.</p>
<p>You cannot write a selector that says &ldquo;select the second span&rdquo; using <code>nth-child</code>. That&rsquo;s where <code>nth-of-type(n)</code> comes in. The selector <code>div span:nth-of-type(2)</code> does exactly that. I can&rsquo;t recall that I&rsquo;ve ever had this need before, but it&rsquo;s also possible that I ended up adding extra tags or convoluted selectors in order to achieve what could have been more elegantly done with <code>nth-of-type</code>.</p>
<p>Additionally, while I was aware that <code>nth-child</code> supported constants and the keywords <code>odd</code> and <code>even</code>, I didn&rsquo;t know that it also supported a formula <code>a<em>n</em> + b</code>. The <em>a</em> is a multiplier and <em>b</em> is an offset. With this formula, you can select every <em>third</em> or <em>fifth</em> (or whatever) element and then move the selection by a given <em>offset</em>.</p>
<p>The selectors <code>first-of-type</code>, <code>last-of-type</code>, etc. also exist, as well as <code>only-of-type</code>, which matches an element when it&rsquo;s the only child of that type in the parent. See <a href="https://css-tricks.com/pseudo-class-selectors/">Meet the Pseudo Class Selectors</a> by <cite>Chris Coyier</cite> (<cite><a href="http://css-tricks.com/">CSS Tricks</a></cite>) for more information.</p>
<p>You may see where this is heading. The article <a href="https://chenhuijing.com/blog/the-wondrous-world-of-css-counters/#pure-css-fizzbuzz">The wondrous world of CSS counters</a> by <cite>Chen Hui Jeng</cite> includes an example where he writes the famous FizzBuzz program with CSS.</p>
<p>Start with an ordered list,</p>
<pre class=" "><code>&lt;ol&gt;
  &lt;li&gt;&lt;/li&gt;
  …add more li elements, like 30 of them…
  &lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;</code></pre><p>Then apply the following CSS to it,</p>
<pre class=" "><code>ol { list-style-position: inside } /* To line-up all items neatly */

li:nth-of-type(3n+3),
li:nth-of-type(5n+5),
li:nth-of-type(3n+3):nth-of-type(5n+5) {
  list-style: none /* When text of Fizz, Buzz or FizzBuzz appears, get rid of the numbers */
}

li:nth-of-type(3n+3)::before {  content: "Fizz" }
li:nth-of-type(5n+5)::before {  content: "Buzz" }
li:nth-of-type(3n+3):nth-of-type(5n+5)::before {  content: "FizzBuzz" }</code></pre><p>Put it all together and you get <a href="https://www.earthli.com/data/news/attachments/entry/4421/css_fizz_buzz.html">CSS FizzBuzz</a>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4403</guid>
    <title><![CDATA[Accessibility is important]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4403</link>
    <pubDate>Tue, 28 Dec 2021 23:45:47 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">28. Dec 2021 23:45:47 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/4403/html_5.png"><img src="https://www.earthli.com/data/news/attachments/entry/4403/html_5_tn.png" alt=" " class=" align-left"></a>I recently read through the <a href="https://a11ymyths.com/"><abbr title="accessibility">a11y</abbr> myths</a>. They&rsquo;re quite interesting and should be required reading for managers running projects that develop web sites.</p>
<p>From it, I learned about the evils of overlays (see the <a href="https://overlayfactsheet.com/">Overlay Fact Sheet</a>) and that there are really good resources out there, like <a href="https://www.w3.org/WAI/WCAG21/Understanding/conformance">Understanding Conformance</a> (<cite><a href="http://www.w3.org/">W3C</a></cite>) with WCAG 2.0 (Web Content Accessibility Guidelines).</p>
<blockquote class="quote quote-block "><div>&ldquo;All WCAG 2.0 Success Criteria are written as testable criteria for objectively determining if content satisfies them. Testing the Success Criteria would involve a combination of automated testing and human evaluation. The content should be tested by those who understand how people with different types of disabilities use the Web.&rdquo;</div></blockquote><p>If you build custom controls, you should use <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA">ARIA</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>). That page includes the following note,</p>
<blockquote class="quote quote-block "><div>&ldquo;Many of these widgets were later incorporated into HTML5, and developers should prefer using the correct semantic HTML element over using ARIA, if such an element exists. For instance, native elements have built-in keyboard accessibility, roles and states. However, if you choose to use ARIA, you are responsible for mimicking (the equivalent) browser behavior in script.&rdquo;</div></blockquote><p>If you do need to use ARIA, then there&rsquo;s a set of rules for its use in the article <a href="https://w3c.github.io/using-aria/#rule1">Notes on ARIA Use in HTML</a> (<cite><a href="http://w3c.github.io/">W3C</a></cite>).</p>
<p>While we&rsquo;re on the topic of building your own custom controls instead of using the built-in HTML inputs, we can also talk about how <a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML#good_semantics">Good semantics</a> also goes a long way to having good accessibility, right out of the gate. So, go ahead and use <code>main</code>, <code>nav</code>, <code>header</code>, <code>footer</code>, <code>aside</code>, <code>section</code>, and <code>article</code>.</p>
<p>There&rsquo;s some really good advice in there on writing clearly (e.g. use full month names and clarify abbreviations) as well as using meaningful text in links (e.g. don&rsquo;t just use &ldquo;click&rdquo; or &ldquo;here&rdquo;).<br>
&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4400</guid>
    <title><![CDATA[TIL CSS border-radius lets you define ellipses]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4400</link>
    <pubDate>Sun, 26 Dec 2021 09:24:51 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">26. Dec 2021 09:24:51 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I hadn&rsquo;t ever really thought about it because I don&rsquo;t use the API very much, but it turns out that the <code>border-radius</code> property is not only a shorthand for setting all four corners at once, but <em>also</em> sets the horizontal and vertical lengths simultaneously. To set them individually, use a <code>/</code> between two values.</p>
<p>The corner radii are then calculated using ellipses as shown in the following visualization,</p>
<p><span style="width: 299px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4400/border-radius-6.png"><img src="https://www.earthli.com/data/news/attachments/entry/4400/border-radius-6.png" alt=" " style="width: 299px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4400/border-radius-6.png">Border-Radius with ellipses</a></span></span></p>
<p>The article <a href="https://9elements.com/blog/css-border-radius/">CSS Border-Radius Can Do That?</a> by <cite>Nils Binder</cite> on October 9, 2018 (<cite><a href="http://9elements.com/">9 elements</a></cite>) has many more examples. It also introduces a <a href="https://9elements.github.io/fancy-border-radius/#51.30.20.25--.">Fancy-Border-Radius tool</a> to help you create the desired shape visually.</p>
<p><span style="width: 521px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4400/screen_shot_2021-12-26_at_09.07.12.png"><img src="https://www.earthli.com/data/news/attachments/entry/4400/screen_shot_2021-12-26_at_09.07.12.png" alt=" " style="width: 521px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4400/screen_shot_2021-12-26_at_09.07.12.png">Sample border-radius setting with rendering</a></span></span></p>
<p>CSS includes the much more generalized <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Shapes/Overview_of_CSS_Shapes"><code>shape()</code> API</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) [1], but it wouldn&rsquo;t be as easy to define the &ldquo;blobs&rdquo; shown above with that API because the &ldquo;blob&rdquo; is defined by the intersection of four overlapping ellipses and the <code>shape()</code> API doesn&rsquo;t allow combining multiple shapes into one shape.</p>
<p>Not only that, but the fact that the &ldquo;blob&rdquo;, as defined by the eight values shown above, can be quite easily <em>animated</em> by providing the end &ldquo;blob&rdquo; to a <code>transition</code> or by providing several &ldquo;blobs&rdquo; to tweenable <code>@keyframes</code>. You can see the technique in action in <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Shapes/Overview_of_CSS_Shapes">this CodePen</a>. Scroll all the way down in the CSS definition to see that the effect uses a combination of morphing the <code>border-radius</code> and rotating using a <code>transform</code> to achieve a quite-complex and organic effect using only very straightforward and highly available CSS.</p>
<pre class=" "><code>@keyframes morph {
  0% {border-radius: 40% 60% 60% 40% / 60% 30% 70% 40%;} 
  100% {border-radius: 40% 60%;} 
}

@keyframes spin {
  to {
    transform: rotate(1turn);
  }
}</code></pre><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4400_1_body" class="footnote-number">[1]</span> <p>You can even use &ldquo;tricks&rdquo; to create many shapes without using the <code>shape()</code> API either. See <a href="https://css-tricks.com/the-shapes-of-css/">The Shapes of CSS</a> by <cite>Chris Coyier</cite> (<cite><a href="http://css-tricks.com/">CSS-Tricks</a></cite>) for many, many examples.</p>
</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4395</guid>
    <title><![CDATA[Real Hacks are not easy]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4395</link>
    <pubDate>Thu, 23 Dec 2021 15:30:47 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">23. Dec 2021 15:30:47 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Most of us know &ldquo;hackers&rdquo; from the media—either the news media, television shows like <em>Mr. Robot</em>, or movies like <em>Swordfish</em>. But the fast and easy way of hacking presented in the media actually does a disservice to how incredibly clever these hacks really are.</p>
<p>Less-complex techniques—like guessing or brute-forcing passwords—still work super-well. And you&rsquo;ve always got social engineering hacks, like just asking someone for their credentials in an official-sounding way. But real, <em>technical</em> hacking involves getting to know a system&rsquo;s dependencies and memory layout and runtime environment even better than the original programmers ever did.</p>
<p>Note: Both of these issues have been fixed, but it’s fascinating to read about how they did it. It really offers insight into what to avoid doing in your own code (e.g. do <em>not</em> open a <code>WebSocket</code> on <code>0.0.0.0</code>).</p>
<h2>NSO&rsquo;s zero-click iMessage exploit</h2><p>The first article <a href="https://googleprojectzero.blogspot.com/2021/12/a-deep-dive-into-nso-zero-click.html">A deep dive into an NSO zero-click iMessage exploit: Remote Code Execution</a> by <cite>Ian Beer &amp; Samuel Gro&szlig;</cite> (<cite><a href="http://googleprojectzero.blogspot.com/">Google Project Zero</a></cite>) is a longer read, but I found it fascinating how many pieces they needed to chain together in order to hack iMessage—which they managed to do with a 0-click exploit. Just sending a message to the phone with a specially coded picture in it was enough to trigger code to run automatically that, unfortunately, ran <em>before</em> the sandbox. It overwrote memory in a controlled manner—making sure not to crash the app—and set up its own virtual machine to execute arbitrary code, which it then did.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;JBIG2 doesn&rsquo;t have scripting capabilities, but when combined with a vulnerability, it does have the ability to emulate circuits of arbitrary logic gates operating on arbitrary memory. So why not just use that to build your own computer architecture and script that!? That&rsquo;s exactly what this exploit does. <strong>Using over 70,000 segment commands defining logical bit operations, they define a small computer architecture with features such as registers and a full 64-bit adder and comparator</strong> which they use to search memory and perform arithmetic operations. It&rsquo;s not as fast as Javascript, but it&rsquo;s fundamentally computationally equivalent.</p>
<p>&ldquo;The bootstrapping operations for the sandbox escape exploit are written to run on this logic circuit and <strong>the whole thing runs in this weird, emulated environment created out of a single decompression pass through a JBIG2 stream.</strong> It&rsquo;s pretty incredible, and at the same time, pretty terrifying.&rdquo;</p>
</div></blockquote><h2>VSC with WSL opens an unprotected WebSocket</h2><p>The second hack is less wide-reaching, in that it would apply only to certain software developers using certain tools, which automatically limits the audience. The <a href="https://parsiya.net/blog/2021-12-20-rce-in-visual-studio-codes-remote-wsl-for-fun-and-negative-profit/#fnref:1">RCE in Visual Studio Code&rsquo;s Remote WSL for Fun and Negative Profit</a> by <cite>Parsia</cite> (<cite><a href="http://parsiya.net/">Hackerman&#039;s Hacking Tutorials</a></cite>) describes, in relatively easy-to-follow detail, how the author found a pretty big hole in the remote-debugging support for Visual Studio Code using WSL (Windows Subsystem for Linux).</p>
<p>In order for it to work, the user had to approve opening the port in the Windows Firewall, but it was kind of unconscionable that it opened <em>such a big hole</em>. The developer could be forgiven for thinking that it was OK to approve the request, given that they had just initiated an action to debug between machines. Approving a firewall in that situation is not only expected, but incredibly common. The dialog box doesn&rsquo;t provide an information about which ports it wanted to amend.</p>
<blockquote class="quote quote-block "><div><p><strong>The Local WebSocket Server</strong></p>
<p>Every time you see a local WebSocket server, you should check <strong>WHO</strong> can connect to it.</p>
<p><span class="quote-inline">&ldquo;WebSocket connections are not bound by the Same-Origin Policy and JavaScript in the browser can connect to local servers.&rdquo;</span></p>
<p><em>— TL;DR WebSockets</em></p>
<p>WebSockets start with a handshake. It is always a &ldquo;<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests">simple</a>&rdquo; (in the context of Cross-Origin Resource Sharing or CORS) GET request so the browser sends it without a preflight request.</p>
</div></blockquote><blockquote class="quote quote-block "><div>These bugs can be chained:<ol>
<li>The local WebSocket server is listening on all interfaces. If allowed through the Windows firewall, outside applications may connect to this server.</li>
<li><strong>The local WebSocket server does not check the Origin header in the WebSocket handshakes or have any mode of authentication. The JavaScript in the browser can connect to this server. This is true even if the server is listening on localhost.</strong></li>
<li>We can spawn a Node inspector instance on a specific port. It&rsquo;s also listening on all interfaces. External applications can connect to it.</li>
<li>If an outside app or a local website can connect to either of these servers, they can run arbitrary code on the target machine.</li></ol></div></blockquote>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4392</guid>
    <title><![CDATA[State of CSS 2021]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4392</link>
    <pubDate>Thu, 23 Dec 2021 09:55:59 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">23. Dec 2021 09:55:59 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I just finished reading through the <a href="https://2021.stateofcss.com/en-US/">State of CSS 2021</a>. It&rsquo;s a well-presented [1] summary of a developer survey about CSS.</p>
<p>I liked the following sections:</p>
<dl><dt class="field"><a href="https://2021.stateofcss.com/en-US/features">Features</a></dt>
<dd>the sub-sections have a pretty fine-grained listing of CSS features, usage, <a href="https://caniuse.com">caniuse</a> and <a href="https://developer.mozilla.org/">MDN</a> links, if you&rsquo;re interested in finding out what you might be missing…or want to be smug about all of the CSS features you know about and use.</dd>
<dt class="field"><a href="https://2021.stateofcss.com/en-US/technologies">Technologies</a></dt>
<dd>The rankings in the sub-sections are broken down by &ldquo;Satisfaction&rdquo;, &ldquo;Interest&rdquo;, &ldquo;Usage&rdquo;, and &ldquo;Awareness&rdquo;.</dd>
<dt class="field"><a href="https://2021.stateofcss.com/en-US/awards">Awards</a></dt>
<dd><a href="https://postcss.org/">PostCSS</a>, <a href="https://vanilla-extract.style/">vanilla-extract</a>, <a href="https://github.com/css-modules/css-modules">CSS Modules</a>, and <a href="https://stitches.dev/">Stiches</a> seem worth following up on.</dd>
<dt class="field"><a href="https://2021.stateofcss.com/en-US/conclusion">Conclusion</a></dt>
<dd>They rightly note that <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries">container queries</a> [2] and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@layer">Cascade Layers</a> [3] will drastically reduce the number of media queries and prefixing and pre- or post-processing needed for CSS. Another step in eliminating pre- or post-processing would be to support CSS nesting natively, but that&rsquo;s a <a href="https://caniuse.com/css-nesting">bit farther out</a>. [4]</dd>
</dl><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4392_1_body" class="footnote-number">[1]</span> The permalinks next to the titles don&rsquo;t work. I submitted an <a href="https://github.com/StateOfJS/Monorepo/issues/59">issue</a> and it may already be fixed by the time you browse to it.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4392_2_body" class="footnote-number">[2]</span> Available behind a flag in Blink-based browsers (Chrome, Edge, Opera). In-progress in WebKit/Safari. There&rsquo;s a <a href="https://github.com/GoogleChromeLabs/container-query-polyfill">container-query polyfill</a> available</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4392_3_body" class="footnote-number">[3]</span> Available behind a flag in Blink-based browsers and Firefox and the Safari TP. [5] No polyfill, so you really have to wait for non-flag release to use this feature.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4392_4_body" class="footnote-number">[4]</span> Technology Preview</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4392_5_body" class="footnote-number">[5]</span> There are support bugs for all major browsers, but no released implementation so far, even behind a feature flag.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4362</guid>
    <title><![CDATA[CSS sub-grids (and grids) with Kevin Powell]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4362</link>
    <pubDate>Sat, 13 Nov 2021 13:36:23 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Nov 2021 13:36:23 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I&rsquo;ve been using CSS Grids for a while now. I&rsquo;ve found many instances where I had used <code>flexbox</code>, where grids turn out to be much more appropriate. That is, the grid layout algorithm lets me specify what I want without fiddling about with <code>flex-base</code> and <code>flex-grow</code>, etc. Flexbox definitely has its place, but I think we all ended up abusing it a bit in our rush to leave tables-for-layout behind.</p>
<p>But that&rsquo;s all in the past because now we have CSS grids <a href="https://caniuse.com/?search=grid">available everywhere</a> and all is well with the world! That being said, if you&rsquo;ve not used CSS grids yet, then you should check out this CSS-grid super-fan&rsquo;s many videos. He has a <a href="https://www.youtube.com/playlist?list=PL4-IK0AVhVjPv5tfS82UF_iQgFp4Bl998">playlist of CSS Grid videos</a> by <cite>Kevin Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>) that you can work your way through.</p>
<p>He even made a short video (5min) describing how to use the grid inspector in browsers. The grid inspector is super-handy, but not so intuitive to find.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/m04RkJwzFgE" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=m04RkJwzFgE&amp;list=PL4-IK0AVhVjPv5tfS82UF_iQgFp4Bl998">Make CSS Grid soooo much easier to understand and use</a> by <cite>Kevin Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<h2>Sub-grids</h2><p>I&rsquo;m more interested in what the same guy has to say about sub-grids. which are <a href="https://caniuse.com/?search=subgrid">currently only available in Firefox</a> (but it&rsquo;s been available there for over 2 years now).</p>
<p>The 8-minute video below shows a concrete, real-world example, where you can see how little effort is required to get the browser to just align everything for you, all without fixed minimum or maximum widths (just like it used to be with tables). It should be immediately obvious why this feature is both <em>a good thing</em> and <em>necessary</em> (because the behavior can&rsquo;t be replicated with existing CSS layout features).</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/IIQa9f0REtM" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=IIQa9f0REtM">Easy and more consistent layouts using subgrid</a> by <cite>Kevin Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>The 11-minute video below shows how the generalized mechanism lets you do the same thing for rows:</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/R7aHcgIeATE" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=R7aHcgIeATE">You can&#039;t do this without subgrid</a> by <cite>Kevin Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>You can find the full list of sub-grid videos (so far) in the <a href="https://www.youtube.com/playlist?list=PL4-IK0AVhVjM4Kjqw_zN-Y3neCFXWPDJ2">Subgrid playlist</a> by <cite>Kevin Powell</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>).</p>
<p>CSS sub-grids are an elegant way of aligning items without hard-coding anything (as required by existing techniques). They will continue to do what you expect regardless of the content added—i.e. there are no fixed minimum or maximum heights to make the alignment work, so you won&rsquo;t be surprised when one of these artificial restrictions limits the algorithm unnecessarily (as it would with flexbox or regular grids).</p>
<p>You can enable <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Subgrid">Subgrid</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) by including <code>grid-template-columns: subgrid</code>. My advice to the feature designers would be to rename the value to <code>grid-template-columns: inherit</code> because that would be closer to the mark. Several times in the video, Kevin has to correct himself that he&rsquo;s talking about <em>the same grid</em> rather than a <em>copy of the grid</em>. That&rsquo;s what the nested container is doing: it&rsquo;s inheriting the grid from a parent. Since it also has to declare itself as a <code>display: grid</code>, it can choose to <em>inherit</em> or explicitly set a template for its rows and/or columns. I think that would be relatively intuitive, but what do I know?</p>
<p>This feature kind of feels like a generalized way of getting back one of the advantages of the table-layout algorithm. The table-layout algorithm makes the cells in columns the same width throughout the table. This, despite the fact that the cells are all defined in different parents—and columns aren&rsquo;t even defined as elements at all. I think we all understand why it&rsquo;s not a good idea to abuse the table semantics just to be able to use the table layout algorithm. It&rsquo;s nice to see that the advantages of that layout are being rescued—and generalized to be even more powerful.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4359</guid>
    <title><![CDATA[Why can't identifiers start with a number?]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4359</link>
    <pubDate>Wed, 10 Nov 2021 11:01:27 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">10. Nov 2021 11:01:27 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The video <a href="https://www.youtube.com/watch?v=tX06aPu1aIg">I&rsquo;m not sure how much longer I can wait!</a> by <cite>Kevin Powell</cite> is an excellent introduction to sub-grids in CSS. But I was more interested in the fact that he told his viewers that,</p>
<blockquote class="quote quote-block "><div>&ldquo;you can use numbers in classes, but if you have a class or id that starts with a number, it&rsquo;s invalid. […] It&rsquo;s one of those weird things in CSS that sometimes trips people up.&rdquo;</div></blockquote><p>I immediately thought to myself, &ldquo;it&rsquo;s not weird. Every programming language is like that.&rdquo;</p>
<p>Then, I thought, &ldquo;I bet this guy only knows CSS, so he doesn&rsquo;t have anything to compare it to.&rdquo;</p>
<p>Then, I thought, &ldquo;Wait…why can&rsquo;t you start an identifier with a number?&rdquo;</p>
<p>And, finally, &ldquo;I bet it&rsquo;s a lexing/parsing thing.&rdquo;</p>
<h2>Parser or lexer?</h2><p>I&rsquo;ve written several parsers for medium-sized languages and my gut feeling is that letting an identifier start with a number seems like a surefire way of making the lexer more ambiguous or pushing more work into the parsing stage.</p>
<p>For example, if <code>25L</code> can be either an identifier <em>or</em> a long integer, then the parser has to figure out from context which one it is (e.g. by checking whether that identifier is declared). If it can only be a number, then it comes out of the lexer as a number token and the parser doesn&rsquo;t have to disambiguate.</p>
<p>Even if your language doesn&rsquo;t allow suffixes, you&rsquo;d still have the problem with an identifier like <code>25</code>, which would be legal <em>unless</em> you introduce the additional restriction that an identifier must have <em>at least</em> one alphabetic character. In that case, though, you might as well make the rule that the identifier has to <em>start</em> with an alphabetic character and avoid the whole ambiguity.</p>
<p>With that common—not weird!—rule, the disambiguation happens in the lexer, where the operation is clearer and less expensive, performance-wise.</p>
<h2>Unresolvable ambiguity</h2><p>It&rsquo;s actually worse than that, though. In the case of a programming language, you could see how the following would result in a compiler ambiguity:</p>
<pre class=" "><code>var 3 = 5; // I'm <em>already</em> confused
           //…the compiler gets it, though

var a = 3; // Now, the compiler's confused as well</code></pre><p>Is the developer assigned the value <code>3</code> to <code>a</code> or the variable <code>3</code>? Not only is this a terrible idea for readability, the compiler can literally not resolve this ambiguity without additional information. So there <em>have</em> to be restrictions on identifier names in order to avoid clashes with not only reserved words (e.g. <code>if</code>) but also manifest constants (e.g. <code>3</code>).</p>
<h2>Where&rsquo;s the problem with CSS?</h2><p>In the case of CSS, where you do have suffixes (e.g. <code>25px</code>) but you can&rsquo;t really mix class identifiers with values, it&rsquo;s possible that you could get away with no ambiguities <em>right now</em>. So it&rsquo;s not <em>weird</em> that you can&rsquo;t start an identifier with a number—it&rsquo;s perfectly natural for developers—but it is, in the case of CSS, not required for unambiguous processing. As you can see below, though, it&rsquo;s still kind of confusing for the user.</p>
<p>What if we have a class named &ldquo;3&rdquo;? It&rsquo;s not very expressive—we&rsquo;d probably call the class something like &ldquo;3-part-panel&rdquo;—but it&rsquo;s the pathological case. Maybe a class called &ldquo;3px&rdquo; would be even worse.</p>
<pre class=" "><code>.3-part-panel {
  /* This is fine */
}
.3 {
  /* Weird, but OK */
}
.3px {
  /* Now you're just being obnoxious */
}</code></pre><p>Do we actually get any ambiguities, though? I don&rsquo;t think so. I think in this case, the authors of CSS just used the &ldquo;standard&rdquo; (not weird!) definition of an identifier. It&rsquo;s only when you have people using CSS who have had no exposure to any other programming languages (or parsing/lexing) that you get people thinking it&rsquo;s &ldquo;weird&rdquo; that you can&rsquo;t start with a number.</p>
<p>The only place where you could get an ambiguity is with CSS customer properties. In that case, though, <span class="quote-inline">&ldquo;[a] custom property is any property whose name starts with two dashes&rdquo;</span>, according to <a href="https://drafts.csswg.org/css-variables/#defining-variables">CSS Custom Properties for Cascading Variables Module Level 1</a> (<cite><a href="http://drafts.csswg.org/">W3C</a></cite>). So, variable names in CSS are even <em>more</em> restricted than in most programming languages. Is that weird? Again, no. As in the case above with other programming languages, the end result is more clarity for the user.</p>
<p>For example, the following declares a few CSS custom properties with deliberately obnoxious names.</p>
<pre class=" "><code>:root {
  red: #F33;
  color: #FF0;
  0: 1;
  3px: 1px;
}

.error-text {
  color: var(red);
  background-color: var(color);
  border-width: var(3px);
  opacity: var(0);
}</code></pre><p>Although I&rsquo;ve chosen confusing values and names, this doesn&rsquo;t—at first glance—seem to cause any ambiguities. As with the examples above, it does force implementations to handle enumerations (e.g. all of the colors) in the parser, rather than the lexer. If the word &ldquo;red&rdquo; cannot be used as a variable, then it could (possibly) be recognized as its own token in the lexer, (possibly) improving performance.</p>
<p>The same goes for the property names. If it&rsquo;s possible for custom properties to use the same names as built-in properties, then the lexer can&rsquo;t handle them. There is no ambiguity because custom-property values must be <em>resolved</em> using the CSS function <code>var()</code>.</p>
<p>The problem is worse than that, though. There is an actual ambiguity that isn&rsquo;t obvious because we&rsquo;re using the <code>:root</code> pseudo-class [1]. The example below, using <code>&lt; html&gt;</code>, makes it clearer.</p>
<pre class=" "><code>html {
  color: #F33; // Is this setting the color 
               // …or declaring a color variable?
}</code></pre><p>This is an ambiguity that the compiler cannot resolve. So that&rsquo;s why the CSS designers settled on a prefix for custom properties.</p>
<p>So, to a layman or user of CSS, naming restrictions on class or custom-property identifiers may seem arbitrary and &ldquo;weird&rdquo;, but they are a logical requirement of being able to process the grammar unambiguously.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4359_1_body" class="footnote-number">[1]</span> If you know where I&rsquo;m headed, then fine, it&rsquo;s obvious <em>to you</em>. Congratulations. I didn&rsquo;t see it immediately, so I&rsquo;m writing it this way.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4280</guid>
    <title><![CDATA[C# 10 Features]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4280</link>
    <pubDate>Sat, 05 Jun 2021 23:04:48 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">5. Jun 2021 23:04:48 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Nov 2021 08:20:38 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://kenbonny.net/introducing-csharp-10">Introducing C# 10</a> by <cite>Ken Bonny</cite> discloses some incremental but very welcome changes to the C# language in the iteration that will be released with .NET 6 in November.</p>
<p>In no particular order:</p>
<ul>
<li><code>field</code> in property accesses to manipulate the backing property without having to define it. This is a welcome improvement that will clean up useless boilerplate for properties that need to do something with the value before storing it (e.g. <code>field.Trim()</code>)</li>
<li>The <code>required</code> keyword for properties in any of the supported types (e.g. <code>records</code>, <code>classes</code>, <code>structs</code>, or <code>struct records</code>). This lets types enforce initialization without forcing a constructor parameter. The compiler will force callers to initialize the property in the object initializer instead.</li>
<li><code>record struct</code> for records that are value instead of reference types</li>
<li><code>operator</code> overloads in <code>records</code></li>
<li>The <code>with</code> operator will work with anonymous classes as well as declared types.</li>
<li><code>global usings</code> for commonly used namespaces (e.g. <code>System</code>) to cut down on clutter in files</li>
<li><code>namespace</code> without braces will put all types in that file into that namespace. This cuts down on an indenting level in all files.</li>
<li>Improvements to lambdas: attributes on parameters and return types, explicit return types</li>
<li>Static methods on <code>interfaces</code> (to round out the default-implementation feature introduced in C# 9)</li>
<li>Constant interpolated <code>strings</code> (e.g. <code>$&rdquo;Hello {Name}&rdquo;</code> is considered constant if <code>Name</code> is also considered constant (recursively, of course). <strong class="highlight">Update on November 11th, 2021 from <a href="https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html">Dissecting Interpolated Strings Improvements in C# 10</a> by <cite>Sergey Teplyakov</cite> (<cite><a href="http://sergeyteplyakov.github.io/">Dissecting the Code</a></cite>):</strong> This feature is based on an a nice performance improvement, as well. The compiler now understands interpolated strings and emits more efficient code rather than always using <code>string.Format()</code>, which incurred allocations for unboxing, time for parsing, etc. There are even attributes to hook the compiler output that could be e.g, <span class="quote-inline">&ldquo;used by logging frameworks to avoid string creation if the logging level is off.&rdquo;</span></li>
<li><strong class="highlight">Update on June 7th, 2021 from <a href="https://medium.com/young-coder/a-closer-look-at-5-new-features-in-c-10-f99738b0158e">A Closer Look at 5 New Features in C# 10</a> by <cite>Matthew MacDonald</cite> (<cite><a href="http://medium.com/">Medium</a></cite>):</strong> Introduce <code>!!</code> suffix for method arguments that instructs the compiler to generated a null-check for that argument. So, <code>string</code> is not nullable, but not checked (i.e. the developer is responsible for including a check to avoid a <code>NullReferenceException</code> if one slips past the compiler), <code>string?</code> is nullable, and <code>string!!</code> is not nullable <em>and</em> checked. This will avoid a ton of boilerplate argument-checks. Can&rsquo;t wait.</li>
<li><strong class="highlight">Update on November 4th, 2021 from <a href="https://thomaslevesque.com/2021/11/04/a-quick-review-of-csharp-10-new-language-features/">A quick review of C# 10 new language features</a> by <cite>Thomas Levesque</cite>:</strong> The compiler will now <span class="quote-inline">&ldquo;[a]utomatically infer a “natural” type for a lambda&rdquo;</span>, so you can now use <code>var</code> to declare variable to which you assign a manifest lambda. E.g. <code>var isEven = (int n) =&gt; n % 2 == 0;</code> automatically gets the type <code>Func&lt; int, bool&gt;</code>.</li>
<li><strong class="highlight">Also from the same November 4th article:</strong> You can now <span class="quote-inline">&ldquo;[m]ix declarations and variables in deconstruction&rdquo;</span> so that you can now write <code>(x3, int y3) = p;</code> where <code>x3</code> is a preexisting variable.</li></ul><p>I really appreciate how the changes build on changes that came in previous versions. There&rsquo;s a very noticeable direction that they&rsquo;re pulling in with these languages changes:</p>
<ul>
<li>Being able to write performant code (records, refs, etc.)</li>
<li>Cutting down on boilerplate for common use cases (records, field, pattern-matching. etc.)</li>
<li>Being able to write maintainable, backwards-compatible code (interface default methods, etc.)</li>
<li>Improving type system (covariant returns, etc.)</li>
<li>Turning runtime issues into compile-time issues (nullability, etc.)</li></ul><p>For more information, see the <a href="https://github.com/dotnet/csharplang/tree/main/proposals">csharplang/proposals/</a> (<cite><a href="http://github.com/">GitHub</a></cite>) folder. Some of the C# 10 features are in the main folder rather in the <code>csharp-10.0/</code> folder.</p>
<p>&nbsp;</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4279</guid>
    <title><![CDATA[Handling Dependencies in Functional Languages]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4279</link>
    <pubDate>Sat, 05 Jun 2021 22:33:53 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">5. Jun 2021 22:33:53 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Out of curiosity, I looked up how dependency injection works in functional languages. I stumbled upon this amazing article series—<a href="https://fsharpforfunandprofit.com/posts/dependencies/">Six approaches to dependency injection</a> by <cite>Scott Wlaschin</cite> (<cite><a href="http://fsharpforfunandprofit.com/">F# for Fun and Profit</a></cite>)<br>
—that presents five different techniques—from very simple and easily applicable to more complex, but potentially robust.</p>
<p>The article series applies various abstraction techniques to a program that reads input, processes it, and writes it out again. The reading and writing are impure operations and should be abstracted away to make it easier to reason about and test the actual program logic.</p>
<p>The <a href="https://fsharpforfunandprofit.com/posts/dependencies/">first article</a> details <em>Dependency Retention</em> (hard-code everything; appropriate for scripts and POC projects) and <em>Dependency Rejection</em> (make an impure/pure/impure sandwich that collects program logic in a testable &ldquo;middle&rdquo;).</p>
<p>The next article covers <a href="https://fsharpforfunandprofit.com/posts/dependencies-2/">Dependency parameterization</a> (passing as parameters and using partial application in a separate abstraction layer). These are all pretty usable techniques.</p>
<p>The next two articles—<a href="https://fsharpforfunandprofit.com/posts/dependencies-3/">The Reader Monad</a> and <a href="https://fsharpforfunandprofit.com/posts/dependencies-4/">Dependency interpretation</a>—are more…involved. With both, you end up writing a description of your program that you can then execute by passing in the appropriate parameters. The dependencies are separate from the logic—in kind of in a separate layer—but there are drawbacks to these approaches. For one, they are quite complex and require everyone on the team to understand the patterns very well.</p>
<p>This is an example of the program description using the <code>Reader</code> monad.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4279/f_code.png"><img src="https://www.earthli.com/data/news/attachments/entry/4279/f_code.png" alt=" " style="width: 646px"></a></p>
<p>The <a href="https://fsharpforfunandprofit.com/posts/dependencies-5/">final article</a> applies all of these techniques to a slightly more complex problem domain, namely a user-profile update that receives an update request, reads from a database, compares data to determine updates, and sends an email to confirm address changes. This is complex enough that we can see how the techniques scale. As expected, the more complicated but functionally pure <em>Reader Monad</em> and <em>Dependency Interpretation</em> examples take up 2/3 of the implementation and explanation (with the later taking 50% all on its own).</p>
<p>All in all, this is impressive work that answered my question superbly. Highly recommended. I&rsquo;ve only very lightly summarized the pros and cons and descriptions above. The original author does a superb job of explaining these in much more detail—without repeating himself.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4118</guid>
    <title><![CDATA[CSS and HTML Toolbox 2021]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4118</link>
    <pubDate>Thu, 22 Apr 2021 18:20:27 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">22. Apr 2021 18:20:27 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. May 2025 10:15:48 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Over the last four months, I&rsquo;ve been collecting interesting HTML/CSS techniques and ideas. </p>
<ol>
<li>I&rsquo;m planning a bit of a make-over of the earthli style and stylesheets to replace some older cruft with more modern, simpler implementations.</li>
<li>I&rsquo;m planning a new curriculum for the JavaScript class I&rsquo;ll be teaching again this coming winter.</li></ol><p>For both of these goals, I&rsquo;m focusing on leveraging as much of the power of the browser—especially CSS/HTML—as possible without getting mired in too much JavaScript or client-side libraries.</p>
<p>To that end, I&rsquo;ve collected the stuff I learned and would like to use in a hopefully semi-readable and searchable format. I tried to split it into coherent sections with supporting information and links. YMMV.</p>
<h2>Guides and Resources</h2><p>The following guides/manuals contain a wealth of information.</p>
<dl><dt class="field"><a href="https://developer.mozilla.org/en-US/docs/Web/CSS">MDN CSS</a></dt>
<dd>MDN is definitely the OG of web sites, with amazing examples and in-depth documentation of everything HTML and CSS. I have n idea how they stay so up-to-date or who pays for it, but it&rsquo;s amazing and much-appreciated</dd>
<dt class="field"><a href="https://www.w3schools.com/css/">W3Schools</a></dt>
<dd>This site is also very complete and, while it doesn&rsquo;t have as much description or documentation as MDN, it has a lot of interactive samples—check out the animation and transform ones—and is easy to browse.</dd>
<dt class="field"><a href="https://css-tricks.com/">CSS-Tricks</a></dt>
<dd>This site has a lot of in-depth articles on various CSS features by various authors. You can find an in-depth article for any of the features discussed below.</dd>
<dt class="field"><a href="https://web.dev/">web.dev</a></dt>
<dd>This site is run by (sponsored by?) Google and it contains a ton of articles and videos and tutorials for taking advantage of the cutting edge of web technology, with an eye toward using advanced features common to all browsers, but also introducing some of the stuff that Chrome has that hasn&rsquo;t been fully adopted yet.</dd>
<dt class="field"><a href="https://almanac.httparchive.org/en/2020/css">Web Almanac By HTTP Archive</a></dt>
<dd>This is an interesting guide that shows usage statistics for certain features. It&rsquo;s enormous and shows an insane amount of detail about e.g. how many sites use flexbox or grid.</dd>
<dt class="field"><a href="https://2020.stateofcss.com/en-US/features/">State of CSS</a></dt>
<dd>In particular for this article, you can check out the usage level of specific <a href="https://2020.stateofcss.com/en-US/features/">features</a>. This list is definitely worth a look, as a supplement to the features I outline below.</dd>
<dt class="field"><a href="https://caniuse.com/">CanIUse</a></dt>
<dd>While MDN also shows you the browser support for features, this site is very searchable and includes links for a tremendous amount of supporting information about quirks and flags for cutting-edge features.</dd>
</dl><h2>Complexity</h2><p>The article <a href="https://timseverien.com/posts/2020-12-06-what-makes-css-hard-to-master/">What Makes CSS Hard To Master</a> has several interesting examples, but it mostly boils down to: &ldquo;HTML documents are complex programs&rdquo;.</p>
<p>It&rsquo;s always been difficult to tell which styles are applied when—it&rsquo;s a near-miracle that browsers can untangle the myriad ways that style rules interact with an ever-changing DOM and viewport size <em>correctly</em> to say nothing of doing so with such sheer <em>alacrity</em>.</p>
<p>There are selectors, media queries, related properties (e.g. <code>position</code>), CSS Properties, and much more and all of it <em>cascades</em> with inheritance everywhere. At least most browsers now handle this similarly with predictable performance.</p>
<p>A tremendous amount of content is generated dynamically using layers of framework code, either on the server or the client. Any one of these moving parts could introduce a seemingly innocuous change that breaks the entire layout or inheritance (e.g. when a component introduces a wrapping <code>&lt;div&gt;&lt;/div&gt;</code> somewhere, either where it&rsquo;s flatly invalid (e.g. a table) or where it&rsquo;s just unwanted (e.g. in a sequence of flexing containers, where the new container does not flex).</p>
<p>To control this chaos, most designers and developers impose self-discipline and use guidelines to avoid confusion while still allowing them to leverage the power of CSS to be able to do what they want.</p>
<p>From the article linked above,</p>
<blockquote class="quote quote-block "><div>&ldquo;I think mastering CSS comes down to having a good amount of knowledge about it, recognising the subtle dependencies between different declarations, rules, and the DOM, understanding how they make your CSS complex, and how to best avoid them.&rdquo;</div></blockquote><p>Congratulations: you&rsquo;ve just described programming at anything but a trivial level of complexity. If a tool has power, then you have to understand it in order to avoid hurting yourself with it. That&rsquo;s why &ldquo;everyone codes&rdquo; is a lost cause doomed to end in failure, broken dreams, and embarrassed disappointment, like so many other quixotic attempts to ignore immanent complexity.</p>
<p>CSS is a moving target. Things that used to be difficult are now easy. [1] But that&rsquo;s the nature of the game: someone is going to abstract away the thing you spent time learning and make it easier for everyone else. That is the nature of abstraction and frameworks. If the new thing (e.g. <code>grid</code>) replaces the old thing (e.g. <code>float</code>) <em>well</em> and you have <em>time</em> and <em>budget</em> to use the new thing <em>and</em> it&rsquo;s a <em>priority</em> then, by all means, upgrade to use the new technique and pay down some technical debt, while hopefully gaining some flexibility.</p>
<h2>Generators</h2><p>While CSS generators—pre-processors like LESS and SASS—are invaluable, they also introduce another layer of abstraction where code is generated for the developer—sometimes with unpredictable results.</p>
<p>The latest versions of CSS have included some of the features introduced in these generators. Vendor prefixes are less necessary than they used to be; CSS properties and variables and <code>eval()</code> (as well as other standard functions) allow a flexibility beyond even that offered by pre-processor variables. Color and transformation and animation functions are standard now.</p>
<h2>Standard Layouts</h2><p>Check out the site <a href="https://smolcss.dev/">SmolCSS</a> by <cite>Stephanie Eckles</cite> for a long list of common layouts, like:</p>
<ul>
<li>Responsive CSS Grid</li>
<li>Modern Centering</li>
<li>Avatar List Component</li>
<li>Stack Layout</li>
<li>And much more…</li></ul><p>It&rsquo;s called &ldquo;smol&rdquo; because almost all of them do a <em>lot</em> of heavy lifting with very few lines of CSS.</p>
<p><span style="width: 490px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4118/smol.png"><img src="https://www.earthli.com/data/news/attachments/entry/4118/smol.png" alt=" " style="width: 490px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4118/smol.png">Smol Grid Layout</a></span></span></p>
<h2>Selectors</h2><p>The article <a href="https://moderncss.dev/guide-to-advanced-css-selectors-part-one/">Guide to Advanced CSS Selectors − Part One</a> by <cite>Stephanie Eckles</cite> (<cite><a href="http://moderncss.dev/">Modern CSS</a></cite>) is a good overview with good illustrations and some selectors I&rsquo;d never heard of, like <a href="https://moderncss.dev/guide-to-advanced-css-selectors-part-one/#general-sibling-combinator">General Sibling Combinator</a>, which <span class="quote-inline">&ldquo;[f]or example, <code>p ~ img</code> would style all images that are located somewhere after a paragraph provided they share the same parent.&rdquo;</span></p>
<p>That whole site is beautiful and exhibits an absolute mastery of CSS. Check out the use of the <code>skew</code> <code>transform</code> for the cards at the bottom of the page or for the <a href="https://moderncss.dev">whole series</a>. The rainbow gradients on the <code>:before</code> and <code>:after</code> borders and backgrounds are a great idea and well-executed.</p>
<p>The excellent tutorial <a href="https://codersblock.com/blog/diving-into-the-before-and-after-pseudo-elements/">Diving into the ::before and ::after Pseudo-Elements</a> by <cite>Will Boyd</cite> (<cite><a href="http://codersblock.com/">Coder&#039;s Block</a></cite>) is an absolute treasure trove of information, including how to use the <code>::before</code>/<code>::after</code> pseudo-elements to insert content, but also noting how a classic use of <code>::after</code> can now be replaced with <code>display: flow-root</code> (the modern <em>clearfix</em>). He also covers <code>::markers</code>.</p>
<p>The article <a href="https://www.bram.us/2021/03/19/three-important-things-you-should-know-about-css-is/">Three important things you should know about CSS :is()</a> (<cite><a href="http://www.bram.us/">Bramus</a></cite>) gives a few caveats but also shows the power of this operator to reduce CSS clutter (along with the up-and-coming <em>nesting</em> feature described <a href="#nesting">below</a>). You can use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:where"><code>where()</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) instead of <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:is"><code>is()</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) to keep the specificity contribution of the clause neutral. The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:has"><code>has()</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) selector function is defined, but isn&rsquo;t available anywhere. Combine any of these with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:not"><code>not()</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) for even more powerful selectors.</p>
<h2>Properties</h2><p>The article <a href="https://webplatform.news/issues/2020-12-04">CSS custom properties are not variables</a> (<cite><a href="http://webplatform.news/">Web Platform News</a></cite>) explains a common misconception about CSS &ldquo;variables&rdquo;.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;A custom property is not a variable, but it defines a variable. Any property can use <em>variables</em> with the <code>var()</code> function whose values are defined by their associated custom <em>properties</em>.</p>
<p>&ldquo;[…] This distinction is useful because it allows us to talk about “variables with fallback values” (a custom property like any other property cannot have a fallback value) and “properties using variables” (a property cannot use a custom property)&rdquo;</p>
</div></blockquote><p>Another great article is <a href="https://www.joshwcomeau.com/css/styled-components/">The styled-components Happy Path</a> by <cite>Josh W. Comeau</cite>. which discusses styling with CSS properties in React components. In it, he references another article of his, <a href="https://www.joshwcomeau.com/css/css-variables-for-react-devs/&#039;">CSS Variables in React tutorial</a>, which is more of an introduction to some of the techniques he works with in the first article.</p>
<p>You commonly properties with default values on the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:root">:root pseudo-selector</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>). [2]</p>
<p>The article <a href="https://codersblock.com/blog/what-can-you-put-in-a-css-variable/">What Can You Put in a CSS Variable?</a> shows a lot of nice uses of CSS properties, variables, and <a href="https://www.w3schools.com/csSref/css_functions.asp">functions</a> (<cite><a href="http://www.w3schools.com/">W3Schools</a></cite>). CSS Properties can basically hold anything you want: text, concatenated strings, references to variables, images via urls, a single value, multiple values, etc. [3]</p>
<blockquote class="quote quote-block "><div>&ldquo;Some properties, like <code>background</code> and <code>box-shadow</code>, can take a list of things. You can use a CSS variable as a single item in the list, a sublist of the list, or the entire list.&rdquo;</div></blockquote><p>As mentioned above, declaring colors is one of the primary uses of a CSS pre-processor language. CSS Properties handle this job very nicely, without preprocessing and also with full recalculation at runtime. [4] The <a href="https://codepen.io/lonekorean/pen/PoGNxjE">demo</a> with the set of animated RGB sliders that control the color of a swatch is worth the price of admission. All without any JavaScript at all. Smooth as butter.</p>
<p>As a practical application, the article <a href="https://www.bram.us/2021/02/01/make-the-page-count-of-a-3d-book-visible-using-css-custom-properties/">Make the page count of a 3D book visible using CSS Custom Properties</a> shows how you can use CSS to make a &ldquo;book&rdquo; out of a div and a cover image, transforming it in 3D-space and then using a CSS property to determine how many &ldquo;pages&rdquo; it looks like it has.</p>
<p><span style="width: 403px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-02-01_at_22.10.37.png"><img src="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-02-01_at_22.10.37.png" alt=" " style="width: 403px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-02-01_at_22.10.37.png">Book with code</a></span></span></p>
<p><a href="https://jsbin.com/tosikapope/edit?html,css,output">You can play with a demo here.</a></p>
<p>You can find a simpler and very straightforward demo in the article <a href="https://christianheilmann.com/2021/02/08/sharing-data-between-css-and-javascript-using-custom-properties/">Sharing data between CSS and JavaScript using custom properties</a> by <cite>Christian Heilmann</cite>, which shows how to use CSS properties with a few lines of JavaScript to follow the cursor in your document.</p>
<p><a href="https://ishadeed.com/article/practical-css-variables/">Practical Use Cases For CSS Variables</a> by <cite>Ahmad Shadeed</cite> provides many, many short examples and ideas for using custom properties as an abstraction instead of setting one or more standard properties directly.</p>
<div class="caution "><p><strong>Future work:</strong> See <a href="#property_proposals">below</a> for a discussion of proposed but not yet supported extensions and uses of CSS Properties. </p>
</div><h2>(Custom) Media Queries</h2><p>The article <a href="https://polypane.app/blog/the-complete-guide-to-css-media-queries/">The complete guide to CSS media queries</a> is a great overview of how media queries work, but also how they&rsquo;ve changed recently for those who&rsquo;ve gotten accustomed to them over the years. For example, the section <a href="https://polypane.app/blog/the-complete-guide-to-css-media-queries/#new-notations-in-media-query-levels-4-and-5">New notations in Media query levels 4 and 5</a> shows how ranges are easier, how you can now use <code>or</code>, the <code>not()</code> function, and <em>custom media queries</em>, which allows you to basically make aliases for media query combinations that you need to use in several places.</p>
<pre class=" "><code>/* Define your custom media query */
@custom-media –small-screen (max-width: 768px);

/* Then use it somewhere in your stylesheet */
@media (–small-screen) {
}

/* You can also combine it with other media features */
@media (–small-screen) and (pointer: fine) {
  /* styling for small screens with a stylus */
}</code></pre><h2>Gradient Overlays</h2><p>The article <a href="https://ishadeed.com/article/handling-text-over-image-css/">Handling Text Over Images in CSS</a> by <cite>Ahmad Shadeed</cite> gives a wonderful overview with many examples on how to use gradient overlays on images to make overlay text readable for all types of images. At the end, you can see how many sites are using this (including YouTube for its overlay video controls).</p>
<p>See also the <a href="https://moderncss.dev">gradients</a> used in borders (hover over a &ldquo;card&rdquo;), headers, and other elements in the ModernCSS tutorial.</p>
<h2>Animations &amp; Transitions</h2><p>Check out <a href="https://www.bram.us/2021/01/29/animating-a-css-gradient-border/">Animating a CSS Gradient Border</a>, which has <em>no JavaScript</em>. It leverages a newer feature of Chrome-based renderers to avoid writing a lot of keyframe boilerplates, but it&rsquo;s all in CSS. You <em>could</em> write it all in bog-standard CSS.</p>
<p>Another example is a slide show written with only HTML and CSS. You can keep all slides in a single document and make animated transitions between them. See <a href="https://www.bram.us/2021/01/24/how-to-play-and-pause-css-animations-with-css-custom-properties/">How to Play and Pause CSS Animations with CSS Custom Properties</a> for ideas. The article <a href="https://www.joshwcomeau.com/animation/css-transitions/">An Interactive Guide to CSS Transitions</a> provides a lot of background and interactive examples of how transitions work and how you can influence their behavior.</p>
<p>CSS animations apply to many, many properties—in all modern browsers—as detailed in the article <a href="https://codersblock.com/blog/the-surprising-things-that-css-can-animate/">The Surprising Things That CSS Can Animate</a> by <cite>Will Boyd</cite> (<cite><a href="http://codersblock.com/">Coder&#039;s Block</a></cite>), which shows how easy it is to animate box-shadows (for a &ldquo;pulsating&rdquo; effect) or even z-order, with a few other properties, to animate two items &ldquo;switching places&rdquo; in a very intuitive way—all <em>without</em> JavaScript.</p>
<h2>Tooltips</h2><p>The article <a href="https://www.bram.us/2020/12/28/cooltipz-css-pure-css-customisable-tooltips/">Cooltipz.css — Pure CSS Customisable Tooltips</a> by <cite>Bramus van Damme</cite> includes a good demonstration of <a href="https://cooltipz.jackdomleo.dev">Cooltipz</a>. This library uses very modern, but well-supported techniques to place and format tooltips or flyouts (for non-desktop browsers).</p>
<h2>Shapes</h2><p><a href="https://ishadeed.com/article/clip-path/">Understanding Clip Path in CSS</a> shows how to work with the standard shape functions and combinators and the <code>clip-path</code> property to make pure-CSS non-rectangular accents and effects that run on all modern browsers.</p>
<p>The article <a href="https://responsibleweb.app">Responsible Web Applications</a> by <cite>Joy Heron</cite> is an absolutely lovely design that illustrates the power and simplicity of pure CSS. Right at the very top, it uses <code>shape-outside</code> and <code>circle</code> to make text wrap elegantly around a circular shape that contains the navigation.</p>
<p><span style="width: 534px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-01-31_at_13.08.56.png"><img src="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-01-31_at_13.08.56.png" alt=" " style="width: 534px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-01-31_at_13.08.56.png">shape-outside in action</a></span></span></p>
<p>The key piece of CSS is very compact and understandable.</p>
<pre class=" "><code>shape-outside: circle(21rem at 1.5rem 40%);</code></pre><p>The page makes liberal use of CSS custom properties (see below) and <code>rem</code> units to make everything scale nicely. It&rsquo;s kind of a master class in CSS and is well worth reading.</p>
<h2>Background clipping</h2><p>Speaking of clipping, you can assign the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip">background-clip</a> property to determine which part of its element a background covers. In particular, setting it to the value <code>text</code> clips the background to show through only for area covered by text. It&rsquo;s been supported for quite some time and allows developers to make dynamic effects that would otherwise have to be hard-coded in graphics.</p>
<p>The article <a href="https://www.bram.us/2021/03/15/css-background-clip-demo-text-with-animated-emoji/">CSS <code>background-clip</code> Demo: Text with Animated Emoji</a> shows a neat demo of an animated SVG ghost moving back and forth behind clipped text.</p>
<p><span style="width: 516px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4118/image_2021-03-16_221723.png"><img src="https://www.earthli.com/data/news/attachments/entry/4118/image_2021-03-16_221723.png" alt=" " style="width: 516px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4118/image_2021-03-16_221723.png">background-clip with ghost emoji behind it</a></span></span></p>
<h2>Filters</h2><p>In the same ballpark is the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter"><code>backdrop-filter</code></a>, which allows you to apply filters to everything behind a particular element. Naturally, you need to make the element at least partially transparent in order to see the effect.</p>
<p><span style="width: 347px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-03-16_at_22.37.56.png"><img src="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-03-16_at_22.37.56.png" alt=" " style="width: 347px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-03-16_at_22.37.56.png">backdrop-filter example</a></span></span></p>
<p>The CSS is very simple and supported on all modern browsers. Being able to create this kind of composition dynamically on the client brings very nice effects without pre-rendered compositing.</p>
<h2>Clipping and masking</h2><p><a href="https://www.bram.us/2020/12/28/css-paper-snowflakes/">CSS Paper Snowflakes</a> combines <code>transforms</code>, <code>clip-paths</code>, <code>mask-images</code>, and tons of properties and variables to render what look like pre-built graphics using only CSS (well, SCSS in this case).</p>
<p>The article <a href="https://www.bram.us/2021/01/14/css-mix-blend-mode-not-working-set-a-background-color/">CSS <code>mix-blend-mode</code> not working? Set a <code>background-color</code>!</a> (<cite><a href="http://www.bram.us/">Bramus</a></cite>) illustrates how to use the <code>mix-blend-mode</code> to make sure that the text has proper contrast versus whichever background it happens to be over.</p>
<p><span style="width: 580px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-01-16_at_23.09.28.png"><img src="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-01-16_at_23.09.28.png" alt=" " style="width: 580px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4118/screen_shot_2021-01-16_at_23.09.28.png">mix-blend-mode: difference in action</a></span></span></p>
<p>This is a really nice effect and very handy for usability. You can have the browser ensure that text is always readable, regardless of what kind of background slides into place behind it.</p>
<h2>Sticking &amp; Snapping</h2><p>The article <a href="https://www.bram.us/2020/01/10/smooth-scrolling-sticky-scrollspy-navigation/">Smooth Scrolling Sticky ScrollSpy Navigation</a> provides a tutorial for building a JS-free TOC with sticky headers. The article <a href="https://css-tricks.com/smooth-scrolling-accessibility/">Smooth Scrolling and Accessibility</a> by <cite>Heather Migliorisi</cite> (<cite><a href="http://css-tricks.com/">CSS Tricks</a></cite>) provides some background, history, and advice on honoring user preferences.</p>
<p>The following CSS is enough to get started. The full demo shows how to use a little bit of JS with an <code>IntersectionObserver</code> to implement the ScrollSpy feature in just one line of code.</p>
<pre class=" "><code>html {
  scroll-behavior: smooth;
}

main &gt; nav {
  position: sticky;
  top: 2rem;
  align-self: start;
}</code></pre><p>The article <a href="https://christianheilmann.com/2021/02/09/using-position-sticky-to-create-persistent-headers-in-long-texts/">Using position: sticky to create persistent headers in long texts</a> by <cite>Christian Heilmann</cite> provides a very minimal and highly re-usable example of using this feature for &ldquo;sticking&rdquo; headers to the top of the page when scrolling.</p>
<pre class=" "><code>h1, h2, h3, h4 {
  position: sticky;
  top: 0;
}</code></pre><p>And there&rsquo;s also <code>scroll-snap-type</code>, <code>scroll-snap-align</code>, and browser units (e.g. <code>vw</code> and <code>vh</code>) to basically make a slide show out of an HTML file without any JavaScript (<a href="https://codepen.io/bramus/pen/GRJGyGE">demo</a> or another <a href="https://codepen.io/Rik/pen/WNGZodZ">demo</a> with some additional JS to highlight the displayed slide/image in a thumbnail browser).</p>
<ul>
<li>The article <a href="https://www.bram.us/2020/12/21/sticky-css-grid-items/">Sticky CSS Grid Items</a> is also good (another <a href="https://codepen.io/Rik/pen/bGwoBaR">demo</a> shows an address-book-like implementation)</li>
<li>The article <a href="https://calendar.perfplanet.com/2020/html-and-css-techniques-to-reduce-your-javascript/">HTML and CSS techniques to reduce your JavaScript</a> is a multi-step tutorial to make picture browsers with &ldquo;snap points&rdquo; and more tricks to control scrolling with minimal or no code.</li>
<li>The article <a href="https://css-tricks.com/practical-css-scroll-snapping/">Practical CSS Scroll Snapping</a> by <cite>Max Kohler</cite> (<cite><a href="http://css-tricks.com/">CSS-Tricks</a></cite>) provides many more examples and techniques.</li></ul><p>As for &ldquo;sticky&rdquo; or &ldquo;stuck&rdquo; elements,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] there is one limitation: <strong>it is impossible to change the appearance of an element whether it is stuck or not, say with a pseudo-class <code>:stuck</code></strong>. This is a general limitation of CSS. In this case, I recommend combining the benefits of position: sticky to keep the element sticking with <code>IntersectionObserver</code> to change its appearance (while taking care not to change its dimensions, to prevent content jumps).&rdquo;</div></blockquote><p>The <a href="https://css-tricks.com/a-table-with-both-a-sticky-header-and-a-sticky-first-column/">A table with both a sticky header and a sticky first column</a> by <cite>Chris Coyier</cite> (<cite><a href="http://css-tricks.com/">CSS Tricks</a></cite>) provides a good example of using sticky to make frozen columns in tables.</p>
<p>For a <em>really</em> fancy scroll-spy, see the <a href="https://lab.hakim.se/progress-nav/">Progress Nav</a> demo. This is very cool-looking, but it&rsquo;s a little bit older, so also check out the <a href="https://www.bram.us/2021/03/20/progress-nav-with-intersectionobserver/">Progress Nav with IntersectionObserver</a> by <cite>Bramus</cite> for a linked version that does the same thing, but uses the <code>IntersectionObserver</code> to reduce the amount of code significantly.</p>
<h2>Line clamping</h2><p>For limiting text in a box, you can let the browser do all of the heavy lifting by using <code>line-clamp</code> or the even smoother and also standardized <code>webkit-line-clamp</code>. See a <a href="https://codepen.io/Rik/pen/jOMGVGY">demo</a> that shows how to use it in a grid layout.</p>
<h2>Functions</h2><p>The <code>line-clamp</code> feature is not to be confused with the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/clamp()"><code>clamp()</code></a> CSS function, which is shorthand for bounding a value between a <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/min()"><code>min()</code></a> and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/max()"><code>max()</code></a>.</p>
<p>There are a <em>ton</em> of <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions">CSS functions</a>, for math, colors, filters, images, fonts, shapes, and more. You can use all of these with variables and custom properties to avoid whole swaths of JavaScript.</p>
<h2>Grid layouts</h2><p>You&rsquo;ll want to use <code>minmax</code> to override the default minimum size of <code>auto</code>, which is content-sizing, which can get quite large in what the cool kids are calling a <span class="quote-inline">&ldquo;grid blowout&rdquo;</span>. See <a href="https://www.bram.us/2021/01/28/the-minimum-content-size-in-css-grid/">The Minimum Content Size In CSS Grid</a> (<cite><a href="http://www.bram.us/">Bramus</a></cite>) for examples, graphics, and more links and guides.</p>
<p>The tutorial <a href="https://www.bram.us/2021/01/23/building-a-side-navigation/">Building a Side Navigation</a> pulls a lot of concepts together to create a common UI element that tends to become a time sink if you don&rsquo;t plan correctly. A lot of the CSS features used in this article help to reduce the work significantly.</p>
<h2>Table Columns</h2><p>If you&rsquo;ve ever wondered what you need <code>&lt;col&gt;</code> and <code>&lt;colgroup&gt;</code> for, then <a href="https://www.matuzo.at/blog/highlighting-columns/#table1-heading">Highlighting columns in HTML tables</a> by <cite>Manuel Matuzovic</cite> will show you how to use them to apply styling to a column without much additional markup. He even has an example that styles a &ldquo;selected&rdquo; column using the <code>:target</code> pseudo-selector.</p>
<h2>Images</h2><p>You can also use a simple attribute to tell the browser to be <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-loading">proactive about loading images</a>.</p>
<p>The article <a href="https://thoughtbot.com/blog/alt-vs-figcaption">Alt vs Figcaption</a> by <cite>Elaina Natario</cite> (<cite><a href="http://thoughtbot.com/">ThoughtBot</a></cite>) nicely illustrates how well browsers now handle the <code>FigCaption</code> tag, which is yet another feature I&rsquo;d implemented on earthli long ago, but with custom HTML and extra containers and positioning code. It&rsquo;s nice to know that I can replace that all with a single attribute that&rsquo;s been supported for years.</p>
<h2>Viewport units</h2><p>Viewport units let the developer size elements based on the size of the viewport. This includes not only <code>vw</code> and <code>vh</code>, but also <code>vmin</code> and <code>vmax</code>, which is the minimum or maximum of the two viewport dimensions, respectively.</p>
<p>The article <a href="https://css-tricks.com/simple-little-use-case-vmin/">Simple Little Use Case for <code>vmin</code></a> by <cite>Chris Coyier</cite> shows a very simple way to make a highly responsive header without using media queries.</p>
<pre class=" "><code>header 
{
  padding: 10vmin 1rem;
}</code></pre><h2>Controls</h2><p>The article <a href="https://www.bram.us/2021/01/13/accept-several-email-addresses-in-a-form-with-the-multiple-attribute/">Accept several email addresses in a form with the <code>multiple</code> attribute</a> (<cite><a href="http://www.bram.us/">Bramus</a></cite>) shows you how to use the <code>multiple</code> property to have the browser automatically validate multiple email addresses, all without any custom JavaScript at all.</p>
<p>Once you&rsquo;re using HTML validations (and you should), you can use the <code>:invalid</code> pseudo-selector to style elements that need correction. <a href="https://www.bram.us/2021/01/28/form-validation-you-want-notfocusinvalid-not-invalid/">Form Validation: You want <code>:not(:focus):invalid</code>, not <code>:invalid</code></a> (<cite><a href="http://www.bram.us/">Bramus</a></cite>) shows several ways of combining it with good UX to avoid annoying users with hyperactive validation messages.</p>
<p>A good setup is:</p>
<pre class=" "><code>.error-message {
    display: none;
}

input:not(:focus):invalid {
  border-color: var(–color-invalid);
}

input:not(:focus):invalid ~ .error-message {
  display: block; 
}

input:not(:focus):not(:placeholder-shown):valid {
  border-color: var(–color-valid);
}</code></pre><p>There&rsquo;s also the new <code>:focus-visible</code> property to help perfect focus-display in forms.</p>
<pre class=" "><code>/* Hide focus styles if they're not needed, for example, 
when an element receives focus via the mouse. */
:focus:not(:focus-visible) {
  outline: 0;
}

/* Show focus styles on keyboard focus. */
:focus-visible {
  outline: 3px solid blue;
}</code></pre><p>See <a href="https://www.bram.us/2021/01/28/focus-visible-is-here/"><code>:focus-visible</code> Is Here</a> (<cite><a href="http://www.bram.us/">Bramus</a></cite>) for more information.</p>
<p>Password controls need a bit more love, as documented in the article <a href="https://www.scottbrady91.com/Authentication/Perfecting-the-Password-Field-with-the-HTML-passwordrules-Attribute">Perfecting the password field with the HTML passwordrules attribute</a> by <cite>Scott Brady</cite>, which makes the case for a new attribute <code>passwordrules</code> to be standardized. His focus is on making password fields maximally accessible and usable for password tools.</p>
<p>A weaker—but available—alternative to his proposal is to use the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/password#htmlattrdefpattern">pattern</a> property to restrict input (helping the user, but not the password generator). To that end, he also mentions that you should set the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete"><code>autocomplete</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>), <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocapitalize"><code> autocapitalize</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>), and <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#autocorrect"><code>autocorrect</code></a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) (non-standard) properties correctly instead of just leaving them at the defaults.</p>
<h2>User-resizing</h2><p>The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/resize">resize</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) CSS property controls the directions in which the user will be able to resize any DOM element.</p>
<blockquote class="quote quote-block "><div>&ldquo;The <code>resize</code> CSS property sets whether an element is resizable, and if so, in which directions.&rdquo;</div></blockquote><div class="error " style="resize: both; width: 200px">This box should be resizable.</div><h2>Accessible Components</h2><p>The article <a href="https://www.smashingmagazine.com/2021/03/complete-guide-accessible-front-end-components/">A Complete Guide To Accessible Front-End Components</a> includes everything from guidance to links to tutorials to full-fledged examples and screenshots of HTML/CSS/JS  implementations of commonly used controls that are also accessible.</p>
<ul>
<li><a href="http://scottaohara.github.io/accessible_modal_window/">Modals</a></li>
<li><a href="https://www.sitepoint.com/accessible-footnotes-css/">Footnotes</a></li>
<li><a href="https://tabpanelwidget.com/">Tabs</a></li>
<li>And <a href="https://www.smashingmagazine.com/2021/03/complete-guide-accessible-front-end-components/">couple of dozen more…</a></li></ul><p>The &ldquo;Tab Panel&rdquo; is quite nice in that it responsively switches to an accordion at smaller widths.</p>
<p>The article <a href="https://web.dev/building-a-settings-component/">Building a Settings component</a> by <cite>Adam Argyle</cite> (<cite><a href="http://web.dev/">web.dev</a></cite>) demonstrates accessible components using a lot of pretty advanced—but generally available—techniques, like properties, grids (w/align-items, vw, minmax, auto-fit for pretty much automatic responsiveness with nearly no code), dark/light theming, light JS manipulation of controls, <code>FormData</code>, <code>accent-color</code>, and much more. Watch the <a href="https://www.youtube.com/watch?v=dm7gnp6eh3Q">embedded video</a> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>) for a very quick, 8-minute overview, play with the <a href="https://www.youtube.com/redirect?event=video_description&amp;redir_token=QUFFLUhqbGg0R3NJQTBnUFp5eS1pVHJJcmwxQzlFWHQ5QXxBQ3Jtc0ttS1NrWV9mQnRhajF2anh0NzZFRFJFZEwxTTIwVEtUY0hmcm9iQ3F5S01kY3FPcFFXT1FTU1pjUEp3b2ZvTFhJVlBKR1NmMVpVNnFOb0U5X1Y2UkJXTm5Ybi1nVjNzTUk3aXlUWXZUVHRKckZjVDQ4aw&amp;q=http%3A%2F%2Fgoo.gle%2F3qysEbW">live demo</a> or grab the <a href="https://github.com/argyleink/gui-challenges/tree/main/settings">source</a> (<cite><a href="http://github.com/">GitHub</a></cite>).</p>
<h2>Web Components</h2><p><a href="https://open-wc.org/guides/knowledge/styling/styles-piercing-shadow-dom/#styling-styles-piercing-shadow-dom">Styling: Styles Piercing Shadow DOM</a> shows you how to reset all styles in your component, using the <code>:host</code> pseudo-selector.</p>
<pre class=" "><code>:host {
  /* Reset specific CSS properties */
  color: initial;

  /* Reset all CSS properties */
  all: initial;
}</code></pre><p>The article <a href="https://nolanlawson.com/2021/01/03/options-for-styling-web-components/">Options for styling web components</a> by <cite>Nolan Lawson</cite> (<cite><a href="http://nolanlawson.com/">Read the Tea Leaves</a></cite>) shows how to design a styling API for a web component using CSS custom properties.</p>
<h2>Custom Form Elements</h2><p>The article <a href="https://css-tricks.com/creating-custom-form-controls-with-elementinternals/">Creating Custom Form Controls with ElementInternals</a> by <cite>Caleb Williams</cite> (<cite><a href="http://css-tricks.com/">CSS Tricks</a></cite>) introduces an interesting concept. The example it uses is to make a single &ldquo;control&rdquo; that holds several text inputs, which isn&rsquo;t groundbreaking, but it does show the power of packaging CSS/HTML/JS as components that show up as simple tags with properties. </p>
<p>None of that is new—we&rsquo;ve had web components for a while now—but the <code>ElementInternals</code> allows deep integration into the form&rsquo;s workings, including hooking validation, submitting, drawing, and so on.</p>
<h2>The <code>inherit</code> value</h2><p>The <code>inherit</code> value is not new, but I often forget to use it as intended. It&rsquo;s meant to help avoid re-stating a base color.</p>
<p>The following example changes the color for the <code>nav</code> tags to <code>red</code>, but wants links to retain the original color.</p>
<pre class=" "><code>body { color: black; }
nav { color: red; }
nav a { color: black; }</code></pre><p>Instead of repeating the value <code>black</code>, you can instead use <code>inherit</code>.</p>
<pre class=" "><code>body { color: black; }
nav { color: red; }
nav a { color: inherit; }</code></pre><p>The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/initial">initial</a> value is also useful.</p>
<h2><code>content-visibility</code></h2><p>The article <a href="https://www.bram.us/2020/08/10/content-visibility-the-new-css-property-that-boosts-your-rendering-performance/"><code>content-visibility</code>: the new CSS property that boosts your rendering performance</a> discusses a very new feature. It landed in official releases of Chrome, Opera, and Edge in September 2020.</p>
<blockquote class="quote quote-block "><div>&ldquo;The <code>content-visibility</code> CSS property controls whether or not an element renders its contents at all, along with forcing a strong set of containments, allowing user agents to potentially omit large swathes of layout and rendering work until it becomes needed. Basically it enables the user agent to skip an element&rsquo;s rendering work, including layout and painting, until it is needed, makes the initial page load much faster.&rdquo;</div></blockquote><p>Related to this newer property are the existing <code>will-change</code>, <code>object-fit</code>, and <code>contain</code>. See <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/contain-intrinsic-size">contain-intrinsic-size</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility">content-visibility</a> for more information.</p>
<h2><code>box-decoration-break</code></h2><div class="caution ">Update January 2022: Added the section below.</div><p>The article <a href="https://www.stefanjudis.com/today-i-learned/box-decoration-break-helps-to-define-how-elements-should-be-rendered-across/">box-decoration-break helps to define how elements should be rendered across lines</a> by <cite>Stefan Judis</cite> presents an interesting property that lets you determine how padding, border, and other properties are applied to inline elements that span multiple lines.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4118/box-decoration-break.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4118/box-decoration-break.jpg" alt=" " style="width: 574px"></a></p>
<h2>Isolating Siblings</h2><p>Instead of setting arbitrary z-indexes in your styles, sometimes the <code>isolation</code> property <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/isolation">is a better way of creating a stacking context</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>). </p>
<h2>Page Visibility</h2><p>The <a href="https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API">Page Visibility API</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) is available in all browsers and provides a high-level API for running code when showing or hiding a page. </p>
<blockquote class="quote quote-block "><div>&ldquo;With tabbed browsing, there is a reasonable chance that any given webpage is in the background and thus not visible to the user. The Page Visibility API provides events you can watch for to know when a document becomes visible or hidden, as well as features to look at the current visibility state of the page.&rdquo;</div></blockquote><p>Pages can use this to &ldquo;pause&rdquo; activity when they&rsquo;re in the background (e.g. server-polling or animations). In the case of animations, though, <span class="quote-inline">&ldquo;Most browsers stop sending <code>requestAnimationFrame()</code> callbacks to background tabs or hidden <code>&lt; iframe&gt;</code>s in order to improve performance and battery life.&rdquo;</span> They also <span class="quote-inline">&ldquo;throttle <code>SetTimeout()</code>&rdquo;</span>.</p>
<h2 id="houdini">Houdini</h2><p>The <a href="https://developer.mozilla.org/en-US/docs/Web/Houdini">CSS Houdini</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) APIs are a low-level way to hook custom JavaScript into various parts of the rendering pipeline. Of particular interest is the part that&rsquo;s finished and implemented in all browsers: the CSSOM (CSS Object Model) and Houdini, which let a page render custom CSS effects using JavaScript. The collection of low-level APIs is known by the umbrella term <em>Houdini</em>, described in <a href="https://web.dev/houdini-how/">Cross-browser paint worklets and Houdini.how</a>.</p>
<p>From the MDN page linked above:</p>
<blockquote class="quote quote-block "><div>&ldquo;Houdini is a set of low-level APIs that exposes parts of the CSS engine, giving developers the power to extend CSS by hooking into the styling and layout process of a browser’s rendering engine.  Houdini is a group of APIs that give developers direct access to the CSS Object Model (CSSOM), enabling developers to write code the browser can parse as CSS, thereby <strong>creating new CSS features without waiting for them to be implemented natively in browsers.</strong>&rdquo;</div></blockquote><p>And:</p>
<blockquote class="quote quote-block "><div>&ldquo;<strong>Houdini enables faster parse times than using JavaScript style for style changes.</strong> Browsers parse the CSSOM — including layout, paint, and composite processes — before applying any style updates found in scripts. In addition, layout, paint, and composite processes are repeated for JavaScript style updates. Houdini code doesn&rsquo;t wait for that first rendering cycle to be complete. Rather, <strong>it is included in that first cycle — creating renderable, understandable styles.</strong> Houdini provides an object-based API for working with CSS values in JavaScript.&rdquo;</div></blockquote><p><a href="https://houdini.how">Houdine.How</a> is a collection of open-source CSS extensions that you can use, extend, and learn from. I heard about this from <a href="https://www.bram.us/2020/12/11/css-houdini-circles-a-houdini-paint-worklet-that-draws-colorful-background-circles/"><code>css-houdini-circles</code> — A Houdini Paint Worklet that draws Colorful Background Circles</a> by <cite>Bram Van Damme</cite> (<cite><a href="http://www.bram.us/">Bram.us</a></cite>) (see his <a href="https://github.com/bramus/css-houdini-circles/blob/main/src/index.js">code</a> (<cite><a href="http://github.com/">GitHub</a></cite>))</p>
<p>The following video provides an excellent overview in 12 minutes.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/5eBar5TI71M" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=5eBar5TI71M">Extending CSS with Houdini</a> by <cite>Google Chrome Developers</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Once you start making custom effects, you&rsquo;ll run into classic rendering problems, one of which is addressed in the article <a href="https://jakearchibald.com/2020/css-paint-predictably-random/">CSS paint API: Being predictably random</a>, which explains how to use a stable seed to use predictably random data for animation data.</p>
<p>While the painting API is relatively well-supported, the <a href="https://www.w3.org/TR/css-layout-api-1/">Layout API</a> is still in early days.</p>
<blockquote class="quote quote-block "><div>&ldquo;The layout stage of CSS is responsible for generating and positioning fragments from the box tree. […] This specification describes an API which allows developers to layout a box in response to computed style and box tree changes.&rdquo;</div></blockquote><h2>VisBug</h2><p>The <a href="https://chrome.google.com/webstore/detail/visbug/cdockenadnadldjbbgcallicgledbeoc">VisBug Chrome/Opera/Edge Extension</a> is an excellent tool in general, but seems to be indispensable for optimizing Houdini code.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/zPHyxvPT0gg" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=zPHyxvPT0gg?t=1407">Day 1 Keynote (Chrome Dev Summit 2018)</a> by <cite>Google Chrome Developers</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Skip to <strong>23:25</strong> for the VisBug demonstration.</p>
<p><hr></p>
<div class="caution ">As of April 2021, the features described below are <em>experimental</em> and either not implemented yet or only available in canary builds or behind feature flags (or both).</div><h2><span id="property_proposals">Advanced Properties</span></h2><p><a href="https://www.bram.us/2020/12/30/the-future-of-css-higher-level-custom-properties-to-control-multiple-declarations/">The future of CSS: Higher Level Custom Properties to control multiple declarations</a> by <cite>Bramus Van Damme</cite> discusses a very, very recent proposal (December 2020), discussed in detail in the issue <a href="https://github.com/w3c/csswg-drafts/issues/5624">[css-variables?] Higher level custom properties that control multiple declarations #5624</a> (<cite><a href="http://github.com/">GitHub</a></cite>)</p>
<p>The article <a href="https://web.dev/at-property/">@property: giving superpowers to CSS variables</a> by <cite>Una Kravets</cite> (<cite><a href="http://web.dev/">web dev</a></cite>) provides more examples.</p>
<h2>Container Queries</h2><p>Another interesting up-and-coming development is <a href="https://www.bram.us/2020/11/05/container-queries-are-coming-to-chromium/">container queries</a> (<cite><a href="http://www.bram.us/">Bram.us</a></cite>), which are like media queries, but addressing the nearest &ldquo;root&rdquo; container in the list of parent containers for the element to which it&rsquo;s applied. The article <a href="https://www.bram.us/2021/03/28/css-container-queries-a-first-look-and-demo/">CSS Container Queries: A First Look + Demo</a> takes you step by step through using it. Basically, you write <code>@container (min-width: 38rem)</code> instead of <code>@media (min-width: 38rem)</code> and assign the <code>contain</code> property, like so: <code>contain: layout inline-size</code>.</p>
<p>The article <a href="https://ishadeed.com/article/say-hello-to-css-container-queries/">Say Hello To CSS Container Queries</a> by <cite>Ahmad Shadeed</cite> provides a lot of real-world examples that will make you wonder how we&rsquo;ve lived with only viewport-based media queries for so long.</p>
<h2><span id="nesting">Nesting in CSS</span></h2><p>One of the main features values added by a CSS pre-processor like LESS is nesting, which improves clarity and cuts down on duplicated definitions. The article <a href="https://www.bram.us/2019/03/17/the-future-of-css-nesting-selectors/">The future of CSS: Nesting Selectors</a> by <cite>Bramus</cite> indicates that this feature is coming to mainline CSS, as documented in <a href="https://drafts.csswg.org/css-nesting-1/">CSS Nesting Module</a> (<cite><a href="http://drafts.csswg.org/">W3C</a></cite>). The document is an editors&rsquo; draft, so there&rsquo;s still quite a way to go.</p>
<p><a href="https://www.bram.us/2021/01/11/nested-media-queries/">Nested Media Queries</a> are already supported, though more as a side-effect of the implementations, not necessarily because it was specified that way.</p>
<h2>Logical properties</h2><p>The &ldquo;logical properties&rdquo; feature will add aliases for some of the venerable CSS properties like <code>margin-right</code> and <code>margin-left</code> that make it easier to build more agnostic and flexible content using, e.g., <code>margin-inline-start</code> and <code>margin-inline-end</code>. Assigning one of these instead of a hard-coded side means that a style will work in both LTR and RTL (for example).</p>
<p>The article <a href="https://ishadeed.com/article/css-logical-properties/">Digging Into CSS Logical Properties</a> by <cite>Ahmad Shadeed</cite> provides many more examples. The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties#reference">full list of proposed properties</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) is quite extensive. Many of the newer modules like flexbox and grid were designed like this from the very start.</p>
<p>See also <a href="https://medium.com/swlh/css-logical-properties-are-the-future-of-the-web-i18n-c7d554c6dd72">CSS Logical Properties Are the Future of the Web &amp; I18N</a> by <cite>Daniel Yuschick</cite> for more information and tons of examples, with a demystification of the difference between <code>direction</code> (inline axis, or flow) and <code>writing-mode</code> (block axis).</p>
<div class="caution "><p><strong>Update: 16.10.2021</strong></p>
<p>Two more interesting logical properties are <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size">inline-size</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>) and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size">block-size</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>), which correspond to <code>width</code> and <code>height</code> in the <code>horizontal-tb</code> <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode">writing-mode</a> (<cite><a href="http://developer.mozilla.org/">MDN</a></cite>). Using the logical properties means that the layout works even if the writing mode is changed to <code>vertical-lr</code> or <code>vertical-rl</code>. </p>
</div><h2>Portals</h2><p>The article <a href="https://web.dev/hands-on-portals/">Hands-on with Portals: seamless navigation on the web</a> explains how this new feature in Chrome/Chromium improves support for securely embedding content from other sites (i.e. &ldquo;portals&rdquo;), as when using OAuth providers. It also generally improves transitions in MPAs (Multiple Page Applications) by allowing one page to prepare another rendered page in memory and then <em>transition</em> to it and perhaps even back.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;Single Page Applications (SPAs) offer nice transitions but come at the cost of higher complexity to build. Multi-page Applications (MPAs) are much easier to build, but you end up with blank screens between pages.</p>
<p>&ldquo;Portals offer the best of both worlds: the low complexity of an MPA with the seamless transitions of an SPA. Think of them like an <code>&lt; iframe&gt;</code> in that they allow for embedding, but unlike an <code>&lt; iframe&gt;</code>, they also come with features to navigate to their content.&rdquo;</p>
</div></blockquote><h2>Page Lifecycle</h2><p>The article <a href="https://developers.google.com/web/updates/2018/07/page-lifecycle-api">Page Lifecycle API</a> by <cite>Philip Walton</cite> (<cite><a href="http://developers.google.com/">Google Developers</a></cite>) discusses an improvement over even the &ldquo;Page Visibility&rdquo; API (discussed above). Instead just handling visibility, it also provides hooks for suspending and resuming pages.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;The Page Lifecycle API, shipping in Chrome 68, provides lifecycle hooks so your pages can safely handle these browser interventions without affecting the user experience. Take a look at the API to see whether you should be implementing these features in your application.</p>
<p>&ldquo;[…] While the web platform has long had events that related to lifecycle states — like <code>load</code>, <code>unload</code>, and <code>visibilitychange</code> — these events only allow developers to respond to user-initiated lifecycle state changes.&rdquo;</p>
</div></blockquote><ul>
<li>The article <a href="https://blog.bitsrc.io/page-lifecycle-api-a-browser-api-every-frontend-developer-should-know-b1c74948bd74">Deep Dive into Page Lifecycle API</a> by <cite>Viduni Wickramarachchi</cite> (<cite><a href="http://blog.bitsrc.io/">Bits and Pieces</a></cite>) provides some real-world tests and data.</li>
<li>Check out the <a href="https://github.com/GoogleChromeLabs/page-lifecycle">page-lifecycle</a> (<cite><a href="http://github.com/">GitHub</a></cite>) package for working with the new events.</li></ul><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4118_1_body" class="footnote-number">[1]</span> The video <a href="https://www.youtube.com/watch?v=ncYzTvEMCyE"> Thinking on ways to solve CENTERING</a> (and accompanying <a href="https://web.dev/centering-in-css/">article</a>) is an excellent look at several modern techniques for doing centering content, most of them one-liners with good-to-great behavior in many situations.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4118_2_body" class="footnote-number">[2]</span> While you&rsquo;re at it, take a look at <a href="https://cloudfour.com/thinks/hsl-a-color-format-for-humans/">HSL: a color format for humans</a> by <cite>Paul Hebert</cite> (<cite><a href="http://cloudfour.com/">CloudFour</a></cite>), a format that is a <em>lot</em> more intuitive for blending and setting up color schemes than the classic RGB. There are also many guides online for picking a color set, like <a href="https://blog.datawrapper.de/which-color-scale-to-use-in-data-vis/">Which color scale to use when visualizing data</a> by <cite>Lisa Charlotte Rost</cite> (<cite><a href="http://blog.datawrapper.de/">Datawrapper</a></cite>) and <a href="https://blog.datawrapper.de/beautifulcolors/">How to pick more beautiful colors for your data visualizations</a> by <cite>Lisa Charlotte Rost</cite> (<cite><a href="http://blog.datawrapper.de/">Datawrapper</a></cite>) as well as tools for choosing colors that work well together, like <a href="https://color.hailpixel.com/#E0B3E6,FAF5F0,A4376A,C8765B,2A547E,A3E0C7,98C757">Colordot</a>, <a href="https://learnui.design/tools/data-color-picker.html#palette">ColorDot</a>, <a href="https://farbvelo.elastiq.ch/">Farbvelo</a>, or <a href="https://medialab.github.io/iwanthue/">I Want Hue</a>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4118_3_body" class="footnote-number">[3]</span> If you didn&rsquo;t know about <code>:root</code>, then check out the list of <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements">Pseudo-elements</a> to see which extra parts of a document you have access to with CSS (e.g. the <code>::file-selector-button</code> selector is a relatively new addition that lets you style the button in an upload control).</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4118_4_body" class="footnote-number">[4]</span> The article <a href="https://www.bram.us/2020/12/22/injecting-a-javascript-attack-vector-using-css-custom-properties/">Injecting a JavaScript Attack Vector using CSS Custom Properties</a> by <cite>Bramus</cite> show a site that executes JavaScript stored in a CSS property.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4109</guid>
    <title><![CDATA[Configuring and using Jetbrains Rider 2021.1.1 and Visual Studio 2019 16.9.4]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4109</link>
    <pubDate>Sun, 18 Apr 2021 22:50:04 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. Apr 2021 22:50:04 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">23. Apr 2021 08:59:44 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Visual Studio with ReSharper has been my main development tool for many, many years. I first started using it in 2008 or 2009.</p>
<p>Over the last several years, I&rsquo;ve used many other IDEs, like Visual Studio Code for documentation, advanced search, and JavaScript/TypeScript or PHPStorm for PHP, Android Studio for Java/Android, XCode for Swift/iOS, or WebStorm for TypeScript/JavaScript.</p>
<p>JetBrains Rider came on the scene several years ago and was not, at first, a viable alternative, but it has gotten much, much better. It now makes sense to consider using Rider as well as or even instead of Visual Studio/R#.</p>
<div class="caution "><strong>tl;dr:</strong> Both IDEs are excellent, if configured properly. <a href="https://www.earthli.com/news/view_attachment.php?id=1999&amp;type=entry">Download the solution template</a> to see an example of a solution configuration that includes all settings discussed below.</div><h2>Initial Visual Studio Setup</h2><p>Before going into the <em>new</em> setup, let&rsquo;s briefly discuss what we were replacing.</p>
<ul>
<li>Visual Studio Community 2019 16.9.4 [1]</li>
<li>ReSharper 2021.1.1</li>
<li>StyleCop by JetBrains 2020.3.0</li>
<li>ReCommended Extension for ReSharper 5.5.0</li>
<li>Enhanced Tooltip 3.15.0</li>
<li>Heap Allocations Viewer 2020.3.0</li>
<li>CyclomaticComplexity 2020.3.0</li>
<li><code>.EditorConfig</code> used only lightly</li></ul><p>All inspections and quick-fixes run through ReSharper. Visual Studio &ldquo;squiggles&rdquo; are disabled because they&rsquo;re distracting and contribute nothing additional. StyleCop does a <em>lot</em> of the heavy lifting, but it does a bit too much. It checks spelling in documentation, even though ReSharper already does that natively.</p>
<p>The biggest drawback is that StyleCop uses its own parser, which is not just detrimental to performance—the Roslyn parser, the ReSharper parser, and the Style Cop parser are all running at the same time—but also the StyleCop parser is no longer compatible with some features of C# 8 and 9. It records &ldquo;syntax errors&rdquo; for perfectly valid code.</p>
<h2>Initial Rider Setup</h2><p>Rider doesn&rsquo;t support the StyleCop, ReCommended, or the Enhanced Tooltip extensions. Not having Enhanced Tooltip isn&rsquo;t that big a deal (Rider&rsquo;s tooltips are OK), but not having StyleCop and ReCommended meant a significant number of style and formatting inspections were not applied in Rider.</p>
<p>Rider supports style and formatting, but it doesn&rsquo;t warn or indicate when there are issues. This makes it more difficult to help developers use a common style.</p>
<h2>Requirements</h2><ul>
<li>Get as close to feature parity as possible between Rider and Visual Studio/ReSharper.</li>
<li>Retain StyleCop&rsquo;s style and formatting checks, but without the old parser</li>
<li>Reduce inspection redundancy wherever possible</li>
<li>Use human-readable and human-maintainable configuration</li>
<li>Use common confirmation for Rider and Visual Studio/ReSharper</li>
<li>Use configuration that Visual Studio, but also Visual Studio Code understands wherever possible or advantageous</li></ul><h2>Approach</h2><h3><code>StyleCop.Analyzers</code></h3><p>The <code>StyleCop.Analyzers</code> project has been around for a while, but making the move is not as straightforward as just installing the package in all projects. You also have to rewrite the configuration. Luckily, they have a good template from which to start and the documentation is very good.</p>
<p>Since the test solution uses <code>Directory.Build.Props</code>, it also made it very easy to include the assembly and configuration for all projects. I created a special version for test assemblies that removes the documentation requirement.</p>
<p><code>StyleCop.Analyzers</code> has its own JSON configuration, but it uses the .NET-standard <em>rulesets</em> to configure inspection severities.</p>
<p>Removing the StyleCop plugin for ReSharper was not without drawbacks; it removed a few minor goodies to which I&rsquo;d grown accustomed:</p>
<ul>
<li>The &ldquo;Chop Parameters&rdquo; quick-fix was nice.</li>
<li>The &ldquo;Add documentation&rdquo; was better than the default in either VS or Rider.</li></ul><p><strong class="highlight">Update 22.04.2021:</strong> I&rsquo;ve since discovered that &ldquo;chop&rdquo; is available in Visual Studio by positioning on a method, pressing <kbd>Ctrl</kbd> + <kbd>.</kbd>, and choosing one of the many wrapping options.</p>
<p><span style="width: 444px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/chop.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4109/chop.jpg" alt=" " style="width: 444px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/chop.jpg">Wrap-parameter options</a></span></span></p>
<p>Also, documentation-generation is getting better with each point release.</p>
<h3><code>.EditorConfig</code></h3><p>Another standard is using the <code>.EditorConfig</code> file for as much configuration as possible. This format is not IDE-specific: Visual Studio, ReSharper, Rider, Visual Studio Code, and many other editors/IDEs make use of it. Keeping as many settings as possible in this file helps ensure style and formatting is applied correctly no matter which IDE is used. It&rsquo;s not a guarantee, but there&rsquo;s a better chance than if these settings are stored in a ReSharper-specific format, as before.</p>
<p>These days, a <em>lot</em> of the configuration can be stored in an <code>.EditorConfig</code> file—all but a handful of the Rider and ReSharper settings are mapped there already and there are a few more with each release.</p>
<h3><code>.Directory.Build.Props</code></h3><p>I&rsquo;m also using SDK-style project files together with the <a href="https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2019#directorybuildprops-and-directorybuildtargets">Directory.Build.Props</a> feature of the MSBuild system to consolidate configuration to just one or two files.</p>
<h2>Evaluated Setup</h2><p>Visual Studio:</p>
<ul>
<li>Visual Studio Community 2019 16.9.4</li>
<li>ReSharper 2021.1.1</li>
<li>ReCommended Extension for ReSharper 5.5.0</li>
<li>Enhanced Tooltip 3.15.0</li></ul><p>Rider:</p>
<ul>
<li>Rider 2021.1.1</li></ul><p>Shared:</p>
<ul>
<li>StyleCop.Analyzers 1.2.0-beta.333</li>
<li>Heap Allocations Viewer 2020.3.0</li>
<li>CyclomaticComplexity 2020.3.0</li>
<li><code>.EditorConfig</code> used for nearly everything</li></ul><p>I have not tested Visual Studio without ReSharper because, although Visual Studio has leapt forward in functionality, there are still too many features I miss without ReSharper. [2]</p>
<h3>General Options</h3><p>I use a separate Git client called <a href="https://www.syntevo.com/smartgit/">SmartGit</a>, so I generally turn off as must of the Git integration as possible to save power and memory. The CodeLens (VS)/Code Vision (Rider) is an amazing insight into a ton of statistical information, but I don&rsquo;t ever use it, so I turned it off. Also, I don&rsquo;t like how it feels when editing code because it introduces virtual &ldquo;lines&rdquo; in too many place. I also would sometimes inadvertently click the links and then have to close detail panels or refocus the editor.</p>
<p>For the same reason, I disable almost all inlay hints in Rider/ReSharper (inline hints in Visual Studio). I do not miss seeing types everywhere. I only care what the actual types are when something doesn&rsquo;t compile. In Rider, you can long-hold the <kbd>Ctrl</kbd> key to show inlay hints on-demand. The only inlay hint I always show is for inherited attributes (e.g. for <code>[NotNull]</code> annotations).</p>
<p>I&rsquo;ve also disabled Code Folding (Rider)/Outlining (Visual Studio) because I never use it. I don&rsquo;t need to see the noise along the left-hand gutter and I don&rsquo;t need to accidentally click the nodes (or accidentally trigger a folding with an inadvertent key combination).</p>
<h3>VS/ReSharper Options</h3><ul>
<li><div>Adjust shortcuts/keys<ul>
<li><kbd>⌘</kbd> + <kbd>W</kbd> to close a window</li>
<li><kbd>⌘</kbd> + <kbd>⌥</kbd> + <kbd>W</kbd> to close other windows</li>
<li><kbd>⌘</kbd> + <kbd>⇧</kbd> + <kbd>W</kbd> to close other windows</li></ul></div>Change color for boxing allocation to orange (default is red)</li>
<li>Disable inlay hints for parameter names</li>
<li>Disable more inlay hints</li>
<li>Disable Code Style</li>
<li>Disable Outlining</li>
<li>Disable Environment / Intellisense / Automatically show parameter info in …</li>
<li>Use Package References for NuGet by default</li></ul><h3>Rider Options</h3><p>These are options that I ended up changing from the defaults.</p>
<ul>
<li>Turn on CamelHumps</li>
<li>Turn on exception-handling / tune
<li><div>Adjust shortcuts/keys<ul>
<li><kbd>⌘</kbd> + <kbd>W</kbd> to close a window</li>
<li><kbd>⌘</kbd> + <kbd>⌥</kbd> + <kbd>W</kbd> to close other windows</li>
<li><kbd>⌘</kbd> + <kbd>⇧</kbd> + <kbd>W</kbd> to close other windows</li>
<li><kbd>Ctrl</kbd>+<kbd>R</kbd>/<kbd>Ctrl</kbd>+<kbd>G</kbd> key-combo to the same command as <kbd>Ctrl</kbd>+<kbd>(opt-)</kbd>+<kbd>O</kbd> (Optimize Imports). This command pops up an ominous &ldquo;Cleaning up Code…&rdquo; progress dialog for a second but, so far, it seems to be doing only the import-cleanup.</li>
<li><kbd>Alt</kbd> + <kbd>&lt;</kbd> to navigate to methods in the same file</li></ul></div>Change color for boxing allocation to orange (default is red)</li>
<li>Change color for matching brace (it&rsquo;s the same as for selected text, which is very confusing, as it always looked like I&rsquo;d selected the brace as well)</li>
<li>Disable inlay hints for parameter names</li>
<li>Disable more inlay hints</li>
<li>Disable Code Vision (equivalent to Code Lens in Visual Studio)</li>
<li>Disable Code Folding</li>
<li>Disable Editor / General / Code Completion / Show the parameter info popup in …</li>
<li>Use Package References for NuGet by defaultReduce default font size from 13 to 12</li>
<li>Reduce default line-spacing from 1.2 to 1.05</li></ul><h2>Code Style and Formatting</h2><p>For C# Code style, I ended up adding these extra settings. There are probably  others, but these are the ones that made <kbd>⌘</kbd> + <kbd>K</kbd> / <kbd>⌘</kbd> + <kbd>D</kbd> usable for me, especially for the single-line null-check statements that we use <em>a lot</em>.</p>
<ul>
<li>Check the box for &ldquo;Keep existing arrangement of embedded blocks&rdquo; to prevent reformatting of blocks</li>
<li>Set the lines to add &ldquo;After statements with child blocks&rdquo; to 0</li>
<li>Set &ldquo;Wrap invocation arguments&rdquo; set to &ldquo;Chop if long or multiline&rdquo; (I&rsquo;m not 100% this won&rsquo;t mess other things up, but it worked a treat in a long test-fixture file)</li>
<li>Set &ldquo;Max object and collection initializer elements on a single line&rdquo; to 1, so he stops reformatting multi-element blocks that we&rsquo;ve put on multiple lines.</li></ul><p>With the first two settings, the formatter won&rsquo;t fix some things that he would have fixed before, but he&rsquo;s also not going to change a whole bunch of stuff that you&rsquo;d rather he left alone.</p>
<div class=" " style="display: grid; grid-template-columns: repeat(auto-fill, 200px); grid-gap: 10px"><span style="width: 200px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/keep_existing_arrangement_of_embedded_blocks.jpeg"><img src="https://www.earthli.com/data/news/attachments/entry/4109/keep_existing_arrangement_of_embedded_blocks_tn.jpeg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/keep_existing_arrangement_of_embedded_blocks.jpeg">Keep existing arrangements of embedded blocks</a></span></span><span style="width: 200px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/lines_to_add_after_statements_with_child_blocks.jpeg"><img src="https://www.earthli.com/data/news/attachments/entry/4109/lines_to_add_after_statements_with_child_blocks_tn.jpeg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/lines_to_add_after_statements_with_child_blocks.jpeg">Lines to add after statements with child blocks</a></span></span><span style="width: 193px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/wrapmultiplearguments.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4109/wrapmultiplearguments_tn.jpg" alt=" " style="width: 193px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/wrapmultiplearguments.jpg">WrapMultipleArguments</a></span></span></div><p>It took me a few tries to configure <kbd>Ctrl</kbd>+<kbd>K</kbd>/<kbd>Ctrl</kbd>+<kbd>D</kbd> (format document) in Rider, which doesn&rsquo;t work as loosely as in ReSharper/Visual Studio. In Visual Studio, it leaves single-line argument checks alone. Rider is more … consistent … and reformats all lines, which messes up a lot of formatting.</p>
<p>On the positive side, the configuration for Rider ended up improving &ldquo;Code Cleanup&rdquo; in Visual Studio/ReSharper, which had never worked so well before. I eventually figured out how to set things up so that &ldquo;Format Document&rdquo; and &ldquo;Code Cleanup&rdquo; (<kbd>Ctrl</kbd>+<kbd>E</kbd>/<kbd>Ctrl</kbd>+<kbd>F</kbd>) both work flawlessly in Rider <em>and</em> Visual Studio, but it took some time and patience to find all of the settings. The &ldquo;Detect Formatting Settings&rdquo; in both ReSharper and Rider were indispensable.</p>
<h3>File Layout</h3><p>I also finally configured the &ldquo;File Layout&rdquo; feature so that &ldquo;Clean Up Code&rdquo; works as expected. StyleCop Analyzers supports enforcing an ordering on members, but it doesn&rsquo;t support configuration of that ordering. The order is fixed as StyleCop wants it. Their default style has fields at the top, which is a no-go for our style.</p>
<p>That means that I&rsquo;ve disabled the &ldquo;arrangement&rdquo; feature of StyleCop and no longer see warnings about out-of-order members. This is OK, though, as re-ordering members just to fix a warning is not that great for reviews and merging. &ldquo;Clean Up Code&rdquo;, however, <em>does</em> apply the file-layout rules.</p>
<p>I think that this is a better balance overall, as leaving a method in place when you&rsquo;ve changed its visibility from public to protects (or vice versa) should not earn a warning.</p>
<h3>Configuration Files</h3><p>As noted above, I configured all of the <em>StyleCop</em>, <code>.EditorConfig</code>, and Rider/R# settings to make &ldquo;format document&rdquo; and &ldquo;clean up code&rdquo; work perfectly with our style. These are just a jumping-off point (even within Encodo). Adjust StyleCop inspection severities in the <code>*.ruleset</code> files.</p>
<p>Adjust formatting preferences in the <code>.EditorConfig</code> whenever you can. Rider/ReSharper will also allow you to override these settings, storing them in the <code>*.sln.DotSettings</code> file, but it&rsquo;s clearer and more consistent to configure the <code>ruleset</code> and <code>.EditorConfig</code> files because those are more human-readable and better-documented than the <code>*.sln.DotSettings</code> file.</p>
<div class="caution "><strong>Tip:</strong> <a href="https://www.earthli.com/news/view_attachment.php?id=1999&amp;type=entry">Download the solution template</a> to see an example of the configuration with all settings discussed above.</div><h2>Comparison</h2><p>I made this comparison over the last 4 months, during which the setup changed slowly into the configuration outlined above. I have tried to weed out the notes and impressions that no longer apply, but I may have missed some. I do my best to give the impression of what it&rsquo;s like to work with these IDEs. I left some longer descriptions in place, just to give a feel of what I experienced while using the IDEs.</p>
<h3>Launch and Processes</h3><p>For small-to-medium projects on a my 4-year-old desktop, you barely notice startup. For the larger Quino project, with over 120 projects (for now), startup speed is more noticeable.</p>
<p>All of the IDEs start relatively quickly now. They&rsquo;re just fast <em>in different places</em>. It really depends on where your focus is. Visual Studio by itself starts very, very quickly. The latest versions of ReSharper start up in parallel, so VS is on the screen and the editor is typable in <em>seconds</em>, even with a solution like Quino. You can&rsquo;t search at that point, though. [3]</p>
<p>Rider <em>looks like</em> it&rsquo;s totally up and running, but it mostly can&rsquo;t search either, not until the projects have been processed and the indexes loaded. The initial Rider project-chooser takes longer to start up than you&rsquo;d expect. Once it&rsquo;s up, though, opening a solution from there is very fast. Rider runs all open solutions in a single process. Visual Studio launches a separate process per solution.</p>
<p>While I&rsquo;m happy that the startup speed has improved all-around, I don&rsquo;t really care about startup speed, not really. I never reboot unless I have to. I never log out unless I reboot. I just leave my tools running all the time. I have 32GB of RAM. Once it&rsquo;s running, it&rsquo;s running, and I don&rsquo;t care how much RAM it takes (within reason)—I care how fast it does the things I ask of it.</p>
<p>Once I configured <code>StyleCop.Analyzers</code>, my initial solution-load in Rider showed a <em>shocking</em> amount of memory for Quino (an extra 4.5GB just for the Roslyn checker process). It felt fast enough, even though the memory usage kept growing. Rider&rsquo;s a 64-bit process and I have 32GB of RAM on my desktop, so it was a luxury I could afford.</p>
<div class=" " style="display: grid; grid-template-columns: repeat(auto-fill, 200px); grid-gap: 10px"><span style="width: 200px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/8gb_with_analyzers.jpeg"><img src="https://www.earthli.com/data/news/attachments/entry/4109/8gb_with_analyzers_tn.jpeg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/8gb_with_analyzers.jpeg">8GB Rider</a></span></span><span style="width: 200px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/10gb_with_analyzers.jpeg"><img src="https://www.earthli.com/data/news/attachments/entry/4109/10gb_with_analyzers_tn.jpeg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/10gb_with_analyzers.jpeg">10GB Rider (1 minute later)</a></span></span></div><p>Luckily, after a restart, the memory was still higher than it was, but now stable at around 3GB.</p>
<div class="caution "><strong>Conclusion:</strong> No real launch-speed advantage until a solution is navigable. Both use about a reasonable amount of RAM.</div><h3>Performance Issues and Crashes</h3><p>Solution-wide analysis is enabled by default in Rider, with no performance degradation noticeable at all. In fairness, there is little to no performance degradation evident with ReSharper in Visual Studio either.</p>
<p>Code Vision is enabled by default in Rider; also no performance-degradation noticeable. I am running everything on a desktop and I have seen CPU usage spike quite high on Rider. Code Lens in Visual Studio and Code Vision in Rider both probably suck the life out of a battery, though. <abbr title="There ain't no such thing as a free lunch"><a href="https://en.wikipedia.org/wiki/There_ain%27t_no_such_thing_as_a_free_lunch">TANSTAFL</a></abbr>.</p>
<p>While it&rsquo;s nice that Rider uses all available CPU power for certain tasks—e.g. building—I imagine that the CPU fan would be running a lot under heavy usage. Visual Studio probably suffers the same, though its CPU usage seemed to be flatter when I checked.</p>
<p>Solution-reloading is more stable and a bit faster than in Visual Studio. In a recent task where I was <em>constantly</em> cherry-picking and rebasing, making changes to project files and the solution file, Rider just worked. Visual Studio would usually throw up a yellow warning bar at the top sooner or later (usually sooner).</p>
<p>Sometimes, Rider is quite slow at getting its &ldquo;intention actions&rdquo;, something I&rsquo;ve never seen with ReSharper.<br>
<a href="https://www.earthli.com/data/news/attachments/entry/4109/riderslowerthanresharper.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/riderslowerthanresharper.png" alt=" "></a><br>
This usually clears up after 5-10 seconds, but a couple of times, Rider went looking for inspections for 10 seconds and came up with nothing—repeatedly. It&rsquo;s odd because, in that case, Rider kept having trouble with the same extension-method call and had to look it up again and again. This effect is noticeable in other places, as well. When you elect to show the dialog to &ldquo;Configure Inspection Severity&rdquo;, then sometimes it takes several seconds to show the dialog box (with no user feedback).</p>
<p>And, sometimes, Rider just <em>dies</em>. For example, when I look up sources for a .NET type, like <code>IndentedTextWriter</code>, by using <kbd>⌥</kbd> + <kbd>F12</kbd>. Rider showed a dialog for several seconds, but didn&rsquo;t seem to be doing anything. It wasn&rsquo;t downloading, as expected; instead, it just showed &ldquo;Searching for implementations…&rdquo;.</p>
<p>This wouldn&rsquo;t be worth mentioning <em>but</em>, after having dismissed the dialog, now I can&rsquo;t navigate to <em>anything</em> with <kbd>F12</kbd>. I have to restart Rider. This is not the first time that this has happened. This <em>never</em> happened with Visual Studio. It definitely makes the IDE feel much shakier.</p>
<p>In Visual Studio, with R#, I can view the sources for <code>IndentedTextWriter</code> after only a slight pause.</p>
<p>On the subject of reloading: Visual Studio definitely still freezes more (usually showing its yellow warning bar at the top after a few seconds), but Rider is just more subtle about being loaded, but still unusable. You have to keep an eye on the progress bar at the bottom in both IDEs. In general, Rider reloads more quickly than Visual Studio—and has no UI &ldquo;hangs&rdquo;, like VS still does, for a few seconds—but not always.</p>
<p>On the other, other hand, I&rsquo;ve also experienced more build errors after changing framework targets than with Visual Studio. Rider can&rsquo;t copy files or its looking in the wrong place for files. Restarting Rider fixed that problem, but I shouldn&rsquo;t have to restart to fix a build. Rebuild should have fixed it, but it didn&rsquo;t.</p>
<div class="caution "><strong>Conclusion:</strong> The latest version of Visual Studio with ReSharper feels more stable than Rider and has fewer mysterious failures. Rider reloads more quickly.</div><h3>Code Analyzers and Quick Fixes</h3><p>I was unable to get Rider to respect the <code>generated_code</code> setting from the <code>.EditorConfig</code> file, something that worked immediately with Visual Studio/Roslyn (ReSharper is not involved). I&rsquo;ve reported that issue as <a href="https://youtrack.jetbrains.com/issue/RIDER-61283">RIDER-61283</a>. In the meantime, I&rsquo;m using the &ldquo;Elements to Skip&rdquo; feature to ignore the same file masks Rider should be ignoring anyway. That at least works for now.</p>
<p>Still, Rider&rsquo;s integration is nice because it pulls everything together into a single list, but its quick-fixes for Analyzer inspections aren&rsquo;t as strong as Visual Studio&rsquo;s nor can you actually fix everything (see the issue with UTF8 below).</p>
<p>In Visual Studio, the analyzers work quite well, but there is no integration with ReSharper. Instead, the integration with Visual Studio is really good—with <kbd>Ctrl</kbd> + <kbd>.</kbd> instead of <kbd>⌥</kbd> + <kbd>⏎</kbd>, you can get quick fixes and even apply them to the entire method, document, project, or solution.</p>
<p>In Visual Studio, there&rsquo;s a very nice preview mode. In fact, there is useful and accurate user feedback throughout, which was a pleasant surprise. It&rsquo;s quite fast in collecting fixes for all 120 projects <em>and</em> applying the changes. There&rsquo;s even good keyboard support for arrowing to the file/project/solution actions. This is a definite boon for getting through thousands of fixes quickly.</p>
<p>In Rider, there are quick fixes, but most of them only work for a single instance of the inspection. Some of the fixes (e.g. each attribute on its own line) can be applied to file/project/solution with ReSharper as well, but not all.  Some of the fixes aren&rsquo;t available at all with ReSharper (e.g. SA1513, insert newline after brace) but are available in Rider.</p>
<p>So, Visual Studio&rsquo;s integration with Code Analyzers worked better out of the box, but it forces you to use both ReSharper quick fixes (<kbd>⌥</kbd> + <kbd>⏎</kbd>) and VS quick fixes (<kbd>⌘</kbd> + <kbd>.</kbd>), depending on which system detected the issue. The inspections also show up in two different panes. This is actually easier to get used to than it sounds, though.</p>
<div class="caution "><strong>Conclusion:</strong> Rider has a merged view, which is nice. Visual Studio has quick fixes for everything, applicable to method, document, project, and solution.</div><h3>Inspections</h3><p>There is no <em>ReCommended</em> extension for Rider (with no plans to add support, according to issue <a href="https://github.com/prodot/ReCommended-Extension/issues/51">#51: Add support for Rider 2020.2</a>, which was closed as &ldquo;too much work&rdquo;. All of <a href="https://github.com/prodot/ReCommended-Extension/wiki">these inspections</a> are missing in Rider.</p>
<ul>
<li>Check usage of annotations</li>
<li>Check <code>async/await</code> usage</li>
<li>Check usage of lock variables</li>
<li><a href="https://github.com/prodot/ReCommended-Extension/wiki">Etc.</a></li></ul><p>When you add a parameter to the constructor, Rider doesn&rsquo;t mark the identifier as unused <em>if it has an attribute</em>. In the examples below, you can see that the identifier is grayed out in Visual Studio, but not in Rider.</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/unused_parameter_in_vs.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/unused_parameter_in_vs.png" alt=" " style="width: 560px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/unused_parameter_in_vs.png">Unused parameter in Visual Studio</a></span></span><span style="width: 563px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/unused_parameter_in_rider.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/unused_parameter_in_rider.png" alt=" " style="width: 563px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/unused_parameter_in_rider.png">Unused parameter in Rider</a></span></span></p>
<p>Sometimes Rider doesn&rsquo;t indicate when a conditional access is unnecessary (e.g. when <code>?.</code> can be converted to <code>.</code>). It also doesn&rsquo;t indicate when an expression that is always false or true could be simplified as reliably as ReSharper does.</p>
<p>Neither Rider nor ReSharper seems to notice when you do a silly pattern-matching check, like <code>if (sender is Person person)</code> when <code>person</code> <em>is already</em> a <code>Person</code>. VS, Rider, and ReSharper simply assume that you&rsquo;re doing the check in order to assign the variable, I guess.</p>
<div class="caution "><strong>Conclusion:</strong> Both have a tremendous number of useful inspections, but Visual Studio/ReSharper/ReCommended is a slightly more powerful combination.</div><h3>Inspection Accuracy &amp; Speed</h3><p>Now I know why the solution-wide analysis is so fast in Rider: It doesn&rsquo;t reevaluate warnings when the project changes (e.g. if you change the root namespace). You have to visit each file individually for it to clear the warning. Clicking &ldquo;Reanalyze all files with errors&rdquo; doesn&rsquo;t work on files with warnings, as it does under ReSharper.</p>
<p>You can use <kbd>⌥</kbd> + <kbd>⇧</kbd> + <kbd>PgDn</kbd> to jump through the warnings, opening each file as you go. It&rsquo;s pretty fast, but feels clunky. This is especially unfortunate when Rider thinks that there are errors. I suppose that this is a side-effect of repeated solution/project reloads as I&rsquo;m quickly switching branches.</p>
<p>Changes to the ruleset and stylecop settings are noticed in both IDEs instantly. I changed a rule from warning to info and Rider changed the color of the squiggle in what felt like less than a second. Unfortunately, changes to the <code>.stylecop.json</code> file are not picked up without a reload of the solution.</p>
<p>Here is where ReSharper is <em>much perceivably faster</em> than Visual Studio. It&rsquo;s even a <em>bit</em> faster than Rider. Turn on solution-wide analysis. Remove the last reference to a function. Watch ReSharper gray out the identifier in the declaration nearly immediately. Or remove a method call. Watch ReSharper underline it immediately. Visual Studio/Roslyn? Still feels laggy.</p>
<p>ReSharper&rsquo;s list of errors and warning updates <em>immediately</em>. Rider&rsquo;s is pretty good, too, but, mysteriously, not as accurate or quick-to-update as ReSharper&rsquo;s. Both are much faster than Visual Studio/Roslyn, which often takes long seconds to clear warnings or errors—and sometimes never does, until you force a build.</p>
<p>Roslyn (Visual Studio) is sometimes flaky and won&rsquo;t clear old warnings/errors until the next build. ReSharper was definitely faster here, even with the extra StyleCop parser. This didn&rsquo;t used to be an issue, but with the switch to Code Analyzers, I&rsquo;m now using Visual Studio/Roslyn for a good portion of my inspections (StyleCop).</p>
<p>What does flaky mean? Whereas Rider updates relatively reliably when you make a change in any file, StyleCop Code Analyzers in Visual Studio will only occasionally show the warnings. If the file isn&rsquo;t open (or in some sort of in-memory cache), then only a &ldquo;Rebuild All&rdquo; will make the warning appear. This also only works if you&rsquo;re <em>not</em> using &ldquo;ReSharper Build&rdquo;.</p>
<p>Rider does this much less often, but it still does occasionally have incorrect inspections that can be very difficult to correct. For example, the following screenshots show an unrecognized dictionary.</p>
<p><span style="width: 473px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/dictionarnotfound.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/dictionarnotfound.png" alt=" " style="width: 473px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/dictionarnotfound.png">Dictionary not found</a></span></span></p>
<p>Visual Studio recognizes the <code>using System.Collections.Generic</code>, but Rider grays it out.</p>
<p><span style="width: 303px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/dictionarynotused.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/dictionarynotused.png" alt=" " style="width: 303px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/dictionarynotused.png">Dictionary marked as not used</a></span></span></p>
<p>Restarting Rider sorted out this error. Several other cached errors and warnings disappeared with the one noted above.</p>
<p>Rider is very quick, as is ReSharper. Also, it&rsquo;s generally pretty good on updating inspections, but I&rsquo;ve also seen flakiness with lingering warnings and errors in the pane, but never in the sources. The only way I&rsquo;ve found to update the pane is by actually opening the file, at which point Rider re-detects that the issues are gone and clears the inspections. Manually triggering a reanalysis does not help here.</p>
<div class="caution "><strong>Conclusion:</strong>  Both have lingering inspections sometimes but, overall, Rider&rsquo;s inspection speed and accuracy are both better. For either IDE, run &ldquo;Rebuild All&rdquo; to see all warnings.</div><h3>Navigation</h3><p>The solution-wide find/replace window in Rider is lightning-fast and supports newlines, copy/paste, regular expressions, shows change previews. It&rsquo;s wonderful. The change previews in Visual Studio Code are just a tiny-bit better, but the overall experience is solid and super-fast. The search/replace in Visual Studio is looks very dated next to this feature in Rider.</p>
<p>Navigation to other files is so fast in Rider that I sometimes thought it hadn&rsquo;t navigated (it had!)</p>
<p>There is no way to navigate the warnings in a solution using the keyboard. In general, Rider tends to let panels &ldquo;steal&rdquo; the keys for next/previous, so when you try to navigate errors or warnings or find-results, the test session can &ldquo;steal&rdquo; these keys and suddenly you&rsquo;re navigating tests and fixtures instead. I find myself grabbing the mouse more often in Rider than I do in Visual Studio.</p>
<p>Where ReSharper has <kbd>Ctrl</kbd> + <kbd>T</kbd> as a central search for everything, the same key combination does not include &ldquo;search everything&rdquo; in Rider. For that, you need to switch to <kbd>Ctrl</kbd> + <kbd>⇧</kbd> + <kbd>F</kbd>. On the other hand, the dedicated &ldquo;find in solution&rdquo; panel is lightning fast and makes up having to switch between panes.</p>
<div class="caution "><strong>Conclusion:</strong> Both offer really good navigation, but I give a slight edge to Visual Studio/ReSharper for consistent keyboard support.</div><h3>Editing</h3><h4>Column/Noncontiguous Selection</h4><p>Rider doesn&rsquo;t really support extending a non-contiguous selection. It has column-selection mode, like Visual Studio, but it doesn&rsquo;t have <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>.</kbd> to select &ldquo;like&rdquo; text. In Sublime Text and Visual Studio Code, this feature is available via <kbd>⌘</kbd> + <kbd>D</kbd>. Rider doesn&rsquo;t seem to have this, which limits editing capabilities. There is documentation for <a href="https://www.jetbrains.com/help/rider/Multicursor.html#multiselection">multi-selection</a> but the shortcut keys are confusing and not the ones I have assigned. Nor can I find anything in the keymap with any of those names. It&rsquo;s either a new feature or its only partially supported.</p>
<p><strong class="highlight">Update 23.04.2021:</strong> I just tried <kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>.</kbd> in Rider (even though that wasn&rsquo;t documented) and it works just like in Visual Studio! That&rsquo;s a nice surprise. I&rsquo;m not sure if this was always there and just poorly documented or whether they just added it in a recent release. At any rate, good news for editing in Rider.</p>
<h4>Commenting</h4><p>Pressing <kbd>Ctrl</kbd>+<kbd>K</kbd>/<kbd>Ctrl</kbd>+<kbd>C</kbd> comments code. However, instead of commenting <em>again</em>, it uncomments if applied a second time. This means I can&rsquo;t &ldquo;double comment&rdquo; to indicate that this code is temporarily preserved, but should not be flagged as commented code to be removed.</p>
<h4>Double-click Select</h4><p>Double-clicking on an identifier uses CamelHumps, if you have CamelHumps enabled (just like all other JetBrains tools). With ReSharper, though, the CamelHumps apply to cursor-based word-selection, but a double-click selects the whole word. I think that&rsquo;s a better balance because that&rsquo;s what I expect when I double-click an identifier. I don&rsquo;t think I&rsquo;ve ever wanted to select just a part of the double-clicked word by default. It&rsquo;s not a deal-breaker, but it&rsquo;s annoying because I have to double-click, then extend the selection manually to get the full identifier.</p>
<h4>Undo Buffers</h4><p>The undo function in Rider fails much more often than I&rsquo;m used to from Visual Studio. I&rsquo;ve deleted lines of documentation and then hit undo and Rider couldn&rsquo;t get them back.</p>
<p><span style="width: 200px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/undoerror.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4109/undoerror_tn.jpg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/undoerror.jpg">Undo Error</a></span></span></p>
<p>Once the undo buffer is broken, you have to restart Rider in order to be able to undo again. It feels quite unstable. I&rsquo;m quite surprised, considering the literally dozens of popular IDEs built on this platform.</p>
<h4>UTF-8 Support</h4><p>Rider creates files as UTF-8, but without the BOM. Then the StyleCop analyzer demands that the file have a BOM, but there is no quick fix in Rider for this, nor is it clear how to convert the file. I end up switching back to Visual Studio, where there&rsquo;s a quick fix to set the encoding properly.</p>
<h4>Typing Speed</h4><p>Typing speed is better in Rider than in Visual Studio/ReSharper. Just a little, but it is. It&rsquo;s smoother. Even after replacing the StyleCop extension with <code>StyleCop.Analyzers</code>, it still feels a bit smoother, overall. Rider on Mac feels even smoother than Windows.</p>
<div class="caution "><strong>Conclusion:</strong> Rider&rsquo;s text-editing is smoother but Visual Studio feels slightly more solid overall.</div><h3>Code Completion</h3><p>I just wasted 10 minutes in Visual Studio trying to figure out from the documentation how to create a <code>StreamWriter</code> with a non-default encoding. The list of overloads did not show any overloads when using a path.</p>
<p><span style="width: 537px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/screen_shot_2021-03-19_at_07.39.jpeg"><img src="https://www.earthli.com/data/news/attachments/entry/4109/screen_shot_2021-03-19_at_07.39.jpeg" alt=" " style="width: 537px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/screen_shot_2021-03-19_at_07.39.jpeg">StreamWriter constructor overloads in Visual Studio</a></span></span></p>
<p>I searched and the wizards at StackOverflow rather snippily asked why not use the docs? So I looked at the docs and then switched to the right target (first .NET 2.1, then .NET Standard 2.0), but the desired overloads have been around forever. Back to VS  and it is really not showing those overloads. Switch to Rider and … there they are.</p>
<p><span style="width: 433px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/screen_shot_2021-03-19_at_07.38.jpeg"><img src="https://www.earthli.com/data/news/attachments/entry/4109/screen_shot_2021-03-19_at_07.38.jpeg" alt=" " style="width: 433px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/screen_shot_2021-03-19_at_07.38.jpeg">StreamWriter constructor overloads in Rider</a></span></span></p>
<p>It turns out that Visual Studio has a maximum height for its overloads list. The only hint that there are more methods are some heretofore not-noticed dashes at the bottom. The only way to see the other overloads is to select the popup and use the arrow keys. There is no scroll bar or other evidence to indicate that this is possible. There is also no reason why the popup couldn&rsquo;t be taller.</p>
<p>In Visual Studio, the developer can use the <kbd>up arrow</kbd> and <kbd>down arrow</kbd> to traverse the various overloads, showing the documentation for them. In Rider, it&rsquo;s not obvious how to navigate. The trick is to keep hitting <kbd>⌘</kbd> + <kbd>⇧</kbd> + <kbd>space</kbd> to cycle forward through the list.</p>
<p>Typing a <code>{</code> in a non-interpolated string does not show code-completion. In ReSharper, you can type <code>{</code>, select a variable and ReSharper automatically makes the string interpolated. If you add a parameter, Rider rightly complains that the data between the curly braces needs to be an index, but doesn&rsquo;t offer to convert the string to interpolated. You have to go back to the front of the string and add the $ yourself. <strong class="highlight">This is now working in Rider 2020.3</strong></p>
<div class="caution "><strong>Conclusion:</strong> Visual Studio&rsquo;s UI is more easily navigable, but Rider&rsquo;s UI is better for longer lists of overloads.</div><h3>Refactoring</h3><p>Rider doesn&rsquo;t offer to rename related symbols as much as ReSharper does. For example, if you rename a field, ReSharper will offer to rename the constructor parameter that sets that field. Rider does not.</p>
<p>When you insert a new parameter in a method call and then tell Rider to add it to the method, it then shows a panel with other calls that need to be updated, asking how to handle each one. This is the same as in ReSharper and is a welcome feature. As in ReSharper, you can navigate the various calls with the arrow keys and the focus is set correctly. However, I can&rsquo;t figure out how to activate the choices with the keyboard. I have to use the mouse.</p>
<div class="caution "><strong>Conclusion:</strong> Both amazing, but slight edge to Visual Studio for completeness.</div><h3>Restore &amp; Build</h3><p>The NuGet integration is nice in Rider and the NuGet Explorer is quite fast. It still doesn&rsquo;t feel as robust as Visual Studio, but it&rsquo;s getting there. I rarely went back to Visual Studio to try to resolve an issue I couldn&rsquo;t solve in the Rider UI.</p>
<p>Rider&rsquo;s &ldquo;build&rdquo; command <em>still</em> doesn&rsquo;t notice when you&rsquo;re changed packages external to the solution and do a <code>nuget restore</code> for you. In fact, when I updated Winform DevEx packages externally (because neither the NuGet UI in Rider nor that in VS could apply the changes without getting tripped up in dependencies because it can&rsquo;t upgrade multiple projects at once), Rider had no idea what I&rsquo;d done until I manually deleted the <code>obj</code> folders from the projects that depend on DevEx.</p>
<p>I don&rsquo;t recall having to do that for Visual Studio, which runs a <code>nuget restore</code> check before each build. Visual Studio was more amenable to finding the actual error with a &ldquo;rebuild all&rdquo;. Rider cached more and stayed stuck on the original &ldquo;error&rdquo;, which was hiding the real problem (an interface mismatch after the upgrade).</p>
<p>When you update NuGet packages, Rider uses stale data a lot more than Visual Studio does now. This is how Visual Studio used to be, but it&rsquo;s gotten a lot better with its caches. Rider is still a few steps behind. I just upgraded NuGet packages for a project and then ran the tests. A bunch of them failed with a <code>MissingMethodException</code>.</p>
<p>I know this error, so I forced a full rebuild and ran the tests again. This time everything worked. With Visual Studio, I&rsquo;d gotten used to no longer having to consider &ldquo;rebuild all&rdquo; or &ldquo;restart the IDE&rdquo; as possible solutions. With Rider, you still have to occasionally use these solutions, for now.</p>
<p>It&rsquo;s not the end of the world, but it does waste time and effort—especially if you don&rsquo;t jump to that conclusion quickly enough. Often enough, you&rsquo;ll lose a good quarter of an hour chasing phantom errors and warnings instead.</p>
<div class="caution "><strong>Conclusion:</strong> They&rsquo;re both about the same for day-to-day use, but Visual Studio is still slightly better at corner cases.</div><h3>Testing</h3><p>When you edit a unit test to change the parameters to a test case, the test session will update <em>and then move the selection to the top of the list</em>. This is very annoying since it always scrolls away from the test area I had focused. It also has an annoying habit of nearly constantly changing the selected item in the tree, making navigation difficult.</p>
<p>This might be related to when tests are running or a build is running, but there&rsquo;s always something like that going on—it&rsquo;s not very nice that the whole IDE has to be quiet before I can use keyboard navigation in a tree without Rider constantly stealing focus and jumping around.</p>
<p>While running tests, Rider does not allow you to collapse nodes in the unit-test session. It quite annoyingly expands it again whenever you try to collapse a node.</p>
<p>Searching in tests is quite slow in both Rider and ReSharper.</p>
<p><strong class="highlight">Update 23.04.2021:</strong> I&rsquo;ve discovered that I can use <kbd>F4</kbd> in Rider to jump to the source of a test. That&rsquo;s very handy because double-clicking on a test in either test runner has unpredictable results that seem to depend on whether the test is defined in a base class.</p>
<p>I can&rsquo;t treat the Unit Test Session window as an editor window in Rider, so it&rsquo;s harder to switch back and forth. The tests are docked at the bottom by default. You have to switch to that window with a hotkey, then use another hotkey to hide it. I&rsquo;m getting used to it, but I don&rsquo;t understand why the JetBrains IDE doesn&rsquo;t support this feature (it doesn&rsquo;t have it in any other JetBrains IDEs I&rsquo;ve used either).</p>
<div class="caution "><strong>Conclusion:</strong> There&rsquo;s not much difference in testing support between the two.</div><h3>Debugging</h3><p>Integrated debugging with auto-disassemble and sources in Rider is pretty awesome (e.g. I debugged into SimpleInjector without SourceLink). You can open any referenced type in any assembly and either have the original source from SourceLink [4] or disassembly. In either case, you can set breakpoints and debug into it. If the file is disassembled, it&rsquo;s not always pretty, but it&rsquo;s amazingly useful for inspection.</p>
<p>The Smart Step-in feature in Rider is a very nice upgrade, to which I&rsquo;ve already become quite accustomed (just <kbd>⇥</kbd> to cycle locations). It&rsquo;s a bit finer-grained than being able to disable property step-in universally in Visual Studio.</p>
<p>On the other hand, I&rsquo;m not super-happy with the different ways of running an application in Rider. They seem to make it very difficult to debug an application <em>and</em> stop on unexpected errors. I&rsquo;ve seen other users using Rider just kind of look in the output window as if live debugging wasn&rsquo;t a feature we should all expect to work. It can be configured, but you have to make sure to run in <em>debug</em> mode <em>and</em> turn on exception-handling.</p>
<p>It&rsquo;s also much harder to debug a <code>StackOverflowException</code> in tests because Rider doesn&rsquo;t show a useful stack trace (it instead shows a trace for the <code>LogException</code> in the test runner itself. The &ldquo;launch log file&rdquo; is detailed, but provides no additional information. Instead, I was forced to set breakpoints and continually &ldquo;edge closer&rdquo; to the crash and find it myself. This is how Visual Studio used to work, but for a couple of years, its handling for stack overflows has been much better.</p>
<p>Also, Rider doesn&rsquo;t stop on unhandled exceptions by default, either when running tests or running a web server. The stack trace in the debug output when running the web server isn&rsquo;t highlighted and can&rsquo;t be clicked.</p>
<p>The debugger in Rider does not make use of the <code>DebuggerTypeProxy</code> to display or format debugging information, which is a shame because Quino has useful customizations for debugger display that I miss in Rider.</p>
<h4>Invalid Targets</h4><p>I was unable to debug unit tests for a while because Rider complained that my DotNet runtime (AnyCPU) didn&rsquo;t match the chosen testing target (x86). All of the solutions I&rsquo;ve opened have been &ldquo;Any CPU&rdquo;-only, so I was mystified how Rider came up with the idea to run my tests as x86.</p>
<p>Rider pops up a helpful tip to take me directly to the setting to change the runtime to use. I don&rsquo;t even <em>have</em> an x86 runtime. And I don&rsquo;t want to run tests as x86 anyway.</p>
<p>The real fix is to go to <em>Settings</em> =&gt; <em>Build, Execution, Deployment</em> =&gt; <em>Unit Testing</em> =&gt; <em>Default platform architecture</em> and set it to &ldquo;Automatic&rdquo;. Mine was hard-coded to x86, for some reason (maybe a settings upgrade from an older version).</p>
<h4>Variable Inspection</h4><p>Viewing a variable isn&rsquo;t as easy because Rider uses a much less-stable tooltip than VS. If you have a long value that you want to &ldquo;view&rdquo;, you have to cruise your mouse along a long, skinny tooltip for dozens of centimeters before you can click the &ldquo;view&rdquo; button (you have to know it&rsquo;s there) at the end.</p>
<p><span style="width: 375px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/image_2021-03-16_080144.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/image_2021-03-16_080144.png" alt=" " style="width: 375px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/image_2021-03-16_080144.png">Debugging tooltip</a></span></span></p>
<p>Since the tooltip is unstable, Rider has trained me to go down to the variable window and copy the value from there.</p>
<div class="caution "><strong>Conclusion:</strong> Both debuggers are excellent—each has advantages and disadvantages—but Visual Studio still has a slight edge. It feels more mature.</div><h3>External Sources</h3><p>Both Rider and VS/ReSharper support navigation using SourceLink as of 2020.3, which is a massive win for usability. Now you can open a type with <kbd>Ctrl</kbd> + <kbd>T</kbd> or hit <kbd>F12</kbd>, <kbd>⌥</kbd> + <kbd>Home</kbd>, <kbd>⌥</kbd> + <kbd>End</kbd> to navigate to a related symbol from source and Rider/ReSharper will navigate within the SourceLink sources, which means that you can easily set breakpoints in code from NuGet packages, as long as they have SourceLink. Rider additionally offers support for setting breakpoints in disassembled code, with mixed results.</p>
<p>However, browsing works less well in Rider. For example, I pressed <kbd>⌥</kbd> + <kbd>F12</kbd> on <code>EventHandler</code> to &ldquo;peek&rdquo; it and it popped up a processing dialog for 15 seconds before I canceled it. When I pressed <kbd>F12</kbd> to navigate there instead, it didn&rsquo;t show a progress dialog, but it also just seemed to <em>break Rider</em> because syntax-highlighting and code-completion stopped working for subsequently typed code. The &ldquo;Errors in Solution&rdquo; pane was similarly crippled, showing files with warnings, but no warnings. The navigation action never showed the code for the <code>EventHandler</code>, but it did make everything else stop working. A restart fixed everything.</p>
<p>In addition, navigation to authenticated sources was only working temporarily. It is broken in the most recent version of Rider, as I&rsquo;ve documented in <a href="https://youtrack.jetbrains.com/issue/RIDER-61280">RIDER-61280</a>.</p>
<div class="caution "><strong>Conclusion:</strong> Visual Studio is more reliable with SourceLink right now. Rider can debug and set breakpoints in disassembled sources (which it has to use because SourceLink is broken again).</div><h3>Documentation</h3><p>The formatting for XML documentation works strangely when Rider inserts text in documentation (e.g. when you apply a fix). We use a tab size of 2 everywhere, but the settings window shows a tab size of 4, but also mention that some settings might be overridden by the <code>.EditorConfig</code>. Reformatting or cleaning up code fixes the indentation to where it should be. It&rsquo;s unclear where Rider is getting its settings for the initial insertion.</p>
<p>Even with the StyleCop Analyzers, there are fewer fixes for XML documentation than with Visual Studio/ReSharper. For example, there is no way to quickly add parameter documentation. Rider does not have any significant support for generating documentation (the initial format is very compact and never formatted according to rules).</p>
<p>Rider&rsquo;s parameter-completion in documentation works more smoothly (<kbd>Esc</kbd> not necessary), but it does not use a &ldquo;smart&rdquo; sorting for tags. In ReSharper, once I&rsquo;ve selected <code>paramref</code> once, that is sorted at the top and selected by default. In Rider, the order is unchanged, so I have to arrow down or type out most of the tag name in order to get past <code>param</code>.</p>
<p>Rider still shows a hint to add <code>&lt;inheritdoc/&gt;</code> on the class, even if the class has its own documentation.</p>
<div class="caution "><strong>Conclusion:</strong> Visual Studio&rsquo;s XML documentation support is slightly better than Rider&rsquo;s, but they&rsquo;re both quite good.</div><h3>General UI</h3><h4>Action Menu</h4><p>There&rsquo;s an extra item in the action list for &ldquo;move to separate file&rdquo; that does nothing. There&rsquo;s another item that includes the name of the file in the caption that <em>does</em> work.</p>
<h4>Tooltips</h4><p>There&rsquo;s no <em>Enhanced Tooltip</em> extension (and the tooltips are not as nicely formatted in Rider)</p>
<div class=" "><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/tooltipinresharper.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/tooltipinresharper_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/tooltipinresharper.png">Tooltip in ReSharper</a></span></span><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/tooltipinrider.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/tooltipinrider_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/tooltipinrider.png">Tooltip in Rider</a></span></span><span class="clear-both"></span></div><h4>Icons</h4><p>I can&rsquo;t seem to change colors of icons as I can for ReSharper. I&rsquo;d gotten used to brighter colors and miss them in Rider.</p>
<p><span style="width: 200px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/resharpericonoptions.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/resharpericonoptions_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/resharpericonoptions.png">ReSharper Icon Options</a></span></span></p>
<h4>Inlays</h4><p>In ReSharper, you can disable specific inlay hints directly from the completion menu. In Rider, you can do this for some of them, but not all. If it&rsquo;s not there, you have to select &ldquo;Configure inlay hints&rdquo; and then have to find the corresponding checkbox yourself.</p>
<h4>Windows Integration</h4><p><del>Rider doesn&rsquo;t keep track of the last opened solutions to open from the task list.</del> <strong class="highlight">[As of 2021.1.1, the task list is now populated with recent solutions.]</strong></p>
<h4>Git Integration</h4><p>The &ldquo;Commit&rdquo; panel doesn&rsquo;t refresh very quickly at all. Long after I&rsquo;d seen the files in SmartGit, they were still not in the panel. When I switched away and then back, the new changes suddenly appeared. I don&rsquo;t use the integrated Git support, but I&rsquo;m not going to start, either, after seeing how it works.</p>
<h4>File Structure</h4><ul>
<li>The file structure panel does not highlight the element where the cursor is.</li>
<li>The file structure panel does not support dragging and dropping</li>
<li>The file structure panel does not refresh to reflect changes without closing it (or switching to another panel that hides it) and reopening/reshowing it</li></ul><h4>Key Maps</h4><p>I can&rsquo;t search for the bindings for a key combination in Rider, like I can in Visual Studio. Instead, I have to guess at the name of the operation that I think it&rsquo;s bound to.</p>
<p><strong class="highlight">Update 23.04.2021:</strong> I&rsquo;ve found that if you click on the magnifying glass to the right of the search field, you can &ldquo;Find actions by shortcut&rdquo;.</p>
<h4>Fine-tuning Formatting</h4><div class=" "><p>Rider also doesn&rsquo;t have the &ldquo;show active configurations&rdquo; panel, for some reason. I&rsquo;m currently fighting with Rider because it suddenly came up with the idea to format everything with 4 spaces instead of 2 spaces. Just <em>yesterday</em> this was finally working so that I could reformat the document and everything worked. Now, Rider is reindenting everything for me. Visual Studio/ReSharper is showing that I have 2 spaces configured.</p>
<p><span style="width: 273px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/activeconfigurations.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4109/activeconfigurations.jpg" alt=" " style="width: 273px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/activeconfigurations.jpg">Active configurations/file formatting info</a></span></span></p>
</div><div class="caution "><strong>Conclusion:</strong> Visual Studio w/ReSharper has a slight advantage in that it still feels more complete than Rider does.</div><h2>Conclusion</h2><p>Although Visual Studio/ReSharper edged out Rider in most of these categories, you&rsquo;re well-served with either one. I think if I&rsquo;d compared Visual Studio by itself to Rider, then Rider would have won easily. It&rsquo;s only in combination with ReSharper that Visual Studio ends up being a bit better. It&rsquo;s just more mature and I never found myself going to Rider from Visual Studio, whereas I did have to open Visual Studio a few times to fix something I couldn&rsquo;t do in Rider.</p>
<p>It&rsquo;s happening less with each version, though. Over the four months of the evaluation, Rider has improved steadily [5] I think you&rsquo;re well-served with either version.</p>
<p>Once Rider files off a few more rough edges and has true feature-parity—perhaps by natively implementing some of the inspections from the ReCommended extension—it&rsquo;s slightly smoother editor might help it pull ahead in this comparison.</p>
<p>Most of the above is complaining to a <em>very</em> standard, though. Both IDEs will make anyone who knows how to use them a much more efficient developer of reliable and readable code.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4109_1_body" class="footnote-number">[1]</span> I actually have an Enterprise license through Encodo&rsquo;s Silver Partnership. However, when that license lapsed at one point (we forgot to take a test on time), I&rsquo;d installed Community in order to keep working. A few days later, when my license was restored, I didn&rsquo;t see the need to install Enterprise again. Almost two years later and I still haven&rsquo;t done it. The Visual Studio installer doesn&rsquo;t offer to &ldquo;upgrade&rdquo; the Community edition and I don&rsquo;t have space for side-by-side installations. I could uninstall and re-install, but everything&rsquo;s working now, and I miss nothing from Enterprise.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4109_2_body" class="footnote-number">[2]</span> <p>The last time I tried working with Visual Studio without ReSharper was over two years ago, with Visual Studio 2019 Preview 3. Still, I can see much more of Visual Studio working better than ever, taking over more and more of what I use ReSharper for.</p>
<p>I&rsquo;d installed Visual Studio 2019 Preview 3 to investigate the following,</p>
<ul>
<li>Memory usage</li>
<li>C# 8 features</li>
<li>How does VS2019 work without ReSharper?</li></ul><p>I installed the desktop and web-development workloads, totaling almost 6GB.</p>
<ul>
<li>Memory usage is better, obviously.</li>
<li>I liked the default highlighting with purple for flow keywords (I actually ended up turning this on for ReSharper, as well)</li>
<li>Finding references, ancestors and implementations is still tedious because Visual Studio does everything in panels or tool windows, rather than with popup menus</li>
<li>Solution-wide analysis isn&rsquo;t nearly the same</li>
<li>Source-level highlighting of errors and warnings as I type are noticeably slower</li>
<li>The test runner is much better than it used to be, but still not as good as the one in ReSharper/Rider.</li>
<li><kbd>Ctrl</kbd> + <kbd>Q</kbd> to quick-search features works just as well as <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>A</kbd> does to find &ldquo;actions&rdquo; in ReSharper.</li></ul><p>In November of 2020, the article <a href="https://devblogs.microsoft.com/dotnet/announcing-net-5-0/">Announcing .NET 5.0</a> by <cite>Richard Lander</cite> (<cite><a href="http://devblogs.microsoft.com/">MS Blogs</a></cite>) wrote that,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…m]oving forward, the idea is that as when we add new features to .NET, we&rsquo;re also adding corresponding analyzers and code fixers to help you use them correctly, right out of the gate.&rdquo;</div></blockquote><p>and</p>
<blockquote class="quote quote-block "><div>&ldquo;With .NET 5, we have heavily improved our support for static code analysis. This includes an analyzer for platform-specific code and a better mechanism to deal with obsoletions. The .NET 5 SDK includes over 230 analyzers!&rdquo;</div></blockquote><p>The latest versions of VS also allow you to fine-tune the severity of any warnings directly from the UI/Solution Explorer. This is all a great leap forward for Visual Studio 2019, but ReSharper still improves the following features:</p>
<ul>
<li>Navigation is much faster</li>
<li><div>Searching and introspection is more efficient and uses better UX than VS&rsquo;s standard lists<div class=" "><p>There are more refactorings. Visual Studio doesn&rsquo;t yet help with inlining variables and methods in as many places as ReSharper does. Also, there are subtle inspections and quick fixes, like the following two that are only available with ReSharper/Rider.</p>
<p><span style="width: 407px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/superfluouscondition.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/superfluouscondition.png" alt=" " style="width: 407px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/superfluouscondition.png">Superfluous Condition</a></span></span><br>
<span style="width: 269px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4109/simplifyexpression.png"><img src="https://www.earthli.com/data/news/attachments/entry/4109/simplifyexpression.png" alt=" " style="width: 269px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4109/simplifyexpression.png">Simplify Expression</a></span></span></p>
</div></div></li>
<li>The test runner is head and shoulders above that of VS</li>
<li>I miss &ldquo;Find Everywhere&rdquo;. R#&rsquo;s integration of &ldquo;find in files&rdquo; is so much faster than VS.</li></ul></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4109_3_body" class="footnote-number">[3]</span> Visual Studio&rsquo;s search is available, but it&rsquo;s weaker than ReSharper&rsquo;s. Enough so that I don&rsquo;t want to use it unless I have to. It&rsquo;s <em>good</em>, don&rsquo;t get me wrong. It&rsquo;s just not <em>as good</em> as I know what I could have were I to install ReSharper.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4109_4_body" class="footnote-number">[4]</span> As <strong class="highlight">noted</strong> in a few places above.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4224</guid>
    <title><![CDATA[Set a Git Tag on Azure]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4224</link>
    <pubDate>Tue, 30 Mar 2021 21:04:45 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. Mar 2021 21:04:45 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>As with <a href="https://www.earthli.com/news/app]view_article.php?id=4223">installing a dotnet tool on Azure</a>, there isn&rsquo;t a standard task for setting a Git tag from a pipeline YAML configuration. The Pipeline UI has an option to easily do this, but that hasn&rsquo;t translated to a task yet, nor does it look like it&rsquo;s likely to, according to online discussions.</p>
<p>Setting a Git tag is relatively straightforward, but is complicated by permissions (as with <a href="https://www.earthli.com/news/app]view_article.php?id=4223">installing a dotnet tool</a>. To tag a build, you have to just execute the <code>git</code> commands in a script.</p>
<pre class=" "><code>  − task: CmdLine@2
    displayName: Push Git Tag
    inputs:
      script: |
        git tag $(Build.BuildNumber)
        git push origin $(Build.BuildNumber)</code></pre><p>If, for whatever reason, you want the tag to be created by the triggering user, then include the following lines as well:</p>
<pre class=" "><code>  − task: CmdLine@2
    displayName: Push Git Tag
    inputs:
      script: |
        git config user.email $env:BUILD_REQUESTEDFOREMAIL
        git config user.name $env:BUILD_REQUESTEDFOR
        git tag $(Build.BuildNumber)
        git push origin $(Build.BuildNumber)</code></pre><p>You should include this step after the version number has been updated.</p>
<p>With the task in place, you have to ensure that you&rsquo;ve granted permissions to the proper user.</p>
<ol>
<li>Go to the &ldquo;project settings&rdquo;</li>
<li>Select &ldquo;Repos/Repositories&rdquo;</li>
<li>Select the &ldquo;Permissions&rdquo; tab</li>
<li>Allow the specific permission &ldquo;Contribute&rdquo; for the &ldquo;Project Collection Build Service&rdquo; user. [1]</li></ol><p><span style="width: 589px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4224/repositorypermissions.png"><img src="https://www.earthli.com/data/news/attachments/entry/4224/repositorypermissions.png" alt=" " style="width: 589px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4224/repositorypermissions.png">Granting Repository Permissions</a></span></span></p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4224_1_body" class="footnote-number">[1]</span> Note: granting the permission to &ldquo;Project Collection Build Service Accounts&rdquo; or &ldquo;[Project Name] Build Services&rdquo; had no noticeable effect.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4223</guid>
    <title><![CDATA[Installing a dotnet tool on Azure]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4223</link>
    <pubDate>Mon, 29 Mar 2021 22:36:59 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">29. Mar 2021 22:36:59 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I have a .NET solution (Quino) that contains a project that I publish as a `dotnet` tool. The tool calculates a version number based on the branch and version number found in the solution. I use it from Quino itself and also from other project pipelines.</p>
<p>In order to use it from any pipeline (including Quino itself), I need to install it from the Quino artifact feed. The original solution is a couple of years old: I&rsquo;d had a secure file for NuGet.Config that included the PAT. This works fine, until the PAT expires.</p>
<p>So, I went searching for a better solution and thought I&rsquo;d try something a bit more resilient and better-supported. By now, I&rsquo;m using YAML files for my pipeline, so I tried the <code>DotNet</code> task, but it doesn&rsquo;t support installing tools.</p>
<p>There are open issues and even a very old open pull-request for supporting a Microsoft tool on Microsoft&rsquo;s premiere hosting service that Microsoft has steadfastly ignored. There seem to be no plans for supporting <code>dotnet tool install</code> natively, with seamless authentication, as they&rsquo;ve done for <code>dotnet restore</code>. The example below shows how this works for <code>restore</code>.</p>
<pre class=" "><code>  − task: DotNetCoreCLI@2
    displayName: 'Restore Server Packages'
    inputs:
      command: 'restore'
      feedsToUse: 'select'
      feedRestore: 'Quino'
      projects: 'server/src/**/*.csproj'
      verbosityRestore: Normal
      includeNuGetOrg: true</code></pre><p>I was hoping to follow this pattern to use the <code>dotnet</code> task to install a tool with something like the following:</p>
<pre class=" "><code>  − task: DotNetCoreCLI@2
    displayName: 'Restore Server Packages'
    inputs:
      command: 'tool install'
      feedsToUse: 'select'
      feedRestore: 'Quino'
      includeNuGetOrg: true
      isGlobal: true
      toolName: quino</code></pre><p>There is no support for this. The PR mentioned above would support it, but it&rsquo;s never been accepted and Microsoft has not seen fit to add automatically authenticated feeds for anything other than <code>restore</code>.</p>
<p>Instead, I use two tasks: the first is a workaround for the lack of proper support in Azure for `dotnet tool install` from authenticated feeds; the second installs the tool. See <a href="https://github.com/Microsoft/azure-pipelines-tasks/issues/10057">dotnet tool install/update&rdquo; not working with Azure Artifacts #10057</a> and <a href="https://github.com/microsoft/azure-pipelines-tasks/pull/13401">Add dotnet tool install command to support tools location in Azure Artifact feeds #13401</a> (the PR) for more information.</p>
<p>I can copy/paste the two tasks below into all of the pipelines that need it. It&rsquo;s a bit bulky and non-intuitive, but it is both project-agnostic and doesn&rsquo;t include any passwords or PATs directly. Instead, it uses the <code>$(System.AccessToken)</code>. If the project has been granted access to the feed identified by <code>&lt;INTERNALFEEDURL&gt;</code> using the standard feed permissions control panel, then it works.</p>
<pre class=" "><code>  − task: NuGetCommand@2
    displayName: 'NuGet Add Credentials For Internal Feed'
    inputs:
      command: custom
      arguments: &gt; 'sources add
        -Name "&lt;INTERNALFEEDNAME&gt;"
        -Source "&lt;INTERNALFEEDURL&gt;/nuget/v3/index.json"
        -Username "this_value_could_anything"
        -Password "$(System.AccessToken)"'
  − task: CmdLine@3
    displayName: Install tools
    inputs:
      targetType: inline
      script: dotnet tool install &lt;TOOLNAME&gt; –global</code></pre><p>Where:</p>
<ul>
<li><code>&lt;INTERNALFEEDURL&gt;</code> is obtained from your Azure project</li>
<li><code>&lt;INTERNALFEEDNAME&gt;</code> doesn&rsquo;t matter, as long as it doesn&rsquo;t conflict with any defaults</li>
<li><code>&lt;TOOLNAME&gt;</code> is the name of the tool to execute</li></ul><p>This is utterly unintuitive, but it works and it&rsquo;s not <em>too</em> much hacking. I think it&rsquo;s indisputable that it would be much nicer if &ldquo;install tool&rdquo; was an option for the &ldquo;dotnet&rdquo; command. It&rsquo;s not like it&rsquo;s an external tool. This is literally how Microsoft has asked us to work.</p>
<p>It would be nice if I hadn&rsquo;t had to spend half an afternoon trying to figure out how to get a dotnet tool installed from a feed in the same project on Azure. I&rsquo;m glad I got it working, but everyone who comes after will also waste time trying to figure this out—or will give up and use a gross hack instead.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4208</guid>
    <title><![CDATA[A nice CSS demo that uses 350% CPU]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4208</link>
    <pubDate>Sat, 13 Mar 2021 22:09:08 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Mar 2021 22:09:08 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://www.bram.us/2021/03/03/mapping-mouse-position-in-css-demo/">Getting the Mouse Position using CSS</a> by <cite>Bramus</cite> talks about a neat trick that uses sibling elements to react to mouse events without using JavaScript. It also features some kick-ass translucency and animation effects with CSS transitions.</p>
<p>As you move the cursor around, the layer of &ldquo;cells&rdquo; change X and Y positions that the CSS text elements &ldquo;watch&rdquo;. This lets the central elements &ldquo;follow&rdquo; the mouse, transforming a stack of &ldquo;CSS&rdquo; texts in a nicely composed and layered stack. It looks like this.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/4208/image_2021-03-13_160129.png" alt=" " style="width: 442px"></p>
<p>While this is a nice-looking effect—and it&rsquo;s impressive that it works purely in the browser and purely in CSS—it kicked in the fan on my iMac, something that rarely happens.</p>
<p>That said, the compositing features of a modern browser are impressive and can save website authors a lot of time and effort. That this is even possible is already really, really nice. Maybe with a bit of tweaking, it can be made less detrimental to battery life.</p>
<p>If you want to try it out yourself or tweak the code, check out the <a href="https://codepen.io/amit_sheen/embed/261df6f09d15a179b63454bb75acc191?default-tab=result&amp;theme-id=1">CodePen</a>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4198</guid>
    <title><![CDATA[TIHI: SmartGit's new "Discard to Stash" Feature]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4198</link>
    <pubDate>Thu, 04 Mar 2021 22:39:04 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Mar 2021 22:39:04 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Mar 2021 22:39:38 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This a quick note for anyone else who&rsquo;s downloaded the latest version of SmartGit (20.2.3 #16150) and is seeing mysterious stashes that they know they haven&rsquo;t created.</p>
<p>There&rsquo;s a new feature called &ldquo;discard to stash&rdquo; that is enabled by default.</p>
<p><span style="width: 498px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4198/screen_shot_2021-03-03_at_13.36.57.png"><img src="https://www.earthli.com/data/news/attachments/entry/4198/screen_shot_2021-03-03_at_13.36.57.png" alt=" " style="width: 498px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4198/screen_shot_2021-03-03_at_13.36.57.png">Discard to Stash selected by default</a></span></span></p>
<p>What this does is to stash every time you press <kbd>⌘</kbd> + <kbd>Z</kbd> to discard changes. I understand that this is a failsafe &ldquo;just in case&rdquo;, but I kept ended up with a dozen stashes I had no use for. On balance, I&rsquo;d rather have the tiny risk of wanting changes back that I&rsquo;d discarded—I can&rsquo;t recall this ever having happened—than the &ldquo;noise&rdquo; of stashes muddling the list of actual stashes I&rsquo;d saved.</p>
<p>I started off trying to train myself to hit <kbd>right arrow</kbd> and then enter, or typing <kbd>D</kbd> instead of <kbd>⏎</kbd>, but I gave up and found an &ldquo;advanced&rdquo; preference to switch the default behavior.</p>
<p><span style="width: 519px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4198/screen_shot_2021-03-04_at_08.34.40.png"><img src="https://www.earthli.com/data/news/attachments/entry/4198/screen_shot_2021-03-04_at_08.34.40.png" alt=" " style="width: 519px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4198/screen_shot_2021-03-04_at_08.34.40.png">Change default value for Discard to Stash</a></span></span> </p>
<ol>
<li>Open Preferences</li>
<li>Select &ldquo;Low-level properties&rdquo;</li>
<li>Select &ldquo;I accept the risk!&rdquo;</li>
<li>Search for &ldquo;discard&rdquo;</li>
<li>Change the value to &ldquo;false&rdquo;</li>
<li>Press OK</li></ol>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4174</guid>
    <title><![CDATA[A breakdown of programming languages used in a week]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4174</link>
    <pubDate>Wed, 17 Feb 2021 21:56:03 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Feb 2021 21:56:03 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In one recent week, I realized I&rsquo;d been working in many different areas and on many different projects, so I took an inventory.</p>
<p>For one project, I reconfigured a program with <strong class="highlight">Delphi Pascal</strong>, using <strong class="highlight">Delphi 7</strong> (it&rsquo;s a very old, legacy solution) to run on my local machine instead of in a VM that had swollen to 120GB. For that project, I also used <strong class="highlight">SQL</strong> on <strong class="highlight">SQL Server</strong>, running in a <strong class="highlight">Docker</strong> container that I&rsquo;d configured with <strong class="highlight">YAML</strong>. The solution has several products, among which you can switch, so I wrote a <strong class="highlight">Windows Batch</strong> program to transfer and back up versions, so you can nicely diff them with <strong class="highlight">SmartGit</strong> using <strong class="highlight">Git</strong>. In order to diff SQL, I used a tool written in <strong class="highlight">TypeScript</strong>, which I extended with a few fixes and tests written with <strong class="highlight">Jest</strong> in <strong class="highlight">Visual Studio Code</strong>. I updated the documentation in <strong class="highlight">Markdown</strong>.</p>
<p>At the same time, I was working on <a href="https://www.encodo.com/quino">Quino</a>, written in <strong class="highlight">C#</strong> for the <strong class="highlight">.NET</strong> platform, using <strong class="highlight">Visual Studio</strong> on <strong class="highlight">Windows</strong> and <strong class="highlight">Jetbrains Rider</strong> on <strong class="highlight">MacOS</strong>. I also set up a new solution using Quino, which involved editing a bunch of <strong class="highlight">XML</strong> project files as well as configuring <strong class="highlight">SQL Server</strong> and <strong class="highlight">PostgreSql</strong> with <strong class="highlight">Docker</strong>. I again used <strong class="highlight">YAML</strong> to define pipelines in <strong class="highlight">Azure DevOps</strong>.</p>
<p>For two evenings, I graded final projects for a <strong class="highlight">JavaScript</strong> class I&rsquo;ve just finished teaching. On the other evenings, I researched modern <strong class="highlight">HTML</strong>, <strong class="highlight">CSS</strong>, and <strong class="highlight">SVG</strong> for an upcoming redesign of earthli. I made a few <strong class="highlight">PHP</strong> fixes for earthli as well.</p>
<p>I wrote blog posts, wiki entries, and issue analyses in <strong class="highlight">Jira Syntax</strong>, <strong class="highlight">Markdown</strong>, <strong class="highlight">XWiki syntax</strong>, and <strong class="highlight"><a href="https://dev.earthli.com/news/text_formatting.php">earthli Syntax</a></strong> in both English and German.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4127</guid>
    <title><![CDATA[Software without Process]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4127</link>
    <pubDate>Sun, 17 Jan 2021 17:43:34 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Jan 2021 17:43:34 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/4127/pallet_o_wrapped_boxes_30595876_6.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4127/pallet_o_wrapped_boxes_30595876_6_tn.jpg" alt=" " class=" align-left"></a>A software product with undocumented or poorly documented commits and a patchy issue-tracker is akin to a shipping pallet with 100 boxes haphazardly stacked on it, all wrapped up in shipping cellophane. You can see some of the labels and some of them you can&rsquo;t and some of the boxes definitely don&rsquo;t even have labels at all.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/4127/pallet_o_ugly_boxes_30595876_6.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/4127/pallet_o_ugly_boxes_30595876_6_tn.jpg" alt=" " class=" align-right"></a>If it looks like the pallet to the right, then you already know you can&rsquo;t ship it. That&rsquo;s an obvious train-wreck of a project that&rsquo;s going to blow up in everyone&rsquo;s face. But the picture to the left looks…OK…ish. How do you know if it&rsquo;s legit? Check the shipping manifest and get out your scanner gun, right?</p>
<p>The shipping manifest on your clipboard has 3 and ½ items on it, none of them really helpful. If you really want to be sure about what you&rsquo;re shipping, you&rsquo;re going to have to unwrap the whole thing and look at each box individually, noting it on the manifest if it&rsquo;s missing — and maybe even opening it up to see what&rsquo;s actually inside. Maybe it&rsquo;s even broken and leaking on other boxes, somewhere in the middle of that whole pile.</p>
<p>Maybe someone wrapped it in cellophane to give it the <em>sheen</em> of reliability, but you can&rsquo;t know for sure. Is it possible that you spend all of the time to dot the i&rsquo;s and cross the t&rsquo;s just in order to find out that it was fine, but just drastically under-documented? It&rsquo;s possible, of course. That&rsquo;s a risk you take when you try to be professional. The alternative is to become a gambler—shipping something and hoping that it doesn&rsquo;t come back to haunt you.</p>
<p>A better approach would have been to use a documenting process as you built the product—like engineers rather than cowboys—slowing our awesome selves down a bit, but also—maybe, just maybe—getting <em>faster</em> because we&rsquo;re more careful and can avoid wasting time on work that doesn&rsquo;t need to be done.</p>
<p>Documenting the work to be done—e.g. to explain it to other team members—can have the much-appreciated side-effect of focusing you on the work that actually needs doing. This is generally more efficient and satisfying than just shooting out of the gate and doing what you &ldquo;know needs doin&rsquo;&rdquo; and not noticing possible ramifications until it&rsquo;s too late do anything but <em>react to</em>  rather than <em>plan for</em> them.</p>
<p>In the end, you have not only solid, well-designed, and tested software, but also good documentation of what was actually done for a given release, as well as analyses for what <em>was not done</em> and <em>what needs doing in the future.</em> That everything is well-documented enough to implement <em>now</em> means you&rsquo;ve got half a chance of still knowing what it means in ½ or ¾ of a year when you finally get a chance to plan and implement it.</p>
<p>Who knows? You may never need to work on it again—which is just fine. At least you&rsquo;ll know what you didn&rsquo;t implement and <em>why</em>. This is very helpful for that time, in a year or two, when you think of this <em>exact same solution</em> and are maybe too stressed or under too much pressure to remember why you decided against it the first time.</p>
<p>A good software product is not just the product itself, but all of the metadata surrounding it: the documentation, the analyses, the release notes, the roadmap.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4142</guid>
    <title><![CDATA[Set up PHP With Docker, PHPStorm, and XDebug]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4142</link>
    <pubDate>Sun, 17 Jan 2021 00:01:34 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Jan 2021 00:01:34 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Until now, PHP debugging involved a fragile balance between the IDE, the server, and the debugger, each with overly verbose configuration. On top of that, using Docker introduced the wrinkle that you were technically debugging on a remote server rather than on the &ldquo;real&rdquo; localhost.</p>
<p>It&rsquo;s been a long journey, but it&rsquo;s finally a <em>lot</em> easier to set up PHP debugging with a server running in a Docker container. Once you use the most modern tools, everything works with a couple of lines of configuration.</p>
<blockquote class="quote abstract "><div><p><abbr title="too long; didn't read">tl;dr</abbr>:</p>
<ul>
<li>Ignore anything you find on StackOverflow from before November of 2020 and use <a href="https://github.com/mlocati/docker-php-extension-installer">the install-php-extensions project</a> instead (see example below).</li>
<li>Set environment variables in the docker-compose file to indicate the client and the default mode (debug)</li>
<li>Use the latest PHPStorm, which supports XDebug 3.x</li></ul></div></blockquote><p>My setup is as follows:</p>
<ul>
<li>PHPStorm 2020.3.1 running on MacOS</li>
<li>Docker 3.0.4 running on MacOS</li>
<li>&ldquo;db&rdquo; container running MySql 5.7.24</li>
<li>&ldquo;web&rdquo; container running PHP 7.2.24 on Apache</li></ul><p>So far, so good: it&rsquo;s basically a standard developer setup for PHP where I have an IDE on my machine and am running servers in Docker containers. XDebug initiates a connection from the server in the &ldquo;web&rdquo; container back to the IDE on the docker host.</p>
<p>Without further ado, these are the magic configuration files to install extensions and set up XDebug for PHP.</p>
<h2>web/Dockerfile</h2><p>After much searching and rigamarole and fighting with <code>docker-php-ext-install</code> and <code>docker-php-ext-enable</code> and <code>PECL</code> and where the <code>PHP.INI</code> is and whether I need to move one of the default files somewhere so that PECL can update it and downloading dependencies with <code>apt-get</code> and getting the right dependencies, depending on the PHP version and passing the right flags to <code>docker-php-ext-configure</code> if the version is a bit older and, and, and…</p>
<p>After trying a ton of no-longer-relevant and now-overly-complex suggestions on StackOverflow, I finally returned to <a href="https://hub.docker.com/_/php/">php on dockerhub</a> and discovered a hint to use <a href="https://github.com/mlocati/docker-php-extension-installer">the install-php-extensions project</a>, which basically takes care of everything for you.</p>
<p>It does. End of story.</p>
<pre class=" "><code>FROM php:7.2.24-apache

ENV DEBIAN_FRONTEND=noninteractive

ADD https://github.com/mlocati/docker-php-extension-installer/releases/
latest/download/install-php-extensions /usr/local/bin/

RUN chmod +x /usr/local/bin/install-php-extensions &amp;&amp; sync &amp;&amp; \
    install-php-extensions gd xdebug mysqli exif zip</code></pre><p>I pin the PHP version to the one on my server, download the latest version of <code>install-php-extensions</code> [1] and then call it to install the non-standard extensions I use on earthli:</p>
<ul>
<li><code>exif</code>: Extract date information from pictures</li>
<li><code>gd</code>: Generate thumbnails</li>
<li><code>mysqli</code>: Provide access to MySql using a legacy API</li>
<li><code>xdebug</code>: Debugging support on the server</li>
<li><code>zip</code>: Open and read files from ZIP archives</li></ul><p>See the <a href="https://github.com/mlocati/docker-php-extension-installer">web site</a> for the list of supported packages. Your site will likely use different ones (but you should definitely install <code>xdebug</code> because it&rsquo;s totally easy to use now).</p>
<h2>docker-compose.yaml</h2><p>Finally, you just need to set two environment variables to enable debugging for PHP:</p>
<ul>
<li><code>XDEBUG_CONFIG</code>: accepts a list of settings, but we only need to set the <code>client_host</code> to tell XDebug which machine hosts the IDE to which to connect (Docker handily provides the <code>host.docker.internal</code> alias for MacOS and Windows)</li>
<li><code>XDEBUG_MODE</code>: this sets up the tool for step-debugging (see <a href="https://xdebug.org/docs/all_settings#mode">XDEBUG mode</a> for more information).</li></ul><p>I&rsquo;ve included nearly the full <code>Dockerfile</code> from earthli, but the only relevant part for debugging is in the <code>environment</code>.</p>
<pre class=" "><code>  web:
    build: web
    container_name: "${COMPOSE_PROJECT_NAME}-web"
    restart: unless-stopped
    ports:
      − 80:80
    volumes:
      − ../site:/var/www/html
      − ../lib:/var/tmp/earthli.com-lib
      − ../../earthli-webcore/site:/var/tmp/webcore-site
      − ../../earthli-webcore/lib:/var/tmp/webcore-lib
      − ../../earthli-data:/var/tmp/earthli-data
      − ../../earthli-logs:/var/tmp/logs
      − ../config/apache-dev.conf:/etc/apache2/sites-available/000-default.conf
    depends_on:
      − db
    environment:
      XDEBUG_CONFIG: client_host=host.docker.internal
      XDEBUG_MODE: debug</code></pre><h2>PHPStorm and Browser</h2><p>At this point, you&rsquo;re well on your way to debugging with PHPStorm. From here, follow the instructions in the settings dialog, shown below.</p>
<p><span style="width: 698px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/4142/phpstormdebugsettings.png"><img src="https://www.earthli.com/data/news/attachments/entry/4142/phpstormdebugsettings.png" alt=" " style="width: 698px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/4142/phpstormdebugsettings.png">PHPStorm Debug Settings</a></span></span></p>
<ul>
<li>You can click the &ldquo;Validate&rdquo; link in the dialog to verify that your XDebug is recognized and working in principle</li>
<li>Activate step debugging from the browser. You can pass <code>XDEBUG_SESSION=PHPSTORM</code> in the query string, but that gets a bit tedious. Instead, <a href="https://www.jetbrains.com/help/phpstorm/2020.3/browser-debugging-extensions.html?utm_source=product&amp;utm_medium=link&amp;utm_campaign=PS&amp;utm_content=2020.3">install a browser-debugging extension</a>, which simply injects the cookie <code>XDEBUG_SESSION=PHPSTORM</code> into the request so that PHPStorm knows that debugging is desired. See <a href="https://xdebug.org/docs/step_debug">XDebug&rsquo;s documentation</a> for more information on other ways of triggering debugging, including from the command line (e.g. when running unit tests).</li>
<li>Make sure PHPStorm is listening for incoming PHP Debug Connections (you can toggle in the dialog shown above or from the toolbar in the IDE).</li></ul><p>That&rsquo;s it. A long and kind of painful journey has finally led to a solid and easy-to-configure debugging experience for PHP.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4142_1_body" class="footnote-number">[1]</span> I will probably pin the version to the one I&rsquo;m using <em>right now</em> because I know it works.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=4026</guid>
    <title><![CDATA[A dynamically generated Groovy foot-gun]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=4026</link>
    <pubDate>Sun, 05 Jul 2020 21:52:52 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">5. Jul 2020 21:52:52 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Groovy is a dynamically typed programming language that executes on the Java Runtime. It mixes its own highly dynamic syntax with islands of Java code. The Android ecosystem and its IDE use Gradle for its build scripts. Gradle uses the Groovy programming language.</p>
<h2>The Problem Code</h2><p>A large project I&rsquo;m working on contains quite a bit of custom Gradle code for integrating framework libraries, making obfuscated builds, configuring publication, and, finally, creating signed builds.</p>
<p>The signed builds are configured using standard Android Gradle DSL commands. Basically, there was a block of code something like the one shown below.</p>
<pre class=" "><code>signing {
  storeFile = getKeyStoreFile()
  storePassword = getKeyStorePassword()
  keyAlias = getKeyAlias()
  keyPassword = getKeyPassword()
}</code></pre><p>The names of the methods (e.g. <code>getKeyAlias</code>) used to be different before I&rsquo;d refactored them to have more standard names. [1] The methods check whether there are environment variables set by the build server, using sane defaults for developer builds. [2]</p>
<p>This is where I went wrong. Never touch a running system [3], even when you&rsquo;re trying to pull it back from the precipice of &ldquo;maintenance nightmare that everyone is terrified to touch, to say nothing of change&rdquo;. Well, I changed it, and ended up frittering away a couple of hours investigating the Groovy &ldquo;feature&rdquo; outlined below.</p>
<h2>Lowering Groovy to Java</h2><p>Groovy performs syntax-checking, but is <em>extremely</em> lenient as far types and variables are concerned. Variables have to be defined, but pretty much anything can be coerced into anything else. It is transformed to Java code and then Java byte code by the Java compiler. Any typing errors you see are from the Java compiler, not the </p>
<p>As any programming language would, Groovy resolves identifiers to match the declaration that is closest in scope to the call, <em>even when that declaration is generated at compile-time</em> and couldn&rsquo;t possibly be the one that the original author had intended to call. This is going to be important later (which is why I put it in scary italics).</p>
<p>The four methods above are defined in an <code>ext {}</code> block [4]. Calling them without a specific target as above automatically resolves to the methods from the <code>ext {}</code> block.</p>
<p>Oddly, of the four properties being set in the example above, only the first two actually called the methods I&rsquo;d defined in the <code>ext {}</code> block. The calls to <code>getKeyAlias()</code> and <code>getKeyPassword()</code> were not made to the expected functions. I could tell they weren&rsquo;t being called because the <code>logger.info()</code> calls from those two methods never appeared in the output.</p>
<p>What the hell is going on? If you look carefully, you&rsquo;ll notice that the first two methods have <em>different</em> names than you would use for writing the getter and setter for the properties being assigned. The second two methods match those names exactly.</p>
<h2>Auto-generated Java Code</h2><p>When Groovy lowers its syntax to Java code, it declares these getters and setters. The Java compiler, in turn, references these new methods because the calls in the original Groovy code hadn&rsquo;t been specific about the target of the methods. Instead of lowering to Java code and being explicit about which <code>ext</code> block the method should be called from, Groovy just left the naked call as I&rsquo;d written it. Probably, if I&rsquo;d explicitly called <code>ext.getKeyAlias()</code>, it would have avoided calling the dynamically generated <code>this.getKeyAlias()</code> method. </p>
<p>Of course, Groovy had trained me to stop prepended the target <code>ext.</code> on global function calls because <code>ext</code> resolves to different things, depending on the DSL-specific context. Sometimes it&rsquo;s the root project&rsquo;s extra variables and sometimes it&rsquo;s the sub-projects extra variables and sometimes <code>ext</code> doesn&rsquo;t work at all (e.g. in Java classes, naturally, but also in blocks created by special keywords). </p>
<p>Sure, you can trying playing around with <code>rootProject.ext.</code> or other similar constructs, but the code quickly becomes even more unreadable than it already would be and the non-prefixed version works 99% of the time.</p>
<p>So what ended up happening was that, instead of calling the method I&rsquo;d actually called, the Groovy compiler generated a new method with the same name and a higher specificity in the scope, capturing the call. Instead of calling my method, it ended up calling <code>this.setKeyAlias(this.getKeyAlias())</code>, which is basically a NOP that leaves the property empty.</p>
<h2>Fixing the Problem</h2><p>The solution is to use a unique name for the function that does not conflict with any of the auto-generated getters. That is, of course, an unmaintainable nightmare, but part and parcel of working with Gradle.</p>
<pre class=" "><code>signing {
  storeFile = getKeyStoreFile()
  storePassword = getKeyStorePassword()
  keyAlias = get<strong class="highlight">Signing</strong>KeyAlias()
  keyPassword = get<strong class="highlight">Signing</strong>KeyPassword()
}</code></pre><p>Lo and behold, my log entries appeared and I was back in business.</p>
<h2>Fixing the Compiler</h2><p>The compiler authors could have tried harder to avoid altering the semantics of the higher-level Groovy code when replacing it with Java.</p>
<p>One way would be to  use more obfuscated auto-generated getters and setters (to the degree that Java even allows this, which I think it does).</p>
<p>Another way was hinted at above: when lowering calls that auto-resolve to functions declared in <code>ext</code> regions, include information about the resolution in the call made in Java. That is, instead of just encoding <code>getKeyAlias()</code> as I&rsquo;d written it (which is semantically correct at the Groovy level), transform that call to <code>rootProject.ext.getKeyAlias()</code> in Java.</p>
<h2><abbr title="too long; didn't read">tl;dr</abbr></h2><p>Gradle is a shaky piece of business that automagically generates code that might replace actual, legitimate calls in your own code. It should never have been used for a build system. It makes <code>MSBuild</code> seem like a pretty good idea.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4026_1_body" class="footnote-number">[1]</span> The code had somewhat haphazard names before, which actually ended up protecting it from the bug I ran into. Lesson learned: using obtuse function names is <em>good</em>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4026_2_body" class="footnote-number">[2]</span> Yes, we&rsquo;re going to integrate a secret store like <em>Vault</em> instead of relying on environment variables. That comes <em>after</em> this refactoring.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4026_3_body" class="footnote-number">[3]</span> In the end, I was happy I&rsquo;d refactored everything because I ended up with a lot less code that was much more self-documenting. The job was to refactor and clean up scripts that had grown over the years, so there was no avoiding renaming oddly named methods. The side-effect in this case was unusually painful.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_4026_4_body" class="footnote-number">[4]</span> <p>Gradle lets you declare &ldquo;extra&rdquo; variables in a scoped block called <code>ext</code>.</p>
<p>The parent of this block depends on the context. It&rsquo;s usually <code>rootProject</code>, <em>unless</em> you&rsquo;re executing project-specific code, in which case any declarations will be made in the sub-project-specific <code>ext</code> block instead of the one for the <code>rootProject</code>.</p>
<p>It can get quite confusing if you&rsquo;re not sure which context you&rsquo;re in when you declare an <code>ext {}</code> block, which is why some authors try to declare <code>rootProject.ext</code> or <code>project.ext</code>, but then you run into problems when you grab a variable from the wrong extra region.</p>
<p>Not to mention that it gets quite a bit messier to read and if all authors don&rsquo;t stick to the same style, it becomes difficult to tell which explicit references are necessary and which are just thrown in there &ldquo;to make sure&rdquo;.</p>
<p>I settled on just declaring as much as possible in the <code>ext {}</code> and letting Groovy figure out which variable to use from scope. That ended up biting me in the ass exactly once, as detailed above.</p>
</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3978</guid>
    <title><![CDATA[C# 9: finally, covariant returns]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3978</link>
    <pubDate>Sun, 24 May 2020 22:27:00 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">24. May 2020 22:27:00 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/">Welcome to C# 9.0</a> by <cite>Mads Torgersen</cite> (<cite><a href="http://devblogs.microsoft.com/">Microsoft Dev Blogs</a></cite>) (May 2020) introduces several nifty new features that I am really looking forward to using.</p>
<h2>What about C# 8?</h2><p>I still haven&rsquo;t moved <a href="https://www.encodo.com/quino/">Quino</a> to C# 8, as the only feature I&rsquo;d love to have there is the non-nullable types, which ReSharper Annotations provide with earlier versions of C#. Not only that, but the nullabilities are properly propagated to users of Quino. It&rsquo;s understood that recent versions of Visual Studio and runtimes and compilers also do this but, until recently, our customers weren&rsquo;t up-to-date yet.</p>
<p>In C# 8, we could also replace extension methods with <strong>default interface methods</strong>—but we&rsquo;ve also been replacing almost all extension methods in Quino with singletons and composition anyway. A lot of the <a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8">rest of the features</a> are nice, and interesting, but they are targeted optimizations that don&rsquo;t really apply to a lot of the code that I write. I see how they are eminently useful for lower-level library and runtime optimization—many are clearly made to be able to handle web requests and fine-grained tasks more quickly and without allocation</p>
<h2>Features in C# 9</h2><p>Still, the features in C# 9 make an upgrade even more attractive.</p>
<ul>
<li><strong>Init-Only Properties</strong> can only be initialized in the object initializer, after which  they are immutable. This extends read-only properties, which can only be initialized to default values or in the constructor to make them much more useful and allow many, many more data structures to be immutable.</li>
<li><strong>Records</strong> reduce a <em>ton</em> of boilerplate for what used to be referred to as DTOs. The declaration support is very similar to the syntax in Typescript. Record classes automatically get construction, deconstruction, and value-based equality and hash-code support for a very natural way of declaring and working with immutable data.</li>
<li>The <strong>with</strong> keyword and functionality allows code to easily derive new data from existing data (e.g. <code>var originalPerson = otherPerson with { LastName = &ldquo;Hunter&rdquo; };</code>)</li>
<li>There&rsquo;s some neat improvements to pattern-matching with <strong>relational patterns</strong> and <strong>logical patterns</strong>, but I honestly don&rsquo;t expect to use that too much (my use of advanced pattern-matching so far has been relatively limited…I haven&rsquo;t even availed myself of the extended support in C# 8).</li>
<li>There are improvements to <strong>target-typing</strong> with some coalescing expressions now compiling as expected rather than requiring what always felt like a superfluous cast. I doubt I&rsquo;ll be using target-typing like this: <code>Point p = new (3, 5);</code> rather than this: <code>var p = new Point(3, 5);</code></li>
<li><div class=" "><p>And, finally, <strong>covariant return types</strong> make an appearance. Java has had these for forever and there is no logical downside to introducing them.</p>
<p>This allows a descendant method to change the return type of an override to a descendant as well. The most common use case would for the return type of a <code>Clone()</code> method. The next step would be to allow <em>anchored types</em> (as in Eiffel), which would let a method declare its return type as <code><em>like</em> this</code> and remove the requirement that each descendant override <code>Clone</code> at all, while still having the desired covariant return type.</p>
<p>I&rsquo;ve been musing about these features for what feels like most of my career.</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=820">Static-typing for languages with covariant parameters</a> (June 2003—as anchored types)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=1042">Joel “Blowhard” Spolsky Sounds Off</a> (January 2005)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=1436">Wildcard Generics</a> (November 2006—in Java, not C#)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=2216">Waiting for C# 4.0: A casting problem in C# 3.5</a> (October 2009—footnote linking to PDF about anchored types)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=2784">A provably safe parallel language extension for C#</a> (February 2013)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3125">C# 6 Features and C# 7 Design Notes</a> (March 2015)</li></ul></div></li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3940</guid>
    <title><![CDATA[W3C Web Animations]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3940</link>
    <pubDate>Mon, 13 Apr 2020 11:20:34 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Apr 2020 11:20:34 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Apr 2020 15:47:26 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The <a href="https://www.w3.org/TR/web-animations-1/">Web Animations Working Draft</a> (<cite><a href="http://www.w3.org/">W3C</a></cite>) was published in October of 2018. <a href="https://caniuse.com/#search=web%20animations">Can I use &ldquo;Web Animations&rdquo;</a> (<cite><a href="http://caniuse.com/">CanIUse</a></cite>) shows that the only browser that supports this API 100% is the latest technology preview on iOS and MacOS. Chromium-based browsers have had (very) basic support for quite some time, but Safari has thrown down the gauntlet with full support, which I learned about from <a href="https://webkit.org/blog/10266/web-animations-in-safari-13-1/">Web Animations in Safari 13.1</a> by <cite>Antoine Quint</cite> (<cite><a href="http://webkit.org/">WebKit Blog</a></cite>).</p>
<p>This API is intended to replace many usages of CSS Animations and CSS Transitions, which are not only somewhat verbose and unwieldy for even simple cases, but are also not efficient in that each animation tends to force itself to start, artificially interrupting the browser as it prepares a page. With the Web Animations API, a page can much more declaratively indicate its intent without force-calculating animation target values, as is required now with CSS Animations.</p>
<p>A page can create and launch animations, but it can also get a reference to that animation and change it on-the-fly afterward. You can play it, pause it, change the play position, the play state, hook into the animation lifecycle with a <code>Promise</code>-based API, and much more. A page can even get all of the animations associated with an element or the entire document and manipulate them wholesale. Safari&rsquo;s new inspector uses this API to offer much richer display and control of all running animations. Understandably, Safari has reimplemented CSS Animations and CSS Transitions on top of a whole new animation engine that the Web Animations API also controls.</p>
<p>Safari puts a very strong implementation forward, with only two features missing:</p>
<ul>
<li>SVG Animations are not running on the new engine yet and cannot be manipulated with the API</li>
<li><a href="https://drafts.csswg.org/web-animations-1/#effect-composition">Effect composition</a> (<cite><a href="http://drafts.csswg.org/">W3C</a></cite>) is not yet supported</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3941</guid>
    <title><![CDATA[PostgreSql Drawbacks]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3941</link>
    <pubDate>Mon, 13 Apr 2020 11:18:02 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Apr 2020 11:18:02 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Despite the title, from what I can gather from <a href="https://medium.com/@rbranson/10-things-i-hate-about-postgresql-20dbab8c2791">10 Things I Hate About PostgreSQL</a> by <cite>Rick Branson</cite> (<cite><a href="http://medium.com/">Medium</a></cite>), the author is a big fan of PostgreSql. However, he has such vast experience with it that he can still list 10 things that don&rsquo;t work as well as they could.</p>
<p>They seem to boil down to:</p>
<ul>
<li>Default replication is still serialized and therefore not as reliable as the alternative async protocol that is much harder to configure and pretty much what every other major database offers.</li>
<li>Obsolete-data-handling requires regular and fine-tuned (for performance-critical) <em>vacuuming</em> instead of just handling it in a cleaner manner like MySQL, Oracle or SQL Server (rollback log or temp tables)</li>
<li>Indexes use more space than they should because they <em>copy</em> the indexed fields rather than referring directly to the data in the table. That is, unlike most other DBs, the index data is physically separate from the table data and therefore can nearly double the required space for a table with few columns.</li>
<li><div class=" "><p>The plan-builder doesn&rsquo;t support planning hints, which means you can&rsquo;t patch a query in production to buy time: you have to either meta-patch it (i.e. figure out some way of sending a &ldquo;hint&rdquo; to the planner through other means) or fix it for real, which can take a lot more time while your production servers are blowing up. From the article,</p>
<blockquote class="quote quote-block "><div>&ldquo;I <em>do</em> understand their reasoning, which largely is about preventing users from attacking problems using query hints that should be fixed by writing proper queries. However, <strong>this philosophy seems brutally paternalistic when you’re watching a production database spiral into a full meltdown</strong>	 under a sudden and unexpected query plan shift. (Emphasis in original.)&rdquo;</div></blockquote></div></li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3921</guid>
    <title><![CDATA[Getting started with D3.js]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3921</link>
    <pubDate>Sat, 21 Mar 2020 18:37:55 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Mar 2020 18:37:55 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Apr 2020 15:50:21 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3921/d3example.png"><img src="https://www.earthli.com/data/news/attachments/entry/3921/d3example_tn.png" alt=" " class=" align-right"></a>The programmable notebook <a href="https://observablehq.com/@mitvis/introduction-to-d3">Introduction to D3</a> by <cite>Arvind Satyanarayan</cite> (<cite><a href="http://observablehq.com/">MIT Visualization Group</a></cite>) is part of a <a href="http://vis.csail.mit.edu/classes/6.894/">full course</a> at MIT about <em>Interactive Data Visualization</em>.</p>
<p>The linked notebook uses <a href="https://d3js.org">D3.js</a>, but previous classes in the course have dealt with <a href="https://vega.github.io/vega/">Vega</a>, which is,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] a visualization grammar, a declarative language for creating, saving, and sharing interactive visualization designs. With Vega, you can describe the visual appearance and interactive behavior of a visualization in a JSON format, and generate web-based views using Canvas or SVG.&rdquo;</div></blockquote><p>Vega is a higher-level abstraction than D3 and is, therefore, both more powerful and more limited than it.</p>
<p>If what you want to build fits the higher-level building blocks of Vega (see <a href="https://vega.github.io/vega/examples/">examples</a>), then you&rsquo;ll be done more quickly with that; if it doesn&rsquo;t, then D3.js offers more flexibility as it functions at finer granularity.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;[…] grammars [like Vega] break visualization design down into a process of specifying mappings (or visual encodings) between data fields and the properties of graphical objects called marks. They&rsquo;re useful for concisely and rapidly creating recognizable visualizations, while giving us more design flexibility (or expressivity) than chart typologies like Microsoft Excel.</p>
<p>&ldquo;However, describing visualization design in these high-level terms limits the types of visualizations we can create. For example, we can only use the available marks, and can only bind data to supported encoding channels.&rdquo;</p>
</div></blockquote><p>With D3.js, you have to do a bit more legwork yourself, but it offers more graphical flexibility and possibilities. Instead of customizing the settings for predefined renderers (or &ldquo;marks&rdquo;), you define the renderers yourself: the notebook includes examples in HTML and SVG. To keep things simple, the SVG examples replicate the HTML examples, but they <em>could</em> render much more that is not so easy to realize in HTML.</p>
<p>Although D3.js has a reputation as a &ldquo;charting library&rdquo;, that moniker is actually more appropriate for Vega. D3.js is a generalized data-to-graphics mapping library. As you can see from the <a href="https://observablehq.com/@d3/gallery">examples</a>, it <em>is</em> very useful for charts, but allows a lot more customizability than <em>Vega</em>. Anyone building charts for their site should consider very carefully whether the additional power and complexity are warranted vs. a solution with something like Vega.</p>
<p>That said, it was a lot of fun getting to know D3 with this notebook. The notebook is extremely well-written and organized and it&rsquo;s absolutely fantastic that it&rsquo;s available online, for free. I was able to understand and execute all of the exercises and feel like I have a good enough grasp of D3 now to be able to build something with it. Perhaps more importantly, I feel that I can now:</p>
<ol>
<li>Determine whether D3 or Vega are appropriate for a given project</li>
<li>Estimate the amount of time required to build something with either of them</li></ol>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3920</guid>
    <title><![CDATA[Rust: from zero to pretty-well-versed in 30 minutes]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3920</link>
    <pubDate>Sat, 21 Mar 2020 15:59:18 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Mar 2020 15:59:18 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I found the article <a href="https://fasterthanli.me/blog/2020/a-half-hour-to-learn-rust/">A half-hour to learn Rust</a> by <cite>Amos</cite> to be extremely helpful in learning the syntax and mechanics of Rust.</p>
<p>It starts out with the absolute basics:</p>
<blockquote class="quote quote-block "><div>&ldquo;<code>let</code> introduces a variable binding […]&rdquo;</div></blockquote><p>then takes you through</p>
<ul>
<li>Modules</li>
<li>Blocks</li>
<li>Conditionals</li>
<li>Matches</li>
<li><code>Options</code></li>
<li><code>mut</code>ables</li>
<li>Copy/clone semantics</li>
<li>Traits</li>
<li>Generic parameters</li>
<li>Constraints</li>
<li>Macros</li>
<li>Enums</li>
<li>Lifetimes and borrowing</li>
<li>Generic lifetimes</li>
<li>Statics vs. owned vs. referenced</li>
<li>Slices and range literals (<code>Index</code> and <code>IndexMut</code>)</li>
<li><code>Results</code></li>
<li>Errors, <code>panic</code> and <code>unwrap</code>, <code>expect()</code> and <code>?</code></li>
<li>Closures (<code>Fn</code>, <code>FnMut</code>, and <code>FnOnce</code>)</li>
<li><code>move</code></li>
<li><code>for … in</code></li></ul><p>and ends up with a function builder that tests strings:</p>
<pre class=" "><code>fn make_tester&lt;'a&gt;(answer: &amp;'a str) -&gt; impl Fn(&amp;str) -&gt; bool + 'a {
    move |challenge| {
        challenge == answer
    }
}

fn main() {
    let test = make_tester("hunter2");
    println!("{}", test("*******"));
    println!("{}", test("hunter2"));
}

// output:
// false
// true</code></pre>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3914</guid>
    <title><![CDATA[Quino 2020 Roadmap]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3914</link>
    <pubDate>Sat, 07 Mar 2020 18:43:04 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">7. Mar 2020 18:43:04 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Mar 2020 10:58:06 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Now that <a href="https://www.encodo.com/latest/developer-blogs/v800-aspnet-core-web-client-2-culturelanguage-improvements/">Quino 8.x is out the door</a>, we can look forward to Quino 9.</p>
<p>Quino 8 is a very solid and stable release that has already been test-integrated into many of our current <a href="https://www.encodo.com/quino/quino-roadmap/">products running on Quino</a>. We don&rsquo;t anticipate any more low-level API changes, though there will be follow-up bug-fix releases.</p>
<p>There are a few larger-scale changes improvements and enhancement, outlined below (and noted in the <a href="https://www.encodo.com/quino/quino-roadmap/">roadmap</a>).</p>
<h2>Ready for Change</h2><p>With this release, we&rsquo;ve got more coverage than ever. Excluding only generated code (e.g. <code>*Metadata.cs</code> and <code>*.Class.css</code> in the model assemblies), we ended up with a respectable 81% test coverage. Quino has almost 10,000 tests comprising about 51k LOC and covering 82k LOC [1], Many, many of these are integration and scenario tests. With this level of test coverage, we feel comfortable with refactoring to improve usability and performance.</p>
<p><span style="width: 565px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3914/quino_8_81_percent_coverage.png" alt=" " style="width: 565px"></span><span class="auto-content-caption">81% Coverage for Quino 8</span></span></p>
<h2>Documentation</h2><p>One of the primary near-term goals is to improve Quino&rsquo;s documentation story. The aim is to take a new developer through the common tasks of working with a solution based on Quino.</p>
<ul>
<li><a href="https://docs.encodo.ch/quino/master/docs/setup/readme.html">Setting up a solution</a>: getting packages and creating standard projects for testing, web, and so on</li>
<li><a href="https://docs.encodo.ch/quino/master/docs/metadata/readme.html">Creating a model</a></li>
<li><a href="https://docs.encodo.ch/quino/master/docs/expressions/readme.html">Using expressions</a></li>
<li><a href="https://docs.encodo.ch/quino/master/docs/tools/readme.html">Using quino&rsquo;s command-line tools</a></li>
<li>Generating <a href="https://docs.encodo.ch/quino/master/docs/data/genericObjects.html">ORM</a> and <a href="https://docs.encodo.ch/quino/master/docs/data/generatedMetadata.html">metadata</a> code</li>
<li>Working with <a href="https://docs.encodo.ch/quino/master/docs/expressions/delegateExpressions.html">business logic</a></li>
<li>Integrating the <a href="https://docs.encodo.ch/quino/master/docs/web.html">web</a></li>
<li>Improving the <a href="https://docs.encodo.ch/quino/master/docs/debugging.html">debugging experience</a></li>
<li><a href="https://docs.encodo.ch/quino/master/docs/testing.html">Writing tests</a> efficiently, quickly and easily using powerful base classes and tools for snapshot-based tests</li></ul><p>Some of this documentation is currently still out-of-date or will change as we improve the corresponding components. For example: </p>
<ul>
<li>Anything that refers to <code>Nant</code> is no longer relevant</li>
<li>Some of the <code>quino</code> tool documentation will no longer be relevant after 8.1 (see tools-related issue in the <a href="https://secure.encodo.ch/jira/issues/?jql=project%20%3D%20QNO%20AND%20fixVersion%20%3D%208.1-CLEANUP">issue tracker</a>)</li>
<li>The <a href="https://docs.encodo.ch/quino/master/docs/data/readme.html">data documentation</a> is still very much a work-in-progress</li></ul><h3>Search and Index</h3><p>The latest <a href="https://docs.encodo.ch/quino/master/docs/readme.html">table of contents</a> is much more comprehensive than before and we&rsquo;re still improving it.</p>
<p>We don&rsquo;t have an integrated search for the conceptual documentation yet, but you can use Google&rsquo;s site-specific search. For example, search for <em>configuration</em> with the following search text &ldquo;configuration site:docs.encodo.ch&rdquo;. The top results are:</p>
<ul>
<li><a href="https://docs.encodo.ch/quino/release/7/docs/core/configuration.html">Configuration</a></li>
<li><a href="https://docs.encodo.ch/quino/master/docs/configuration_system.html">Configuration System</a></li>
<li><a href="https://docs.encodo.ch/quino/master/docs/architecture/application.html">Quino Application Configuration</a></li></ul><p>Which is pretty decent, overall.</p>
<h2>Database-first</h2><p>Several of our upcoming products using Quino (two are so new that they&rsquo;re <a href="https://www.encodo.com/quino/quino-products.html">not yet listed</a>) are replacing legacy products that are highly dependent on a central database that defines the application domain. That is, the model is in the database or in a model description that is not <em>initiallly</em> a Quino model.</p>
<p>Instead of defining the model in C# code manually and then building the database from that (the standard approach with Quino), these products define the model with varying levels of automation and import and then use the existing database.</p>
<p>The following list shows the various ways that we&rsquo;re building Quino models, in addition to the standard approach of <a href="https://docs.encodo.ch/quino/master/docs/metadata/builders.html">defining them in C#</a>: </p>
<ul>
<li><em>Import</em> a model from Microsoft Dynamics CRM</li>
<li><em>Import</em> a model from a legacy DSL like the <em>Atlas</em> modeling language</li>
<li><em>Import</em> a model from the database schema itself, using Quino&rsquo;s <a href="https://www.encodo.com/latest/developer-blogs/schema-migration-in-quino-113/">schema-import/migration support</a></li>
<li><em>Map</em> a model in C# to an existing database schema, using Quino&rsquo;s new <a href="https://docs.encodo.ch/quino/master/docs/metadata/mappingToSchema.html">support for mapping schemas</a></li></ul><p>This allows customers with existing databases to relatively quickly and easily produce a Quino model that gets them access to <a href="https://www.encodo.com/quino">the plethora of features available to Quino applications</a> (e.g. ORM, schema-check and -migration, generated GUI for desktop or web, and so on).</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3914_1_body" class="footnote-number">[1]</span> <p>The LOC analyzer included in Visual Studio had slightly different numbers:</p>
<ul>
<li>297k LOC (source)</li>
<li>198k LOC (docs)</li>
<li>202k LOC (source/libs)</li>
<li>99k LOC (executable)</li>
<li>56k LOC (executable/libs)</li>
<li>43k LOC (executable/tests)</li></ul><p>Quino has almost one line of testing code per line of library code (43k/56k ~  77%). Quino has almost 4 lines of non-executable code per line of executable library code (202k/56k ~ 360%).</p>
<p>The disparity between the two results (JetBrains DotCover and Microsoft Visual Studio) just goes to show what a fraught metric LOC really is. According to these two measurements, Quino has between 56k and 83k LOC of executable library code.</p>
</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3908</guid>
    <title><![CDATA[Quino v8.0.0: ASP.NET Core, Web Client 2, Culture/Language improvements]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3908</link>
    <pubDate>Sat, 22 Feb 2020 17:43:38 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">22. Feb 2020 17:43:38 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The summary below describes major new features, items of note and breaking changes.</p>
<ul>
<li><div>Resources<ul>
<li><a href="https://encodo.pkgs.visualstudio.com/_packaging/Quino/nuget/v3/index.json">Artifacts</a> (Note: the URL is a NuGet Source; you can&rsquo;t browse here directly)</li>
<li><a href="https://docs.encodo.ch/quino/release/8/">Documentation</a></li></ul></div><div>Issues/Changelog<ul>
<li><a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=25518">Quino-Standard 8.0.0.2505</a></li>
<li><a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=12730&amp;version=25517">Quino-WebAPI 8.0.0.2511</a></li>
<li><a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=12731&amp;version=25519">Quino-Windows 8.0.0.69</a></li></ul></div></ul><p><small class="notes">The links above require a login.</small></p>
<h2>Highlights</h2><ul>
<li>Quino-Web now targets ASP.NET Core (<a href="https://secure.encodo.ch/jira/browse/QNOWEB-149">QNOWEB-149</a>, <a href="https://secure.encodo.ch/jira/browse/QNOWEB-84">QNOWEB-84</a>, <a href="https://secure.encodo.ch/jira/browse/QNOWEB-55">QNOWEB-55</a>)</li>
<li>Quino-Web has Serilog enabled by default (<a href="https://secure.encodo.ch/jira/browse/QNOWEB-147">QNOWEB-147</a>, <a href="https://secure.encodo.ch/jira/browse/QNOWEB-146">QNOWEB-146</a>, <a href="https://secure.encodo.ch/jira/browse/QNOWEB-145">QNOWEB-145</a>, <a href="https://secure.encodo.ch/jira/browse/QNOWEB-139">QNOWEB-139</a>)</li>
<li>Enabled SourceLink for all packages (<a href="https://secure.encodo.ch/jira/browse/QNOWIN-262">QNOWIN-262</a>)</li>
<li>Improved testing and debugging support. (<a href="https://secure.encodo.ch/jira/browse/QNO-6289">QNO-6289</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6282">QNO-6282</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6278">QNO-6278</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6277">QNO-6277</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6275">QNO-6275</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6255">QNO-6255</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6213">QNO-6213</a>)</li>
<li>Improved culture and language-handling (<a href="https://secure.encodo.ch/jira/browse/QNO-6302">QNO-6302</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6303">QNO-6303</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6253">QNO-6253</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6230">QNO-6230</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6228">QNO-6228</a>)</li>
<li>Extended expression functions with <code>CreateGuid()</code>, <code>CreateDate()</code>, and <code>CreateTime()</code>. (<a href="https://secure.encodo.ch/jira/browse/QNO-6304">QNO-6304</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-6305">QNO-6305</a>)</li></ul><h2>Breaking Changes</h2><p>Before upgrading, products should make sure that they do not depend on any obsolete members in the current version (7.x).</p>
<h3>ASP.NET Core</h3><p>Quino-Web 8.0 is a rewrite and is therefore mostly incompatible with 7.x.</p>
<ul>
<li>The controller returns data in a completely different format</li>
<li>The Quino Client has been completely rewritten to accommodate it</li>
<li>The startup and pipeline have been completely rewritten to integrate with ASP.NET Core</li>
<li>Testing support has been considerably extended to accommodate end-to-end integration testing and in-process hosts</li></ul><p>See the <code>Quino-Web/Sandbox.Web</code> project for a working example. This integrates the standard <code>SandboxApplication</code> into a web site using the standard <code>GenericController</code> and <code>MetadataController</code> to provide data and UI to the generic Quino Client.</p>
<h3>Namespace Changes</h3><p>Some internal types in Quino-Standard have been moved to more appropriate namespaces and assemblies, but the impact on products should be non-existent or very limited.</p>
<p>The following types were moved from <code>Encodo.Quino.Core</code> to <code>Encodo.Quino.Culture</code>:</p>
<ul>
<li><code>LanguageTextAttribute</code></li>
<li><code>IValueParser</code></li>
<li><code>CaptionAttribute</code></li>
<li><code>LanguageDescriptionAttribute</code></li></ul><p>The following types were moved from <code>Encodo.Quino.Core</code> to <code>Encodo.Quino.TextFormatting</code>:</p>
<p>* <code>IFileSizeFormatter</code></p>
<h3>Culture- and Language-Handling</h3><p>Quino&rsquo;s default culture-handling has been overhauled. Instead of tracking its own language, Quino now uses the standard .NET <code>CultureInfo.CurrentUICulture</code> for the default language and <code>CultureInfo.CurrentCulture</code> for default formatting (e.g. times, dates, and currencies). Many fields have been marked as obsolete and are no longer used by Quino.</p>
<h3>Default Languages</h3><p>The default languages in Quino have changed from &ldquo;en-US&rdquo; and &ldquo;de-CH&rdquo; to &ldquo;en and &ldquo;de&rdquo;, respectively.</p>
<p>The reasoning behind this is that, while a _requested language_ should be as specific as possible, a _supported language_ should be as general as possible. The standard culture mechanisms and behavior (e.g. .NET Resources) &ldquo;fall back&rdquo; to a parent language when a more-specific language cannot be found. If an application claims to only support &ldquo;en-US&rdquo;, then a request for &ldquo;en-GB&rdquo; fails. If the supported language is &ldquo;en&rdquo;, then any request to a language in the &ldquo;en&rdquo; family (e.g. &ldquo;en-US&rdquo;, &ldquo;en-GB&rdquo;, &ldquo;en-AU&rdquo;) will use &ldquo;en&rdquo;. </p>
<p>An application that supports &ldquo;en-US&rdquo; and &ldquo;de-CH&rdquo; has, therefore, a more limited palette of languages that it can support.</p>
<h3>Fallback-resolution</h3><p>Quino code runs in the context of a user, who has a list of preferred languages, in decreasing order of preference. This context can last the entire duration of an application (e.g. a standalone application like a console or desktop application) or last as long as a web request.</p>
<p>The application itself has a list of languages that it supports, as well as resources and metadata that defines text in these languages. The resources are standard .NET Resources with the standard fallback mechanism (i.e. a request for &ldquo;en-US&rdquo; can be satisfied by &ldquo;en&rdquo;). The metadata uses <code>DynamicString</code> objects, which encapsulate a map from language codes (e.g. &ldquo;en&rdquo; or &ldquo;de&rdquo;) to strings.</p>
<p>During application startup or at the beginning of a web request, the <code>ILanguageResolver</code> determines the language to use for a given set of requested languages. In ASP.NET Core, the requested languages come from the HTTP headers provided by the browser. In standalone applications, the <code>IRequestedLanguageCalculator</code> provides the requested languages. The <code>ILanguageInitializer</code> is responsible for coordinating this during application startup.</p>
<p>The rest of Quino uses the following singletons to work with languages.</p>
<ul>
<li><code>IDynamicStringFallbackCalculator</code>: Comes into play when a request is made for a language that is not directly supported. For example, if the application supports &ldquo;en&rdquo; and &ldquo;de&rdquo;, then a request for &ldquo;en-US&rdquo; will ask this singleton how to resolve the request.</li>
<li><code>IDynamicStringFactory</code>: Creates a dynamic string to describe a given object. The default implementation uses .NET Attributes.</li>
<li><code>ILanguageResolver</code>: Determines the culture to use from a list of available cultures and a list of requested/preferred cultures.</li>
<li><code>IRequestedLanguageCalculator</code>: Provides the sequence of languages from which to choose during initial resolution (web requests _do not_ use this).</li>
<li><code>ILanguageInitializer</code>: Integrates language-selection into the application startup.</li>
<li><code>ICaptionCalculator</code>: Extracts a single caption for a culture from a given object. Appications should use the <code>IDynamicStringFactory</code> in most cases, instead.</li></ul><p>An application can control fallback by registering custom <code>IDynamicStringFallbackCalculator</code> and <code>ILanguageResolver</code> implementations (though this is almost certainly not necessary).</p>
<h3>Opting in or out</h3><p>Any product that calls <code>AddEnglishAndGerman()</code> will automatically be upgraded as well. A product can avoid this change by calling <code>AddAmericanEnglishAndSwissGerman()</code> instead.</p>
<h4>Reports</h4><p>A product that uses the new languages will have to replace all fields in reports targeted at &ldquo;en-US&rdquo; and &ldquo;de-CH&rdquo; to target &ldquo;en&rdquo; and &ldquo;de&rdquo; instead.</p>
<h4>Database Fields</h4><p>A product that does use the new default languages will have to determine how to migrate database fields created for languages that are no longer explicitly supported. If the model includes value-lists (enums) or multi-language properties , the application will have to migrate the database schema to update multi-language fields (e.g. &ldquo;caption_en_us&rdquo; =&gt; &ldquo;caption_en&rdquo;).</p>
<h4>Manual MetaIds</h4><p>A product that sets <code>MetaIds</code> manually will migrate without modification (Quino will rename the property in the database).</p>
<h4>Automatic MetaIds</h4><p>A product that does _not_ set <code>MetaIds</code> (this has been the default in Quino since version 2) will have a MetaID mismatch because the name has changed.</p>
<p>By default, Quino will migrate by attempting to drop, then re-create multi-language properties. In the case of value-list captions, this is harmless (since the data stored in these tables are generated wholly from the metadata). For actual multi-language properties with user data in them, this is _a problem_.</p>
<p>The simple solution is to call <code>UseLegacyLanguageMappingFinalizerBuilder()</code> during application configuration to ensure a smooth migration (Quino will rename the property in the database).</p>
<h4>Regenerating Code</h4><p>A product that updates its languages should regenerate code to update any generated language-specific properties. Properties that had previously been generated as, e.g. <code>Caption_en_us</code> will now be <code>Caption_en</code>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3907</guid>
    <title><![CDATA[When [NotNull] is null]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3907</link>
    <pubDate>Tue, 18 Feb 2020 09:08:08 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. Feb 2020 09:08:08 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I prefer to be very explicit about nullability of references, wherever possible. Happily, most modern languages support this feature non-nullable references natively (e.g. TypeScript, Swift, Rust, Kotlin).</p>
<p>As of version 8, C# also supports non-nullable references, but we haven&rsquo;t migrated to using that enforcement yet. Instead, we&rsquo;ve used the JetBrains nullability annotations for years. [1]</p>
<p>Recently, I ended up with code that returned a <code>null</code> even though R# was convinced that the value could never be <code>null</code>.</p>
<p>The following code <em>looks like</em> it could never produce a null value, but somehow it does.</p>
<pre class=" "><code>[NotNull] <strong class="highlight">// The R# checker will verify that the method does not return null</strong>
public DynamicString GetCaption()
{
  var result = GetDynamic() ?? GetString() ?? new DynamicString();
}

[CanBeNull]
private DynamicString GetDynamic() { … }

[CanBeNull]
private string GetString() { … }</code></pre><p>So, here we have a method <code>GetCaption()</code> whose result can never be <code>null</code>. It calls two methods that <em>may</em> return <code>null</code>, but then ensures that its own result can <em>never</em> be null by creating a new object if neither of those methods produces a string. The nullability checker in ReSharper is understandably happy with this.</p>
<p>At runtime, though, a call to <code>GetCaption()</code> was returning <code>null</code>. How can this be?</p>
<h2>The Culprit: An Implicit Operator</h2><p>There is a bit of code missing that explains everything. A <code>DynamicString</code> declares <em>implicit operators</em> that allow the compiler to convert objects of that type to and from a <code>string</code>.</p>
<pre class=" "><code>public class DynamicString
{
  // …Other stuff

  [CanBeNull]
  public static implicit operator string([CanBeNull] DynamicString dynamicString) =&gt; dynamicString?.Value;
}</code></pre><p>A <code>DynamicString</code> contains zero or more key/value pairs mapping a language code (e.g. &ldquo;en&rdquo;) to a value. If the object has no translations, then it is equivalent to <code>null</code> when converted to a <code>string</code>. Therefore, a <code>null</code> or empty <code>DynamicString</code> converts to <code>null</code>.</p>
<p>If we look at the original call, the compiler does the following:</p>
<ol>
<li>The call to <code>GetDynamic()</code> sets the type of the expression to <code>DynamicString</code>.</li>
<li>The compiler can only apply the <code>??</code> operator if <em>both sides are of the same type</em>; otherwise, the code is in error.</li>
<li>Since <code>DynamicString</code> can be <em>coerced</em> to <code>string</code>, the compiler decides on <code>string</code> for the type of the first coalesced expression.</li>
<li>The next coalesce operator (<code>??</code>) triggers the same logic, coercing the right half (<code>DynamicString</code>) to the type it has in common with the left half (<code>string</code>, from before).</li>
<li>Since the type of the expression must be <code>string</code> in the end, even if we fall back to the <code>new DynamicString()</code>, it is coerced to a <code>string</code> and thus, <code>null</code>.</li></ol><p>Essentially, what the compiler builds is:</p>
<pre class=" "><code>var result = 
  (string)GetDynamic() ?? 
  GetString() ?? 
  (string)new DynamicString();</code></pre><p>The R# nullability checker sees only that the final argument in the expression is a <code>new</code> expression and determines that the <code>[NotNull]</code> constraint has been satisfied. The compiler, on the other hand, executes the final cast to <code>string</code>, converting the empty <code>DynamicString</code> to <code>null</code>.</p>
<h2>The Fix: Avoid Implicit <code>DynamicString</code>-to-<code>string</code> Conversion</h2><p>To fix this issue, I avoided the <code>??</code> coalescing operator. Instead, I rewrote the code to return <code>DynamicString</code> wherever possible and to implicitly convert from <code>string</code> to <code>DynamicString</code>, where necessary (instead of in the other direction).</p>
<pre class=" "><code>public DynamicString GetCaption()
{
  var d = GetDynamic();
  if (d != null)
  {
    return d;
  }

  var s = GetString();
  if (s != null)
  {
    return s; <strong class="highlight">// Implicit conversion to DynamicString</strong>
  }

  return GetDefault();
}</code></pre><h2>Conclusion</h2><p>The takeaway? Use features like implicit operators sparingly and only where absolutely necessary. A good rule of thumb is to define such operators only for <code>structs</code> which are values and can never be <code>null</code>.</p>
<p>I think the convenience of being able to use a <code>DynamicString</code> as a <code>string</code> outweighs the drawbacks in this case, but YMMV.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3907_1_body" class="footnote-number">[1]</span> Java also has <code>@NonNull</code> and <code>@Nullable</code> annotations, although it&rsquo;s <a href="https://stackoverflow.com/questions/4963300/which-notnull-java-annotation-should-i-use">unclear which standard you&rsquo;re supposed to use.</a> (<cite><a href="http://stackoverflow.com/">StackOverflow</a></cite>)</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3898</guid>
    <title><![CDATA[Configuring .NET Framework Assembly-binding Redirects]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3898</link>
    <pubDate>Thu, 30 Jan 2020 22:30:05 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. Jan 2020 22:30:05 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. Jan 2020 22:30:51 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>After years of getting incrementally better at fixing binding redirects, I&rsquo;ve finally taken the time to document my methodology for figuring out what to put into <code>app.config</code> or <code>web.config</code> files.</p>
<p>The method described below works: when you get an exception because the runtime gets an unexpected version of an assembly—e.g. <span class="quote-inline">&ldquo;The located assembly’s manifest definition does not match the assembly reference&rdquo;</span>—this technique lets you formulate a binding-redirect that will fix it. You&rsquo;ll then move on to the <em>next</em> binding issue, until you&rsquo;ve taken care of them all and your code runs again.</p>
<h2>Automatic Binding Redirects</h2><p>If you have an executable, you can usually get Visual Studio (or MSBuild) to regenerate your binding redirects for you. Just delete them all out of the <code>app.config</code> or <code>web.config</code> and <em>Rebuild All</em>. You should see a warning appear that you can double-click to generate binding redirects.</p>
<p>If, however, this doesn&rsquo;t work, then you&rsquo;re on your own for discovering which version you actually have in your application. You need to know the version or you can&rsquo;t write the redirect. You can&rsquo;t just take any number: it has to match exactly.</p>
<h2>Testing Assemblies</h2><p>Where the automatic generation of binding redirects <em>doesn&rsquo;t</em> work is for unit-test assemblies.</p>
<p>My most recent experience was when I upgraded <code>Quino-Windows</code> to use the latest <code>Quino-Standard</code>. The <code>Quino-Windows</code> test assemblies were suddenly no longer able to load the PostgreSql driver. The <code>Quino.Data.PostgreSql</code> assembly targets .NET Standard 2.0. The testing assemblies in <code>Quino-Windows</code> target .NET Framework.</p>
<p>After the latest upgrade, many tests failed with the following error message:</p>
<div class="error ">Could not load file or assembly &lsquo;System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&rsquo; or one of its dependencies. The located assembly&rsquo;s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)</div><p>This is the version that it was <em>looking for</em>. It will either be the version required by the loading assembly (<code>npgsql</code> in this case) or the version already specified in the <code>app.config</code> (that is almost certainly out of date).</p>
<h2>Which File Was Loaded?</h2><p>To find out the file version that your application <em>actually uses</em>, you have to figure out which assembly .NET loaded. A good first place to look is in the output folder for your executable assembly (the testing assembly in this case).</p>
<p>If, for whatever reason, you can&rsquo;t find the assembly in the output folder—or it&rsquo;s not clear which file is being loaded—you can tease the information out of the exception itself.</p>
<ol>
<li>From the exception settings, make sure that the debugger will stop on a <code>System.IO.FileLoadException</code></li>
<li>Debug your test</li>
<li>The debugger should break on the exception</li></ol><p><span style="width: 515px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3898/assemblybindingredirect_exception.png" alt=" " style="width: 515px"></span><span class="auto-content-caption">Assembly-binding exception</span></span></p>
<p>Click &ldquo;View Details&rdquo; to show the <em>QuickWatch</em> window for the exception. There&rsquo;s a property called <code>FusionLog</code> that contains more information.</p>
<p><span style="width: 529px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3898/showing_details_in_the_fusionlog.png"><img src="https://www.earthli.com/data/news/attachments/entry/3898/showing_details_in_the_fusionlog.png" alt=" " style="width: 529px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3898/showing_details_in_the_fusionlog.png">Fusion log details (with loaded assembly path)</a></span></span></p>
<p>The log is quite detailed and shows you the configuration file that was used to calculate the redirect as well as the file that it loaded.</p>
<p><span style="width: 529px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3898/assemblybindingredirect_fusionlog.png"><img src="https://www.earthli.com/data/news/attachments/entry/3898/assemblybindingredirect_fusionlog.png" alt=" " style="width: 529px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3898/assemblybindingredirect_fusionlog.png">Assembly-binding &#039;fusion log&#039;</a></span></span></p>
<h2>Which Version Is It?</h2><p>With the path to the assembly in hand, it&rsquo;s time to get the assembly version.</p>
<p>Showing the file properties will most likely not show you the assembly version. For third-party assemblies (e.g. Quino), the file version is <em>often</em> the same as the assembly version (for pre-release versions, it&rsquo;s not). However, Microsoft <em>loves</em> to use a different file version than the assembly version. That means that you have to open the assembly in a tool that can dig that version out of the assembly manifest.</p>
<p>The easiest way to get the version number is to use the free tool <em>JetBrains DotPeek</em> or use the <em>AssemblyExplorer</em> in <em>JetBrains ReSharper</em> or <em>JetBrains Rider</em>.</p>
<p>You can see the three assemblies that I had to track down in the following screenshot.</p>
<p><span style="width: 565px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3898/actualversions.png" alt=" " style="width: 565px"></span><span class="auto-content-caption">Actual versions of various System assemblies</span></span></p>
<h2>Writing Binding Redirects</h2><p>Armed with the actual versions and the public key-tokens, I was ready to create the <code>app.config</code> file for my testing assembly.</p>
<p><span style="width: 706px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3898/assemblybindingredirect_mappings.png"><img src="https://www.earthli.com/data/news/attachments/entry/3898/assemblybindingredirect_mappings.png" alt=" " style="width: 706px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3898/assemblybindingredirect_mappings.png">Assembly-binding mappings</a></span></span></p>
<p>And here it is in text/code form:</p>
<pre class=" "><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;configuration&gt;
  &lt;runtime&gt;
    &lt;assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"&gt;
      &lt;dependentAssembly&gt;
        &lt;assemblyIdentity 
          name="System.Numerics.Vectors"
          publicKeyToken="B03F5F7F11D50A3A"
          culture="neutral"
        /&gt;
        &lt;bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0"/&gt;
      &lt;/dependentAssembly&gt;
      &lt;dependentAssembly&gt;
        &lt;assemblyIdentity
          name="System.Runtime.CompilerServices.Unsafe"
          publicKeyToken="B03F5F7F11D50A3A"
          culture="neutral"
        /&gt;
        &lt;bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0"/&gt;
      &lt;/dependentAssembly&gt;
      &lt;dependentAssembly&gt;
        &lt;assemblyIdentity
          name="System.Threading.Tasks.Extensions"
          publicKeyToken="CC7B13FFCD2DDD51"
          culture="neutral
        "/&gt;
        &lt;bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1"/&gt;
      &lt;/dependentAssembly&gt;
    &lt;/assemblyBinding&gt;
  &lt;/runtime&gt;
&lt;/configuration&gt;</code></pre>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3864</guid>
    <title><![CDATA[Rebase Considered Essential]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3864</link>
    <pubDate>Thu, 02 Jan 2020 10:41:06 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">2. Jan 2020 10:41:06 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Fossil is a distributed Source Control Manager that claims to offer the same power without the complexity of Git. The article <a href="https://www.fossil-scm.org/fossil/doc/trunk/www/rebaseharm.md">Fossil: Rebase Considered Harmful</a> by <cite>D. Richard Hipp</cite> (<cite><a href="http://www.fossil-scm.org/">Fossil SCM</a></cite>) is part of the documentation for the tool.</p>
<p>One of the main selling points of Fossil is that <em>it does not support rebase</em>. In the article, the author lays out the many ways in which rebasing causes no end of woes for developers using Git.</p>
<p>I&rsquo;d heard of Fossil before and I&rsquo;d even skimmed this document before. This time around, though, I read it through to learn the author&rsquo;s reasoning. My short take is: I do not want to use an SCM that does not allow rebase. [1] I think a project benefits greatly in clarity if a developer is able to alter the local history before cementing commits into an unalterable history (i.e. pushing to the server).</p>
<h2>Terminology and Concepts</h2><p>The following definitions are not complete, but are sufficient for the ensuing discussion.</p>
<ul>
<li>A <strong>repository</strong> describes the history of a set of data</li>
<li>A <strong>commit</strong> includes instructions for how to change the state of the <em>repository</em></li>
<li>A <strong>branch</strong> points to a commit, but generally refers to a set of <em>commits</em>; a <em>repository</em> may contains multiple, independent <em>branches</em></li>
<li>A <strong>merge operation</strong> integrates two <em>branches</em> with a <em>merge commit</em> that describes the delta; it <em>retains</em> all commits from both <em>branches</em> </li>
<li>A <strong>rebase operation</strong> integrates two <em>branches</em> by re-applying each <em>commit</em> since the <em>branches</em> diverged from one <em>branch</em> to the other, possibly changing the original <em>commits</em>; it <em>replaces</em> the <em>commits</em> from one of the <em>branches</em> with new <em>commits</em></li></ul><p>A rebase is considered a <em>destructive</em> operation because it discards part of the history of the repository by <em>rewriting</em> commits.</p>
<p>If I think about it, though, many of the operations I&rsquo;m accustomed to making are destructive:</p>
<ul>
<li>Editing the commit message</li>
<li>Amending a commit with more changes</li>
<li>Squashing commits</li>
<li>Re-ordering commits</li></ul><p>All of these operations are considered destructive because they modify the &ldquo;true&rdquo; history of the repository. But what do we mean by &ldquo;true&rdquo; history? Where does the story start?</p>
<p>The changes outlined above are not for sharing. It&rsquo;s not interesting to the final reader that I had to backspace through and re-spell the word &ldquo;outlined&rdquo; in the previous sentence. It <em>might</em> be interesting to see different <em>drafts</em>, though, to see how I arrived at the final version. But those changes are at a different level of granularity.</p>
<p>Who decides where one level of granularity stops and the next begins? I think it&rsquo;s the author of the commits. My workflow over the last ten years is based heavily on being able to massage commits so that I can prepare what I share to the server repository, where it can no longer be changed. I agree that there should be an unalterable history, but disagree with the author on where that history begins.</p>
<h2>Hairball Commits</h2><p>I agree with the author that developers should not work in silos, massaging their code until it is <em>perfect</em>, pushing only once there are no more errors and no-one could possibly take issue with anything in the feature. At this point, the author purports that many developers squash <em>all</em> of their local commits to a single so-called hairball commit that makes it look like the code sprung from the forehead of the developer as Eve sprung from Adam&rsquo;s rib: whole and without blemish.</p>
<p>Hairball commits are acknowledged as bad, so attacking them as the prime reason to eliminate the tool that allows them seems to be more of a straw man. </p>
<p>Preventing developers from making any changes to local commits is not the way to solve the problem, though. While Fossil does not allow discarding any single commit from the history, the author acknowledges that Fossil allows developers to apply addenda that the common Fossil tools will show while hiding the original commits. [2]</p>
<p>I see the author&rsquo;s point—that (potentially) important parts of a history are retained whether the developer wants them or not. That is, it is not up to the developer to decide, but up to the archeologist examining the commits later. This is an interesting idea, but the argument is ultimately not convincing.</p>
<p>Let&rsquo;s suppose a developer uses an SCM without rebase. Either there will be many commits in the history that—unlike the author claims—do not provide any clarity because they are <em>garbage</em> commits (e.g. WIP and other sorts of investigatory commits that were quickly reverted or undone). Or, the developer will be terrified of making a commit before it&rsquo;s ready and runs the risk of losing work or working less efficiently.</p>
<p>Developers will not magically become ego-less and kowtow to the machine. Instead, they will pick up bad habits that are <em>worse</em> than local rebasing. They will keep work uncommitted for too long or will fail to split up commits properly because they are afraid that they can&rsquo;t fix them up later. In either case, it&rsquo;s chaos in the commit history and the project efficiency and reliability suffers.</p>
<p>But the author is arguing with a straw man that doesn&rsquo;t really exist outside of shitty developer teams with undisciplined developers. One can argue that these are the kind of developers that many projects have, but that can only be addressed with <em>process</em>. Weakening the tools so that disciplined developers are less efficient is a bad idea.</p>
<p>You don&rsquo;t like hairball commits? Tell developers to stop making them. Enforce the policy with reviews. The Git documentation already encourages developers to make focused commits. Rebase allows a developer to split up commits during or after a code review. Rebase can actually be used to <em>combat</em> hairball commits.</p>
<p>I have personally used it to split up commits that inadvertently mixed a bug fix or two into a large pile of refactoring changes. I&rsquo;ve also often advised people to <em>redesign</em> their commits so that they tell a better story.</p>
<h2>Citations and Responses</h2><p>I&rsquo;ve interspersed citations from the <a href="https://www.fossil-scm.org/fossil/doc/trunk/www/rebaseharm.md">document</a> linked above  and included responses and thoughts.</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] [some tools] accomplish things that cannot be done otherwise, or at least cannot be done easily. Rebase does not fall into that category, <strong>because it provides no new capabilities.</strong> (Emphasis added.)&rdquo;</div></blockquote><p>As discussed above, I think that this is fundamentally wrong. My workflow is considerably different than it was before I used Git or had access to rebase. I would now be much less efficient if I didn&rsquo;t have rebase. It would make me constantly focus on cleaning up commits before I really care to. You could make the argument that cleaning up afterward takes more time, but I haven&rsquo;t experienced that to be the case. Instead, I want to be able to set the priorities rather than worry about committing something that I cannot undo.</p>
<h2>Telling a good story</h2><p>And it&rsquo;s not about ego or &ldquo;looking stupid&rdquo; to future readers of the history; instead, it&rsquo;s about having control of the story you tell to those same readers. If you don&rsquo;t have rebase, then you tell just as poor a story as if you use rebase badly. It&rsquo;s perhaps closer to the &ldquo;true&rdquo; story, but it&rsquo;s not the &ldquo;best&rdquo; story. <em>Without rebase, you&rsquo;re forcing future archeologists of your code to read all drafts as well as the final version simultaneously.</em></p>
<p>At Encodo, we don&rsquo;t focus on ego, we focus on efficiency. We do not obliterate commits that make sense just to squash a whole feature. We retain commits in order to tell a good story about how a feature was built. We do not emphasize being able to build each commit: often we&rsquo;ll add a failing test in one commit, then fix the bug in another commit, <em>because that tells a better story</em>.</p>
<p>We need rebase in order to massage local commits so that they tell this good story rather than uploading dozens of commits that no-one should ever have to look at (typos, code comments, formatting, etc.). Often, we&rsquo;ll squash in little fixes and changes that come up during a review. Is the Fossil author suggesting that there is some benefit to seeing these in a separate commit? It would make understanding the commits at a later time that much harder.</p>
<p>I think most of the author&rsquo;s concerns are addressed by using review and process to enforce better commits. Fossil can&rsquo;t make this happen because the developers have to create good commits in the first place or, at least, <em>eventually</em>. Rebase helps better developers clean up their own commits and also helps them help others clean up their commits, teaching them how to tell the story of their code.</p>
<blockquote class="quote quote-block "><div>&ldquo;A rebase is just a merge with historical references omitted&rdquo;</div></blockquote><p>Exactly. If I can&rsquo;t eliminate WIP commits or squash local commits, then my workflow changes. Honestly what&rsquo;s the point of keeping each commit? Many are scribbles, unwanted drafts. They&rsquo;re not part of a history anyone would retell.  Once commits are cleaned up and tell a good story, there is no need to keep the old commits around. At that point, you&rsquo;re wasting the future archeologist&rsquo;s time.</p>
<blockquote class="quote quote-block "><div>&ldquo;Surely a better approach is to record the complete ancestry of every check-in but then fix the tool to show a &ldquo;clean&rdquo; history in those instances where a simplified display is desirable and edifying, but retain the option to show the real, complete, messy history for cases where detail and accuracy are more important.&rdquo;</div></blockquote><p>This feature is an interesting one for commits that can no longer be changed (i.e. have already been pushed), but why make the developer mark every accident and mistake instead of just letting him undo them? The &ldquo;full&rdquo; view would be of marginal to no value. Even once the messy commits were deciphered, they would most likely yield no useful information. </p>
<p>What possible benefit is it to keep a jungle of &ldquo;fix typo&rdquo; and &ldquo;add missing file&rdquo; or &ldquo;fix broken test&rdquo; commits just because the developer made a commit before running tests or seeing a warning in the IDE? [3]</p>
<h2>Command Line vs. UI</h2><blockquote class="quote quote-block "><div>&ldquo;So, another way of thinking about rebase is that it is a kind of merge that intentionally forgets some details in order to not overwhelm the weak history display mechanisms available in Git.&rdquo;</div></blockquote><p>I honestly think that this guy just wants to make Git look stupid and Fossil look spectacular. I understand fully that it&rsquo;s silly to argue that Git doesn&rsquo;t need a feature that Fossil has just because I&rsquo;ve personally never needed it. A good feature is something that becomes essential once you have it, but you never knew you were missing it or were less efficient without it. Fossil&rsquo;s ability to easily see which changes were made to a file after a given commit sounds like it might be that kind of feature. However, rebase in Git is such a feature, so if Fossil takes that away, it&rsquo;s a deal-breaker.</p>
<p>At this point, I think also that the author is considering Git as a command-line application rather than extended by a truly powerful UI like SmartGit, which provides fast access to gobs of historical data with little effort.</p>
<h2>When does Siloed Development begin?</h2><blockquote class="quote quote-block "><div>&ldquo;Or, to put it another way, you are doing siloed development. You are not sharing your intermediate work with collaborators. This is not good for product quality.&rdquo;</div></blockquote><p>What has this guy seen in the wild that he&rsquo;s reacting this way? Who hurt this poor man? How often does he expect us all to commit and push to the server? Should we code directly on the server? Where does he draw the line for &ldquo;siloed&rdquo; work? A day? An hour?</p>
<p>More to the point: who is paying developers (or a project lead) to examine unvetted commits? Do you think we&rsquo;re made out of free time? Keeping everything around forever is not the most efficient way of optimizing information about your code. <strong>It&rsquo;s a hoarder mentality.</strong></p>
<p>I understand the sentiment: you want to avoid people massaging commits into oblivion, eliminating important information. But, honestly, I&rsquo;ve seen the opposite problem: commits pushed to the server in the shabbiest form, thereafter unalterable. [4]</p>
<blockquote class="quote quote-block "><div>&ldquo;Many developers are drawn to private branches out of sense of ego. &ldquo;I want to get the code right before I publish it.&rdquo;&rdquo;</div></blockquote><p>No, that is not my requirement. I want an efficient review that pinpoints (and fixes) errors quickly so no-one wastes time.</p>
<h2>Online Repository Tools</h2><p>The author claims that,</p>
<blockquote class="quote quote-block "><div>&ldquo;Rebase adds new check-ins to the blockchain without giving the operator an opportunity to test and verify those check-ins. Just because the underlying three-way merge had no conflict does not mean that the resulting code actually works. Thus, rebase runs the very real risk of adding non-functional check-ins to the permanent record.&rdquo;</div></blockquote><p>This is true only for the special case of online merges. These should be avoided like the plague, in any case. I know that people <em>really, really</em> trust their tools. I know that they think that merges are infallible, that their CI builds their software and runs their tests and gives their pull request a green flag and a thumbs-up.</p>
<p>But anything other than a trivial pull request should be examined with tools more capable than online repository managers. Not only are they not as <em>good</em>, they are wildly inefficient when compared to a good desktop tool. I know this next generation of developers want to do everything on their phones, but this is <em>ridiculous</em>. The screen is too small and the tools are too limited. </p>
<p>Get a machine with usable screen real estate and learn what being efficient <em>really means</em>. Not only will you be quicker, you&rsquo;ll be better: your error rate will decrease and you&rsquo;ll see connections in the commits much better than with the (comparatively) meager online tools. I&rsquo;ve written before about one such UI, SmartGit, in <a href="https://www.earthli.com/news/view_article.php?id=3216">Git: Managing local commits and branches</a> and <a href="https://www.earthli.com/news/view_article.php?id=3823">Using Git efficiently: SmartGit + BeyondCompare</a>.</p>
<p>Other online tools have similar weaknesses versus their desktop brethren: for example, text editors like Word or Google Docs. It&rsquo;s definitely a killer feature that they&rsquo;re online, but their only selling point is that they&rsquo;re attached to an online document storage. That&rsquo;s the selling point. As amazing as it is that these tools run in a browser, they are <em>pathetic</em> compared to tools from <em>thirty years ago</em>. My God, I fondly remember WriteNow 4.0 for Mac OS 6 and 7, which handled a 250-page document with aplomb, complete with figures, tables, TOC, numbering, custom styles, … all of those things that an editor should do. Somehow, just because it&rsquo;s in the cloud means that we should be happy with <em>WordPad</em> instead of a full-fledged editor. It&rsquo;s a joke.</p>
<h2>Where does lying begin?</h2><p>The author claims that,</p>
<blockquote class="quote quote-block "><div>&ldquo;Rebasing is the same as lying By discarding parentage information, rebase attempts to deceive the reader about how the code actually came together.&rdquo;</div></blockquote><p>Then you should include all command/undo buffers from your IDE, too. At this point in the document, the author is just repeating the same argument over and over, reformulated but not different.</p>
<blockquote class="quote quote-block "><div>&ldquo;Unless your project is a work of fiction, it is not a &ldquo;story&rdquo; but a &ldquo;history.&rdquo; Honorable writers adjust their narrative to fit history. Rebase adjusts history to fit the narrative.&rdquo;</div></blockquote><p>That&rsquo;s not even how <em>human</em> history works. It&rsquo;s not even how your own stories about your own life work. This is the kind of mentality that wants to keep all 6000 pictures from a vacation. Why? Just in case you need that picture of the ground that you took by accident? Because you need all 300 pictures of the Matterhorn? You&rsquo;re wasting your readers&rsquo; time and your own.</p>
<blockquote class="quote quote-block "><div>&ldquo;The intent is that development appear as though every feature were created in a single step: no multi-step evolution, no back-tracking, no false starts, no mistakes.&rdquo;</div></blockquote><p>Again, he proposes to fix a problem—poorly built commits—by <em>not allowing anyone to modify commits.</em></p>
<blockquote class="quote quote-block "><div>&ldquo;We believe it is easier to understand a line of code from the 10-line check-in it was a part of — and then to understand the surrounding check-ins as necessary — than it is to understand a 500-line check-in that collapses a whole branch’s worth of changes down to a single finished feature.&rdquo;</div></blockquote><p>I agree with this 100%. As already noted above, though, the review should disallow such foolish hairball commits.</p>
<blockquote class="quote quote-block "><div>&ldquo;The more comments you have from a given developer on a given body of code, the more concise documentation you have of that developer’s thought process.&rdquo;</div></blockquote><p>Correct. But you don&rsquo;t want to see everything. He presents a false choice between all the history and an improperly truncated version. Then he says he&rsquo;d rather have all of it, and wants to get rid of history-rewriting. This doesn&rsquo;t fix the problem of shitty programmers making shitty commits. The only way to fix that is gatekeeping reviews and process. Taking a vital tool for clarity (rebasing) away from disciplined programmers is a terrible idea.</p>
<blockquote class="quote quote-block "><div>&ldquo;If we rebase each feature branch down into the development branch as a single check-in, pushing only the rebase check-in up to the parent repo, only that fix’s developer has the information locally to perform the cherry-pick of the fix onto the stable branch.&rdquo;</div></blockquote><p>He really seems to.be attacking a repo-management/history-editing process I&rsquo;ve never used. It sounds horrid.</p>
<blockquote class="quote quote-block "><div>&ldquo;Rebasing is an anti-pattern. It is dishonest. It deliberately omits historical information. It causes problems for collaboration. And it has no offsetting benefits.&rdquo;</div></blockquote><p>Only one of those sentences is true.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3864_1_body" class="footnote-number">[1]</span> Before I used Git, I used Perforce, which allowed a developer to keep changelists around without committing them. Once a changelist had been submitted to the server, it was frozen in the history. Until then, though, the developer could alter files and the commit message.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3864_2_body" class="footnote-number">[2]</span> Or so it sounded—I have not actually used Fossil.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3864_3_body" class="footnote-number">[3]</span> If you&rsquo;re a SmartGit user, then you can see the trail of commits you&rsquo;re leaving behind by selecting &ldquo;Recyclable Commits&rdquo; in the Log View. This shows all commits that will be reclaimed by the garbage collector the next time it runs.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3864_4_body" class="footnote-number">[4]</span> As noted above, Fossil seems to offer a feature with which you can &ldquo;amend&rdquo; commits and messages afterwards. I, however, want to be able to prevent bad commits from entering the stream in the first place.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3876</guid>
    <title><![CDATA[Advanced CSS (blend modes and subgrids)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3876</link>
    <pubDate>Sat, 28 Dec 2019 23:23:06 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">28. Dec 2019 23:23:06 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">28. Dec 2019 23:23:47 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://24ways.org/2019/zs-still-not-dead-baby-zs-still-not-dead/">Z’s Still Not Dead Baby, Z’s Still Not Dead</a> by <cite>Andy Clarke</cite> (<cite><a href="http://24ways.org/">24 Ways</a></cite>) is well-written, very interesting and taught me a few new CSS tricks of which I was unaware.</p>
<p>Granted, my work usually doesn&rsquo;t call for fancy effects like those you can achieve with something like <code>background-blend-mode</code>, but it can happen. There&rsquo;s not only <code>background-blend-mode</code>, there&rsquo;s also <code>mix-blend-mode</code> and <code>filter</code>, all of which apply high-quality effects dynamically.</p>
<p>In the late spring, I had a two-month project where I had to use a lot of transformations and animations—and I was able to get it all done with CSS. Once you know about these kinds of techniques, you keep them in mind, and are able to consider solutions that would seem impossible (or very difficult/time-consuming/unmaintainable) if you didn&rsquo;t know the technique.</p>
<p>A modern browser can construct the following image by composing and blending a couple of graphics.</p>
<p><span style="width: 401px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3876/austinseven850ad.png"><img src="https://www.earthli.com/data/news/attachments/entry/3876/austinseven850ad.png" alt=" " style="width: 401px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3876/austinseven850ad.png">Samples of Austin Seven 850 Ads</a></span></span></p>
<p>It&rsquo;s actually pretty cool that you can get this type of layout with wide browser support and no hacks. See the linked article for a lot of examples.</p>
<p>I have used CSS Grid before (as the author does). The author mentions <em>subgrids</em>, but ends up using a second grid within the first grid because browser support for nested grids is good, whereas no-one <a href="https://caniuse.com/#search=subgrid">supports subgrids except for the latest version of Firefox</a>. The MDN documentation for <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Subgrid">Subgrids</a> explains that it differs from nested grids in that</p>
<blockquote class="quote quote-block "><div>&ldquo;If you set the value subgrid on grid-template-columns, grid-template-rows or both, instead of creating a new track listing the nested grid uses the tracks defined on the parent.&rdquo;</div></blockquote><p>The linked page includes many examples and more detail.</p>
<p>As with any advanced techniques, you have to take into account your own target browsers to see whether you can use them in your own projects. It&rsquo;s a well-written article and I learned a few more techniques that I can hopefully use at some point.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3856</guid>
    <title><![CDATA[Framework Design: Programming Paradigms and Idioms]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3856</link>
    <pubDate>Sat, 30 Nov 2019 15:36:51 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. Nov 2019 15:36:51 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:28:45 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The discussion <a href="https://news.ycombinator.com/item?id=21667403">React in concurrent mode: 2000 state-connected comps re-rendered at 60FPS </a> (<cite><a href="http://news.ycombinator.com/">YCombinator</a></cite>) is illuminating mostly in that it shows how ego can impede productivity.</p>
<h2>Ego-driven design</h2><p>Ego can also be that thing that drives a talented programmer to create something of use to the rest of us, but that&rsquo;s honestly a very rare case. More often than not, the best case is that a developer  improves their skills—and perhaps learns to be more humble instead of shooting of their mouth about how &ldquo;easy&rdquo; it is to create a &ldquo;good&rdquo; product. Such claims are nearly always made without defining what they mean by &ldquo;good&rdquo;. </p>
<p>Some comments are from programmers more interested in a pissing contest of who can write performant code on their own. Their implementation often focuses laser-like on a specific use case not often found in nature without tackling the tough question of how to design a more generalized solution that incorporates and balances more than just the one aspect of the system that they think they&rsquo;re good at (e.g. performance).</p>
<p>That is, they tend to carefully define the application domain based on what they&rsquo;re already good at. This is not how product development works. Many of the commentators get distracted by the overreaching claims of the reposter (faster than any other WebGL rendering, which is patently not true) instead of reading the much more reasonable claims of Dan Abramov, who is the original poster.</p>
<h2>Product-driven design</h2><p>Thankfully, there are others who seem to understand that giving up a logical, declarative paradigm in order to do so is not an acceptable tradeoff in almost any given project. What are some facets other than performance that contribute to a good solution?</p>
<ul>
<li><strong>Maintainability</strong></li>
<li><strong>Extendability</strong></li>
<li><strong>Readability</strong>: low syntax noise</li>
<li><strong>Testability</strong>: composition-based</li>
<li><strong>Discoverability</strong>: consistent API</li>
<li><strong>Flexibility</strong>: applicability to different problem domains</li>
<li><strong>Expressiveness</strong>: concise and precise</li>
<li><strong>Correctness</strong>: error-free is strongly encouraged or enforced</li>
<li><strong>Completeness</strong>: degree to which the definition captures all facets of the problem domain</li>
<li><strong>Learnability</strong>: low number of concepts cover application needs</li>
<li><strong>Scalability</strong>: layered API allows more control where needed</li>
<li><strong>Efficiency</strong>: ratio of effort to product low</li>
<li><strong>High signal-to-noise ratio</strong></li>
<li><strong>Optimizability/Performance</strong></li></ul><p>Products that try optimizing all facets generally never see the light of day or serve as the base material from which more viable projects are born.</p>
<p>A higher level of abstraction is a <em>good thing</em>. It allows mediocre  programmers (and be happy if you have even mediocre programmers) to write programs that aren&rsquo;t a nightmare to maintain or refactor. It allows good developers to very quickly write maintainable programs. If the underlying framework has a declarative and easily understood paradigm that has only a handful of orthogonal concepts <em>and</em> it offers great performance by default, that&rsquo;s a win. There are few projects that need <em>spectacular</em> performance as their main feature.</p>
<h2>Focus on your application domain</h2><p>I would argue that most web programming is about making line-of-business apps and pages where look and feel matters so much that it&rsquo;s worth investing 50% more budget to get near-perfect and smooth updates. If it janks, it janks. There is no time or budget (or, sometimes, programming skill) to &ldquo;fix&rdquo; it. And, if &ldquo;fixing&rdquo; it means abandoning the high-level declarative programming model that makes working with Reactive so efficient, maintainable and productive, then that&rsquo;s even more implicit cost bound up in it.</p>
<p>As the commentator <em>Onion2k</em> put it:</p>
<blockquote class="quote quote-block "><div>&ldquo;This is a demo of good performance using a web framework on top of a WebGL framework. It&rsquo;s showing that a future version of React will make building a solid 60fps web app UI […] within the reach of most web developers. Sure, you can hand-roll code to get that performance today if you know how, but this is about putting that performance in the hands of developers who can&rsquo;t (or, <strong>more often, aren&rsquo;t given the resources to</strong>). To argue that is unnecessary or <em>actually bad</em> is ridiculous. Libraries that make it easier to build better apps are universally good things. (Emphasis added.)&rdquo;</div></blockquote><h2>Defining an application model</h2><p>To use React, you have to make concessions to Reactive mode in your application definition. But that&rsquo;s the way <em>programming works</em>. Instead of writing &ldquo;a person must have a company, while the company has a possibly empty list of people&rdquo;, we write (example from <a href="https://www.encodo.com/quino">Quino</a>),</p>
<pre class=" "><code>Elements.Module.Company
  .AddOneToManyRelation(Elements.Module.Person)</code></pre><p>Programming is all <em>about</em> explaining what an application does. The programming language and framework and runtime balance all of the factors listed above to be able to transform the formulation most accessible to a product owner (&ldquo;I want a CRM&rdquo;) through a business analyst (&ldquo;It has a list of companies, each of which has a list of people&rdquo;) to a programmer (formulation above).</p>
<p>The formulation above is still quite high-level, but satisfactory for 99% of cases. For the remaining 1%, the API has to provide some way of digging into the underpinnings of the implementation without dropping the developer off of a cliff. Quino does this reasonably well, as does React. The focus here is on realizing that a framework&rsquo;s ability to accommodate that 1%  of use cases smoothly is only one aspect of its effectiveness. Given that it doesn&rsquo;t come up very much, it makes no sense to focus too much effort on optimizing that path, no matter how much more interesting it would be to the developers to do so.</p>
<h2>Concurrent mode in React</h2><p>This is one of those silly blogs-posted-as-tweets, but the points in <a href="https://twitter.com/dan_abramov/status/1120971795425832961">Is Concurrent Mode just a workaround for “virtual DOM diffing” overhead? […]</a> by <cite>Dan Abramov</cite> (<cite><a href="http://twitter.com/">Twitter</a></cite>) are good.</p>
<p>The point is that <a href="https://reactjs.org/docs/concurrent-mode-intro.html">Concurrent Mode</a> is not a speed improvement <em>only for React</em>. It also improves how your app&rsquo;s code updates and is scheduled <em>without you having to change your code</em> (much, or at all). The linked article explains how this sea change in rendering components forms the basis of many other performance improvements that apply to existing applications without modification.</p>
<p>It&rsquo;s exciting that a near-future version of React will make animations and updates even smoother than they are now. This taking into consideration that they are already more than good enough for most apps without tweaking. </p>
<h2>React&rsquo;s idioms</h2><p>React is not a game-programming framework. It makes no sense to claim that React apps will blow away apps written in Unity. We make line-of-business apps with it. React already allows apps to have much better update characteristics with almost no code other than a few functional declarations to define rendering and components and the state that they rely on. </p>
<p>The model is unimpeachable in that it accurately reflects the application model without adding any ceremony.</p>
<p>You make some concessions in order to define your declarations about your program&rsquo;s logic and states so that the framework can optimize as much as it can, <em>but no more</em>. With hooks, you can declare simple, mutable state or one-time, partially mutable state (memos and callbacks), listeners for lifecycle events (effects) and so on.</p>
<p>On the one hand, you&rsquo;re forced to define your logic using React&rsquo;s idioms but, on the other, they still make sense in that they make your assumptions about your app&rsquo;s logic <em>explicit</em> rather than <em>implicit</em>. Once you&rsquo;ve done this, the framework knows more about what it can optimize away and what it can&rsquo;t. And you haven&rsquo;t wasted time because you&rsquo;re technically describing salient properties of your application domain.</p>
<h2>Declaring Behavior</h2><p>That&rsquo;s the idea behind the <code>&lt; Suspense/&gt;</code> component: the app can declaratively determine how it would like components to be updated in different asynchronous situations involving multiple asynchronous tasks. Concurrent Mode allows the framework to work before that update is technically complete because it allows any work to be interrupted—and discarded, if it is no longer relevant.</p>
<p>This allows the reconciliation to benefit a bit from something like the branch predictor in a CPU, where speculative branches are executed in parallel and occasionally discarded. JavaScript imposes a cooperative rather than parallel model, but low-level support for interruptibility (especially when automatically applied) is worlds better than nothing.</p>
<h2>Working within a paradigm</h2><p>Any language—and the combination of the underlying programming language and the framework API, combined, is the language a programmer uses—must have a shape, a paradigm that it enforces. Naturally, a programmer can use a different paradigm than the recommended one. But a good framework finds the balance between a paradigm that is comfortable for a large part of its audience and one that is enough of an abstraction that it has a lot of leeway for applying to the next layers down (until it gets to machine code). </p>
<p>A good framework provides an out-of-the-box experience that provides a clearer programming idiom and better performance than most programmers could do on their own.</p>
<p>In the thread above, Abramov in no way claims that it&rsquo;s not possible to create a faster application for thousands of components, just that the new renderer is much, much faster than the old one <em>without changing the programming idiom at all</em>. The programming idiom in React is very good, if not great. This is really good news.</p>
<p>Instead, you could say that Abramov&rsquo;s claim is that anyone who claims to have made a faster renderer is making tradeoffs in other areas (e.g. from the list above). Most likely, the resulting balance is not as good as the clear, declarative syntax of React or it doesn&rsquo;t cover nearly as many use cases.</p>
<h2>Comparing Idioms (React vs. Svelte)</h2><p>Is React&rsquo;s syntax the best it can be? Maybe not yet. For example, a component declares mutable, internal state with the <code>useState()</code> hook, which returns a state variable and a &ldquo;setter&rdquo; function to change that state. Svelte, for example, improves on this by allowing the app to just declare the state variable and <em>automatically</em> noticing when that state is updated and generating the state-update code in the transpilation phase. This is an improvement that allows an app developer to work even closer to &ldquo;normal&rdquo; code than before.</p>
<p>If Svelte can provide this clearly more <em>readable</em> feature without introducing problems in other facets (e.g. learnability, performance, completeness), then it&rsquo;s a clear win.</p>
<h2>Case study: <code>async/await</code>)</h2><p>A similar kind of improvement is <code>async/await</code>. This feature didn&rsquo;t actually change how asynchronous code works. Instead, it allowed a programmer to write synchronous code that could be made asynchronous <em>automatically</em>.</p>
<p>This is a sea change for most developers—even those clever and experienced enough to have written that level of asynchronous code themselves. The point is that the developer is no longer wasting time writing what amounts to boilerplate code that is very error-prone and difficult to thoroughly test (which means that it&rsquo;s often not thoroughly tested).</p>
<p>The idiom of <code>async/await</code> imposed minimal &ldquo;noise&rdquo; (none, actually) and has a tremendous upside. The code doesn&rsquo;t necessarily get faster, but it <em>could be made faster without changing it</em>.</p>
<h2>Inherent Limitations of Languages/Runtimes</h2><p>The comment on <a href="https://github.com/facebook/react/issues/7942#issuecomment-254984862">Fiber Principles: Contributing To Fiber</a> by <cite>sebmarkbage</cite> (<cite><a href="http://github.com/">React/Github</a></cite>) is another well-written contribution to this discussion that shows that there are a lot of clever people working on React that are aware of the fine balance between the requirements involved in writing a strong framework. </p>
<p>The user responds to accusations that much of this work would not be necessary if JavaScript had proper threading. The author argues that globally mutable prototypes are an intrinsic concept that is used in many, many JavaScript use cases. However, they also limit the ability of <em>ever</em> bringing threads to JavaScript. The language is limited from the get-go.</p>
<p>That doesn&rsquo;t mean we should all stop using JavaScript. It just means that this is something that goes in the <em>cons</em> list and must be weighed against all of the <em>pros</em>. Anything that is in the <em>cons</em> list must be compensated with <em>effort</em>. JavaScript has many pros going for it: for example, it&rsquo;s won the client-side programming-language war.</p>
<p>Perhaps WebAssembly will replace it as a runtime, but only time will tell. By then, it won&rsquo;t matter, because we&rsquo;ll be using languages like Elm or TypeScript to write our code. Even this doesn&rsquo;t matter, though, because these languages must <em>also</em> transpile to the underlying paradigm defined by an engine that must run JavaScript.</p>
<p>That goes—for now—for WebAssembly targets as well. And threading is out for any of this stuff. Until something in this situation changes and we can target a threaded execution engine on the client side, we should be happy that there are very clever people making cooperative multi-tasking transparent and easy to program for the rest of us.</p>
<p>Those of us who worked on Apple OSs before OS X or Windows before 95 know what it&rsquo;s like to have to deal with cooperative multi-tasking in our own code. I welcome the declarative paradigm that allows excellent performance for a wide range of use cases without making me write and maintain a whole bunch of code that has nothing to do with my application domain.</p>
<h2>Avoiding shared, mutable state</h2><p>There&rsquo;s a reason why everyone with sense is talking about this concept. Using shared, mutable state makes it very easy to write the happy path of a single use case, but it makes it very hard to reason about other use cases and branches. It doesn&rsquo;t scale, extend, test or maintain well. If these requirements don&rsquo;t apply to your application—e.g. a script or one-off throwaway prototype—then you might be fine.</p>
<p>I would personally advise against practicing or becoming accustomed to techniques that apply to one use-case but that are dangerous in all other situations. You&rsquo;ll generally end up using the technique to which you&rsquo;ve become accustomed. While training yourself to build high-quality solutions risks the danger of over-engineering solutions to problems that could have been solved more simply, it&rsquo;s easier to &ldquo;downscale&rdquo; your coding style than to &ldquo;upscale&rdquo; it.</p>
<p>With enough practice and the right techniques, you can write quality code just as initially efficiently as crappy code. I would also say to beware of the seductiveness of bad programming models that promise an initial speed in development that quickly drops off once it&rsquo;s too late to change. </p>
<p>Prototypes happen to be built into the language in JavaScript&rsquo;s case, but shared mutable data is the great stumbling block of concurrent programming. Applications that batch work into parallelizable chunks can be optimized to run more quickly by a clever runtime.</p>
<p>It is much simpler to reason about an application without shared mutable data. There are fewer cases and branches. Otherwise, an application must use locks (or fences or some sort of synchronization concept). The point is that efficient synchronization is not easy and many laic implementations tend toward speed rather than robustness and are buggy as a result.</p>
<p>Though it&rsquo;s possible to hand-code faster concurrency than standard frameworks, most people can&rsquo;t do it. And, given time, framework implementations get <em>really, really good</em> at optimizing nearly all cases. C# and .Net, for example, have a tremendously clever runtime underlying <code>async/await</code> now that can hardly be beaten for throughput, scheduling, etc. Successive versions have built on new language concepts introduced <em>precisely</em> to allow an application—where needed—to be more declarative in ways that allow even more optimization (e.g. record references, etc.)</p>
<p>It&rsquo;s nice to see that Concurrent React—much like <code>async/await</code> in JS—provides a simple idiom for moving that effort out of the hands of most developers. </p>
<h2>Reinventing the Wheel</h2><p>Naturally, a developer is free to do that work on their own—and many commentators in the original thread at the start of this article seem to enjoy writing code that has nothing to do with their actual app just to show that <em>they can</em>. But with enhancements like <code>async/await</code> or Concurrent React, they don&rsquo;t <em>have to</em> in order to enjoy performance benefits. That&rsquo;s a win-win—a free lunch.</p>
<p>The point made above by <em>Onion2k</em> is very salient: very often <span class="quote-inline">&ldquo;developers [aren&rsquo;t] given the resources to&rdquo;</span> make the kind of optimizations that React will provide for free. Could a given rockstar developer write something even faster for exactly their application domain? Probably. Are they going to be given the time and budget to do so? Almost certainly not. It&rsquo;s far better to have a good default that is smooth as silk and more than adequate to the task for almost all conceivable applications.</p>
<p>No-one&rsquo;s paying you to reinvent the wheel. That&rsquo;s almost certainly not your job. If you&rsquo;d like it to be your job, then maybe you should work on a project where you&rsquo;re inventing the wheel directly (i.e. a framework project). Then, you can build on that experience and your framework to turn around tightly written, maintainable and performant applications for your paying customers. </p>
<h2>Inventing the Wheel</h2><p>It&rsquo;s important to be pragmatic and remember when you&rsquo;re working on framework code and when you&rsquo;re working on code that <em>benefits</em> from framework code without <em>reinventing</em> it. Otherwise, you&rsquo;ve got a terrible situation: you invest in framework/infrastructure on every single project because you never reap the benefits of having written a framework. In the case of frameworks that are completely external to your application, like React (or Quino), you never even had to invest in writing the framework at all.</p>
<p>If you write a framework for just expert developers, there will be no adoption <em>and</em> you don&rsquo;t help a large part of the community to write better apps. But what do we mean by <em>better</em>?</p>
<p>Continuing with React as an example, the abstract requirements at the start of this article roughly map to:</p>
<ul>
<li>Maintainable (minimum of idioms)</li>
<li>Robust (not buggy)</li>
<li>Scaling performance
<li><div>Consistent UX for<ul>
<li>Error conditions</li>
<li>Networking latency (progressive handling, from avoiding needless jank to notifying the user that something is happening when it takes longer) </li>
<li>Small/large data/updates</li></ul></div></li>
<li>Tooling support for introspection, code-completion, debugging, discovery, etc.</li>
<li><div>Support for common tasks<ul>
<li>State management, from function-local to multi-function/context</li>
<li>Describing state (mutable, non-mutable)</li></ul></div></ul><h2>Minimizing Impedance</h2><p>An application should have to only declare things about itself that are relevant to itself—but that also help to render the application better. Again, these idioms should scale: an application which will not have foreseeable performance issues in most components should be able to write those components with more approachable code.</p>
<p>Individual &ldquo;islands&rdquo; of code can provide additional information to optimize hotspots (like memoization, immutability hints, etc.) It&rsquo;s important to note that these concepts are <em>not</em> introduced by the framework—they are intrinsic to the application&rsquo;s domain model, but usually kept implicit.</p>
<p>If the application does not describe these aspects of itself, then the framework must make more pessimistic assumptions. Often this doesn&rsquo;t matter. Where it does matter, the application should be able to use compatible and familiar idioms to improve the granularity of its description about itself. This, in turn, lets the framework use a faster approach where it now <em>knows</em> that it won&rsquo;t violate the application&rsquo;s definition.</p>
<p>The simplest of these is to tell React which parts of the state are mutable and which are immutable. When determining what has changed in an application state, a framework can simply compare the reference to the root node of an immutable object graph to  the previous root-node reference to determine if that part of the graph has changed. If the object graph does not declare itself as immutable, then the framework must be pessimistic and compare the entire subgraph to determine if it has changed.</p>
<p>This is a concept that is <em>intrinsic</em> to programming. It is hard to conceive of it ever not being relevant. Naturally, if there is more than enough processing power available or the graph is small enough, it won&rsquo;t matter, but it&rsquo;s still axiomatically <em>more</em> work to compare potentially mutable graphs than immutable graphs. If an application fails to express immutability where it could have, that small missing bit of information reduces flexibility in choosing an algorithm.</p>
<p>This is not a new thing: most functional languages have immutability baked in as the default. Even C has the notion of <code>const</code> and <code>volatile</code> to give hints to the compiler about how it can deal with that data. Naturally, higher-level languages try to abstract away these concepts, but it constrains all the layers below.</p>
<h2>Other Intrinsic Concepts</h2><p>On this subject, another unavoidable concept is nullability: is a reference assigned or not? Most new languages (and newer versions of languages, like C#) are switching from the age-old—and convenient-for-the-compiler—default of nullable references. Again, reference assignment is a core concept that is unavoidable when thinking about code with pointers.</p>
<p>Another concept that limits choosing a more performant transformation during compilation is failing to express function purity. Does a function cause a side-effect? A compiler can optimize a function known to be pure in ways that it cannot with impure functions.</p>
<p>All of these features are a balance between programmer convenience, onboarding of new developers, and allowing programmers to focus on application logic rather than making concessions to the language and framework. As discussed above, though, there are concepts intrinsic to programming that have ostensibly nothing to do with application logic, but that an application declares (if not explicitly, then implicitly).</p>
<p>Taking the example from above, if an application declares that a person is in a company, but fails to mention that a person <em>must</em> be in a company, then the underlying software (framework and compiler) must be more pessimistic about that relationship than is strictly necessary. </p>
<p>A good framework encourages software to be precise about its own model by allowing the application to declare the salient parts of its model in a declarative minimal set of idioms.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3847</guid>
    <title><![CDATA[Thoughts on Atomic/Utility CSS]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3847</link>
    <pubDate>Sun, 24 Nov 2019 20:55:24 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=root" title="(withheld)" class="visible">root</a> on <span class="date-time">24. Nov 2019 20:55:24 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://frontstuff.io/in-defense-of-utility-first-css">In Defense of Utility-First CSS</a> by <cite>Sarah Dayan</cite> on January 15th, 2018 (<cite><a href="http://frontstuff.io/">Frontstuff</a></cite>) is very long [1], so I&rsquo;ve summarized a bit with notes and thoughts. [2]</p>
<p>I don&rsquo;t really care about being pedantic without first knowing some facts. What are the requirements?</p>
<h2>Requirements</h2><ul>
<li>Can I quickly make a precise change to a single component?</li>
<li>Can I make a global, thematic change?</li>
<li>How quickly can I make changes?</li>
<li>How maintainable is the result?</li></ul><p>If atomic/utility CSS can deliver these things, then it&rsquo;s probably a fine tool. But—spoiler alert—it seems more like a tool for designers—not programmers. Programmers have other, better tools for building CSS in a way that fulfills the requirements above.</p>
<h2>Designers vs. Programmers</h2><p>Essentially, these designers are like we programmers used to be: we used to care about cascading when we were still hand-coding our CSS. Now that we&rsquo;re using LESS or another generator, we can use variables and functions for theming and use local CSS for precision. We can lean on specificity when it suits us and avoid it when it only gets in the way.</p>
<p>We want to declaratively say how we want everything to look and let our tools (LESS, WebPack with plugins) figure out how best to generate the CSS to accommodate supported browsers and also to create the kind of CSS that performs well without blowing up memory client-side. None of these optimizations and accommodations for targets should be up to the programmer/designer/CSS-writer at this point. </p>
<h2>Utility vs. BEM</h2><p>Utility-CSS feels functional, but it also feels like something you use when you don&rsquo;t have LESS. I&rsquo;ve never used BEM and agree that it never really made sense, from several good coding practices like DRY. That the author is coming from BEM to utility-CSS is not a surprise: BEM was never a good idea.</p>
<h2>A Refactoring Use Case</h2><blockquote class="quote quote-block "><div>&ldquo;Early refactors are a pretty good indicator of unmaintainability.&rdquo;</div></blockquote><p>I don&rsquo;t agree. It&rsquo;s more a sign of shifting priorities or requirements. It&rsquo;s not uncommon in agile development. The example the author has of changing the meaning of a &ldquo;card&rdquo; after there are already components using that style just means that you should make a &ldquo;card2&rdquo; class (not a &ldquo;card-no-ribbon&rdquo; one) because it&rsquo;s just a different card type.</p>
<p>The problem is that the design now includes two cards, not that your implementation should somehow be able to easily roll with a confusing design.</p>
<p>Where I see a problem is when a card is supposed to have a certain padding and a border with a certain color (let&rsquo;s say the &ldquo;padding-top-8&rdquo; and &ldquo;border-bottom-lemon&rdquo; from the author&rsquo;s example). But then you don&rsquo;t want those anymore.</p>
<p>Granted, with proper components, you&rsquo;ll only have to change the style in one place anyway, right? So it doesn&rsquo;t matter what you call it. You could have just called it &ldquo;card&rdquo; in the local styles and been done with it. So, either you have to remove those highly specific styles in many places in your HTML (as with an old-style web site, like earthli) or you change it in one place anyway (new-fangled, with React components).</p>
<h2>Visuals vs. Semantics</h2><p>I guess it&rsquo;s the difference between knowing from the HTML what the component is going to <em>look like</em> (<code>&lt;blockquote class=&ldquo;border-thick-left-red padding-left-medium font-navy&rdquo;&gt;</code>) and knowing what the component <em>is</em> (<code>&lt;blockquote class=&ldquo;newspaper&rdquo;&gt;</code>).</p>
<p>The author writes:</p>
<blockquote class="quote quote-block "><div>&ldquo;Yet, the bigger and the more complex a component gets, the less obvious it is to know what class name maps to what element on the screen, or what it looks like.&rdquo;</div></blockquote><p>But then they include an example where it&rsquo;s absolutely clear which components do what:</p>
<pre class=" "><code>&lt;div class="entry"&gt;
  &lt;h2 class="entry-title"&gt;The Shining&lt;/h2&gt;
  &lt;div class="widget widget-lead"&gt;
    &lt;div class="widget-content"&gt;
      &lt;p&gt;His breath stopped in a gasp…&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class="author"&gt;
      &lt;img class="author-avatar" src="…"&gt;
      &lt;h3 class="author-name"&gt;Stephen King&lt;/h3&gt;
      &lt;p&gt;Stephen Edwin King …&lt;/p&gt;
      &lt;div class="btn-group"&gt;
        &lt;a class="btn" href="#"&gt;Website&lt;/a&gt;
        &lt;a class="btn" href="#"&gt;Twitter&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;</code></pre><p>I think this again shows the difference between programmers and designers: the code above is crystal clear to a programmer, so if a programmer is writing the CSS, then there&rsquo;s no need to change anything.</p>
<p>The author seems to be a designer hell-bent on knowing exactly what the page will look like without actually showing it in a browser. I wish they&rsquo;d included the version with utility CSS … it would have been a giant block of unreadable code, doubled in size with class names.</p>
<h2>Don&rsquo;t Change Anything</h2><p>The author makes a good case for theming using CSS variables, which can be applied &ldquo;at runtime&rdquo; in the browser. The solution to theming with utility CSS turns out to be … making semantic styles instead of precisely named styles. So…not utility CSS.</p>
<p>The author references a few other articles, one of which is <a href="http://www.zeldman.com/2017/01/03/kiss-my-classname/">Kiss My Classname</a> by <cite>Jeffrey Zeldman</cite>, which eloquently argues that there is nothing to change. He instead argues that developers and designers should use a <em>visual style guide</em>.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;I don’t believe the problem is the principle of semantic markup or the cascade in CSS. I believe the problem is a dozen people working on something without talking to each other.</p>
<p>&ldquo;Slapping a visually named class on every item in your markup may indeed make your HTML easier to understand for a future developer who takes over without talking to you, especially if you don’t document your work and create a style guide. But making things easier for yourself and other developers is not your job. <strong>And if you want to make things easier for yourself and other developers, talk to them, and create a style guide or pattern library.</strong>&rdquo;</p>
</div></blockquote><blockquote class="quote quote-block "><div>&ldquo;The present is always compromised, always rushed. We muddle through with half the information we need, praised for our speed and faulted when we stop to contemplate or even breathe. (Emphasis added.)&rdquo;</div></blockquote><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3847_1_body" class="footnote-number">[1]</span> It&rsquo;s also almost two years old, but still seems to describe the state-of-the-nation in utility/atomic CSS.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3847_2_body" class="footnote-number">[2]</span> <p>Another article they referenced was <a href="https://adamwathan.me/css-utility-classes-and-separation-of-concerns/">CSS Utility Classes and &ldquo;Separation of Concerns&rdquo;</a> by <cite>Adam Wathan</cite> on August 7th, 2017 and it&rsquo;s even longer. It&rsquo;s almost a jeremiad with the seeming intent of breaking the reader down with a flood of words. I could only skim it, but it seems like these people are styling without programming: that is, some of the utility classes and even the slightly semantic ones they use could very easily be written more cleanly if they just used component-local styles.</p>
<p>For example, this is completely unnecessary with local styles, because you don&rsquo;t have to worry about specificity biting you in the ass:</p>
<pre class=" "><code>&lt;div class="media-card"&gt;
  &lt;img class="media-card__image" 
src="https://i.vimeocdn.com/video/585037904_1280x720.webp" alt=""&gt;
  &lt;div class="media-card__content"&gt;
    &lt;h2 class="media-card__title"&gt;Stubbing …&lt;/h2&gt;
    &lt;p class="media-card__body"&gt;
      In this quick blog post and screencast, …
    &lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;</code></pre><p>In another article <a href="https://css-tricks.com/growing-popularity-atomic-css/">On the Growing Popularity of Atomic CSS</a> by <cite>Ollie Williams</cite> on November 24th, 2017, the author mentions that they&rsquo;re addressing <span class="quote-inline">&ldquo;n a mixed-ability team, perhaps involving backend developers with limited interest and knowledge of CSS&rdquo;</span>. I didn&rsquo;t have the energy to finish that one either, because a skim indicated that it repeated a lot of what was in the article I did read.</p>
</div><p> </p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3825</guid>
    <title><![CDATA[Azure Linked Accounts and SSH Keys]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3825</link>
    <pubDate>Thu, 17 Oct 2019 14:42:13 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Oct 2019 14:42:13 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Azure DevOps allows you to link multiple accounts. </p>
<p>Our concrete use case was:</p>
<ul>
<li>User U1 was registered with an Azure DevOps organization O1</li>
<li>Microsoft did some internal management and gave our partner account a new organization O2, complete with new accounts for all users. Now I have user U2 as well, registered with O2.</li>
<li>U2 was unable to take tests to qualify for partner benefits, so I had to use U1 but link the accounts so that those test results accrued to O2 as well as O1.</li>
<li>We want to start phasing out our users from O1, so we wanted to remove U1 from O1 and add U2</li></ul><p>Are we clear so far? U1 and U2 are linked because reasons. U1 is old and busted; U2 is the new hotness.</p>
<p>The linking has an unexpected side-effect when managing SSH keys. If you have an SSH key registered with one of the linked accounts, you cannot register an SSH key with the same signature with any of the other accounts.</p>
<p>This is somewhat understandable (I guess), but while the error message indicates that you have a duplicate, it doesn&rsquo;t tell you that the duplicate is in another account. When you check the account that you&rsquo;re using and see no other SSH keys registered, it&rsquo;s more than a little confusing.</p>
<p>Not only that, but if the user to which you&rsquo;ve added the SSH key has been removed from the organization, it isn&rsquo;t at all obvious how you&rsquo;re supposed to access your SSH key settings for an account that no longer has access to Azure DevOps (in order to remove the SSH key).</p>
<p>Instead, you&rsquo;re left with an orphan account that&rsquo;s sitting on an SSH key that you&rsquo;d like to use with a different account.</p>
<p>So, you could create a new SSH key _or_ you could do the following:</p>
<ul>
<li>Re-add U1 to O1</li>
<li>Remove SSH key SSH1 from U1</li>
<li>Register SSH key SSH1 with U2</li>
<li>Profit</li></ul><p>If you can&rsquo;t add U1 to O1 anymore, then you&rsquo;ll just have to generate and use a new SSH1 key for Azure. It&rsquo;s not an earth-shatteringly bad user experience, but interesting to see how several logical UX decisions led to a place where a couple of IT guys were confused for long minutes.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3823</guid>
    <title><![CDATA[Using Git efficiently: SmartGit + BeyondCompare]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3823</link>
    <pubDate>Thu, 17 Oct 2019 13:27:26 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Oct 2019 13:27:26 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Mar 2021 14:33:13 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I&rsquo;ve written about using <em>SmartGit</em> (SG) before [1] [2] and I still strongly recommend that developers who manage projects use a UI for Git.</p>
<p>If you&rsquo;re just developing a single issue at a time and can branch, commit changes and make pull requests with your IDE tools, then more power to you. For this kind of limited workflow, you can get away with a limited tool-set without too big of a safety or efficiency penalty. </p>
<p>However, if you need an overview or need to more management, then you&rsquo;re going to sacrifice efficiency and possibly correctness if you use only the command line or IDE tools.</p>
<p>I tend to manage Git repositories, which means I&rsquo;m in charge of pruning merged or obsolete branches and making sure that everything is merged. A well-rendered log view and overview of branches is indispensable for this kind of work.</p>
<h2>SmartGit</h2><p>I have been and continue to be a proponent of <em>SmartGit</em> for all Git-related work. It not only has a powerful and intuitive UI, it also supports pull requests, including code comments that integrate with <em>BitBucket</em>, <em>GitLab</em> and <em>GitHub</em>, among others.</p>
<p>It has a wonderful log view that I now regularly use as my standard view. It&rsquo;s fast and accurate (I almost never have to refresh explicitly to see changes) and I have a quick overview of the workspace, the index and recent commits. I can search for files and easily get individual logs and blame.</p>
<p>The file-differ has gotten a lot better and has <em>almost</em> achieved parity with my favorite diffing/merging tool <em>Beyond Compare</em>. Almost, but not quite. The difference is still significant enough to justify <em>Beyond Compare</em>&rsquo;s purchase price of $60.</p>
<p>What&rsquo;s better in <em>Beyond Compare</em> [3]?</p>
<h2>Diffing</h2><ul>
<li>While both differs have syntax-highlighting (and the supported file-types seem to be about the same), <em>Beyond Compare</em> distinguishes between significant and insignificant (e.g. comments or whitespace) changes. It makes it much easier to see whether code or documentation has changed.</li>
<li>The intra-line diffing in <em>Beyond Compare</em> is more fine-grained and tends to highlight changes better. <em>SmartGit</em> is catching up in this regard.</li>
<li>You can re-align a diff manually using &lt;key&gt;F7&lt;/key&gt;. This is helpful if you moved code and want to compare two chunks that the standard diff no longer sees as being comparable</li></ul><h2>Merging</h2><p>I could live without the <em>Beyond Compare</em> differ, but not without the merger.</p>
<p><span style="width: 920px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3823/textmerge.png" alt=" " style="width: 920px"></span><span class="auto-content-caption">TextMerge in BeyondCompare Pro</span></span></p>
<ul>
<li>The 4-pane view shows left, base and right above as well as the target below, with the target window being editable. Each change has its own color, so you can see afterwards whether you took left, right or made manual changes.</li>
<li>The merge view includes a line-by-line differ that shows left, base, right and target lines directly above one another, with a scrollbar for longer lines.</li>
<li>The target view is color-coded to show the origin of each line of text: right, left, base or custom edited.</li>
<li><em>BeyondCompare</em> makes a smart recommendation for how to merge a given conflict that is very often exactly what you want, which means that for many conflicts, you can just confirm the recommendation.</li>
<li><em>SmartGit</em> has two separate windows for base vs. left/right and right/left vs. target. Long lines are really hard to decipher/merge in <em>SmartGit</em></li></ul><h2>Integrate <em>Beyond Compare</em> into <em>SmartGit</em></h2><p>To set up <em>SmartGit</em> to use <em>Beyond Compare</em></p>
<ol>
<li><div>Select Tools &gt; Diff Tools<ol>
<li>Click the &ldquo;Add…&rdquo; button</li>
<li>Set File Pattern to <code>*</code></li>
<li>Select &ldquo;External diff tool&rdquo;</li>
<li>Set the command to <code>C:\Program Files (x86)\Beyond Compare 4\BCompare.exe</code></li>
<li>Set the arguments to <code>&ldquo;${leftFile}&rdquo; &ldquo;${rightFile}&rdquo;</code></li></ol></div></li>
<li><div>Select Tools &gt; Conflict Solvers<ol>
<li>Select &ldquo;External Conflict Solver&rdquo;</li>
<li>Set File Pattern to <code>*</code></li>
<li>Set the command to <code>C:\Program Files (x86)\Beyond Compare 4\BCompare.exe</code></li>
<li>Set the arguments to <code>&ldquo;${leftFile}&rdquo; &ldquo;${rightFile}&rdquo; &ldquo;${baseFile}&rdquo; &ldquo;${mergedFile}&rdquo;</code></li></ol></div></li></ol><h2>Update March 11th, 2021</h2><p>I was testing the Git support in Visual Studio Code and ran into a somewhat surprising limitation. For those that use IDE Git integration without an external tool, this would be a pretty disappointing message. What do you do then?</p>
<p><span style="width: 295px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3823/vscgitcannothandletoomanychanges.png"><img src="https://www.earthli.com/data/news/attachments/entry/3823/vscgitcannothandletoomanychanges.png" alt=" " style="width: 295px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3823/vscgitcannothandletoomanychanges.png">VS Code Git overwhelmed</a></span></span></p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3823_1_body" class="footnote-number">[1]</span> In <a href="https://www.earthli.com/news/view_article.php?id=3216">Git: Managing local commits and branches</a> in December 2016 and <a href="https://www.earthli.com/news/view_article.php?id=2780">Programming in the <del>modern</del>current age</a> in February 2013</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3823_2_body" class="footnote-number">[2]</span> I am in no way affiliated with <em>SmartGit</em>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3823_3_body" class="footnote-number">[3]</span> I am in no way affiliated with <em>BeyondCompare</em>.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3822</guid>
    <title><![CDATA[Visual Studio 2019 Survey]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3822</link>
    <pubDate>Thu, 17 Oct 2019 07:38:00 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Oct 2019 07:38:00 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Visual Studio 2019 (VS) asked me this morning if I was interested in taking a survey to convey my level of satisfaction with the IDE.</p>
<p>VS displays the survey in an embedded window using IE11. [1] I captured the screen of the first thing I saw when I agreed to take the survey.</p>
<p><span style="width: 507px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3822/microsoft_visual_studio_survey.png"><img src="https://www.earthli.com/data/news/attachments/entry/3822/microsoft_visual_studio_survey.png" alt=" " style="width: 507px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3822/microsoft_visual_studio_survey.png">Visual Studio 2019 Survey error</a></span></span></p>
<p>I know it&rsquo;s the SurveyMonkey script that&rsquo;s failing, but it&rsquo;s still not an auspicious start.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3822_1_body" class="footnote-number">[1]</span> I&rsquo;d just upgraded to Windows 10 build 1903, which includes IE 11.418.18362.0. I can&rsquo;t imagine that they didn&rsquo;t test this combination.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3743</guid>
    <title><![CDATA[Svelte vs. React (overselling a framework as a revolution)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3743</link>
    <pubDate>Sun, 19 May 2019 17:15:28 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">19. May 2019 17:15:28 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Jan 2022 09:53:18 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I&rsquo;ve just read about a web framework called Svelte in the post <a href="https://svelte.dev/blog/virtual-dom-is-pure-overhead">Virtual DOM is pure overhead</a>. I think the product itself sounds interesting, but that the author uses unnecessarily misleading arguments.</p>
<p>From what I gather, Svelte is a compile-time reconciliation generator for JSX/TSX components. This pre-calculated generator applies changes to the DOM without needing a virtual DOM and without real-time diffing or reconciliation. That is, instead of having real-time calculation, with possible performance hits [1], the app benefits from having all possible state changes pre-calculated and ready to apply immediately and quickly.</p>
<p>This all sounds pretty good, I think. I&rsquo;m definitely going to take a look at the more-advanced tutorials. [2]</p>
<p>However, the author wasn&rsquo;t happy with just presenting his product, but seems to need to  mischaracterize why products like React abstracted away from the DOM in the first place. He tells us that the virtual DOM was <em>always</em> slower than manipulating the DOM. But that isn&rsquo;t the claim React makes. React helps users avoid common performance pitfalls in the <em>model of programming that it replaced</em>—it never claimed to be the final word in performance optimization.</p>
<p>It&rsquo;s clear that something like Svelte—if it can cover all the needs of an app—is faster than maintaining a virtual DOM.</p>
<p>But that product isn&rsquo;t what React replaced. React replaced products written in jQuery. React brought an asynchronous frame-based renderer to the web (something that products like WPF have had for decades). It brought us type-safe views (when used with TypeScript) and taught us about the advantages of immutable data structures.</p>
<blockquote class="quote pullquote align-right right" style="width: 7em"><div>He stands on their shoul-ders, then implies that they were idiots for not having been taller.</div></blockquote><p>The author characterizes the notion that a virtual DOM is faster as a &ldquo;meme&rdquo;. This is silly and imprecise. It is <em>true</em> that React will be more efficient than most hand-coded web sites of a typical level of complexity. jQuery sites tended to teeter and collapse under their own weight. They were unmaintainable and very difficult to optimize without nearly rewriting them. React sites, on the other hand, are modular in nature and the library includes several standard patterns to apply and measures to take to optimize these components. It&rsquo;s not always easy, but it&rsquo;s better than it was in the old days.</p>
<p>And there are solutions in React to performance issues. The users must follow patterns and use the APIs correctly. That&rsquo;s the way it is in every framework or library. Some libraries offer less leeway for users to screw up performance in the way that they <em>shape</em> their APIs.</p>
<p>Sometimes the API surface goes too much in that direction and ends up handcuffing users. That is, users can&rsquo;t write what they want to write in a way that feels natural because the pattern they prefer wouldn&rsquo;t perform well under their framework. Instead, the user must change how they think about writing apps just to use the framework. This isn&rsquo;t necessarily a bad thing, but is definitely something to consider. It&rsquo;s possible that Svelte offers all of the advantages of React with even more flexibility and less opinion.</p>
<p>React—and its companion Redux—was always about being very declarative about state and changes. There is no magic, even the reconciliation algorithm is very predictable. There are other approaches, like MobX, which users claim &ldquo;does the right thing&rdquo; with state changes, even if the user fails to <em>declare</em> dependencies as clearly as React would have required. [3] I imagine that Svelte is going in this direction as well.</p>
<p>The claim I think that Svelte is making is that users can write code that feels more natural <em>without</em> changing their paradigm to match the framework. That is, Svelte must have <em>some</em> rules for which state the compiler observes and pre-compiles, but the claim is that it&rsquo;s much more flexible and forgiving than React&rsquo;s &ldquo;straitjacket&rdquo; (my word). [4]</p>
<p>He goes on to say that React acknowledges its own slowness by giving the user control over <code>shouldComponentUpdate</code>. This is a silly argument again. It&rsquo;s arguing that React bamboozled people in 2013 by convincing them to use their framework instead of a library that the author purports is faster but that he only started in 2017.</p>
<p>There is honestly no need for this kind of bullshit. If your library offers advantages over React, describe them and let them speak for themselves. There is no need to rewrite the whole history of a product that quite clearly inspired your own, pretending that the authors of your own framework&rsquo;s inspiration are your inferiors because they failed to leap directly to the concepts outlined in your library. <em>He stands on their shoulders, then implies that they were idiots for not having been taller.</em></p>
<p>Through all of this fluff, it took to about ¾ of the way through the article to find out that Svelte generates update code at <em>build time</em>. I would have been much more intrigued had the author led with that. Now, I&rsquo;m going to be suspicious of everything about this framework because the author went to such lengths to bamboozle and oversell me. He seems to want me to think I&rsquo;ve been a fool for having used React in the first place, when his framework has been waiting for me all along, since all the way back to sometime in 2018. [5]</p>
<p>But he waits until the <em>very last paragraph</em> to explain what Svelte actually is—even though he&rsquo;s been comparing it to React the entire time. It&rsquo;s a good description:</p>
<blockquote class="quote quote-block "><div><p>&ldquo;It&rsquo;s important to understand that virtual DOM isn&rsquo;t a feature. It&rsquo;s a means to an end, the end being declarative, state-driven UI development. Virtual DOM is valuable because it allows you to build apps without thinking about state transitions, with performance that is generally good enough. That means less buggy code, and more time spent on creative tasks instead of tedious ones.</p>
<p>&ldquo;But it turns out that we can achieve a similar programming model without using virtual DOM — and that&rsquo;s where Svelte comes in.&rdquo;</p>
</div></blockquote><p>This is a much fairer characterization of the two libraries: they both base on a very similar model—one that React did a tremendous amount of legwork in establishing as an attractive approach in people&rsquo;s minds—but that Svelte goes a step further to improve the reconciliation mechanism, moving it from runtime to compile-time. Svelte&rsquo;s improvement could be a highly welcome one, but it&rsquo;s incremental, not revolutionary.</p>
<p>That&rsquo;s wonderful! But it&rsquo;s actually even <em>more wonderful</em> than his article indicated, because I actually don&rsquo;t have to learn anything to work with Svelte instead of React. I can work pretty much the same (Svelte doesn&rsquo;t have hooks [6] because it seems it doesn&rsquo;t need them) and just kind of &ldquo;drop in&rdquo; Svelte instead of React and have better performance, even in places where I&rsquo;d never noticed I might have had problems. </p>
<p>That is, with Svelte instead of React, my app will be overall faster because performance no longer suffers from <span class="quote-inline">&ldquo;death by a thousand cuts&rdquo;</span>, as the author puts it. Despite the author&rsquo;s overzealous mischaracterizations and attempts at hot-take marketing, I&rsquo;m still going to check out Svelte.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3743_1_body" class="footnote-number">[1]</span> Such performance hits are often irrelevant, as even the author admits. However, if you can choose between two frameworks, one that punishes you with bad performance and another that optimizes instead, you would choose the more forgiving one, if there are no other downsides.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3743_2_body" class="footnote-number">[2]</span> Here I&rsquo;m going to lead with my conclusion so as not to follow in the author&rsquo;s footsteps, using a style that I spend the rest of this article upbraiding.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3743_3_body" class="footnote-number">[3]</span> <p>I&rsquo;m not sure what MobX 5 is up to or what introspection it offers into the web of observables and dependencies in a more-complex application, but older versions of the library were not easy to debug when performance problems arose. From what I&rsquo;ve read from users, things have gotten much better, but I&rsquo;m still inclined to think that React&rsquo;s declarative approach suits me better—it&rsquo;s easier for me to apply well-established patterns in my own code rather than trying to figure out how to appease the MobX black box. Again, things may be different now than in earlier versions. I&rsquo;m open to taking another look at MobX.</p>
<p>I&rsquo;m also not sure how Svelte and MobX compare: MobX requires users to indicate that state is &ldquo;observable&rdquo; before it manages it, whereas I assume Svelte determines for itself which state-transitions it should track.</p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3743_4_body" class="footnote-number">[4]</span> <p>Update January 2022: In going through the tutorial available today, you&rsquo;re very quickly introduced to &lt;em&gt;reactive declarations&lt;/em&gt; to help Svelte determine which compound expressions should be &ldquo;watched&rdquo; for changes to sub-elements. That is, if you declare simple variable, any references to it in view code will be automatically updated, but if you derive another simple value from it and observe that value, it only updates when the derived value is updated directly. This is unlikely, as the derives value presumably implements an algorithm of some sort and should never be directly changed (i.e. it&rsquo;s a &lt;em&gt;calculated property&lt;/em&gt; in the parlance of other frameworks. For example, given the following code,</p>
<pre class=" "><code>let count = 0;
doubled = count * 2;</code></pre><p>Any observers (i.e. embeddings in a view) of the value of <code>doubled</code> will not be updated when <code>value</code> changes, even though the naive interpretation of a JavaScript developer would be that <em>of course it changes</em>. In order to get the desired effect, you must make it a reactive declaration with <code>$:</code>. For example,</p>
<pre class=" "><code>let count = 0;
doubled = count * 2;</code></pre><p>This is <em>perfectly fine</em>, but is an example of how the &ldquo;you don&rsquo;t have to do anything to make your JavaScript work naturally, <strong>unlike smelly React</strong>&rdquo;, is overselling the advantage. Missing &lt;em&gt;reactive declarations&lt;/em&gt; will cause an app to not work as expected just as must as a missing <code>useState()</code> does in React.</p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3743_5_body" class="footnote-number">[5]</span> It&rsquo;s hard to tell when it was released because there are 254 releases, one nearly every day and I didn&rsquo;t feel like hitting &ldquo;older&rdquo; in GitHub for 30 pages or cloning the repository just to get a better look at the log.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3743_6_body" class="footnote-number">[6]</span> <p>The author disparages hooks, saying that they are even worse for performance and linking to a tweet with the words <span class="quote-inline">&ldquo;with predictable results&rdquo;</span>. The tweet complains about atrocious performance because of constant reconciliation and rendering—but a dozen answers down is the answer: the original poster failed to tell the <code>useEffect()</code> hook on which state it relied.</p>
<p>That&rsquo;s kind of a rookie mistake—<em>in that framework</em>. [7] I understand that Svelte claims that it doesn&rsquo;t need these hints in order to be able to determine <em>at compile-time</em> when a piece of code needs to be executed because the state on which it relies has changed.</p>
<p>React is declarative and requires help from the user whereas presumably the selling point of Svelte is that this user would have wasted less time improving performance and more time focused on application logic because Svelte is smart enough to do all this for you.</p>
<p>I personally think that this sounds awesome and that it is an admirable goal, but have my doubts that Svelte doesn&rsquo;t also impose its own set of limitations on what kind of state transformations you can do that the compiler can actually detect.</p>
<p>That is, React provides an API with which callers can &ldquo;help&rdquo; the reconciliation algorithm avoid work. Svelte claims that this isn&rsquo;t necessary, but I&rsquo;m going to guess that there are rules for how sophisticated state changes can be before the Svelte compiler no longer detects them. In that case, what does Svelte do? Fall back to using a React-like virtual DOM to reconcile changes? Or just not update when the user expects? Or just fail to compile, spitting out an error indicating what the user should do to fix them issue (my personal favorite)?</p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3743_7_body" class="footnote-number">[7]</span> Update January 2022: It&rsquo;s also a mistake that IDEs will help you avoid. WebStorm issues a warning if you rely on state in an effect that you have not listed in the dependencies.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3487</guid>
    <title><![CDATA[Why use an IOC? (hint: testing)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3487</link>
    <pubDate>Mon, 08 Apr 2019 09:38:17 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Apr 2019 09:38:17 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">14. Feb 2026 17:46:44 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <h2 id="Introduction">Introduction</h2><p>Testing is any form of validation that verifies code. That includes not only structured validation using checklists, test plans, etc. but also informal testing, as when developers click their way through a UI or emit values in debugging output to  a console.</p>
<p><em>Automated testing</em> covers the topic of all regression-style tests that execute both locally and in CI. This includes unit, integration, and end-to-end tests.</p>
<p>Testing is primarily a mindset.</p>
<p>You should think of writing tests not as something you <em>have</em> to do, but rather as something you <em>want</em> to do.</p>
<ul>
<li>How else do you prove that what you wrote works?</li>
<li>What does <em>&ldquo;it works&rdquo;</em> mean?</li>
<li>Which <em>use cases</em> are covered?</li>
<li>How do you answer these questions without tests?</li>
<li>What do we mean by <em>writing</em> tests?</li></ul><h2 id="You">You&rsquo;re already testing!</h2><p>You&rsquo;re almost certainly already testing.</p>
<p>You might be clicking through the UI or emitting statements in a command-line application, but you&rsquo;re verifying your code <em>somehow</em>. I mean … you are, right? RIGHT?</p>
<p>I&rsquo;m kidding. Of course you&rsquo;re not just writing code, building it, and committing it. You&rsquo;re validating it somehow.</p>
<p>That&rsquo;s testing.</p>
<h3 id="A">A list of validations</h3><p>If you&rsquo;re really good, you might even keep a list of these validations. Once you have a list, then,</p>
<ol>
<li>You don&rsquo;t have to worry about forgetting to do them in the future</li>
<li>Even someone with no knowledge of the system can perform validation</li></ol><p>This is fine, but it&rsquo;s still a manual process. A manual process carries with it the following drawbacks:</p>
<ol>
<li>It gets quite time-consuming, especially as the list of validations grows
<li><div>You&rsquo;re highly unlikely to perform the validations often enough<ul>
<li>It&rsquo;s much easier to fix a mistake if you learn about it relatively soon after you made it</li></ul></div></li>
<li><div>You&rsquo;re also unlikely to add <em>all</em> of the validations you need<ul>
<li>Generally, you won&rsquo;t validate smaller &ldquo;facts&rdquo; and will focus on high-level stuff</li></ul></div></li>
<li>A manual validation process can&rsquo;t be run as part of CI or CD</li></ol><h3 id="Automating">Automating the list</h3><p>Automated testing means that you <em>codify</em> those validations.</p>
<blockquote class="quote abstract "><div>😒 Great! I have tests! How the heck do I <em>codify</em> them?</div></blockquote><p>Don&rsquo;t panic. Almost any code can be tested. In fact, if you can&rsquo;t get at it with a test, then you might have found an architectural problem.</p>
<p>See? Automating tests will even help you write better code!</p>
<blockquote class="quote abstract "><div>🤨 How do I get started?</div></blockquote><p>Just start somewhere. It doesn&rsquo;t matter where. Don&rsquo;t worry about coverage. Just get the feeling for writing a proof about a facet of your code. Any bit of logic can—and should—be tested.</p>
<p>What if you still don&rsquo;t know where to begin? Ask someone for help! Don&rsquo;t be shy. It&rsquo;s in everyone&rsquo;s best interest for a project to have good tests. You want everyone&rsquo;s code to have tests so you know <em>right away</em> when you&rsquo;ve broken something in a completely unrelated area. This is a good thing!</p>
<h2 id="Goals">Goals</h2><blockquote class="quote abstract "><div>🤸‍♀️ Developers should be excited to use tests to prove that their code works.</div></blockquote><h3 id="Tests">Tests should be quick and easy (maybe even fun) to write</h3><p>A project should provide support for mocking devices and external APIs, or for using test-specific datasets.</p>
<h3 id="Tests">Tests should be reasonably fast</h3><p>A reasonably fast test suite will tend to be run more often. We would like a developer to notice a broken test right after the change that broke it, preferably even before pushing it.</p>
<h3 id="Avoid">Avoid debugging tests in CI</h3><p>Tests a developer runs locally should almost always work in CI. Failing tests in CI should also fail locally.</p>
<h2 id="Guidelines">Guidelines</h2><blockquote class="quote abstract "><div>🤨 Don&rsquo;t be pedantic.</div></blockquote><p>For example,</p>
<ul>
<li><a href="https://stackoverflow.blog/2022/11/03/multiple-assertions-per-test-are-fine/">Stop requiring only one assertion per unit test: Multiple assertions are fine</a>
<li><div>Don&rsquo;t forbid mocking in integration tests and don&rsquo;t force mocking in unit tests.<ul>
<li>In fact, stop worrying about whether it&rsquo;s a unit or an integration and just <em>write useful tests</em> that <em>prove useful things</em> about your code.</li></ul></div></li>
<li><div>Don&rsquo;t get obsessed with automating <em>everything</em>.<ul>
<li>Get the low-hanging fruit first, and leave the rest to manual testing.</li>
<li>See where you stand.</li>
<li>If you haven&rsquo;t automated enough, iterate until done. 🔄</li></ul></div></ul><h3 id="Tests">Tests should be useful</h3><p>We never want anyone in a team to get the impression that we&rsquo;re writing tests just to write tests. We write tests because they help us write better code and because it feels good to be able to prove that something that was working continues to work. You should feel more efficient and productive and feel like you&rsquo;re producing higher-quality code.</p>
<ul>
<li>Tests should confirm use cases</li>
<li>Tests should prove something about your code that you think is worth proving.</li>
<li>Tests should confirm behavior that either is how the code <em>currently</em> works or how it <em>should</em> work.</li>
<li>Tests should help you write better code from the get-go.</li>
<li>Every bug that you need to fix is de-facto a use case that needs a test.</li></ul><h3 id="Code">Code Coverage &amp; Reviews</h3><p>How do you know when there are &ldquo;enough&rdquo; automated tests?</p>
<p>Don&rsquo;t get distracted by trying to achieve a specific coverage percentage. The most important thing is that the major use cases are covered.</p>
<p>If software is stable and there is &ldquo;only&rdquo; 40% test-coverage, then maybe there is a lot of code that rarely or never gets used? In that case, you might want to think about removing code that you don&rsquo;t need rather than to waste time writing tests for code that never runs.</p>
<p>New code, though, should always have automated tests. A <strong>code reviewer</strong> should verify that new functionality is being tested.</p>
<h2 id="Types">Types of tests</h2><dl><dt>Unit</dt>
<dd><div class=" "><p>Cover a single unit, mocking away other dependencies where needed. </p>
<p>Useful for verifying simple logic like calculated properties or verifying the results of service methods with given inputs</p>
</div></dd>
<dt>Integration</dt>
<dd><div class=" "><p>Cover multiple units, possibly mocking unwanted dependencies.</p>
<p>Useful for verifying behavior of units in composition, as they will be used in the end product. The goal is to cover as much as possible without resorting to more costly end-to-end tests</p>
</div></dd>
<dt>End-to-End</dt>
<dd><div class=" "><p>Also called <em>UI Tests</em>, these tests verify the entire stack for actual customer use cases.</p>
<p>Very useful, but generally require more maintenance as they tend to be more fragile. Essential for verifying UI behavior not reflected in a programmatic model. Can work with snapshots (e.g. error label is in red)</p>
</div></dd>
</dl><h2 id="Approach">Approach</h2><p>The article <a href="https://kentcdodds.com/blog/write-tests">Write tests. Not too many. Mostly integration.</a> describes a pragmatic approach quite well. Instead of the classic &ldquo;testing pyramid&rdquo;, it suggests a &ldquo;testing trophy&rdquo;.</p>
<p>!<a href="https://www.earthli.com/.attachments/image-6b9cafdf-0bac-4155-bb8f-363a92822bc3.png =300x">image.png</a></p>
<p>This style of development has the following aims:</p>
<ol>
<li>Verify as much as possible <em>statically</em>, with linting and analyzers</li>
<li>Make <em>integration tests</em> cheaper because they prove more about your system than <em>unit tests</em></li>
<li>Prove as much as possible outside of <em>end-to-end tests</em> because they&rsquo;re expensive and brittle</li></ol><h2 id="Analysis">Analysis</h2><blockquote class="quote abstract "><div>Remember that everything you use has to work both locally and in CI.</div></blockquote><h3 id="Static">Static-checking</h3><p>A project should include analyzers and techniques so that the compiler helps make many tests unnecessary. For example, if you know that a parameter or result can never be <code>null</code>, then you can avoid a whole slew of tests.</p>
<p>Developers should only spend time writing tests that verify semantic aspects that can&rsquo;t be proven by the compiler.</p>
<h4 id="Null">Null-reference analysis in .NET</h4><p>The .NET world provides many, many analyzers and tools to verify code quality. One of the most important things a project can do is to improve null-checking. The best way to do this is to upgrade to C# 8 or higher and enable <a href="https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references">null-reference analysis</a>. The <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/configure-language-version">default language for .NET Framework is going to stay C# 7.3</a>, but <br>
you can <a href="https://www.infoq.com/articles/CSharp-8-Framework/">enable null-reference analysis for .NET Framework</a> quite easily.</p>
<p>Another option is to use the <a href="https://www.nuget.org/packages/JetBrains.Annotations/">JetBrains Annotations NuGet package</a>, which provides attributes to indicate whether parameters or results are nullable.</p>
<p>The preferred way, though, is to use the by-now standard nullability-checking available in .NET.</p>
<p>Doing neither is not a good option, as it will be very difficult to avoid null-reference exceptions.</p>
<h3 id="Unit">Unit-testing</h3><p>Unit tests are very useful for validating <em>requirements</em> and <em>invariants</em> about your code.</p>
<p>These are the easiest tests to write and will generally be the first ones that you will write.</p>
<p>A requirement or an invariant may be specified in the story itself, but it can be anything that you know about the code that&rsquo;s important. It&rsquo;s up to the developer and the reviewer(s) to determine which tests are necessary. It gets easier with experience—and it doesn&rsquo;t take long to get enough experience so that it&rsquo;s no longer so intimidating.</p>
<h4 id="Unit">Unit-testing example</h4><p>Just as a quick example in .NET, consider the following code,</p>
<pre class=" "><code>public bool IsDiagnosticModeRunning
{
    get =&gt; _isDiagnosticModeRunning;
    set
    {
        _isDiagnosticModeRunning = value;
        _statusManager.InstrumentState = value ? InstrumentState.DiagnosticMode : InstrumentState.Ready;
    }
}</code></pre><p>Here we see a relatively simple property with a getter and a setter. However, we also see that there is an invariant in the implementation: that the <code>_statusManager.InstrumentState</code> is synced with it.</p>
<p>Using many of the <a href="#tools-and-techniques">techniques described below</a>, we could write the following test:</p>
<pre class=" "><code>[DataRow(true, InstrumentState.DiagnosticMode)]
[DataRow(false, InstrumentState.Ready)]
[TestMethod]
public void TestIsDiagnosticModeRunning(bool running, InstrumentState expectedInstrumentState)
{
    var locator = CreateLocator();
    var instrumentControlService = locator.GetInstance&lt;IInstrumentControlService&gt;();
    var statusManager = locator.GetInstance&lt;IStatusManager&gt;();

    Assert.AreNotEqual(expectedInstrumentState, statusManager.InstrumentState);

    instrumentControlService.IsDiagnosticModeRunning = running;

    Assert.AreEqual(expectedInstrumentState, statusManager.InstrumentState);
}</code></pre><p>Here, we&rsquo;re using MSTest to create a parameterized test that,</p>
<ul>
<li>creates the IOC</li>
<li>gets the two relevant services from it</li>
<li>Verifies that the state is not already set to the expected state (in which case the test would succeed even if the tested code doesn&rsquo;t do anything)</li>
<li>Sets the property to a given value</li>
<li>Verifies that the state is correct for that value</li></ul><p>We now have code that validates two <em>facts</em> about the system. Should something change where these facts are no longer true, the tests will fail, giving the developer a chance to analyze the situation.</p>
<ul>
<li>Was the change inadvertent or deliberate?</li>
<li>Are the facts still correct? Does the test need to be updated?</li></ul><p>If you&rsquo;re addressing a bug-fix, though, you might be able to <em>prove</em> that you&rsquo;ve fixed the bug with a unit test, but it&rsquo;s also likely that you&rsquo;ll have to write an integration test instead.</p>
<h3 id="Integration">Integration-testing</h3><p>Unit tests have their place, but they are far too emphasized in the testing pyramid. The testing pyramid comes from a time when writing integration tests was much more difficult than it (theoretically) is today.</p>
<p>The &ldquo;theoretically&rdquo; above means that the ability to write integration tests as efficiently as unit tests is contingent on a project offering proper tools and support.</p>
<p>One common complaint about integration tests vis à vis unit tests is that they run more slowly. Another is that they take longer to develop. Ideally, a project provides support to counteract both of these tendencies.</p>
<p>To this end, then, a project should offer base and support classes that make common integration tests easy to set up and quick to execute:</p>
<ul>
<li>Interacting with a database</li>
<li>Setting up a known database schema</li>
<li>Getting to a clean dataset</li>
<li>[Mocking]() the database</li>
<li>Mocking other external dependencies in a project (e.g. loading configuration from an endpoint, sending emails, sending modifications to endpoints)</li></ul><p>There are many different ways to solve this problem, each with tradeoffs. For example, a project can load dependencies in Docker containers, either created and started manually (see <a href="https://josef.codes/testing-your-asp-net-core-application-using-a-real-database/">Testing your ASP.NET Core application − using a real database</a>) or even dynamically with a tool like the <a href="https://github.com/testcontainers/testcontainers-dotnet">Testcontainers NuGet package</a>.</p>
<h3 id="Comparing">Comparing Unit and Integration tests</h3><p>A drawback to unit tests is that, while they can test an individual component well, it&rsquo;s really the big picture that we want to test. We want to test scenarios that correspond to actual use cases rather than covering theoretical call stacks. It&rsquo;s not that the second part <em>isn&rsquo;t</em> important, but that it&rsquo;s not <em>as</em> important.</p>
<p>Given limited time and resources, we would prefer to have integration tests that also cover a lot of the same code paths that we would have covered with unit tests, rather than to have unit tests, but few to no integration tests.</p>
<p>This, however, leads directly to…</p>
<p>The advantage of a unit test over an integration test is that when it fails, it&rsquo;s obvious which code failed. An integration test, by its very nature, involves multiple components. When it fails, it might not be obvious which sub-component caused the error.</p>
<p>If you find that you have integration tests failing and it takes a while to figure out what went wrong, then that&rsquo;s a sign that you should bolster your test suite with more unit tests.</p>
<p>Once an integration test fails <em>and</em> one or more unit tests fail, then you have the best of both worlds: you&rsquo;ve been made aware that you&rsquo;ve broken a use case (integration test), but you also know which precise behavior is no longer working as before (unit test).</p>
<h2 id="Tools">Tools and Techniques</h2><h3 id="Tests">Tests are Code</h3><p>Test code is just as important as product code. Use all of the same techniques to improve code quality in test code as you would in product code. Clean coding, good variable names, avoid copy/paste coding—all of it applies just as much to tests.</p>
<p>There are two main differences:</p>
<ul>
<li>You don&rsquo;t need to document tests.</li>
<li>You don&rsquo;t have to write tests for tests. 😀</li></ul><h3 id="Writing">Writing testable code</h3><p>This is a big, big topic, of course. There are a few guidelines that make it easier to write tests—or to avoid having to write tests at all.</p>
<p>As noted above, code that can be validated by the compiler (static analysis) doesn&rsquo;t need tests. E.g. you don&rsquo;t have to write a test for how your code behaves when passed a <code>null</code> parameter if you just <em>forbid it</em>. Likewise, you don&rsquo;t have to re-verify that types work as they should in statically typed languages. We can trust the compiler.</p>
<p>Here are a handful of tips.</p>
<ul>
<li>Prefer composition to inheritance</li>
<li>A functional programming style is very testable</li>
<li>An IOC Container is very helpful</li>
<li>Avoid nullable properties, results, and parameters</li>
<li>Avoid mutable data</li>
<li>Interfaces are much easier to fake or mock; use those wherever you can</li></ul><p>See the following articles for more ideas.</p>
<ul>
<li><a href="https://github.com/mvonballmo/CSharpHandbook/blob/master/4_design.md">C# Handbook − Chapter 4: Design</a> (2017)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=2996">Questions to consider when designing APIs: Part I</a> (2014)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=2997">Questions to consider when designing APIs: Part II</a> (2014)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3487">Why use an IOC? (hint: testing)</a> (2019)</li></ul><h3 id="Parameterized">Parameterized Tests</h3><p>Investigate your testing library to learn how to write multiple tests without having to write a lot of code. In the MSTests framework, you can use <code>DataRow</code> to parameterize a test. In NUnit, <code>TestCase</code> does the same thing, and <code>Value</code> allows you to provide parameter values for a list of tests that are the Cartesian product of all values.</p>
<h3 id="Mocking">Mocking/Faking</h3><p>Use mocks or fakes to exclude a subsystem from a test. What would you want to exclude? While you will want to make some tests that include database access or REST API calls, there are a lot of tests where you&rsquo;re proving a fact that doesn&rsquo;t depend on these results.</p>
<h4 id="Focus">Focus on what you&rsquo;re testing</h4><p>For example, suppose a component reads its configuration from the database by default. A test of that component may simply want to see how it reacts with a given input to a given method. Where the configuration came from is irrelevant to that particular test. In that case, you could mock away the component that loads the configuration from the database and instead use a fake object that just provides some standard values.</p>
<h4 id="Test">Test error conditions</h4><p>Another possibility is to fake an external service to see how your code reacts when the service returns an error or an ambiguous response. Without mocks, how would you test how your code reacts when a REST endpoint returns 503 or 404? Without a mock, how would you force the purely external endpoint to give a certain code? You really can&rsquo;t. With a mock, though, you can replace the service and return a 404 response for a specific test. This is quite a powerful technique.</p>
<h4 id="How">How to fake?</h4><p>As noted above, it&rsquo;s much, much easier to use fake objects if you&rsquo;ve consistently used interfaces. You can just create your own implementation of the interface whose standard implementation you want to replace, give it a fake implementation (e.g. returning <code>false</code> and empty string and <code>null</code> for methods and properties), and then use that class as the implementation.</p>
<h4 id="Faking">Faking/mocking libraries</h4><p>If you have interfaces that perform a single task (single-responsibility principle), then it doesn&rsquo;t take too much effort to write the fake object by hand. However, it&rsquo;s much easier to use a library to create fake objects—and there are other benefits as well, like tracking which methods were called with which parameters. You can assert on this data collected by the fake object.</p>
<p>For .NET, a great library for faking objects is <a href="https://fakeiteasy.github.io/">FakeItEasy</a>.</p>
<p>With a fake object, you can indicate which values to return for a given set of parameters without too much effort. Similarly, you can use the same API to query how often these methods have been called. This allows you to verify, for example, that a call to a REST service <em>would have been made</em>. This is a powerful way of proving facts about your code without having to actually interact with external services.</p>
<h4 id="An">An example</h4><p>The following code configures a fake object for <code>ITestUnitConfigurationService</code> that returns default data for all properties, except for <code>Configuration</code> and <code>GetTestUnitParameterValues()</code>, which are configured to return specific data.</p>
<pre class=" "><code>private static ITestUnitConfigurationService CreateFakeTestUnitConfigurationService()
{
    var result = A.Fake&lt;ITestUnitConfigurationService&gt;();

    var testUnitParameters = CreateTestUnitParameters();
    var testUnitConfiguration = new TestUnitConfiguration(testUnitParameters);

    A.CallTo(() =&gt; result.Configuration).Returns(testUnitConfiguration);

    var testUnitParameterValues = CreateTestUnitParameterValues();

    A.CallTo(() =&gt; result.GetTestUnitParameterValues()).Returns(testUnitParameterValues);

    return result;
}</code></pre><p>In the test, we could get this fake object back out of the IOC (for example) and then verify that certain methods have been called the expected number of times.</p>
<pre class=" "><code>var testUnitConfigurationService = locator.GetInstance&lt;ITestUnitConfigurationService&gt;();

A.CallTo(() =&gt; testUnitConfigurationService.Configuration).MustHaveHappenedOnceExactly();
A.CallTo(() =&gt; testUnitConfigurationService.GetTestUnitParameterValues()).MustHaveHappenedOnceExactly();</code></pre><h3 id="Snapshot">Snapshot-testing</h3><p>You can avoid writing a ton of assertions and a ton of tests with snapshot testing.</p>
<p>For example, imagine you have a test that generates a particular view model. You want to verify 30 different parts of this complex model.</p>
<p>You <em>could</em> navigate the data structure, asserting the 30 values individually.</p>
<p>That would be pretty tedious, though, and lead to fragile and hard-to-maintain testing code.</p>
<p>Instead, you could emit that structure as text and save it as a <em>snapshot</em> in the repository. If a future code change leads to a different snapshot, the test fails and the developer that caused the failure would have to approve the new snapshot (if it&rsquo;s an expected or innocuous change) or fix the code (if it was inadvertent and wrong).</p>
<p>The upside is that large swaths of assertions are reduced to a simple snapshot assertion. The downside is that the test might break more often for spurious reasons. Generally, you can avoid these spurious reasons by being judicious about how your format the snapshot,</p>
<ul>
<li>Avoid timestamps or data that changes over time</li>
<li>Avoid using output methods that are too likely to change over time</li></ul><p>See the documentation for the <a href="https://swisslife-oss.github.io/snapshooter/">Snapshooter NuGet package</a>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3666</guid>
    <title><![CDATA[Using Unity, Collab and Git]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3666</link>
    <pubDate>Tue, 22 Jan 2019 19:47:58 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">22. Jan 2019 19:47:58 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>If you&rsquo;re familiar with the topic, you might be recoiling in horror. It would be unclear, though, whether you&rsquo;re recoiling from the &ldquo;using Collab&rdquo; part or the &ldquo;using Collab with Git&rdquo; part.</p>
<p>Neither is as straightforward as I&rsquo;d hoped.</p>
<blockquote class="quote abstract "><div><p><abbr title="too long; didn't read">tl;dr</abbr>: If you have to use Collab with Unity, but want to back it up with Git, disable <code>core.autocrlf</code> [1] and add <code>* -text</code> to the <code>.gitattributes</code>.</p>
</div></blockquote><h2>Collab&rsquo;s Drawbacks</h2><p>Collab is the source-control system integrated into the Unity IDE. </p>
<p>It was built for designers to be able to do some version control, but not much more. Even with its limited scope, it&rsquo;s a poor tool.</p>
<h3>The functionality horror</h3><ul>
<li>The system does not ever show you any differences, neither in the web UI nor the local UI, neither for uncommitted nor committed files</li>
<li>Some changes cannot be reverted. No reason is given.</li>
<li>You can only delete new files from the file system.</li>
<li>There is no support for renaming</li>
<li>Reverting to a known commit has worked for me <em>exactly once</em> out of about 10 tries. The operation fails with an <span class="error">Error occurred</span> and no further information. If you really get stuck, your only choice is to restore the entire workspace by re-cloning/re-downloading it.</li>
<li>Conflict resolution is poorly supported, although it works better than expected (it integrates with <em>BeyondCompare</em>, thank goodness).</li></ul><h3>The usability horror</h3><ul>
<li><div>The UI only lets you commit all changed files at once.<ul>
<li>There is no notion of &ldquo;commits&rdquo;.</li>
<li>You can’t commit individual files or chunks.</li>
<li>There is no staging area.</li>
<li>You can&rsquo;t exclude files. </li>
<li>You can ignore them completely, but that doesn&rsquo;t help.</li></ul></div></li>
<li>The UI is only accessible via mouse from the menu bar.</li>
<li>You can <em>sometimes</em> revert folders (sometimes you can&rsquo;t, again with an <span class="error">Error occurred</span> message), but you can&rsquo;t revert arbitrary groups of files.</li>
<li>The UI is almost entirely in that custom drop-down menu.</li>
<li>You can scroll through your changed files, but you can&rsquo;t expand the menu to show more files at once.</li>
<li>You can show a commit history, but there are no diffs. None.</li>
<li>There aren&rsquo;t even any diffs in the web version of the UI, which is marginally better, but read-only.</li></ul><h2>Pair Git with Collab</h2><p>This is really dangerous, <em>especially</em> with Unity projects. There is so much in a Unity project without a proper &ldquo;Undo&rdquo; that you very often want to return to a known good version.</p>
<p>So what can we do to improve this situation? We would like to use Git <em>instead of</em> Collab.</p>
<p>However, we have to respect the capabilities and know-how of the designers on our team, who don&rsquo;t know how to use Git.</p>
<p>On our current project, there&rsquo;s no time to train everyone on Git—and they already know how to use Collab and don&rsquo;t feel tremendously limited by it. </p>
<p>Remember, <em>any</em> source control is better than <em>no</em> source control. The designers are regularly backing up their work now. In its defense, Collab is definitely better than nothing (or using a file-share or some other weak form of code-sharing).</p>
<p>Instead, those of us who know Git are using Git <em>alongside</em> Collab.</p>
<h2>It <em>kind of</em> works…</h2><p>We started naively, with all of our default settings in Git. Our workflow was:</p>
<ol>
<li>Pull in Unity/Collab</li>
<li>Fetch from Git/Rebase to head (we actually just use &ldquo;pull with rebase&rdquo;)</li></ol><p>Unfortunately, we would often end up with a ton of files marked as changed in Collab. These were always line-ending differences. As mentioned above, Collab is not a good tool for reverting changes.</p>
<p>The project has time constraints—it&rsquo;s a prototype for a conference, with a hard deadline—so, despite its limitations, we reverted in Collab and updated Git with the line-endings that Collab expected.</p>
<p>We limped along like this for a bit, but with two developers on Git/Collab on Windows and one designer on Collab on Mac, we were spending too much time &ldquo;fixing up&rdquo; files. The benefit of having Git was outweighed by the problems it caused with Collab.</p>
<h2>Know Your Enemy</h2><p>So we investigated what was really going on. The following screenshots show that Collab doesn&rsquo;t seem to care about line-endings. They&rsquo;re all over the map.</p>
<p><span style="width: 450px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3666/collab_vs_git.png"><img src="https://www.earthli.com/data/news/attachments/entry/3666/collab_vs_git.png" alt=" " style="width: 450px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3666/collab_vs_git.png">JSON file with mixed line-endings</a></span></span></p>
<p><span style="width: 376px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3666/collab_vs_git_dot_cs_file.png"><img src="https://www.earthli.com/data/news/attachments/entry/3666/collab_vs_git_dot_cs_file.png" alt=" " style="width: 376px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3666/collab_vs_git_dot_cs_file.png">CS file with CRLF line-endings</a></span></span></p>
<p><span style="width: 353px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3666/collab_vs_git_dot_unity_file.png"><img src="https://www.earthli.com/data/news/attachments/entry/3666/collab_vs_git_dot_unity_file.png" alt=" " style="width: 353px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3666/collab_vs_git_dot_unity_file.png">.unity file with LF line-endings</a></span></span></p>
<h2>Configuring Git</h2><p>Git, on the other hand, <em>really</em> cares about line-endings. By default, Git will transform the line-endings <em>in files that it considers to be text files</em> (this part is important later) to the line-ending of the local platform.</p>
<p>In the repository, all text files are LF-only. If you work on MacOS or Linux, line-endings in the workspace are unchanged; if you work on Windows, Git changes all of these line-endings to CRLF on checkout—and back to LF on commit.</p>
<p>Our first &ldquo;fix&rdquo; was to turn off the <code>core.autocrlf</code> option in the local Git repository.</p>
<pre class=" "><code>git config –local core.autocrlf false</code></pre><p>We thought this would fix everything since now Git was no longer transforming our line-endings on commit and checkout.</p>
<p>This turned out to be only part of the problem, though. As you can see above, the text files in the repository have an arbitrary mix of line-endings already. Even with the feature turned off, Git <em>was still  normalizing line-endings to LF</em> on Windows.</p>
<p>The only thing we&rsquo;d changed so far is to stop using the CRLF instead of LF. Any time we <code>git reset</code>, for example, the line-endings in our workspace would still end up being different than what was in Git or Collab.</p>
<h2>Git: Stop doing stuff</h2><p>What we really want is for Git to stop changing any line-endings at all.</p>
<p>This isn&rsquo;t part of the command-line configuration, though. Instead, you have to set up <code>.gitattributes</code>. Git has default settings that determine which files it treats as which types. We wanted to adjust these default settings by telling Git that, in this repository, it should treat <em>no files as text</em>.</p>
<p>Once we knew this, it&rsquo;s quite easy to configure. Simply add a <code>.gitattributes</code> file to the root of the repository, with the following contents:</p>
<pre class=" "><code>* -text</code></pre><p>This translates to &ldquo;do not treat any file as text&rdquo; (i.e. match all files; disable text-handling).</p>
<h2>Conclusion</h2><p>With these settings, the two developers were able to reset their workspaces and both Git and Collab were happy. Collab is still a sub-par tool, but we can now work with designers and still have Git to allow the developers to use a better workflow.</p>
<p>The designers using only Collab were completely unaffected by our changes.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3666_1_body" class="footnote-number">[1]</span> <em>Technically</em>, I don&rsquo;t think you have to change the <code>autocrlf</code> setting. Turning off text-handling in Git should suffice. However, I haven&rsquo;t tested with this feature left on and, due to time-constraints, am not going to risk it.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3670</guid>
    <title><![CDATA[Finding deep assembly dependencies]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3670</link>
    <pubDate>Mon, 21 Jan 2019 20:26:52 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Jan 2019 20:26:52 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Quino contains a Sandbox in the main solution that lets us test a lot of the Quino subsystems in real-world conditions. The Sandbox has several application targets:</p>
<ul>
<li>WPF</li>
<li>Winform</li>
<li>Remote Data Server</li>
<li>WebAPI Server</li>
<li>Console</li></ul><p>The targets that connect directly to a database (e.g. WPF, Winform) were using the PostgreSql driver by default. I wanted to configure all Sandbox applications to be easily configurable to run with SqlServer.</p>
<h2>Just add the driver, right?</h2><p>This is pretty straightforward for a Quino application. The driver can be selected directly in the application (directly linking the corresponding assembly) or it can be configured externally.</p>
<p>Naturally, if the Sandbox loads the driver from configuration, some mechanism still has to make sure that the required data-driver assemblies are available.</p>
<p>The PostgreSql driver was in the output folder. This was expected, since that driver works. The SqlServer was not in the output folder. This was also expected, since that driver had never been used.</p>
<p>I checked the direct dependencies of the Sandbox Winform application, but it didn&rsquo;t include the PostgreSql driver. That&rsquo;s not really good, as I would like both SqlServer and PostgreSql to be configured in the same way. As it stood, though, I would be referencing SqlServer directly and PostgreSql would continue to show up <em>by magic</em>.</p>
<p>Before doing anything else, I was going to have to find out why PostgreSql was included in the output folder.</p>
<p>I needed to figure out assembly dependencies.</p>
<h2>Visual Studio?</h2><p>My natural inclination was to reach for NDepend, but I thought maybe I&rsquo;d see what the other tools have to offer first.</p>
<p>Does Visual Studio include anything that might help? The &ldquo;Project Dependencies&rdquo; shows only assemblies on which a project is dependent. I wanted to find assemblies that were dependent on PostgreSql. I have the Enterprise version of Visual Studio and I seem to recall an &ldquo;Architecture&rdquo; menu, but I <a href="https://developercommunity.visualstudio.com/content/problem/25007/architecture-menu-is-not-showing-for-vs-enterprise.html">discovered that these tools are no longer installed by default</a>.</p>
<p>According to the VS support team in that link, you have to install the &ldquo;Visual Studio extension development&rdquo; workload in the Visual Studio installer. In this package, the &ldquo;Architecture and analysis tools&rdquo; feature is available, but not included by default.</p>
<p>Hovering this feature shows a tooltip indicating that it contains &ldquo;Code Map, Live Dependency Validation and Code Clone detection&rdquo;. The &ldquo;Live Dependency Validation&rdquo; sounds like it might do what I want, but it also sounds quite heavyweight and somewhat intrusive, as described in <a href="https://blogs.msdn.microsoft.com/devops/2016/11/30/live-dependency-validation-in-visual-studio-2017/">this blog from the end of 2016</a> (<cite><a href="http://blogs.msdn.microsoft.com/">MSDN</a></cite>). Instead of further modifying my VS installation (and possibly slowing it down), I decided to try another tool.</p>
<h2>ReSharper?</h2><p>What about ReSharper? For a while now, it&rsquo;s included project-dependency graphs and hierarchies. Try as I might, I couldn&rsquo;t get the tools to show me the transitive dependency on PostgreSql that Sandbox Winform was pulling in from <em>somewhere</em>. The hierarchy view is live and quick, but it doesn&rsquo;t show <em>all</em> transitive usages.</p>
<p><span style="width: 340px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3670/0531_resharper_missing_dependencies.png" alt=" " style="width: 340px"></span><span class="auto-content-caption">ReSharper missing dependencies</span></span></p>
<p>The graph view is nicely rendered, but shows dependencies by default instead of dependencies <em>and</em> usages. At any rate, the Sandbox wasn&rsquo;t showing up as a transitive user of PostgreSql.</p>
<p><span style="width: 556px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3670/0531_resharper_missing_dependencies_graph.png"><img src="https://www.earthli.com/data/news/attachments/entry/3670/0531_resharper_missing_dependencies_graph.png" alt=" " style="width: 556px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3670/0531_resharper_missing_dependencies_graph.png">ReSharper missing dependencies Graph</a></span></span></p>
<p>I didn&rsquo;t believe ReSharper at this point because <em>something</em> was causing the data driver to be copied to the output folder.</p>
<h2>NDepend to the rescue </h2><p>So, as expected, I turned to NDepend. I took a few seconds to run an analysis and then right-clicked the PostgreSql data-driver project to select <code>NDepend =&gt; Select Assemblies… =&gt; That are Using Me (Directly or Indirectly)</code> to show the following query and results.</p>
<p><span style="width: 602px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3670/0531_ndepend_dependency_query_and_list.png"><img src="https://www.earthli.com/data/news/attachments/entry/3670/0531_ndepend_dependency_query_and_list.png" alt=" " style="width: 602px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3670/0531_ndepend_dependency_query_and_list.png">Ndepend Dependency Query and List</a></span></span></p>
<p>Bingo. <code>Sandbox.Model</code> is indirectly referencing the PostgreSql data driver, via a transitive-dependency chain of 4 assemblies. Can I see which assemblies they are? Of course I can: this kind of information is best shown on a graph, so you can show a graph of any query results by clicking <code>Export to Graph</code> to show the graph below.</p>
<p><span style="width: 637px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3670/0531_ndepend_dependency_graph.png"><img src="https://www.earthli.com/data/news/attachments/entry/3670/0531_ndepend_dependency_graph.png" alt=" " style="width: 637px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3670/0531_ndepend_dependency_graph.png">Ndepend Dependency Graph</a></span></span></p>
<p>Now I can finally see that the <code>SandboxModel</code> pulls in the <code>Quino.Testing.Models.Generated</code> (to use the <code>BaseTypes</code> module) which, in turn, has a reference to <code>Quino.Tests.Base</code> which, of course, includes the PostgreSql driver because that&rsquo;s the default testing driver for Quino tests.</p>
<p>Now that I know how the reference is coming in, I can fix the problem. Here I&rsquo;m on my own: I have to solve this problem without NDepend. But at least NDepend was able to show me exactly what I have to fix (unlike VS or ReSharper).</p>
<p>I ended up moving the test-fixture base classes from <code>Quino.Testing.Models.Generated</code> into a new assembly called <code>Quino.Testing.Models.Fixtures</code>. The latter assembly still depends on <code>Quino.Tests.Base</code> and thus the PostgreSql data driver, but it&rsquo;s now possible to reference the Quino testing models without transitively referencing the PostgreSql data driver.</p>
<p>A quick re-analysis with NDepend and I can see that the same query now shows a clean view: only testing code and testing assemblies reference the PostgreSql driver.</p>
<p><span style="width: 426px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3670/0531_ndepend_dependency_query_and_list_all_cleaned_up.png"><img src="https://www.earthli.com/data/news/attachments/entry/3670/0531_ndepend_dependency_query_and_list_all_cleaned_up.png" alt=" " style="width: 426px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3670/0531_ndepend_dependency_query_and_list_all_cleaned_up.png">Ndepend Dependency Query and List (cleaned up)</a></span></span></p>
<h2>Finishing up</h2><p>And now to finish my original task! I ran the Winform Sandbox application with the PostgreSql driver configured and was greeted with an error message that the driver could not be loaded. I now had parity between PostgreSql and SqlServer.</p>
<p>The fix? Obviously, make sure that the drivers are available by referencing them directly from any Sandbox application that needs to connect to a database. This was the obvious solution from the beginning, but we had to quickly fix a problem with dependencies first. Why? Because we hate hacking. :-)</p>
<p>Two quick references added, one build and I was able to connect to both SQL Server and PostgreSql.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3681</guid>
    <title><![CDATA[QQL: A Query Language for Quino]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3681</link>
    <pubDate>Sun, 20 Jan 2019 22:37:35 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 22:37:35 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Jan 2019 10:00:49 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In late 2011 and early 2012, Encodo designed a querying language for Quino. Quino has an ORM that, combined with .NET Linq provides a powerful querying interface for developers. QQL is a DSL that brings this power to non-developers.</p>
<p>QQL never made it to implementation—only specification. In the meantime, the world moved on and we have common, generic querying APIs like OData. The time for QQL is past, but the specification is still an interesting artifact, in its own right.</p>
<p>Who knows? Maybe we&rsquo;ll get around to implementing some of it, at some point.</p>
<p>At any rate, you can download the specification from <a href="https://encodo.com/media/2726/encodo-qql-handbook.pdf">Encodo</a> or <a href="https://www.earthli.com/data/news/attachments/entry/3681/encodo-qql-handbook.pdf">here at earthli</a>.</p>
<p>The following excerpts should give you an idea of what you&rsquo;re in for, should you download and read the 80-page document.</p>
<h2>Details</h2><p>The TOC lists the following top-level chapters:</p>
<ol>
<li>Introduction</li>
<li>Examples</li>
<li>Context &amp; Scopes</li>
<li>Standard Queries</li>
<li>Grouping Queries</li>
<li>Evaluation</li>
<li>Syntax</li>
<li>Data Types and Operators</li>
<li>Libraries</li>
<li>Best Practices</li>
<li>Implementation Details</li>
<li>Future Enhancements</li></ol><p>From the abstract in the document:</p>
<blockquote class="quote quote-block "><div>&ldquo;The Quino Query Language (QQL) defines a syntax and semantics for formulating data requests against hierarchical data structures. It is easy to read and learn both for those familiar with SQL and non-programmers with a certain capacity for abstract thinking (i.e. power users). Learning only a few basic rules is enough to allow a user to quickly determine which data will be returned by all but the more complex queries. As with any other language, more complex concepts result in more complex texts, but the syntax of QQL limits these cases.&rdquo;</div></blockquote><p>From the overview:</p>
<blockquote class="quote quote-block "><div>&ldquo;QQL defines a syntax and semantics for writing queries against hierarchical data structures. A query describes a set of data by choosing an initial context in the data and specifying which data are to be returned and how the results are to be organized. An execution engine generates this result by applying the query to the data.&rdquo;</div></blockquote><h2>Examples</h2><h3>Standard Projections</h3><p>The follow is from chapter 2.1, &ldquo;Simple Standard Query&rdquo;:</p>
<blockquote class="quote quote-block "><div><p>The following query returns the first and last name of all active people as well as their 10 most recent time entries, reverse-sorted first by last name, then by first name.</p>
<pre class=" "><code>Person
{
  select
  {
    FirstName; LastName;
    Sample:= TimeEntries { orderby Date desc; limit 10 }
  }
  where Active
  orderby
  {
    LastName desc;
    FirstName desc;
  }
}</code></pre></div></blockquote><p>In chapter 2, there are also &ldquo;2.2 Intermediate Standard Query&rdquo; and &ldquo;2.3 Complex Standard Query&rdquo; examples.</p>
<h3>Grouping Projections</h3><p>The following is from chapter 2.4, &ldquo;Simple Grouping Query&rdquo;:</p>
<blockquote class="quote quote-block "><div><p>The following query groups active people by last name and returns the age of the youngest person and the maximum contracts for each last name. Results are ordered by the maximum contracts for each group and then by last name.</p>
<pre class=" "><code>group Person
{
  groupby LastName;
  select
  {
    default;
    Age:= (Now − BirthDate.Min).Year;
    MaxContracts:= Contracts.Count.Max
  }
  where Active;
  orderby
  {
    MaxContracts desc;
    LastName desc;
  }
}</code></pre></div></blockquote><p>In chapter 2, there are also &ldquo;2.5 Complex Grouping Query&rdquo;, &ldquo;2.6 Standard Query with Grouping Query&rdquo; and &ldquo;2.7 Nested Grouping Queries&rdquo; examples.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3682</guid>
    <title><![CDATA[Breaking Changes in C#]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3682</link>
    <pubDate>Sun, 20 Jan 2019 22:19:02 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 22:19:02 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 22:20:10 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Due to the nature of the language, there are some API changes that almost inevitably lead to breaking changes in C#.</p>
<h2>Change constructor parameters</h2><p>While you can easily make another constructor, marking the old one(s) as obsolete, if you use an IOC that allows only a single public constructor, you&rsquo;re forced to either </p>
<ul>
<li>remove the obsolete constructor or </li>
<li>mark the obsolete constructor as <code>protected</code>.</li></ul><p>In either case, the user has a compile error.</p>
<h2>Virtual methods/Interfaces</h2><p>There are several known issues with introducing new methods or changing existing methods on an existing interface. For many of these situations, there are relatively smooth upgrade paths.</p>
<p>I encountered a situation recently that I thought worth mentioning. I wanted to introduce a new <em>overload</em> on an existing type.</p>
<p>Suppose you have the following method:</p>
<pre class=" "><code>bool TryGetValue&lt;T&gt;(
  out T value,
  TKey key = default(TKey),
  [CanBeNull] ILogger logger = null
);</code></pre><p>We would like to remove the <code>logger</code> parameter. So we deprecate the method above and declare the new method.</p>
<pre class=" "><code>bool TryGetValue&lt;T&gt;(
  out T value,
  TKey key = default(TKey)
);</code></pre><p>Now the compiler/ReSharper notifies you that there will be an ambiguity if a caller does not pass a <code>logger</code>. How to resolve this? Well, we can just remove the  default value for that parameter in the obsolete method.</p>
<pre class=" "><code>bool TryGetValue&lt;T&gt;(
  out T value,
  TKey key = default(TKey),
  [CanBeNull] ILogger logger
);</code></pre><p>But now you&rsquo;ve got another problem: The parameter <code>logger</code> cannot come after the <code>key</code> parameter because it doesn&rsquo;t have a default value.</p>
<p>So, now you&rsquo;d have to <em>move</em> the <code>logger</code> parameter in front of the key parameter. This will cause a compile error in clients, which is what we were trying to avoid in the first place.</p>
<p>In this case, we have a couple of sub-optimal options.</p>
<dl><dt class="field">Multiple Releases</dt>
<dd><div class=" "><p>Use a different name for the new API (e.g. <code>TryGetValueEx</code> à la Windows) in the next major version, then switch the name back in the version <em>after that</em> and finally remove the obsolete member in <em>yet another</em> version.</p>
<p>That is,</p>
<ul>
<li>in version <em>n</em>, <code>TryGetValue</code> (with logger) is obsolete and users are told to use <code>TryGetValueEx</code> (no logger)</li>
<li>in version <em>n+1</em>, <code>TryGetValueEx</code> (no logger) is obsolete and users are told to use <code>TryGetValue</code> (no logger)</li>
<li>in version <em>n+2</em>, we finally remove <code>TryGetValueEx</code>.</li></ul><p>This is a lot of work and requires three upgrades to accomplish. You really need to stay on the ball in order to get this kind of change integrated and it takes a non-trivial amount of time and effort.</p>
<p>We generally don&rsquo;t use this method, as our customers are developers and can deal with a compile error or two, especially when it&rsquo;s noted in the release notes <em>and</em> the workaround is fairly obvious (e.g. the <code>logger</code> parameter is just no longer required).</p>
</div></dd>
<dt class="field">Remove instead of deprecating</dt>
<dd>Accept that there will be a compile error and soften the landing as much as possible for customers by noting it in the release notes.</dd>
</dl>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3680</guid>
    <title><![CDATA[Version numbers in .NET Projects]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3680</link>
    <pubDate>Sun, 20 Jan 2019 22:00:30 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 22:00:30 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Any software product should have a version number. This article will answer the following questions about how Encodo works with them.</p>
<ul>
<li>How do we choose a version number?</li>
<li>What parts does a version number have?</li>
<li>What do these parts mean?</li>
<li>How do different stakeholders interpret the number?</li>
<li>What conventions exist for choosing numbers?</li>
<li>Who chooses and sets these parts?</li></ul><h2>Stakeholders</h2><p>In decreasing order of expected expertise,</p>
<ul>
<li><strong>Developers</strong>: Writes the software; may *change* version numbers</li>
<li><strong>Testers</strong>: Tests the software; highly interested in version numbers that make sense</li>
<li><strong>End users</strong>: Uses the software as a black box</li></ul><p>The intended audience of this document is *developers*.</p>
<h2>Definitions and Assumptions</h2><ul>
<li>Build servers, not developer desktops, produce artifacts</li>
<li>The source-control system is Git</li>
<li>The <code>quino</code> command-line tool is installed on all machines. This tool can *read* and *write* version numbers for any .NET solution, regardless of which of the many version-numbering methods a given solution actually uses.</li>
<li>A *software library* is a package or product that has a <em>developer</em> as an *end user*
<li><div>A *breaking change* in a software library causes one of the following<ul>
<li>a build error</li>
<li>an API to behave differently in a way that cannot be justified as a bug fix</li></ul></div></ul><p> </p>
<h2>Semantic versions</h2><p>Encodo uses semantic versions. This scheme has a strict ordering that allows you to determine which version is &ldquo;newer&rdquo;. It indicates pre-releases (e.g. alphas, betas, rcs) with a &ldquo;minus&rdquo;, as shown below.</p>
<p>Version numbers come in two flavors:</p>
<ul>
<li>Official releases: <code>[Major].[Minor].[Patch].[Build]</code></li>
<li>Pre-releases: <code>[Major].[Minor].[Patch]-[Label][Build]</code></li></ul><p>See Microsoft&rsquo;s <a href="https://docs.microsoft.com/en-us/nuget/reference/package-versioning">NuGet Package Version Reference</a> for more information.</p>
<h3>Examples</h3><ul>
<li><code>0.9.0-alpha34</code>: A pre-release of 0.9.0</li>
<li><code>0.9.0-beta48</code>: A pre-release of 0.9.0</li>
<li><code>0.9.0.67</code>: An official release of 0.9.0</li>
<li><code>1.0.0-rc512</code>: A pre-release of 1.0.0</li>
<li><code>1.0.0.523</code>: An official release of 1.0.0</li></ul><p>The numbers are strictly ordered. The first three *parts* indicate the &ldquo;main&rdquo; version. The final *part* counts strictly upward.</p>
<h2>Parts</h2><p>The following list describes each of the parts and explains what to expect when it changes.</p>
<h3>Build</h3><ul>
<li>Identifies the build task that produced the artifact</li>
<li>Strictly increasing</li></ul><h3>Label</h3><ul>
<li>An arbitrary designation for the &ldquo;type&rdquo; of pre-release</li></ul><h3>Patch</h3><ul>
<li>Introduces bug fixes but no features or API changes</li>
<li>May introduce obsolete members</li>
<li>May *not* introduce breaking changes</li></ul><p>This part is also known as &ldquo;Maintenance&rdquo; (see <a href="https://en.wikipedia.org/wiki/Software&lt;i">versioning&rdquo;&gt;Software versioning</a> on Wikipedia).</p>
<h3>Minor</h3><ul>
<li>Introduces new features that extend existing functionality</li>
<li>May include bug fixes</li>
<li>May cause minor breaking changes</li>
<li>May introduce obsolete members that cause compile errors</li>
<li>Workarounds must be documented in release notes or obsolete messages</li></ul><h3>Major</h3><ul>
<li>Introduces major new features</li>
<li>Introduces breaking changes that require considerable effort to integrate</li>
<li>Introduces a new data or protocol format that requires migration</li></ul><h2>Conventions</h2><h3>Uniqueness for official releases</h3><p>There will only ever be one artifact of an official release corresponding to a given &ldquo;main&rdquo; version number.</p>
<p>That is, if <code>1.0.0.523</code> exists, then there will never be a <code>1.0.0.524</code>. This is due the fact that the build number (e.g. 524) is purely for auditing.</p>
<p>For example, suppose your software uses a NuGet package with version <code>1.0.0.523</code>. NuGet will <em>not</em> offer to upgrade to  <code>1.0.0.524</code>.</p>
<h3>Pre-release Labels</h3><p>There are no restrictions on the labels for pre-releases. However, it&rsquo;s recommended to use one of the following:</p>
<ul>
<li><code>alpha</code></li>
<li><code>beta</code></li>
<li><code>rc</code></li></ul><p>Be aware that if you choose a different label, then it is ordered <em>alphabetically</em> relative to the other pre-releases.</p>
<p>For example, if you were to use the label <code>pre-release</code> to produce the version <code>0.9.0-prealpha21</code>, then that version is considered to be <em>higher</em> than <code>0.0.0-alpha34</code>. A tool like NuGet will not see the latter version as an upgrade.</p>
<h3>Release branches</h3><p>The name of a release branch should be the major version of that release. E.g. <code>release/1</code> for version 1.x.x.x.</p>
<h3>Pre-release branches</h3><p>The name of a pre-release branch should be of the form <code>feature/[label]</code> where <code>[label]</code> is one of the labels recommended above. It&rsquo;s also OK to use a personal branch to create a pre-release build, as in <code>mvb/[label]</code>.</p>
<h2>Setting the base version</h2><p>A developer uses the <code>quino</code> tool to set the version.</p>
<p>For example, to set the version to 1.0.1, execute the following:</p>
<pre class=" "><code>quino fix -v 1.0.1.0</code></pre><p>The tool will have updated the version number in all relevant files.</p>
<h2>Calculating final version</h2><p>The build server calculates a release&rsquo;s version number as follows,</p>
<ul>
<li><strong>major</strong>: Taken from solution</li>
<li><strong>minor</strong>: Taken from solution</li>
<li><strong>maintenance</strong>: Read from solution</li>
<li><strong>label</strong>: Taken from the Git branch (see below for details)</li>
<li><strong>build</strong>: Provided by the build server</li></ul><h3>Git Branches</h3><p>The name of the Git branch determines which kind of release to produce.</p>
<ul>
<li>If the name of the branch matches the glob <code>**/release/*</code>, then it&rsquo;s an official release</li>
<li>Everything else is a pre-release</li></ul><p>For example,</p>
<ul>
<li><code>origin/release/1</code></li>
<li><code>origin/production/release/new</code></li>
<li><code>origin/release/</code></li>
<li><code>release/1</code></li>
<li><code>production/release/new</code></li>
<li><code>release/</code></li></ul><p>The name of the branch doesn&rsquo;t influence the version number since an official release doesn&rsquo;t have a label.</p>
<h3>Pre-release labels</h3><p>The label is taken from the last part of the branch name.</p>
<p>For example,</p>
<ul>
<li><code>origin/feature/beta</code> yields <code>beta</code></li>
<li><code>origin/feature/rc</code> yields <code>rc</code></li>
<li><code>origin/mvb/rc</code> yields <code>rc</code></li></ul><p>The following algorithm ensures that the label can be part of a valid semantic version.</p>
<ul>
<li>Remove invalid characters</li>
<li>Append an <code>X</code> after a trailing digit</li>
<li>Use <code>X</code> if the label is empty (or becomes empty after having removed invalid characters)</li></ul><p>For example,</p>
<ul>
<li><code>origin/feature/rc1</code> yields <code>rc1X</code></li>
<li><code>origin/feature/linuxcompat</code> yields <code>linuxcompat</code></li>
<li><code>origin/feature/12</code> yields <code>X</code></li></ul><h3>Examples</h3><p>Assume that,</p>
<ul>
<li>the version number in the solution is 0.9.0.0</li>
<li>the build counter on the build server is at 522</li></ul><p>Then,</p>
<ul>
<li>Deploying from branch <code>origin/release/1</code> produces artifacts with version number <code>0.9.0.522</code></li>
<li>Deploying from branch <code>origin/feature/rc</code> produces artifacts with version number <code>0.9.0-rc522</code></li></ul><h2>Release Workflow</h2><p>The following are very concise guides for how to produce artifacts.</p>
<h3>Pre-release</h3><ul>
<li>Ensure you are on a non-release branch (e.g. <code>feature/rc</code>, <code>master</code>)</li>
<li>Verify or set the base version (e.g. <code>quino fix -v 1.0.2.0</code></li>
<li>Push any changes to Git</li>
<li>Execute the &ldquo;deploy&rdquo; task against your branch on the build server</li></ul><h3>Release</h3><ul>
<li>Ensure you are on a release branch (e.g. <code>release/1</code>)</li>
<li>Verify or set the base version (e.g. <code>quino fix -v 1.0.2.0`</code>)</li>
<li>Push any changes to Git</li>
<li>Execute the &ldquo;deploy&rdquo; task against your branch on the build server</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3679</guid>
    <title><![CDATA[v6.0: .NET Standard &amp; Authentication]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3679</link>
    <pubDate>Sun, 20 Jan 2019 21:59:55 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 21:59:55 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">Note: this article was originally published at <a href="https://encodo.com/latest/developer-blogs/v60-net-standard-authentication/">Encodo.com</a> at the end of October, 2018.</small></p>
<p><hr></p>
<p>The summary below describes major new features, items of note and breaking changes.</p>
<ul>
<li><a href="https://files.encodo.ch/index.php/apps/files/?dir=%2FQuino%2Freleases%2F6.0.0">Download the artifacts</a>
<li><div>See the full list of issues<ul>
<li><a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=23321">Quino-Standard 6.0.0</a></li>
<li><a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=24907">Quino-WebAPI 6.0.0</a></li>
<li><a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=24914">Quino-Windows 6.0.0</a></li></ul></div></ul><p><em>The links above require a login.</em></p>
<h2>Overview</h2><p>At long last, Quino enters the world of .NET Standard and .NET Core. Libraries target .NET Standard 2.0, which means they can all be used with any .NET runtime on any .NET platform (e.g. Mac and Linux). Sample applications and testing assemblies target .NET Core 2.0. Tools like <code>quinogenerate</code> and <code>quinofix</code> target .NET Core 2.1 to take advantage of the standardized external tool-support there.</p>
<p>Furthermore, the Windows, Winform and WPF projects have moved to a separate solution/repository called <code>Quino-Windows</code>.</p>
<p><code>Quino-Standard</code> is the core on which both <code>Quino-Windows</code> and <code>Quino-WebAPI</code> build.</p>
<ul>
<li>All core assemblies target .NET Standard 2.0.</li>
<li>All assemblies in <code>Quino-Windows</code> target .NET Framework 4.6.2 because that&rsquo;s the first framework that can interact with .NET Standard (and under which Windows-specific code runs).</li>
<li>All assemblies in <code>Quino-WebAPI</code> currently target .NET Framework 4.6.2. We plan on targeting .NET Core in an upcoming version (tentatively planned for v7).</li></ul><h2>Highlights</h2><ul>
<li>Target .NET Standard and .NET Core from Quino-Standard</li>
<li>Split Windows-specific code to Quino-Windows</li>
<li>Improve authentication API to use <code>IIdentity</code> everywhere (deprecating <code>ICredentials</code> and <code>IUserCredentials</code>).</li></ul><h2>Breaking Changes</h2><p>6.0 is a pretty major break from the 5.x release. Although almost all assembly names have stayed the same, we had to move some types around to accommodate targeting .NET Standard with 85% of Quino&rsquo;s code.</p>
<h3>APIs</h3><p>We&rsquo;ve tried to support existing code wherever possible, but some compile errors will be unavoidable (e.g. from namespace changes or missing references). In many cases, R#/VS should be able to help repair these errors.</p>
<p>These are the breaking changes that are currently known.</p>
<ul>
<li>Moved <code>IRunSettings</code> and <code>RunMode</code> from <code>Encodo.Application</code> to <code>Encodo.Core</code>.</li></ul><h3>References</h3><p>Any .NET Framework executable that uses assemblies targeting .NET Standard must reference .NET Standard itself. The compiler (<code>MSBuild</code>) in Visual Studio will alert you to add a reference to .NET Standard using NuGet. This applies not just to Winform executables, but also to any unit-test assemblies.</p>
<h3>Tools</h3><p>One piece that has changed significantly is the tool support formerly provided with <code>Quino.Utils</code>. As of version 6, Quino no longer uses <code>NAnt</code>, instead providing <code>dotnet</code>-compatible tools that you can install using common .NET commands. Currently, Quino supports:</p>
<ul>
<li><code>dotnet quinofix</code></li>
<li><code>dotnet quinogenerate</code></li>
<li><code>dotnet quinopack</code></li></ul><p>Please see the <a href="https://docs.encodo.ch/quino/master/docs/tools/tools.html">tools documentation</a> for more information on how to install and use the new tools.</p>
<p>The standalone Winforms-based tools are in the <code>Quino-Windows</code> download, in the <code>Tools.zip</code> archive.</p>
<ul>
<li><code>Quino.Migrator</code></li>
<li><code>Quino.PasswordEncryptor</code></li></ul><p><code>Quino.Utils</code> is no longer supported as a NuGet package.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3673</guid>
    <title><![CDATA[Learning Quino: a roadmap for documentation and tutorials]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3673</link>
    <pubDate>Sun, 20 Jan 2019 21:59:29 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 21:59:29 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">Note: this article was originally published at <a href="https://encodo.com/latest/developer-blogs/learning-quino-a-roadmap-for-documentation-and-tutorials/">Encodo.com</a> in July, 2018.</small></p>
<p><hr></p>
<p>In recent articles, we outlined <a href="https://www.earthli.com/latest/developer-blogs/quinos-roadmap-to-net-standard-and-net-core/">a roadmap to .NET Standard and .NET Core</a> and <a href="https://encodo.com/latest/developer-blogs/delivering-quino-a-roadmap-for-deployment/">a roadmap for deployment and debugging</a>. These two roadmaps taken together illustrate our plans to extend as much of Quino as possible to other platforms (.NET Standard/Core) and to make development with Quino as convenient as possible (getting/upgrading/debugging).</p>
<p>To round it off, we&rsquo;ve made good progress on another vital piece of any framework: <strong>documentation</strong>.</p>
<h2>Introducing docs.encodo.ch</h2><p>We recently set up a new server to host <a href="https://docs.encodo.ch">Quino documentation</a>. There, you can find documentation for current releases. Going forward, we&rsquo;ll also retain documentation for any past releases.</p>
<p>We&rsquo;re generating our documentation with <a href="https://dotnet.github.io/docfx/">DocFX</a>, which is the same system that powers Microsoft&rsquo;s own documentation web site. We&rsquo;ve integrated documentation-generation as a build step in Quino&rsquo;s nightly build on TeamCity, so it&rsquo;s updated every night (Zürich time) [1].</p>
<p>The documentation includes <a href="https://docs.encodo.ch/quino/master/docs/readme.html">conceptual documentation</a> which provides an overview/tutorials/FAQ for basic concepts in Quino. The <a href="https://docs.encodo.ch/quino/master/docs/_api/Encodo.App.Application.html">API Reference</a> includes comprehensive documentation about the types and methods available in Quino.</p>
<h2>Next Steps</h2><p>While we&rsquo;re happy to announce that we have publicly available documentation for Quino, we&rsquo;re aware that we&rsquo;ve got work to do. The next steps are:</p>
<ul>
<li>Improve and extend conceptual documentation (<a href="https://secure.encodo.ch/jira/browse/QNO-3452">QNO-3452</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3453">QNO-3453</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3985">QNO-3985</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5282">QNO-5282</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5283">QNO-5283</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5284">QNO-5284</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5286">QNO-5286</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5391">QNO-5391</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5528">QNO-5528</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5544">QNO-5544</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5562">QNO-5562</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5813">QNO-5813</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5912">QNO-5912</a> )</li>
<li>Improve the search for API documentation to include members as well as types (<a href="https://secure.encodo.ch/jira/browse/QNO-5934">QNO-5934</a>)</li>
<li>Integrate documentation for the newly created/separated Quino-WebApi repository (<a href="https://secure.encodo.ch/jira/browse/IT-1293">IT-1293</a>)</li>
<li>Retain documentation for the soon-to-be-split-off Quino-Windows repository (<a href="https://secure.encodo.ch/jira/browse/QNO-5904">QNO-5904</a>)</li></ul><p>Even though there&rsquo;s still work to do, this is a big step in the right direction. We&rsquo;re very happy to have found DocFX, which is a very comprehensive, fast and nice-looking solution to generating documentation for .NET code. [2]</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3673_1_body" class="footnote-number">[1]</span> If the build succeeds, naturally. :-)</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3673_2_body" class="footnote-number">[2]</span> We used to use Sandcastle many years ago, but dropped support because it took forever to generate documentation, required its own solution file, didn&rsquo;t look very nice out-of-the-box, wasn&rsquo;t so easily customized and didn&rsquo;t have a very good search (which also didn&rsquo;t work without an IIS running it).</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3672</guid>
    <title><![CDATA[Delivering Quino: a roadmap for deployment]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3672</link>
    <pubDate>Sun, 20 Jan 2019 21:58:53 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 21:58:53 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">Note: this article was originally published at <a href="https://encodo.com/latest/developer-blogs/delivering-quino-a-roadmap-for-deployment/">Encodo.com</a> in July, 2018.</small></p>
<p><hr></p>
<p>In a recent article, we outlined <a href="https://dev.earthli.com/news/view_article.php?id=3671">a roadmap to .NET Standard and .NET Core</a>. We&rsquo;ve made really good progress on that front: we have a branch of Quino-Standard that targets .NET Standard for class libraries and .NET Core for utilities and tests. So far, we&rsquo;ve smoke-tested these packages with Quino-WebApi. Our next steps there are to convert Quino-WebApi to .NET Standard and .NET Core as well. We&rsquo;ll let you know when it&rsquo;s ready, but progress is steady and promising.</p>
<p>With so much progress on several fronts, we want to address how we get Quino from our servers to our customers and users.</p>
<h2>Getting Quino</h2><p>Currently, we provide access to a private fileshare for customers. They download the NuGet packages for the release they want. They copy these to a local folder and bind it as a NuGet source for their installations.</p>
<p>In order to make a build available to customers, we have to <em>publish</em> that build by deploying it and copying the files to our file share. This process has been streamlined considerably so that it really just involves telling our CI server (TeamCity) to deploy a new release (official or pre-). From there, we download the ZIP and copy it to the fileshare.</p>
<p>Encodo developers don&rsquo;t have to use the fileshare because we can pull packages directly from TeamCity as soon as they&rsquo;re available. This is a much more comfortable experience and feels much more like working with nuget.org directly.</p>
<h2>Debugging Quino</h2><p>The debugging story with external code in .NET is much better than it used to be (spoiler: it was almost impossible, even with Microsoft sources), but it&rsquo;s not as smooth as it should be. This is mostly because NuGet started out as a packaging mechanism for <em>binary</em> dependencies published by vendors with proprietary/commerical products. It&rsquo;s only in recent year(s) that packages are predominantly open-source.</p>
<p>In fact, debugging with third-party sources—even without NuGet involved—has never been easy with .NET/Visual Studio.</p>
<p>Currently, all Quino developers must download the sources separately (also available from TeamCity or the file-share) in order to use source-level debugging.</p>
<p>Binding these sources to the debugger is relatively straightforward but cumbersome. Binding these sources to ReSharper is even more cumbersome and somewhat unreliable, to boot. I&rsquo;ve created the issue <a href="https://youtrack.jetbrains.com/issue/RSRP-470463">Add an option to let the user search for external sources explicitly (as with the VS debugger) when navigating</a> in the hopes that this will improve in a future version. JetBrains has already fixed one of my issues in this are (<a href="https://youtrack.jetbrains.com/issue/RSRP-459740">Navigate to interface/enum/non-method symbol in Nuget-package assembly does not use external sources</a>), so I&rsquo;m hopeful that they&rsquo;ll appreciate this suggestion, as well.</p>
<p>The use case I cited in the issue above is,</p>
<p>Developers using NuGet packages that include sources or for which sources are available want to set breakpoints in third-party source code. Ideally, a developer would be able to use R# to navigate through these sources (e.g. via F12) to drill down into the code and set a breakpoint that will actually be triggered in the debugger.</p>
<p>As it is, navigation in these sources is so spotty that you often end up in decompiled code and are forced to use the file-explorer in Windows to find the file and then drag/drop it to Visual Studio where you can set a breakpoint that will work.</p>
<p>The gist of the solution I propose is to have R# <em>ask the user</em> where missing sources are <em>before decompiling</em> (as the Visual Studio debugger does).</p>
<h2>Nuget Protocol v3 to the rescue?</h2><p>There is hope on the horizon, though: Nuget is going to address the debugging/symbols/sources workflow in an upcoming release. The overview is at <a href="https://github.com/NuGet/Home/wiki/NuGet-Package-Debugging-&amp;-Symbols-Improvements">NuGet Package Debugging &amp; Symbols Improvements</a> and the issue is <a href="https://github.com/NuGet/Home/issues/6104">Improve NuGet package debugging and symbols experience</a>.</p>
<p>Once this feature lands, Visual Studio will offer seamless support for debugging packages hosted on nuget.org. Since we&rsquo;re using TeamCity to host our packages, we need JetBrains to <a href="https://youtrack.jetbrains.com/issue/TW-47289">Add support for NuGet Server API v3</a> [1] in order to benefit from the improved experience. Currently, our customers are out of luck even if JetBrains releases simultaneously (because our TeamCity is not available publicly).</p>
<h2>Quino goes public?</h2><p>I&rsquo;ve created an issue for Quino, <a href="https://secure.encodo.ch/jira/browse/QNO-5953">Make Quino Nuget packages available publicly</a> to track our progress in providing Quino packages to our customers in a more convenient way that also benefits from improvements to the debugging workflow with Nuget Packages.</p>
<p>If we published Quino packages to NuGet (or MyGet, which allows private packages), then we would have the benefit of the latest Nuget protocol/improvements for both ourselves and our customers as soon as it&rsquo;s available. Alternatively, we could also proxy our TeamCity feed publicly. We&rsquo;re still considering our options there.</p>
<p>As you can see, we&rsquo;re always thinking about the development experience for both our developers and our customers. We&rsquo;re fine-tuning on several fronts to make developing and debugging with Quino a seamless experience for all developers on all platforms.</p>
<p>We&rsquo;ll keep you posted.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3672_1_body" class="footnote-number">[1]</span> This issue has been closed and released with R# in the latest versions.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3674</guid>
    <title><![CDATA[Removing unwanted references to .NET 4.6.1 from web applications]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3674</link>
    <pubDate>Sun, 20 Jan 2019 21:55:36 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 21:55:36 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">Note: this article was originally published at <a href="https://encodo.com/latest/developer-blogs/removing-unwanted-references-to-net-461-from-web-applications/">Encodo.com</a> in July, 2018.</small></p>
<p><hr></p>
<p>The title is a bit specific for this blog post, but that&rsquo;s the gist of it: we ended up with a bunch of references to an in-between version of .NET (4.6.1) that was falsely advertising itself as a more optimal candidate for satisfying 4.6.2 dependencies. This is a known issue; there are several links to MS GitHub issues below.</p>
<p>In this blog, I will discuss direct vs. transient dependencies as well as internal vs. runtime dependencies.</p>
<h2><abbr title="too long; didn't read">tl;dr</abbr></h2><p>If you&rsquo;ve run into problems with an application targeted to .NET Framework 4.6.2 that does not compile on certain machines, it&rsquo;s possible that the binding redirects Visual Studio has generated for you use versions of assemblies that aren&rsquo;t installed anywhere but on a machine with Visual Studio installed.</p>
<p>How I solved this issue:</p>
<ul>
<li>Remove the <code>C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\</code> directory</li>
<li>Remove all System* binding redirects</li>
<li>Clean out all <code>bin/</code> and <code>obj/</code> folders</li>
<li>Delete the <code>.vs</code> folder (may not be strictly necessary)</li>
<li>Build in Visual Studio</li>
<li>Observe that a few binding-redirect warnings appear</li>
<li>Double-click them to re-add the binding redirects, but this time <em>to actual 4.6.2 versions</em> (you may need to add <code>&lt;AutoGenerateBindingRedirects&gt;true&lt;/AutoGenerateBindingRedirects&gt;</code> to your project)</li>
<li>Rebuild and verify that you have no more warnings</li></ul><p>The product should now run locally and on other machines.</p>
<p>For more details, background and the story of how I ran into and solved this problem, read on.</p>
<p><small class="notes">Note: I published a recent article, <a href="https://dev.earthli.com/news/view_article.php?id=3637">.NET Tips and Resources</a>, containing a link to a video by Immo Landwerth, in which says <span class="quote-inline">&ldquo;If you want to be compatible with .NET Core 1.5 or lower, then you can use .NET Framework 4.6.1. For .NET Standard compatibility, you should definitely use .NET Framework 4.7.2 instead.&rdquo;</span> That will probably fix the problem as well. Moving to .NET Core will also fix the problem, as all binding is handled automatically there.</small></p>
<h2>Building Software</h2><p>What do we mean when we say that we &ldquo;build&rdquo; an application?</p>
<p>Building is the process of taking a set of <em>inputs</em> and producing an artifact <em>targeted</em> at a certain runtime. Some of these inputs are <em>included directly</em> while others are <em>linked externally</em>.</p>
<ul>
<li>Examples of direct inputs are the binary artifacts produced from the source code that comprises your application</li>
<li>Examples of external inputs are OS components and runtime environments</li></ul><p>The machine does exactly what you tell it to, so it&rsquo;s up to you to make sure that your instructions are as precise as possible. However, you also want your application to be flexible so that it can run on as wide an array of environments as possible.</p>
<p>Your source code consists of <em>declarations</em>. We&rsquo;ve generally got the direct inputs under control. The code compiles and produces artifacts as expected. It&rsquo;s the external-input declarations where things go awry.</p>
<p>What kind of external inputs does our application have?</p>
<ul>
<li>System dependencies in the runtime target (assemblies like System.Runtime, System.Data, etc.), each with a minimum version</li>
<li>Third-party dependencies pulled via NuGet, each with a minimum version</li></ul><p>How is this stitched together to produce the application that is executed?</p>
<ul>
<li>The output folder contains our application, our own libraries and the assemblies from NuGet dependencies</li>
<li>All other dependencies (e.g. system dependencies) are pulled from the <em>environment</em></li></ul><p>The NuGet dependencies are resolved at <em>build time</em>. All resources are pulled and added to the release on the build machine. There are no run-time decisions to make about which versions of which assemblies to use.</p>
<p>Dependencies come in two flavors:</p>
<ul>
<li><strong>Direct</strong>: A reference in the project itself</li>
<li><strong>Transient</strong>: A <em>direct</em> reference inherited from another <em>direct</em> or <em>transient</em> reference</li></ul><p>It is with the transient references that we run into issues. The following situations can occur:</p>
<ul>
<li>A transient dependency is referenced one or more times with the same version. This is no problem, as the builder simply uses that version or substitutes a newer version if that version is no longer available (rare, but possible)</li>
<li>A transient dependency is referenced in different versions. In this case, the builder tries to substitute a single version for all requirements. This generally works OK since most dependencies require a given version <em>or higher</em>. It may be that one or another library cannot work with all newer versions, but this is also rare. In this case, the top-level assembly (the application) must include a hint (an assembly-binding redirect) that indicates that the substitution is OK. More on these below.</li>
<li>A transient dependency requires a lower version than the version that is directly referenced. This is also not a problem, as the transient dependency is satisfied by the direct dependency with the higher version. In this case, the top-level application must also include an assembly-binding redirect to allow the substitution without warning.</li>
<li>A transient dependency requires a higher version than the version that is directly referenced. This is an error (no longer just a warning) that must be solved by either downgrading the dependency that leads to the problematic transient dependency <em>or</em> upgrading the direct dependency. Generally, the application will upgrade the direct dependency.</li></ul><h2>Assembly-Binding Redirects</h2><p>An application generally includes an <code>app.config</code> (desktop applications or services) or <code>web.config</code> XML file that includes a section where binding redirects are listed. A binding redirect indicates the range of versions that can be mapped (or <em>redirected</em>) to a certain fixed version (which is generally also included as a direct dependency).</p>
<p>A redirect looks like this (a more-complete form is further below):</p>
<pre class=" "><code>&lt;bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/&gt;</code></pre><p>When the direct dependency is updated, the binding redirect must be updated as well (generally by updating the maximum version number in the range and the version number of the target of the redirect). NuGet does this for you when you&rsquo;re using <code>package.config</code>. If you&rsquo;re using Package References, you must update these manually. This situation is currently not so good, as it increases the likelihood that your binding redirects remain too restrictive.</p>
<h2>NuGet Packages</h2><p>NuGet packages are resolved at <em>build time</em>. These dependencies are delivered as part of the deployment. If they could be resolved on the build machine, then they are unlikely to cause issues on the deployment machine.</p>
<h2>System Dependencies</h2><p>Where the trouble comes in is with dependencies that are resolved at <em>execution time</em> rather than <em>build time</em>. The .NET Framework assemblies are resolved in this manner. That is, an application that targets .NET Framework expects certain versions of certain assemblies to be available on the deployment machine.</p>
<p>We mentioned above that the algorithm sometimes chooses the desired version <em>or higher</em>. This is not the case for dependencies that are in the assembly-binding redirects. Adding an explicit redirect <em>locks</em> the version that can be used.</p>
<p>This is generally a <em>good idea</em> as it increases the likelihood that the application will only run in a deployment environment that is extremely close or identical to the development, building or testing environment.</p>
<h2>Aside: Other Bundling Strategies</h2><p>How can we avoid these pesky run-time dependencies? There are several ways that people have come up with, in increasing order of flexibility:</p>
<ul>
<li>Deliver hardware and software together. This is common in industrial applications and used to be much more common for businesses, as well. Nearly bulletproof. If it worked in the factory, it will work for the customer.</li>
<li>Deliver a VM (virtual machine) as your application. This includes the entire execution environment right down to the hardware. Safe, but inefficient.</li>
<li>Use a container (e.g. Docker) to deliver a description of the execution environment. The image is built to match the declaration. This is also quite stable and can avoid many of the substitution errors outlined above. If components are outdated, the machine fails to start and the definition must first be updated (and, presumably, tested). This type of deployment is getting more reliable but is also overkill for many applications.</li>
<li>Deliver the runtime with the application instead of <em>describing</em> the runtime you&rsquo;d like to have. Targeting .NET Core instead of .NET Framework includes the runtime. This seems like a nice alternative and it&rsquo;s not surprising that Microsoft went in this direction with .NET Core. It&rsquo;s a good solution to the external-dependency issues outlined above.</li></ul><p>To sum up:</p>
<ul>
<li>A VM delivers the OS, runtime and application.</li>
<li>A Container delivers a description of the OS and runtime as well as the application itself.</li>
<li>.NET Core includes the runtime and application and is OS-agnostic (within reason).</li>
<li>.NET Framework includes only the application and some directives on the remaining components to obtain from the runtime environment.</li></ul><p>Our application targets .NET Framework (for now). We&rsquo;re looking into .NET Core, but aren&rsquo;t ready to take that step yet.</p>
<h2>Where can the deployment go wrong?</h2><p>To sum up the information from above, problems arise when the build machine contains components that are not available on the deployment machine.</p>
<p>How can this happen? Won&rsquo;t the deployment machine just use the best match for the directives included in the build?</p>
<p>Ordinarily, it would. However, if you remember our discussion of assembly-binding redirects above, those are set in stone. What if you included binding redirects that <em>required</em> versions of system dependencies that are only available on your build machine … or even your developer machine?</p>
<h2>Special Tip for Web Applications</h2><p>We actually discovered an issue in our deployment because the API server was running, but the Authentication server was not. The Authentication server was crashing because it couldn&rsquo;t find the runtime it needed in order to <em>compile</em> its Razor views (it has ASP.Net MVC components). We only discovered this issue on the deployment server because the views were only ever compiled on-the-fly.</p>
<p>To catch these errors earlier in the deployment process, you can enable pre-compiling views in release mode so that the build server will fail to compile instead of a producing a build that will sometimes fail to run.</p>
<p>Add the <code>&lt;MvcBuildViews&gt;true&lt;/MvcBuildViews&gt;</code> to any MVC projects in the <code>PropertyGroup</code> for the release build, as shown in the example below:</p>
<pre class=" "><code>&lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "&gt;
  &lt;DebugType&gt;pdbonly&lt;/DebugType&gt;
  &lt;Optimize&gt;true&lt;/Optimize&gt;
  &lt;OutputPath&gt;bin&lt;/OutputPath&gt;
  &lt;DefineConstants&gt;TRACE&lt;/DefineConstants&gt;
  &lt;ErrorReport&gt;prompt&lt;/ErrorReport&gt;
  &lt;WarningLevel&gt;4&lt;/WarningLevel&gt;
  &lt;LangVersion&gt;6&lt;/LangVersion&gt;
  &lt;MvcBuildViews&gt;true&lt;/MvcBuildViews&gt;
&lt;/PropertyGroup&gt;</code></pre><h2>How do I create a redirect?</h2><p>We mentioned above that NuGet is capable of updating these redirects when the target version changes. An example is shown below. As you can see, they&rsquo;re not very easy to write:</p>
<pre class=" "><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;configuration&gt;
  &lt;runtime&gt;
    &lt;assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"&gt;
      &lt;dependentAssembly&gt;
        &lt;assemblyIdentity
          name="System.Reflection.Extensions" 
          publicKeyToken="B03F5F7F11D50A3A"
          culture="neutral"/&gt;
        &lt;bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/&gt;
      &lt;/dependentAssembly&gt;
      &lt;!– Other bindings… –&gt;
    &lt;/assemblyBinding&gt;
  &lt;/runtime&gt;
&lt;/configuration&gt;</code></pre><p>Most bindings are created automatically when MSBuild emits a warning that one would be required in order to avoid potential runtime errors. If you compile with MSBuild in Visual Studio, the warning indicates that you can double-click the warning to automatically generate a binding.</p>
<p>If the warning doesn&rsquo;t indicate this, then it will tell you that you should add the following to your project file:</p>
<pre class=" "><code>&lt;AutoGenerateBindingRedirects&gt;true&lt;/AutoGenerateBindingRedirects&gt;</code></pre><p>After that, you can rebuild to show the new warning, double-click it and generate your assembly-binding redirect.</p>
<h2>How did we get the wrong redirects?</h2><p>When MSBuild generates a redirect, it uses the highest version of the dependency <em>that it found on the build machine</em>. In most cases, this will be the developer machine. A developer machine tends to have more versions of the runtime targets installed than either the build or the deployment machine.</p>
<p>A Visual Studio installation, in particular, includes myriad runtime targets, including many that you&rsquo;re not using or targeting. These are available to MSBuild but are ordinarily ignored in favor of more appropriate ones.</p>
<p>That is, unless there&rsquo;s a bit of a bug in one or more of the assemblies included with one of the SDKs…as there is with the net461 distribution in Visual Studio 2017.</p>
<p>Even if you are targeting .NET Framework 4.6.2, MSBuild will still sometimes reference assemblies from the 461 distribution because the assemblies are incorrectly marked as having a higher version than those in 4.6.2 and are taken first.</p>
<p>I found the following resources somewhat useful in explaining the problem (though none really offer a solution):</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/issues/26456">.dll in Microsoft.NET.Build.Extensions\net461 targets .NET Framework 4.6.1</a></li>
<li><a href="https://github.com/Microsoft/msbuild/issues/2527">ImplicitlyExpandNETStandardFacades option on MSBuild Extensions corrupts build</a> (GitHub issue)</li>
<li><a href="https://social.msdn.microsoft.com/Forums/vstudio/en-US/51dc828b-43ca-4177-b68e-7a6a9cf81db5/ms-build-extensions-file-corrupt-my-bin-web-api-folder?forum=msbuild">MS Build Extensions file corrupt my bin (Web API) folder</a></li></ul><p>How can you fix the problem if you&rsquo;re affected?</p>
<p>You&rsquo;ll generally have a crash on the deployment server that indicates a certain assembly could not be loaded (e.g. <code>System.Runtime</code>). If you show the properties for that reference in your web application, do you see the path <code>C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461</code> somewhere in there? If so, then your build machine is linking in references to this incorrect version. If you let MSBuild generate binding redirects with those referenced paths, they will refer to versions of runtime components that do not generally exist on a deployment machine.</p>
<p>Tips for cleaning up:</p>
<ul>
<li>Use MSBuild to debug this problem. R# Build is nice, but not as good as MSBuild for this task.</li>
<li>Clean and Rebuild to force all warnings
<li><div>Check your output carefully.<ul>
<li>Do you see warnings related to package conflicts?</li>
<li>Ambiguities?</li>
<li>Do you see the path <code>C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461</code> in the output?</li></ul></div></ul><p>A sample warning message:</p>
<div class="warning ">[ResolvePackageFileConflicts] Encountered conflict between <code>Platform:System.Collections.dll</code> and <code>CopyLocal:C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\System.Collections.dll</code>.  Choosing <code>CopyLocal:C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\System.Collections.dll</code> because AssemblyVersion <code>4.0.11.0</code> is greater than <code>4.0.10.0</code>.</div><h2>The Solution</h2><p>As mentioned above, but reiterated here, this what I did to finally stabilize my applications:</p>
<ul>
<li>Remove the <code>C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\</code> directory</li>
<li>Remove all System* binding redirects</li>
<li>Clean out all <code>bin/</code> and <code>obj/</code> folders</li>
<li>Delete the <code>.vs</code> folder (may not be strictly necessary)</li>
<li>Build in Visual Studio</li>
<li>Observe that a few binding-redirect warnings appear</li>
<li>Double-click them to re-add the binding redirects, but this time <em>to actual 4.6.2 versions</em> (you may need to add <code>&lt;AutoGenerateBindingRedirects&gt;true&lt;/AutoGenerateBindingRedirects&gt;</code> to your project)</li>
<li>Rebuild and verify that you have no more warnings</li>
<li>Deploy and TADA!</li></ul><h2>One more thing</h2><p>When you install any update of Visual Studio, it will silently <em>repair</em> these missing files for you. So be aware and check the folder after any installations or upgrades to make sure that the problem doesn&rsquo;t creep up on you again.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3671</guid>
    <title><![CDATA[Quino's Roadmap to .NET Standard and .NET Core]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3671</link>
    <pubDate>Sun, 20 Jan 2019 21:49:13 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 21:49:13 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">Note: this article was originally published at <a href="https://encodo.com/latest/developer-blogs/quinos-roadmap-to-net-standard-and-net-core/">Encodo.com</a> in May, 2018.</small></p>
<p><hr></p>
<p>With Quino 5, we&rsquo;ve gotten to a pretty good place organizationally. Dependencies are well-separated into projects—and there are almost 150 of them.</p>
<p>We can use code-coverage, solution-wide-analysis and so on without a problem. TeamCity runs the ~10,000 tests quickly enough to provide feedback in a reasonable time. The tests run even more quickly on our desktops. It&rsquo;s a pretty comfortable and efficient experience, overall.</p>
<h2>Monolithic Solution: Pros and Cons</h2><p>As of Quino 5, all Quino-related code was still in one repository and included in a single solution file. Luckily for us, Visual Studio 2017 (and Rider and Visual Studio for Mac) were able to keep up quite well with such a large solution. Recent improvements to performance kept the experience quite comfortable on a reasonably equipped developer machine.</p>
<p>Having everything in one place is both an advantage and disadvantage: when we make adjustments to low-level shared code, the refactoring is applied in all dependent components, automatically. If it&rsquo;s not 100% automatic, at least we know where we need to make changes in dependent components. This provides immediate feedback on any API changes, letting us fine-tune and adjust until the API is appropriate for known use cases.</p>
<p>On the other hand, having everything in one place means that you <em>must</em> make sure that your API not only works for but compiles and tests against components that you may not immediately be interested in.</p>
<p>For example, we&rsquo;ve been pushing much harder on the web front lately. Changes we make in the web components (or in the underlying Quino core) must also work immediately for dependent Winform and WPF components. Otherwise, the solution doesn&rsquo;t compile and tests fail.</p>
<p>While this setup had its benefits, the drawbacks were becoming more painful. We wanted to be able to work on one platform without worrying about all of the others.</p>
<p>On top of that, all code in one place is no longer possible with cross-platform support. Some code—Winform and WPF—doesn&rsquo;t run on Mac or Linux. [1]</p>
<p>The time had come to separate Quino into a few larger repositories.</p>
<h2>Separate Solutions</h2><p>We decided to split along platform-specific lines.</p>
<ul>
<li><strong>Quino-Standard</strong>: all common code, including base libraries, application, configuration and IOC support, metadata, builders and all data drivers</li>
<li><strong>Quino-WebApi</strong>: all web-related code, including remaining ASP.NET MVC support</li>
<li><strong>Quino-Windows</strong>: all Windows-platform-only code (Windows-only APIs (i.e. native code) as well as Winform and WPF)</li></ul><p>The Quino-WebApi and Quino-Windows solution will <em>consume</em> Quino-Standard via NuGet packages, just like any other Quino-based product. And, just like any Quino-based product, they will be able to choose when to upgrade to a newer version of Quino-Standard.</p>
<h2>Quino-Standard</h2><p>Part of the motivation for the split is cross-platform support. The goal is to target all assemblies in Quino-Standard to .NET Standard 2.0. The large core of Quino will be available on all platforms supported by .NET Core 2.0 and higher.</p>
<p>This work is quite far along and we expect to complete it by August 2018.</p>
<h2>Quino-WebApi</h2><p>As of Quino 5.0.5, we&rsquo;ve moved web-based code to its own repository and set up a parallel deployment for it. Currently, the assemblies still target .NET Framework, but the goal here is to target class libraries to .NET Standard and to use .NET Core for all tests and sample web projects.</p>
<p>We expect to complete this work by August 2018 as well.</p>
<h2>Quino-Windows</h2><p>We will be moving all Winform and WPF code to its own repository, setting it up with its own deployment (as we did with Quino-WebApi). These projects will remain targeted to .NET Framework 4.6.2 (the lowest version that supports interop with .NET Standard assemblies).</p>
<p>We expect this work to be completed by July 2018.</p>
<h2>Quino-Mobile</h2><p>One goal we have with this change is to be able to use Quino code from Xamarin projects. Any support we build for mobile projects will proceed in a separate repository from the very beginning.</p>
<p>We&rsquo;ll keep you posted on work and improvements and news in this area.</p>
<h2>Conclusion</h2><p>Customer will, for the most part, not notice this change, except in minor version numbers. Core and platform versions may (and almost certainly will) diverge between major versions. For major versions, we plan to ship all platforms with a single version number.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3671_1_body" class="footnote-number">[1]</span> I know, Winform can be made to run on Mac using Mono. And WPF may eventually become a target of Xamarin. But a large part of our Winform UI uses the Developer Express components, which aren&rsquo;t going to run on a Mac. And the plans for WPF on Mac/Linux are still quite up in the air right now.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3683</guid>
    <title><![CDATA[Convert Markdown to earthli format]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3683</link>
    <pubDate>Sun, 20 Jan 2019 21:44:30 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 21:44:30 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The earthli blogging format uses HTML-like formatting, described in the <a href="https://dev.earthli.com/news/text_formatting.php">lengthy manual</a> (with examples). However, Encodo&rsquo;s blogging back-end now uses Umbraco, with Markdown for content. I used to be able to cross-post with ease, by copy/pasting. Now, I need to convert the content from Markdown to earthli formatting.</p>
<p>The following steps suffice to convert any article:</p>
<ol>
<li>If there are attached media (e.g. graphics), save those locally</li>
<li>Create a new earthli article with the same title as the source article</li>
<li>Attach all media to the new article</li>
<li>Copy the main text; paste into <em>Sublime Text</em>
<li><div>Find/replace the following regular expressions with the replacements:<ul>
<li><code>### ([^\n]+)$</code> =&gt; <code>&lt;h level=&ldquo;3&rdquo;&gt;\1&lt;/h&gt;</code></li>
<li><code>## ([^\n]+)$</code> =&gt; <code>&lt;h&gt;\1&lt;/h&gt;</code></li>
<li><code>\[([^!][^\]]+)\]\(([^\)]+)\)</code> =&gt; <code>&lt;a href=&ldquo;\2&rdquo;&gt;\1&lt;/a&gt;</code></li>
<li><code>\*\*([^\*]+)\*\*</code> =&gt; <code>&lt;b&gt;\1&lt;/b&gt;</code></li>
<li><code>_([^_]+)_</code> =&gt; <code>&lt;i&gt;\1&lt;/i&gt;</code></li>
<li><code>```txt\n([^`]+)\n```</code> =&gt; <code>&lt;pre&gt;\1&lt;/pre&gt;</code></li>
<li><code>```[a-z]+\n([^`]+)\n```</code> =&gt; <code>&lt;code&gt;\1&lt;/code&gt;</code></li>
<li><code>`([^`]+)`</code> =&gt; <code>&lt;c&gt;\1&lt;/c&gt;</code></li></ul></div></li>
<li>Manually re-attach all media in the appropriate locations [1]</li></ol><p>I haven&rsquo;t automated this process yet because I only rarely transfer articles.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3683_1_body" class="footnote-number">[1]</span> This is easy since the earthli UI includes an attachment formatter that lets you place, align, link and scale the attachment better than in the original specification anyway.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3554</guid>
    <title><![CDATA[Compiler Pessimism]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3554</link>
    <pubDate>Tue, 08 Jan 2019 22:46:23 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Jan 2019 22:46:23 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jan 2019 11:22:48 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <div><div class="auto-content-block"><blockquote class="quote quote-block "><div>&ldquo;In practice, nearly everything you write is potentially dependent upon the order of evaluation, but in practice it isn&rsquo;t because you are not a nincompoop.&rdquo;</div></blockquote></div><div class="auto-content-caption">&mdash;<cite><a href="https://blogs.msdn.microsoft.com/oldnewthing/20180711-00/?p=99215">Raymond Chen</a></cite> (<cite><a href="http://blogs.msdn.microsoft.com/">The Old New Thing</a></cite>)</div></div><p>He completes the thought with <span class="quote-inline">&ldquo;[b]ut the compiler doesn&rsquo;t know that. The compiler must adhere to the letter of the language standard, because it has to compile insane code as well as sane code.&rdquo;</span></p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3598</guid>
    <title><![CDATA[Inventing languages for the sake of it]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3598</link>
    <pubDate>Tue, 08 Jan 2019 22:28:18 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Jan 2019 22:28:18 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://www.reaktor.com/blog/fear-trust-and-javascript/">Fear, trust and JavaScript: When types and functional programming fail</a> presents issues in JavaScript and a solution: use another language. The list several newer ones that are completely untested.</p>
<p>But the main problem that the article mentions can&rsquo;t be solved 100% by any language. The main problem is at the boundaries of your application: inputs.</p>
<p>When you get data from an external source, you have to validate it somehow before passing it along to the rest of the application.</p>
<p>No language can remove this requirement. It doesn&rsquo;t matter how functional, curryable, immutable or sexy it is; it just can&rsquo;t do it. What you have instead is languages with more built-in mechanisms for defining types that allow the rest of the program to work safely with the data, <em>once it&rsquo;s been validated</em>.</p>
<p>So if your language supports immutability and types, then you can validate that the data is OK before hydrating the object from the serialized source (e.g. JSON).</p>
<p>What we&rsquo;re trying to avoid is unexpected runtime errors, no? Or, at the very least, we want a runtime error of a known type that precisely identifies the problem with the incoming data. That is, the data either conforms to the definition—and the definition is statically typed—or there is an error.</p>
<p>The desire is to push this gatekeeper/conversion to a single place so that the rest of the application works with the compiler to find errors rather than tyhe programmer defensively checking throughout the source.</p>
<p>However, suggesting that PureScript or Elm or ClojureScript are somehow better at doing this the JavaScript is incorrect. Where they are better is in providing language mechanisms that allow you to precisely define the shape of the data.</p>
<p>Despite the author&rsquo;s suggestions, they are not that much different than TypeScript. The only difference being that TypeScript chose to stay much closer to JavaScript for compatibility reasons. At the time that TypeScript came out, this was a reasonable requirement, since almost no-one wanted to move completely away from JavaScript.</p>
<p>Five years later and the development world is ready for other languages. With WASM (Web Assembly) as a target (instead of just JavaScript), there are more possibilities than ever. </p>
<p>JavaScript as a compile target is <em>still</em> open to runtime errors. When you use a higher-level language, you&rsquo;re restricting the range of functionality that you can use in the target bytecode/machine code. That is, when you write an if-statement in C, you&rsquo;re using the JMP statement, but you&rsquo;re only able to JMP to certain address locations instead of anywhere in addressable memory.</p>
<p>It&rsquo;s the same with JavaScript as a compile target. It doesn&rsquo;t really matter that JavaScript allows too much—what matters is what the higher-level language allows. TypeScript may still allow too much, but it&rsquo;s worlds better than JavaScript.</p>
<p>It&rsquo;s true that PureScript or Elm or ClojureScript can close some loopholes that TypeScript leaves open. That&rsquo;s fine. But if you&rsquo;re going to just use JavaScript (or WASM) as a compile target, then why not choose a more-established language like C# or F#?</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3596</guid>
    <title><![CDATA[Anyone Can Be a Programmer, Right?]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3596</link>
    <pubDate>Tue, 08 Jan 2019 22:24:05 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Jan 2019 22:24:05 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The post on Reddit called <a href="https://old.reddit.com/r/webdev/comments/9pq0gh/someone_asked_me_to_make_a_site_for_them_and_i/">Someone asked me to make a site for them and I don&rsquo;t know how the fuck I&rsquo;m supposed to go about it.</a> is about exactly what it sounds like it&rsquo;s about. Amid the flurry of comments with recommendations on how to pretend he (or she) knows how to build a web site by using tools he&rsquo;s (or she&rsquo;s) never heard of, I chimed in with,</p>
<blockquote class="quote quote-block "><div><p>What is it about software that makes people who have never done it think that they can do it professionally?</p>
<p>What if your neighbor had heard you were a carpenter and had asked you to make a dining-room set for &ldquo;good money&rdquo;? Would you watch YouTube videos about how to make furniture and then charge money for the first furniture you ever made?</p>
<p>What about if they&rsquo;d asked for a haircut/trim/style/dye? Would you just go for it, after having asked around on /r/coiffeur for a few minutes?</p>
<p>Or maybe they&rsquo;d heard you were a chef and offered &ldquo;good money&rdquo; to cook their Thanksgiving dinner for them? Would you risk doing that?</p>
<p>Probably not, because if you&rsquo;ve never done any of those things, you&rsquo;re not good at them and charging for doing them can only backfire horribly.</p>
<p>Unless your neighbor is a sap and a fool, in which case go for it.</p>
</div></blockquote>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3642</guid>
    <title><![CDATA[Ray-tracing on postcards]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3642</link>
    <pubDate>Mon, 31 Dec 2018 22:55:26 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">31. Dec 2018 22:55:26 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://fabiensanglard.net/postcard_pathtracer/">Deciphering The Postcard Sized Raytracer</a> by <cite>Fabien Sanglard</cite> is a wonderfully presented breakdown of how the <em>path</em> tracer found on a postcard does its magic. It&rsquo;s not super-fast (it takes 3 minutes to produce a much rougher version on the author&rsquo;s machine). He includes his final <a href="https://fabiensanglard.net/postcard_pathtracer/formatted_full.html">cleaned-up source code</a>.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3642/rendered_pixar.png"><img src="https://www.earthli.com/data/news/attachments/entry/3642/rendered_pixar.png" alt=" " style="width: 449px"></a></p>
<p>It comes from the same person who made the business card ray-tracer discussed in the article <a href="https://fabiensanglard.net/rayTracing_back_of_business_card/">Decyphering The Business Card Raytracer</a> by <cite>Fabien Sanglard</cite>.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3636</guid>
    <title><![CDATA[The problem with slow development tools]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3636</link>
    <pubDate>Sun, 30 Dec 2018 23:03:19 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. Dec 2018 23:03:19 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. Dec 2018 23:03:37 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="http://aras-p.info/blog/2018/12/28/Modern-C-Lamentations/">&rdquo;Modern&rdquo; C++ Lamentations</a> by <cite>Aras Pranckevicius</cite>is a wide-ranging rant about the inefficiency of C++ template programming and the degree to which it&rsquo;s inappropriate for many of the areas where C++ is used. Aras is one of the developers for the Unity game engine</p>
<p>In particular, he highlights the disastrous compilation and execution speeds when using a lot of the STL. Not only that, but the debugging time is extremely slow, due to the inordinate amount of extra symbol information associated with hundreds of thousands of lines of code pulled in to implement relatively simple concepts that are standard in other languages, libraries and runtimes.</p>
<p>On top of it all, even the high-level C++ code isn&rsquo;t very easy to read, despite the tremendous amount of abstraction.</p>
<p>The optimized version of C++ code has an even worse compilation time, but it has a comparable/reasonable run-time to the C/C++-style version. However, it&rsquo;s very difficult to debug optimized code, which makes it doubly bad for development. Interactive development is hindered because of long compile times and, when debugging is necessary, most introspection tools don&rsquo;t work (e.g. reading variables) very well. It&rsquo;s the rare developer who can make headway debugging optimized code.</p>
<p>He compares versions of an algorithm built using &ldquo;classic&rdquo; C/C++ programming vs. STL programming. He then compares to C#, which compiles and runs and debugs very quickly—and is very easy to read, to boot.</p>
<p>The problem with C++ boils down to its approach of making &ldquo;everything a library&rdquo;. It&rsquo;s almost like an exercise in abstraction: since a few generic-programming concepts can be used to build everything in the library rather than the language, that&rsquo;s what C++ does. It&rsquo;s almost as if it does it to <em>prove that it can be done</em>. I&rsquo;m all for removing redundancy in a language, but C++ is far from such a language. It&rsquo;s almost like the designers don&rsquo;t use their own language.</p>
<p>He cites <a href="https://twitter.com/ChristerEricson/status/1078095388244996096">Christer Ericson</a> (<cite><a href="http://twitter.com/">Twitter</a></cite>)</p>
<blockquote class="quote quote-block "><div>&ldquo;Goal of programmers is to ship, on time, on budget. It’s not “to produce code.” IMO most modern C++ proponents 1) overassign importance to source code over 2) compile times, debug[g]ability, cognitive load for new concepts and extra complexity, project needs, etc. 2 is what matters.&rdquo;</div></blockquote><p>Aras continues discussing the future of C++ and how it is currently used in game companies, for example. These are the companies using C++ the most. Rust is making some inroads, but the area is <em>dominated</em> by C/C++.</p>
<p>Finally, he has some good advice for programmers—for any professional, really—on how to take criticism and turn it into something useful.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;Ignoring literal trolls who complain on the internet “just for the lulz”, [the] majority of complaints do have [an] actual issue or problem behind it. It might be worded poorly, or exaggerated, or whoever is complaining did not think about other possible viewpoints, but there is a valid issue behind the complaint anyway.</p>
<p>&ldquo;What I do whenever someone complains about thing I’ve worked on, is try to forget about “me” and “work I did”, and get their point of view. What are they trying to solve, and what problems do they run into? The purpose of any software/library/language is to help their users solve the problems they have. It might be a perfect tool at solving their problem, an “ok I guess that will work” one, or a terribly bad one at that.&rdquo;</p>
</div></blockquote><p>As a postscript, the article <a href="http://tonsky.me/blog/slow-wrong/">It is fast or it is wrong</a> by <cite>Nikita Tonsky</cite> discusses a very similar issue with Clojure vs. ClojureScript.</p>
<blockquote class="quote quote-block "><div>&ldquo;What do ClojureScript/Google Closure compilers do for so long? They are wasting your time, that’s what. Of course it’s nobody’s fault, but in the end, this whole solution is simply wrong. We can do the same thing much faster, we have proof of that, we have the means to do it, it just happens that we are not. But we could. If we wanted to. That huge overhead you’re paying, you’re paying it for nothing. You don’t get anything from being on JS, except a 2× performance hit and astronomical build times.&rdquo;</div></blockquote><p>I find these points interesting because programming is very much about which tools you use and how they help you to turn your work around more quickly. I&rsquo;m in charge of choosing which languages, libraries and tools we use at Encodo and I&rsquo;m hyper-aware of the efficiency losses when developers are hindered by their tools or libraries. Being the lead developer of our framework Quino makes me doubly aware of this.</p>
<p>If you have a very slow feedback loop, then you&rsquo;ll take much longer to get your work done. I remember back in the late 90s/early 2000s, working with C++, where I would have to schedule builds because it took over 30 minutes to rebuild all of my static libraries if I made a low-level change. This was on a project that cross-compiled to Mac and Windows. Instead of working on my project, I spent way too much time massaging PCH files and avoiding making low-level changes so that I could continue testing.</p>
<p>Bad tools that run too slowly are a problem. That&rsquo;s why you should always be very careful in choosing your languages, libraries and environments. Jumping ship to the &ldquo;new hotness&rdquo; very often means that you&rsquo;re going to have your time wasted by tools that aren&rsquo;t ready for prime time.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3637</guid>
    <title><![CDATA[.NET Tips and Resources]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3637</link>
    <pubDate>Sun, 30 Dec 2018 22:12:44 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. Dec 2018 22:12:44 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>If you&rsquo;re a .NET developer, this is video you&rsquo;ve been looking for:</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/hLFyycJVo0I" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><a href="https://www.youtube.com/watch?v=hLFyycJVo0I">S107 − Build great libraries using .NET Standard</a> by <cite>Immo Landwerth</cite> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>)</span></span></p>
<p>Immo tells you everything you need to know about Nuget, using Package References, switching to .NET Core, and using Assembly-Binding Redirects in .NET Framework (they&rsquo;re not necessary in .NET Core). He also includes an effusive apology for the nightmare of compatibility issues that accompanied the purported interoperability between .NET 4.6.1 and .NET Core.</p>
<p>If you want to be compatible with .NET Core 1.5 or lower, then you can use .NET Framework 4.6.1. For .NET Standard compatibility, you should definitely use .NET Framework 4.7.2 instead.</p>
<p>He includes a list of resources for digging through open-source code and checking platform and target compatibility.</p>
<dl><dt class="field"><a href="https://apisof.net">.NET API Catalog</a></dt>
<dd><div class=" "><p>While you can use <a href="https://docs.microsoft.com/">Microsoft Docs</a> to find out which targets or platforms support which APIs, this resource lets you do it faster.</p>
<p>You can browse a giant list of namespaces and click on any one of them to see the types, and then drill down to properties and methods. For each level, you can see a nice list of supported targets/platforms and the assemblies to use.</p>
<p>You can also &ldquo;Search&rdquo;, which opens what looks like a terminal that let&rsquo;s you camel-case search for your namespace, type or member. Selecting a result takes you to the location in the catalog.</p>
</div></dd>
<dt class="field"><a href="https://referencesource.microsoft.com">.NET Framework Source-code browser</a></dt>
<dd><div class=" "><p>Yes, you read that correctly. I had no idea that this existed—I&rsquo;ve been digging through decompiled assembly code instead. This is much faster and includes the original documentation and comments. The source is syntax-highlighted and all types, methods and properties are linked.</p>
<p>There&rsquo;s a document explorer, namespace explorer and project manager, all linked up very nicely. You can click any element and show all references in a separate pane. Clicking one of those references navigates there—and other references in that file are also highlighted.</p>
<p>If that&rsquo;s not sufficient, you can even download the entire source code as a ZIP file from here—complete with solution and project files so you can open it in Visual Studio for browsing.</p>
</div></dd>
<dt class="field"><a href="https://source.dot.net">.NET Core Source Browser</a></dt>
<dd>This is the same thing as the link above, but for .NET Core sources.</dd>
<dt class="field"><a href="https://www.fuget.org">FuGet</a></dt>
<dd><div class=" "><p>This is a NuGet package browser combined with an API browser over all of the assemblies in a package.</p>
<ul>
<li>You can search the package for keywords.</li>
<li>You can browse types and see the formatted XML documentation. </li>
<li>You can diff versions of the package to see which APIs have changed. </li>
<li>You can jump to the code in the Git repository, if it&rsquo;s given in the package.</li></ul><p>It&rsquo;s an open-source GitHub project, so you could even run your own copy for diffing privately published packages.</p>
</div></dd>
</dl>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3557</guid>
    <title><![CDATA[Which type should you register in an IOC container?]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3557</link>
    <pubDate>Mon, 16 Jul 2018 21:55:42 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Jul 2018 21:55:42 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <h2>Use Case</h2><p>I just ran into an issue recently where a concrete implementation registered as a singleton was suddenly <em>not</em> registered as a singleton because of architectural changes.</p>
<p>The changes involved creating mini-applications within a main application, each of which has its own IOC. Instead of creating controllers using the main application, I was now creating controllers with the mini-application instead (to support multi-tenancy, of which more in an upcoming post).</p>
<h2>Silent Replacement of Singleton with Transient</h2><p>Controllers are, by their nature, transient; a new controller is created to handle each incoming request.</p>
<p>In the original architecture, the concrete singleton was injected into the controller and all controller instances used the same shared instance. In the new architecture, the registration was not present in the mini-application (at first), which led to a (relatively) subtle bug: a transient and freshly created instance was injected into each new controller.</p>
<p>In cases where the singleton is a stateless algorithm, this wouldn&rsquo;t be a logical problem at all. At the very worst, you&rsquo;re over-allocating—but you probably wouldn&rsquo;t notice that, either. In this case, the singleton was a settings object, configured at application startup. The configured object was still in the main application&rsquo;s IOC, but not registered in the mini-application&rsquo;s IOC.</p>
<p>Because the singleton was registered on a concrete type rather than an interface, the semantic error occurred silently instead of throwing a lifestyle-mismatch or unregistered-interface exception.</p>
<h2>A Straightforward Fix</h2><p>This is only one of the reasons that I recommend using interfaces as the anchoring type of an IOC registration.</p>
<p>To fix the issue, I did exactly this: I extracted an interface from the class and used the interface everywhere (except for the implementing type of the registration). Re-running the test caused an immediate exception rather than a strange data bug (which resulted because the default configuration in the concrete type was <em>just correct</em> enough to allow it to limp to a result).</p>
<p>To show an example, instead of the following,</p>
<pre class=" "><code>application.RegisterSingle&lt;ApiSettings&gt;()</code></pre><p>I used,</p>
<pre class=" "><code>application.RegisterSingle&lt;<strong class="highlight">IApiSettings,</strong> ApiSettings&gt;()</code></pre><p>This still didn&rsquo;t fix the crash because the mini-application doesn&rsquo;t get that registration automatically.</p>
<p>I also can&rsquo;t use the same registration as above because that would just create a new unconfigured <code>ApiSettings</code> in each mini-application (the same as I had before, but now as a singleton). To go that route, I would have to replicate the configuration-loading for the <code>ApiSettings</code> as well. And I don&rsquo;t want to do that.</p>
<p>Instead, I just injected the <code>IApiSettings</code> from the main application to the component responsible for creating the mini-application and registered the object as a singleton directly, as shown below.</p>
<pre class=" "><code>public class MiniApplicationFactory
{
  public MiniApplicationFactory([NotNull] IApiSettings apiSettings)
  {
    if (apiSettings = null) { throw new ArgumentNullException(nameof(apiSettings(); }

    _apiSettings = apiSettings;
  }

  IApplication CreateApplication()
  {
    return new Application()<strong class="highlight">.UseRegisterSingle(_apiSettings)</strong>;
  }

  [NotNull]
  private readonly IApiSettings _apiSettings;
}</code></pre><p>On a side note, whereas C# syntax has become more concise and powerful from version to version, I still think it has a way to go in terms of terseness for such simple objects. For such things, Kotlin and TypeScript nicely illustrate what such a syntax could look like. [1]</p>
<h2>Other Drawbacks</h2><p>I mentioned above that this is only &ldquo;one&rdquo; of the reasons I don&rsquo;t like registering concrete singletons. The other two reasons are:</p>
<ol>
<li><strong>Complicates replacement</strong>: If the registered type is a concrete instance, then any replacement <em>must</em> inherit from this instance. The base class has to be constructed more carefully in order to allow for all foreseeable customizations. With an interface, the implementor is completely free to either use the existing class as a base or to re-implement the interface entirely.</li>
<li><strong>Limits Mocking</strong>: Related to the first reason is that mocking is limited in its ability to override non-virtual methods. Even without a mocking library, you&rsquo;re just as hard-pressed to work around unwanted behavior in a hand-coded mock as you are with an actual replacement (as described above). Such limitations are non-existent with interfaces.</li></ol><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3557_1_body" class="footnote-number">[1]</span> <p>I&rsquo;m still waiting for C# to clean up a bit more of this syntax for me. The <code>[NotNull]</code> should be a language feature checked by the compiler so that the <code>ArgumentNullException</code> is no longer needed. On top of that, I&rsquo;d like to see <em>parameter properties</em>, as in <a href="https://www.typescriptlang.org/docs/handbook/classes.html">TypeScript</a> (this is where you can prefix a constructor parameter with a keyword to declare and initialize it as a property). With a few more C#-language iterations that included non-nullable reference types and parameter properties, the example could look like the code below:</p>
<pre class=" "><code>public class MiniApplicationFactory
{
  public MiniApplicationFactory(private IApiSettings apiSettings)
  {
  }

  IApplication CreateApplication()
  {
    return new Application().UseRegistereSingle(apiSettings);
  }
}</code></pre></div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3546</guid>
    <title><![CDATA[Tools for maintaining Quino]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3546</link>
    <pubDate>Thu, 24 May 2018 22:12:33 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">24. May 2018 22:12:33 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The <a href="https://encodo.com/quino/quino-roadmap/">Quino roadmap</a> shows you where we&rsquo;re headed. How do we plan to get there?</p>
<p>A few years back, we made a big leap in Quino 2.0 to split up dependencies in anticipation of the initial release of .NET Core. Three tools were indispensable: <a href="https://www.jetbrains.com/resharper/">ReSharper</a>, <a href="https://www.ndepend.com">NDepend</a> and, of course, Visual Studio. Almost all .NET developers use Visual Studio, many use ReSharper and most should have at least heard of NDepend.</p>
<p>At the time, I wrote a series of articles on the migration from two monolithic assemblies (<code>Encodo</code> and <code>Quino</code>) to dozens of layered and task-specific assemblies that allows applications to include our software in a much more fine-grained manner. As you can see from the articles, NDepend was the main tool I used for finding and tracking dependencies. [1] I used ReSharper to disentangle them.</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=3167">Splitting up assemblies in Quino using NDepend (Part I)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3169">Iterating with NDepend to remove cyclic dependencies (Part II)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3158">The Road to Quino 2.0: Maintaining architecture with NDepend (part I)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=3164">The Road to Quino 2.0: Maintaining architecture with NDepend (part II)</a></li></ul><p>Since then, I&rsquo;ve not taken advantage of NDepend&rsquo;s features for <em>maintaining</em> architecture as much as I&rsquo;d like. I recently fired it up again to see where Quino stands now, with 5.0 in beta.</p>
<p>But, first, let&rsquo;s think about why we&rsquo;re using yet another tool for examining our code. Since I started using NDepend, other tools have improved their support for helping a developer maintain code quality.</p>
<ul>
<li>ReSharper itself has introduced tools for visualizing project and type dependencies with very nice graphs. However, there is currently no support for establishing boundaries and getting ReSharper to tell me when I&rsquo;ve inadvertently introduced new dependencies. In fact, ReSharper&rsquo;s only improved its support for quickly pulling in a dependency with its excellent Nuget-Package integration. ReSharper is excellent for finding lower-level code smells, like formatting, style and null-reference issues, as well as language usage, missing documentation and code-complexity (with an extension). DotCover provides test-coverage data but I haven&rsquo;t used it for real-time analysis yet (I don&rsquo;t use continuous testing with ReSharper on Quino because I feel it would destroy my desktop).</li>
<li>Visual Studio has also been playing catch-up with ReSharper and has done an excellent job in the last couple of years. VS 2017 is much, much faster than its predecessors; without it, we would be foundering badly with a Quino solution with almost 150 projects. [2] Visual Studio provides Code Analysis and Portability Analysis and can calculate Code Metrics. Code Analysis is mostly covered by ReSharper, although it has a few extra inspections related to proper application and usage of the <code>IDisposable</code> pattern. The Portability Analysis is essential for moving libraries to .NET Standard but doesn&rsquo;t offer any insight into architectural violations like NDepend does.</li>
<li>We&rsquo;ve recently started working with SonarQube on our TeamCity build server because a customer wanted to use it. It has a very nice UI and very nice reports, but doesn&rsquo;t go much farther than VS/R# inspections. Also, the report isn&rsquo;t in the UI, so it&rsquo;s not as quick to jump into the code. I don&rsquo;t want to review it here, since we only recently started working with it. It looks promising and is a welcome addition to that project. Hopefully more will reveal itself in time.</li>
<li>TeamCity provides a lot of the services that ReSharper also provides: inspections and code-coverage for builds. This takes quite a while, though, so we only run inspections and coverage for the Quino nightly build. The reports are nice but, as with SonarQube, of limited use because of the tenuous integration with Visual Studio. The integration works, but it&rsquo;s balky and we don&rsquo;t use it very much. Instead, we analyze inspections in real-time in Visual Studio with ReSharper and don&rsquo;t use real-time code-coverage. [3]</li>
<li>NDepend integrates right into Visual Studio and has a super-fast analysis with a very nice dashboard overview, from which you can drill down into myriad issues and reports and analyses, from technical debt (with very daunting but probably accurate estimates for repair) to type- and assembly-interdependency problems. NDepend can also integrate code-coverage results from DotCover to show how you&rsquo;re doing on that front on the dashboard as well. As with TeamCity and SonarQube, the analyses are retained as snapshots. With NDepend, you can quickly <em>compare</em> them (and comparing against a baseline is even included by default in the dashboard), which is essential to see if you&rsquo;re making progress or regressing. [4] NDepend also integrates with TeamCity, but we haven&rsquo;t set that up (yet).</li></ul><p>With a concrete .NET Core/Standard project in the wings/under development, we&rsquo;re finally ready to finish our push to make Quino Core ready for cross-platform development. For that, we&rsquo;re going to need NDepend&rsquo;s help, I think. Let&rsquo;s take a look at where we stand today.</p>
<p>The first step is to choose what you want to cover. In the past, I&rsquo;ve selected specific assemblies that corresponded to the &ldquo;Core&rdquo;. I usually do the same when building code-coverage results, because the UI assemblies tend to skew the results heavily. As noted in a footnote below, we&rsquo;re starting an effort to separate Quino into high-level components (roughly, a core with satellites like Winform, WPF and Web). Once we&rsquo;ve done that, the health of the core itself should be more apparent (I hope).</p>
<p>For starters, though, I&rsquo;ve thrown all assemblies in for both NDepend analysis as well as code coverage. Let&rsquo;s see how things stand overall.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3546/quino_5_dashboard.png"><img src="https://www.earthli.com/data/news/attachments/entry/3546/quino_5_dashboard.png" alt=" " style="width: 767px"></a></p>
<p>The amount of information can be quite daunting but the latest incarnation of the dashboard is quite easy to read. All data is presented with a current number and a delta from the analysis against which you&rsquo;re comparing. Since I haven&rsquo;t run an analysis in a while, there&rsquo;s no previous data against which to compare, but that&rsquo;s OK.</p>
<ul>
<li>Lines of Code</li>
<li>Code Elements (Types, Methods, etc.)</li>
<li>Comments (documentation)</li>
<li>Technical Debt</li>
<li>Code Coverage [5]</li>
<li>Quality Gates / Rules / Issues</li></ul><p>Let&rsquo;s start with the positive.</p>
<ul>
<li>The Quino sources contain almost 50% documentation. That&rsquo;s not unexpected. The XML documentation from which we generate our developer documentation [6] is usually as long as or longer than the method itself.</li>
<li>We have a solid B rating for technical debt, which is really not bad, all things considered. I take that to mean that, even without looking, we instinctively produce code with a reasonable level of quality.</li></ul><p>Now to the cool part: you can click anything in the NDepend dashboard to see a full list of all of the data in the panel.</p>
<p>Click the &ldquo;B&rdquo; on technical debt and you&rsquo;ll see an itemized and further-drillable list of the grades for all code elements. From there, you can see what led to the grade. By clicking the &ldquo;Explore Debt&rdquo; button, you get a drop-down list of pre-selected reports like &ldquo;Types Hot Spots&rdquo;.</p>
<p>Click lines of code and you get a breakdown of which projects/files/types/methods have the most lines of code</p>
<p>Click failed quality gates to see where you&rsquo;ve got the most major problems (Quino currently has 3 categories)</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3546/ndepend_blocker_quality_gates.png"><img src="https://www.earthli.com/data/news/attachments/entry/3546/ndepend_blocker_quality_gates.png" alt=" " style="width: 446px"></a></p>
<p>Click &ldquo;Critical&rdquo; or &ldquo;Violated&rdquo; rules to see architectural rules that you&rsquo;re violating. As with everything in NDepend, you can pick and choose which rules should apply. I use the default set of rules in Quino.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3546/ndepend_critical_rule_violations.png"><img src="https://www.earthli.com/data/news/attachments/entry/3546/ndepend_critical_rule_violations.png" alt=" " style="width: 727px"></a></p>
<p>Most of our critical issues are for mutually-dependent namespaces. This is most likely not root namespaces crossing each other (though we&rsquo;d like to get rid of those ASAP) but sub-namespaces that refer back to the root and vice-versa. This isn&rsquo;t necessarily a no-go, but it&rsquo;s definitely something to watch out for.</p>
<p>There are so many interesting things in these reports:</p>
<ul>
<li>Don&rsquo;t create threads explicitly (this is something we&rsquo;ve been trying to reduce; I already knew about the one remaining, but it&rsquo;s great to see it in a report as a tracked metric)</li>
<li>Methods with too many parameters (you can adjust the threshold, of course)</li>
<li>Types too big: we&rsquo;d have to check these because some of them are probably generated code, in which case we&rsquo;d remove them from analysis.</li>
<li>Abstract constructors should be protected: ReSharper also indicates this one, but we have it as a suggestion, not a warning, so it doesn&rsquo;t get regularly cleaned up. It&rsquo;s not critical, but a code-style thing. I find the NDepend report much easier to browse than the inspection report in TeamCity.</li></ul><p>Click the &ldquo;Low&rdquo; issues (Quino has over 46,000!) and you can see that NDepend analyzes your code at an incredibly low level of granularity</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3546/ndepend_low_level_violations.png"><img src="https://www.earthli.com/data/news/attachments/entry/3546/ndepend_low_level_violations.png" alt=" " style="width: 723px"></a></p>
<ul>
<li>There are almost 10,000 cases where methods could have a lower visibility. This is good to know, but definitely low-priority.</li>
<li>Namespace does not correspond to file location: I&rsquo;m surprised to see 4,400 violations because I thought that ReSharper managed that for us quite well. This one bears investigating – maybe NDepend found something ReSharper didn&rsquo;t or maybe I need to tweak NDepend&rsquo;s settings.</li></ul><p>Finally, there&rsquo;s absolutely everything, which includes boxing/unboxing issues [7], method-names too long, large interfaces, large instances (could also be generated classes).</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3546/ndpend_all_violations.png"><img src="https://www.earthli.com/data/news/attachments/entry/3546/ndpend_all_violations.png" alt=" " style="width: 719px"></a></p>
<p>These already marked as low, so don&rsquo;t worry that NDepend just rains information down on you. Stick to the critical/high violations and you&rsquo;ll have real issues to deal with (i.e. code that might actually lead to bugs rather than code that leads to maintenance issues or incurs technical debt, both of which are more long-term issues).</p>
<p>What you&rsquo;ll also notice in the screenshots that NDepend doesn&rsquo;t just provide pre-baked reports: everything is based on its query language. That is, NDepend&rsquo;s analysis is lightning fast (takes only a few seconds for all of Quino) during which it builds up a huge database of information about your code that it then queries in real-time. NDepends provides a ton of pre-built queries linked from all over the UI, but you can adjust any of those queries in the pane at the top to tweak the results. The syntax is Linq to Sql and there are a ton of comments in the query to help you figure out what else you can do with it.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3546/ndepend_deep_drill_down.png"><img src="https://www.earthli.com/data/news/attachments/entry/3546/ndepend_deep_drill_down.png" alt=" " style="width: 891px"></a></p>
<p>As noted above, the amount of information can be overwhelming, but just hang in there and figure out what NDepend is trying to tell you. You can pin or hide a lot of the floating windows if it&rsquo;s all just a bit too much at first.</p>
<p>In our case, the test assemblies have more technical debt than the code that it tests. This isn&rsquo;t optimal, but it&rsquo;s better than the other way around. You might be tempted to exclude test assemblies from the analysis, to boost your grade, but I think that&rsquo;s a bad idea. Testing code is production code. Make it just as good as the code it tests to ensure overall quality.</p>
<p>I did a quick comparison between Quino 4 and Quino 5 and we&rsquo;re moving in the right direction: the estimation of work required to get to grade A was already cut in half, so we&rsquo;ve made good progress even without NDepend. I&rsquo;m quite looking forward to using NDepend more regularly in the coming months. I&rsquo;ve got my work cut out for me.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3546_1_body" class="footnote-number">[1]</span> Many thanks to Patrick Smacchia of NDepend for generously providing an evaluator&rsquo;s license to me over the years.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3546_2_body" class="footnote-number">[2]</span> We came up with a plan for reducing the size of the core solution in a recent architecture meeting. More on that in a subsequent blog post.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3546_3_body" class="footnote-number">[3]</span> Quino has 10,000 tests, many of which are integration tests, so a change to a highly shared component would trigger thousands of tests to run, possibly for minutes. I can&rsquo;t see how it would be efficient to run tests continuously as I type in Quino. I&rsquo;ve used continuous testing in smaller projects and it&rsquo;s really wonderful (both with ReSharper and also Wallaby for TypeScript), but it doesn&rsquo;t work so well with Quino because of its size and highly generalized nature.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3546_4_body" class="footnote-number">[4]</span> I ran the analysis on both Quino 4 and Quino 5, but wasn&rsquo;t able to directly compare results because I think I inadvertently threw them away with our <code>nant clean</code> command. I&rsquo;d moved the ndepend <code>out</code> folder to the common folder and our command wiped out the previous results. I&rsquo;ll work on persisting those better in the future.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3546_5_body" class="footnote-number">[5]</span> <p>I generated coverage data using DotCover, but realized only later that I should have configured it to generate NDepend-compatible coverage data (as detailed in <a href="https://www.ndepend.com/docs/code-coverage#DotCoverFile">NDepend Coverage Data</a>. I&rsquo;ll have to do that and run it again. For now, no coverage data in NDepend. This is what it looks like in DotCover, though. Not too shabby:</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3546/dotcover_test_coverage.png"><img src="https://www.earthli.com/data/news/attachments/entry/3546/dotcover_test_coverage.png" alt=" " style="width: 375px"></a></p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3546_6_body" class="footnote-number">[6]</span> Getting that documentation out to our developers is also a work-in-progress. Until recently, we&rsquo;ve been stymied by the lack of a good tool and ugly templates. But recently we added <a href="https://dotnet.github.io/docfx/">DocFX</a> support to Quino and the generated documentation is gorgeous. There&rsquo;ll be a post hopefully soon announcing the public availability of Quino documentation.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3546_7_body" class="footnote-number">[7]</span> There&rsquo;s probably a lot of low-hanging fruit of inadvertent allocations here. On the other hand, if they&rsquo;re not code hot paths, then they&rsquo;re mostly harmless. It&rsquo;s more a matter of coding consistently. There&rsquo;s also an extension for ReSharper (the &ldquo;Heap Allocations Viewer&rdquo;) that indicates allocations directly in the IDE, in real-time. I have it installed, and it&rsquo;s nice to see where I&rsquo;m incurring allocations.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3534</guid>
    <title><![CDATA[File-system consistency]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3534</link>
    <pubDate>Sat, 31 Mar 2018 23:28:27 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">31. Mar 2018 23:28:27 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The long and technical article <a href="http://danluu.com/file-consistency/">Files are hard</a> by <cite>Dan Luu</cite> discusses several low-level and scholarly analyses of how common file-systems and user-space applications deal with read/write errors.</p>
<ul>
<li>How theoretically consistent is the file system?</li>
<li>How well-documented are patterns that guarantee consistency?</li>
<li>How well-understand are these patterns in the communities using them?</li>
<li>How do common applications (e.g. source control, databases, etc.) use these patterns?</li>
<li>Are these applications guaranteeing consistency?</li>
<li>What about the file-system designs? Are those airtight?</li>
<li>Are the file-system implementations correct?</li>
<li>How do the various components deal with hardware degradation or failure?</li></ul><h2>Asynchronous programming is hard</h2><p>File-system operations work with <em>devices</em> and are thus asynchronous by nature. The analyses discovered similar ordering issues as with multi-threaded code.</p>
<blockquote class="quote quote-block "><div>&ldquo;The most common class of error was incorrectly assuming ordering between syscalls. The next most common class of error was assuming that syscalls were atomic2. These are fundamentally the same issues people run into when doing multithreaded programming. Correctly reasoning about re-ordering behavior and inserting barriers correctly is hard. But even though shared memory concurrency is considered a hard problem that requires great care, writing to files isn’t treated the same way, even though it’s actually harder in a number of ways.&rdquo;</div></blockquote><p>This is why most applications should use a framework or runtime support to access the file system. Even this might not be enough, though, if the implementation is still not robust enough for the application requirements. The .NET runtime has for quite a while now offered an API that uses async/await (i.e. a promise/future-based API), which at the very least indicates the asynchronous nature of these calls, with separate paths for success and error. This is better than nothing, even if the implementation occasionally fails to properly propagate errors (as we see with the POSIX APIs below).</p>
<p>At any rate, the article drives home the point that programming against file systems is <em>hard</em>.</p>
<blockquote class="quote quote-block "><div>&ldquo;People almost always just run some tests to see if things work, rather than making sure they’re coding against what’s legal in a POSIX filesystem.&rdquo;</div></blockquote><p>Having a few tests is better than nothing, but it&rsquo;s even better to hoist your code up as many levels of abstraction as possible and avoid having to know about how to interleave <code>fsync</code> calls at all. Unless you&rsquo;re writing a database or a source-control system, right?</p>
<h2>A common problem: documentation</h2><p>He goes on to discuss <span class="quote-inline">&ldquo;how much misinformation is out there&rdquo;</span> and that <span class="quote-inline">&ldquo;it’s hard for outsiders to troll through a decade and a half of mailing list postings to figure out which ones are still valid and which ones have been obsoleted&rdquo;</span></p>
<p>This is a common problem that applies not just to low-level systems programming, but to any other programming problem. We have a surfeit of choice: just search online and you&rsquo;ll find <em>something</em> that matches what you searched.</p>
<ul>
<li>Is the source authoritative?</li>
<li>Is the source even competent?</li>
<li>Is the source relevant? Or just kind of related?</li>
<li>Is the source current? Or outdated?</li>
<li>Are you in an echo chamber that feels authoritative but is just a bunch of low-skill developers at a local maximum when the real answer to your problem is elsewhere and is actually much more elegant?</li></ul><p>I recently ran into this phenomenon when learning Docker. Docker has changed and improved so much that the Internet is literally <em>littered</em> with old and overly complicated solutions to problems that either no longer exist or that can be solved with a simple one-liner in a configuration file. If you follow the instructions you find online, it&rsquo;s possible that you&rsquo;ll have something that works the way you want it to, but it&rsquo;s also very likely that you&rsquo;ll end up with a Frankenstein&rsquo;s Monster of a setup that kind of works but is fragile in unnecessary ways.</p>
<h2>Drives are not infallible</h2><p>From the article:</p>
<blockquote class="quote quote-block "><div>&ldquo;So far, we’ve assumed that the disk works properly, or at least that the filesystem is able to detect when the disk has an error via SMART or some other kind of monitoring. I’d always figured that was the case until I started looking into it, but that assumption turns out to be completely wrong.&rdquo;</div></blockquote><p>That sounds bad, of course. It&rsquo;s not something we user-space programmers ever really think about, is it? You read from a file, you write to a file, it works, right? And if it doesn&rsquo;t work (super-rare, right?), then the runtime throws an exception.</p>
<p>If we assume that the runtime throws an exception, we&rsquo;re also assuming that the runtime is <em>notified</em> when an error occurs during a read or write operation. This was, apparently, not the case (at least in 2005-2008; we&rsquo;ll see improvements below).</p>
<blockquote class="quote quote-block "><div>&ldquo;In one presentation, one of the authors remarked that the ext3 code had lots of comments like “I really hope a write error doesn&rsquo;t happen here&rdquo; in places where errors weren&rsquo;t handled. […] NTFS is somewhere in between. The authors found that it has many consistency checks built in, and is pretty good about propagating errors to the user. However, like ext3, it ignores write failures.&rdquo;</div></blockquote><p>Ignoring write failures! That&rsquo;s kind of incredible, but if you&rsquo;ve ever relied heavily on NTFS, you know that there are bugs in it. Sometimes files are just mysteriously locked and inaccessible until the system is rebooted. Why does the problem go away on reboot? NTFS is journaled and can recover its data, but it needs to be unmounted and checked. Instead of panicking, the write error is ignored. [1]</p>
<blockquote class="quote quote-block "><div>&ldquo;At this point, we know that it&rsquo;s quite hard to write files in a way that ensures their robustness even when the underlying filesystem is correct, the underlying filesystem will have bugs, and that attempting to repair corruption to the filesystem may damage it further or destroy it.&rdquo;</div></blockquote><h2>Replicating the results</h2><p>The papers referenced in the first article are quite old (a decade or more) but the conclusions are still fascinating. Luu discusses the need for replicating the study and laments that <span class="quote-inline">&ldquo;replications usually give little to no academic credit. This is one of the many cases where the incentives align very poorly with producing real world impact.&rdquo;</span></p>
<p>Happily, Luu followed up with another post, called <a href="http://danluu.com/filesystem-errors/">File-system error-handling</a> that reproduces some of the original results with the 2017 versions of the file systems. This is an interesting study in its own right, discussing in detail interesting nuggets like the fact that <span class="quote-inline">&ldquo;apfs doesn’t checksum data because “[apfs] engineers contend that Apple devices basically don’t return bogus data”.&rdquo;</span> (from <a href="http://dtrace.org/blogs/ahl/2016/06/19/apfs-part5/">APFS in Detail: Data Integrity</a>).</p>
<p>The second article concludes that <span class="quote-inline">&ldquo;Filesystem error handling seems to have improved.&rdquo;</span> Basic write errors are now propagated to user-space wherever possible (i.e. if the drive is not dead). However, <span class="quote-inline">&ldquo;[m]ost filesystems don’t have checksums for data and leave error detection and correction up to userspace software.&rdquo;</span> This is probably something that most user-space software developers never think about, but it&rsquo;s crucially important. Does your software assume that the file system will always throw an error? Or does it <span class="quote-inline">&ldquo;just assume[…] that filesystems and disks don’t have errors&rdquo;</span>?</p>
<h2>Abstract it away!</h2><p>The first article concludes with a citation from <a href="http://danluu.com/butler-lampson-1999/#parallelism">Butler Lampson</a>:</p>
<blockquote class="quote quote-block "><div>&ldquo;Lampson suggests that the best known general purpose solution is to package up all of your parallelism into as small a box as possible and then have a wizard write the code in the box.&rdquo;</div></blockquote><p>This is generally a good approach for anything complicated: programmers should use as high-level an API as possible for a given task. Problems like security, memory-allocation, file-system access, networking, asynchronous/parallel programming…these all fall into that category. Generally, the advice is, as usual, to get your requirements, make components that satisfy those requirements and include automated tests that verify that the components will continue to satisfy the requirements.</p>
<p>As Lampson says, don&rsquo;t write code that&rsquo;s beyond you—get a &ldquo;wizard&rdquo; to write it instead. That&rsquo;s what most of us do when we use the runtime provided with our language. [2]</p>
<p>The best you can usually do is to abstract away access to external systems (including the file system) so that you can improve behavior later, should it be required. The budget and reliability constraints of a project don&rsquo;t always allow you to program perfectly safely. What you can do is to make sure that the system can be made safer later with a reasonable amount of effort. To be clear: don&rsquo;t be unnecessarily sloppy, but don&rsquo;t tank your project guaranteeing NASA-level safety where its not needed.</p>
<p>So what does that mean? If you&rsquo;re programming on .NET, it means you should probably stay away from some constructs that you&rsquo;ve previously considered safe and not worth wrapping, like <code>File</code> or <code>Directory</code>. Instead of using these directly, use them from an injected service. This level of abstraction is not difficult to enforce if introduced early in a project and will allow for improved testing anyway. If the filesystem is abstracted, components will no longer need their tests to actually write out files in order to work.</p>
<p>As discussed above, this isn&rsquo;t to say that you jeopardize your deadline to abstract away every single file-system reference. For some applications, file-system access is so intrinsic as to be un-mockable (e.g. databases, source-control, etc.). However, your application is probably not one of those. It&rsquo;s likely that your application reads/writes files in a highly localizable manner that could be wrapped in a simple component.</p>
<p>This advice is similar to the by-now common practice of not using the global <code>DateTime.UtcNow</code>. How can this be a problem? Well, if code uses an <code>IClock</code> component instead, then tests can adjust &ldquo;now&rdquo; to be a point in the past or future and test scheduling components more easily. It&rsquo;s an easy pattern to follow in new code that pays for itself the first time you need to reproduce a timing problem.</p>
<h2>Avoiding Bugs</h2><p>At the end of the second article, there&rsquo;s an interesting discussion of how to avoid these kind of bugs—or just bugs, in general.</p>
<blockquote class="quote quote-block "><div>&ldquo;There&rsquo;s a very old debate over how to prevent things like this from accidentally happening.&rdquo;</div></blockquote><p>Better <span class="quote-inline">&ldquo;tools or processes&rdquo;</span>? Be <span class="quote-inline">&ldquo;better programmers&rdquo;</span>? Are tools like guardrails? Does it make sense to keep driving, bashing back and forth across the road, but happy that the guardrails are keeping us on the road at all? Would you do that in a car?</p>
<p>Well, no.</p>
<p>But, yes, if that&rsquo;s the best option? What&rsquo;s the other option? Just stop the car and don&rsquo;t go anywhere anymore? Or get out and walk?</p>
<p>That analogy has been beaten to death—and I don&rsquo;t think it&rsquo;s very appropriate (as you can see from my discussion about abstraction above). Tools and processes are <em>better than nothing</em>. Proper programming practices and patterns are, as well. If you train yourself to use tried-and-true patterns, then you automatically avoid common errors. </p>
<ul>
<li>Use a language with static type-checking [3]</li>
<li>Abstract away interfaces to the system</li>
<li>Use non-nullable references wherever possible</li>
<li>Use immutable data wherever possible [4]</li>
<li>Segregate mutable data into dumb objects</li></ul><p>The point isn&rsquo;t to be able to say that &ldquo;there are no bugs&rdquo;; it&rsquo;s be able to say that &ldquo;these tested bugs won&rsquo;t happen&rdquo;. The point is to use practices that avoid whole classes of problems.</p>
<h2>What are better tools?</h2><blockquote class="quote quote-block "><div>&ldquo;Even better than a static analysis tool would be a language that makes it harder to accidentally forget about checking for an error.&rdquo;</div></blockquote><p>And now we come to the justification for some of the newer languages out there. Rust is such a language, which attempts to fix many of the shortcomings of C and C++ in the domain of allocating, sharing, modifying and freeing memory.</p>
<p>For error-handling, the article <a href="http://joeduffyblog.com/2016/02/07/the-error-model/">The Error Model</a> by <cite>Joe Duffy</cite> discusses a very interesting and promising approach taken by a Microsoft Research team with Midori, a 100%-managed version of Windows. The basic insight is to separate <em>bugs</em> from <em>recoverable errors</em> and unrecoverable errors.</p>
<p>A bug is something the user-space application did wrong (e.g. passing a null reference to a method that expects only non-null references). A recoverable error is a validation error encountered when processing user input. An unrecoverable error is a file-read error in a base configuration file or a stack overflow or an out-of-memory error.</p>
<p>For almost all software, file-system errors are something that should just be considered an unrecoverable error. There is no reason why most applications should attempt to continue when e.g. the main configuration cannot be loaded. Most applications don&rsquo;t even need to be able to recover from that. The problem occurs so rarely that you should just get a file out of backup. </p>
<p>Lower-level applications like Git or PostgreSql have to take more care to deal with file-system errors [5], but your software most likely doesn&rsquo;t need to <em>handle</em> them. As discussed above, be <em>aware</em> that they can happen, <em>abstract</em> your code from the file-system so you can test error situations and improve handling where needed, but <em>fail fast</em> unless your project has a requirement to be able to recover in error conditions.</p>
<p>Generally, no-one expects a user-space application to include robust file-recovery. It&rsquo;s expected, though, that the application detects when something is wrong and reports it, failing fast rather than just limping along and corrupting data.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3534_1_body" class="footnote-number">[1]</span> Anecdotally, it&rsquo;s definitely possible to get file corruption: I&rsquo;ve had critical configuration files filled with <code>NULL</code> bytes after certain catastrophic operations.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3534_2_body" class="footnote-number">[2]</span> Or why we use libraries for tough tasks (e.g. the immutable data-structures libraries for .NET, which provide a performant and correct implementation).</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3534_3_body" class="footnote-number">[3]</span> Not that I didn&rsquo;t say <em>explicit</em> types. I&rsquo;ve used Swift and TypeScript for production code (and played with F#), all of which have inferred types. I still prefer specifying parameter and return types because it helps me localize errors immensely. For most methods, it helps me reason about the code more easily without giving away any flexibility. Still, that&rsquo;s a matter of taste (and, perhaps, familiarity); the point is that static type-checking is a good thing.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3534_4_body" class="footnote-number">[4]</span> The article <a href="http://lucumr.pocoo.org/2018/3/31/you-cant-rust-that/">You can&rsquo;t Rust that</a> by <cite>Armin Ronacher</cite> discusses how to use immutability in a language that provides pretty good support for it, Rust. He comes to the proper conclusion that you should <span class="quote-inline">&ldquo;[c]onsider promoting new state instead of interior mutability&rdquo;</span>, which is, not coincidentally, the same concept that the .NET immutable-collections library uses.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3534_5_body" class="footnote-number">[5]</span> And if you look at the analysis in the first article, Git wasn&rsquo;t particularly radiant, but PostgreSql and Sqlite both did quite well.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3419</guid>
    <title><![CDATA[Adventures in .NET Standard 2.0-preview1]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3419</link>
    <pubDate>Sun, 14 May 2017 21:38:17 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">14. May 2017 21:38:17 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. May 2017 08:36:05 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>.NET Standard 2.0 is finally publicly available as a preview release. I couldn&rsquo;t help myself and took a crack at converting parts of Quino to .NET Standard just to see where we stand. To keep me honest, I did all of my investigations on my MacBook Pro in MacOS.</p>
<h2>IDEs and Tools</h2><p>I installed Visual Studio for Mac, the latest JetBrains Rider EAP and .NET Standard 2.0-preview1. I already had Visual Studio Code with the C#/OmniSharp extensions installed. Everything installed easily and quickly and I was up-and-running in no time.</p>
<p>Armed with 3 IDEs and a powerful command line, I waded into the task.</p>
<h2>Porting Quino to .NET Standard</h2><p>Quino is an almost decade-old .NET Framework solution that has seen continuous development and improvement. It&rsquo;s quite modern and well-modularized, but we still ran into considerable trouble when experimenting with .NET Core 1.1 almost a year ago. At the time, we dropped our attempts to work with .NET Core, but were encouraged when Microsoft shifted gears from the extremely low–surface-area API of .NET Core to the more inclusive though still considerably cleaned-up API of .NET Standard.</p>
<p>Since it&rsquo;s an older solution, Quino projects use the older csproj file-format: the one where you have to whitelist the files to include. Instead of re-using these projects, I figured a good first step would be to use the <code>dotnet</code> command-line tool to create a new solution and projects and then copy files over. That way, I could be sure that I was really only including the code I wanted—instead of random cruft generated into the project files by previous versions of Visual Studio.</p>
<h2>The <code>dotnet</code> Command</h2><p>The <code>dotnet</code> command is really very nice and I was able to quickly build up a list of core projects in a new solution using the following commands:</p>
<ul>
<li><code>dotnet new sln</code></li>
<li><code>dotnet new classlib -n {name}</code></li>
<li><code>dotnet add reference {../otherproject/otherproject.csproj}</code></li>
<li><code>dotnet add package {nuget-package-name}</code></li>
<li><code>dotnet clean</code></li>
<li><code>dotnet build</code></li></ul><p>That&rsquo;s all I&rsquo;ve used so far, but it was enough to investigate this brave new world without needing an IDE. Spoiler alert: I like it very much. The API is so straightforward that I don&rsquo;t even need to include descriptions for the commands above. (Right?)</p>
<p>Everything really seems to be coming together: even the <a href="https://docs.microsoft.com/en-us/dotnet/api/?view=netstandard-2.0">documentation</a> is clean, easy-to-navigate and has very quick and accurate search results.</p>
<h2>Initial Results</h2><ul>
<li><code>Encodo.Core</code> compiles (almost) without change. The only change required was to move project-description attributes that used to be in the <code>AssemblyInfo.cs</code> file to the project file instead (where they admittedly make <em>much</em> more sense). If you don&rsquo;t do this, the compiler complains about <span class="quote-inline">&ldquo;[CS0579] Duplicate &lsquo;System.Reflection.AssemblyCompanyAttribute&rsquo; attribute&rdquo;</span> and so on.</li>
<li><code>Encodo.Expressions</code> references <code>Windows.System.Media</code> for <code>Color</code> and the <code>Colors</code> constants. I changed those references to <code>System.Drawing</code> and <code>Color</code>, respectively—something I knew I would have to do.</li>
<li><code>Encodo.Connections</code> references the .NET-Framework–only <code>WindowsIdentity</code>. I will have to move these references to a <code>Encodo.Core.Windows</code> project and move creation of the <code>CurrentCredentials</code>, <code>AnonymousCredentials</code> and <code>UserCredentials</code> to a factory in the IOC.</li>
<li><code>Quino.Meta</code> references the .NET-Framework–only <code>WeakEventManager</code>. There are only two references and these are used to implement a <code>CollectionChanged</code> feature that is nearly unused. I will probably have to copy/implement the <code>WeakEventManager</code> for now until we can deprecate those events permanently.</li>
<li><code>Quino.Data</code> depends on <code>Quino.Meta.Standard</code>, which references <code>System.Windows.Media</code> (again) as well as a few other things. The <code>Quino.Meta.Standard</code> potpourri will have to be split up.</li></ul><p>I discovered all of these things using just VS Code and the command-line build. It was pretty easy and straightforward.</p>
<p>So far, porting to .NET Standard is a much more rewarding process than our previous attempt at porting to .NET Core.</p>
<h2>The Game Plan</h2><p>At this point, I had a shadow copy of a bunch of the core Quino projects with new project files as well as a handful of ad-hoc changes and commented code in the source files. While OK for investigation, this was not a viable strategy for moving forward on a port for Quino.</p>
<p>I want to be able to work in a branch of Quino while I further investigate the viability of:</p>
<ul>
<li>Targeting parts of Quino to .Net Standard 2.0 while keeping other parts targeting the lowest version of .NET Framework that is compatible with .NET Standard 2.0 (4.6.1).  This will, eventually, be only the Winform and WPF projects, which will never be supported under .NET Standard.</li>
<li>Using the new project-file format for all projects, regardless of target (which IDEs can I still use? Certainly the latest versions of Visual Studio et. al.)</li></ul><p>To test things out, I copied the new <code>Encodo.Core</code> project file back to the main Quino workspace and opened the old solution in <em>Visual Studio for Mac</em> and <em>JetBrains Rider</em>. </p>
<h2>IDE Pros and Cons</h2><h3>Visual Studio for Mac</h3><p>Visual Studio for Mac <em>says</em> it&rsquo;s a production release, but it stumbled right out of the gate: it failed to compile <code>Encodo.Core</code> even though <code>dotnet build</code> had compiled it without complaint from the get-go. Visual Studio for Mac claimed that <code>OperatingSytem</code> was not available. However, according to <a href="https://docs.microsoft.com/en-us/dotnet/api/system.operatingsystem?view=netstandard-2.0">the documentation</a>, <code>Operating System</code> is available for .NET Standard—but not in <em>.NET Core</em>. My theory is that Visual Studio for Mac was somehow misinterpreting my project file.</p>
<p>Update: After closing and re-opening the IDE, though, this problem went away and I was able to build <code>Encodo.Core</code> as well. Shaky, but at least it works now.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3419/visual_studio_for_mac_sdk_mixup.png"><img src="https://www.earthli.com/data/news/attachments/entry/3419/visual_studio_for_mac_sdk_mixup_tn.png" alt=" " class=" align-left"></a>Unfortunately, working with this IDE remained difficult. It stumbled again on the second project that I changed to .NET Standard. <code>Encodo.Core</code> and <code>Encodo.Expressions</code> both have the same framework property in their project files—<code>&lt;TargetFramework&gt;netstandard2.0&lt;/TargetFramework&gt;</code>—but, as you can see in the screenshot to the left, both are identified as <em>.NETStandard.Library</em> but one has version 2.0.0-preview1-25301-01 and the other has version 1.6.1. I have no idea where there second version number is coming from—it looks like this IDE is mashing up the .NET Framework version and the .NET Standard versions. Not quite ready for primetime.</p>
<p>Also, the application icon is mysteriously the bog-standard MacOS-app icon instead of something more…Visual Studio-y.</p>
<h3>JetBrains Rider EAP (April 27th)</h3><p>JetBrains Rider built the assembly without complaint, just as <code>dotnet build</code> did on the command line. Rider doesn&rsquo;t didn&rsquo;t stumble as hard as Visual Studio for Mac, but it also didn&rsquo;t had problems building projects after the framework had changed. On top of that, it wasn&rsquo;t always so easy to figure out what to do to get the framework downloaded and installed. Rider still has a bit of a way to go before I would make it my main IDE.</p>
<p>I also noticed that, while Rider&rsquo;s project/dependencies view accurately reflects .NET Standard projects, the &ldquo;project properties&rdquo; dialog shows the framework version as just &ldquo;2.0&rdquo;. The list of version numbers makes this look like I&rsquo;m targeting .NET Framework 2.0.</p>
<p>Addtionally, Rider&rsquo;s error messages in the build console are almost always truncated. <a href="https://www.earthli.com/data/news/attachments/entry/3419/rider_error.png"><img src="https://www.earthli.com/data/news/attachments/entry/3419/rider_error_tn.png" alt=" " class=" align-right"></a>The image to the right is of the IDE trying to inform me that <code>Encodo.Logging</code> (which was still targeting .NET Framework 4.5) cannot reference <code>Encodo.Core</code> (which references NET Standard 2.0). If you copy/paste the message into an editor, you can see that&rsquo;s what it says. [1]</p>
<h3>Visual Studio Code</h3><p>I don&rsquo;t really know how to get Visual Studio Code to do much more than syntax-highlight my code and expose a terminal from which I can manually call <code>dotnet build</code>. They <a href="https://code.visualstudio.com/Docs/languages/csharp">write about</a> Roslyn integration where <span class="quote-inline">&ldquo;[o]n startup the best matching projects are loaded automatically but you can also choose your projects manually&rdquo;</span>. While I saw that the solution was loaded and recognized, I never saw any error-highlighting in VS Code. The documentation does say that it&rsquo;s <span class="quote-inline">&ldquo;optimized for cross-platform .NET Core development&rdquo;</span> and my projects targeted <em>.NET Standard</em> so maybe that was the problem. At any rate, I didn&rsquo;t put much time into VS Code yet.</p>
<h2>Next Steps</h2><ol>
<li>Convert all Quino projects to use the new project-file format and target .NET Framework. Once that&rsquo;s all running with the new project-file format, it will be much easier to start targeting .NET Standard with certain parts of the framework</li>
<li>Change the target for all projects to .NET Framework 4.6.1 to ensure compatibility with .NET Standard once I start converting projects.</li>
<li>Convert projects to .NET Standard wherever possible. As stated above, <code>Encodo.Core</code> already works and there are only minor adjustments needed to be able to compile <code>Encodo.Expressions</code> and <code>Quino.Meta</code>.</li>
<li>Continue with conversion until I can compile <code>Quino.Schema</code>, <code>Quino.Data.PostgreSql</code>, <code>Encodo.Parsers.Antlr</code> and <code>Quino.Web</code>. With this core, we&rsquo;d be able to run the WebAPI server we&rsquo;re building for a big customer on a Mac or a Linux box.</li>
<li>Given this proof-of-concept, a next step would be to deploy as an OWIN server to Linux on Amazon and finally see a Quino-based application running on a much leaner OS/Web-server stack than the current Windows/IIS one.</li></ol><p>I&rsquo;ll keep you posted. [2]</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3419_1_body" class="footnote-number">[1]</span> <div class="error "><p>Encodo.Expressions.AssemblyInfo.cs(14, 12): [CS0579] Duplicate &lsquo;System.Reflection.AssemblyCompanyAttribute&rsquo; attribute<br>
    Microsoft.NET.Sdk.Common.targets(77, 5): [null] Project &lsquo;/Users/marco/Projects/Encodo/quino/src/libraries/Encodo.Core/Encodo.Core.csproj&rsquo; targets &lsquo;.NETStandard,Version=v2.0&rsquo;. It cannot be referenced by a project that targets &lsquo;.NETFramework,Version=v4.5&rsquo;.</p>
</div></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3419_2_body" class="footnote-number">[2]</span> Update: I investigated a bit farther and I&rsquo;m having trouble using NETStandard2.0 from NETFramework462 (the Mono version on Mac). I was pretty sure that&rsquo;s how it&rsquo;s supposed to work, but NETFramework (any version) doesn&rsquo;t seem to want to play with NETStandard right now. Visual Studio for Mac tells me that <code>Encodo.Core</code> (NETStandard2.0) cannot be used from <code>Encodo.Expressions</code> (Net462), which doesn&rsquo;t seem right, but I&rsquo;m not going to fight with it on this machine anymore. I&rsquo;m going to try it on a fully updated Windows box next—just to remove the Mono/Mac/NETCore/Visual Studio for Mac factors from the equation. Once I&rsquo;ve got things running on Windows, I&rsquo;ll prepare a NETStandard project-only solution that I&rsquo;ll try on the Mac.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3418</guid>
    <title><![CDATA[C# Handbook 7.0]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3418</link>
    <pubDate>Mon, 01 May 2017 21:42:56 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">1. May 2017 21:42:56 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">1. May 2017 22:01:15 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3418/csharp-icon-clr.png"><img src="https://www.earthli.com/data/news/attachments/entry/3418/csharp-icon-clr_tn.png" alt=" " class=" align-left"></a><a href="https://www.earthli.com/news/view_article.php?id=3256">I announced almost exactly one year ago</a> that I was rewriting the Encodo C# Handbook. The original was <a href="https://www.earthli.com/news/view_article.php?id=1817">published almost exactly nine years ago</a>. There were a few <a href="https://www.earthli.com/news/view_article.php?id=2219">more releases</a> as well as a few <a href="https://www.earthli.com/news/view_article.php?id=2506">unpublished</a> <a href="https://www.earthli.com/news/view_article.php?id=2507">chapters</a>.</p>
<p>I finally finished a version that I think I can once again recommend to my employees at <a href="http://encodo.com">Encodo</a>. The major changes are:</p>
<p><span class="clear-both"></span></p>
<ul>
<li>The entire book is now a <a href="https://github.com/mvonballmo/CSharpHandbook">Git Repository</a> (<cite><a href="http://github.com/">GitHub</a></cite>). All content is now in Markdown. Pull requests are welcome.</li>
<li>I&rsquo;ve rewritten pretty much everything. I removed a lot of redundancies, standardized formulations and used a much more economical writing style than in previous versions.</li>
<li>Recommendations now include all versions of C# up to 7</li>
<li>There is a clearer distinction between general and C#-specific recommendations </li>
<li>There are now four main sections: <a href="https://github.com/mvonballmo/CSharpHandbook/blob/master/1_naming.md">Naming</a>, <a href="https://github.com/mvonballmo/CSharpHandbook/blob/master/2_formatting.md">Formatting</a>, <a href="https://github.com/mvonballmo/CSharpHandbook/blob/master/3_usage.md">Usage</a> and <em>Best Practices</em>, which is broken into <a href="https://github.com/mvonballmo/CSharpHandbook/blob/master/4_design.md">Design</a>, <a href="https://github.com/mvonballmo/CSharpHandbook/blob/master/5_safeProgramming.md">Safe Programming</a>, <a href="https://github.com/mvonballmo/CSharpHandbook/blob/master/6_errorHandling.md">Error-handling</a>, <a href="https://github.com/mvonballmo/CSharpHandbook/blob/master/9_documentation.md">Documentation</a> and a handful of other, smaller topics.</li></ul><p>Here&rsquo;s the introduction:</p>
<blockquote class="quote quote-block "><div>&ldquo;The focus of this document is on providing a reference for writing C#. It includes naming, structural and formatting conventions as well as best practices for writing clean, safe and maintainable code. Many of the best practices and conventions apply equally well to other languages.&rdquo;</div></blockquote><p>Check out the <a href="https://github.com/mvonballmo/CSharpHandbook">whole thing</a> (<cite><a href="http://github.com/">GitHub</a></cite>)! Or download the <a href="https://github.com/mvonballmo/CSharpHandbook/blob/master/C%23Handbook.pdf">PDF</a> that I included in the repository.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3391</guid>
    <title><![CDATA[The weird world of type-compatibility in TypeScript]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3391</link>
    <pubDate>Sat, 04 Mar 2017 20:20:22 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Mar 2017 20:20:22 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I recently fixed a bug in some TypeScript code that compiled just fine—but it looked for all the world like it shouldn&rsquo;t have. </p>
<p><small class="notes"><abbr title="too long; didn't read">tl;dr</abbr>: there is no TypeScript compiler bug, but my faith in the TypeScript language&rsquo;s type model is badly shaken.</small></p>
<h2>A simple example</h2><p>The following code compiles—and well it should.</p>
<pre class=" "><code>interface IB {
  name: string;
}

interface IA {
  f(action: (p: IB) =&gt; void): IA;
}

class A implements IA {
  f = (action: (p: IB) =&gt; void): IA =&gt; {
    return this;
  }
}</code></pre><p>Some notes on this example:</p>
<ul>
<li>The shape of interface <code>IB</code> isn&rsquo;t relevant to the discussion.</li>
<li>The intent of interface <code>IA</code> is to require implementors to define a method named <code>f</code> that takes single parameter of type <code>İ =&gt; void</code> and returns <code>IA</code>.</li>
<li>The implementation <code>A</code> above satisfies this requirement. It doesn&rsquo;t do anything with parameter <code>action</code> but that&rsquo;s OK.</li>
<li>The definition of <code>A.f()</code> is what a naive user of TypeScript would assume was the only way of satisfying the requirement from <code>IA</code></li></ul><h2>Oddly compatible lambdas</h2><p>However, the following implementations of <code>IA</code> also compile.</p>
<pre class=" "><code>class A2 implements IA {
  f = (action: () =&gt; IB): IA =&gt; {
    return this;
  }
}

class A3 implements IA {
  f = (action: (p: IB) =&gt; IB): IA =&gt; {
    return this;
  }
}

class A4 implements IA {
  f = (action: () =&gt; void): IA =&gt; {
    return this;
  }
}

class A5 implements IA {
  f = (): IA =&gt; {
    return this;
  }
}</code></pre><h2>Forcing incompatibility</h2><p>The only one I tried that doesn&rsquo;t compile is shown below.</p>
<pre class=" "><code>class A6 implements IA {
  f = (action: (p: number) =&gt; void): IA =&gt; {
    return this;
  }
}</code></pre><p>In this case, the TypeScript compiler rightly shows the following error:</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/3391/compileerror.png" alt=" " style="width: 350px"></p>
<p>Hovering over the class name <code>A5</code> shows the following tooltip:</p>
<blockquote class="quote quote-block "><div><pre class=" ">Class &lsquo;A5&rsquo; incorrectly implements interface &lsquo;IA&rsquo;.
  Types of property &lsquo;f&rsquo; are incompatible.
    Type &lsquo;(action: (p: number) =&gt; void) =&gt; IA&rsquo; is not assignable to type &lsquo;(action: (p: IB) =&gt; void) =&gt; IA&rsquo;.
      Types of parameters &lsquo;action&rsquo; and &lsquo;action&rsquo; are incompatible.
        Type &lsquo;(p: IB) =&gt; void&rsquo; is not assignable to type &lsquo;(p: number) =&gt; void&rsquo;.
          Types of parameters &lsquo;p&rsquo; and &lsquo;p&rsquo; are incompatible.
            Type &lsquo;number&rsquo; is not assignable to type &lsquo;IB&rsquo;.</pre></div></blockquote><p>To summarize, the following types seem to be compatible with <code>İ =&gt; void</code>:</p>
<ul>
<li><code>() =&gt; IB</code></li>
<li><code>İ =&gt; IB</code></li>
<li><code>() =&gt; void</code></li>
<li><em>No parameter at all</em></li></ul><h2>The nitty-gritty of TypeScript&rsquo;s type system</h2><p>In a more strongly typed language like C#, it&rsquo;s clear that none of this would fly. But this is TypeScript, which defines its typing model on compatibility with the dynamic language JavaScript.</p>
<p>It almost looks like the type of the lambda isn&rsquo;t part of the type signature of the method, which came as a quite a surprise to me (and also to my colleague, Urs, who is much more of a TypeScript expert than I am).</p>
<p>But maybe we don&rsquo;t know enough about the TypeScript type system. Let&rsquo;s look at the <a href="http://www.typescriptlang.org/docs/handbook/type-compatibility.html">Type compatibility</a> documentation for TypeScript.</p>
<p>This section starts off with a <span class="quote-inline">&ldquo;Note on Soundness&rdquo;</span>, which contains a note that suggests that what we have above is completely valid TypeScript.</p>
<blockquote class="quote quote-block "><div>&ldquo;The places where TypeScript allows unsound behavior were carefully considered, and throughout this document we’ll explain where these happen and the motivating scenarios behind them.&rdquo;</div></blockquote><p>The section <em>Comparing two functions</em> starts off explaining some rather surprising things about the type-compatibility of functions: for a function to be type-compatible with another function, the types of its parameters must match the types of the target type&rsquo;s parameters, <em>but the number of parameters doesn&rsquo;t have to match</em>. So if the target type has 4 parameters and the lambda to assign has 0 parameters, that lambda is compatible.</p>
<p>From the manual:</p>
<pre class=" "><code>let x = (a: number) =&gt; 0;
let y = (b: number, s: string) =&gt; 0;

y = x; // OK
x = y; // Error</code></pre><p>For return types, the matching behavior is <em>opposite</em>. That is, a &ldquo;bigger&rdquo; type that satisfies the expected return type is just fine.</p>
<pre class=" "><code>let x = () =&gt; ({name: "Alice"});
let y = () =&gt; ({name: "Alice", location: "Seattle"});

x = y; // OK
y = x; // Error because x() lacks a location property</code></pre><h2>Reëxamining the oddly compatible lambdas</h2><p>Armed with this new knowledge, let&rsquo;s see if the previously bizarre-seeming behavior is actually valid.</p>
<p>To recap, the TypeScript compiler says that following signatures are compatible with <code>İ =&gt; void</code>:</p>
<ul>
<li><code>f(() =&gt; IB): IA</code>: this is compatible because the zero parameters conform by definition and any return type is OK because <code>void</code> is expected.</li>
<li><code>f(İ =&gt; IB): IA</code>: this is compatible because the single parameter conforms and any return type is OK because <code>void</code> is expected.</li>
<li><code>f(() =&gt; void): IA</code>: this is compatible because because the zero parameters conform by definition and any return type is OK because <code>void</code> is expected.</li>
<li><code>f() =&gt; IA</code>: this one looks plain wrong at first, but the same logic applies to the whole function <code>f(İ =&gt; void) =&gt; IA</code> instead of to the lambda parameter for it. The interface expects a function <code>f</code> with a single parameter, returning <code>IA</code>. By the first rule above, a function with zero parameters satisfies that requirement.</li>
<li><code>f((number) =&gt; void): IA</code>: This does not satisfy the requirement because <code>number</code> is not compatible with <code>IB</code>.</li>
<li><code>f(number): IA</code>: This does not satisfy the requirement because <code>number</code> is not compatible with <code>İ =&gt; void</code>.</li>
<li><code>f(): void</code>: This does not satisfy the requirement because while zero parameters is OK, the type <code>void</code> is smaller than <code>IA</code>.</li></ul><p>Well, it looks like there&rsquo;s nothing to see here, folks. The compiler is doing exactly what it&rsquo;s supposed to. Move along and get on with your day.</p>
<p>Unfortunately, that means that TypeScript is going to be considerably less helpful for ensuring program correctness than I&rsquo;d previously thought.</p>
<p>In fact, the caveat about Typescript <span class="quote-inline">&ldquo;allow[ing] unsound behavior [in] carefully considered [places]&rdquo;</span> seems a bit disingenuous because, to a programmer accustomed to something like C# or Java or Swift, this kind of type-enforcement for method compatibility cannot be relied upon to enforce much of anything.</p>
<h2>Actual vs. Formal Arguments</h2><p>When I read <a href="https://www.earthli.com/news/www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554"><abbr title="Object-Oriented Software Construction">OOSC2</abbr></a> (<cite><a href="http://www.earthli.com/">Amazon</a></cite>) a long time ago [1], I remember how Bertrand Meyer made the distinction between the <em>formal</em> type of an argument (the type in the method signature) and the <em>actual</em> type of an argument (the runtime type).</p>
<p>The method-type–conformance rules for TypeScript make sense for <em>actual</em> arguments. They ensure compatibility with JavaScript. What&rsquo;s not clear to me is that this same logic be applied to <em>formal</em> arguments that are only available in TypeScript. If I declare a specific type signature in an interface, what are the odds that I want the wishy-washy JavaScript-friendly type rules for those situations? From an architect&rsquo;s point of view, it would certainly be nicer to have more strict type-checking for formal definitions.</p>
<p>Since we don&rsquo;t have that, this very lenient type-compatibility renders type-checking for lambdas largely useless in interface declarations. The compiler won&rsquo;t be able to tell you that your implementation no longer matches the interface declaration because almost anything you write will actually match.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3391_1_body" class="footnote-number">[1]</span> I&rsquo;m a nerd, I read all 1300 pages twice.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3380</guid>
    <title><![CDATA[My Impressions and Notes from VoxxedDays 2017]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3380</link>
    <pubDate>Sat, 04 Mar 2017 00:06:33 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Mar 2017 00:06:33 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Mar 2017 12:07:35 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="http://encodo.com">Encodo</a> presented a short talk at <a href="https://voxxeddays.com/zurich/">Voxxed Days 2017</a> this year, called <a href="https://cfp-vdz.exteso.com/2017/talk/BXA-2258/The_truth_about_code_reviews">The truth about code reviews</a>. Sebastian and I also attended the rest of the conference. The following is a list of notes and reactions to the talks.</p>
<p><hr></p>
<blockquote class="quote pullquote align-left left" style="width: 300px"><div><h2><a href="https://cfp-vdz.exteso.com/2017/talk/PPN-3778/Engineering_You">Engineering You</a></h2><p><em>Martin Thompson</em> — <a href="https://www.youtube.com/watch?v=cJDcPeQG7Bw&amp;list=PLRsbF2sD7JVp2CcMjJqCAzz810iPcOw4t&amp;index=5">Video</a></p>
</div></blockquote><p>The keynote was about our place in the history of software engineering. Martin described us more as alchemists than engineers right now, a sentiment with which I can only agree. There is too little precision, too little reproducibility and too little focus on safety for use to qualify as engineers.</p>
<p>He gave as an example the pride with which car companies brag about the hundreds of millions of lines of code they have running in software in their cars: a claim that should send shivers down your spine. We know how this software is written and how it is tested.</p>
<p><a href="http://encodo.com/en/quino.php">Quino</a> has fewer than 100,000 lines of code (about 85,000, at least 15% of which is obsolete) and we&rsquo;ve been building that for almost 10 years. How a company whose main business is building automobiles guarantees safety and correctness of 300 million lines of code is beyond my comprehension. I would venture that <em>they don&rsquo;t</em>.</p>
<p>Highly recommended talk. Very interesting. Lots of good history mixed with common-sense recommendations, like the following:</p>
<ul>
<li>Code reviews</li>
<li>Iterative design</li>
<li>Be an engineer, not an alchemist</li>
<li>Automate</li>
<li>Test</li></ul><p>References:</p>
<ul>
<li><a href="http://www.scrummanager.net/files/nato1968e.pdf">SOFTWARE ENGINEERING: Report on a conference sponsored by the NATO SCIENCE COMMITTEE Garmisch, Germany, 7th to 11th October 1968</a> (PDF)</li>
<li><a href="https://www.usenix.org/system/files/conference/osdi14/osdi14-paper-yuan.pdf">Simple Testing Can Prevent Most Critical Failures: An Analysis of Production Failures in Distributed Data-Intensive Systems</a> (PDF)</li></ul><p><hr></p>
<blockquote class="quote pullquote align-left left" style="width: 300px"><div><h2><a href="https://cfp-vdz.exteso.com/2017/talk/SAF-7331/Swiss_Transport_in_Real_Time__Tribulations_in_the_Big_Data_Stack">Swiss Transport in Real Time: Tribulations in the Big Data Stack</a></h2><p><em><a href="http://blog.octo.com/en">Alexandre Masselot</a></em> — <a href="https://www.youtube.com/watch?v=yTigmCL68uw&amp;list=PLRsbF2sD7JVp2CcMjJqCAzz810iPcOw4t&amp;index=32">Video</a></p>
</div></blockquote><p>He discussed a proof-of-concept transport-tracking application. Uses the SBB REST API for vehicle positions (using the same API as exposed for the app). Then there is the OpenData Transport API for station-board information, which provides details about delays. Everything is available as JSON with relatively straightforward data models.</p>
<p>Uses Kafka to handle this real-time data pipeline (kind of like Chronicle, RabbitMQ or EasyMQ, but from Apache). The pipeline includes reformatting the data into the desired format (mostly eliding unwanted data), then store them in LogStash and then to ElasticSearch, which allows easy querying of the stored data. This type of data isn&rsquo;t fundamentally relational, so a document-based store is appropriate.</p>
<p>The transformation also involves extrapolating the data that you&rsquo;re interested in from the data you obtained. For example, determining whether a train is stopped. E.g. are there <em>x</em> events with the same position? Is the position near a station?</p>
<p>It was developed in Scala with Akka actors as well as the Play framework for REST. They represented all stations and trains with actors (objects). The actors are async and can run on any number of machines.</p>
<p>After that comes Cassandra? Are they trying to use every possible technology? I&rsquo;m losing track over here. Deployment on Docker. Also uses Zookeeper in another container for load-balancing/redundancy. OMG buzzwords.</p>
<p>He asks: Why not a single application on a single server? Classic Java on Tomcat? It doesn&rsquo;t scale. It can only scale up, but not out. The actual solution feels like a lot of moving parts, but each part does a compartmentalized task, handing off to the next piece. It ends up being quite lightweight, using very little CPU overall.</p>
<p>The simple, one-use components scale natively and relatively easily (LogStash, streaming, docker). The app server using Akka <em>can</em> be scaled, but it&rsquo;s here that you have to invest time to use the available fallback and clustering strategies.</p>
<p>To render the data on the map, they used React to manage the data and d3.js to render. React is fast and scalable (but as Encodo has also discovered, that&rsquo;s not free either). Also, the client-side CPU usage is not insignificant, even with a lot of nodes.</p>
<p>He also discussed UX and UI with tests. How to visualize possibly overlapping and differently sized elements at different zoom levels.</p>
<p>Used Jupiter to analyze data and produce graphs.</p>
<p>Conclusion: offload the parts of your application that aren&rsquo;t your core problem to external software and services. Things like managing data streams, transforming data, etc. Focus on your models and analyzing your data.</p>
<ul>
<li><a href="http://blog.octo.com/en/visualizing-massive-data-streams-a-public-transport-use-case/">Visualizing massive data streams: a public transport use case</a></li>
<li><a href="http://blog.octo.com/en/d3-js-transitions-killed-my-cpu-a-d3-js-pixi-js-comparison/">D3.js transitions killed my CPU! A d3.js &amp; pixi.js comparison</a></li>
<li><a href="https://academic.oup.com/biostatistics/article/11/3/385/257703/An-invitation-to-reproducible-computational">An invitation to reproducible computational research</a></li></ul><p><hr></p>
<blockquote class="quote pullquote align-left left" style="width: 300px"><div><h2><a href="https://cfp-vdz.exteso.com/2017/talk/XYY-0556/Functional_data_structures_in_Java">Functional data structures in Java</a></h2><p><em>Oleg Šelajev</em> — <a href="https://www.youtube.com/watch?v=NWV5IrEg3c0&amp;list=PLRsbF2sD7JVp2CcMjJqCAzz810iPcOw4t&amp;index=26">Video</a></p>
</div></blockquote><p>He discussed how to build reusable structures that don&rsquo;t share mutable state (non-imperative vs. functional).</p>
<ul>
<li>Classic standard libraries define mutable data structures, like lists, arrays, etc. These are not optimal for multi-tasking and asynchronous work. Mutable data structures produce side effects.</li>
<li><code>Void</code> is a &ldquo;code smell&rdquo; because the only reason to call it is to cause a side effect. Prefer pure methods.</li>
<li>A functional data structure has to be immutable.</li>
<li>A functional data structure has to be persistent. This is similar to the first property, but it allows for a new structure to be created that is a mutation of the prior version. Obviously, we want to optimize storage here, reusing as much of the prior version as possible (instead of copying).</li>
<li>This is how mutation works, since we <em>know</em> that the prior version will never change, so it can be freely referenced.</li>
<li>Return values from methods on functional data structures are <em>referentially transparent</em>. You can cache the value without worrying that it will ever change or disappear.</li>
<li>This allows an application to work lock-free instead of guarding access to all possibly mutating methods.</li>
<li>It is easier to reason about functional (pure) data structures.</li></ul><p>Any discussion of data-structure design/implementation will naturally involve balancing performance vs. storage. The safety is baked-in, but performance is always a concern when working with immutable data structures, most especially when changing them.</p>
<p>Even though the <em>average</em> call time for a method is nearly constant (as with most mutable structures), what if you call too many expensive operations and skew the average in real-world use? Well, you can combat this by leveraging the cachability of your collections (as defined above) as a way of memoizing (a well-known performance-optimization technique which carries with it possibly higher storage costs if you can&rsquo;t share the memoized instances very much.)</p>
<p>In some cases, you can reason about performance in the following way: if you get to a situation where you would have to do an expensive operation (e.g. the reverse implicit in balancing head/tail of a queue), you can only get to this situation by having done <em>n</em> cheap operations first. So it is proven that the <em>average</em> is still constant time.</p>
<p>Destructive behavior (like <code>deque</code>) looks different than mutable data structure. In those cases, the operation returns both the removed element as well as a reference to the queue that represents the new state of the queue.</p>
<pre class=" "><code>Tuple&lt;T, Queue&lt;T&gt;&gt; Dequeue();</code></pre><p>For maps, you need a concept called <code>Zip</code> that lets you quickly build a representation of the structure where the element viewed at a particular point in an existing structure is different. So even when a desired mutation would require alteration of a lot of the underlying structure, this operation allows reuse of a lot more of the structure than would otherwise be possible. The node can point to different parent and child nodes, referencing the new part of the structure while embedded in as much of the prior version as possible.</p>
<blockquote class="quote quote-block "><div>&ldquo;Object-oriented programming makes it easier to reason about moving parts. FUnctional programming makes it easier to minimize moving parts.&rdquo;</div></blockquote><p>References:</p>
<ul>
<li><a href="http://cstheory.stackexchange.com/questions/1539/whats-new-in-purely-functional-data-structures-since-okasaki#1550">What&rsquo;s new in purely functional data structures since Okasaki?</a></li></ul><p><hr></p>
<blockquote class="quote pullquote align-left left" style="width: 300px"><div><h2><a href="https://cfp-vdz.exteso.com/2017/talk/UHP-2529/Does_diversity_really_matter_">Does diversity really matter?</a></h2><p><em>Sombra González</em> and <em>Brigitte Hulliger</em> — <a href="https://www.youtube.com/watch?v=dNl7XNL9oQI&amp;list=PLRsbF2sD7JVp2CcMjJqCAzz810iPcOw4t&amp;index=17">Video</a></p>
</div></blockquote><p>This talk began by posing the following questions to the audience.</p>
<ul>
<li>Do you work with women in a technical capacity? (My answer: No. The closest I&rsquo;ve come was a programmer I trained as part of a group of 7 others for a customer.)</li>
<li>Can you remember having been in a meeting with two women or more? (My answer: A couple of project meetings over the last couple of years, but no-one in a technical capacity. Also some con conference calls, but neither of the two female participants were in a technical capacity.)</li></ul><p>Good questions. Good topic. Mostly well-presented, although the middle dragged a bit: Sombra envisioned a (near-)future where women are the same as men in a tech world, a meritocracy. It didn&rsquo;t add very much.</p>
<p>As with everywhere else, the software industry has to figure out how to deal with long maternity leaves. Some countries have introduced &ldquo;rainbow&rdquo; leaves, which allow sharing of the time between partners, so if the partner is male, the industry has to deal with male absence as well. That will probably help increase acceptance of female leave, as it removes the distinction.</p>
<p>For small companies, these kinds of extended leaves are a big hurdle because we can&rsquo;t so easily absorb so much missing capacity.</p>
<p>We haven&rsquo;t improved at all in the last quarter-century: there have been proportionally fewer women in technical software positions every year since 1991. The quit rate is much higher (41%) than for men (17%). This is not primarily due to family concerns, though. It&rsquo;s mostly due to women not feeling comfortable in an industry where they&rsquo;re often the only female in a meeting, on a team or in a company.</p>
<p>Reference:</p>
<ul>
<li><a href="http://weshapetech.com/events.html">@WeShapeTech</a></li></ul><p><hr></p>
<blockquote class="quote pullquote align-left left" style="width: 300px"><div><h2><a href="https://cfp-vdz.exteso.com/2017/talk/BXA-2258/The_truth_about_code_reviews">The truth about code reviews</a></h2><p><em>Sebastian Greulach</em> — <a href="https://www.youtube.com/watch?v=35iBUEIYHU8&amp;list=PLRsbF2sD7JVp2CcMjJqCAzz810iPcOw4t&amp;index=23">Video</a></p>
</div></blockquote><p>This talk is a reduced version of the code-review talk that Sebastian has been doing for <a href="http://encodo.com">Encodo Systems</a> in both English and German over the last year.</p>
<p>The presentation includes some statistics about the value of code reviews, a discussion of which benefits you can expect to get, which types of reviewers are likely to yield which benefits as well as Encodo&rsquo;s approach and advice for integrating code reviews into your development process.</p>
<p>This was the most informative and amazing presentation at the entire show. All kidding aside, the room was packed and the ratings were quite good. There seemed to be a lot of interest in process.</p>
<p>Reference:</p>
<ul>
<li><a href="http://encodo.com/en/documents.php#presentation-2016-1">English slides (long form)</a></li>
<li><a href="http://encodo.com/de/documents.php#presentation-2016-1">German slides (long form)</a></li></ul><p><hr></p>
<blockquote class="quote pullquote align-left left" style="width: 300px"><div><h2><a href="https://cfp-vdz.exteso.com/2017/talk/OWQ-5486/How_Modern_SQL_Databases_Come_up_with_Algorithms_that_You_Would_Have_Never_Dreamed_Of">How Modern SQL Databases Come up with Algorithms that You Would Have Never Dreamed Of</a></h2><p><em>Lukas Eder</em> — <a href="https://www.youtube.com/watch?v=wTPGW1PNy_Y&amp;list=PLRsbF2sD7JVp2CcMjJqCAzz810iPcOw4t&amp;index=19">Video</a></p>
</div></blockquote><p>This guy was supremely entertaining. He is the undisputed master of the animated and reaction GIF in presentations. Informative, spirited and very funny.</p>
<ul>
<li>SQL is a 4GL.</li>
<li>It&rsquo;s a declarative language.</li>
<li>He shows off with a calculation of the Mandelbrot set with PostgreSql (but that&rsquo;s not the presentation)</li>
<li>He presents an example of how to address business needs (e.g. how much money per film per day). Shows how simple joins are in SQL</li>
<li>Then he shows how to do it with classic Java (which sucks). Basically, he shows how good SQL is by slagging on Java</li>
<li>He shows something that could be on <a href="http://annotatiomania.com">Annotatiomania</a></li>
<li>At this point, the Java code is so long that <span class="quote-inline">&ldquo;they can see our code from space.&rdquo;</span></li>
<li>Eager-loading is a code smell. You should actually be able to get the objects that you want in the form that you want. The optimal result type is the exact shape of the data that you want, not the ORM objects. [1]</li>
<li><span class="quote-inline">&ldquo;When does that ever happen? Changing requirements. Never.&rdquo;</span></li>
<li>He&rsquo;s talking about using SQL instead of code because you don&rsquo;t care about algorithms or storage types or caches—let the database developers worry about that. They&rsquo;re good at it. And they love it. And the questions that you&rsquo;re answering are <em>higher-level</em>.</li>
<li>He discusses how Java streams look much, much nicer. But I think .NET Linq is even nicer … and he doesn&rsquo;t mention that at all. So he shows how the more readable API is much better in Java … but it&rsquo;s now exactly how SQL works.</li>
<li>The Java is now more readable, but it&rsquo;s still lazy-loading a ton of data you don&rsquo;t need. You&rsquo;re doing stuff on the client that the database would do much better.</li>
<li>Java Streams are so much uglier than Linq. They are forced to use explicitly typed Tuples (because there is still no <code>var</code>) and the tuple elements are unnamed (<code>p1</code>, <code>p2</code>, etc.) C# 6 is still like this, but C# 7 introduced named items for anonymous tuples.</li>
<li>The general-purpose languages force us to think about these things when they are not our programming domain.</li>
<li>Database also is capable of caching execution plans and optimizing subsequent queries. Prepared queries are da bomb. [2]</li>
<li>Any algorithm that produces the correct result is acceptable. It doesn&rsquo;t matter how you get there.</li>
<li>We don&rsquo;t really know what the database is really doing with a declarative syntax. We probably can&rsquo;t even guess at the optimizations that the clever database is doing. Use &ldquo;Explain Query&rdquo; to see the estimated plan and the actual plan (based on the actual data and current situation on the database instance).</li>
<li>The cardinality is a hint that indicates whether to use linear or logarithmic algorithm. This will also give a hint as the order that the database will load data (e.g. to reduce the dataset as quickly as possible before applies further joins, ordering and restrictions).</li>
<li><img src="http://farm5.static.flickr.com/4152/5186917068_5586abe14f.jpg" alt=" " class=" align-right" style="width: 300px">Conclusion: let the database choose the algorithm based on the dataset available and the current state of the database. He shows an example with a histogram: how a query with one filter might use an index whereas a different filter might be more efficient just scanning the whole table (because 90% of the data is required anyway). The database can take disk-access speed into account. How can the developer predict which algorithm to use? The data and deployment environment isn&rsquo;t known at compile-time. So since you can&rsquo;t know and you&rsquo;re not the guy to decide, then you should offload that decision to the software that does know: the SQL database. What about latencies for remote data? Same thing. Let the database decide.</li>
<li>Unless you&rsquo;re the one writing the database.</li>
<li>The database is really good at this. It remembers how well its estimate matched the actual cost and it uses this to improve its execution plan.</li>
<li>Oracle can actually change the execution plan &ldquo;in flight&rdquo; if it sees during execution that an assumption was grievously wrong.</li>
<li>Also, SQL is functional: no side effects.</li>
<li><span class="quote-inline">&ldquo;Coders want to code; they want to do everything themselves.&rdquo;</span></li>
<li>Also: use production data whenever possible so you have a commensurate dataset size.</li>
<li>Joolambda is a product from his company. Also JOOQ. Looks like Linq, actually. But maybe it works better? Nice clean API which works with arbitrary result sets instead of fixed ORM objects. Can Quino learn something from it? I asked him after the talk where JOOQ gets its metadata and it generates it from the database schema.</li>
<li>Without hash joins there are a whole lot of algorithms that aren&rsquo;t available (MySQL).</li>
<li>Put business logic in the database, but be careful because how do you test it? I talked to Martin, Vlad and Lukas after the talk about testing and we agreed that databases should be immutable (Martin forbids the <code>UPDATE</code> statement in his projects, where he can) and then you basically have an immutable data structure in a separate process with a really powerful and efficient query languages over the graph. [3]</li>
<li>Locks are terribly complicated and performance is unpredictable. He says he&rsquo;s <span class="quote-inline">&ldquo;lucky to only work with read-only databases. So much easier. So much fun.&rdquo;</span></li>
<li>Summary of chat after talk (some repeat from above): Chatted with Martin, Vlad and Lukas [4] after the talk about testing the database. Martin suggested that you don&rsquo;t use the update statement, only insert. Lukas responded similarly, saying that we should use SQL for read-only logical queries. Jooq has a metadata generator for analyzing your database so that you can query it. It doesn&rsquo;t define objects; you can only define the Tuple that you will return. That is pretty cool. Martin also pointed out that you could enforce immutability and store your data in an immutable, queryable graph by using the database.</li></ul><p>References:</p>
<ul>
<li><a href="https://blog.jooq.org/2016/04/25/10-sql-tricks-that-you-didnt-think-were-possible/">10 SQL Tricks That You Didn’t Think Were Possible</a> (<a href="https://www.youtube.com/watch?v=mgipNdAgQ3o">Video</a> (<cite><a href="http://www.youtube.com/">YouTube</a></cite>))</li>
<li><a href="http://bigocheatsheet.com">Big-O Cheat-Sheet</a></li></ul><p><hr></p>
<blockquote class="quote pullquote align-left left" style="width: 300px"><div><h2><a href="https://cfp-vdz.exteso.com/2017/talk/DTE-8339/A_practical_introduction_to_Category_Theory">A practical introduction to Category Theory</a></h2><p><em>Daniela Sfregola</em> — <a href="https://www.youtube.com/watch?v=DsACb1HCcEA&amp;list=PLRsbF2sD7JVp2CcMjJqCAzz810iPcOw4t&amp;index=13">Video</a></p>
</div></blockquote><p>Category theory is about Monads, examples of which are <code>Option</code>, <code>Try</code> and <code>Future</code> (promise).</p>
<p>The example she uses shows how to apply category-theory constructs to data-validation. The examples are in Scala, although the API that she presents looks very similar to the terminology used in Java&rsquo;s Streams API. E.g. <code>flatMap()</code>. That&rsquo;s <code>Select()</code> for C# developers. Similarly, <code>Options</code> is <code>Nullable</code>, although I can&rsquo;t think of the type analog for <code>Some</code> or <code>None</code>.</p>
<p>Her validation example is well-made, going from returning an <code>Option</code> which is no better than a <code>Boolean</code>. Then she shows an <code>Either</code> but that doesn&rsquo;t allow for having both sides wrong. This can be done with <code>Either</code> but it&rsquo;s painful. That&rsquo;s why we invented pattern-matching (now available in C# 7).</p>
<p>When she introduced a <code>Validated</code>, which is capable of returning a list of errors. <span class="quote-inline">&ldquo;Focus on how things compose.&rdquo;</span></p>
<p>The talk was quite short and didn&rsquo;t introduce much new. The pattern-matching syntax in Scala is a bit wordy.</p>
<p><hr></p>
<blockquote class="quote pullquote align-left left" style="width: 300px"><div><h2><a href="https://cfp-vdz.exteso.com/2017/talk/MYE-9920/g___f_patterns">g º f patterns</a></h2><p><em>Mario Fusco</em> — <a href="https://www.youtube.com/watch?v=zmU_ULBzZTQ&amp;list=PLRsbF2sD7JVp2CcMjJqCAzz810iPcOw4t&amp;index=12">Video</a></p>
</div></blockquote><p>Since my previous talk was done early, I joined Sebastian in this one. I saw only the tail-end of it, but man are the streams() libraries still really wordy. Welcome to functional programming, Java! Still, I&rsquo;m disappointed that I can&rsquo;t use <code>streams()</code> in the Android project I&rsquo;m working on because it required Java 8, which forces API level 24, which excludes a <em>lot</em> of devices.</p>
<p>Sebastian said the talk was pretty good.</p>
<p><hr></p>
<blockquote class="quote pullquote align-left left" style="width: 300px"><div><h2><a href="https://cfp-vdz.exteso.com/2017/talk/AQA-4191/What_about_CSS__Progressive_Enhancement_and_CSS">What about CSS? Progressive Enhancement and CSS</a></h2><p><em>Ire Aderinokun</em> — <a href="https://www.youtube.com/watch?v=xStk7gSr8Ek&amp;list=PLRsbF2sD7JVp2CcMjJqCAzz810iPcOw4t&amp;index=10">Video</a></p>
</div></blockquote><ul>
<li>She&rsquo;s from Lagos, Nigeria. Google talk something or other.</li>
<li>Nicest slides I&rsquo;ve seen all day.</li>
<li>Graceful degradation is the solution for only the current best browser. It doesn&rsquo;t necessarily scale to future versions.</li>
<li>Most designers test only one version older than the supported version. Encodo tests the versions required in the spec.</li>
<li>The goal isn&rsquo;t to dazzle the user, but to deliver the information to the widest possible audience.</li>
<li>Admittedly, some sites do have &ldquo;dazzle the user&rdquo; as a goal</li></ul><p>Rules:</p>
<ul>
<li>Use sparse, semantic markup</li>
<li>Use plain text for the content in the markup</li>
<li>The basic layout should work without CSS</li>
<li>CSS is an enhancement</li>
<li>Enhanced behavior can be provided by unobtrusive JavaScript</li>
<li>End-user browser preferences should be respected (e.g. don&rsquo;t restrict zooming the UI, since a lot of users can&rsquo;t see so well)</li></ul><p>WTF is the squirrel browser? (It turns out it&rsquo;s <a href="https://en.wikipedia.org/wiki/UC_Browser">UC Browser</a>, popular in China.) Or the one with the strange globe? (Maybe Flock? Not sure.) Does Opera really have higher market-share than IE? Probably globally, right? Phone browser in India/China/etc.</p>
<p>She showed a really cool graph of how many hours you have to work to use 500MB of data. Germany: 1h, Brazil: 56h, US: 6h. Bandwidth matters. A lot. WWW != Wealthy Western Web ammirite?</p>
<ul>
<li>Use aria rules if you know that you might run on browsers that don&rsquo;t understand the new tag types (increasingly unlikely). Still, phone browsers in Africa probably have never heard of <code>&lt;main&gt;</code> or <code>&lt;header&gt;</code>.</li>
<li>There is no difference between an unsupported CSS property or a bad value or name in the style, selector, etc.</li>
<li>CSS doesn&rsquo;t have built-in fallbacks</li></ul><p>More rules:</p>
<ul>
<li>Start with sensible HTML (same as above)</li>
<li>Go &ldquo;Mobile-first&rdquo;</li>
<li>Use media queries</li>
<li>Use flexbox (was designed as a progressive enhancement, so <code>vertical-align</code> is ignored when flexing is enabled.)</li>
<li>What about &ldquo;Offline-first&rdquo;? That is, making sure that your app works offline to at least some degree. Syncing data can be a pain, depending on the data, though. If you just have data to log, that&rsquo;s independent of other data, it&rsquo;s OK.</li>
<li>Use CSS Feature queries (detect support or NOT support)</li>
<li>Use progressive enhancement to deal with IE, which doesn&rsquo;t support feature queries</li>
<li>A good tip is that a property with a bad value is ignored by the browser.</li></ul><p>What about the future of the web? VR? Old devices handed down from the 1st to the 3rd world. </p>
<p>I asked about testing that the progressive enhancements work as programmed, but no-one has any new ideas for testing, though. Manual testing to verify that the enhancements and fallbacks work.</p>
<p>References:</p>
<ul>
<li><a href="http://bitsofco.de">BitsOfCo.De</a></li>
<li><a href="https://alistapart.com/article/understandingprogressiveenhancement">Understanding Progressive Enhancement</a> by <cite>Aaron Gustafson</cite> (<cite><a href="http://alistapart.com/">AListApart</a></cite>)</li></ul><p><hr></p>
<blockquote class="quote pullquote align-left left" style="width: 300px"><div><h2><a href="https://cfp-vdz.exteso.com/2017/talk/KCP-5900/I_just_hacked_your_app_">I just hacked your app!</a></h2><p><em>Marcos Placona</em> — <a href="https://www.youtube.com/watch?v=BbeZmZ7_YE0&amp;list=PLRsbF2sD7JVp2CcMjJqCAzz810iPcOw4t&amp;index=6">Video</a></p>
</div></blockquote><p>He started off the talk as a bandit, reverse-engineering a Base64-encoded name/password. He used Charles to get MITM. It was a nice trick, and it probably works on a lot of devices and apps.</p>
<p>It&rsquo;s very easy to make a hackable application if you don&rsquo;t think about security. He uses a nice word-definition slide with pronunciation and usage to make it look all official.</p>
<ul>
<li>Pace is a bit slow at first.</li>
<li>Pokemon Hack was a MITM; it wasn&rsquo;t malicious: kids just didn&rsquo;t feel like walking. Important to remember that if motivation is high, a hacker will try <em>really</em> hard.</li>
<li>Beer hack was a loyalty hack (Kuba Gretsky)</li>
<li>Encrypt all the values instead of sending plain-text</li>
<li>But be careful of where you put your keys</li>
<li>This one guy Luke Chadwick uploaded his Amazon key to GitHub by accident. Farmers who watch every damned public commit got it, spun up some EC2 instances and started mining BitCoins</li>
<li>Use security features where possible</li>
<li>Use certificate pinning with the <code>CertificatePinner()</code></li>
<li>Do NOT trust the device</li>
<li>Do NOT trust the app; it can be decompiled.</li>
<li>What about magic strings?</li>
<li>You can get your keys from a server</li>
<li>Or you can encrypt them, but what about the encryption key for the encryption key?</li>
<li>Get the key from the NDK. You can store information in the NDK itself, which is more secure and less decompilable than app code.</li>
<li>Check that the application name hasn&rsquo;t been changed.</li>
<li>Check that the package manager is supported/correct; otherwise, your app has been republished to a new server.</li>
<li>Or you can also check that the installer is Google or Amazon</li>
<li>Check your application signature; you can check whether the app was actually compiled by YOU</li>
<li>Check if the device is rooted (he used some exec() command)</li>
<li>Check for emulator (If the build fingerprint starts with &ldquo;emulator&rdquo;)</li>
<li>Do not allow users to switch your App into debug mode</li>
<li>Use ProGuard, DexGuard. ProGuard is the lite version. DexGuard supports a lot of the checks listed above. DexGuard uses non-Latin Unicode for obfuscation. :-) Unfortunately, it&rsquo;s a per-user charge. That&rsquo;s per user of your app.</li>
<li>So, SafetyNet it is! That&rsquo;s more like it.</li>
<li><span class="quote-inline">&ldquo;The Internet is not a Safe Place&rdquo;</span> (shows a slide of a dirty van with &ldquo;Hannah Montana Concert Shuttle&rdquo; sprayed on the side)</li>
<li>Try to hack your own applications. Always.</li></ul><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3380_1_body" class="footnote-number">[1]</span> Just thinking out loud: Often, though, you want the object, more or less, so it&rsquo;s OK, no? Can we add this kind of anonymous-loading to Quino? It would be interesting to get arbitrary result sets. Like QQL. But it&rsquo;s nice to work with metadata (although we&rsquo;re very close to the SQL model anyway. Can we make it easier to build queries that aggregate?)</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3380_2_body" class="footnote-number">[2]</span> Quino doesn&rsquo;t use those either. Lots of wasted time there. Can we move toward working closer with the database API? How is it that we&rsquo;ve avoided aggregations for so long? We just write those queries by hand.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3380_3_body" class="footnote-number">[3]</span> Also thinking of a talk for next year: Schema Migration with Quino. I really like SQL and it&rsquo;s the best answer to a lot of questions. But I&rsquo;m a programmer and I don&rsquo;t like to define my metadata in table form. I like to describe my model in an agnostic way so that I can <em>re-use</em> my metadata in more than just a database context. Or what about a focus on building metadata-based applications? Capturing your domain model in a way that&rsquo;s not so database-centric?</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3380_4_body" class="footnote-number">[4]</span> Nice clean API which works with arbitrary result sets instead of fixed ORM objects.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3368</guid>
    <title><![CDATA[The evolving Swift string API and implementation]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3368</link>
    <pubDate>Mon, 06 Feb 2017 00:10:55 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">6. Feb 2017 00:10:55 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>As Microsoft did a couple of years ago, Apple&rsquo;s language designers are also designing the next version of Swift in public. [1] One example of the new design is the discussion of <a href="https://github.com/apple/swift/blob/master/docs/StringManifesto.md">String Processing For Swift 4</a> (<cite><a href="http://github.com/">GitHub</a></cite>). If you read through the relatively long document, you can at least see that they&rsquo;re giving the API design a tremendous amount of thought.</p>
<h2>API Considerations for Strings</h2><p>There are so many factors to weigh when building the API, especially for a low-level construct like <code>String</code>.</p>
<ul>
<li>As they state right at the beginning of the document, they are concerned with <span class="quote-inline">&ldquo;Ergonomics, Correctness, Performance&rdquo;</span> (probably in that order).</li>
<li>How does the API affect storage?</li>
<li>Is it still possible to use a <abbr title="Copy On Write">COW</abbr> pattern in order to save memory for multiple copies of the same string? Other, similar languages like C# and Java have slowly moved to a more-eager copying mechanism to reduce complexity in the memory-manager for strings, especially when used in multi-tasking.</li>
<li>How allocation-efficient is the base string library? Does the API help the more well-worn code paths avoid allocation unless absolutely necessary?</li>
<li>What about slicing support? Does the API force copying when it would not be needed? Does it at least allow the decision to copy to be delayed until absolutely necessary?</li>
<li>How accessible are the various supported representations? (E.g. UTF8 vs. UTF16)</li>
<li>How compatible/performant is the optimally <em>ergonomic</em> API with the <a href="https://github.com/apple/swift/blob/master/docs/StringManifesto.md#substrings-ranges-and-objective-c-interop">Objective-C interoperability</a>? This is a common case and must be as close to allocation-free as possible and fast (because thunking between Swift code and Objective-C/Cocoa APIs is very common).</li>
<li>Does the API leverage patterns from other parts of the API rather than expanding the <code>String</code> API with a bunch of overloads? (E.g. the <a href="https://github.com/apple/swift/blob/master/docs/StringManifesto.md#same-type-copied-storage">discussion of storage for sub-strings</a>.)</li>
<li>Is immutable the default, with mutability opt-in? (This prevents unwanted copies and dangling references in the reference-counted world of Swift … although <code>Strings</code> are actually <code>structs</code> rather than <code>classes</code>.)</li>
<li>Does the API do the &ldquo;right thing&rdquo; by default? In the case of Swift&rsquo;s string-handling, this means that the caller of the API works with Unicode graphemes, by default.</li>
<li>What about case-sensitive/insensitive comparisons? Accent sensitivity?</li>
<li>What about ordering? Collation? Localization?</li>
<li>Does the API scale nicely to allow increasing specificity, with good defaults?</li>
<li>Is there consistency within the string API?</li>
<li>What about consistency with similar constructs, like <code>Array</code>?</li>
<li>How does the API fit with with developer expectations? Should the <code>String</code> be a <code>Collection</code>? If so, what is the default item-type?</li>
<li>Why doesn&rsquo;t the <code>Character</code> have the same or a similar API as a <code>String</code>? (E.g. why can&rsquo;t you get the sub-structure of the grapheme cluster for a character without first casting it to a <code>String</code>?)</li></ul><h2>Slices/Substrings</h2><p>A good example is the discussion of how to represent string slices: should there be a separate type, called <code>Substring</code>, analogous to the <code>ArraySlice</code> that already exists for an <code>Array</code>?</p>
<blockquote class="quote quote-block "><div><p>&ldquo;Long-term storage of Substring instances is discouraged. A substring holds a reference to the entire storage of a larger string, not just to the portion it presents, even after the original string&rsquo;s lifetime ends.</p>
<p>&ldquo;[…]</p>
<p>&ldquo;The downside of having two types is the inconvenience of sometimes having a Substring when you need a String, and vice-versa. It is likely this would be a significantly bigger problem than with Array and ArraySlice, as slicing of String is such a common operation. It is especially relevant to existing code that assumes String is the currency type – that is, the default string type used for everyday exchange between APIs. To ease the pain of type mismatches, Substring should be a subtype of String in the same way that Int is a subtype of Optional&lt;Int&gt;.&rdquo;</p>
</div></blockquote><h2>To implement <code>Collection</code> or not?</h2><p>For those that watch as the API for Swift evolves from one major version to another—with each change introducing non–backward-compatible incompatibilities—this document should hopefully reassure them that the changes are not made lightly. It may seem like the designers don&rsquo;t have a plan, but, over the years, designers and opinions change. E.g. Witness the <a href="https://github.com/apple/swift/blob/master/docs/StringManifesto.md#string-should-be-a-collection-of-characters-again">discussion of what the default representation of the string should be</a>.</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] in Swift 1.0, String was a collection of Character (extended grapheme clusters). […] In Swift 2.0, String&rsquo;s Collection conformance was dropped, because we convinced ourselves that its semantics differed from those of Collection too significantly.&rdquo;</div></blockquote><p>After listing several reasons why the change in Swift 2.0 was not a good direction, they conclude that in 4.0, they should revert to the original behavior.</p>
<blockquote class="quote quote-block "><div>&ldquo;It would be much better to legitimize the conformance to Collection and simply document the oddity of any concatenation corner-cases, than to deny users the benefits on the grounds that a few cases are confusing.&rdquo;</div></blockquote><p>Again, the discussion is open and public and, despite the claims of some who think that they&rsquo;re just a bunch of cowboys changing stuff willy-nilly, they have a documented plan. </p>
<p>It&rsquo;s unfortunate that it took them so long to get there, but this kind of design isn&rsquo;t always easy.</p>
<h2>Consolidating Index Types</h2><p>Because Swift uses Unicode grapheme clusters as the default &ldquo;items&rdquo; view for strings, the discussion of <a href="https://github.com/apple/swift/blob/master/docs/StringManifesto.md#string-indices">string indices</a> might seem unnecessarily abstract for developers coming from other languages, where the index is always an <code>int</code> int <code>bytes</code>.</p>
<blockquote class="quote quote-block "><div>&ldquo;String currently has four views–characters, unicodeScalars, utf8, and utf16 […]&rdquo;</div></blockquote><p>Because of these different views, it&rsquo;s necessary to discuss how to reduce API surface by consolidating the various index types used to refer to individual elements in these different &ldquo;views&rdquo; on a <code>String</code>.</p>
<h2>Doing the Right Thing</h2><p>It&rsquo;s not like C#—and most other mainstream languages—have anything to brag about with their string-handling. In that respect, even Swift 1 and 2 are light-years ahead in Unicode correctness with their focus on grapheme clusters rather than the utterly nonsensical 90s-era <code>bytes</code> still used in those other languages.</p>
<p>The <a href="https://github.com/apple/swift/blob/master/docs/StringManifesto.md#guidance-for-api-designers">Guidance for API Designers</a> shows how they try to build the API so that it makes sense for callers.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;A Substring passed where String is expected will be implicitly copied. When compared to the &ldquo;same type, copied storage&rdquo; model, we have effectively deferred the cost of copying from the point where a substring is created until it must be converted to String for use with an API.</p>
<p>&ldquo;A user who needs to optimize away copies altogether should use this guideline: if for performance reasons you are tempted to add a Range argument to your method as well as a String to avoid unnecessary copies, you should instead use Substring.&rdquo;</p>
</div></blockquote><p>Their goal is noble, though it&rsquo;s unclear to what degree the vision can be realized. The <a href="https://github.com/apple/swift/blob/master/docs/StringManifesto.md#unified-pattern-matcher-protocol">following citation</a> could be written as the high-level goal of <em>any</em> API.</p>
<blockquote class="quote quote-block "><div>&ldquo;We should represent these aspects as orthogonal, composable components, abstracting pattern matchers into a protocol like this one, that can allow us to define logical operations once, without introducing overloads, and massively reducing API surface area.&rdquo;</div></blockquote><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3368_1_body" class="footnote-number">[1]</span> Also as Microsoft did, Apple now has an <a href="https://bugs.swift.org/">official, public issue tracker for Swift.</a> [2] You could have knocked me over with a feather.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3368_2_body" class="footnote-number">[2]</span> The downside: it&rsquo;s <em>Atlassian Jira</em>.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3367</guid>
    <title><![CDATA[A tuple-inference bug in the Swift 3.0.1 compiler]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3367</link>
    <pubDate>Sat, 04 Feb 2017 18:17:03 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Feb 2017 18:17:03 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">5. Feb 2017 23:42:56 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I encountered some curious behavior while writing a service-locator interface (_protocol_) in Swift. I&rsquo;ve reproduced the issue in a stripped-down playground [1] and am almost certain I&rsquo;ve found a bug in the Swift 3.0.1 compiler included in XCode 8.2.1.</p>
<p><small class="notes">Update: At the suggestion of a reader, I searched and found <a href="https://bugs.swift.org/">Apple&rsquo;s Jira for Swift</a> [2] and reported this issue as <a href="https://bugs.swift.org/browse/SR-3865">A possible tuple-inference/parameter-resolution bug in Swift 3.0.1</a></small></p>
<h2>A Simple, Generic Function</h2><p>We&rsquo;ll start off with a very basic example, shown below.</p>
<p><span style="width: 690px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3367/simplesinglelabeledargument.png"><img src="https://www.earthli.com/data/news/attachments/entry/3367/simplesinglelabeledargument.png" alt=" " style="width: 690px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3367/simplesinglelabeledargument.png">Simple argument with label</a></span></span></p>
<p>The example above shows a very simple function, generic in its single parameter with a required argument label <code>a:</code>. As expected, the compiler determines the generic type <code>T</code> to be <code>Int</code>.</p>
<p>I&rsquo;m not a big fan of argument labels for such simple functions, so I like to use the <code>_</code> to free the caller from writing the label, as shown below.</p>
<p><span style="width: 690px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3367/simplesinglenolabelargument.png"><img src="https://www.earthli.com/data/news/attachments/entry/3367/simplesinglenolabelargument.png" alt=" " style="width: 690px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3367/simplesinglenolabelargument.png">Simple argument without label</a></span></span></p>
<p>As you can see, the result of calling the function is unchanged.</p>
<h2>Or Maybe Not So Simple?</h2><p>Let&rsquo;s try calling the function with some other combinations of parameters and see what happens.</p>
<p><span style="width: 748px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3367/nolabelargumentmakeseverythingatuple.png"><img src="https://www.earthli.com/data/news/attachments/entry/3367/nolabelargumentmakeseverythingatuple.png" alt=" " style="width: 748px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3367/nolabelargumentmakeseverythingatuple.png">Label-less argument with tuples and multiple parameters</a></span></span></p>
<p>If you&rsquo;re coming from another programming language, it might be quite surprising that the Swift compiler happily compiles every single one of these examples. Let&rsquo;s take them one at a time.</p>
<ul>
<li><code>int</code>: This works as expected</li>
<li><code>odd</code>: This is the call that I experienced in my original code. At the time, I was utterly mystified how Swift—a supposedly very strictly typed language—allowed me to call a function with a single parameter with <em>two</em> parameters. This example&rsquo;s output makes it more obvious what&rsquo;s going on here: Swift interpreted the two parameters as a <em>Tuple</em>. Is that correct, though? Are the parentheses allowed to serve double-duty both as part of the function-call expression <em>and</em> as part of the tuple expression?</li>
<li><code>tuple</code>: With two sets of parentheses, it&rsquo;s clear that the compiler interprets <code>T</code> as tuple <code>(Int, Int)</code>.</li>
<li><code>labels</code>: The issue with double-duty parentheses isn&rsquo;t limited to anonymous tuples. The compiler treats what looks like two labeled function-call parameters as a tuple with two Ints labeled <code>a:</code> and <code>b:</code>.</li>
<li><code>nestedTuple</code>: The compiler seems to be playing fast and loose with parentheses inside of a function call. The compiler sees the same type for the parameter with one, two and three sets of parentheses. [3] I would have expected the type to be <code>((Int, Int))</code> instead. </li>
<li><code>complexTuple</code>: As with <code>tuple</code>, the compiler interprets the type for this call correctly.</li></ul><h2>Narrowing Down the Issue</h2><p>The issue with double-duty parentheses seems to be limited to function calls without argument labels. When I changed the function definition to require a label, the compiler choked on all of the calls, as expected. To fix the problem, I added the argument label for each call and you can see the results below.</p>
<p><span style="width: 751px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3367/labeledargumentmakesmoresense.png"><img src="https://www.earthli.com/data/news/attachments/entry/3367/labeledargumentmakesmoresense.png" alt=" " style="width: 751px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3367/labeledargumentmakesmoresense.png">Labeled argument with tuples and multiple parameters</a></span></span></p>
<ul>
<li><code>int</code>: This works as expected</li>
<li><code>odd</code>: With an argument label, instead of inferring the tuple type <code>(Int, Int)</code>, the compiler correctly binds the label to the first parameter <code>1</code>. The second parameter <code>2</code> is marked as an error.</li>
<li><code>tuple</code>: With two sets of parentheses, it&rsquo;s clear that the compiler interprets <code>T</code> as tuple <code>(Int, Int)</code>.</li>
<li><code>labels</code>: This example behaves the same as <code>odd</code>, with the second parameter <code>b: 2</code> flagged as an error.</li>
<li><code>nestedTuple</code>: This example works the same as <code>tuple</code>, with the compiler ignoring the extra set of parentheses, as it did without an argument label.</li>
<li><code>complexTuple</code>: As with <code>tuple</code>, the compiler interprets the type for this call correctly.</li></ul><h2>Swift Grammar</h2><p>I claimed above that I was pretty sure that we&rsquo;re looking at a compiler bug here. I took a closer look at the productions for tuples and functions defined in <em>The Swift Programming Language (Swift 3.0.1)</em> manual available from Apple.</p>
<p>First, let&rsquo;s look at tuples:</p>
<p><span style="width: 553px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3367/grammarofatupleexpression.png"><img src="https://www.earthli.com/data/news/attachments/entry/3367/grammarofatupleexpression.png" alt=" " style="width: 553px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3367/grammarofatupleexpression.png">Grammar of a Tuple Expression</a></span></span></p>
<p>As expected, a tuple expression is created by surrounding zero or more comma-separated expressions (with optional identifiers) in parentheses. I don&rsquo;t see anything about <em>folding</em> parentheses in the grammar, so it&rsquo;s unclear why <code>(((1)))</code> produces the same type as <code>(1)</code>. Using parentheses makes it a bit difficult to see what&rsquo;s going on with the types, so I&rsquo;m going to translate to C# notation.</p>
<ul>
<li><code>()</code> =&gt; empty tuple [4]</li>
<li><code>(1)</code> =&gt; <code>Tuple&lt;int&gt;</code></li>
<li><code>((1))</code> =&gt; <code>Tuple&lt;Tuple&lt;int&gt;&gt;</code></li>
<li>…and so on.</li></ul><p>This seems to be a separate issue from the second, but opposite, problem: instead of ignoring parentheses, the compiler allows one set of parentheses to simultaneously denote the argument clause of a single-arity function call <em>and</em> an argument of type <code>Tuple</code> encompassing all parameters.</p>
<p>A look at the grammar of a function call shows that the parentheses are required.</p>
<p><span style="width: 566px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3367/grammarofafunctioncallexpression.png"><img src="https://www.earthli.com/data/news/attachments/entry/3367/grammarofafunctioncallexpression.png" alt=" " style="width: 566px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3367/grammarofafunctioncallexpression.png">Grammar of a Function Call Expression</a></span></span></p>
<p>Nowhere did I find anything in the grammar that would allow the kind of folding I observed in the compiler, as shown in the examples above. I&rsquo;m honestly not sure how that would be indicated in grammar notation.</p>
<h2>Conclusion</h2><p>Given how surprising the result is, I can&rsquo;t imagine this is anything but a bug. Even if it can be shown that the Swift compiler is correctly interpreting these cases, it&rsquo;s  confusing that the type-inference is different with and without labels.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3367_1_body" class="footnote-number">[1]</span> <p>The X-Code playground is a very decent REPL for this kind of example. Here&rsquo;s the code I used, if you want to play around on your own.</p>
<pre class=" "><code>func test&lt;T&gt;(_ a: T) -&gt; String
{
  return String(describing: type(of: T.self))
}

var int = test(1)
var odd = test(1, 2)
var tuple = test((1, 2))
var labels = test(a: 1, b: 2)
var nestedTuple = test(((1, 2)))
var complexTuple = test((1, (2, 3)))</code></pre></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3367_2_body" class="footnote-number">[2]</span> I was amazed to find that Apple actually has a normal bug tracker for which I could create an account. Wonders never cease.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3367_3_body" class="footnote-number">[3]</span> I didn&rsquo;t include the examples, but the type is unchanged with four, five and six sets of parentheses. The compiler treats them as semantically irrelevant, though the Swift grammar doesn&rsquo;t allow for this, as far as I could tell from the BNF in the official manual.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3367_4_body" class="footnote-number">[4]</span> This is apparently legal in Swift, but I can&rsquo;t divine its purpose in an actual program</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3356</guid>
    <title><![CDATA[Programming-language Features: How much is too much?]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3356</link>
    <pubDate>Sun, 15 Jan 2017 23:40:49 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Jan 2017 23:40:49 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2023 21:24:02 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="http://blog.cleancoder.com/uncle-bob/2017/01/11/TheDarkPath.html">Dark Path</a> by <cite>Robert C. Martin</cite> was an interesting analysis of a recent &ldquo;stricter&rdquo; trend in programming languages, as evidenced by Swift and Kotlin. I think TypeScript is also taking some steps along this path, as well as Rust, which I have a read a lot about, but haven&rsquo;t had much occasion to use.</p>
<h2>Correct vs. Expressive</h2><p>The point Martin makes is that all of these languages seem to be heedlessly improving correctness at the possible cost of expressiveness and maintainability. That is, as types are inferred from implementation, it can become more difficult to pinpoint where the intent of the programmer and the understanding of the compiler parted ways. As well, with increasing strictness—e.g. non-null references, reference-ownership, explicit exceptions, explicit overrides—there comes increasing overhead in maintaining code.</p>
<p>Not only that, but developers must know their types—and hence their design—up front, which restricts evolving design as practiced in the very successful TDD approach and seems to be headed back to the stone age of waterfall design. As well, that level of strictness convinces developers—who are similarly encouraged by the language designers—that once their code compiles, then it runs as expected.</p>
<p>But then they think they don&rsquo;t need to test, whereas the compiler really has no idea whether your code does what it should do. All it can guarantee is that no exception went unhandled—or explicitly ignored—(e.g. in Kotlin or Swift) or there are no race conditions or deadlocks (Rust) or that there are no null references where not explicitly programmed (Swift, Kotlin, TypeScript).</p>
<p>These compiler-enforced language features are very useful, but are in the same class as the spell-checker in your text editor. Having no red, wavy lines in your document is no guarantee that the document makes any sense whatsoever.</p>
<p>So these are interesting and useful features. They can lead to increased safety. But, they won&rsquo;t make your program do what it&rsquo;s supposed to do. At best, they help you avoid writing behavior that you most definitely don&rsquo;t want.</p>
<p>These features are nice to have, but they are not worth having at any price.</p>
<h2>Round Two: Defaming Types</h2><p>It was an interesting article that I more-or-less agreed with. The follow-up article <a href="http://blog.cleancoder.com/uncle-bob/2017/01/13/TypesAndTests.html">Types and Tests</a> by <cite>Robert C. Martin</cite> (<cite><a href="http://blog.cleancoder.com/">Clean Coder Blog</a></cite>) followed close on its heels because Martin apparently wanted to respond to feedback he&rsquo;d received on the first article. I thought he went a bit far in the second article. For example, he emphasized that,</p>
<blockquote class="quote quote-block "><div>&ldquo;No, types are not tests. Type systems are not tests. Type checking is not testing. Here’s why.&rdquo;</div></blockquote><p>That&rsquo;s absolutely true, but types are still related to testing. Types help me specify my interface more precisely and I can trust the compiler to enforce them. That&rsquo;s a lot of tests I don&rsquo;t have to write.</p>
<p>Otherwise, for every API I write, I&rsquo;d have to write tests to <em>prove</em> that only the supported types can be passed in—and I&rsquo;d also have to specify how my API behaves when value with an incorrect type is passed in. Do I fail silently? How do I let the caller know what to expect? This seems not only sloppy but time-consuming. It sounds like busy work, having to think about this kind of stuff for every API.</p>
<h2>Precise Requirements</h2><p>Martin continues,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] the way <code>f</code> is called has nothing to do with the required behavior of the system. Rather it is a test of an arbitrary constraint imposed by the programmer. <strong>A constraint that was likely over[-]specified from the point of view of the system requirements.</strong> (Emphasis added.)&rdquo;</div></blockquote><p>The first sentence is a useful observation. The second is hyperbole. Indicating <code>int</code> rather than <code>object</code> for a parameter called <code>limit</code> hardly seems like an over-specification. In fact, in seems like exactly what I want.</p>
<p>If the requirement says <em>shall allow a user to enter a <strong>value</strong> for limit…</em> rather than <em>shall allow a user to enter a <strong>positive number</strong> for limit…</em>, then I would argue that 99% of the time it&rsquo;s the requirement that isn&rsquo;t precise enough. I would not assume that the requirements engineer knew just what she was doing when she left the door open for a limit given as a <code>string</code>.</p>
<p>Without types, our requirements would also become bloated with over-definitions like:</p>
<ul>
<li>The system shall allow the user to enter a value that defines the upper limit of records to return.</li>
<li>The system shall throw an exception of type <code>ArgumentOutOfRangeException</code> for values that are less than zero or greater than 1000.</li>
<li>The system shall marshal the value to a numeric representation where necessary.</li>
<li>The system shall throw an exception of type <code>ClassCastException</code> if the given value cannot be marshaled to a numeric value.</li></ul><p>For this specification, a developer could write:</p>
<pre class=" "><code>public void SetLimit(object limit)
{
  int limitAsNumber;
  if (!Int32.ParseInt(limit, out limitAsNumber))
  {
    throw new ClassCastException("…");
  }

  if (limitAsNumber &gt; 1000)
  {
    throw new ArgumentOutOfRangeException("limit");
  }

  _limit = limit;
}</code></pre><p>The developer could also write:</p>
<pre class=" "><code>public void SetLimit(UInt32 limit)
{
  if (limit &gt; 1000)
  {
    throw new ArgumentOutOfRangeException("limit");
  }

  _limit = limit;
}</code></pre><p>That&rsquo;s actually what we <em>want</em> the developer to write, no? If you choose JavaScript to implement this requirement, then you would need to over-specify because you need to decide how to handle values with unsupported types. If the requirements engineer is allowed to assume that the implementing language has a minimal type system, then the requirements are also easier to write, as shown below.</p>
<ul>
<li>The system shall allow the user to enter a <strong class="highlight">positive integer</strong> that defines the upper limit of records to return.</li>
<li>The system shall throw an exception of type <code>ArgumentOutOfRangeException</code> for values that are less than zero or greater than 1000.</li>
<li><del>The system shall marshal the value to a numeric representation where necessary.</del></li>
<li><del>The system shall throw an exception of type <code>ClassCastException</code> if the given value cannot be marshaled to a numeric value.</del></li></ul><h2>Expressive Types are a Good Thing</h2><p>Assuming a minimal type system in the target language <em>saves time and effort</em>. The requirements engineer can specify more concisely and the software engineer wastes less time writing boilerplate that has nothing to do with application behavior.</p>
<p>Martin finished up with this sentiment,</p>
<blockquote class="quote quote-block "><div>&ldquo;So, no, type systems do not decrease the testing load. <strong>Not even the tiniest bit.</strong> But they can prevent some errors that unit tests might not see. (e.g. Double vs. Int) (Emphasis added.)&rdquo;</div></blockquote><p>As you can imagine, I strongly disagree with the <span class="quote-inline">&ldquo;[n]ot even the tiniest bit&rdquo;</span> part, based on my arguments above. If you use JavaScript, then you have to test all valid input and verify its behavior. In JavaScript, literally any data is valid input and it&rsquo;s up to your method to declare it invalid.</p>
<p>Only tests can provide any protection against your method being called at runtime with invalid data. You have to write a test to verify that your method throws an error when passed a <code>double</code> rather than an <code>int</code>. Most people will not write these kind of tests, which I suspect is why Martin says there&rsquo;s no change in testing load.</p>
<h2>Strict Languages for Bad Programmers?</h2><p>I agree that the pendulum in Swift has swung too far in a restrictive direction. The language does feel pretty overloaded. I also agree that the behavior of the system itself needs to be tested and that types don&rsquo;t help you there.</p>
<p>Martin again,</p>
<blockquote class="quote quote-block "><div>&ldquo;On the other hand, internal self-consistency does not mean the program exhibits the correct behavior. <strong>Behavior and self-consistency are orthogonal concepts.</strong> Well behaved programs can be, and have been, written in languages with high ambiguity and low internal consistency. Badly behaved programs have been written in languages that are deeply self-consistent and tolerate few ambiguities. (Emphasis added.)&rdquo;</div></blockquote><p>Agreed.</p>
<p>I think, though, that Martin might be forgetting about all of the people writing software who aren&rsquo;t the kind of people who can write a well-behaved program in a wildly inconsistent language. I, for example, am so awesome [1] that I wrote my entire web-site software in PHP—one of the worst languages in the world for internal self-consistency—and it&rsquo;s been running my site for going on 18 years. Programming skill and iron discipline fill the gap left by language consistency.</p>
<p>But for bad programmers? They write utter garbage in PHP. Maybe it&rsquo;s not a bad idea to create languages that channel poorly disciplined programmers into better practices. I take the point from the previous article (<a href="http://blog.cleancoder.com/uncle-bob/2017/01/11/TheDarkPath.html">Dark Path</a>) that bad programmers will simply work their way around the rigor, where possible. They will mark every class as <code>open</code> in Swift instead of thinking about their architecture.</p>
<p>For those of us with discipline, the language will put up roadblocks that force us to write more code rather than less.</p>
<h2>Unfixable Errors?</h2><p>As a counterexample, there is Rust, which enforces reference-ownership in a way that guarantees concurrent code with no deadlocks and no race conditions. This is a good thing. It probably gets in your way when you&rsquo;re trying to write other types of programs, but it&rsquo;s overall a good thing.</p>
<p>I haven&rsquo;t had any personal experience with it, but I&rsquo;ve heard that it&rsquo;s sometimes difficult to figure out <em>why</em> a given program won&rsquo;t compile. I would hope that these situations become fewer with experience, but would also be cautious because I remember programming in C++ with templates and know how much time can be lost when you don&rsquo;t know how to fix your program based on an error message.</p>
<h2>Non-nullable types are not a step too far</h2><p>I, for one, <em>like</em> that my compiler tells me when I have potential null-reference exceptions. I use attributes in C# to tell me exactly that and I use R# to find all places in my code where I have potential violations. Those are more tests that I don&rsquo;t have to write, if the compiler can &ldquo;prove&rdquo; that this code is never called with a <code>null</code> reference. [2] It lets me write more concise implementation and spares me a lot of scaffolding.</p>
<h2>What about const/non-mutable types?</h2><p>Many years ago, I had the same experience with <code>const</code> in C++ as Martin discusses. After some time working with <code>const</code>, I starting making everything I possibly could <code>const</code> in order to eliminate a whole class of mutation errors in my code. That did have consequences, at the time. Changing one thing could—as Martin describes for his hypothetical language TDP—lead to knock-on changes throughout the code base.</p>
<p>Generics can have this effect, as well, with changes leaking into all of the places they&rsquo;re used. I wrote a <a href="https://www.earthli.com/news/view_article.php?id=3166">blog series</a> on having pulled back from generics in a few central places in Quino.</p>
<h2>Exceptions in method signatures</h2><p>I often felt the way that Martin does about Java&rsquo;s <code>throws</code> declaration. I imagine that I&rsquo;ll start to feel the same about Swift&rsquo;s, as well. I read once about a <a href="http://joeduffyblog.com/2016/02/07/the-error-model/">nice typing system in Midori</a>, the managed version of Windows created by Joe Duffy and team at Microsoft Research, that I felt I would like to try (no pun intended).</p>
<h2>Toward more expressive types</h2><p>Martin says that he uses both dynamically and statically typed languages. He acknowledges that certain extensions to the type system can be useful (but just that some languages have gone too far).</p>
<p>I, too, think some innovations can be very helpful. I <em>like</em> immutables (types, declarations, whatever) because they let me reason better about my code. They let me eliminate unwanted code paths with the compiler rather than having to write more rote tests that I think even Martin will agree have nothing to do with the original specification or the behavior of my application.</p>
<p>If I can mark something as readonly because I don&rsquo;t expect it to ever need to be changed, that&rsquo;s a little note I&rsquo;ve left for future programmers that, should they want to modify that value, they will have to make sure to reason differently about the implementation. The value was never intended to be rewritten and there are no tests for that behavior. It&rsquo;s a nice way of reducing the scope of the implementation.</p>
<p>It simultaneously restricts that scope, but that&rsquo;s a good thing. A program can, very quickly, do a lot of things that it should not do. I don&rsquo;t want to write tests for all of this stuff. I have neither the inclination nor the time—nor the budget—to write tests for things that I could instead eliminate entirely from the realm of possibility with a powerful type system.</p>
<h2>Agreeing with Martin</h2><p>I read up on Kotlin and saw a seminar on it last year. I, too, noticed that there seems to be an &ldquo;everything but the kitchen sink&rdquo; feel to it. It&rsquo;s the same feeling I get when I look at Scala&rsquo;s type system, though that one is less about restriction than about letting you do everything in 3 different ways.</p>
<p>I&rsquo;ve been reading through the Swift language guide and I&rsquo;m getting the same feeling. It doesn&rsquo;t help that they have their own name and keyword for nearly every commonly known programming concept. You can use <code>self.</code> but the guide prefers just <code>.</code>, which takes some getting used to. <code>finally</code>? Nope. Use <code>defer</code> instead.</p>
<h2>An example from TypeScript</h2><p>To be honest, I&rsquo;m also a bit dizzy at how quickly the TypeScript type system has gotten more and more complex. <a href="https://blog.mariusschulz.com/2017/01/06/typescript-2-1-keyof-and-lookup-types">TypeScript 2.1: keyof and Lookup Types</a> by <cite>Marius Schulz</cite> includes details on even more typing specifications that let you infer types from dynamic objects with flow-control analysis.</p>
<p>I think this is quite an interesting approach, akin to more functional languages, like ML and F#, where return types are inferred and even parameter types are inferred. Swift has also gone a long way in this direction. Interfaces are replaced with non-inheritable types that describe the shape of data.</p>
<p>Types can even be inferred by which fields you access within conditionals so that a single variable has a different inferred type depending on which path through the code it takes. It&rsquo;s all very exciting, but I wonder how much can be used correctly—especially by the aforementioned crappy programmers.</p>
<p>For example, this is the definition for the <code>Object.entries()</code> method from JavaScript.</p>
<pre class=" "><code>interface ObjectConstructor {
    // …
    entries&lt;T extends { [key: string]: any }, K extends keyof T&gt;(o: T): [keyof T, T[K]][];
    // …
}</code></pre><h2>Inferred method return-types</h2><p>After having used languages that have explicit return types for methods, I&rsquo;m still a bit at sea when I read TypeScript code without them. I find myself hovering identifiers to see which type was inferred for them by the real-time compilation.</p>
<p>I agree that the code is cleaner, but maybe something&rsquo;s gone missing. It&rsquo;s harder to tell what the hell I&rsquo;m supposed to pass in as a parameter or what the hell I get back from a function when the type can be a union of 3 or 4 other vaguely and sometimes ad-hoc–defined types.</p>
<p>For example, a lot of code just constantly redefines the hash-table interface rather than just defining a type for it … so the caller isn&rsquo;t restricted to implementing a specific interface. This is nice for library code, I guess, but it makes it harder to reason about the code because you don&rsquo;t have good names for types. This is an interesting enough experience for seasoned programmers; I can&rsquo;t even imagine how average or bad programmers deal with it.</p>
<p>I see where Martin is coming from, that he&rsquo;s afraid of <abbr title="Big Design Up Front">BDUF</abbr>, something he&rsquo;s been fighting for years by arguing that you can design as you go if you&rsquo;ll just <strong>test</strong> your code as you write it. If you see that a parameter has to be an <code>IHashMap</code>, that&rsquo;s easier to understand than <code>{ [key: string]: any }</code> or <code>{ [key: string]: T }</code> where T is a completely different type. There are advantages and disadvantages.</p>
<blockquote class="quote quote-block "><div>&ldquo;Every step down that path increases the difficulty of using and maintaining the language. Every step down that path forces users of the language to get their type models “right” up front; because changing them later is too expensive. Every step down that path forces us back into the regime of Big Design Up Front.&rdquo;</div></blockquote><p>I agree with the sentiment, but I don&rsquo;t know if we&rsquo;re there yet. Martin argues that there is a balance and maybe I need more experience with the languages he&rsquo;s horrified about. He does write:</p>
<blockquote class="quote quote-block "><div>&ldquo;I think Java and C# have done a reasonable job at hovering near the balance point. (If you ignore the horrible syntax for generics, and the ridiculous proscription against multiple inheritance.)&rdquo;</div></blockquote><p>…which I agree with wholeheartedly. I have learned to live without multiple inheritance, but I regularly railed against its absence for decades. I have given up because the world has moved on. I would love to see proper contravariance and covariant return types and anchored types, but I&rsquo;ve kind of given up on seeing that kind of stuff in a mainstream language, as well. Instead, I&rsquo;ve drifted more toward immutable, stateless, functional style—even in C#. I&rsquo;m ogling F#. I&rsquo;m working with Swift now and will do much more of that this year.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3356_1_body" class="footnote-number">[1]</span> Did you expect me to soften that brag down here, in this footnote?</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3356_2_body" class="footnote-number">[2]</span> I also use R#&rsquo;s solution-wide analysis.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3355</guid>
    <title><![CDATA[Set up JetBrains DataGrip with local SQL Server Express]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3355</link>
    <pubDate>Wed, 11 Jan 2017 08:47:45 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Jan 2017 08:47:45 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="https://blog.jetbrains.com/datagrip/2016/06/21/connecting-datagrip-to-ms-sql-server/">Connecting DataGrip to MS SQL Server</a> by <cite>Maksim Sobolevskiy</cite> on June 21, 2016 (<cite><a href="http://blog.jetbrains.com/">JetBrains Blog</a></cite>) covers all of the points well, with screen shots but I just wanted to record my steps, collected into a tight list. Screenshots for most of these steps are available in the blog linked above.</p>
<p>If you don&rsquo;t have a license for <em>DataGrip</em>, you can <a href="https://www.jetbrains.com/datagrip/download">download</a> a 30-day trial <em>or</em> you can <a href="https://www.jetbrains.com/rider/">download</a> the <em>JetBrains Rider</em> EAP, which bundles it. Once Rider is released, you&rsquo;ll have to have a license for it, but—for now—you can use it for free.</p>
<ul>
<li>Open <em>SQL Server Configuration Manager</em> to make sure that the TCP/IP protocol for <em>SQL Server Express</em> in the <em>SQL Server Network Configuration</em> is enabled. Restart the <em>SQL Server</em> Windows service if you made changes.</li>
<li>Make sure that the <em>SQL Server Browser</em> Windows service is running.</li>
<li><div>Open the <em>Database</em> tool window.<div class=" "><p>Add a <em>SQL Server (Microsoft)</em> connection. Make sure the driver is downloaded. Fill out the settings as shown for <em>QuinoTests</em> below (click to expand). Note that the port has been cleared.</p>
<p><span style="width: 523px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3355/mssqlserverexpressdatagrip.png"><img src="https://www.earthli.com/data/news/attachments/entry/3355/mssqlserverexpressdatagrip.png" alt=" " style="width: 523px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3355/mssqlserverexpressdatagrip.png">SqlServer Express Settings for DataGrip</a></span></span></p>
</div></div></li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3313</guid>
    <title><![CDATA[A Surfeit of C#/.NET IDEs]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3313</link>
    <pubDate>Thu, 24 Nov 2016 20:02:47 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">24. Nov 2016 20:02:47 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>For many years, the C#/.NET world has been dominated by a single main IDE: Visual Studio. MonoDevelop has also been available for a while, as an alternative for users on other platforms. Lately, though, there have been a few new contenders in the .NET IDE arena.</p>
<h2>Visual Studio for Mac</h2><p>We&rsquo;ll get this one out of the way first: this is basically Xamarin Studio for Mac, rebranded as Visual Studio for Mac. This IDE is pretty and extremely well-integrated into MacOS, with a lot of animated editor interaction for compiler warnings and errors.</p>
<p>Unlike Rider or Visual Studio 2017 with ReSharper, Xamarin Studio doesn&rsquo;t benefit from the R# tooling, so there are a few things immediately missing. Navigation is not as smooth as with ReSharper-based IDEs [1], although it&rsquo;s definitely on-par with what I&rsquo;ve experienced in Xcode. Xamarin Studio is fast and pretty good and I&rsquo;ll definitely keep it in the mix for testing Quino on alternate platforms once we start the move to .NET Standard 2.0. [2]</p>
<h2>Project Rider</h2><p><a href="https://www.earthli.com/data/news/attachments/entry/3313/a3u1zkfq.png"><img src="https://www.earthli.com/data/news/attachments/entry/3313/a3u1zkfq_tn.png" alt=" " class=" align-left"></a>This is only an EAP, so keep that in mind when testing. I installed this IDE on my Mac and Windows. The setup process was very smooth, asking for theme/color preferences and—most importantly—keyboard preferences. This time, the key-mapping for &ldquo;Visual Studio&rdquo; turned out to be quite appropriate and good.</p>
<p>I was able to load the Quino solution relatively quickly. The first load kicks off two processes: Nuget Restore and Process Files. On subsequent loads, the Nuget Restore no longer applies and Process Files benefits from Rider having cached everything the first time around.</p>
<p>I couldn&rsquo;t find any option to add an extra NuGet source, which was odd. There is a tab in the &ldquo;Nuget Packages&rdquo; pane called &ldquo;sources&rdquo;, but it just lists the NuGet configuration files but doesn&rsquo;t offer any way to add sources.</p>
<p>On the plus side, the test runner worked immediately. but on the minus side, it delivered results inconsistent with VS2015 and VS2017 running on the same machine. It looks and behaves like the same test runner as in ReSharper [3], but the results are different for some (a few hundred) Quino tests.</p>
<p>It loads quickly, can deal with the Quino solution without issues and the test runner works. Everything else felt like Visual Studio with ReSharper—at least for the stuff I use. I&rsquo;ll keep an eye on this IDE.</p>
<h2>Visual Studio 2017 RC1</h2><p><a href="https://www.earthli.com/data/news/attachments/entry/3313/mstile-310x310.png"><img src="https://www.earthli.com/data/news/attachments/entry/3313/mstile-310x310_tn.png" alt=" " class=" align-left"></a>I installed this with ReSharper 2016.3EAP9 and was pleasantly surprised to see that it behaved like an actual RC. That is, instead of releasing Alpha/early-beta software as an RC—I&rsquo;m looking at you, .NET Core—they&rsquo;ve got a really solid release on their hands.</p>
<p>That said, it&rsquo;s not quite ready for production use (obvious from the RC moniker) but I was able to use it for <em>productive</em> use over a long weekend. So I was pretty encouraged that I&rsquo;ll be able to let the guys at <a href="http://encodo.com">Encodo</a> use it sooner rather than later. [4]</p>
<p>That said, here are the things I&rsquo;ve noticed that are missing:</p>
<ul>
<li>They claim that EditorConfig is included, but it didn&rsquo;t work for me. I found an EditorConfig extension that I installed, but I&rsquo;d already set the configuration manually by then, so I&rsquo;m not sure what effect it had.</li>
<li>I&rsquo;d turned CodeLens off, but I still saw a rogue Git process. I haven&rsquo;t seen this process before or since, so I can only assume it came from 2017.</li>
<li>The StyleCop by JetBrains extension is not available yet, so that&rsquo;s a lot of hints and warnings missing. The maintainers of this extension write that <a href="https://github.com/StyleCop/StyleCop/issues/71">they will release as soon as ReSharper does</a>.</li>
<li>The standard Visual Studio TestRunner is still unusable. I can&rsquo;t imagine working without the ReSharper TestRunner. [5]</li></ul><p>Everything else seemed to work fine, which speaks well of both VS2017 and R#&rsquo;s latest EAP.</p>
<h2>Conclusion</h2><ul>
<li><strong>Xamarin Studio/Visual Studio for Mac:</strong> this won&rsquo;t be in the mix yet. It doesn&rsquo;t offer anything more than Rider on Mac. Plus, the Quino solution isn&rsquo;t ready for Mac development yet. Once .NET Standard 2.0 is ready and we can target Quino to that, we&rsquo;ll take another look.</li>
<li><strong>Project Rider:</strong> I&rsquo;ll be keeping an eye on future releases of JetBrains&rsquo;s Project Rider, but won&rsquo;t use the current EAP version again (tests don&rsquo;t work reliably).</li>
<li><strong>Visual Studio 2017:</strong> Once this is released, I feel good about installing it and releasing to other Encodo developers much sooner than with other versions. Especially since ReSharper&rsquo;s support is already so solid and once the StyleCop extension is available. Fingers crossed that the quality stays the same.</li></ul><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3313_1_body" class="footnote-number">[1]</span> I.e. go to Base/Inheriting implementations, and so on.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3313_2_body" class="footnote-number">[2]</span> Although .NET Core 1.1 has been released, it seems that .NET Standard 2.0 will not be available until 2017. This isn&rsquo;t exactly unexpected, but we aren&rsquo;t going to move Quino onto a new platform target until this is released. It&rsquo;s possible that we could target .NET Core as well, but we burned our fingers once, so we&rsquo;re going to hold off until .NET Standard.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3313_3_body" class="footnote-number">[3]</span> E.g. I&rsquo;ve been having sporadic test failures when the runner is unable to load the latest <em>FakeItEasy</em> assembly in Visual Studio on my desktop—but never my laptop or our TeamCity build server. A bunch of test failures in Rider were due to the same reason.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3313_4_body" class="footnote-number">[4]</span> We usually wait until the first service pack—at least.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3313_5_body" class="footnote-number">[5]</span> Which has been—thankfully—stable since 2016.2.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3271</guid>
    <title><![CDATA[ABD: Improving the Aspect-modeling API for Quino]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3271</link>
    <pubDate>Sun, 05 Jun 2016 12:52:31 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">5. Jun 2016 12:52:31 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <h2>Overview</h2><p>We discussed <abbr title="Always Be Designing">ABD</abbr> in a recent article <a href="https://www.earthli.com/view_article.php?id=3266">ABD: Refactoring and refining an API</a>. To cite from that article,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] the most important part of code is to think about how you’re writing it and what you’re building. You shouldn’t write a single line without thinking of the myriad ways in which it must fit into existing code and the established patterns and practices.&rdquo;</div></blockquote><p>With that in mind, I saw another teaching opportunity this week and wrote up my experience designing an improvement to an existing API.</p>
<h2>Requirements</h2><p>Before we write any code, we should know what we&rsquo;re doing. [1]</p>
<ul>
<li>We use aspects (<code>IMetaAspects</code>) in Quino to add domain-specific metadata (e.g. the <code>IVisibleAspect</code> controls element visibility)</li>
<li>Suppose we have such an aspect with properties A1…AN. When we set property A1 to a new value, we want to retain the values of properties A2…AN (i.e. we don&rsquo;t want to discard previously set values)</li>
<li>The current pattern is to call <code>FindOrAddAspect()</code>. This method does what it advertises: If an aspect with the requested type already exists, it is returned; otherwise, an instance of that type is created, added and returned. The caller gets an instance of the requested type (e.g. <code>IVisibleAspect</code>).</li>
<li>Any properties on the requested type that you want to change must have <em>setters</em>.</li>
<li>If the requested type is an interface, then we end up defining our interface as mutable.</li>
<li>Other than when building the metadata, every other use of these interfaces should not make changes.</li>
<li>We would like to be able to define the interface as read-only (no setters) and make the implementation mutable (has setters). Code that builds the metadata uses both the interface and the implementation type.</li></ul><p>Although we&rsquo;re dealing concretely with aspects in Quino metadata, the pattern and techniques outlined below apply equally well to other, similar domains.</p>
<h2>The current API</h2><p>A good example is the <code>IClassCacheAspect</code>. It exposes five properties, four of which are read-only. You can modify the property (<code>OrderOfMagnitude</code>) through the interface. This is already not good, as we are forced to work with the implementation type in order to change any property other than <code>OrderOfMagnitude</code>.</p>
<p>The current way to address this issue would be to make <em>all</em> of the properties settable on the interface. Then we could use the <code>FindOrAddAspect()</code> method with the <code>IClassCacheAspect</code>. For example,</p>
<pre class=" "><code>var cacheAspect = 
  Element.Classes.Person.FindOrAddAspect&lt;IClassCacheAspect&gt;(
    () =&gt; new ClassCacheAspect()
  );
cacheAspect.OrderOfMagnitude = 7;
cacheAspect.Capacity = 1000;</code></pre><p>For comparison, if the caller were simply creating the aspect instead of getting a possibly-already-existing version, then it would just use an object initializer.</p>
<pre class=" "><code>var cacheAspect = Element.Classes.Person.Aspects.Add(
  new ClassCacheAspect()
  {
    OrderOfMagnitude = 7;
    Capacity = 1000;
  }
}</code></pre><p>This works nicely for creating the initial aspect. But it causes an error if an aspect of that type had already been added. Can we design a single method with all the advantages?</p>
<h2>The new API</h2><p>A good way to approach a new is to ask: How would we want the method to look if we were calling it?</p>
<pre class=" "><code>Element.Classes.Person.SetCacheAspectValues(
  a =&gt;
  {
    a.OrderOfMagnitude = 7;
    a.Capacity = 1000;
  }
);</code></pre><p>If we only want to change a single property, we can use a one-liner:</p>
<pre class=" "><code>Element.Classes.Person.SetCacheAspectValues(a =&gt; a.Capacity = 1000);</code></pre><p>Nice. That&rsquo;s even cleaner and has fewer explicit dependencies than creating the aspect ourselves.</p>
<h2>Making it work for one aspect type</h2><p>Now that we know what we want the API to look like, let&rsquo;s see if it&rsquo;s possible to provide it. We request an interface from the list of aspects but want to use an implementation to set properties. The caller has to indicate how to create the instance if it doesn&rsquo;t already exist, but what if it does exist? We can&rsquo;t just upcast it because there is no guarantee that the existing aspect is the same implementation.</p>
<p>These are relatively lightweight objects and the requirement above is that the <em>property values</em> on the existing aspect are set on the returned aspect, not that the existing aspect is preserved.</p>
<p>What if we just provided a mechanism for copying properties from an existing aspect onto the new version?</p>
<pre class=" "><code>var cacheAspect = new ClassCacheAspect();
var existingCacheAspect =
  Element.Classes.Person.Aspects.FirstOfTypeOrDefault&lt;IClassCacheAspect&gt;();
if (existingCacheAspect != null)
{
  result.OrderOfMagnitude = existingAspect.OrderOfMagnitude;
  result.Capacity = existingAspect.Capacity;
  // Set all other properties
}

// Set custom values
cacheAspect.OrderOfMagnitude = 7;
cacheAspect.Capacity = 1000;</code></pre><p>This code does exactly what we want and doesn&rsquo;t require any setters on the interface properties. Let&rsquo;s pack this away into the API we defined above. The extension method is:</p>
<pre class=" "><code>public static ClassCacheAspect SetCacheAspectValues(
  this IMetaClass metaClass,
  Action&lt;ClassCacheAspect&gt; setValues)
{
  var result = new ClassCacheAspect();
  var existingCacheAspect =
    metaClass.Aspects.FirstOfTypeOrDefault&lt;IClassCacheAspect&gt;();
  if (existingCacheAspect != null)
  {
    result.OrderOfMagnitude = existingAspect.OrderOfMagnitude;
    result.Capacity = existingAspect.Capacity;
    // Set all other properties
  }

  setValues(result);

  return result;
}</code></pre><p>So that takes care of the boilerplate for the <code>IClassCacheAspect</code>. It hard-codes the implementation to <code>ClassCacheAspect</code>, but let&rsquo;s see how big a restriction that is once we&rsquo;ve generalized below.</p>
<h2>Generalize the aspect type</h2><p>We want to see if we can do anything about generalizing <code>SetCacheAspectValues()</code> to work for other aspects.</p>
<p>Let&rsquo;s first extract the main body of logic and generalize the aspects.</p>
<pre class=" "><code>public static TConcrete SetAspectValues&lt;TService, TConcrete&gt;(
  this IMetaClass metaClass,
  Action&lt;TConcrete, TService&gt; copyValues,
  Action&lt;TConcrete&gt; setValues
)
  where TConcrete : new, TService
  where TService : IMetaAspect
{
  var result = new TConcrete();
  var existingAspect = metaClass.Aspects.FirstOfTypeOrDefault&lt;TService&gt;();
  if (existingAspect != null)
  {
    copyValues(result, existingAspect);
  }

  setValues(result);

  return result;
}</code></pre><h2>Remove constructor restriction</h2><p>This isn&rsquo;t bad, but we&rsquo;ve required that the <code>TConcrete</code> parameter implement a default constructor. Instead, we could require an additional parameter for creating the new aspect.</p>
<pre class=" "><code>public static TConcrete SetAspectValues&lt;TService, TConcrete&gt;(
  this IMetaClass metaClass,
  <strong class="highlight">Func&lt;TConcrete&gt; createAspect,</strong>
  Action&lt;TConcrete, TService&gt; copyValues,
  Action&lt;TConcrete&gt; setValues
)
  where TConcrete : TService
  where TService : IMetaAspect
{
  var result = <strong class="highlight">createAspect();</strong>
  var existingAspect = metaClass.Aspects.FirstOfTypeOrDefault&lt;TService&gt;();
  if (existingAspect != null)
  {
    copyValues(result, existingAspect);
  }

  setValues(result);

  return result;
}</code></pre><h2>Just pass in the new aspect to use</h2><p>Wait, wait, wait. We not only don&rsquo;t need to the <code>new</code> generic constraint, we also don&rsquo;t need the <code>createAspect</code> lambda parameter, do we? Can&rsquo;t we just <em>pass in</em> the object instead of passing in a lambda to create the object and <em>then calling it immediately</em>?</p>
<pre class=" "><code>public static TConcrete SetAspectValues&lt;TService, TConcrete&gt;(
  this IMetaClass metaClass,
  <strong class="highlight">TConcrete aspect,</strong>
  Action&lt;TConcrete, TService&gt; copyValues,
  Action&lt;TConcrete&gt; setValues
)
  where TConcrete : TService
  where TService : IMetaAspect
{
  var existingAspect = metaClass.Aspects.FirstOfTypeOrDefault&lt;TService&gt;();
  if (existingAspect != null)
  {
    copyValues(aspect, existingAspect);
  }

  setValues(aspect);

  return aspect;
}</code></pre><p>That&rsquo;s a bit more logical and intuitive, I think.</p>
<h2>Redefine original method</h2><p>We can now redefine our original method in terms of this one:</p>
<pre class=" "><code>public static ClassCacheAspect SetAspectValues(
  this IMetaClass metaClass,
  Action&lt;ClassCacheAspect&gt; setValues)
{
  return metaClass.UpdateAspect(
    new ClassCacheAspect(),
    (aspect, existingAspect) =&gt;
    {
      result.OrderOfMagnitude = existingAspect.OrderOfMagnitude;
      result.Capacity = existingAspect.Capacity;
      // Set all other properties
    },
    setValues
  );
}</code></pre><h2>Generalize copying values</h2><p>Can we somehow generalize the copying behavior? We could make a wrapper that expects an interface on the <code>TService</code> that would allow us to call <code>CopyFrom(existingAspect)</code>.</p>
<pre class=" "><code>public static TConcrete SetAspectValues&lt;TService, TConcrete&gt;(
  this IMetaClass metaClass,
  TConcrete aspect,
  Action&lt;TConcrete&gt; setValues
)
  where TConcrete : TService, ICopyTarget
  where TService : IMetaAspect
{
  return metaClass.UpdateAspect&lt;TService, TConcrete&gt;(
    aspect,
    (aspect, existingAspect) =&gt; aspect.CopyFrom(existingAspect),
    setValues
  );
}</code></pre><p>What does the <code>ICopyTarget</code> interface look like?</p>
<pre class=" "><code>public interface ICopyTarget
{
  void CopyFrom(object other);
}</code></pre><p>This is going to lead to type-casting code at the start of every implementation to make sure that the <code>other</code> object is the right type. We can avoid that by using a generic type parameter instead.</p>
<pre class=" "><code>public interface ICopyTarget&lt;T&gt;
{
  void CopyFrom(T other);
}</code></pre><p>That&rsquo;s better. How would we use it? Here&rsquo;s the definition for <code>ClassCacheAspect</code>:</p>
<pre class=" "><code>public class ClassCacheAspect : IClassCacheAspect, ICopyTarget&lt;IClassCacheAspect&gt;
{
  public void CopyFrom(IClassCacheAspect otherAspect)
  {
    OrderOfMagnitude = otherAspect.OrderOfMagnitude;
    Capacity = otherAspect.Capacity;
    // Set all other properties
  }
}</code></pre><p>Since the final version of <code>ICopyTarget</code> has a generic type parameter, we need to adjust the extension method. But that&rsquo;s not a problem because we already have the required generic type parameter in the outer method.</p>
<pre class=" "><code>public static TConcrete SetAspectValues&lt;TService, TConcrete&gt;(
  this IMetaClass metaClass,
  TConcrete aspect,
  Action&lt;TConcrete&gt; setValues
)
  where TConcrete : TService, ICopyTarget<strong class="highlight">&lt;TService&gt;</strong>
  where TService : IMetaAspect
{
  return metaClass.UpdateAspect(
    aspect,
    (aspect, existingAspect) =&gt; aspect.CopyFrom(existingAspect),
    setValues
  );
}</code></pre><h2>Final implementation</h2><p>Assuming that the implementation of <code>ClassCacheAspect</code> implements <code>ICopyTarget</code> as shown above, then we can rewrite the cache-specific extension method to use the new extension method for <code>ICopyTargets</code>.</p>
<pre class=" "><code>public static ClassCacheAspect SetCacheAspectValues(
  this IMetaClass metaClass,
  Action&lt;ClassCacheAspect&gt; setValues)
{
  return metaClass.UpdateAspect&lt;IClassCacheAspect, ClassCacheAspect&gt;(
    new ClassCacheAspect(),
    setValues
  );
}</code></pre><p>This is an extension method, so any caller that wants to use its own <code>IClassCacheAspect</code> could just copy/paste this one line of code and use its own aspect.</p>
<h2>Conclusion</h2><p>This is actually pretty neat and clean:</p>
<ul>
<li>We have a pattern where all properties on the interface are read-only</li>
<li>We have a pattern where an aspect can indicate how its values are to be copied from another instance. This is basically boilerplate, but must be written only once per aspect—and it can be located right in the implementation itself rather than in an extension method.</li>
<li>A caller building metadata passes in a single lambda to set values. Existing values are handled automatically.</li>
<li>Adding support for more aspects is straightforward and involves very little boilerplate.</li></ul><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3271_1_body" class="footnote-number">[1]</span> You would think that would be axiomatic. You&rsquo;d be surprised.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3266</guid>
    <title><![CDATA[ABD: Refactoring and refining an API]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3266</link>
    <pubDate>Sat, 21 May 2016 10:58:43 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. May 2016 10:58:43 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. May 2016 10:59:27 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>We&rsquo;ve been doing more internal training at <a href="http://encodo.com">Encodo</a> lately and one topic that we&rsquo;ve started to tackle is design for architecture/APIs. Even if you&rsquo;re not officially a software architect—designing and building entire systems from scratch—every developer designs code, on some level.</p>
<blockquote class="quote pullquote align-left left" style="text-align: left"><div><p>[A]lways<br>
[B]e<br>
[D]esigning</p>
</div></blockquote><p>There are broad guidelines about how to format and style code, about how many lines to put in a method, about how many parameters to use, and so on. We strive for Clean Code™.</p>
<p>But the most important part of code is to think about how you&rsquo;re writing it and what you&rsquo;re building. You shouldn&rsquo;t write a single line without thinking of the myriad ways in which it must fit into existing code and the established patterns and practices.</p>
<p>We&rsquo;ve written about this before, in the two-part series called &ldquo;Questions to consider when designing APIs&rdquo; (<a href="https://www.earthli.com/news/view_article.php?id=2996">Part I</a> and <a href="https://www.earthli.com/news/view_article.php?id=2997">Part II</a>). Those two articles comprise a long list of aspects of a design to consider.</p>
<blockquote class="quote pullquote align-right right" style="width: 180px"><div>First make a good design, <em>then</em> compromise to fit project constraints.</div></blockquote><p>Your project defines the constraints under which you can design. That is, we should still have our designer caps on, but the options available are much more strictly limited.</p>
<p>But, frustrating as that might be, it doesn&rsquo;t mean you should stop thinking. A good designer figures out what would be optimal, then adjusts the solution to fit the constraints. Otherwise, you&rsquo;ll forget what you were compromising <em>from</em>—and your design skills either erode or never get better.</p>
<p>We&rsquo;ve been calling this concept ABD—Always Be Designing. [1] Let&rsquo;s take a closer, concrete look, using a recent issue in the schema migration for Quino. Hopefully, this example illustrates how even the tiniest detail is important. [2]</p>
<h2>A bug in the schema migrator</h2><p>We detected the problem when the schema migration generated an invalid SQL statement.</p>
<pre class=" "><code>ALTER TABLE "punchclock__timeentry" ALTER COLUMN "personid" SET DEFAULT ;</code></pre><p>As you can see, the default value is missing. It seems that there are situations where the code that generates this SQL is unable to correctly determine that a default value could not be calculated.</p>
<p>The code that calculates the default value is below.</p>
<pre class=" "><code>result = Builder.GetExpressionPayload(
  null,
  CommandFormatHints.DefaultValue,
  new ExpressionContext(prop),
  prop.DefaultValueGenerator
);</code></pre><p>To translate, there is a <code>Builder</code> that produces a payload. We&rsquo;re using that builder to get the payload (SQL, in this case) that corresponds to the <code>DefaultValueGenerator</code> expression for a given property, <code>prop</code>. </p>
<p>This method is an extension method of the <code>IDataCommandBuilder</code>, reproduced below in full, with additional line-breaks for formatting:</p>
<pre class=" "><code>public static string GetExpressionPayload&lt;TCommand&gt;(
  this IDataCommandBuilder&lt;TCommand&gt; builder,
  [CanBeNull] TCommand command,
  CommandFormatHints hints, 
  IExpressionContext context,
  params IExpression[] expressions)
{
  if (builder == null) { throw new ArgumentNullException("builder"); }
  if (context == null) { throw new ArgumentNullException("context"); }
  if (expressions == null) { throw new ArgumentNullException("expressions"); }

  return builder.GetExpressionPayload(
    command,
    hints,
    context,
    expressions.Select(
      e =&gt; new ExecutableQueryItem&lt;IExecutableExpression&gt;(new ExecutableExpression(e))
    )
  );
}</code></pre><p>This method does no more than to package each item in the <code>expressions</code> parameter in an <code>ExecutableQueryItem</code> and call the interface method.</p>
<p>The problem isn&rsquo;t immediately obvious. It stems from the fact that each <code>ExecutableQueryItem</code> can be marked as <code>Handled</code>. The extension method ignores this feature, and always returns a result. The caller is unaware that the result may correspond to an only partially handled expression.</p>
<h2>Is there a quick fix?</h2><p>Our first instinct is, naturally, to try to figure out how we can fix the problem. [3] In the code above, we could keep a reference to the executable items and then check if any of them were unhandled, like so:</p>
<pre class=" "><code>var executableItems = expressions.Select(
  e =&gt; new ExecutableQueryItem&lt;IExecutableExpression&gt;(new ExecutableExpression(e))
);
var result = builder.GetExpressionPayload(command, hints, context, executableItems);

if (executableItems.Unhandled().Any())
{
  <span class="warning">// Now what?</span>
}

return result;
}</code></pre><p>We can detect if at least one of the input expressions could not be mapped to SQL. But we don&rsquo;t know what to do with that information.</p>
<ul>
<li>Do we throw an exception? No, we can&rsquo;t just do that. None of the callers are expecting an exception, so that&rsquo;s an API change. [4]</li>
<li>Do we return <code>null</code>? What can we return to indicate that the input expressions could not be mapped? Here we have the same problem as with throwing an exception: all callers assume that the result can be mapped.</li></ul><p>So there&rsquo;s no quick fix. We have to change an API. We have to <em>design</em>.</p>
<h2>Part of the result is missing</h2><p>As with most bugs, the challenge lies not in knowing how to fix the bug, but in how to fix the underlying design problem that led to the bug. The problem is actually not in the extension method, but in the method signature of the interface method.</p>
<p>Instead of a single result, there are actually two results for this method call:</p>
<ul>
<li>Can the given expressions be mapped to a string (the target representation)?</li>
<li>If so, what is that text?</li></ul><p>Instead of a <code>Get</code> method, this is a classic <code>TryGet</code> method.</p>
<h2>How to Introduce the Change</h2><p>If this code is already in production, then you have to figure out how to introduce the bug fix without breaking existing code. If you already have consumers of your API, you can&rsquo;t just change the signature and cause a compile error when they upgrade. You have to decorate the existing method with <code>[Obsolete]</code> and make a new interface method.</p>
<p>So we don&rsquo;t change the existing method and instead add the method <code>TryGetExpressionPayload()</code> to <code>IDataCommandBuilder</code>.</p>
<h2>What are the parameters?</h2><p>Now, let&rsquo;s figure out what the parameters are going to be.</p>
<p>The method called by the extension method above has a slightly different signature. [5]</p>
<pre class=" "><code>string GetExpressionPayload(
  [CanBeNull] TCommand command, 
  CommandFormatHints hints,
  [NotNull] IExpressionContext context,
  [NotNull] IEnumerable&lt;ExecutableQueryItem&lt;IExecutableExpression&gt;&gt; expressions
);</code></pre><p>That last parameter is a bit of a bear. What does it even mean? The signature of the extension method deals with simple <code>IExpression</code> objects—I know what those are. But what are <code>ExecutableQueryItems</code> and <code>IExecutableExpressions</code>?</p>
<p>As an author and maintainer of the data driver, I know that these objects are part of the internal representation of a query as it is processed. But as a caller of this method, I&rsquo;m almost never going to have a list of these objects, am I?</p>
<p>Let&rsquo;s find out. </p>
<p><strong>Me:</strong> Hey, ReSharper, how many callers of that method are there in the entire Quino source?<br>
<strong>ReSharper:</strong> Just one, Dave. [6]</p>
<p>So, we defined an API with a signature that&rsquo;s so hairy no-one calls it except through an extension method that makes the signature more palatable. And it introduces a bug. Lovely.</p>
<p>We&rsquo;ve now figured out that our new method should accept a sequence of <code>IExpression</code> objects instead of <code>ExecutableQueryItem</code> objects.</p>
<p>How&rsquo;s the signature looking so far?</p>
<pre class=" "><code>bool TryGetExpressionPayload(
  [CanBeNull] TCommand command, 
  CommandFormatHints hints,
  [NotNull] IExpressionContext context,
  [NotNull] IEnumerable&lt;IExpression&gt; expressions,
  out string payload
);</code></pre><h2>Are We Done?</h2><p>Not quite. There are two things that are still wrong with this signature, both important.</p>
<h3>Fix the Result Type</h3><p>One problem is that the rest of the <code>IDataCommandBuilder&lt;TCommand&gt;</code> deals with a generic payload type and this method only works for builders where the target representation is a string. The Mongo driver, for example, uses <code>MongoStorePayload</code> and <code>MongoRetrievePayload</code> objects instead of strings and throws a <code>NotSupportedException</code> for this API. </p>
<p>That&rsquo;s not very elegant, but the Mongo driver was forced into that corner by the signature. Can we do better? The API would currently require Mongo to always return <code>false</code> because our Mongo driver doesn&rsquo;t know how to map <em>anything</em> to a string. But it could map to one of the aforementioned object representations.</p>
<p>If we change the <code>out</code> parameter type from a <code>string</code> to an <code>object</code>, then any driver, regardless of payload representation, has at least the possibility of implementing this API correctly.</p>
<h3>Fix parameters</h3><p>Another problem is that the order of parameters does not conform to the code style for Encodo. </p>
<ul>
<li>We prefer to place all <strong>non-nullable parameters first.</strong> Otherwise, a call that passes <code>null</code> as the first parameter looks strange. The <code>command</code> can be null, so it should move after the two non-nullable parameters. If we move it all the way to the end, we can even make it optional.</li>
<li>Also, <strong>primitives should come after the references.</strong> (So <code>hints</code> should be third.)</li>
<li>Also, semantically, the call is getting the payload for the <code>expressions</code> not the <code>context</code>. The <strong>first parameter should be the target</strong> of the method; the rest of the parameters provide context for that input.</li>
<li>The original method accepted <code>params IExpression[]</code>. Using <code>params</code> allows a caller to provide zero or more expressions, but it&rsquo;s only allowed on the terminal parameter. Instead, we&rsquo;ll accept an <code>IEnumerable&lt;IExpression&gt;</code>, which is more standard for the Quino library anyway.</li></ul><p>The final method signature is below.</p>
<pre class=" "><code>bool TryGetExpressionPayload(
  [NotNull] IEnumerable&lt;IExpression&gt; expressions,
  [NotNull] IExpressionContext context,
  CommandFormatHints hints,
  out object payload,
  [CanBeNull] TCommand command = default(TCommand)
);</code></pre><h2>Our API in Action</h2><p>The schema migration called the original API like this:</p>
<pre class=" "><code>result = Builder.GetExpressionPayload(
  null,
  CommandFormatHints.DefaultValue,
  new ExpressionContext(prop),
  prop.DefaultValueGenerator
);

return true;</code></pre><p>The call with the new API—and with the bug fixed—is shown below. The only non-functional addition is that we have to call <code>ToSequence()</code> on the first parameter (highlighted). Happily, though, we&rsquo;ve fixed the bug and only include a default value in the field definition if one can actually be calculated.</p>
<pre class=" "><code>object payload;
if (Builder.TryGetExpressionPayload(
  prop.DefaultValueGenerator<strong class="highlight">.ToSequence()</strong>,
  new ExpressionContext(prop),
  CommandFormatHints.DefaultValue,
  out payload)
)
{
  result = payload as string ?? payload.ToString();

  return true;
}</code></pre><h2>One More Design Decision…</h2><p>A good rule of thumb is that if you find yourself explaining something in detail, it might still be too complicated. In that light, the call to <code>ToSequence()</code> is a little distracting. [7] It would be nice to be able to map a single expression without having to pack it into a sequence.</p>
<p>So we have one more design decision to make: where do we add that method call? Directly to the interface, right? But the method for a single expression can easily be expressed in terms of the method we already have (as we saw above). It would be a shame if every implementor of the interface was forced to produce this boilerplate.</p>
<p>Since we&rsquo;re using C#, we can instead <em>extend</em> the interface with a static method, as shown below (again, with more line breaks for this article):</p>
<pre class=" "><code>public static bool TryGetExpressionPayload&lt;TCommand&gt;(
  <strong class="highlight">[NotNull] this IDataCommandBuilder&lt;TCommand&gt; builder, // Extend the builder</strong>
  [NotNull] IExpression expression,
  [NotNull] IExpressionContext context,
  CommandFormatHints hints,
  out object payload,
  [CanBeNull] TCommand command = default(TCommand)
)
{
  return builder.TryGetExpressionPayload(
    expression.ToSequence(),
    context,
    hints,
    out payload,
    command
  );
}</code></pre><p>We not only avoided cluttering the interface with another method, but now a caller with a single expression doesn&rsquo;t have to create a sequence for it [8], as shown in the final version of the call below.</p>
<pre class=" "><code>object payload;
if (Builder.TryGetExpressionPayload(
  prop.DefaultValueGenerator,
  new ExpressionContext(prop),
  CommandFormatHints.DefaultValue,
  out payload)
)
{
  result = payload as string ?? payload.ToString();

  return true;
}</code></pre><h2>Conclusion</h2><p>We saw in this post how we <em>always</em> have our designer/architect cap on, even when <em>only</em> fixing bugs. We took a look at a quick-fix and then backed out and realized that we were designing a new solution. Then we covered, in nigh-excruciating detail, our thought process as we came up with a new solution.</p>
<p><small class="notes">Many thanks to Dani for the original design and Sebastian for the review!</small></p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3266_1_body" class="footnote-number">[1]</span> This is a bit of a riff on ABC—Always Be Closing—as popularized by Alec Baldwin in the movie <a href="http://www.investopedia.com/terms/a/always-be-closing.asp">Glengarry Glen Ross</a>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3266_2_body" class="footnote-number">[2]</span> Also, understand that it took much longer to write this blog post and itemize each individual step of how we thought about the issue. In reality, we took only a couple of minutes to work through this chain of reasoning and come up with the solution we wanted. It was only after we&rsquo;d finished designing that I realized that this was a good example of <abbr title="Always Be Designing">ABD</abbr>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3266_3_body" class="footnote-number">[3]</span> Actually, our first instinct is to make sure that there is a failing test for this bug. But, this article deals with how to analyze problems and design fixes, not how to make sure that the code you write is tested. That&rsquo;s super-important, too, though, just so you know. Essential, even.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3266_4_body" class="footnote-number">[4]</span> Even though C# doesn&rsquo;t include the exceptions thrown in the signature of a method, as Java does. Where the Java version is fraught with issues, see the &ldquo;Recoverable Errors: Type-Directed Exceptions&rdquo; chapter of <a href="http://joeduffyblog.com/2016/02/07/the-error-model/">Midori: The Error Model</a> by <cite>Joe Duffy</cite> for a really nice proposal/implementation of a language feature that includes expected exceptions in the signature of a method.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3266_5_body" class="footnote-number">[5]</span> Which is why we defined the extension method in the first place.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3266_6_body" class="footnote-number">[6]</span> I&rsquo;m fully aware that my name isn&rsquo;t Dave. It&rsquo;s just what ReSharper calls me. <a href="http://www.imdb.com/title/tt0062622/quotes">Old-school reference.</a></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3266_7_body" class="footnote-number">[7]</span> This was pointed out, by the way, by a reviewer of this blog post and escaped the notice of both designers and the code-reviewer. API design is neither easy nor is it done on the first try. It&rsquo;s only finished after multiple developers have tried it out. Then, you&rsquo;ll probably be able to live with it.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3266_8_body" class="footnote-number">[8]</span> Most developers would have used <code>new [] { expression }</code>, which I think is kind of ugly.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3262</guid>
    <title><![CDATA[v2.2: Winform fixes and Query Improvements]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3262</link>
    <pubDate>Thu, 12 May 2016 22:22:36 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">12. May 2016 22:22:36 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The summary below describes major new features, items of note and breaking changes. The <a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=22103">full list of issues</a> is also available for those with access to the Encodo issue tracker.</p>
<h2>Highlights</h2><ul>
<li>Lots of bug fixes and improvements for the <strong>Winform UI</strong> and <strong>German translations</strong> with the release of Punchclock on this version. (<a href="https://secure.encodo.ch/jira/browse/QNO-5162">QNO-5162</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5159">QNO-5159</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5158">QNO-5158</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5157">QNO-5157</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5156">QNO-5156</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5140">QNO-5140</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5155">QNO-5155</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5145">QNO-5145</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5111">QNO-5111</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5107">QNO-5107</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5106">QNO-5106</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5104">QNO-5104</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5015">QNO-5015</a>)</li>
<li><code>DateTimeExtensions.GetDayOfWeek()</code> had a <strong>leap-day bug</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-5051">QNO-5051</a>)</li>
<li>Fixed how the <strong>hash code</strong> for <code>GenericObjects</code> is calculated, which fixes sorting issues in grids, specifically for non-persisted or transient objects (<a href="https://secure.encodo.ch/jira/browse/QNO-5137">QNO-5137</a>)</li>
<li>Improvements to the <strong><code>IAccessControl</code> API</strong> for getting groups and users and testing membership (<a href="https://secure.encodo.ch/jira/browse/QNO-5133">QNO-5133</a>)</li>
<li><div class=" "><p>Add support for <strong>query aliases</strong> (e.g. for joining the same table multiple times) (<a href="https://secure.encodo.ch/jira/browse/QNO-531">QNO-531</a>) This changes the API surface only minimally. Applications can pass an <code>alias</code> when calling the <code>Join</code> method, as shown below,</p>
<pre class=" "><code>query.Join(Metadata.Project.Deputy, alias: "deputy")</code></pre><p>You can find more examples of aliased queries in the <code>TestAliasedQuery()</code>, <code>TestJoinAliasedTables()</code>, <code>TestJoinChildTwice()</code> defined in the <code>QueryTests</code> testing fixture.</p>
</div></li>
<li>Add a standalone <code>IQueryAnalyzer</code> for optimizations and in-memory mini-drivers (<a href="https://secure.encodo.ch/jira/browse/QNO-4830">QNO-4830</a>)</li></ul><h2>Breaking changes</h2><ul>
<li><code>ISchemaManager</code> has been removed. Instead, you should retrieve the interface you were looking for from the IOC. The possible interfaces you might need are <code>IImportHandler</code>, <code>IMappingBuilder</code>, <code>IPlanBuilder</code> or <code>ISchemaCommandFactory</code>.</li>
<li><code>ISchemaManagerSettings.GetAuthorized()</code> has been moved to <code>ISchemaManagerAuthorizer</code>. </li>
<li><div>The hash-code fix for <code>GenericObjects</code> may have an effect on the way your application sorts objects.<div class=" "><p>The <code>IParticipantManager</code> (base interface of <code>IAccessControl</code>) no longer has a single method called <code>GetGroups(IParticipant)</code>. This method was previously used to get the groups to which a user belongs <em>and</em> the child groups of a given group. This confusing double duty for the API led to an incorrect implementation for <em>both</em> usages. Instead, there are now two methods:</p>
<ul>
<li><code>IEnumerable&lt;IGroup&gt; GetGroups(IUser user)</code>: Gets the groups for the given user</li>
<li><code>IEnumerable&lt;IGroup&gt; GetChildGroups(IGroup group)</code>: Gets the child groups for the given group</li></ul><p>The old method has been removed from the interface because (A) it never worked correctly anyway and (B) it conflicts with the new API.</p>
</div></div></li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3261</guid>
    <title><![CDATA[Quino Retrospective and Roadmap]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3261</link>
    <pubDate>Thu, 12 May 2016 22:16:43 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">12. May 2016 22:16:43 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">12. May 2016 22:30:34 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <h2>History</h2><p>Before taking a look at the roadmap, let&rsquo;s quickly recap how far we&rsquo;ve come. An overview of the release schedule shows a steady accretion of features over the years, as driven by customer or project needs.</p>
<p><span style="width: 1110px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3261/quino_change_log_timeline.png"><img src="https://www.earthli.com/data/news/attachments/entry/3261/quino_change_log_timeline.png" alt=" " style="width: 1110px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3261/quino_change_log_timeline.png">Timeline</a></span></span></p>
<p>The list below includes more detail on the releases highlighted in the graphic. [1]</p>
<ul>
<li><strong><a href="https://www.earthli.com/news/view_article.php?id=271">0.1</a></strong>: Proof of concept with metadata, PostgreSql (data and schema-migration) and Winforms UI</li>
<li><strong><a href="https://www.earthli.com/news/view_article.php?id=281">1.0</a></strong>: First customer product with PostgreSql, DevExpress Winforms UI and Reporting</li>
<li><strong><a href="http://encodo.com/en/blogs.php?entry_id=228">1.0.5</a></strong>: MS-SQL driver (parity with PostgreSql driver)</li>
<li><strong><a href="http://encodo.com/en/blogs.php?entry_id=255">1.5.0</a></strong>: Remoting data driver; require .NET 4.0</li>
<li><strong><a href="http://encodo.com/en/blogs.php?entry_id=256">1.6.0</a></strong>: Mongo/NoSQL data driver </li>
<li><strong><a href="http://encodo.com/en/blogs.php?entry_id=230">1.8.0</a></strong>: Rewrite data driver to use sessions</li>
<li><strong><a href="http://encodo.com/en/blogs.php?entry_id=233">1.8.5</a></strong>: Support <a href="https://www.earthli.com/news/view_article.php?id=2720">improved metadata-generation pattern</a></li>
<li><strong><a href="http://encodo.com/en/blogs.php?entry_id=246">1.9.0</a></strong>: Add plugin/overlay support</li>
<li><strong><a href="http://encodo.com/en/blogs.php?entry_id=354">1.10.0</a></strong>: Require .NET 4.5; add JSON-based remoting protocol; Windows-service support</li>
<li><strong><a href="https://www.earthli.com/news/view_article.php?id=3052">1.13.0</a></strong>: Rewrite security API</li>
<li><strong><a href="https://www.earthli.com/news/view_article.php?id=3128">v2.0-beta1</a></strong>: Rewrite configuration, logging and schema-migration APIs</li>
<li><strong><a href="https://www.earthli.com/news/view_article.php?id=3142">v2.0-beta2</a></strong>: Add V2 generated-code format</li>
<li><strong><a href="https://www.earthli.com/news/view_article.php?id=3194">2.0</a></strong>: Finish configuration/IOC rewrite; produce NuGet packages for delivery</li>
<li><strong><a href="https://www.earthli.com/news/view_article.php?id=3262">2.2</a></strong>: Stabilize Winform; support aliased tables in queries</li>
<li><strong><a href="https://www.earthli.com/news/view_article.php?id=3260">3.0</a></strong>: Rewrite MetaBuilder API; improve support for plugins</li></ul><p> </p>
<p>We took 1.5 years to get to <strong>v1</strong>. The initial major version was to signify the first time that Quino-based code went into external production. [2]</p>
<p>After that, it took 6.5 years to get to <strong>v2</strong>. Although we added several large products that use Quino, we were always able to extend rather than significantly change anything in the core. The second major version was to signify sweeping changes made to address technical debt, to modernize certain components and to prepare for changes coming to the .NET platform.</p>
<p>It took just 5 months to get to <strong>v3</strong> for two reasons:</p>
<ol>
<li>Although we were able to make a lot of planned changes in <strong>v2</strong> [3], we had to leave some breaking changes for future versions. [4]</li>
<li>We now strictly adhere to the rule that a breaking change anywhere in the software&rsquo;s API—and Quino&rsquo;s API surface is large—leads automatically to a major-version change. [5]</li></ol><h2>Roadmap</h2><p>So that&rsquo;s where we&rsquo;ve been. Where are we headed?</p>
<p>As you can see above, Quino is a very mature product that satisfies the needs of a wide array of software on all tiers. What more is there to add?</p>
<p>Quino&rsquo;s design has always been driven by a combination of customer requirements and what we anticipated would <em>be</em> customer requirements.</p>
<p>We&rsquo;re currently working on the following features.</p>
<dl><dt class="field">Modeling improvements</dt>
<dd>This work builds on the API changes made to the <code>MetaBuilder</code> in <strong>v3</strong>. We&rsquo;re creating a more fluent, modern and extensible API for building metadata. We hope to be able to add these changes incrementally without introducing any breaking changes. [6]</dd>
<dt class="field">WPF / VSG</dt>
<dd><div class=" "><p>A natural use of the rich metadata in Quino is to generate user interfaces for business entities without have to hand-tool each form. From the POC onward, Quino has included support for generating UIs for .NET Winforms.</p>
<p>Winforms has been replaced on the Windows desktop with <abbr title="Windows Presentation Framework">WPF</abbr> and <abbr title="Universal Windows Platform">UWP</abbr>. We&rsquo;ve gotten quite far with being able to generate WPF applications from Quino metadata. The screenshots below come from a pre-alpha version of the Sandbox application included in the Quino solution.</p>
<p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_date_picker.png"><img src="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_date_picker_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_date_picker.png">Sandbox Date Picker</a></span></span><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_dialog_view.png"><img src="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_dialog_view_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_dialog_view.png">Sandbox Dialog View</a></span></span><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_edit_view.png"><img src="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_edit_view_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_edit_view.png">Sandbox Edit View</a></span></span><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_list_view.png"><img src="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_list_view_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3261/sandbox_list_view.png">Sandbox List View</a></span></span></p>
<p><span class="clear-both"></span>You may have noticed the lovely style of the new UI. [7] We&rsquo;re using a <abbr title="Visual Style Guide">VSG</abbr> designed for us by <a href="http://www.ergosign.de/">Ergosign</a>, for whom we&rsquo;ve done some implementation work in the past.</p>
</div></dd>
<dt class="field"><span class="clear-both"></span>.NET Core</dt>
<dd><div class=" "><p>If you&rsquo;ve been following Microsoft&rsquo;s announcements, things are moving quickly in the .NET world. There are whole new platforms available, if you target your software to run on them. We&rsquo;re investigating the next target platforms for Quino. Currently that means getting the core of Quino—<code>Quino.Meta</code> and its dependencies—to compile under .NET Core.</p>
<p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3261/compilingdotnetcore.png"><img src="https://www.earthli.com/data/news/attachments/entry/3261/compilingdotnetcore_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3261/compilingdotnetcore.png">Compiling Encodo.Core on the .NET Core Platform</a></span></span>As you can see in the screenshot, we&rsquo;ve got one of the toughest assemblies to compile—<code>Encodo.Core</code>. After that, we&rsquo;ll try for running some tests under Linux or OS X. The long-term goal is to be able to run Quino-based application and web servers on non-Windows—and, most importantly, non-IIS—platforms. [8]</p>
<p>These changes will almost certainly cause builds using previous versions to break. Look for any additional platform support in an upcoming major-version release.</p>
</div></dd>
</dl><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3261_1_body" class="footnote-number">[1]</span> There were, of course, more minor and patch releases throughout, but those didn&rsquo;t introduce any major new functionality.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3261_2_body" class="footnote-number">[2]</span> Punchclock, our time-entry and invoicing software—and Quino &ldquo;<a href="http://encyclopedia2.thefreedictionary.com/eating+one%27s+own+dogfood" title="When a developer uses their own code for their own daily needs. Being a user as well as a developer creates the user empathy that is the hallmark of good software.">dogfood</a>&rdquo; product—had been in use internally at Encodo earlier than that.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3261_3_body" class="footnote-number">[3]</span> E.g. splitting the monolithic <code>Encodo</code> and <code>Quino</code> assemblies into dozens of new, smaller and much more focused assemblies. Reorganizing configuration around the IOC and rewriting application startup for more than just desktop applications was another sweeping change.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3261_4_body" class="footnote-number">[4]</span> One of those breaking changes was to the <code>MetaBuilder</code>, which started off as a helper class for assembling application metadata, but became a monolithic and unavoidable dependency, even in v2. In v3, we made the breaking changes to remove this component from its central role and will continue to replace its functionality with components that more targeted, flexible and customizable.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3261_5_body" class="footnote-number">[5]</span> In the years between <strong>v1</strong> and <strong>v2</strong>, we used the minor-version number to indicate when breaking changes could be made. We also didn&rsquo;t try as hard to avoid breaking changes by gracefully deprecating code. The new approach tries very hard to avoid breaking changes but accepts the consequences when it&rsquo;s deemed necessary by the team.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3261_6_body" class="footnote-number">[6]</span> That is, when users upgrade to a version with the newer APIs, they will get <span class="warning">obsolete</span> warnings but their existing code will continue to build and run, as before the upgrade. In this way, customers can smoothly upgrade without breaking any builds.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3261_7_body" class="footnote-number">[7]</span> You may also have noticed that the &ldquo;Sandbox Dialog View&rdquo; includes a little tag in it for the &ldquo;XAML Spy&rdquo;, a tool that we use for WPF development. Just so you know the screenshots aren&rsquo;t faked… :-)</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3261_8_body" class="footnote-number">[8]</span> As with the WPF interface, we&rsquo;re likely to dogfood all of these technologies with Punchclock, our time-tracking and invoicing system written with Quino. The application server and web components that run on Windows could be migrated to run on one of our many Linux machines instead.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3260</guid>
    <title><![CDATA[Quino v3.0: Metadata builders and code-generation improvements]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3260</link>
    <pubDate>Thu, 12 May 2016 22:11:29 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">12. May 2016 22:11:29 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The summary below describes major new features, items of note and breaking changes. The <a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=19704">full list of issues</a> is also available for those with access to the Encodo issue tracker.</p>
<h2>Highlights</h2><ul>
<li><strong>Metadata builders</strong> are more lightweight now and have fewer restrictions on their API. (<a href="https://secure.encodo.ch/jira/browse/QNO-4994">QNO-4994</a>)</li>
<li>Improve support for <strong>plugins</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-5189">QNO-5189</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5190">QNO-5190</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5196">QNO-5196</a>)</li>
<li>Improve and clean up <strong>expression</strong> library (<a href="https://secure.encodo.ch/jira/browse/QNO-5174">QNO-5174</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5176">QNO-5176</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5182">QNO-5182</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5183">QNO-5183</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5184">QNO-5184</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5188">QNO-5188</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5198">QNO-5198</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5205">QNO-5205</a>)</li>
<li>Improve <strong>schema-migration tools</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-5179">QNO-5179</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5206">QNO-5206</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5212">QNO-5212</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5213">QNO-5213</a>)</li></ul><h2>Breaking changes</h2><ul>
<li><code>IDataSession</code> and <code>IApplication</code> now directly implement the <code>IServiceRequestHandler</code> and helper methods that used to extend <code>IApplication</code> now extend this interface instead, so calls like <code>GetModel()</code> can now be executed against an <code>IApplication</code> or an <code>IDataSession</code>. Many methods have been moved out of the <code>IServiceRequestHandler</code> interface to extension methods declared in the <code>Encodo.IOC</code> namespace. This move will require applications to update the <code>usings</code>. ReSharper will automatically find the correct namespace and apply it for you.</li>
<li>Similarly, the extension method <code>ApplicationExtensions.GetInstance()</code> has been replaced with a direct implementation of the <code>IServiceRequestHandler</code> by <code>IApplication</code>.</li>
<li><code>MetaBuilder.Include()</code> has been replaced with <code>Dependencies.Include()</code></li>
<li>When you call the new version of <code>CreateModel()</code>, you can no longer call <code>CreateMainModule()</code> because the main module is set up automatically. Although the call is marked as obsolete, it can only be combined with the older overload of the <code>CreateModel()</code>. Using it with the newer overload will cause a runtime error as the main module is added to the model twice.</li>
<li><div class=" "><p>The various methods to create paths with the <code>MetaBuilder</code> have been replaced by <code>AddPath()</code>. To rewrite a path, use the following style:</p>
<pre class=" "><code>Builder.AddPath(
  Elements.Classes.A.FromOne("Id"), 
  Elements.Classes.B.ToMany("FileId"), 
  path =&gt; path.SetMetaId(new Guid("…")).SetDeleteRule(MetaPathRule.Cascade),
  idx =&gt; idx.SetMetaId(new Guid("…"))
);</code></pre></div></li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3256</guid>
    <title><![CDATA[C# Handbook Rewrite]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3256</link>
    <pubDate>Tue, 26 Apr 2016 21:40:40 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">26. Apr 2016 21:40:40 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">27. Apr 2016 07:13:40 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Encodo published its first C# Handbook and published it to <a href="http://encodo.com/en/blogs.php?entry_id=141">its web site</a> in 2008. At the time, we also published to several other standard places and got some good, positive feedback. Over the next year, I made some more changes and published new versions. The latest version is 1.5.2 and is available from <a href="http://encodo.com/en/documents.php#csharp-handbook">Encodo&rsquo;s web site</a>. Since then, though I&rsquo;ve made a few extra notes and corrected a few errors, but never published an official version again.</p>
<p>This is not because Encodo hasn&rsquo;t improved or modernized its coding guidelines, but because of several issues, listed below.</p>
<ul>
<li>At 72 pages, it&rsquo;s really quite long</li>
<li>A more compact, look-up reference would be nice</li>
<li>It contains a mix of C#-specific, Encodo-specific and library-specific advice</li>
<li>It&rsquo;s maintained in Microsoft Word</li>
<li>Code samples are manually formatted</li>
<li>New versions are simply new copies in versioned folders (no source control)</li>
<li>Collaboration is nearly impossible</li>
<li>There is nothing about any .NET version newer than 3.5</li>
<li>There is no mention of any other programming language (e.g. TypeScript, JavaScript)</li>
<li>A lot of stuff is overly complicated (e.g. <code>var</code> advice) or just plain wrong (e.g. <code>var</code> advice)</li></ul><p>To address these issues and to accommodate the new requirements, here&rsquo;s what we&rsquo;re going to do:</p>
<ul>
<li><div>Convert the entire document from Word to Markdown and put it in a Git repository<ul>
<li>Collaboration? Pull requests. Branches.</li>
<li>Versioning? Standard diffing of commits.</li>
<li>Code samples? Automatic highlighting from GitLab (Encodo&rsquo;s internal server) or GitHub (external repository).</li></ul></div></li>
<li>Separate the chapters into individual files and keep them shorter and more focused on a single topic</li>
<li><div>Separate all of the advice and rules into the following piles:<ul>
<li>General programming advice and best practices</li>
<li>C#-specific</li>
<li>Encodo-specific</li>
<li>Library-specific (e.g. Quino)</li></ul></div></ul><p>These are the requirements and goals for a new version of the C# handbook.</p>
<p>The immediate next steps are:</p>
<ol>
<li>Convert current version from Microsoft Word to Markdown (<del>done</del>)</li>
<li>Add everything to a Git repository (<del>done</del>)</li>
<li>Overhaul the manual to remove incorrect and outdated material; address issues above (<strong class="highlight">in progress</strong>)</li>
<li>Mirror externally (<a href="https://github.com">GitHub</a> or <a href="https://gitlab.com">GitLab</a> or both)</li></ol><p>I hope to have an initial, modern version ready within the next month or so.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3240</guid>
    <title><![CDATA[API Design: The Road Not Taken]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3240</link>
    <pubDate>Thu, 07 Apr 2016 22:27:10 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">7. Apr 2016 22:27:10 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <blockquote class="quote quote-block "><div>&ldquo;Unwritten code requires no maintenance and introduces no cognitive load.&rdquo;</div></blockquote><p>As I was working on another part of Quino the other day, I noticed that the oft-discussed registration and configuration methods [1] were a bit clunkier than I&rsquo;d have liked. To whit, the methods that I tended to use together for configuration had different return types and didn&rsquo;t allow me to freely mix calls fluently.</p>
<h2>The difference between <code>Register</code> and <code>Use</code></h2><p>The return type for <code>Register</code> methods is <code>IServiceRegistrationHandler</code> and the return type for <code>Use</code> methods is <code>IApplication</code> (a descendant), The <em>Register*</em> methods come from the IOC interfaces, while the application builds on top of this infrastructure with higher-level <em>Use*</em> configuration methods.</p>
<p>This forces developers to write code in the following way to create and configure an application.</p>
<pre class=" "><code>public IApplication CreateApplication()
{
  var result =
    new Application()
    .UseStandard()
    .UseOtherComponent();

  result.
    .RegisterSingle&lt;ICodeHandler, CustomCodeHandler&gt;()
    .Register&lt;ICodePacket, FSharpCodePacket&gt;();

  return result;
}</code></pre><p>That doesn&rsquo;t look too bad, though, does it? It doesn&rsquo;t seem like it would cramp anyone&rsquo;s style too much, right? Aren&rsquo;t we being a bit nitpicky here?</p>
<p>That&rsquo;s exactly why Quino 2.0 was released with this API. However, here we are, months later, and I&rsquo;ve written a lot more configuration code and it&rsquo;s really starting to chafe that I have to declare a local variable and sort my method invocations.</p>
<p>So I think it&rsquo;s worth addressing. Anything that disturbs me as the writer of the framework—that gets in my way or makes me write more code than I&rsquo;d like—is going to disturb the users of the framework as well.</p>
<p>Whether they&rsquo;re aware of it or not.</p>
<h2>Developers are the Users of a Framework</h2><p>In the best of worlds, users will complain about your crappy API and make you change it. In the world we&rsquo;re in, though, they will cheerfully and unquestioningly copy/paste the hell out of whatever examples of usage they find and cement your crappy API into their products <em>forever</em>.</p>
<p>Do not underestimate how quickly calls to your inconvenient API will proliferate. In my experience, programmers really tend to just add a workaround for whatever annoys them instead of asking you to fix the problem at its root. This is a shame. I&rsquo;d rather they just complained vociferously that the API is crap rather than <em>using it</em> and making me support it side-by-side with a better version for usually feels like an eternity.</p>
<p>Maybe it&rsquo;s because I very often have control over framework code that I will just not deal with bad patterns or repetitive code. Also I&rsquo;ve become very accustomed to having a wall of tests at my beck and call when I bound off on another initially risky but in-the-end rewarding refactoring.</p>
<p>If you&rsquo;re not used to this level of control, then you just deal with awkward APIs or you build a workaround as a band-aid for the symptom rather than going after the root cause.</p>
<h2>Better Sooner than Later</h2><p>So while the code above doesn&rsquo;t trigger warning bells for most, once I&rsquo;d written it a dozen times, my fingers were already itching to add <code>[Obsolete]</code> on <em>something</em>.</p>
<p>I am well-aware that this is not a simple or cost-free endeavor. However, I happen to know that there aren&rsquo;t <em>that</em> many users of this API yet, so the damage can be controlled.</p>
<p>If I wait, then replacing this API with something better <em>later</em> will take a bunch of versions, obsolete warnings, documentation and re-training until the old API is finally eradicated. It&rsquo;s much better to use your own APIs—if you can—before releasing them into the wild.</p>
<p>Another more subtle reason why the API above poses a problem is that it&rsquo;s more difficult to discover, to learn. The difference in return types will feel arbitrary to product developers. Code-completion is less helpful than it could be.</p>
<p>It would be much nicer if we could offer an API that helped users discover it at their own pace instead of making them step back and learn new concepts. Ideally, developers of Quino-based applications shouldn&rsquo;t have to know the subtle difference between the IOC and the application.</p>
<h2>A Better Way</h2><p>Something like the example below would be nice.</p>
<pre class=" "><code>return
  new Application()
  .UseStandard()
  .RegisterSingle&lt;ICodeHandler, CustomCodeHandler&gt;()
  .UseOtherComponent()
  .Register&lt;ICodePacket, FSharpCodePacket&gt;();</code></pre><p>Right? Not a gigantic change, but if you can imagine how a user would write that code, it&rsquo;s probably a lot easier and more fluid than writing the first example. In the second example, they would just keep asking code-completion for the next configuration method <em>and it would just be there</em>.</p>
<h2>Attempt #1: Use a Self-referencing Generic Parameter</h2><p>In order to do this, I&rsquo;d already created an issue in our tracker to parameterize the <code>IServiceRegistrationHandler</code> type in order to be able to pass back the proper return type from registration methods.</p>
<p>I&rsquo;ll show below what I mean, but I took a crack at it recently because I&rsquo;d just watched the very interesting video <a href="https://vimeo.com/154564491">Fun with Generics</a> by <cite>Benjamin Hodgson</cite> (<cite><a href="http://vimeo.com/">Vimeo</a></cite>), which starts off with a technique identical to the one I&rsquo;d planned to use—and that I&rsquo;d already used successfully for the <code>IQueryCondition</code> interface. [2]</p>
<p>Let&rsquo;s redefine the <code>IServiceRegistrationHandler</code> interface as shown below,</p>
<pre class=" "><code>public interface IServiceRegistrationHandler&lt;TSelf&gt;
{
  TSelf Register&lt;TService, TImplementation&gt;()
      where TService : class
      where TImplementation : class, TService;

  // …
}</code></pre><p>Can you see how we pass the type we&rsquo;d like to return as a generic type parameter? Then the descendants would be defined as,</p>
<pre class=" "><code>public interface IApplication : IServiceRegistrationHandler&lt;IApplication&gt;
{
}</code></pre><p>In the video, Hodgson notes that the technique has a name in formal notation, &ldquo;F-bounded quantification&rdquo; but that a snappier name comes from the C++ world, &ldquo;curiously recurring template pattern&rdquo;. I&rsquo;ve often called it a self-referencing generic parameter, which seems to be a popular search term as well.</p>
<p>This is only the first step, though. The remaining work is to update all usages of the formerly non-parameterized interface <code>IServiceRegistrationHandler</code>. This means that a lot of extension methods like the one below</p>
<pre class=" "><code>public static IServiceRegistrationHandler RegisterCoreServices(
  [NotNull] this IServiceRegistrationHandler handler)
{
}</code></pre><p>will now look like this:</p>
<pre class=" "><code>public static TSelf RegisterCoreServices&lt;TSelf&gt;(
[NotNull] this IServiceRegistrationHandler&lt;TSelf&gt; handler)
  where TSelf : IServiceRegistrationHandler&lt;TSelf&gt;
{
}</code></pre><p>This makes defining such methods more complex (again). [3] in my attempt at implementing this, Visual Studio indicated 170 errors remaining after I&rsquo;d already updated a couple of extension methods. </p>
<h2>Attempt #2: Simple Extension Methods</h2><p>Instead of continuing down this path, we might just want to follow the pattern we established in a few other places, by defining both a <code>Register</code> method, which uses the <code>IServiceRegistrationHandler</code>, <em>and</em> a <code>Use</code> method, which uses the <code>IApplication</code></p>
<p>Here&rsquo;s an example of the corresponding &ldquo;Use&rdquo; method:</p>
<pre class=" "><code>public static IApplication UseCoreServices(
  [NotNull] this IApplication application)
{
  if (application == null) { throw new ArgumentNullException("application"); }

  application
    .RegisterCoreServices()
    .RegisterSingle(application.GetServices())
    .RegisterSingle(application);

  return application;
}</code></pre><p>Though the technique involves a bit more boilerplate, it&rsquo;s easy to write and understand (and reason about) these methods. As mentioned in the initial sentence of this article, the cognitive load is lower than the technique with generic parameters.</p>
<p>The only place where it would be nice to have an <code>IApplication</code> return type is from the <code>Register*</code> methods defined on the <code>IServiceRegistrationHandler</code> itself.</p>
<p>We already decided that self-referential generic constraints would be too messy. Instead, we could define some extension methods that return the correct type. We can&rsquo;t name the method the same as the one that already exists on the interface [4], though, so let&rsquo;s prepend the word <code>Use</code>, as shown below:</p>
<pre class=" "><code>IApplication UseRegister&lt;TService, TImplementation&gt;(
  [NotNull] this IApplication application)
      where TService : class
      where TImplementation : class, TService;
{
  if (application == null) { throw new ArgumentNullException("application"); }

  application.Register&lt;TService, TImplementation&gt;();

  return application;
}</code></pre><p>That&rsquo;s actually pretty consistent with the other configuration methods. Let&rsquo;s take it for a spin and see how it feels. Now that we have an alternative way of registering types fluently without &ldquo;downgrading&rdquo; the result type from <code>IApplication</code> to <code>IServiceRegistrationHandler</code>, we can rewrite the example from above as:</p>
<pre class=" "><code>return
  new Application()
  .UseStandard()
  .UseRegisterSingle&lt;ICodeHandler, CustomCodeHandler&gt;()
  .UseOtherComponent()
  .UseRegister&lt;ICodePacket, FSharpCodePacket&gt;();</code></pre><p>Instead of increasing cognitive load by trying to push the C# type system to places it&rsquo;s not ready to go (yet), we use tiny methods to tweak the API and make it easier for users of our framework to write code correctly. [5]</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3240_1_body" class="footnote-number">[1]</span> See Encodo’s configuration library for Quino <a href="https://www.earthli.com/news/view_article.php?id=412">Part 1</a>, <a href="https://www.earthli.com/news/view_article.php?id=413">Part 2</a> and <a href="https://www.earthli.com/news/view_article.php?id=414">Part 3</a> as well as API Design: Running and Application <a href="https://www.earthli.com/news/view_article.php?id=422">Part 1</a> and <a href="https://www.earthli.com/news/view_article.php?id=426">Part 2</a> and, finally, <a href="https://www.earthli.com/news/view_article.php?id=412">Starting up an application, in detail</a>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3240_2_body" class="footnote-number">[2]</span> The video goes into quite a bit of depth on using generics to extend the type system in the <em>direction</em> of dependent types. Spoiler alert: he doesn&rsquo;t make it because the C# type system can&rsquo;t be abused in this way, but the journey is informative.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3240_3_body" class="footnote-number">[3]</span> As detailed in the links in the first footnote, I&rsquo;d just <em>gotten rid</em> of this kind of generic constraint in the configuration calls because it was so ugly and offered little benefit.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3240_4_body" class="footnote-number">[4]</span> <p>If you define an extension method for a descendant type that has the same name as a method of an ancestor interface, the method-resolution algorithm for C# will never use it. Why? Because the directly defined method matches the name and all the types and is a &ldquo;stronger&rdquo; match than an extension method.</p>
<p>Perhaps an example is in order:</p>
<pre class=" "><code>interface IA 
{
  IA RegisterSingle&lt;TService, TConcrete&gt;();
}

interface IB : IA { }

static class BExtensions
{
  static IB RegisterSingle&lt;TService, TConcrete&gt;(this IB b) { return b; }

  static IB UseStuff(this IB b) { return b; }
}</code></pre><p>Let&rsquo;s try to call the method from <code>BExtensions</code>:</p>
<pre class=" "><code>public void Configure(IB b)
{
  b.RegisterSingle&lt;IFoo, Foo&gt;().UseStuff();
}</code></pre><p>The call to <code>UseStuff</code> cannot be resolved because the return type of the matched <code>RegisterSingle</code> method is the <code>IA</code> of the interface method not the <code>IB</code> of the extension method. There is a solution, but you&rsquo;re not going to like it (I know I don&rsquo;t).</p>
<pre class=" "><code>public void Configure(IB b)
{
  BExtensions.RegisterSingle&lt;IFoo, Foo&gt;(b).UseStuff();
}</code></pre><p>You have to specify the extension-method class&rsquo;s name explicitly, which engenders awkward fluent chaining—you&rsquo;ll have to nest these calls if you have more than one—but the desired method-resolution was obtained.</p>
<p>But at what cost? <a href="http://www.imdb.com/title/tt0078788/quotes?item=qt0324876">The horror…the horror.</a> (<cite><a href="http://www.imdb.com/">IMDb</a></cite>)</p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3240_5_body" class="footnote-number">[5]</span> The final example does not run against Quino 2.2, but will work in an upcoming version of Quino, probably 2.3 or 2.4.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3235</guid>
    <title><![CDATA[v2.2: Winform fixes and Query Improvements]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3235</link>
    <pubDate>Fri, 25 Mar 2016 13:41:54 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">25. Mar 2016 13:41:54 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The summary below describes major new features, items of note and breaking changes. The <a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=22103">full list of issues</a> is also available for those with access to the Encodo issue tracker.</p>
<h2>Highlights</h2><ul>
<li>Lots of bug fixes and improvements for the <strong>Winform UI</strong> and <strong>German translations</strong> with the release of Punchclock on this version. (<a href="https://secure.encodo.ch/jira/browse/QNO-5162">QNO-5162</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5159">QNO-5159</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5158">QNO-5158</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5157">QNO-5157</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5156">QNO-5156</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5140">QNO-5140</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5155">QNO-5155</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5145">QNO-5145</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5111">QNO-5111</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5107">QNO-5107</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5106">QNO-5106</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5104">QNO-5104</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-5015">QNO-5015</a>)</li>
<li><code>DateTimeExtensions.GetDayOfWeek()</code> had a <strong>leap-day bug</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-5051">QNO-5051</a>)</li>
<li>Fixed how the <strong>hash code</strong> for <code>GenericObjects</code> is calculated, which fixes sorting issues in grids, specifically for non-persisted or transient objects (<a href="https://secure.encodo.ch/jira/browse/QNO-5137">QNO-5137</a>)</li>
<li>Improvements to the <strong><code>IAccessControl</code> API</strong> for getting groups and users and testing membership (<a href="https://secure.encodo.ch/jira/browse/QNO-5133">QNO-5133</a>)</li>
<li><div class=" "><p>Add support for <strong>query aliases</strong> (e.g. for joining the same table multiple times) (<a href="https://secure.encodo.ch/jira/browse/QNO-531">QNO-531</a>) This changes the API surface only minimally. Applications can pass an <code>alias</code> when calling the <code>Join</code> method, as shown below,</p>
<pre class=" "><code>query.Join(Metadata.Project.Deputy, alias: "deputy")</code></pre><p>You can find more examples of aliased queries in the <code>TestAliasedQuery()</code>, <code>TestJoinAliasedTables()</code>, <code>TestJoinChildTwice()</code> defined in the <code>QueryTests</code> testing fixture.</p>
</div></li>
<li>Add a standalone <code>IQueryAnalyzer</code> for optimizations and in-memory mini-drivers (<a href="https://secure.encodo.ch/jira/browse/QNO-4830">QNO-4830</a>)</li></ul><h2>Breaking changes</h2><ul>
<li><code>ISchemaManager</code> has been removed. Instead, you should retrieve the interface you were looking for from the IOC. The possible interfaces you might need are <code>IImportHandler</code>, <code>IMappingBuilder</code>, <code>IPlanBuilder</code> or <code>ISchemaCommandFactory</code>.</li>
<li><code>ISchemaManagerSettings.GetAuthorized()</code> has been moved to <code>ISchemaManagerAuthorizer</code>. </li>
<li><div>The hash-code fix for <code>GenericObjects</code> may have an effect on the way your application sorts objects.<div class=" "><p>The <code>IParticipantManager</code> (base interface of <code>IAccessControl</code>) no longer has a single method called <code>GetGroups(IParticipant)</code>. This method was previously used to get the groups to which a user belongs <em>and</em> the child groups of a given group. This confusing double duty for the API led to an incorrect implementation for <em>both</em> usages. Instead, there are now two methods:</p>
<ul>
<li><code>IEnumerable&lt;IGroup&gt; GetGroups(IUser user)</code>: Gets the groups for the given user</li>
<li><code>IEnumerable&lt;IGroup&gt; GetChildGroups(IGroup group)</code>: Gets the child groups for the given group</li></ul><p>The old method has been removed from the interface because (A) it never worked correctly anyway and (B) it conflicts with the new API.</p>
</div></div></li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3234</guid>
    <title><![CDATA[Voxxed Z&uuml;rich 2016: Notes]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3234</link>
    <pubDate>Fri, 25 Mar 2016 13:41:30 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">25. Mar 2016 13:41:30 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">This article was originally published on the <a href="http://blogs.encodo.ch/news/view_article.php?id=448">Encodo Blogs</a>.</small></p>
<p><hr></p>
<p>This first-ever <a href="https://voxxeddays.com/zurich/">Voxxed Zürich</a> was hosted at the cinema in the SihlCity shopping center in Zürich on March 3rd. All presentations were in English. The conference was relatively small—333 participants—and largely vendor-free. The overal technical level of the presentations and participants was quite high. I had a really nice time and enjoyed a lot of the presentations.</p>
<p>There was a nice common thread running through all of the presentations, starting with the Keynote. There&rsquo;s a focus on performance and reliability through immutabiliy, sequences, events, actors, delayed execution (lambdas, which are relatively new to Java), instances in the cloud, etc. It sounds very BUZZWORDY, but instead it came as a very technically polished conference that reminded me of how many good developers there are trying to do the right thing. Looking forward to next year; hopefully Encodo can submit a presentation.</p>
<p>You can take a look at the <a href="https://cfp-vdz.exteso.com/program/byday/thursday.html">VoxxedDays Zürich – Schedule</a>. The talks that I visited are included below, with links to the presentation page, the video on YouTube and my notes and impressions. YMMV.</p>
<h2>Keynote: Life beyond the Illusion of the Present</h2><p><a href="https://cfp-vdz.exteso.com/program/talk/FMJ-0830/Life_Beyond_the_Illusion_of_Present.html">Life beyond the Illusion of the Present</a>—<em>Jonas Bonér</em></p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/Nhz5jMXS8gE" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><cite><a href="http://www.youtube.com/">YouTube</a></cite></span></span></p>
<h3>Notes</h3><ul>
<li>He strongly recommended reading <a href="http://queue.acm.org/detail.cfm?id=2655736">The Network is reliable</a> by <em>Peter Bailis</em>.</li>
<li>This talk is about event-driven, CQRS programming.</li>
<li>Focus on  immutable state, very much like JoeDuffy, etc. transactional accrual of facts. </li>
<li><strong>Never delete data, annotate with more facts.</strong></li>
<li>The reality at any point can be calculated for a point in time by aggregating facts up to that point. Like the talk I once wrote up some notes about (<a href="http://www.infoq.com/presentations/Complexity-Big-Data">Runaway Complexity in Big Data, and a Plan to Stop It</a> by <cite>Nathan Marz</cite> (<cite><a href="http://www.infoq.com/">InfoQ</a></cite>)). </li>
<li>Everything else is a performance optimization. <strong>Database views, tables are all caches on the transaction log.</strong> Stop throwing the log away, though.</li>
<li>Define smaller atomic units. Not a whole database. Smaller. Consistency boundary.  Services?</li>
<li><strong>Availability trumps consistency.</strong> Use causal consistency through mechanisms other than time stamps. Local partial better than global.</li>
<li>He talked about data-flow programming; fingers crossed that we get some language support in C# 7</li>
<li>Akka (Akka.NET) is the main product.</li></ul><h2>Kotlin − Ready for production</h2><p><a href="https://cfp-vdz.exteso.com/program/talk/CPG-0115/Kotlin____Ready_for_production.html">Kotlin − Ready for production</a>—<em>Hadi Hariri</em></p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/mSg9kSYfeX0" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><cite><a href="http://www.youtube.com/">YouTube</a></cite></span></span></p>
<ul>
<li>Used at JetBrains, open-source. 14k+ users. It&rsquo;s not a ground-breaking language. They tried Scala and Scala was the first language they tried to use (Java already being off the table) but they didn&rsquo;t like it, so they invented Kotlin.</li>
<li>Interoperable with Java (of course). Usable from all sorts of systems, but intelliJ Idea has first-class support.
<li><div>Much less code, less maintenance. Encapsulates some concepts like &ldquo;data classes&rdquo; which do what they&rsquo;re supposed for DTO definitions.<ul>
<li>Inferred type on declarations. No nulls. <strong>Null-safe by design.</strong> Opt-in for nulls.</li>
<li>Implicit casts as well</li>
<li>Interface delegation</li>
<li>Lazy delegation</li>
<li>Deconstruction</li>
<li>Global infix operators; very expressive</li>
<li>Also <strong>defaults to/focuses on immutability</strong></li>
<li><strong>Algebraic data types/ data flow</strong></li>
<li>Anglo is statically typed XML views for android</li></ul></div></li>
<li>JavaScript target exists and is the focus of work. Replacement for TypeScript?</li></ul><h2>Reactive Apps with Akka and AngularJS</h2><p><a href="https://cfp-vdz.exteso.com/program/talk/EVM-5752/Reactive_Apps_with_Akka_and_AngularJS.html">Reactive Apps with Akka and AngularJS</a>—<em>Heiko Seeberger</em></p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/s8W-aqKieAg" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><cite><a href="http://www.youtube.com/">YouTube</a></cite></span></span></p>
<ul>
<li>He strongly recommended reading <a href="http://www.reactivemanifesto.org">the reactive manifesto</a></li>
<li>Responsive: timely response / non-functional / also under load / scale up/down/out</li>
<li>Resilient: fail early</li>
<li>Message-driven: <strong>async message-passing</strong> is a way of getting reactive/responsive. Automatic decoupling leads to better error-handling, no data loss
<li><div>Akka provides support for:<ul>
<li>Actor-based model (actors are services); watch video from Channel Nine</li>
<li>Akka HTTP Server is relatively new</li>
<li>Akka is written in Scala</li>
<li>There&rsquo;s a Scala DSL for defining the controller (define routes)</li>
<li>The Scala compiler is pure crap. Sooooo slooooowww (62 seconds for 12 files)</li></ul></div></ul><p>During his talk, he took us through the following stages of building a scalable, resilient actor-based application with Akka.</p>
<ul>
<li>First he started with static HTML</li>
<li>Then he moved on to something connected to AKKA, but not refreshing</li>
<li>W3C Server-sent events is unidirectional channel from the server to the client. He next used this to have instant refresh on the client; not available on IE. Probably used by SignalR (or whatever replaced it)? Nothing is typed, though, just plain old JavaScript</li>
<li>Then he set up sharding</li>
<li>Then persistence (Cassandra, Kafka)</li></ul><p>AKKA Distributed Data</p>
<ul>
<li>Deals with keeping replicas consistent without central coordination</li>
<li>Conflict-free replicated data types</li>
<li>Fully distributed, has pub/sub semantics</li>
<li>Uses the Gossip protocol</li>
<li>Support various consistency strategies</li>
<li>Using AKKA gives you automated scaling support (unlike the SignalR demo Urs and I did over 2 years ago, but that was a chat app as well)</li></ul><p>AKKA Cluster Sharding</p>
<ul>
<li>Partitioning of actors/services across clusters</li>
<li>Supports various strategies</li>
<li>Default strategy is to distribute unbalanced actors to new shards</li>
<li>The ShardRegion is another actor that manages communication with sharded actors (entities). This introduces a new level of indirection, which must be honored in the code (?)</li></ul><p>AKKA Persistence</p>
<ul>
<li>Event-sourcing: validate commands, journal events, apply the event after persistence.</li>
<li>Application is applied to local state only after the journal/persistence has indicated that the command was journaled</li>
<li>On recovery, events are replayed</li>
<li>Supports snapshotting (caching points in time)</li>
<li>Requires a change to the actor/entity to use it. All written in Scala.</li></ul><p>Akka looks pretty good. It guarantees the ordering because ACTORS. Any given actor only exists on any shard once. If a shard goes down, the actor is recreated on a different shard, and filled with information from the persistent store to &ldquo;recreate&rdquo; the state of that actor.</p>
<p>DDD (Domain-Driven Design) and the actor model. Watch <a href="https://channel9.msdn.com/Shows/Going+Deep/Hewitt-Meijer-and-Szyperski-The-Actor-Model-everything-you-wanted-to-know-but-were-afraid-to-ask">Hewitt, Meijer and Szyperski: The Actor Model (everything you wanted to know, but were afraid to ask)</a> (<cite><a href="http://channel9.msdn.com/">Channel9</a></cite>).</p>
<p>Code is on GitHub: seeberger/reactive_flows</p>
<h2>Lambda core − hardcore</h2><p><a href="https://cfp-vdz.exteso.com/program/talk/WCB-3457/Lambda_core___hardcore.html">Lambda core − hardcore</a>—<em>Jarek Ratajski</em></p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/Dun8ewSeX6c" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><cite><a href="http://www.youtube.com/">YouTube</a></cite></span></span></p>
<p>Focus on immutability and no side-effects. Enforced by the lambda calculus. Pretty low-level talk about lambda calculus. Interesting, but not applicable. He admitted as much at the top of the talk.</p>
<p>Links:</p>
<ul>
<li><a href="http://weblogs.asp.net/dixin">Dixin&rsquo;s Blog</a></li>
<li><a href="https://github.com/jarekratajski/badlam">Badlam visualization</a></li>
<li><a href="http://www.setblack.pl/vision/lambda/index.html">His presentation engine</a></li></ul><h2>expect(&ldquo;poo&rdquo;).length.toBe(1)</h2><p><a href="https://cfp-vdz.exteso.com/program/talk/PFW-5895/expect______length_toBe_1_.html">expect(&ldquo;poo&rdquo;).length.toBe(1)</a>—<em>Philip Hofstetter</em> [1]</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/7NuA9OXWjV4" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><cite><a href="http://www.youtube.com/">YouTube</a></cite></span></span></p>
<p>This was a talk about expectations of the length of a character. The presenter was very passionate about his talk and went into an incredible amount of detail.</p>
<ul>
<li>What is a string? This is the kind of stuff every programmer needs to know. [2]</li>
<li>String is not a collection of bytes. It&rsquo;s a sequence of graphemes. string &lt;&gt; char[]</li>
<li>UTF-16 is crap. What about the in-memory representation? Why in God&rsquo;s name did Python 3 use UTF32? Unicode Transformation format.</li>
<li>What is the length of a string? ä is how many? Single character (diuresis included) or a with combining diuresis?</li>
<li>In-memory representation in Java and C# are UCS-2 (UNICODE 1); stuck in 1996, before Unicode 2.0 came out. This leaks into APIs because of how strings are returned … string APIs use UTF-16, encoding with surrogate pairs to get to characters outside of the BMP (understood by convention, but not by the APIs that expect UTF-16 … which has no idea what surrogate pairs are … and counting algorithms, find, etc. won&rsquo;t work).</li>
<li>ECMAScript hasn&rsquo;t really fixed this, either. substr() can break strings charAt() is still available and has no idea about code points. Does this apply to ES6? String-equality doesn&rsquo;t work for the diuresis above.</li>
<li>So we&rsquo;re stuck with server-side. <strong>Who does it right? Perl. Swift. Python. Ruby.</strong> Python went through hell with backwards compatibility but with 3.3 they&rsquo;re doing OK again. Ruby strings are a tuple of encoding and data. All of the others have their string libraries dealing in graphemes. How did Perl always get it right? Perl has three methods for asking questions about length, in graphemes, code points or bytes</li>
<li>What about those of us using JavaScript? C#? Java? There are external libraries that we should be using. Not just for DateTime, but for string-handling as well. Even <strong>EcmaScript15 still uses code points rather than graphemes</strong>, so the count varies depending on how the grapheme is constructed.</li>
<li>Security concerns: certificate authorities have to be aware of homographs (e.g. a character that looks like another one, but has a different encoding/byte sequence).</li>
<li>He recommended the book <a href="http://www.amazon.com/Unicode-Explained-Jukka-K-Korpela/dp/059610121X/">Unicode explained</a> (<cite><a href="http://www.amazon.com/">Amazon</a></cite>) by <em>Jukka K. Korpela</em>.</li></ul><h2>How usability fits in UX − it&rsquo;s no PICNIC</h2><p><a href="https://cfp-vdz.exteso.com/program/talk/KYD-9831/How_usuability_fits_in_UX___it_s_no_PICNIC.html">How usability fits in UX − it&rsquo;s no PICNIC</a>—<em>Myriam Jessier</em></p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/8eFulIAxJQ0" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><cite><a href="http://www.youtube.com/">YouTube</a></cite></span></span></p>
<p>What should a UI be?</p>
<ol>
<li>Functional</li>
<li>Reliable</li>
<li>Usable</li>
<li>Convenient</li>
<li>Pleasurable</li></ol><p>Also nice to have:</p>
<ol>
<li>Desirable</li>
<li>Delightful</li>
<li>memorable</li>
<li>Learnable</li>
<li>3 more</li></ol><p>Book recommendation: <a href="http://www.amazon.com/Dont-Make-Think-Revisited-Usability/dp/0321965515/">Don&rsquo;t make me think</a> by <em>Steve Krug</em></p>
<ul>
<li>Avoid mindless and unambiguous clicks. Don&rsquo;t count clicks, count useless shit you need to do.</li>
<li>Let the words go. People&rsquo;s attention will wander.</li>
<li>UX is going to be somewhat subjective. <strong>Don&rsquo;t try to please everyone.</strong></li>
<li>OMG She uses hyphens correctly.</li>
<li>She discussed the difference between UX, CX, UI.</li>
<li>Personas are placeholders for your users. See <a href="http://Personapp.io">Personapp</a> to get started working with personas.</li></ul><p>Guidelines:</p>
<ul>
<li>Consistent and standardized UI</li>
<li>Guide the user (use visual cues, nudging)</li>
<li>Make the CallToAction (CTA) interactive objects obvious</li>
<li>Give feedback on progress, interaction</li>
<li>Never make a user repeat something they already told you. You&rsquo;re software, you should have eidetic memory</li>
<li><strong>Always have default values in forms (e.g. show the expected format)</strong></li>
<li>Explain how the inputed information will be used (e.g. for marketing purposes)</li>
<li>No more &ldquo;reset&rdquo; button or mass-delete buttons. Don&rsquo;t make it possible/easy to wipe out all someone&rsquo;s data</li>
<li>Have clear and explanatory error or success messages (be encouraging)</li>
<li>Include a clear and visual hierarchy and navigation</li></ul><p>Guidelines for mobile:</p>
<ul>
<li>Make sure it works on all phones</li>
<li>Give incentives for sharing and purpose (engagement rates make marketing happy. CLICK THE BUTTON)</li>
<li>Keep usability and conversion in mind (not necessarily money, but you actually want people to be using your app correctly)</li>
<li>Usability (can you use your app on the lowest screen-brightness?)</li>
<li>…and more…</li>
<li>Make it pretty (some people don&rsquo;t care, e.g. She very clearly said that she&rsquo;s not aesthetically driven, it&rsquo;s not her field; other people do care. A lot).</li>
<li>Give all the information a customer needs to purchase</li>
<li>Design for quick movement (no lag)</li>
<li>Do usability testing through video</li></ul><ul>
<li>Leverage expectations. Fit in to the environment. Search is on the left? Behind a button? Do that. Don&rsquo;t make a new way of searching.</li>
<li>If you offer a choice, then make them as mutually exclusive as possible. When a company talks to itself (e.g. industry jargon), then users get confused</li>
<li>The registration process should be commensurate to the thing that you&rsquo;re registering for</li>
<li>Small clickable ads on mobile. Make click targets appropriate.</li>
<li>Don&rsquo;t blame negative feedback on &ldquo;fear of change&rdquo;. It&rsquo;s probably you. If people don&rsquo;t like it, then it might not be user-friendly. The example with Twitter&rsquo;s star vs. heart. It&rsquo;s interesting how we let the world frame our interactions. Why not both? Too complex? Would people really be confused by two buttons? One to &ldquo;like&rdquo; and one for &ldquo;read later&rdquo;?</li></ul><p>Suggested usability testing tools:</p>
<ul>
<li>Crazy Egg is $9 per month for heatmaps.</li>
<li>Qualaroo</li>
<li>Optimizely (A/B testing)</li>
<li>Usabilia</li>
<li>Userfeel</li>
<li>Trymyui</li></ul><h2>React − A trip to Russia isn&rsquo;t all it seems</h2><p><a href="https://cfp-vdz.exteso.com/program/talk/GYI-7629/React___A_trip_to_Russia_isn_t_all_it_seems.html">React − A trip to Russia isn&rsquo;t all it seems</a>—<em>Josh Sephton</em> [3]</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/A-KJr0IwXuI" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><cite><a href="http://www.youtube.com/">YouTube</a></cite></span></span></p>
<p>This talk was about Web UI frameworks and how his team settled on React.</p>
<ul>
<li>Angular too &ldquo;all or nothing&rdquo;.</li>
<li>Backbone has no data-binding.</li>
<li>React looks good. Has its own routing for SPAs. Very component-heavy. Everything&rsquo;s a component. Nothing new here so far.</li>
<li>They built their React to replace a Wordpress-based administration form</li>
<li><strong>Stateful components are a bad idea</strong></li>
<li>React components are like self-contained actors/services</li>
<li>They started with Flux, but ended up with Redux. We&rsquo;re using Redux in our samples. I&rsquo;m eyeballing how to integrate Akka.Net (although I&rsquo;m not sure if that has anything to do with this.</li>
<li>ReactNative: write once, use on any device</li>
<li>Kind of superficial and kinda short but I knew all about this in React already</li></ul><h2>The reactor programming model for composable distributed computing</h2><p><a href="https://cfp-vdz.exteso.com/program/talk/GVW-4138/The_reactor_programming_model_for_composable_distributed_computing.html">The reactor programming model for composable distributed computing</a>—<em>Aleksandar Prokopec</em> [4]</p>
<p><span style="width: 560px; display: table"><span class="auto-content-inline"><embed src="https://www.youtube.com/v/w8B4bJ1XV2E" type="application/x-shockwave-flash" style="width: 560px; height: 350px"></span><span class="auto-content-caption"><cite><a href="http://www.youtube.com/">YouTube</a></cite></span></span></p>
<ul>
<li>Reactive programming, with events as sequences of event objects</li>
<li>Events are equivalent to a list/sequence/streams (enumerable in C#)</li>
<li>This talk is also about managing concurrency</li>
<li>There must be a boundary between outer concurrent events vs. how your application works on them</li>
<li>That&rsquo;s why most UI toolkits are single-threaded</li>
<li><strong>Asynchronous is the antonym of concurrency</strong> (at least in the dictionary)</li>
<li>Filter the stream of events to compress them to frames, then render and log, so the events come in, are marshaled through the serializing bottleneck and are then dispatched asynchronously to different tasks</li>
<li>Reactor lets clients create their own channels (actors) from which they read events and which they register with a server so that it can publish</li>
<li>Akka supports setting up these things, Reactor is another implementation?</li>
<li>Dammit I want destructuring of function results (C# 7?)</li>
<li>It&rsquo;s very easy to build client/server and broadcast and even ordered synchronization using UIDs (or that pattern mentioned by Jonas in the keynote) The UID needs to be location-specific, though. That&rsquo;s not sufficient either, what you need is client-specific. For this, you need special data structures to store the data in a way that edits are automatically correctly ordered. Events sent for these changes make the events are ordered correctly</li>
<li>What is the CRDT? We just implemented an online collaborative editor: composes nicely and provides a very declarative, safe and scalable way of defining software. This is just a function (feeds back into the idea of lambdas here, actually, immutability, encapsulation)</li>
<li><a href="http://github.com/reactors-io/reactors">Reactors</a></li></ul><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3234_1_body" class="footnote-number">[1]</span> I am aware of the irony that the emoji symbol for &ldquo;poo&rdquo; is not supported on this blogging software. That was basically the point of the presentation—that encoding support is difficult to get right. There&rsquo;s an issue for it: <a href="http://earthli.com/projects/view_job.php?id=2084">Add support for UTF8 as the default encoding</a>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3234_2_body" class="footnote-number">[2]</span> In my near-constant striving to be the worst conversational partner ever,  I once gave a similar encoding lesson to my wife on a two-hour walk around a lake when she dared ask why mails sometimes have those &ldquo;stupid characters&rdquo; in them.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3233</guid>
    <title><![CDATA[Finovate 2016: Bank2Things]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3233</link>
    <pubDate>Fri, 25 Mar 2016 13:39:04 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">25. Mar 2016 13:39:04 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <div class=" align-right right"><p><a href="http://finovate.com/videos/finovateeurope-2016-crealogix/"><img src="https://www.earthli.com/data/news/attachments/entry/3233/finovate-logo-mobile_tn.png" alt=" "></a><br>
<a href="http://finovate.com/videos/finovateeurope-2016-crealogix/"><img src="https://www.earthli.com/data/news/attachments/entry/3233/finovate_2016_spreadsheet_tn.png" alt=" "></a></p>
</div><p>At the beginning of the year, we worked on an interesting project that dipped into IOT (Internet of Things). The project was to create use cases for Crealogix&rsquo;s banking APIs in the real world. Concretely, we wanted to show how a customer could use these APIs in their own workflows. The use cases were to provide proof of the promise of flexibility and integrability offered by well-designed APIs.</p>
<p><a href="http://finovate.com/videos/finovateeurope-2016-crealogix/">Watch 7–minute video of the presentation</a></p>
<p><span class="clear-both"></span></p>
<h2>The Use Cases</h2><h3>Football Club Treasurer</h3><p><span style="width: 120px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/app_activity_stream.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/app_activity_stream_tn.png" alt=" " style="width: 120px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/app_activity_stream.png">Activity Stream in the App</a></span></span>The first use case is for the treasurer of a local football club. The treasurer wants to be notified whenever an annual club fee is transferred from a member. The club currently uses a Google Spreadsheet to track everything, but it&rsquo;s updated manually. It would be really nice if the banking API could connected—via some scripting &ldquo;glue&rdquo;—to update the spreadsheet directly, without user intervention. The treasurer would just see the most current numbers whenever he opened the spreadsheet.</p>
<p>The spreadsheet is in addition to the up-to-date view of payments in the banking app. The information is also available there, but not necessarily in the form that he or she would like. Linking automatically to the spreadsheet is the added value.</p>
<p><span class="clear-both"></span></p>
<h3>Chore &amp; Goal Tracker</h3><p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/red_lamp.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/red_lamp_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/red_lamp.png">Red Lamp!</a></span></span><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/green_lamp.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/green_lamp_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/green_lamp.png">Green Lamp!</a></span></span>Imagine a family with a young son who wants to buy a drone. He would have to earn it by doing chores. Instead of tracking this manually, the boy&rsquo;s chores would be tabulated automatically, moving money from the parents&rsquo; account to his own as he did chores. Additionally, a lamp in the boy&rsquo;s room would glow a color indicating how close he was to his goal. The parents wanted to track the boy&rsquo;s progress in a spreadsheet, tracking the transfers as they would have had they not had any APIs.</p>
<p>The idea is to provided added value to the boy, who can record his chores by pressing a button and see his progress by looking at a lamp&rsquo;s color. The parents get to stay in their comfort zone, working with a spreadsheet as usual, but having the data automatically entered in the spreadsheet.</p>
<h2>The Plan</h2><p>It&rsquo;s a bit of a stretch, but it sufficed to ground the relatively abstract concept of banking APIs in an example that non-technical people could follow.</p>
<p>So we needed to pull quite a few things together to implement these scenarios.</p>
<ul>
<li>A lamp that can be controlled via API</li>
<li>A button that can trigger an API</li>
<li>A spreadsheet accessibly via API</li>
<li>An API that can transfer money between accounts</li>
<li>&ldquo;Glue&rdquo; logic that binds these APIs together</li></ul><h2>The Lamp</h2><p><span style="width: 179px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/lifx-color-1000-a19-b22-solo-front-view_2.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/3233/lifx-color-1000-a19-b22-solo-front-view_2_tn.jpg" alt=" " style="width: 179px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/lifx-color-1000-a19-b22-solo-front-view_2.jpg">Lifx Bulb</a></span></span><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/lifxapp.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/lifxapp_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/lifxapp.png">Lifx Smartphone App</a></span></span><br>
We looked at two lamps:</p>
<div class=" " style="margin-left: 195px"><ul>
<li><a href="http://www2.meethue.com/en-us/">Philips Hue</a></li>
<li><a href="http://www.lifx.com">Lifx</a></li></ul></div><p>Either of these—just judging from their websites—would be sufficient to utterly and completely change our lives. The Hue looked like it was going to turn us into musicians, so we went with Lifx, which only threatened to give us horn-rimmed glasses and a beard (and probably skinny jeans and Chuck Taylor knockoffs).</p>
<p>Yeah, we think the marketing for what is, essentially, <em>a light-bulb</em>, is just a touch overblown. Still, you can change the color of the light bulb with a SmartPhone app, or control it via API (which is what we wanted to do).</p>
<p><span class="clear-both"></span></p>
<h2>The Button</h2><p>The button sounds simple. You&rsquo;d think that, in 2016, these things would be as ubiquitous as AOL CDs were in the 1990s. You&rsquo;d be wrong.</p>
<p><span style="width: 179px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/flic_usage.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/flic_usage_tn.png" alt=" " style="width: 179px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/flic_usage.png">Flic Functionality</a></span></span>There&rsquo;s a KickStarter project called <a href="https://flic.io">Flic</a> that purports to have buttons that send signals over a wireless connection. They cost about CHF20. Though we ordered some, we never saw any because of manufacturing problems. If you thought the hype and marketing for a light bulb were overblown, then you&rsquo;re sure to enjoy how Flic presents a <em>button</em>.</p>
<p>We quickly moved along a parallel track to get buttons that can be pressed in real life rather than just viewed from several different angles and in several different colors online.</p>
<p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/cottonelle.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/3233/cottonelle_tn.jpg" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/cottonelle.jpg">Amazon Dash Button</a></span></span>Amazon has what they have called &ldquo;Dash&rdquo; buttons that customers can press to add predefined orders to their one-click shopping lists. The buttons are bound to certain household products that you tend to purchase cyclically: toilet paper, baby wipes, etc.</p>
<p>They sell them dirt-cheap—$5—but only to Amazon Prime customers—and only to customers in the U.S. Luckily, we knew someone in the States willing to let us use his Amazon Prime account to deliver them, naturally only to a domestic address, from which they would have to be forwarded to us here in Switzerland.</p>
<p>That we couldn&rsquo;t use them to order toilet paper in the States didn&rsquo;t bother us—we were planning to hack them anyway.</p>
<p>These buttons showed up after a long journey and we started trapping them in our own mini-network so that we could capture the signal they send and interpret it as a trigger. This was not ground-breaking stuff, but we really wanted the demonstrator to be able to press a physical button on stage to trigger the API that would cascade other APIs and so on.</p>
<p>Of course we could have just hacked the whole thing so that someone presses a button on a screen somewhere—and we programmed this as a backup plan—but the physicality of pressing a button was the part of the demonstration that was intended to ground the whole idea for non-technical users. [1]</p>
<h2>The Spreadsheet</h2><p><span style="width: 193px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/google_docs_club.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/google_docs_club_tn.png" alt=" " style="width: 193px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/google_docs_club.png">Football Club Payment Spreadsheet</a></span></span><span style="width: 193px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/google_docs.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/google_docs_tn.png" alt=" " style="width: 193px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/google_docs.png">Drone Payment Spreadsheet</a></span></span>If you&rsquo;re going to use an API to modify a spreadsheet, then that spreadsheet has to be available online somewhere. The spreadsheet application in Google Docs is a good candidate.</p>
<p>The API allows you to add or modify existing data, but that&rsquo;s pretty much it. When you make changes, they show up immediately, with no ceremony. That, unfortunately, doesn&rsquo;t make for a very nice-looking demo.</p>
<p>Google Docs also offers a Javascript-like scripting language that let&rsquo;s you do more. We wanted to not only insert rows, we wanted charts to automatically update and move down the page to accommodate the new row. All animated, thank you very much.</p>
<p>This took a couple pages of scripting and a good amount of time. It&rsquo;s also no longer a solution that an everyday user is likely to make themselves. And, even though we pushed as hard as we could, we also didn&rsquo;t get everything we wanted. The animation is very jerky (watch the video linked above) but gets the job done.</p>
<p><span class="clear-both"></span></p>
<h2>The Glue</h2><p><span style="width: 118px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/app_connector_selection.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/app_connector_selection_tn.png" alt=" " style="width: 118px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/app_connector_selection.png">Connection Selection in the App</a></span></span>So we&rsquo;ve got a bunch of pieces that are all capable of communicating in very similar ways. The final step is to glue everything together with a bit of script. There are several services available online, like IFTTT—If This Then That—that allow you to code simple logic to connect signals to actions. </p>
<p>In our system, we had the following signals:</p>
<ul>
<li>Transfer was made to a bank account</li>
<li>Button was pressed</li></ul><p>and the following actions:</p>
<ul>
<li>Insert data into Google Spreadsheet</li>
<li>Set color of lamp</li></ul><p><span class="clear-both"></span></p>
<h2>The Crealogix API and UI</h2><p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/crealogix_app_2_things.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/crealogix_app_2_things_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/crealogix_app_2_things.png">Bank 2 Things</a></span></span><span style="width: 122px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/app_post_transfer.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/app_post_transfer_tn.png" alt=" " style="width: 122px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/app_post_transfer.png">Small Transfer in the Activity Stream</a></span></span><span style="width: 105px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3233/app_login.png"><img src="https://www.earthli.com/data/news/attachments/entry/3233/app_login_tn.png" alt=" " style="width: 105px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3233/app_login.png">Logging in to the App</a></span></span>So we&rsquo;re going to betray a tiny secret here. Although the product demonstrated on-stage did actually do what it said, it didn&rsquo;t do it using the Crealogix API to actually transfer money. That&rsquo;s the part that we were actually selling and it&rsquo;s the part we ended up faking/mocking out because the actual transfer is beside the point. Setting up bank accounts is not so easy, and the banks take umbrage at creating them for fake purposes.</p>
<p>Crealogix could have let us use fake testing accounts, but even that would have been more work than it was worth: if we&rsquo;re already faking, why not just fake in the easiest way possible by skipping the API call to Crealogix and only updating the spreadsheet?</p>
<p>Likewise, the entire UI that we included in the product was mocked up to include only the functionality required by the demonstration. You can see an example here—of the login screen—but other screens are linked throughout this article. Likewise, the <em>Bank2Things</em> screen shown above and to the left is a mockup.</p>
<h2>Wrapup</h2><p>So what did Encodo actually contribute?</p>
<ul>
<li>We used the Crealogix UX and VSG to mock up all of the app screens that you seen linked in this article. We did all of the animation and logic and styling.</li>
<li>We built two Google Spreadsheets and hooked them up to everything else</li>
<li>We hooked up the Lifx lamp API into our system</li>
<li>We hacked the Amazon Dash buttons to communicate in our own network instead of beaming home to the mothership</li>
<li>We built a web site to handle any mocking/faking that needed to be done for the demo and through which the devices communicated</li>
<li>We provided a VM (Virtual Machine) on which everything ran (other than the Google Spreadsheets)</li></ul><p>As last year—when we helped Crealogix create the prototype for their <a href="http://finovate.com/videos/finovateeurope-2015-crealogix/">BankClip for Finovate 2015</a>—we had a lot of fun investigating all of these cutting-edge technologies and putting together a custom solution in time for Finovate 2016.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3233_1_body" class="footnote-number">[1]</span> As it turns out, if you watch the <a href="http://finovate.com/videos/finovateeurope-2016-crealogix/">7–minute video of the presentation</a>, nowhere do you actually see a button. Maybe they could see them from the audience.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3222</guid>
    <title><![CDATA[Mini-applications and utilities with Quino]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3222</link>
    <pubDate>Sat, 27 Feb 2016 12:36:39 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">27. Feb 2016 12:36:39 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">27. Feb 2016 12:52:18 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In several articles last year [1], I went into a lot of detail about the configuration and startup for Quino applications. Those posts discuss a lot about what led to the architecture Quino has for loading up an application. </p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3222/folder_utily.png"><img src="https://www.earthli.com/data/news/attachments/entry/3222/folder_utily_tn.png" alt=" " class=" align-right"></a>Some of you might be wondering: what if I want to start up and run an application that doesn&rsquo;t use Quino? Can I build applications that don&rsquo;t use any fancy metadata because they&rsquo;re super-simple and don&rsquo;t even need to store any data? Those are the kind of utility applications I make all the time; do you have anything for me, you continue to wonder?</p>
<p>As you probably suspected from the leading question: You&rsquo;re in luck. Any functionality that doesn&rsquo;t need metadata is available to you without using any of Quino. We call this the &ldquo;Encodo&rdquo; libraries, which are the base on which Quino is built. Thanks to the fundamental changes made in Quino 2, you have a wealth of functionality available in just the granularity you&rsquo;re looking for.</p>
<h2>Why use a Common Library?</h2><p>Instead of writing such small applications from scratch—and we know we could write them—why would we want to leverage existing code? What are the <strong>advantages</strong> of doing this?</p>
<ul>
<li>Writing code that is <em>out of</em> scope takes time away from writing code that is <em>in</em> scope.</li>
<li>Code you never write has no bugs.</li>
<li>It also doesn&rsquo;t require maintenance or documentation.</li>
<li>While library code is not guaranteed to be bug-free, it&rsquo;s probably much better off than the code you <em>just wrote seconds ago</em>.</li>
<li>Using a library increases the likelihood of having robust, reliable and extendible code for out-of-scope application components. </li>
<li>One-off applications tend to be maintainable only by the originator. Applications using a common library can be maintained by anyone familiar with that library.</li>
<li>Without a library, common mistakes must be fixed in all copies, once for each one-off application.</li>
<li>The application can benefit from bug fixes and improvements made to the library.</li>
<li>Good practices and patterns are encouraged/enforced by the library.</li></ul><p>What are potential <strong>disadvantages</strong>?</p>
<ul>
<li>The library might compel a level of complexity that makes it take <em>longer</em> to create the application than writing it from scratch</li>
<li>The library might force you to use components that you don&rsquo;t want.</li>
<li>The library might hamstring you, preventing innovation.</li></ul><p>A developer unfamiliar with a library—or one who is too impatient to read up on it—will feel these disadvantages more acutely and earlier.</p>
<h2>Two Sample Applications</h2><p>Let&rsquo;s take a look at some examples below to see how the Encodo/Quino libraries stack up. Are we able to profit from the advantages without suffering from the disadvantages?</p>
<p>We&rsquo;re going to take a look at two simple applications:</p>
<ol>
<li>An application that loads settings for Windows service-registration. We built this for a customer product.</li>
<li>The <em>Quino Code Generator</em> that we use to generate metadata and ORM classes from the model</li></ol><h2>Windows Service Installer</h2><p>The actual service-registration part is boilerplate generated by Microsoft Visual Studio [2], but we&rsquo;d like to replace the hard-coded strings with customized data obtained from a configuration file. So how do we get that data?</p>
<ul>
<li>The main requirement is that the user should be able to indicate which settings to use when registering the Windows service.</li>
<li>The utility could read them in from the command line, but it would be nicer to read them from a configuration file.</li></ul><p>That doesn&rsquo;t sound that hard, right? I&rsquo;m sure you could just whip something together with an <code>XMLDocument</code> and some hard-coded paths and filenames that would do the trick. [3] It might even work on the first try, too. But do you really want to bother with all of that? Wouldn&rsquo;t you rather just get the scaffolding for free and focus on the part where you load your settings?</p>
<h3>Getting the Settings</h3><p>The following listing shows the main application method, using the Encodo/Quino framework libraries to do the heavy lifting.</p>
<pre class=" "><code>[NotNull]
public static ServiceSettings LoadServiceSettings()
{
  ServiceSettings result = null;
  var transcript = new ApplicationManager().Run(
    CreateServiceConfigurationApplication,
    app =&gt; result = app.GetInstance&lt;ServiceSettings&gt;()
  );

  if (transcript.ExitCode != ExitCodes.Ok)
  {
    throw new InvalidOperationException(
      "Could not read the service settings from the configuration file." + 
      new SimpleMessageFormatter().GetErrorDetails(transcript.Messages)
    );
  }

  return result;
}</code></pre><p>If you&rsquo;ve been following along in the other articles (see first footnote below), then this structure should be very familiar. We use an <code>ApplicationManager()</code> to execute the application logic, creating the application with <code>CreateServiceConfigurationApplication</code> and returning the settings configured by the application in the second parameter (the &ldquo;run&rdquo; action). If anything went wrong, we get the details and throw an exception.</p>
<p>You can&rsquo;t see it, but the library provides debug/file logging (if you enable it), debug/release mode support (exception-handling, etc.) and everything is customizable/replaceable by registering with an IOC.</p>
<h3>Configuring the Settings Loader</h3><p>Soooo…I can see where we&rsquo;re returning the <code>ServiceSettings</code>, but where are they configured? Let&rsquo;s take a look at the second method, the one that creates the application.</p>
<pre class=" "><code>private static IApplication CreateServiceConfigurationApplication()
{
  var application = new Application();
  application
    .UseSimpleInjector()
    .UseStandard()
    .UseConfigurationFile("service-settings.xml")
    .Configure&lt;ServiceSettings&gt;(
      "service", 
      (settings, node) =&gt;
      {
        settings.ServiceName = node.GetValue("name", settings.ServiceName);
        settings.DisplayName = node.GetValue("displayName", settings.DisplayName);
        settings.Description = node.GetValue("description", settings.Description);
        settings.Types = node.GetValue("types", settings.Types);
      }
    ).RegisterSingle&lt;ServiceSettings&gt;();

  return application;
}</code></pre><ol>
<li>First, we create a standard <code>Application</code>, defined in the <code>Encodo.Application</code> assembly. What does this class do? It does very little other than manage the main IOC (see articles linked in the first footnote for details).</li>
<li>The next step is to choose an IOC, which we do by calling <code>UseSimpleInjector()</code>. Quino includes support for the <em>SimpleInjector</em> IOC out of the box. As you can see, you must include this support <em>explicitly</em>, so you&rsquo;re also free to assign your own IOC (e.g. one using Microsoft&rsquo;s Unity). <em>SimpleInjector</em> is very lightweight and super-fast, so there&rsquo;s no downside to using it.</li>
<li>Now we have an application with an IOC that doesn&rsquo;t have any registrations on it. How do we get more functionality? By calling methods like <code>UseStandard()</code>, defined in the <code>Encodo.Application.Standard</code> assembly. Since I know that <code>UseStandard()</code> pulls in what I&rsquo;m likely to need, I&rsquo;ll just use that. [4]</li>
<li>The next line tells the application the name of the configuration file to use. [5]</li>
<li>The very next line is already application-specific code, where we configure the <code>ServiceSettings</code> object that we want to return. For that, there&rsquo;s a <code>Configure</code> method that returns an object from the IOC along with a specific node from the configuration data. This method is called only if everything started up OK.</li>
<li>The final call to <code>RegisterSingle</code> makes sure that the <code>ServiceSettings</code> object created by the IOC is a singleton (it would be silly to configure one instance and return another, unconfigured one).</li></ol><p>Basically, because this application is so simple, it has already accomplished its goal by the time the standard startup completes. At the point that we would &ldquo;run&rdquo; this application, the <code>ServiceSettings</code> object is already configured and ready for use. That&rsquo;s why, in <code>LoadServiceSettings()</code>, we can just get the settings from the application with <code>GetInstance()</code> and exit immediately.</p>
<h2>Code Generator</h2><p>The code generator has a bit more code, but follows the same pattern as the simple application above. In this case, we use the command line rather than the configuration file to get user input.</p>
<h3>Execution</h3><p>The main method defers all functionality to the <code>ApplicationManager</code>, passing along two methods, one to create the application, the other to run it.</p>
<pre class=" "><code>internal static void Main()
{
  new ApplicationManager().Run(CreateApplication, GenerateCode);
}</code></pre><h3>Configuration</h3><p>As before, we first create an <code>Application</code>, then choose the <em>SimpleInjector</em> and some standard configuration and registrations with <code>UseStandard()</code>, <code>UseMetaStandardServices() </code> and <code>UseMetaTools()</code>. [6]</p>
<p>We set the application title to &ldquo;Quino Code Generator&rdquo; and then include objects with <code>UseSingle()</code> that will be configured from the command line and used later in the application. [7] And, finally, we add our own <code>ICommandSet</code> to the command-line processor that will configure the input and output settings. We&rsquo;ll take a look at that part next.</p>
<pre class=" "><code>private static IApplication CreateApplication(
  IApplicationCreationSettings applicationCreationSettings)
{
  var application = new Application();

  return
    application
    .UseSimpleInjector()
    .UseStandard()
    .UseMetaStandardServices()
    .UseMetaTools()
    .UseTitle("Quino Code Generator")
    .UseSingle(new CodeGeneratorInputSettings())
    .UseSingle(new CodeGeneratorOutputSettings())
    .UseUnattendedCommand()
    .UseCommandSet(CreateGenerateCodeCommandSet(application))
    .UseConsole();
}</code></pre><h3>Command-line Processing</h3><p>The final bit of the application configuration is to see how to add items to the command-line processor.</p>
<p>Basically, each command set consists of required values, optional values and zero or more switches that are considered part of a set.</p>
<p>The one for <kbd>i</kbd> simply sets the value of <code>inputSettings.AssemblyFilename</code> to whatever was passed on the command line after that parameter. Note that it pulls the <code>inputSettings</code> from the application to make sure that it sets the values on the same singleton reference as will be used in the rest of the application.</p>
<p>The code below shows only one of the code-generator–specific command-line options. [8]</p>
<pre class=" "><code>private static ICommandSet CreateGenerateCodeCommandSet(
  IApplication application)
{
  var inputSettings = application.GetSingle&lt;CodeGeneratorInputSettings&gt;();
  var outputSettings = application.GetSingle&lt;CodeGeneratorOutputSettings&gt;();

  return new CommandSet("Generate Code")
  {
    Required =
    {
      new OptionCommandDefinition&lt;string&gt;
      {
        ShortName = "i",
        LongName = "in",
        Description = Resources.Program_ParseCommandLineArgumentIn,
        Action = value =&gt; inputSettings.AssemblyFilename = value
      },
      // And others…
    },
  };
}</code></pre><h3>Code-generation</h3><p>Finally, let&rsquo;s take a look at the main program execution for the code generator. It shouldn&rsquo;t surprise you too much to see that the logic consists mostly of getting objects from the IOC and telling them to do stuff with each other. [9]</p>
<p>I&rsquo;ve highlighted the code-generator–specific objects in the code below. All other objects are standard library tools and interfaces.</p>
<pre class=" "><code>private static void GenerateCode(IApplication application)
{
  var logger = application.GetLogger();
  <strong class="highlight">var inputSettings = application.GetInstance&lt;CodeGeneratorInputSettings&gt;();</strong>

  if (!inputSettings.TypeNames.Any())
  {
    logger.Log(Levels.Warning, "No types to generate.");
  }
  else
  {
    var modelLoader = application.GetInstance&lt;IMetaModelLoader&gt;();
    var metaCodeGenerator = application.GetInstance&lt;IMetaCodeGenerator&gt;();
    <strong class="highlight">var outputSettings = application.GetInstance&lt;CodeGeneratorOutputSettings&gt;();</strong>
    var modelAssembly = AssemblyTools.LoadAssembly(
      inputSettings.AssemblyFilename, logger
    );

    outputSettings.AssemblyDetails = modelAssembly.GetDetails();

    foreach (var typeName in inputSettings.TypeNames)
    {
      metaCodeGenerator.GenerateCode(
        modelLoader.LoadModel(modelAssembly, typeName), 
        outputSettings,
        logger
      );
    }
  }
}</code></pre><p>So that&rsquo;s basically it: no matter how simple or complex your application, you configure it by indicating what stuff you want to use, then use all of that stuff once the application has successfully started. The Encodo/Quino framework provides a large amount of standard functionality. It&rsquo;s yours to use as you like and you don&rsquo;t have to worry about building it yourself. Even your tiniest application can benefit from sophisticated error-handling, command-line support, configuration and logging without lifting a finger.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3222_1_body" class="footnote-number">[1]</span> See Encodo’s configuration library for Quino <a href="https://www.earthli.com/news/view_article.php?id=3132">Part 1</a>, <a href="https://www.earthli.com/news/view_article.php?id=3138">Part 2</a> and <a href="https://www.earthli.com/news/view_article.php?id=3137">Part 3</a> as well as API Design: Running and Application <a href="https://www.earthli.com/news/view_article.php?id=3165">Part 1</a> and <a href="https://www.earthli.com/news/view_article.php?id=3166">Part 2</a> and, finally, <a href="https://www.earthli.com/news/view_article.php?id=3175">Starting up an application, in detail</a>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3222_2_body" class="footnote-number">[2]</span> <p>That boilerplate looks like this:</p>
<pre class=" "><code>var fileService = new ServiceInstaller();
fileService.StartType = ServiceStartMode.Automatic;
fileService.DisplayName = "Quino Sandbox";
fileService.Description = "Demonstrates a Quino-based service.";
fileService.ServiceName = "Sandbox.Services";</code></pre><p>See the <code>ServiceInstaller.cs</code> file in the <code>Sandbox.Server</code> project in Quino 2.1.2 and higher for the full listing.</p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3222_3_body" class="footnote-number">[3]</span> <p>The standard implementation of Quino&rsquo;s <em>ITextKeyValueNodeReader</em> supports XML, but it would be trivial to create and register a version that supports JSON (<a href="https://secure.encodo.ch/jira/browse/QNO-4993">QNO-4993</a>) or YAML. The configuration file for the utility looks like this:</p>
<pre class=" "><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;config&gt;
  &lt;service&gt;
    &lt;name&gt;Quino.Services&lt;/name&gt;
    &lt;displayName&gt;Quino Utility&lt;/displayName&gt;
    &lt;description&gt;The application to run all Quino backend services.&lt;/description&gt;
    &lt;types&gt;All&lt;/types&gt;
  &lt;/service&gt;
&lt;/config&gt;</code></pre></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3222_4_body" class="footnote-number">[4]</span> <p>If you look at the implementation of the <code>UseStandard</code> method [10], it pulls in a lot of stuff, like support for BCrypt, enhanced CSV and enum-value parsing and standard configuration for various components (e.g. the file log and command line). It&rsquo;s called &ldquo;Standard&rdquo; because it&rsquo;s the stuff we tend to use in a lot of applications.</p>
<p>But that method is just a composition of over a dozen other methods. If, for whatever reason (perhaps dependencies), you don&rsquo;t want all of that functionality, you can just call the subset of methods that you <em>do</em> want. For example, you could call <code>UseApplication()</code> from the <code>Encodo.Application</code> assembly instead. That method includes only the support for:</p>
<ul>
<li>Processing the command line (<code>ICommandSetManager</code>)</li>
<li>Locating external files (<code>ILocationManager</code>)</li>
<li>Loading configuration data from file (<code>IConfigurationDataLoader</code>)</li>
<li>Debug- and file-based logging (<code>IExternalLoggerFactory</code>)</li>
<li>and interacting with the <code>IApplicationManager</code>.</li></ul><p>If you want to go even lower than that, you can try <code>UseCore()</code>, defined in the <code>Encodo.Core</code> assembly and then pick and choose the individual components yourself. Methods like <code>UseApplication()</code> and <code>UseStandard()</code> are tried and tested defaults, but you&rsquo;re free to configure your application however you want, pulling from the rich trove of features that Quino offers.</p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3222_5_body" class="footnote-number">[5]</span> <p>By default, the application will look for this file next to the executable. You can configure this as well, by getting the location manager with <code>GetLocationManager()</code> and setting values on it.</p>
<p>You&rsquo;ll notice that I didn&rsquo;t use <code>Configure&lt;ILocationManager&gt;()</code> for this particular usage. That&rsquo;s ordinarily the way to go if you want to make changes to a singleton before it is used. However, if you want to change where the application looks for configuration files, then you have to change the location manager <em>before</em> it&rsquo;s used any other configuration takes place. It&rsquo;s a special object that is available before the IOC has been fully configured. To reiterate from other articles (because it&rsquo;s important), the order of operations we&rsquo;re interested in here are:</p>
<ol>
<li>Create application (this is where you call <code>Use*()</code> to build the application)</li>
<li>Get the location manager to figure out the path for <code>LocationNames.Configuration</code></li>
<li>Load the configuration file</li>
<li>Execute all remaining actions, including those scheduled with calls to <code>Configure()</code></li></ol><p>If you want to change the configuration-file location, then you have to get in there before the startup starts running—and that&rsquo;s basically during application construction. Alternatively, you could also call <code>UseConfigurationDataLoader()</code> to register your own object to actually load configuration data and do whatever the heck you like in there, including returning constant data. :-)</p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3222_6_body" class="footnote-number">[6]</span> The metadata-specific analog to <code>UseStandard()</code> is <code>UseMetaStandard()</code>, but we don&rsquo;t call that. Instead, we call <code>UseMetaStandardServices()</code>. Why? The answer is that we want the code generator to be able to use some objects defined in Quino, but the code generator itself isn&rsquo;t a metadata-based application. We want to include the <em>IOC registrations</em> required by metadata-based applications without adding any of the startup or shutdown actions. Many of the standard <code>Use*()</code> methods included in the base libraries have analogs like this. The <code>Use*Services()</code> analogs are also very useful in automated tests, where you want to be able to create objects but don&rsquo;t want to add anything to the startup.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3222_7_body" class="footnote-number">[7]</span> Wait, why didn&rsquo;t we call <code>RegisterSingle()</code>? For almost any object, we could totally do that. But objects used during the first stage of application startup—before the IOC is available—must go in the <em>other</em> IOC, accessed with <code>SetSingle()</code> and <code>GetSingle()</code>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3222_8_body" class="footnote-number">[8]</span> The full listing is in <code>Program.cs</code> in the <code>Quino.CodeGenerator</code> project in any 2.x version of Quino.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3222_9_body" class="footnote-number">[9]</span> Note that, once the application is started, you can use <code>GetInstance()</code> instead of <code>GetSingle()</code> because the IOC is now available and all singletons are mirrored from the startup IOC to the main IOC. In fact, once the application is started, it&rsquo;s <em>recommended</em> to use <code>GetInstance()</code> everywhere, for consistency and to prevent the subtle distinction between IOCs—present only in the first stage of startup—from bleeding into your main program logic.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3222_10_body" class="footnote-number">[10]</span> If you have the Quino source code handy, you can look it up there, but if you have ReSharper installed, you can just <kbd>F12</kbd> on <code>UseStandard()</code> to decompile the method. In the latest <em>DotPeek</em>, the extension methods are even displayed much more nicely in decompiled form.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3207</guid>
    <title><![CDATA[Verity Stob Teaches Functional Programming]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3207</link>
    <pubDate>Sun, 17 Jan 2016 22:27:10 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Jan 2016 22:27:10 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. Jan 2016 07:12:55 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The article <a href="http://www.theregister.co.uk/2016/01/13/stob_remember_the_monoids/">Learn you Func Prog on five minute quick!</a> by <cite>Verity Stob</cite> (<cite><a href="http://www.theregister.co.uk/">The Register</a></cite>) provides a typically twisted and unhelpful overview of the state of functional programming in this 21st-century renaissance—heralded decades ago by Lisp programmers. It includes an honest overview of the major players, including Scala, for which the &ldquo;pro&rdquo; and &ldquo;con&rdquo; are the same (a <span class="quote-inline">&ldquo;[c]lose relationship with Java […]&rdquo;</span>) and ending with JavaScript, for which the &ldquo;pro&rdquo; is <span class="quote-inline">&ldquo;It&rsquo;s what you&rsquo;ll end up using.&rdquo;</span></p>
<p>The discussion continues with rules: variable immutability, function purity, curryability and monadicity, which is where things really go off the rails. Property 7 dribbles to a shuddering halt with,</p>
<blockquote class="quote quote-block "><div><p>&ldquo;All monads define a <code>unit()</code> function called <code>of()</code>, a <code>bind()</code> function called <code>map()</code> and a type constructor function called…</p>
<p>&ldquo;Wait a minute. Wait a minute. Perhaps <code>bind()</code> is a functor not a function. I&rsquo;m pretty sure about that. Hold on to the horses a moment there while I look it up.</p>
<p>&ldquo;…And I should perhaps clarify that this <code>bind()</code> and <code>map()</code> is nothing to do with any other <code>bind()</code> or <code>map()</code> methods or functions that you might be familiar with, although their actions are in some sense quite similar.</p>
<p>&ldquo;<em>Summary:</em> It has been an honour and a pleasure to clear all that up for you.</p>
<p>&ldquo;<em>Final Reader&rsquo;s comment:</em> My gratitude is inexpressible. [1]&rdquo;</p>
</div></blockquote><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3207_1_body" class="footnote-number">[1]</span> I&rsquo;ve been reading Verity Stob since the days when she was published in <em>Dr. Dobbs</em>. Nice to see her still going with the same sense of humour (sic) and insight into the at-times puffed-up and self-important programming world. [2]</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3207_2_body" class="footnote-number">[2]</span> <p>Which is not to say that I don&rsquo;t enjoy immensely the functional aspects of C#. I do. I also have read a lot about monads and am completely familiar with the tragically bad and unenlightening explanations. Stob captures this elegantly with the following corollary to Rule 4:</p>
<blockquote class="quote quote-block "><div>&ldquo;If you should by some accident come to understand what a Monad is, you will simultaneously lose the ability to explain it to anybody else.&rdquo;</div></blockquote></div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3204</guid>
    <title><![CDATA[Profiling: that critical 3% (Part II)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3204</link>
    <pubDate>Sat, 16 Jan 2016 12:53:04 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Jan 2016 12:53:04 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3204/after_optimization.png"><img src="https://www.earthli.com/data/news/attachments/entry/3204/after_optimization_tn.png" alt=" " class=" align-right"></a>In <a href="https://www.earthli.com/news/view_article.php?id=3203">part I</a> of this series, we discussed some core concepts of profiling. In that article, we not only discussed the problem at hand, but also how to think about not only fixing performance problems, but reducing the likelihood that they get out of hand in the first place.</p>
<p>In this second part, we&rsquo;ll go into detail and try to fix the problem.</p>
<p><span class="clear-both"></span></p>
<h2>Reëvaluating the Requirements</h2><p>Since we have new requirements for an existing component, it&rsquo;s time to reconsider the requirements for all stakeholders. In terms of requirements, the <code>IScope</code> can be described as follows:</p>
<ol>
<li>Hold a list of objects in LIFO order</li>
<li>Hold a list of key/value pairs with a unique name as the key</li>
<li>Return the value/reference for a key</li>
<li>Return the most appropriate reference for a given requested type. The most appropriate object is the one that was added with <em>exactly</em> the requested type. If no such object was added, then the first object that conforms to the requested type is returned</li>
<li>These two piles of objects are entirely separate: if an object is added by name, we do not expect it to be returned when a request for an object of a certain type is made</li></ol><p>There is more detail, but that should give you enough information to understand the code examples that follow.</p>
<h2>Usage Patterns</h2><p>There are many ways of implementing the functional requirements listed above. While you can implement the feature with only requirements, it&rsquo;s very helpful to know usage patterns when trying to optimize code. </p>
<p>Therefore, we&rsquo;d like to know <em>exactly</em> what kind of contract our code has to implement—and to not implement any more than was promised.</p>
<p>Sometimes a hopeless optimization task gets a lot easier when you realize that you only have to optimize for a very specific situation. In that case, you can leave the majority of the code alone and optimize a single path through the code to speed up 95% of the calls. All other calls, while perhaps a bit slow, will at least still be yield the correct results.</p>
<p>And &ldquo;optimized&rdquo; doesn&rsquo;t necessarily mean that you have to throw all of your language&rsquo;s higher-level constructs out the window. Once your profiling tool tells you that a particular bit of code has introduced a bottleneck, it often suffices to just examine that particular bit of code more closely. Just picking the low-hanging fruit will usually be more than enough to fix the bottleneck. [1]</p>
<h2>Create scopes faster [2]</h2><p>I saw in the profiler that creating the <code>ExpressionContext</code> had gotten considerably slower. Here&rsquo;s the code in the constructor.</p>
<pre class=" "><code>foreach (var value in values.Where(v =&gt; v != null))
{
  Add(value);
}</code></pre><p>I saw a few potential problems immediately.</p>
<ul>
<li>The call to <code>Add()</code> had gotten more expensive in order to return the most appropriate object from the <code>GetInstances()</code> method</li>
<li>The Linq replaced a call to <code>AddRange()</code></li></ul><p>The faster version is below:</p>
<pre class=" "><code>var scope = CurrentScope;
for (var i = 0; i &lt; values.Length; i++)
{
  var value = values[i];
  if (value != null)
  {
    scope.AddUnnamed(value);
  }
}</code></pre><p>Why is this version faster? The code now uses the fact that we know we&rsquo;re dealing with an indexable list to avoid allocating an enumerator and to use non-allocating means of checking null. While the Linq code is highly optimized, a <code>for</code> loop is always going to be faster <em>because it&rsquo;s guaranteed not to allocate anything</em>. Furthermore, we now call <code>AddUnnamed()</code> to use the faster registration method because the more involved method is never needed for these objects.</p>
<p>The optimized version is less elegant and harder to read, but it&rsquo;s not terrible. Still, you should use these techniques only if you can prove that they&rsquo;re worth it.</p>
<h2>Optimizing <code>CurrentScope</code></h2><p>Another minor improvement is that the call to retrieve the scope is made only once regardless of how many objects are added. On the one hand, we might expect only a minor improvement since we noted above that most use cases only ever add one object anyway. On the other, however, we know that we call the constructor 20 million times in at least one test, so it&rsquo;s worth examining.</p>
<p>The call to <code>CurrentScope</code> gets the last element of the list of scopes. Even something as innocuous as calling the Linq extension method <code>Last()</code> can get more costly than it needs to be when your application calls it millions of times. Of course, Microsoft has decorated its Linq calls with all sorts of compiler hints for inlining and, of course, if you decompile, you can see that the method itself is implemented to check whether the target of the call is a list and use indexing, but it&rsquo;s still slower. There is still an extra stack frame (unless inlined) and there is still a type-check with <code>as</code>.</p>
<p>Replacing a call to <code>Last()</code> with getting the item at the index of the last position in the list is not recommended in the general case. However, making that change in a <em>provably</em> performance-critical area shaved a percent or two off a test run that takes about 45 minutes. That&rsquo;s not nothing.</p>
<pre class=" align-left left" style="width: 40%"><code>protected IScope CurrentScope
{
  get { return _scopes.Last(); }
}</code></pre><pre class=" align-right right" style="width: 40%"><code>protected IScope CurrentScope
{
  get { return <strong class="highlight">_scopes[_scopes.Count − 1]</strong>; }
}</code></pre><p><span class="clear-both"></span>That takes care of the creation &amp; registration side, where I noticed a slowdown when creating the millions of <code>ExpressionContext</code> objects needed by the data driver in our product&rsquo;s test suite.</p>
<h2>Get objects faster</h2><p>Let&rsquo;s now look at the evaluation side, where objects are <em>requested</em> from the context.</p>
<p>The offending, slow code is below:</p>
<pre class=" "><code>public IEnumerable&lt;TService&gt; GetInstances&lt;TService&gt;()
{
  var serviceType = typeof(TService);
  var rawNameMatch = this[serviceType.FullName];

  var memberMatches = All.OfType&lt;TService&gt;();
  var namedMemberMatches = NamedMembers.Select(
    item =&gt; item.Value
  ).OfType&lt;TService&gt;();

  if (rawNameMatch != null)
  {
    var nameMatch = (TService)rawNameMatch;

    return
      nameMatch
      .ToSequence()
      .Union(namedMemberMatches)
      .Union(memberMatches)
      .Distinct(ReferenceEqualityComparer&lt;TService&gt;.Default);
  }

  return namedMemberMatches.Union(memberMatches);
}</code></pre><p>As you can readily see, this code isn&rsquo;t particularly concerned about performance. It is, however, relatively easy to read and to figure out the logic behind returning objects, though. As long as no-one really needs this code to be fast—if it&rsquo;s not used that often and not used in tight loops—it doesn&rsquo;t matter. What matters more is legibility and maintainability.</p>
<p>But we now know that we need to make it faster, so let&rsquo;s focus on the most-likely use cases. I know the following things:</p>
<ul>
<li>Almost all <code>Scope</code> instances are created with a single object in them and no other objects are ever added.</li>
<li>Almost all object-retrievals are made on such single-object scopes</li>
<li>Though the scope should be able to return all matching instances, sorted by the rules laid out in the requirements, all existing calls get the <code>FirstOrDefault()</code> object.</li></ul><p>These extra bits of information will allow me to optimize the already-correct implementation to be much, much faster for the calls that we&rsquo;re likely to make.</p>
<p>The optimized version is below:</p>
<pre class=" "><code>public IEnumerable&lt;TService&gt; GetInstances&lt;TService&gt;()
{
  var members = _members;

  if (members == null)
  {
    yield break;
  }

  if (members.Count == 1)
  {
    if (members[0] is TService)
    {
      yield return (TService)members[0];
    }

    yield break;
  }

  object exactTypeMatch;
  if (TypedMembers.TryGetValue(typeof(TService), out exactTypeMatch))
  {
    yield return (TService)exactTypeMatch;
  }

  foreach (var member in members.OfType&lt;TService&gt;())
  {
    if (!ReferenceEquals(member, exactTypeMatch))
    {
      yield return member;
    }
  }
}</code></pre><p>Given the requirements, the handful of use cases and decent naming, you should be able to follow what&rsquo;s going on above. The code contains many more escape clauses for common and easily handled conditions, handling them in an allocation-free manner wherever possible.</p>
<ol>
<li>Handle empty case</li>
<li>Handle single-element case</li>
<li>Return exact match</li>
<li>Return all other matches [3]</li></ol><p>You&rsquo;ll notice that returning a value added by-name is not a requirement and has been dropped. Improving performance by removing code for unneeded requirements is a perfectly legitimate solution.</p>
<h2>Test Results</h2><p>And, finally, how did we do? I created tests for the following use cases:</p>
<ul>
<li>Create scope with multiple objects</li>
<li>Get all matching objects in an empty scope</li>
<li>Get first object in an empty scope</li>
<li>Get all matching objects in a scope with a single object</li>
<li>Get first object in a scope with a single object</li>
<li>Get all matching objects in a scope with multiple objects</li>
<li>Get first object in a scope with multiple objects</li></ul><p>Here are the numbers from the automated tests.</p>
<p><span style="width: 449px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3204/before.png"><img src="https://www.earthli.com/data/news/attachments/entry/3204/before.png" alt=" " style="width: 449px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3204/before.png">Before optimization</a></span></span></p>
<p><span style="width: 439px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3204/after_optimization.png"><img src="https://www.earthli.com/data/news/attachments/entry/3204/after_optimization.png" alt=" " style="width: 439px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3204/after_optimization.png">After optimization</a></span></span></p>
<ul>
<li>Create scope with multiple objects — <strong>12x</strong> faster</li>
<li>Get all matching objects in an empty scope — almost <strong>2.5x</strong> faster</li>
<li>Get first object in an empty scope — almost <strong>3.5x</strong> faster</li>
<li>Get all matching objects in a scope with a single object — over <strong>3x</strong> faster</li>
<li>Get first object in a scope with a single object — over <strong>3.25x</strong> faster</li>
<li>Get all matching objects in a scope with multiple objects — almost <strong>3x</strong> faster</li>
<li>Get first object in a scope with multiple objects — almost <strong>2.25x</strong> faster</li></ul><p>This looks <em>amazing</em> but remember: while the optimized solution <em>may</em> be faster than the original, all we really know is that we&rsquo;ve just managed to claw our way back from the atrocious performance characteristics introduced by a recent change. We <em>expect</em> to see vast improvements versus a really slow version.</p>
<p>Since I know that these calls showed up as hotspots and were made millions of times in the test, the performance improvement shown by these tests is enough for me to deploy a pre-release of Quino via TeamCity, upgrade my product to that version and run the tests again. Wish me luck! [4]</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3204_1_body" class="footnote-number">[1]</span> Or, most likely, push it to some other piece of code.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3204_2_body" class="footnote-number">[2]</span> The best approach at this point is to create issues for the other performance investigations you could make. For example, I opened an issue called <a href="https://secure.encodo.ch/jira/browse/QNO-5027">Optimize allocations in the data handlers (start with IExpressionContexts)</a>, documented everything I had analyzed and quickly got back to the issue on which I&rsquo;d started.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3204_3_body" class="footnote-number">[3]</span> For those with access to the Quino Git repository, the diffs shown below come from commit a825d5030ce6f65a452e1db85a308e1351288b96.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3204_4_body" class="footnote-number">[4]</span> If you&rsquo;re following along very, very carefully, you&rsquo;ll recall at this point that the requirement stated above is that objects are returned in LIFO order. The faster version of the code returns objects in FIFO order. You can&rsquo;t tell that the original, slow version <em>did</em> guarantee LIFO ordering, but only because the call to get <code>All</code> members contained a hidden call to the Linq call <code>Reverse()</code>, which slowed things down even more! I removed the call to reverse all elements because (A) I don&rsquo;t actually have any tests for the LIFO requirement nor (B) do I have any other code that expects it to happen. I wasn&rsquo;t about to make the code even more complicated and possibly slower just to satisfy a purely theoretical requirement. That&rsquo;s the kind of behavior that got me into this predicament in the first place.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3204_5_body" class="footnote-number">[5]</span> Spoiler alert: it worked. ;-) The fixes cut the testing time from about 01:30 to about 01:10 for all tests on the build server, so we won back the lost 25%.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3203</guid>
    <title><![CDATA[Profiling: that critical 3% (Part I)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3203</link>
    <pubDate>Wed, 13 Jan 2016 07:05:23 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Jan 2016 07:05:23 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>An oft-quoted bit of software-development sagacity is</p>
<div><div class="auto-content-block"><blockquote class="quote quote-block "><div>&ldquo;Premature optimization is the root of all evil.&rdquo;</div></blockquote></div><div class="auto-content-caption">&mdash;<cite>Donald Knuth</cite></div></div><p>As is so often the case with quotes—especially those on the Internet [1]—this one has a slightly different meaning in context. The snippet above invites developers to overlook the word &ldquo;premature&rdquo; and interpret the received wisdom as &ldquo;you don&rsquo;t ever need to optimize.&rdquo;</p>
<p>Instead, Knuth&rsquo;s full quote actually tells you how much of your code is likely to be affected by performance issues that matter (highlighted below).</p>
<div><div class="auto-content-block"><blockquote class="quote quote-block "><div>&ldquo;Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. <strong>Yet we should not pass up our opportunities in that critical 3%.</strong>&rdquo;</div></blockquote></div><div class="auto-content-caption"><a href="https://en.wikiquote.org/wiki/Donald_Knuth">Computer Programming as an Art (1974)</a> by <cite>Donald Knuth</cite> (<cite><a href="http://en.wikiquote.org/">WikiQuote</a></cite>)</div></div><h2>An Optimization Opportunity in Quino [2]</h2><p>In other articles, I&rsquo;d mentioned that we&rsquo;d upgraded several solutions to Quino 2 in order to test that the API was solid enough for a more general release. One of these products is both quite large and has a test suite of almost 1500 tests. The product involves a lot of data-import and manipulation and the tests include several scenarios where Quino is used very intensively to load, process and save data.</p>
<p>These tests used to run in a certain amount of time, but started taking about <strong>25% longer</strong> after the upgrade to Quino 2.</p>
<h2>Measuring Execution Speed</h2><p>Before doing anything else—making educated guesses as to what the problem could be, for example—we measure. At Encodo, we use JetBrains DotTrace to collect performance profiles.<br>
 <br>
There is no hidden secret: the standard procedure is to take a measurement before and after the change and to compare them. However, so much had changed from Quino 1.13 to Quino 2—e.g. namespaces and type names had changed—that while DotTrace was able to show <em>some</em> matches, the comparisons were not as useful as usual.</p>
<p>A comparison between codebases that hadn&rsquo;t changed so much is much easier, but I didn&rsquo;t have that luxury.</p>
<h2>Tracking the Problem</h2><p>Even excluding the less-than-optimal comparison, it was an odd profile. Ordinarily, one or two issues stick out right away, but the slowness seemed to suffuse the entire test run. Since the direct profiling comparison was difficult, I downloaded test-speed measurements as CSV from TeamCity for the product where we noticed the issue.</p>
<p>How much slower, you might ask? The test that I looked at most closely took almost 4 minutes (236,187ms) in the stable version, but took 5:41 in the latest build.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/3203/tc_test_comparison.png" alt=" " style="width: 675px"></p>
<p>This test was definitely one of the largest and longest tests, so it was particularly impacted. Most other tests that imported and manipulated data ranged anywhere from 10% to 30% slower.</p>
<p>When I looked for hot-spots, the profile unsurprisingly showed me that database access took up the most time. The issue was more subtle: while database-access still used the most time, it was using a <em>smaller percentage</em> of the total time. Hot-spot analysis wasn&rsquo;t going to help this time. Sorting by absolute times and using call counts in the tracing profiles yielded better clues.</p>
<p>The tests were slower when saving and also when loading data. But I knew that the ORM code itself had barely changed at all. And, since the product was using Quino so heavily, the stack traces ran quite deep. After a lot of digging, I noticed that creating the <code>ExpressionContext</code> to hold an object while evaluating expressions locally seemed to be taking longer than before. This was my first, real clue.</p>
<p>Once I was on the trail, I found that when evaluating calls (getting objects) that used local evaluation, it was also always slower.</p>
<h2>Don&rsquo;t Get Distracted</h2><p><a href="https://www.earthli.com/data/news/attachments/entry/3203/fix_all_the_things_mage.jpeg"><img src="https://www.earthli.com/data/news/attachments/entry/3203/fix_all_the_things_mage_tn.jpeg" alt=" " class=" align-right"></a>Once you start looking for places where performance is not optimal, you&rsquo;re likely to start seeing them <em>everywhere</em>. However, as noted above, 97% of them are harmless.</p>
<p>To be clear, we&rsquo;re not optimizing because we feel that the framework is <em>too slow</em> but because we&rsquo;ve determined that the framework is now <em>slower than it used to be</em> and we don&rsquo;t know why.</p>
<p>Even after we&rsquo;ve finished restoring the previous performance (or maybe even making it a little better), we might still be able to easily optimize further, based on other information that we gleaned during our investigation.</p>
<p>But we want to make sure that we don&rsquo;t get distracted and start trying to FIX ALL THE THINGS instead of just focusing on one task at a time. While it&rsquo;s somewhat disturbing that we seem to be created 20 million <code>ExpressionContext</code> objects in a 4-minute test, that is also how we&rsquo;ve always done it, and no-one has complained about the speed up until now.</p>
<p>Sure, if we could reduce that number to only 2 million, we might be even faster [3], but the point is that that we used to be faster on the exact same number of calls—so fix that <em>first</em>.</p>
<h2>A Likely Culprit: Scope</h2><p>I found a likely candidate in the <code>Scope</code> class, which implements the <code>IScope</code> interface. This type is used throughout Quino, but the two use-cases that affect performance are:</p>
<ol>
<li>As a base for the <code>ExpressionContext</code>, which holds the named values and objects to be used when evaluating the value of an <code>IExpression</code>. These expressions are used everywhere in the data driver.</li>
<li>As a base for the poor-man&rsquo;s IOC used in Stage 2 of application execution. [4]</li></ol><p>The former usage has existed unchanged for years; its implementation is unlikely to be the cause of the slowdown. The latter usage is new and I recall having made a change to the semantics of which objects are returned by the <code>Scope</code> in order to make it work there as well.</p>
<h2>How could this happen?</h2><p>You may already be thinking: smooth move, moron. You changed the behavior of a class that is used everywhere for a tacked-on use case. That&rsquo;s definitely a valid accusation to make.</p>
<p>In my defense, my instinct is to reuse code wherever possible. If I already have a class that holds a list of objects and gives me back the object that matches a requested type, then I will use that. If I discover that the object that I get back isn&rsquo;t as predictable as I&rsquo;d like, then I improve the predictability of the API until I&rsquo;ve got what I want. If the improvement comes at no extra cost, then it&rsquo;s a win-win situation. However, this time I paid for the extra functionality with degraded performance.</p>
<p>Where I really went wrong was that I&rsquo;d made two assumptions:</p>
<ol>
<li>I <em>assumed</em> that all other usages were <em>also</em> interested in improved predictability.</li>
<li>I <em>assumed</em> that all other usages were not performance-critical. When I wrote the code you&rsquo;ll see below, I distinctly remember thinking: it&rsquo;s not fast, but it&rsquo;ll do and I&rsquo;ll make it faster if it becomes a problem. Little did I know how difficult it would be to find the problem.</li></ol><h2>Preventing future slippage</h2><blockquote class="quote pullquote align-right right" style="width: 240px"><div>Avoid changing a type shared by different systems without considering all stakeholder requirements.</div></blockquote><p>I think a few words on process here are important. Can we improve the development process so that this doesn&rsquo;t happen again? One obvious answer would be to avoid changing a type shared by different systems without considering all stakeholder requirements. That&rsquo;s a pretty tall order, though. Including this in the process will most likely lead to less refactoring and improvement out of fear of breaking something.</p>
<p>We discussed above how completely reasonable assumptions and design decisions led to the performance degradation. So we can&rsquo;t be sure it won&rsquo;t happen again. What we would like, though, is to be <em>notified quickly when there is performance degradation</em>, so that it appears as a test failure.</p>
<blockquote class="quote pullquote align-left left" style="width: 240px"><div>Notify quickly when there is performance degradation</div></blockquote><p>Our requirements are captured by tests. If all of the tests pass, then the requirements are satisfied. Performance is a non-functional requirement. Where we could improve Quino is to include high-level performance tests that would sound the alarm the next time something like this happens. [5]</p>
<p><span class="clear-both"></span>Enough theory: in <a href="https://www.earthli.com/news/view_article.php?id= 3204">part II</a>, we&rsquo;ll describe the problem in detail and take a crack at improving the speed. See you there.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3203_1_body" class="footnote-number">[1]</span> In fairness, the quote is at least properly attributed. It really was Donald Knuth who wrote it.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3203_2_body" class="footnote-number">[2]</span> By &ldquo;opportunity&rdquo;, of course, I mean that I messed something up that made Quino slower in the new version.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3203_3_body" class="footnote-number">[3]</span> See the article <a href="https://www.earthli.com/news/news/view_article.php?id=427">Quino 2: Starting up an application, in detail</a> for more information on this usage.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3203_4_body" class="footnote-number">[4]</span> I&rsquo;m working on this right now, in issue <a href="https://secure.encodo.ch/jira/browse/QNO-5037">Add standard performance tests</a> for release 2.1.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3195</guid>
    <title><![CDATA[Quino v2.1: API-smoothing and performance]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3195</link>
    <pubDate>Fri, 01 Jan 2016 22:52:49 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">1. Jan 2016 22:52:49 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The summary below describes major new features, items of note and breaking changes. The <a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=19704">full list of issues</a> is also available for those with access to the Encodo issue tracker.</p>
<h2>Highlights</h2><p>Quino 2 is finally ready and will go out the door with a 2.1 rather than a 2.0 version number. The reason being that we released 2.0 internally and tested the hell out of it. 2.1 is the result of that testing. It includes a lot of bug fixes as well as API tweaks to make things easier for developers.</p>
<ul>
<li>Made more improvements to the <strong>Startup/Configuration</strong> API for products (<a href="https://secure.encodo.ch/jira/browse/QNO-4860">QNO-4860</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4991">QNO-4991</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4990">QNO-4990</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4911">QNO-4911</a>)</li>
<li>Further refined the independent and properly decoupled <strong>assemblies</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-5001">QNO-5001</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4609">QNO-4609</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-2514">QNO-2514</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4980">QNO-4980</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4974">QNO-4974</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4865">QNO-4865</a>)</li>
<li>Improved support for continuous integration and deployment of Quino packages and symbols via <strong>TeamCity</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-5003">QNO-5003</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3738">QNO-3738</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4998">QNO-4998</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4756">QNO-4756</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4995">QNO-4995</a>)</li>
<li>Improved the <strong>Web</strong> integration with ASP.NET WebAPI and MVC authentication filters (<a href="https://secure.encodo.ch/jira/browse/QNO-4711">QNO-4711</a>)</li>
<li><strong>Addressed</strong> some <strong>performance regressions</strong> from 1.13 and added a suite of performance tests to keep better track of performance targets.</li></ul><p>On top of that, I&rsquo;ve gone through the backlog and found many issues that had either been fixed already, were obsolete or had been inadequately specified. The Quino backlog dropped from 682 to 542 issues.</p>
<ul>
<li><div><strong>18</strong> issues marked as <em>won&rsquo;t fix</em> and <strong>46</strong> issues marked as <em>obsolete</em><ul>
<li>Stop supporting Glimpse, although there is a <code>Quino.Web.Glimpse</code> package to use the support we do have (<a href="https://secure.encodo.ch/jira/browse/QNO-4560">QNO-4560</a>)</li>
<li>Stop supporting <code>HtmlHelpers</code> and other client-side rendering (<a href="https://secure.encodo.ch/jira/browse/QNO-3921">QNO-3921</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3995">QNO-3995</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3804">QNO-3804</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3797">QNO-3797</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3974">QNO-3974</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4001">QNO-4001</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3992">QNO-3992</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3991">QNO-3991</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3973">QNO-3973</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3970">QNO-3970</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3969">QNO-3969</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3918">QNO-3918</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3866">QNO-3866</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3865">QNO-3865</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3857">QNO-3857</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3849">QNO-3849</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3848">QNO-3848</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3842">QNO-3842</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3839">QNO-3839</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3837">QNO-3837</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3836">QNO-3836</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3834">QNO-3834</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3833">QNO-3833</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3831">QNO-3831</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3824">QNO-3824</a> w/sub-tasks, <a href="https://secure.encodo.ch/jira/browse/QNO-3806">QNO-3806</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3805">QNO-3805</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3802">QNO-3802</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-2288">QNO-2288</a>)</li></ul></div><strong>12</strong> issues marked as <em>incomplete</em> (not sufficiently specified)</li>
<li><strong>2</strong> issues marked as <em>cannot reproduce</em></li>
<li><strong>97</strong> issues marked as <em>fixed</em></li></ul><h2>Breaking changes</h2><p>The following changes are marked with <code>Obsolete</code> attributes, so you&rsquo;ll get a hint as to how to fix the problem. Since these are changes from an unreleased version of Quino, they cause a compile error.</p>
<ul>
<li><code>UseMetaSchemaWinformDxFeedback()</code> has been renamed to <code>UseMetaschemaWinformDx()</code></li>
<li><code>UseSchemaMigrationSupport()</code> has been renamed to <code>UseIntegratedSchemaMigration()</code></li>
<li><code>MetaHttpApplicationBase.MetaApplication</code> has been renamed to <code>BaseApplication</code></li>
<li>The <code>IServer.Run()</code> extension method is no longer supported.</li>
<li><code>GetStandardFilters</code>, <code>GetStandardFiltersForFormsAuthentication()</code> and <code>GetStandardFiltersForUnrestrictedAuthentication</code> are no longer supported. Instead, you should register filters in the IOC and use the <code>IWebFilterAttributeFactory.CreateFilters()</code> to get the list of supported filters</li>
<li>The <code>ToolRequirementAttribute</code> is no longer supported or used.</li>
<li><code>AssemblyExtensions.GetLoadableTypesWithInterface()</code> is no longer supported</li>
<li><code>AssemblyTools.GetValidAssembly()</code> has been replaced with <code>AssemblyTools.GetApplicationAssembly()</code>; <code>GetExecutableName()</code> and <code>GetExecutablePath()</code> have removed.</li>
<li>All of the constant expressions on the <code>MetaBuilderBase</code> (e.g. <code>EndOfTimeExpression</code>) are obsolete. Instead, use <code>MetaBuilderBase.ExpressionFactory.Constants.EndOfTime</code> instead.</li>
<li>All of the global values on <code>MetaObjectDescriptionExtensions</code> are obsolete; instead, use the <code>IMetaObjectFormatterSettings</code> from the IOC to change settings on startup.</li>
<li>Similarly, the set of extension methods that included <code>GetShortDescription()</code> has been moved to the  <code>IMetaObjectFormatter</code>. Obtain an instance from the IOC, as usual.</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3194</guid>
    <title><![CDATA[Quino v2.0: Logging, Dependencies, New Assemblies &amp; Nuget]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3194</link>
    <pubDate>Mon, 28 Dec 2015 10:40:24 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">28. Dec 2015 10:40:24 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The summary below describes major new features, items of note and breaking changes. The <a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=19704">full list of issues</a> is also available for those with access to the Encodo issue tracker.</p>
<h2>Highlights</h2><p>In the <a href="https://www.earthli.com/news/view_article.php?id=3128">beta1</a> and <a href="https://www.earthli.com/news/view_article.php?id=3142">beta2</a> release notes, we read about changes to configuration, dependency reduction, the data driver architecture, DDL commands, security and access control in web applications and a new code-generation format.</p>
<p>In 2.0 final—which was actually released internally on November 13th, 2015 (a Friday)—we made the following additional improvements:</p>
<ul>
<li><strong>Moved</strong> the <strong>metadata</strong> table maintained for the schema-migrator to a proper Quino <strong>module</strong>. (<a href="https://secure.encodo.ch/jira/browse/QNO-4741">QNO-4741</a>)</li>
<li><strong>Rebuilt</strong> the <strong>logging</strong> and messaging API and drastically simplified the implementation throughout (<a href="https://secure.encodo.ch/jira/browse/QNO-4688">QNO-4688</a> w/sub-tasks, <a href="https://secure.encodo.ch/jira/browse/QNO-4954">QNO-4954</a>)</li>
<li><strong>Split</strong> Encodo and Quino into dozens of <strong>new</strong>, independent and properly decoupled <strong>assemblies</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-4678">QNO-4678</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4672">QNO-4672</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4670">QNO-4670</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4376">QNO-4376</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4920">QNO-4920</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4926">QNO-4926</a>)</li>
<li>Rebuilt the <strong>configuration</strong> and <strong>application-startup</strong> API (<a href="https://secure.encodo.ch/jira/browse/QNO-4855">QNO-4855</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4051">QNO-4051</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4895">QNO-4895</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4931">QNO-4931</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4930">QNO-4930</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4949">QNO-4949</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4659">QNO-4659</a> w/sub-tasks, <a href="https://secure.encodo.ch/jira/browse/QNO-4950">QNO-4950</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4857">QNO-4857</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4910">QNO-4910</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4934">QNO-4934</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4898">QNO-4898</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4935">QNO-4935</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4937">QNO-4937</a>)</li>
<li>Changed delivery and <strong>deployment</strong> for Quino and all products to <strong>Nuget packages</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-4916">QNO-4916</a>)</li>
<li>Added scripting and support for continuous integration and deployment of Quino packages and symbols via <strong>TeamCity</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-4871">QNO-4871</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4932">QNO-4932</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3437">QNO-3437</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4433">QNO-4433</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4494">QNO-4494</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4871">QNO-4871</a>)</li>
<li>Restructured and refactored the standard testing base-classes and <strong>testing support</strong> for Quino products (<a href="https://secure.encodo.ch/jira/browse/QNO-4963">QNO-4963</a>)</li>
<li>Improved and fixed <strong>code-generation</strong> for both v1 and v2 formats (<a href="https://secure.encodo.ch/jira/browse/QNO-4804">QNO-4804</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4828">QNO-4828</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4897">QNO-4897</a>)</li>
<li>Refactored the <strong>application server</strong> API to improve decoupling and extensibility (<a href="https://secure.encodo.ch/jira/browse/QNO-4927">QNO-4927</a>)</li></ul><p>These notes are being published for completeness and documentation. The first publicly available release of Quino 2.x will be 2.1 or higher (release notes coming soon).</p>
<h2>Breaking changes</h2><p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3194/upgrade_to_quino_2_big_project.png"><img src="https://www.earthli.com/data/news/attachments/entry/3194/upgrade_to_quino_2_big_project_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3194/upgrade_to_quino_2_big_project.png">A big project will have a lot of errors (over 12,000!)</a></span></span>As we&rsquo;ve mentioned before, this release is absolutely merciless in regard to backwards compatibility. Old code is not retained as <code>Obsolete</code>. Instead, a project upgrading to 2.0 will encounter compile errors.</p>
<p>The following notes serve as an incomplete guide that will help you upgrade a Quino-based product.</p>
<p>As I wrote in the release notes for <a href="https://www.earthli.com/news/view_article.php?id=3128">beta1</a> and <a href="https://www.earthli.com/news/view_article.php?id=3142">beta2</a>, if you arm yourself with a bit of time, ReSharper and the release notes (and possibly keep an Encodo employee on speed-dial), the upgrade is not difficult. It consists mainly of letting ReSharper update namespace references for you.</p>
<h3>Global Search/Replace</h3><p>Instead of going through the errors (example shown to the right) one by one, you can take care of a lot of errors with the following search/replace pairs.</p>
<ul>
<li><code>Encodo.Quino.Data.Persistence</code> =&gt; <code>Encodo.Quino.Data</code></li>
<li><code>IMetaApplication</code> =&gt; <code>IApplication</code></li>
<li><code>ICoreApplication</code> =&gt; <code>IApplication</code></li>
<li><code>GetServiceLocator()</code> =&gt; <code>GetServices()</code></li>
<li><code>MetaMethodTools.GetInstance</code> =&gt; <code>DataMetaMethodExtensions.GetInstance</code></li>
<li><code>application.ServiceLocator.GetInstance</code> =&gt; <code>application.GetInstance</code></li>
<li><code>Application.ServiceLocator.GetInstance</code> =&gt; <code>Application.GetInstance</code></li>
<li><code>application.ServiceLocator</code> =&gt; <code>application.GetServices()</code></li>
<li><code>Application.ServiceLocator</code> =&gt; <code>Application.GetServices()</code></li>
<li><code>application.Recorder</code> =&gt; <code>application.GetLogger()</code></li>
<li><code>Application.Recorder</code> =&gt; <code>Application.GetLogger()</code></li>
<li><code>session.GetRecorder()</code> =&gt; <code>session.GetLogger()</code></li>
<li><code>Session.GetRecorder()</code> =&gt; <code>Session.GetLogger()</code></li>
<li><code>Session.Application.Recorder</code> =&gt; <code>Session.GetLogger()</code></li>
<li><code>FileTools.Canonicalize()</code> =&gt; <code>PathTools.Normalize()</code></li>
<li><code>application.Messages</code> =&gt; <code>application.GetMessageList()</code></li>
<li><code>Application.Messages</code> =&gt; <code>Application.GetMessageList()</code></li>
<li><code>ServiceLocator.GetInstance</code> =&gt; <code>Application.GetInstance</code></li>
<li><code>MetaLayoutTools</code> =&gt; <code>LayoutConstants</code></li>
<li><code>GlobalContext.Instance.Application.Configuration.Model</code> =&gt; <code>GlobalContext.Instance.Application.GetModel()</code></li>
<li><code>IMessageRecorder</code> =&gt; <code>ILogger</code></li>
<li><code>GetUseReleaseSettings()</code> =&gt; <code>IsInReleaseMode()</code></li>
<li><code>ReportToolsDX</code> =&gt; <code>ReportDxExtensions</code></li></ul><p>Although you can&rsquo;t just search/replace everything, it gets you a long way.</p>
<h3>Model-Building Fixes</h3><p>These replacement pairs, while not recommended for global search/replace, are a handy guide for how the API has generally changed.</p>
<ul>
<li><code>*Generator<code> =&gt; *</code>Builder</code></li>
<li><code>SetUpForModule<code> =&gt; </code>CreateModule</code></li>
<li><code>Builder.SetElementVisibility(prop, true)<code> =&gt; </code>prop.Show()</code></li>
<li><code>Builder.SetElementVisibility(prop, false)<code> =&gt; </code>prop.Hide()</code></li>
<li><code>Builder.SetElementControlIdentifier(prop, ControlIdentifiers<code> =&gt; </code>prop.SetInputControl(ControlIdentifiers</code></li>
<li><code>Builder.SetPropertyHeightInPixels(prop, 200);<code> =&gt; </code>prop.SetHeightInPixels(200);</code></li></ul><p>Constructing a module has also changed. Instead of using the following syntax,</p>
<pre class=" "><code>var module = Builder.SetUpForModule&lt;AuditModule&gt;(Name, "ApexClearing.Alps.Core", Name, true);</code></pre><p>Replace it with the following direct replacement,</p>
<pre class=" "><code>var module = Builder.CreateModule(Name, "ApexClearing.Alps.Core", Name);</code></pre><p>Or use this replacement, with the recommended style for the v2 format (no more class prefix for generated classes and a standard namespace):</p>
<pre class=" "><code>var module = Builder.CreateModule(Name, typeof(AuditModuleBuilder).GetParentNamespace());</code></pre><h3>Standard Modules (e.g. Reporting, Security, etc.)</h3><p>Because of how the module class-names have changed, the standard module ORM classes all have different names. The formula is that the ORM class-name is no longer prepended its module name.</p>
<ul>
<li><code>ReportsReportDefinition</code> =&gt; <code>ReportDefinition</code></li>
<li><code>SecurityUser</code> =&gt; <code>User</code></li>
<li>And so on…</li></ul><p>Furthermore, all modules have been converted to use the v2 code-generation format, which has the metadata separate from the ORM object. Therefore, instead of referencing metadata using the ORM class-name as the base, you use the module name as the base.</p>
<ul>
<li><code>ReportReportDefinition.Fields.Name</code> =&gt; <code>ReportModule.ReportDefinition.Name.Identifier</code></li>
<li><code>ReportReportDefinition.MetaProperties.Name</code> =&gt; <code>ReportModule.ReportDefinition.Name</code></li>
<li><code>ReportReportDefinition.Metadata</code> =&gt; <code>ReportModule.ReportDefinition.Metadata</code></li>
<li>And so on…</li></ul><p>There&rsquo;s an upcoming article that will show more examples of the improved flexibility and capabilities that come with the v2-metadata.</p>
<h3>Action names</h3><p>The standard action names have moved as well.</p>
<ul>
<li>ActionNames =&gt; ApplicationActionNames</li>
<li>MetaActionNames =&gt; MetaApplicationActionNames</li></ul><p>Any other, more rarely used action names have been moved back to the actions themselves, so for example</p>
<pre class=" "><code>SaveApplicationSettingsAction.ActionName</code></pre><p>If you created any actions of your own, then the API there has changed as well. As previously documented in <a href="https://www.earthli.com/news/view_article.php?id=426">API Design: To Generic or not Generic? (Part II)</a>, instead of overriding the following method,</p>
<pre class=" "><code>protected override int DoExecute(IApplication application, ConfigurationOptions options, int currentResult)
{
  base.DoExecute(application, options, currentResult);
}</code></pre><p>you instead override in the following way,</p>
<pre class=" "><code>public override void Execute()
{
  base.Execute();
}</code></pre><h3>Using NuGet</h3><p>If you&rsquo;re already using Visual Studio 2015, then the NuGet UI is a good choice for managing packages. If you&rsquo;re still on Visual Studio 2013, then the UI there is pretty flaky and we recommend using the console.</p>
<p>The examples below assume that you have configured a source called &ldquo;Local Quino&rdquo; (e.g. a local folder that holds the <code>nupkg</code> files for Quino).</p>
<pre class=" "><code>install-package Quino.Data.PostgreSql.Testing -ProjectName Punchclock.Core.Tests -Source "Local Quino"
install-package Quino.Server -ProjectName Punchclock.Server -Source "Local Quino"
install-package Quino.Console -ProjectName Punchclock.Server -Source "Local Quino"
install-package Quino.Web -ProjectName Punchclock.Web.API -Source "Local Quino"</code></pre><h3>Debugging Support</h3><p>We recommend using Visual Studio 2015 if at all possible. Visual Studio 2013 is also supported, but we have all migrated to 2015 and our knowhow about 2013 and its debugging idiosyncrasies will deteriorate with time.</p>
<p>These are just brief points of interest to get you set up. As with the NuGet support, these instructions are subject to change as we gain more experience with debugging with packages as well.</p>
<ul>
<li>Hook up to a working symbol-source server (e.g. TeamCity)</li>
<li>Get the local sources for your version</li>
<li>If you don&rsquo;t have a source server or it&rsquo;s flaky, then get the PDBs for the Quino version you&rsquo;re using (provided in <code>Quino.zip</code> as part of the package release)</li>
<li>Add the path to the PDBs to your list of symbol sources in the VS debugging options</li>
<li>Tell Visual Studio where the sources are when it asks during debugging</li>
<li>Tell R# how to map from the source folder (c:\BuildAgent\work\9a1bb0adebb73b1f for Quino 2.0.0-1765) to the location of your sources</li></ul><p>Quino packages are no different than any other NuGet packages. We provide both standard packages as well as packages with symbols and sources. Any complications you encounter with them are due to the whole NuGet experience still being a bit in-flux in the .NET world.</p>
<p>An upcoming post will provide more detail and examples.</p>
<h3>Creating Nuget Packages</h3><p>We generally use our continuous integration server to create packages, but you can also create packages locally (it&rsquo;s up to you to make sure the version number makes sense, so be careful). These instructions are approximate and are subject to change. I provide them here to give you an idea of how packages are created. If they don&rsquo;t work, please contact Encodo for help.</p>
<ul>
<li>Open PowerShell</li>
<li>Change to the <code>%QUINO_ROOT%\src</code> directory</li>
<li>Run <code>nant build pack</code> to build Quino and packages</li>
<li>Set up a local NuGet Source name &ldquo;Local Quino&rdquo; to <code>%QUINO_ROOT%\nuget</code> (one-time only)</li>
<li>Change to the directory where your Quino packages are installed for your solution.</li>
<li>Delete all of the Encodo/Quino packages</li>
<li>Execute <code>nant nuget</code> from your project directory to get the latest Quino build from your local folder</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3189</guid>
    <title><![CDATA[Improving NUnit integration with testing harnesses]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3189</link>
    <pubDate>Sun, 06 Dec 2015 11:57:57 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">6. Dec 2015 11:57:57 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3189/abstract_base_class.png"><img src="https://www.earthli.com/data/news/attachments/entry/3189/abstract_base_class_tn.png" alt=" " class=" align-right"></a>These days nobody who&rsquo;s anybody in the software-development world is writing software without tests. Just <em>writing</em> them doesn&rsquo;t help make the software better, though. You also need to be able to <em>execute</em> tests—reliably and quickly and repeatably.</p>
<p>That said, you&rsquo;ll have to get yourself a test runner, which is a different tool from the compiler or the runtime. That is, just because your tests compile (satisfy all of the language rules) and <em>could</em> be executed doesn&rsquo;t mean that you&rsquo;re done writing them yet.</p>
<h2>Testing framework requirements</h2><p>Every testing framework has its own rules for how the test runner selects methods for execution as tests. The standard configuration options are:</p>
<ul>
<li>Which classes should be considered as test fixtures?</li>
<li>Which methods are considered tests?</li>
<li>Where do parameters for these methods come from?</li>
<li>Is there startup/teardown code to execute for the test or fixture?</li></ul><p>Each testing framework will offer different ways of configuring your code so that the test runner can find and execute setup/test/teardown code. To write NUnit tests, you decorate classes, methods and parameters with C# attributes.</p>
<p>The standard scenario is relatively easy to execute—run all methods with a <code>Test</code> attribute in a class with a <code>TestFixture</code> attribute on it.</p>
<h2>Test-runner Requirements</h2><blockquote class="quote pullquote align-right right" style="width: 240px"><div>There are legitimate questions for which even the best specification does not provide answers.</div></blockquote><p>When you consider multiple base classes and generic type arguments, each of which may also have NUnit attributes, things get a bit less clear. In that case, not only do you have to know what NUnit offers as possibilities but also whether the test runner that you&rsquo;re using <em>also understands and implements</em> the NUnit specification in the same way. Not only that, but there are legitimate questions for which even the best specification does not provide answers.</p>
<p>At Encodo, we use Visual Studio 2015 with ReSharper 9.2 and we use the ReSharper test runner. We&rsquo;re still looking into using the built-in VS test runner—the continuous-testing integration in the editor is intriguing [1]—but it&rsquo;s quite weak when compared to the ReSharper one.</p>
<p>So, not only do we have to consider what the NUnit documentation says is possible, but we must also know what how the R# test runner interprets the NUnit attributes and what is supported.</p>
<h2>Getting More Complicated</h2><p>Where is there room for misunderstanding? A few examples,</p>
<ul>
<li>What if there&rsquo;s a <code>TestFixture</code> attribute on an abstract class?</li>
<li>How about a <code>TestFixture</code> attribute on a class with generic parameters?</li>
<li>Ok, how about a non-abstract class with <code>Tests</code> but no <code>TestFixture</code> attribute?</li>
<li>And, finally, a non-abstract class with <code>Tests</code> but no <code>TestFixture</code> attribute, but there are non-abstract descendants that <em>do</em> have a <code>TestFixture</code> attribute?</li></ul><p>In our case, the answer to these questions depends on which version of R# you&rsquo;re using. Even though it feels like you configured everything correctly and it logically <em>should</em> work, the test runner sometimes disagrees. </p>
<ul>
<li>Sometimes it shows your tests as expected, but refuses to run them (Inconclusive FTW!)</li>
<li>Or other times, it obstinately includes generic base classes that cannot be instantiated into the session, then complains that you didn&rsquo;t execute them. When you try to delete them, it brings them right back on the next build. When you try to run them—perhaps not noticing that it&rsquo;s those damned base classes—then it complains that it can&rsquo;t instantiate them. <em>Look of disapproval.</em></li></ul><p>Throw the TeamCity test runner into the mix—which is ostensibly the same as that from R# but still subtly different—and you&rsquo;ll have even more fun.</p>
<h2>Improving Integration with the R# Test Runner</h2><p>At any rate, now that you know the general issue, I&rsquo;d like to share how the ground rules we&rsquo;ve come up with that avoid all of the issues described above. The text below comes from the <a href="https://secure.encodo.ch/jira/browse/QNO-5009">issue</a> I created for the impending release of Quino 2.</p>
<h3>Environment</h3><ul>
<li>Windows 8.1 Enterprise</li>
<li>Visual Studio 2015</li>
<li>ReSharper 9.2</li></ul><h3>Expected behavior</h3><p>Non-leaf-node base classes should never appear as nodes in test runners. A user should be able to run tests in descendants directly from a fixture or test in the base class.</p>
<h3>Observed behavior</h3><p>Non-leaf-node base classes are shown in the R# test runner in both versions 9 and 10. A user must navigate to the descendant to run a test. The user can no longer run all descendants or a single descendant directly from the test.</p>
<h3>Analysis</h3><p>Relatively recently, in order to better test a misbehaving test runner and accurately report issues to JetBrains, I standardized all tests to the same pattern:</p>
<ul>
<li>Do not use abstract anywhere (the base classes don&rsquo;t <em>technically</em> need it)</li>
<li>Use the <code>TestFixture</code> attribute <em>only</em> on leaf nodes</li></ul><p>This worked just fine with ReSharper 8.x but causes strange behavior in both R# 9.x and 10.x. We discovered recently that not only did the test runner act strangely (something that they might fix), but also that the unit-testing integration in the files themselves behaved differently when the base class is abstract (something JetBrains is unlikely to fix).</p>
<p>You can see that R# treats a non-abstract class with tests as a testable entity, even when it doesn&rsquo;t actually have a <code>TestFixture</code> attribute and even expects a generic type parameter in order to instantiate.</p>
<p>Here it&rsquo;s not working well in either the source file or the test runner. In the source file, you can see that it offers to run tests in a category, but not the tests from actual descendants. If you try to run or debug anything from this menu, it shows the fixture with a question-mark icon and marks any tests it manages to display as inconclusive. This is not surprising, since the test fixture may not be abstract, but <em>does</em> require a type parameter in order to be instantiated.</p>
<p><span style="width: 638px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3189/no_abstract_base_class.png"><img src="https://www.earthli.com/data/news/attachments/entry/3189/no_abstract_base_class.png" alt=" " style="width: 638px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3189/no_abstract_base_class.png">Non-abstract base class</a></span></span></p>
<p>Here it looks and acts correctly:</p>
<p><span style="width: 596px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3189/abstract_base_class.png"><img src="https://www.earthli.com/data/news/attachments/entry/3189/abstract_base_class.png" alt=" " style="width: 596px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3189/abstract_base_class.png">A test in an abstract test fixture</a></span></span></p>
<p>I&rsquo;ve reported this issue to JetBrains, but our testing structure either isn&rsquo;t very common or it hasn&rsquo;t made it to their core test cases, because neither 9 nor 10 handles them as well as the 8.x runner did.</p>
<p>Now that we&rsquo;re also using TeamCity a lot more to not only execute tests but also to collect coverage results, we&rsquo;ll capitulate and just change our patterns to whatever makes R#/TeamCity the happiest.</p>
<h3>Solution</h3><ul>
<li>Make all testing base classes that include at least one {{Test}} or {{Category}} attribute {{abstract}}. Base classes that do not have any testing attributes do not need to be made abstract.</li></ul><p>Once more to recap our ground rules for making tests:</p>
<ul>
<li>Include <code>TestFixture</code> only on leafs (classes with no descendants)</li>
<li>You can put <code>Category</code> or <code>Test</code> attributes anywhere in the hierarchy, but need to declare the class as abstract.</li>
<li>Base classes that have no testing attributes do not need to be abstract</li>
<li>If you feel you need to execute tests in both a base class and one of its descendants, then you&rsquo;re probably doing something wrong. Make two descendants of the base class instead.</li></ul><p>When you make the change, you can see the improvement immediately.</p>
<p><span style="width: 657px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3189/after_making_base_class_abstract.png"><img src="https://www.earthli.com/data/news/attachments/entry/3189/after_making_base_class_abstract.png" alt=" " style="width: 657px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3189/after_making_base_class_abstract.png">After making the base class abstract</a></span></span></p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3189_1_body" class="footnote-number">[1]</span> ReSharper 10.0 also offers continuous integration, but our experiments with the EAP builds and the first RTM build left us underwhelmed and we downgraded to 9.2 until JetBrains manages to release a stable 10.x.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3175</guid>
    <title><![CDATA[Quino 2: Starting up an application, in detail]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3175</link>
    <pubDate>Sat, 28 Nov 2015 13:58:45 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">28. Nov 2015 13:58:45 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">10. Nov 2025 10:54:46 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>As part of the final release process for Quino 2, we&rsquo;ve upgraded 5 solutions [1] from Quino 1.13 to the latest API in order to shake out any remaining API inconsistencies or even just inelegant or clumsy calls or constructs. A lot of questions came up during these conversions, so I wrote the following blog to provide detail on the exact workings and execution order of a Quino application.</p>
<p>I&rsquo;ve discussed the design of Quino&rsquo;s configuration before, most recently in <a href="https://www.earthli.com/news/view_article.php?id=3165">API Design: Running an Application (Part I)</a> and <a href="https://www.earthli.com/news/view_article.php?id=3166">API Design: To Generic or not Generic? (Part II)</a> as well as the three-part series that starts with <a href="https://www.earthli.com/news/view_article.php?id=3132">Encodo’s configuration library for Quino: part I</a>.</p>
<h2>Quino Execution Stages</h2><p>The life-cycle of a Quino 2.0 application breaks down into roughly the following stages:</p>
<ol>
<li><strong>Build Application</strong>: Register services with the <abbr title="Inversion Of Control container">IOC</abbr>, add objects needed during configuration and add actions to the startup and shutdown lists</li>
<li><strong>Load User Configuration</strong>: Use non-IOC objects to bootstrap configuration from the command line and configuration files; IOC is initialized and can no longer be modified after action <code>ServicesInitialized</code></li>
<li><strong>Apply Application Configuration</strong>: Apply code-based configuration to IOC objects; ends with the <code>ServicesConfigured</code> action</li>
<li><strong>Execute</strong>: execute the loop, event-handler, etc.</li>
<li><strong>Shut Down</strong>: dispose of the application, shutting down services in the IOC, setting the exit code, etc.</li></ol><h2>Stage 1</h2><p>The first stage is all about putting the application together with calls to <code>Use</code> various services and features. This stage is covered in detail in three parts, starting with <a href="https://www.earthli.com/news/view_article.php?id=3132">Encodo’s configuration library for Quino: part I</a>.</p>
<h2>Stage 2</h2><p>Let&rsquo;s tackle this one last because it requires a bit more explanation.</p>
<h2>Stage 3</h2><p>Technically, an application can add code to this stage by adding an <code>IApplicationAction</code> before the <code>ServicesConfigured</code> action. Use the <code>Configure&lt;TService&gt;()</code> extension method in stage 1 to configure individual services, as shown below.</p>
<pre class=" "><code>application.Configure&lt;IFileLogSettings&gt;(
  s =&gt; s.Behavior = FileLogBehavior.MultipleFiles
);</code></pre><h2>Stage 4</h2><p>The execution stage is application-specific. This stage can be short or long, depending on what your application does.</p>
<p>For desktop applications or single-user utilities, stage 4 is executed in application code, as shown below, in the <code>Run</code> method, which called by the <code>ApplicationManager</code> after the application has started.</p>
<pre class=" "><code>var transcript = new ApplicationManager().Run(CreateApplication, Run);

IApplication CreateApplication() { … }
void Run(IApplication application) { … }</code></pre><p>If your application is a service, like a daemon or a web server or whatever, then you&rsquo;ll want to execute stages 1–3 and then let the framework send requests to your application&rsquo;s running services. When the framework sends the termination signal, execute stage 5 by disposing of the application. Instead of calling <code>Run</code>, you&rsquo;ll call <code>CreateAndStartupUp</code>.</p>
<pre class=" "><code>var application = new ApplicationManager().CreateAndStartUp(CreateApplication);

IApplication CreateApplication() { … }</code></pre><h2>Stage 5</h2><p>Every application has certain tasks to execute during shutdown. For example, an application will want to close down any open connections to external resources, close file (especially log files) and perhaps inform the user of shutdown.</p>
<p>Instead of exposing a specific &ldquo;shutdown&rdquo; method, a Quino 2.0 application can simply be disposed to shut it down. </p>
<p>If you use <code>ApplicationManager.Run()</code> as shown above, then you&rsquo;re already sorted—the application will be disposed and the user will be informed in case of catastrophic failure; otherwise, you can shut down and get the final application transcript from the disposed object.</p>
<pre class=" "><code>application.Dispose();
var transcript = application.GetTranscript();
// Do something with the transcript…</code></pre><h2>Stage 2 Redux</h2><p>We&rsquo;re finally ready to discuss stage 2 in detail.</p>
<p>An IOC has two phases: in the first phase, the application <em>registers</em> services with the IOC; in the second phase, the application <em>uses</em> services from the IOC.</p>
<p>An application should <em>use</em> the IOC as much as possible, so Quino keeps stage 2 as short as possible. Because it can&rsquo;t use the IOC during the registration phase, code that runs in this stage shares objects via a poor-man&rsquo;s IOC built into the <code>IApplication</code> that allows modification and only supports singletons. Luckily, very little end-developer application code will ever need to run in this stage. It&rsquo;s nevertheless interesting to know how it works.</p>
<p>Obviously, any code in this stage that <em>uses</em> the IOC will cause it to switch from phase one to phase two and subsequent attempts to register services will fail. Therefore, while application code in stage 2 has to be careful, you don&rsquo;t have to worry about <em>not</em> knowing you&rsquo;ve screwed up.</p>
<p>Why would we have this stage? Some advocates of using an IOC claim that everything should be configured in code. However, it&rsquo;s not uncommon for applications to want to run very differently based on command-line or other configuration parameters. The Quino startup handles this by placing the following actions in stage 2:</p>
<ul>
<li>Parse and apply command-line</li>
<li>Import and apply external configuration (e.g. from file)</li></ul><p>An application is free to insert more actions before the <code>ServicesInitialized</code> action, but they have to play by the rules outlined above.</p>
<h2>&ldquo;Single&rdquo; objects</h2><p>Code in stage 2 shares objects by calling <code>SetSingle()</code> and <code>GetSingle()</code>. There are only a few objects that fall into this category. </p>
<p>The calls <code>UseCore()</code> and <code>UseApplication()</code> register most of the standard objects used in stage 2. Actually, while they&rsquo;re <em>mostly</em> used during stage 2, some of them are also added to the poor man&rsquo;s IOC in case of catastrophic failure, in which case the IOC cannot be assumed to be available. A good example is the <code>IApplicationCrashReporter</code>.</p>
<h2>Executing Stages</h2><p>Before listing all of the objects, let&rsquo;s take a rough look at how a standard application is started. The following steps outline what we consider to be a good minimum level of support for any application. Of course, the Quino configuration is modular, so you can take as much or as little as you like, but while you can use a naked <code>Application</code>—which has absolutely <em>nothing</em> registered—and you can call <code>UseCore()</code> to have a bit more—it registers a handful of low-level services but no actions—we recommend calling at least <code>UseApplication()</code> to adds most of the functionality outlined below.</p>
<ol>
<li><strong>Create application</strong>: This involves creating the IOC and most of the IOC registration as well as adding most of the application startup actions (stage 1)</li>
<li><strong>Set debug mode</strong>: Get the final value of <code>RunMode</code> from the <code>IRunSettings</code> to determine if the application should catch all exceptions or let them go to the debugger. This involves getting the <code>IRunSettings</code> from the application and getting the final value using the <code>IApplicationManagerPreRunFinalizer</code>. This is commonly an implementation that can allows setting the value of <code>RunMode</code> from the command-line in debug builds. This further depends on the <code>ICommandSetManager</code> (which depends on the <code>IValueTools</code>) and possibly the <code>ICommandLineSettings</code> (to set the <code>CommandLineConfigurationFilename</code> if it was set by the user).</li>
<li><strong>Process command line</strong>: Set the <code>ICommandProcessingResult</code>, possibly setting other values and adding other configuration steps to the list of startup actions (e.g. many command-line options are switches that are handled by calling <code>Configure&lt;TSettings&gt;()</code> where <code>TSettings</code> is the configuration object in the IOC to modify).</li>
<li><strong>Read configuration file</strong>: Load the configuration data into the <code>IConfigurationDataSettings</code>, involving the <code>ILocationManager</code> to find configuration files and the <code>ITextValueNodeReader</code> to read them.</li>
<li>The <code>ILogger</code> is used throughout by various actions to log application behavior</li>
<li>If there is an unhandled error, the <code>IApplicationCrashReporter</code> uses the <code>IFeedback</code> or the <code>ILogger</code> to notify the user and log the error</li>
<li>The <code>IInMemoryLogger</code> is used to include all in-memory messages in the <code>IApplicationTranscript</code></li></ol><p>The next section provides detail to each of the individual objects referenced in the workflow above.</p>
<h2>Available Objects</h2><p>You can get any one of these objects from the <code>IApplication</code> in at least two ways, either by using <code>GetSingle&lt;TService&gt;()</code> (safe in all situations) or <code>GetInstance&lt;TService&gt;()</code> (safe only in stage 3 or later) or there&rsquo;s almost always a method which starts with &ldquo;Use&rdquo; and ends in the service name.</p>
<p>The example below shows how to get the <code>ICommandSetManager</code> [2] if you need it.</p>
<pre class=" "><code>application.GetCommandSetManager();
application.GetSingle&lt;ICommandSetManager&gt;(); // Prefer the one above
application.GetInstance&lt;ICommandSetManager&gt;();</code></pre><p>All three calls return the exact same object, though. The first two from the poor-man&rsquo;s IOC; the last from the real IOC.</p>
<p>Only applications that need access to low-level objects or need to mess around in stage 2 need to know which objects are available where and when. Most applications don&rsquo;t care and will just always use <code>GetInstance()</code>.</p>
<p>The objects in the poor-man&rsquo;s IOC are listed below.</p>
<h3>Core</h3><ul>
<li><code>IValueTools</code>: converts values; used by the command-line parser, mostly to translate enumerate values and flags</li>
<li><code>ILocationManager</code>: an object that manages aliases for file-system locations, like &ldquo;Configuration&rdquo;, from which configuration files should be loaded or &ldquo;UserConfiguration&rdquo; where user-specific overlay configuration files are stored; used by the configuration loader</li>
<li><code>ILogger</code>: a reference to the main logger for the application</li>
<li><code>IInMemoryLogger</code>: a reference to an in-memory message store for the logger (used by the <code>ApplicationManager</code> to retrieve the message log from a crashed application)</li>
<li><code>IMessageFormatter</code>: a reference to the object that formats messages for the logger</li></ul><h3>Command line</h3><ul>
<li><code>ICommandSetManager</code>: sets the schema for a command line; used by the command-line parser</li>
<li><code>ICommandProcessingResult</code>: contains the result of having processed the command line</li>
<li><code>ICommandLineSettings</code>: defines the properties needed to process the command line (e.g. the <code>Arguments</code> and <code>CommandLineConfigurationFilename</code>, which indicates the optional filename to use for configuration in addition to the standard ones)</li></ul><h3>Configuration</h3><ul>
<li><code>IConfigurationDataSettings</code>: defines the <code>ConfigurationData</code> which is the hierarchical representation of all configuration data for the application as well as the <code>MainConfigurationFilename</code> from which this data is read; used by the configuration-loader</li>
<li><code>ITextValueNodeReader</code>: the object that knows how to read <code>ConfigurationData</code> from the file formats supported by the application [3]; used by the configuration-loader</li></ul><h3>Run</h3><ul>
<li><code>IRunSettings</code>: an object that manages the <code>RunMode</code> (&ldquo;release&rdquo; or &ldquo;debug&rdquo;), which can be set from the command line and is used by the <code>ApplicationManager</code> to determine whether to use global exception-handling</li>
<li><code>IApplicationManagerPreRunFinalizer</code>: a reference to an object that applies any options from the command line <em>before</em> the decision of whether to execute in release or debug mode is taken.</li>
<li><code>IApplicationCrashReporter</code>: used by the <code>ApplicationManager</code> in the code <em>surrounding</em> the entire application execution and therefore not guaranteed to have a usable IOC available</li>
<li><code>IApplicationDescription</code>: used together with the <code>ILocationManager</code> to set application-specific aliases to user-configuration folders (e.g. <code>AppData\{CompanyTitle}\{ApplicationTitle}</code>)</li>
<li><code>IApplicationTranscript</code>: an object that records the last result of having run the application; returned by the <code>ApplicationManager</code> after <code>Run()</code> has completed, but also available through the application object returned by <code>CreateAndStartUp()</code> to indicate the state of the application after startup.</li></ul><p>Each of these objects has a very compact interface and has a single responsibility. An application can easily replace any of these objects by calling <code>UseSingle()</code> during stage 1 or 2. This call sets the object in both the poor-man&rsquo;s IOC as well as the real one. For those rare cases where a non-IOC singleton needs to be set after the IOC has been finalized, the application can call <code>SetSingle()</code>, which does not touch the IOC. This feature is currently used only to set the <code>IApplicationTranscript</code>, which needs to happen even after the IOC registration is complete.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3175_1_body" class="footnote-number">[1]</span> <p>Two large customer solutions, two medium-sized internal solutions (Punchclock and JobVortex) as well as the Demo/Sandbox solution. These solutions include the gamut of application types:</p>
<ul>
<li>3 ASP.NET MVC applications</li>
<li>2 ASP.NET WebAPI applications</li>
<li>2 Windows services</li>
<li>3 Winform/DevExpress applications</li>
<li>2 Winform/DevExpress utilities</li>
<li>4 Console applications and utilities</li></ul></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3175_2_body" class="footnote-number">[2]</span> <p>I originally used <code>ITextValueNodeReader</code> as an example, but that&rsquo;s one case where the recommended call doesn&rsquo;t match 1-to-1 with the interface name.</p>
<pre class=" "><code>application.GetSingle&lt;ITextValueNodeReader&gt;();
application.GetInstance&lt;ITextValueNodeReader&gt;();
application.GetConfigurationDataReader(); <strong class="highlight">// Recommended</strong></code></pre></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3175_3_body" class="footnote-number">[3]</span> Currently only XML, but <a href="https://secure.encodo.ch/jira/browse/QNO-4993">JSON</a> is on the way when someone gets a free afternoon.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3173</guid>
    <title><![CDATA[IServer: converting hierarchy to composition]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3173</link>
    <pubDate>Mon, 23 Nov 2015 22:31:29 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">23. Nov 2015 22:31:29 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Quino has long included support for connecting to an application server instead of connecting directly to databases or other sources. The application server uses the same model as the client and provides modeled services (application-specific) as well as CRUD for non-modeled data interactions.</p>
<p>We wrote the first version of the server in 2008. Since then, it&rsquo;s acquired better authentication and authorization capabilities as well as routing and state-handling. We&rsquo;ve always based it on the .NET <code>HttpListener</code>.</p>
<h2>Old and Busted</h2><p>As late as Quino 2.0-beta2 (which we had deployed in production environments already), the server hierarchy looked like screenshot below, pulled from issue <a href="https://secure.encodo.ch/jira/browse/QNO-4927">QNO-4927</a>:</p>
<p><span style="width: 719px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3173/2015-11-10_22_53_56-quino_-_microsoft_visual_studio.png" alt=" " style="width: 719px"></span><span class="auto-content-caption">Server class/interface hierarchy</span></span></p>
<p>This screenshot was captured <em>after</em> a few unneeded interfaces had already been removed. As you can see by the class names, we&rsquo;d struggled heroically to deal with the complexity that arises when you use inheritance rather than composition.</p>
<p>The state-handling was welded onto an authentication-enabled server, and the base machinery for supporting authentication was spread across three hierarchy layers. The hierarchy only hints at composition in its naming: the &ldquo;Stateful&rdquo; part of the class name <code>CoreStatefulHttpServerBase&lt;TState&gt;</code> had already been moved to a state provider and a state creator in previous versions. That support is unchanged in the 2.0 version.</p>
<h2>Implementation Layers</h2><p>We mentioned above that implementation was <span class="quote-inline">&ldquo;spread across three hierarchy layers&rdquo;</span>. There&rsquo;s nothing wrong with that, in principle. In fact, it&rsquo;s a good idea to encapsulate higher-level patterns in a layer that doesn&rsquo;t introduce too many dependencies and to introduce dependencies in other layers. This allows applications not only to be able to use a common implementation without pulling in unwanted dependencies, but also to profit from the common tests that ensure the components works as advertised.</p>
<p>In Quino, the following three layers are present in many components:</p>
<ol>
<li><strong>Abstract</strong>: a basic encapsulation of a pattern with almost no dependencies (generally just <code>Encodo.Core</code>).</li>
<li><strong>Standard</strong>: a functional implementation of the abstract pattern with dependencies on non-metadata assemblies (e.g. <code>Encodo.Application</code>, <code>Encodo.Connections</code> and so on)</li>
<li><strong>Quino</strong>: an enhancement of the standard implementation that makes use of metadata to fill in implementation left abstract in the previous layer. Dependencies can include any of the Quino framework assemblies (e.g. <code>Quino.Meta</code>, <code>Quino.Application</code> and so on).</li></ol><h2>The New Hotness [1]</h2><p>The diagram below shows the new hotness in Quino 2. [2]</p>
<p><span style="width: 863px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3173/server_dependencies_graph.png"><img src="https://www.earthli.com/data/news/attachments/entry/3173/server_dependencies_graph.png" alt=" " style="width: 863px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3173/server_dependencies_graph.png">Quino 2.0 Server Infrastructure</a></span></span></p>
<p>The hierarchy is now extremely <em>flat</em>. There is an <code>IServer</code> interface and a <code>Server</code> implementation, both generic in <code>TListener</code>, of type <code>IServerListener</code>. The server manages a single instance of an <code>IServerListener</code>.</p>
<p>The listener, in turn, has an <code>IHttpServerRequestHandler</code>, the main implementation of which uses an <code>IHttpServerAuthenticator</code>.</p>
<p>As mentioned above, the <code>IServerStateProvider</code> is included in this diagram, but is unchanged from Quino 2.0-beta3, except that it is now used by the request handler rather than directly by the server.</p>
<p>You can see how the abstract layer is enhanced by an HTTP-specific layer (the <code>Encodo.Server.Http</code> namespace) and the metadata-specific layer is nice encapsulated in three classes in the <code>Quino.Server</code> assembly.</p>
<h2>Server Components and Flow</h2><p>This type hierarchy has decoupled the main elements of the workflow of handling requests for a server:</p>
<ul>
<li>The server manages listeners (currently a single listener), created by a listener factory</li>
<li>The listener, in turn, dispatches requests to the request handler</li>
<li>The request handler uses the route handler to figure out where to direct the request</li>
<li>The route handler uses a registry to map requests to response items</li>
<li>The request handler asks the state provider for the state for the given request</li>
<li>The state provider checks its cache for the state (the default support uses persistent states to cache sessions for a limited time); if not found, it creates a new one</li>
<li>Finally, the request handler checks whether the user for the request is authenticated and/or authorized to execute the action and, if so, executes the response items</li></ul><p>It is important to note that this behavior is <em>unchanged</em> from the previous version—it&rsquo;s just that now each step is encapsulated in its own component. The components are small and easily replaced, with clear and concise interfaces.</p>
<p>Note also that the current implementation of the request handler is for HTTP servers only. Should the need arise, however, it would be relatively easy to abstract away the <code>HttpListener</code> dependency and generalize most of the logic in the request handler for any kind of server, regardless of protocol and networking implementation. Only the request handler is affected by the HTTP dependency, though: authentication, state-provision and listener-management can all be re-used as-is.</p>
<p>Also of note is that the only full-fledged implementation is for metadata-based applications. At the bottom of the diagram, you can see the metadata-specific implementations for the route registry, state provider and authenticator. This is reflected in the standard registration in the IOC.</p>
<p>These are the service registrations from <code>Encodo.Server</code>:</p>
<pre class=" "><code>return handler
  .RegisterSingle&lt;IServerSettings, ServerSettings&gt;()
  .RegisterSingle&lt;IServerListenerFactory&lt;HttpServerListener&gt;, HttpServerListenerFactory&gt;()
  .Register&lt;IServer, Server&lt;HttpServerListener&gt;&gt;();</code></pre><p>And these are the service registrations from <code>Quino.Server</code>:</p>
<pre class=" "><code>handler
  .RegisterSingle&lt;IServerRouteRegistry&lt;IMetaServerState&gt;, StandardMetaServerRouteRegistry&gt;()
  .RegisterSingle&lt;IServerStateProvider&lt;IMetaServerState&gt;, MetaPersistentServerStateProvider&gt;()
  .RegisterSingle&lt;IServerStateCreator&lt;IMetaServerState&gt;, MetaServerStateCreator&gt;()
  .RegisterSingle&lt;IHttpServerAuthenticator&lt;IMetaServerState&gt;, MetaHttpServerAuthenticator&gt;()
  .RegisterSingle&lt;IHttpServerRequestHandler, HttpServerRequestHandler&lt;IMetaServerState&gt;&gt;()</code></pre><p>As you can see, the registration is extremely fine-grained and allows very precise customization as well as easy mocking and testing.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3173_1_body" class="footnote-number">[1]</span> Any <em>Men in Black</em> fans out there? Tommy Lee Jones was <span class="quote-inline">&ldquo;old and busted&rdquo;</span> while Will Smith was <span class="quote-inline">&ldquo;the new hotness&rdquo;</span>? No? Just me? All righty then…</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3173_2_body" class="footnote-number">[2]</span> This diagram brought to you by the diagramming and architecture tools in ReSharper 9.2. Just select the files or assemblies you want to diagram in the Solution Explorer and choose the option to show them in a diagram. You can right-click any type or assembly to show dependent or referenced modules or types. For type diagrams , you can easily control which relationships are to be shown (e.g. I hide aggregations to avoid clutter) and how the elements are to be grouped (e.g. I grouped by namespace to include the boxes in my diagram).</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3169</guid>
    <title><![CDATA[Iterating with NDepend to remove cyclic dependencies (Part II)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3169</link>
    <pubDate>Fri, 16 Oct 2015 11:44:35 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Oct 2015 11:44:35 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">7. Dec 2024 23:11:14 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In the previous article, we discussed the task of <a href="https://www.earthli.com/news/view_article.php?id=430">Splitting up assemblies in Quino using NDepend.</a> In this article, I&rsquo;ll discuss both the high-level and low-level workflows I used with NDepend to efficiently clear up these cycles.</p>
<p>Please note that what follows is a description of how I have used the tool—so far—to get my very specific tasks accomplished. If you&rsquo;re looking to solve other problems or want to solve the same problems more efficiently, you should take a look at the <a href="http://www.ndepend.com/docs/getting-started-with-ndepend">official NDepend documentation</a>.</p>
<h2>What were we doing?</h2><p>To recap briefly: we are reducing dependencies among top-level namespaces in two large assemblies, in order to be able to split them up into multiple assemblies. The resulting assemblies will have dependencies on each other, but the idea is to make at least <em>some</em> parts of the Encodo/Quino libraries opt-in.</p>
<h2>The plan of attack</h2><p>On a high-level, I tackled the task in the following loosely defined phases.</p>
<dl><dt class="field">Remove direct, root-level dependencies</dt>
<dd>This is the big first step—to get rid of the little black boxes. I made NDepend show only direct dependencies at first, to reduce clutter. More on specific techniques below.</dd>
<dt class="field">Remove indirect dependencies</dt>
<dd><div class=" "><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_black_hole.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_black_hole_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_black_hole.png">Direct and Indirect references (the Black Hole)</a></span></span>Crank up the magnification to show indirect dependencies as well. This will will help you root out the remaining cycles, which can be trickier if you&rsquo;re not showing enough detail. On the contrary, if you turn on indirect dependencies too soon, you&rsquo;ll be overwhelmed by darkness (see the depressing initial state of the Encodo assembly to the right).</div></dd>
<dt class="field">Examine dependencies between root-level namespaces</dt>
<dd><div class=" "><p>Even once you&rsquo;ve gotten rid of all <em>cycles</em>, you may still have unwanted dependencies that hinder splitting namespaces into the desired constellation of assemblies.</p>
<p>For example, the plan is to split all logging and message-recording into an assembly called <code>Encodo.Logging</code>. However, the <code>IRecorder</code> interface (with a single method, <code>Log()</code>) is used practically <em>everywhere</em>. It quickly becomes necessary to split interfaces and implementation—with many more potential dependencies—into two assemblies for some very central interfaces and support classes. In this specific case, I moved <code>IRecorder</code> to <code>Encodo.Core</code>.</p>
<p>Even after you&rsquo;ve conquered the black hole, you might still have quite a bit of work to do. Never fear, though: NDepend is there to help root out those dependencies as well.</p>
</div></dd>
<dt class="field">Examine cycles in non-root namespaces</dt>
<dd><div class=" "><p>Because we can split off smaller assemblies regardless, these dependencies are less important to clean up for our current purposes. However, once this code is packed into its own assembly, its namespaces become root namespaces of their own and—voila! you have more potentially nasty dependencies to deal with. Granted, the problem is less severe because you&rsquo;re dealing with a logically smaller component.</p>
<p>In Quino, use non-root namespaces more for organization and less for defining components. Still, cycles are cycles and they&rsquo;re worth examining and at least plucking the low-hanging fruit.</p>
</div></dd>
</dl><h2>Removing root-level namespace cycles</h2><p>With the high-level plan described above in hand, I repeated the following steps for the many dependencies I had to untangle. Don&rsquo;t despair if it looks like your library has a ton of unwanted dependencies. If you&rsquo;re smart about the ones you untangle first, you can make excellent—and, most importantly, <em>rewarding</em>—progress relatively quickly. [1]</p>
<ol>
<li>Show the dependency matrix</li>
<li>Choose the same assembly in the row and column</li>
<li>Choose a square that&rsquo;s black</li>
<li>Click the name of the namespace in the column to show sub-namespaces</li>
<li>Do the same in a row</li>
<li>Keep zooming until you can see where there are dependencies that you don&rsquo;t want</li>
<li>Refactor/compile/run NDepend analysis to show changes</li>
<li><code>GOTO 1</code></li></ol><h2>Once again, with pictures!</h2><p>The high-level plan of attack sounded interesting, but might have left you cold with its abstraction. Then there was the promise of detail with a focus on root-level namespaces, but alas, you might still be left wondering just how <em>exactly</em> do you reduce these much-hated cycles?</p>
<p>I took some screenshots as I worked on Quino, to document my process and point out parts of NDepend I thought were eminently helpful.</p>
<h2>Show only namespaces</h2><p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/show_namespaces_involved_in_dependency.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/show_namespaces_involved_in_dependency_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/show_namespaces_involved_in_dependency.png">Show Namespaces involved in a Dependency</a></span></span><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_cycles_namespace_reference_only.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_cycles_namespace_reference_only_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_cycles_namespace_reference_only.png">Reference cycles in Encodo (Namespaces only)</a></span></span>I mentioned above that you should <span class="quote-inline">&ldquo;[k]eep zooming in&rdquo;</span>, but how do you do that? A good first step is to zoom all the way out and show only direct <em>namespace</em> dependencies. This focuses only on <code>using</code> references instead of the much-more frequent member accesses. In addition, I changed the default setting to show dependencies in only one direction—when a column references a row (blue), but not vice versa (green).</p>
<p>As you can see, the diagrams are considerably less busy than the one shown above. Here, we can see a few black spots that indicate cycles, but it&rsquo;s not so many as to be overwhelming. [2] You can hover over the offending squares to show more detail in a popup.</p>
<p><span class="clear-both"></span></p>
<h2>Show members</h2><p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_cycles.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_cycles_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_cycles.png">Reference cycles in Encodo (Members)</a></span></span><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/bind_matrix_headers_to_cluster_cycles.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/bind_matrix_headers_to_cluster_cycles_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/bind_matrix_headers_to_cluster_cycles.png">Bind Matrix to Cluster Cycles Together</a></span></span>If you don&rsquo;t see any more cycles between namespaces, switch the detail level to &ldquo;Members&rdquo;. Another very useful feature is to &ldquo;Bind Matrix&rdquo;, which forces the columns and rows to be shown in the same order and concentrates the cycles in a smaller area of the matrix.</p>
<p>As you can see in the diagram, NDepend then highlights the offending area and you can even click the upper-left corner to focus the matrix only on that particular cycle.</p>
<p><span class="clear-both"></span></p>
<h2>Drill down to classes</h2><p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/show_classes_involved_in_dependency.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/show_classes_involved_in_dependency_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/show_classes_involved_in_dependency.png">Show Classes involved in a Dependency</a></span></span><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/dependency_arrows.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/dependency_arrows_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/dependency_arrows.png">Use the handy arrow dependency-indicators</a></span></span>Once you&rsquo;re looking at members, it isn&rsquo;t enough to know just the namespaces involved—you need to know which types are referencing which types. The powerful matrix view lets you drill down through namespaces to show classes as well.</p>
<p>If your classes are large—another no-no, but one thing at a time—then you can drill down to show which <em>method</em> is calling which method to create the cycle. In the screenshot to the right, you can see where I had to do just that in order to finally figure out what was going on.</p>
<p>In that screenshot, you can also see something that I only discovered after using the tool for a while: the direction of usage is indicated with an arrow. You can turn off the tooltips—which are informative, but can be distracting for this task—and you don&rsquo;t have to remember which color (blue or green) corresponds to which direction of usage.</p>
<h2>Indirect dependencies</h2><p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_black_hole_smaller.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_black_hole_smaller_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_black_hole_smaller.png">The black hole is almost gone</a></span></span><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_members_only_smaller.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_members_only_smaller_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_namespace_members_only_smaller.png">No more black squares and a 5-element cycle left</a></span></span>Once you&rsquo;ve drilled your way down from namespaces-only to showing member dependencies, to focusing on classes, and even members, your diagram should be shaping up quite well.</p>
<p>On the right, you&rsquo;ll see a diagram of all direct dependencies for the remaining area with a problem. You don&rsquo;t see any black boxes, which means that all <em>direct</em> dependencies are gone. So we have to turn up the power of our microscope further to show indirect dependencies.</p>
<p>On the left, you can see that the scary, scary black hole from the start of our journey has been whittled down to a small, black spot. And that&rsquo;s with all direct and indirect dependencies as well as both directions of usage turned on (i.e. the green boxes are back). This picture is much more pleasing, no?</p>
<h2>Queries and graphs</h2><p><span style="width: 59px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/ndepend_query_language.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/ndepend_query_language_tn.png" alt=" " style="width: 59px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/ndepend_query_language.png">NDepend Query Language</a></span></span><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/view_graph_to_see_cycle.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/view_graph_to_see_cycle_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/view_graph_to_see_cycle.png">View graph to see cycle from Culture to Enums (through Expression)</a></span></span><span style="width: 200px; display: table" class=" align-right clear-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/zoom_on_culture_and_enums_and_indirect.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/zoom_on_culture_and_enums_and_indirect_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/zoom_on_culture_and_enums_and_indirect.png">Show indirect (zoom) in on enums &amp; culture</a></span></span>For the last cluster of indirect dependencies shown above, I had to unpack another feature: NDepend queries: you can select any element and run a query to show using/used by assemblies/namespaces. [3] The results are shown in a panel, where you can edit the query to see live updates immediately.</p>
<p>Even with a highly zoomed-in view on the cycle, I still couldn&rsquo;t see the problem, so I took NDepend&rsquo;s suggestion and generated a graph of the final indirect dependency between <code>Culture</code> and <code>Enums</code> (through <code>Expression</code>). At this zoom level, the graph becomes more useful (for me) and illuminates problems that remain muddy in the matrix (see right).</p>
<p><span class="clear-both"></span></p>
<h2>Crossing the finish line</h2><p>In order to finish the job efficiently, here are a handful of miscellaneous tips that are useful, but didn&rsquo;t fit into the guide above.</p>
<p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_assembly_is_finally_clean.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/encodo_assembly_is_finally_clean_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/encodo_assembly_is_finally_clean.png">Encodo assembly is finally clean</a></span></span></p>
<ul>
<li>I set NDepend to automatically re-run an analysis on a successful build. The matrix updates automatically to reflect changes from the last analysis and won&rsquo;t lose your place. </li>
<li>If you have ReSharper, you&rsquo;ll generally be able to tell whether you&rsquo;ve fixed the dependencies because the usings will be grayed out in the offending file. You can make several fixes at once before rebuilding and rerunning the analysis.</li>
<li>At higher zoom levels (e.g. having drilled down to methods), it is useful to toggle display of row dependencies back on because the dependency issue is only clear when you see the one green box in a sea of blue.</li>
<li>Though Matrix Binding is useful for localizing, remember to toggle it off when you want to drill down in the row independently of the namespace selected in the column.</li></ul><p>And BOOM! just like that [4], phase 1 (root namespaces) for Encodo was complete! Now, on to Quino.dll…</p>
<h2>Conclusion</h2><p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3169/refactoring_82087_symbols.png"><img src="https://www.earthli.com/data/news/attachments/entry/3169/refactoring_82087_symbols_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3169/refactoring_82087_symbols.png">Refactoring 82,087 Symbols…</a></span></span>Depending on what shape your library is in, <em>do not</em> underestimate the work involved. Even with NDepend riding shotgun and barking out the course like a rally navigator, you still have to actually make the changes. That means lots of refactoring, lots of building, lots of analysis, lots of running tests and lots of reviews of at-times quite-sweeping changes to your code base. The destination is worth the journey, but do not embark on it lightly—and don&rsquo;t forget to bring the right tools. [5]</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3169_1_body" class="footnote-number">[1]</span> This can be a bit distracting: you might get struck trying to figure out which of all these offenders to fix <em>first</em>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3169_2_body" class="footnote-number">[2]</span> I&rsquo;m also happy to report that my initial forays into <em>maintaining</em> a relatively clean library—as opposed to <em>cleaning</em> it—with NDepend have been quite efficient.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3169_3_body" class="footnote-number">[3]</span> And much more: I don&rsquo;t think I&rsquo;ve even scratched the surface of the analysis and reporting capabilities offered by this ability to directly query the dependency data.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3169_4_body" class="footnote-number">[4]</span> I&rsquo;m just kidding. It was a lot of time-consuming work.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3169_5_body" class="footnote-number">[5]</span> In this case, in case it&rsquo;s not clear: NDepend for analysis and good ol&rsquo; ReSharper for refactoring. And ReSharper&rsquo;s new(ish) architecture view is also quite good, though not even <em>close</em> to detailed enough to replace NDepend: it shows assembly-level dependencies only.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3167</guid>
    <title><![CDATA[Splitting up assemblies in Quino using NDepend (Part I)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3167</link>
    <pubDate>Sun, 04 Oct 2015 07:44:39 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Oct 2015 07:44:39 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3167/quino_logo_no_text-small.png"><img src="https://www.earthli.com/data/news/attachments/entry/3167/quino_logo_no_text-small.png" alt=" " class=" align-left" style="width: 150px"></a>A lot of work has been put into Quino 2.0 [1], with almost no stone left unturned. Almost every subsystem has been refactored and simplified, including but not limited to the data driver, the schema migration, generated code and metadata, model-building, security and authentication, service-application support and, of course, configuration and execution.</p>
<p>Two of the finishing touches before releasing 2.0 are to <strong>reorganize</strong> all of the code into a more coherent <strong>namespace</strong> structure and to <strong>reduce the size</strong> of the two monolithic <strong>assemblies</strong>: Encodo and Quino.</p>
<p><span class="clear-both"></span></p>
<h2>A Step Back</h2><p>The first thing to establish is: why are we doing this? Why do we want to reduce dependencies and reduce the size of our assemblies? There are several reasons, but a major reason is to improve the <strong>discoverability</strong> of patterns and types in Quino. Two giant assemblies are not inviting—they are, in fact, daunting. Replace these assemblies with dozens of smaller ones and users of your framework will be more likely to (A) find what they&rsquo;re looking for on their own and (B) build their own extensions with the correct dependencies and patterns. Neither of these is guaranteed, but smaller modules are a great start.</p>
<p>Another big reason is <strong>portability</strong>. The .NET Core was released as open-source software some time ago and more and more .NET source code is added to it each day. There are portable targets, non-Windows targets, Universal-build targets and much more. It makes sense to split code up into highly portable units with as few dependencies as possible. That is, the dependencies should be explicit and intended.</p>
<p>Not only that, but NuGet <strong>packaging</strong> has come to the fore more than ever. Quino was originally designed to keep third-party boundaries clear, but we wanted to make it as easy as possible to use Quino. Just include Encodo and Quino and off you went. However, with NuGet, you can now say you want to use Quino.Standard and you&rsquo;ll get Quino.Core, Encodo.Core, Encodo.Services.SimpleInjector, Quino.Services.SimpleInjector and other packages.</p>
<p>With so much interesting code in the Quino framework, we want to make it available as much as possible not only for our internal projects but also for customer projects where appropriate and, also, possibly for open-source distribution.</p>
<h2>NDepend</h2><p>I&rsquo;ve used NDepend before [2] to clean up dependencies. However, the last analysis I did about a year ago showed quite deep problems [3] that needed to be addressed before any further dependency analysis could bear fruit at all. With that work finally out of the way, I&rsquo;m ready to re-engage with NDepend and see where we stand with Quino.</p>
<p>As luck would have it, NDepend is in version 6, released at the start of summer 2015. As was the case last year, NDepend has generously provided me with an upgrade license to allow me to test and evaluate the new version with a sizable and real-world project.</p>
<p>Here is some of the <a href="https://twitter.com/ndepend/status/648538044287488000">feedback I sent to NDepend</a> (<cite><a href="http://twitter.com/">Twitter</a></cite>):</p>
<blockquote class="quote quote-block "><div><p>I really, really like the depth of insight NDepend gives me into my code. I find myself thinking &ldquo;SOLID&rdquo; much more often when I have NDepend shaking its head sadly at me, tsk-tsking at all of the dependency snarls I&rsquo;ve managed to build.</p>
<ul>
<li>It&rsquo;s fast and super-reliable. I can work these checks into my workflow relatively easily.</li>
<li>I&rsquo;m using the matrix view a lot more than the graphs because even NDepend recommends I don&rsquo;t use a graph for the number of namespaces/classes I&rsquo;m usually looking at</li>
<li>Where the graph view is super-useful is for examining *indirect* dependencies, which are harder to decipher with the graph</li>
<li>I&rsquo;ve found so many silly mistakes/lazy decisions that would lead to confusion for developers new to my framework</li>
<li>I&rsquo;m spending so much time with it and documenting my experiences because I want more people at my company to use it</li>
<li>I haven&rsquo;t even scratched the surface of the warnings/errors but want to get to that, as well (the Dashboard tells me of 71 rules violated; 9 critical; I&rsquo;m afraid to look :-)</li></ul></div></blockquote><h2>Use Cases</h2><p>Before I get more in-depth with NDepend, please note that there at least two main use cases for this tool [4]:</p>
<ol>
<li>Clean up a project or solution that has never had a professional dependency checkup</li>
<li>Analyze and maintain separation and architectural layers in a project or solution</li></ol><p>These two use cases are vastly different. The first is like cleaning a gas-station bathroom for the first time in years; the second is more like the weekly once-over you give your bathroom at home. The tools you&rsquo;ll need for the two jobs are similar, but quite different in scope and power. The same goes for NDepend: how you&rsquo;ll use it to claw your way back to architectural purity is different than how you&rsquo;ll use it to occasionally clean up an already mostly-clean project.</p>
<p>Quino is much better than it was the last time we peeked under the covers with NDepend, but we&rsquo;re still going to need a bucket of industrial cleaner before we&rsquo;re done. [5]</p>
<p>The first step is to make sure that you&rsquo;re analyzing the correct assemblies. Show the project properties to see which assemblies are included. You should remove all assemblies from consideration that don&rsquo;t currently interest you (especially if your library is not quite up to snuff, dependency-wise; afterwards, you can leave as many clean assemblies in the list as you like). [6]</p>
<h2>Industrial-strength cleaner for Quino</h2><p>Running an analysis with NDepend 6 generates a nice report, which includes the following initial dependency graph for the assemblies.</p>
<p><span style="width: 503px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3167/componentdependenciesdiagram.png"><img src="https://www.earthli.com/data/news/attachments/entry/3167/componentdependenciesdiagram.png" alt=" " style="width: 503px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3167/componentdependenciesdiagram.png">Assembly dependencies for Encodo and Quino</a></span></span></p>
<p>As you can see, Encodo and Quino depend only on system assemblies, but there are components that pull in other references where they might not be needed. The initial dependency matrices for Encodo and Quino both look much better than they did when I last generated one. The images below show what we have to work with in the Encodo and Quino assemblies.</p>
<p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3167/initial_dependency_matrix_for_encodo.png"><img src="https://www.earthli.com/data/news/attachments/entry/3167/initial_dependency_matrix_for_encodo_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3167/initial_dependency_matrix_for_encodo.png">Initial Dependency Matrix for Encodo</a></span></span><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3167/initial_dependency_matrix_for_quino.png"><img src="https://www.earthli.com/data/news/attachments/entry/3167/initial_dependency_matrix_for_quino_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3167/initial_dependency_matrix_for_quino.png">Initial Dependency Matrix for Quino</a></span></span></p>
<p><span class="clear-both"></span>It&rsquo;s not as terrible as I&rsquo;ve made out, right? There is far less namespace-nesting, so it&rsquo;s much easier to see where the bidirectional dependencies are. There are only a handful of cyclic dependencies in each library, with Encodo edging out Quino because of (A) the nature of the code and (B) I&rsquo;d put more effort into Encodo so far. </p>
<p>I&rsquo;m not particularly surprised to see that this is relatively clean because we&rsquo;ve put effort into keeping the <em>external</em> dependencies low. It&rsquo;s the internal dependencies in Encodo and Quino that we want to reduce.</p>
<h2>Small and Focused Assemblies</h2><p><span style="width: 359px; display: table" class=" align-right clear-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3167/architecture_graph_for_quino-beta3.png"><img src="https://www.earthli.com/data/news/attachments/entry/3167/architecture_graph_for_quino-beta3.png" alt=" " style="width: 359px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3167/architecture_graph_for_quino-beta3.png">(Partial) Architecture Graph for Quino 2.0-beta3</a></span></span><span style="width: 314px; display: table" class=" align-right clear-right"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3167/encodo_assemblies_2_0.png" alt=" " style="width: 314px"></span><span class="auto-content-caption">Encodo assemblies for Quino 2.0-beta3</span></span><span style="width: 313px; display: table" class=" align-right clear-right"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3167/quino_assemblies_2_0.png" alt=" " style="width: 313px"></span><span class="auto-content-caption">Quino assemblies for Quino 2.0-beta3</span></span>The goal, as stated in the title of this article, is to split Encodo and Quino into separate assemblies. While removing cyclic dependencies is <em>required</em> for such an operation, it&rsquo;s not <em>sufficient</em>. Even without cycles, it&rsquo;s still possible that a given assembly is still <em>too dependent</em> on other assemblies.</p>
<p>Before going any farther, I&rsquo;m going to list the assemblies we&rsquo;d like to have. By &ldquo;like to have&rdquo;, I mean the list that we&rsquo;d originally planned plus a few more that we added while doing the actual splitting. [7] The images on the right show the assemblies in Encodo, Quino and a partial overview of the dependency graph (calculated with the ReSharper Architecture overview rather than with NDepend, just for variety).</p>
<p>Of these, the following assemblies and their dependencies are of particular interest [8]:</p>
<ul>
<li><strong>Encodo.Core</strong>: System dependencies only</li>
<li><strong>Encodo.Application</strong>: basic application support [9]</li>
<li><strong>Encodo.Application.Standard</strong>: configuration methods for non-metadata applications that don&rsquo;t want to pick and choose packages/assemblies</li>
<li><strong>Encodo.Expressions</strong>: depends only on <code>Encodo.Core</code></li>
<li><strong>Quino.Meta</strong>: depends only on <code>Encodo.Core</code> and <code>Encodo.Expressions</code></li>
<li><strong>Quino.Meta.Standard</strong>: Optional, but useful metadata extensions</li>
<li><strong>Quino.Application</strong>: depends only on <code>Encodo.Application</code> and <code>Quino.Meta</code></li>
<li><strong>Quino.Application.Standard</strong>: configuration methods for metadata applications that don&rsquo;t want to pick and choose packages/assemblies</li>
<li><strong>Quino.Data</strong>: depends on <code>Quino.Application</code> and some Encodo.* assemblies</li>
<li><strong>Quino.Schema</strong>: depends on <code>Quino.Data</code></li></ul><p>This seems like a good spot to stop, before getting into the nitty-gritty detail of how we used NDepend in practice. In the next article, I&rsquo;ll discuss both the high-level and low-level workflows I used with NDepend to efficiently clear up these cycles. Stay tuned!</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3167_1_body" class="footnote-number">[1]</span> <p>Release notes for 2.0 betas:</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=411">v2.0-beta1: Configuration, services and web</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=415">v2.0-beta2: Code generation, IOC and configuration</a></li></ul><p>Articles about design:</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=412">Encodo’s configuration library for Quino: part I</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=413">Encodo’s configuration library for Quino: part II</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=414">Encodo’s configuration library for Quino: part III</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=422">API Design: Running an Application (Part I)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=426">API Design: To Generic or not Generic? (Part II)</a></li></ul></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3167_2_body" class="footnote-number">[2]</span> <p>I published a two-parter in August and November of 2014.</p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=390">The Road to Quino 2.0: Maintaining architecture with NDepend (part I)</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=400">The Road to Quino 2.0: Maintaining architecture with NDepend (part II)</a></li></ul></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3167_3_body" class="footnote-number">[3]</span> You can see a lot of the issues associated with these changes in the release notes for <a href="https://www.earthli.com/news/view_article.php?id=411">Quino 2.0-beta1</a> (mostly the first point in the &ldquo;Highlights&rdquo; section) and <a href="https://www.earthli.com/news/view_article.php?id=415">Quino 2.0-beta2</a> (pretty much all of the points in the &ldquo;Highlights&rdquo; section).</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3167_4_body" class="footnote-number">[4]</span> I&rsquo;m sure there are more, but those are the ones I can think of that would apply to my project (for now).</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3167_5_body" class="footnote-number">[5]</span> …to stretch the gas-station metaphor even further.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3167_6_body" class="footnote-number">[6]</span> <p>Here I&rsquo;m going to give you a tip that confused me for a while, but that I think was due to particularly bad luck and is actually quite a rare occurrence.</p>
<div class="caution "><p>If you already see the correct assemblies in the list, you should still check that NDepend picked up the right paths. That is, if you haven&rsquo;t followed the advice in NDepend&rsquo;s white paper and still have a different <code>bin</code> folder for each assembly, you may see something like the following in the tooltip when you hover over the assembly name: </p>
<blockquote class="quote quote-block "><div>&ldquo;Several valid .NET assemblies with the name {Encodo} have been found. They all have the same version. the one with the biggest file has been chosen.&rdquo;</div></blockquote><p>If NDepend has accidentally found an older copy of your assembly, you must delete that assembly. Even if you add an assembly directly, NDepend will <em>not</em> honor the path from which you added it. This isn&rsquo;t as bad as it sounds, since it&rsquo;s a very strange constellation of circumstances that led to this assembly hanging around anyway:</p>
<ul>
<li>The project is no longer included in the latest Quino but lingers in my workspace</li>
<li>The version number is unfortunately the same, even though the assembly is wildly out of date</li></ul><p>I only noticed because I <em>knew</em> I didn&rsquo;t have that many dependency cycles left in the Encodo assembly.</p>
</div></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3167_7_body" class="footnote-number">[7]</span> Especially for larger libraries like Quino, you&rsquo;ll find that your expectations about dependencies between modules will be largely correct, but will still have gossamer filaments connecting them that prevent a clean split. In those cases, we just created new assemblies to hold these common dependencies. Once an initial split is complete, we&rsquo;ll iterate and refactor to reduce some of these ad-hoc assemblies.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3167_8_body" class="footnote-number">[8]</span> Screenshots, names and dependencies are based on a pre-release version of Quino, so while the likelihood is small, everything is subject to change.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3167_9_body" class="footnote-number">[9]</span> Stay tuned for an upcoming post on the details of starting up an application, which is the support provided in <code>Encodo.Application</code>.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3166</guid>
    <title><![CDATA[API Design: To Generic or not Generic? (Part II)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3166</link>
    <pubDate>Sat, 26 Sep 2015 11:27:08 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">26. Sep 2015 11:27:08 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Jan 2017 23:18:41 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3166/cupt.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/3166/cupt_tn.jpg" alt=" " class=" align-right"></a>In this article, I&rsquo;m going to continue the discussion started in <a href="https://www.earthli.com/news/view_article.php?id=3165">Part I</a>, where we laid some groundwork about the state machine that is the startup/execution/shutdown feature of Quino. As we discussed, this part of the API still suffers from  <span class="quote-inline">&ldquo;several places where generic TApplication parameters [are] cluttering the API&rdquo;</span>. In this article, we&rsquo;ll take a closer look at different design approaches to this concrete example—and see how we decided whether to use generic type parameters. </p>
<h2>Consistency through Patterns and API</h2><p>Any decision you take with a non-trivial API is going to involve several stakeholders and aspects. It&rsquo;s often not easy to decide which path is best for your stakeholders and your product.</p>
<blockquote class="quote pullquote align-left left" style="width: 280px"><div>For any API you design, consider how others are likely to extend it—and whether your pattern is likely to deteriorate from neglect.</div></blockquote><p>For any API you design, consider how others are likely to extend it—and whether your pattern is likely to deteriorate from neglect. Even a very clever solution has to be balanced with simplicity and elegance if it is to have a hope in hell of being used and standing the test of time.</p>
<p>In Quino 2.0, the focus has been on ruthlessly eradicating properties on the <code>IApplication</code> interface as well as getting rid of the descendant interfaces, <code>ICoreApplication</code> and <code>IMetaApplication</code>. Because Quino now uses a pattern of placing sub-objects in the IOC associated with an <code>IApplication</code>, there is far less need for a generic <code>TApplication</code> parameter in the rest of the framework. See <a href="https://www.earthli.com/news/view_article.php?id=412">Encodo’s configuration library for Quino: part I</a> for more information and examples.</p>
<p>This focus raised an API-design question: if we no longer want descendant interfaces, should we eliminate parameters generic in that interface? Or should we continue to support generic parameters for applications so that the caller will always get back the type of application that was passed in?</p>
<p>Before getting too far into the weeds [1], let&rsquo;s look at a few concrete examples to illustrate the issue.</p>
<h2>Do Fluent APIs require generic return-parameters?</h2><p>As discussed in <a href="https://www.earthli.com/news/view_article.php?id=414">Encodo’s configuration library for Quino: part III</a> in detail, Quino applications are configured with the &ldquo;Use*&rdquo; pattern, where the caller includes functionality in an application by calling methods like <code>UseRemoteServer()</code> or <code>UseCommandLine()</code>. The latest version of this API pattern in Quino recommends returning the application that was passed in to allow chaining and fluent configuration.</p>
<p>For example, the following code chains the aforementioned methods together without creating a local variable or other clutter.</p>
<pre class=" "><code>return new CodeGeneratorApplication().UseRemoteServer().UseCommandLine();</code></pre><p>What should the return type of such standard configuration operations be? Taking a method above as an example, it could be defined as follows:</p>
<pre class=" "><code>public static IApplication UseCommandLine(this IApplication application, string[] args) { … }</code></pre><p>This seems like it would work fine, but the original type of the application that was passed in is lost, which is not exactly in keeping with the fluent style. In order to maintain the type, we could define the method as follows:</p>
<pre class=" "><code>public static TApplication UseCommandLine&lt;TApplication&gt;(this TApplication application, string[] args)
  where TApplication : IApplication
{ … }</code></pre><p>This style is not as succinct but has the advantage that the caller loses no type information. On the other hand, it&rsquo;s more work to define methods in this way and there is a strong likelihood that many such methods will simply be written in the style in the first example.</p>
<blockquote class="quote pullquote align-right right" style="width: 250px"><div>Generics definitely offer advantages, but it remains to be seen how much those advantages are worth.</div></blockquote><p>Why would other coders do that? Because it&rsquo;s easier to write code without generics, and because the stronger result type is not needed in 99% of the cases. If every configuration method expects and returns an <code>IApplication</code>, then the stronger type will never come into play. If the compiler isn&rsquo;t going to complain, you can expect a higher rate of entropy in your API right out of the gate.</p>
<p>One way the more-derived type would come in handy is if the caller wanted to define the application-creation method with their own type as a result, as shown below:</p>
<pre class=" "><code>private static CodeGeneratorApplication CreateApplication()
{
  return new CodeGeneratorApplication().UseRemoteServer().UseCommandLine();
}</code></pre><p>If the library methods expect and return <code>IApplication</code> values, the result of <code>UseCommandLine()</code> will be <code>IApplication</code> and requires a cast to be used as defined above. If the library methods are defined generic in <code>TApplication</code>, then everything works as written above.</p>
<p>This is definitely an advantage, in that the user gets the <em>exact</em> type back that they created. Generics definitely offer advantages, but it remains to be seen how much those advantages are worth. [2]</p>
<h2>Another example: The <code>IApplicationManager</code></h2><p>Before we examine the pros and cons further, let&rsquo;s look at another example.</p>
<p>In Quino 1.x, applications were created directly by the client program and passed into the framework. In Quino 2.x, the <code>IApplicationManager</code> is responsible for creating and executing applications. A caller passes in two functions: one to create an application and another to execute an application. </p>
<p>A standard application startup looks like this:</p>
<pre class=" "><code>new ApplicationManager().Run(CreateApplication, RunApplication); [3]</code></pre><blockquote class="quote pullquote align-right right" style="width: 290px"><div>Generic types can trigger an <em>avalanche of generic parameters</em>™ throughout your code.</div></blockquote><p>The question is: what should the types of the two function parameters be? Does <code>CreateApplication</code> return an <code>IApplication</code> or a caller-specific derived type? What is the type of the application parameter passed to <code>RunApplication</code>? Also <code>IApplication</code>? Or the more derived type returned by <code>CreateApplication</code>?</p>
<p>As with the previous example, if the <code>IApplicationManager</code> is to return a derived type, then it must be generic in <code>TApplication</code> and both function parameters will be generically typed as well. These generic types will trigger an <em>avalanche of generic parameters</em>™ throughout the other extension methods, interfaces and classes involved in initializing and executing applications.</p>
<p>That sounds horrible. This sounds like a pretty easy decision. Why are we even considering the alternative? Well, because it can be very advantageous if the application can declare <code>RunApplication</code> with a strictly typed signature, as shown below.</p>
<pre class=" "><code>private static void RunApplication(CodeGeneratorApplication application) { … }</code></pre><p>Neat, right? I&rsquo;ve got my very own type back.</p>
<h2>Where Generics Goes off the Rails</h2><p>However, if the <code>IApplicationManager</code> is to call this function, then the signature of <code>CreateAndStartUp()</code> and <code>Run()</code> have to be generic, as shown below.</p>
<pre class=" "><code>TApplication CreateAndStartUp&lt;TApplication&gt;(
  Func&lt;IApplicationCreationSettings, TApplication&gt; createApplication
)
 where TApplication : IApplication;

IApplicationExecutionTranscript Run&lt;TApplication&gt;(
  Func&lt;IApplicationCreationSettings, TApplication&gt; createApplication,
  Action&lt;TApplication&gt; run
)
  where TApplication : IApplication;</code></pre><p>These are quite messy—and kinda scary—signatures. [4] if these core methods are already so complex, any other methods involved in startup and execution would have to be equally complex—including helper methods created by calling applications. [5]</p>
<p>The advantage here is that the caller will always get back the type of application that was created. The compiler guarantees it. The caller is not obliged to cast an <code>IApplication</code> back up to the original type. The disadvantage is that all of the library code is infected by a generic &lt;TApplication&gt; parameter with its attendant <code>IApplication</code> generic constraint. [6]</p>
<h2>Don&rsquo;t add Support for Conflicting Patterns</h2><p>The title of this section seems pretty self-explanatory, but we as designers must remain vigilant against the siren call of what seems like a really elegant and strictly typed solution.</p>
<blockquote class="quote pullquote align-left left" style="width: 280px"><div>But aren&rsquo;t properties on an application exactly what we just worked so hard to eliminate?</div></blockquote><p>The generics above establish a pattern that must be adhered to by subsequent extenders and implementors. And to what end? So that a caller can attach properties to an application and access those in a statically typed manner, i.e. without  casting?</p>
<p>But aren&rsquo;t properties on an application exactly what we just worked so hard to eliminate? Isn&rsquo;t the recommended pattern to create a &ldquo;settings&rdquo; object and add it to the IOC instead? That is, as of Quino 2.0, you get an <code>IApplication</code> and obtain the desired settings from its IOC. Technically, the cast is still taking place in the IOC somewhere, but that seems somehow less bad than a direct cast.</p>
<p>If the framework recommends that users <em>don&rsquo;t</em> add properties to an application—and ruthlessly eliminated all standard properties and descendants—then why would the framework turn around and add support—at considerable cost in maintenance and readability and extendibility—for callers that expect a certain type of application?</p>
<h2>Wrapping up</h2><p>Let&rsquo;s take a look at the non-generic implementation and see what we lose or gain. The final version of the <code>IApplicationManager</code> API is shown below, which properly balances the concerns of all stakeholders and hopefully will stand the test of time (or at least last until the next major revision).</p>
<pre class=" "><code>IApplication CreateAndStartUp(
  Func&lt;IApplicationCreationSettings, IApplication&gt; createApplication
);

IApplicationExecutionTranscript Run(
  Func&lt;IApplicationCreationSettings, IApplication&gt; createApplication,
  Action&lt;IApplication&gt; run
);</code></pre><p>These are the hard questions of API design: ensuring consistency, enforcing intent and balancing simplicity and cleanliness of code with expressiveness.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3166_1_body" class="footnote-number">[1]</span> A predilection of mine, I&rsquo;ll admit, especially when writing about a topic about which I&rsquo;ve thought quite a lot. In those cases, the instinct to just skip &ldquo;the object&rdquo; and move on to the esoteric details that stand in the way of an elegant, <em>perfect</em> solution, is very, very strong.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3166_2_body" class="footnote-number">[2]</span> This more-realized typing was so attractive that we used it in many places in Quino without properly weighing the consequences. This article is the result of reconsidering that decision.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3166_3_body" class="footnote-number">[3]</span> This call looks the same for all UI (console, Winform, WPF, etc.), all services (e.g. ASP.NET, Windows-services, etc.) as well as for automated tests. This fact isn&rsquo;t germane to the discussion above, but it&rsquo;s pretty neat in its own right. All an application has to do is define two methods with the right signatures and call the appropriate <code>Run()</code> method for the desired type of application. Almost all of the startup code is shared and the pattern is the same everywhere.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3166_4_body" class="footnote-number">[4]</span> Yes, the C# compiler will allow you to elide generics for most method calls (so long as the compiler can determine the types of the parameters without it). However, generics cannot be removed from constructor calls. These must always specify all generic parameters, which makes for messier-looking, lengthy code in the caller e.g. when creating the <code>ApplicationManager</code> were it to have been defined with generic parameters. Yet another thing to consider when choosing how to define you API.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3166_5_body" class="footnote-number">[5]</span> As already mentioned elsewhere (but it bears repeating): callers can, of course, eschew the generic types and use <code>IApplication</code> everywhere—and most probably will, <em>because the advantage offered by making everything generic is vanishingly small.</em>. If your API looks this scary, entropy will eat it alive before the end of the week, to say nothing of its surviving to the next major version.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3166_6_body" class="footnote-number">[6]</span> A more subtle issue that arises is if you <em>do</em> end up—even accidentally—mixing generic and non-generic calls (i.e. using <code>IApplication</code> as the extended parameter in some cases and <code>TApplication</code> in others). This issue is in how the application object is registered in the IOC. During development, when the framework was still using generics everywhere (or almost everywhere), some parts of the code were retrieving a reference to the application using the most-derived type whereas the application had been registered in the container as a singleton using <code>IApplication</code>. The call to retrieve the most derived type returned a <em>new instance</em> of the application rather than the pre-registered singleton, which was a subtle and difficult bug to track down.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3165</guid>
    <title><![CDATA[API Design: Running an Application (Part I)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3165</link>
    <pubDate>Sat, 19 Sep 2015 07:29:59 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">19. Sep 2015 07:29:59 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">26. Sep 2015 11:24:56 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In this article, we&rsquo;re going to discuss a bit more about the configuration library in Quino 2.0. </p>
<p>Other entries on this topic have been the articles about Encodo’s configuration library for Quino: <a href="https://www.earthli.com/news/blogs.php?entry_id=412">part I</a>, <a href="https://www.earthli.com/news/blogs.php?entry_id=413">part II</a> and <a href="https://www.earthli.com/news/blogs.php?entry_id=414">part III</a>.</p>
<p>The goal of this article is to discuss a concrete example of how we decided whether to use generic type parameters throughout the configuration part of Quino. The meat of that discussion will be in a part 2 because we&rsquo;re going to have to lay some groundwork about the features we want first. (Requirements!)</p>
<h2>A Surfeit of Generics</h2><p>As of <a href="https://www.earthli.com/news/blogs.php?entry_id=412">Quino 2.0-beta2</a>, the configuration library consisted of a central <code>IApplication</code> interface which has a reference to an IOC container and a list of startup and shutdown actions.</p>
<p>As shown in <a href="https://www.earthli.com/news/blogs.php?entry_id=414">part III</a>, these actions no longer have a generic <code>TApplication</code> parameter. This makes it not only much easier to use the framework, but also easier to extend it. In this case, we were able to remove the generic parameter without sacrificing any expressiveness or type-safety.</p>
<p>As of beta2, there were still several places where generic <code>TApplication</code> parameters were cluttering the API. Could we perhaps optimize further? Throw out even more complexity without losing anything?</p>
<h2>Starting up an application</h2><p>One of these places is the actual engine that executes the startup and shutdown actions. This code is a bit trickier than just a simple loop because Quino supports execution in debug mode—without exception-handling—and release mode—with global exception-handling and logging.</p>
<p>As with any application that uses an <abbr title="Inversion of Control">IOC</abbr> container, there is a configuration phase, during which the container can be changed and an execution phase, during which the container produces objects but can no longer be re-configured.</p>
<p>Until 2.0-beta2, the execution engine was encapsulated in several extension methods called <code>Run()</code>, <code>StartUp()</code> and so on. These methods were generally generic in <code>TApplication</code>. I write &ldquo;generally&rdquo; because there were some inconsistencies with extension methods for custom application types like Winform or Console applications.</p>
<p>While extension methods can be really useful, this usage was not really appropriate as it violated the open/closed principle. For the final release of Quino, we wanted to move this logic into an <code>IApplicationManager</code> so that applications using Quino could (A) choose their own logic for starting an application and (B) add this startup class to a non-Quino IOC container if they wanted to.</p>
<h2>Application Execution Modes</h2><p>So far, so good. Before we discuss how to rewrite the application manager/execution engine, we should quickly revisit what exactly this engine is supposed to do. As it turns out, not only do we wnat to make an architectural change to make the design more open for extension, but the basic algorithm for starting an application changed, as well.</p>
<blockquote class="quote pullquote align-right right" style="width: 220px"><div>What does it mean to <em>run</em> an application?</div></blockquote><p>Quino has always acknowledged and kinda/sorta supported the idea that a single application can be run in different ways. Even an execution that results in immediate failure technically counts as an execution, as a traversal of the state machine defined by the application.</p>
<p>If we view an application for the state machine that it is, then every application has at least two terminal nodes: OK and Error.</p>
<p>But what does OK mean for an application? In Quino, it means that all startup actions were executed without error and the <code>run()</code> action passed in by the caller was also executed without error. Anything else results in an exception and is shunted to Error.</p>
<p><a href="https://www.earthli.com/data/news/attachments/entry/3165/144986.gif"><img src="https://www.earthli.com/data/news/attachments/entry/3165/144986_tn.gif" alt=" " class=" align-left"></a>But is that true, really? Can you think of other ways in which an application could successfully execute without really having failed? For most applications, the answer is yes. Almost every application—and certainly every Quino application—supports a command line. One of the default options for the command line of a Quino application is <code>-h</code>, which shows a manual for the other command-line options.</p>
<p>If the application is running in a console, this manual is printed to the console; for a Winform application, a dialog box is shown; and so on.</p>
<p>This &ldquo;help&rdquo; mode is actually a successful execution of the application that did <em>not</em> result in the main event loop of the application being executed.</p>
<p>Thought of in this way, any command-line option that controls application execution could divert the application to another type of terminal node in the state machine. A good example is when an application provides support for importing or exporting data via the command line.</p>
<h2>&ldquo;Canceled&rdquo; Terminal Nodes</h2><p>A terminal node is also not necessarily only <code>Crashed</code> or <code>Ok</code>. Almost any application will also need to have a <code>Canceled</code> mode that is a perfectly valid exit state. For example, </p>
<ul>
<li>If the application requires a login during execution (startup), but the user aborts authentication</li>
<li>If the application supports schema migration, but the user aborts without migrating the schema</li></ul><p>These are two ways in which a standard Quino application could run to completion without crashing but without having accomplished any of its main tasks. It ran and it didn&rsquo;t crash, but it also didn&rsquo;t do anything useful.</p>
<h2>Intermediate Nodes in the Application State Machine</h2><p>This section title sounds a bit pretentious, but that&rsquo;s exactly what we want to discuss here. Instead of having just start and terminal nodes, the Quino startup supports cycles through intermediate nodes as well. What the hell does that mean? It means that some nodes may trigger Quino to <em>restart</em> in a different mode in order to handle a particular kind of error condition that could be <em>repaired</em>. [1]</p>
<p>A concrete example is desperately needed here, I think. The main use of this feature in Quino right now is to support on-the-fly schema-migration without forcing the user to restart the application. This feature has been in Quino from the very beginning and is used almost exclusively by developers during development. The use case to support is as follows:</p>
<ol>
<li>Developer is running an application</li>
<li>Developer make change to the model (or pulls changes from the server)</li>
<li>Developer runs the application with a schema-change</li>
<li>Application displays migration tool; developer can easily migrate the schema and continue working</li></ol><p>This workflow minimizes the amount of trouble that a developer has when either making changes or when integrating changes from other developers. In all cases in which the application model is different from the developer&rsquo;s database schema, it&rsquo;s very quick and easy to upgrade and continue working.</p>
<h2>&ldquo;Rescuing&rdquo; an application in Quino 2.0</h2><p>How does this work internally in Quino 2.0? The application starts up but somehow encounters an error that indicates that a schema migration might be required. This can happen in one of two ways:</p>
<ol>
<li>The schema-verification step in the standard Quino startup detects a change in the application model vis à vis the data schema</li>
<li>Some other part of the startup accesses the database and runs into a <code>DatabaseException</code> that is indicative of a schema-mismatch</li></ol><p>In all of these cases, the application that was running throws an <code>ApplicationRestartException</code>, that the standard <code>IApplicationManager</code> implementation knows how to handle. It handles it by shutting down the running application instance and asking the caller to create a new application, but this time one that knows how to handle the situation that caused the exception. Concretely, the exception includes an <code>IApplicationCreationSettings</code> descendant that the caller can use to decide how to customize the application to handle that situation.</p>
<p>The manager then runs <em>this new</em> application to completion (or until a new <code>RestartApplicationException</code> is thrown), shuts it down, and asks the caller to create the original application again, to give it another go.</p>
<p>In the example above, if the user has successfully migrated the schema, then the application will start on this second attempt. If not, then the manager enters the cycle again, attempting to repair the situation so that it can get to a terminal node. Naturally, the user can cancel the migration and the application also exits gracefully, with a <code>Canceled</code> state.</p>
<p>A few examples of possible application execution paths:</p>
<ul>
<li>Standard =&gt; <strong class="highlight">OK</strong></li>
<li>Standard =&gt; <span class="error">Error</span></li>
<li>Standard =&gt; <span class="caution">Canceled</span></li>
<li>Standard =&gt; Restart =&gt; Migrator =&gt; Standard =&gt; <strong class="highlight">OK</strong></li>
<li>Standard =&gt; Restart =&gt; Migrator =&gt; <span class="caution">Canceled</span></li></ul><p>The pattern is the same for interactive, client applications as for headless applications like test suites, which attempt migration once and abort if not successful. Applications like web servers or other services will generally only support the OK and Error states and fail when they encounter a <code>RestartApplicationException</code>.</p>
<p>Still, it&rsquo;s nice to know that the pattern is there, should you need it. It fits relatively cleanly into the rest of the API without making it more complicated. The caller passes two functions to the <code>IApplicationManager</code>: one to create an application and one to run it.</p>
<p>An example from the Quino <code>CodeGeneratorApplication</code> is shown below:</p>
<pre class=" "><code>internal static void Main()
{
  new ApplicationManager().Run(CreateApplication, GenerateCode);
}

private static IApplication CreateApplication(
  IApplicationCreationSettings applicationCreationSettings
) { … }

private static void GenerateCode(IApplication application) { … }</code></pre><p>We&rsquo;ll see in the next post what the final API looks like and how we arrived at the final version of that API in Quino 2.0.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3165_1_body" class="footnote-number">[1]</span> Or <em>rescued</em>, using the nomenclature from Eiffel exception-handling, which actually does something very similar. The exception handling in most languages lets you clean up and move on, but the intent isn&rsquo;t necessarily to re-run the code that failed. In Eiffel, this is exactly how exception-handling works: fix whatever was broken and re-run the original code. Quino now works very much like this as well.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3164</guid>
    <title><![CDATA[Encodo Git Handbook 3.0]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3164</link>
    <pubDate>Sat, 19 Sep 2015 07:18:15 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">19. Sep 2015 07:18:15 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Encodo first published a Git Handbook for employees in September 2011 and last updated it in July of 2012. Since then, we&rsquo;ve continued to use Git, refining our practices and tools. Although a lot of the content is still relevant, some parts are quite outdated and the overall organization suffered through several subsequent, unpublished updates.</p>
<p>What did we change from the version 2.0?</p>
<ul>
<li>We <strong>removed</strong> all references to the <strong>Encodo Git Shell</strong>. This shell was a custom environment based on <em>Cygwin</em>. It configured the SSH agent, set up environment variables and so on. Since tools for Windows have improved considerably, we no longer need this custom tool. Instead, we&rsquo;ve moved to <em>PowerShell</em> and <em>PoshGit</em> to handle all of our Git command-line needs.</li>
<li>We <strong>removed</strong> all references to <strong>Enigma</strong>. This was a Windows desktop application developed by Encodo to provide an overview, eager-fetching and batch tasks for multiple Git repositories. We stopped development on this when <em>SmartGit</em> included all of the same functionality in versions 5 and 6.</li>
<li>We <strong>removed</strong> all detailed documentation for Git <strong>submodules</strong>. Encodo stopped using submodules (except for one legacy project) several years ago. We used to use submodules to manage external binary dependencies but have long since moved to NuGet instead.</li>
<li>We <strong>reorganized</strong> the <strong>chapters</strong> to lead off with a quick overview of <em>Basic Concepts</em> followed by a focus on <em>Best Practices</em> and our recommended <em>Development Process</em>. We also reorganized the Git-command documentation to use a more logical order.</li></ul><p>You can download <a href="https://www.earthli.com/data/news/attachments/entry/3164/encodo_git_handbook_3.pdf">version 3 of the Git Handbook</a> or <a href="http://encodo.com/en/documents.php#git-handbook">get the latest copy from here</a>. </p>
<p>Chapter 3, <em>Basic Concepts</em> and chapter 4, <em>Best Practices</em> have been included in their entirety below.</p>
<h2>3 Best Practices</h2><h3>3.1 Focused Commits</h3><p>Focused commits are required; small commits are highly recommended. Keeping the number of changes per commit tightly focused on a single task helps in many cases.</p>
<ul>
<li>They are easier to resolve when merge conflicts occur</li>
<li>They can be more easily merged/rebased by Git</li>
<li>If a commit addresses only one issue, it is easier for a reviewer or reader to decide whether it should be examined.</li></ul><p>For example, if you are working on a bug fix and discover that you need to refactor a file as well, or clean up the documentation or formatting, you should finish the bug fix first, commit it and then reformat, document or refactor in a separate commit.</p>
<p>Even if you have made a lot of changes all at once, you can still separate changes into multiple commits to keep those commits focused. Git even allows you to split changes from a single file over multiple commits (the <em>Git Gui</em> provides this functionality as does the index editor in <em>SmartGit</em>).</p>
<h3>3.2 Snapshots</h3><p>Use the staging area to make quick snapshots without committing changes but still being able to compare them against more recent changes.</p>
<p>For example, suppose you want to refactor the implementation of a class. </p>
<ul>
<li>Make some changes and run the tests; if everything’s ok, stage those changes</li>
<li>Make more changes; now you can diff these new changes not only against the version in the repository but also against the version in the index (that you staged).</li>
<li>If the new version is broken, you can revert to the staged version or at least more easily figure out where you went wrong (because there are fewer changes to examine than if you had to diff against the original)</li>
<li>If the new version is ok, you can stage it and continue working</li></ul><h3>3.3 Developing New Code</h3><p>Where you develop new code depends entirely on the project release plan.</p>
<ul>
<li>Code for releases should be committed to the release branch (if there is one) or to the develop branch if there is no release branch for that release</li>
<li>If the new code is a larger feature, then use a feature branch. If you are developing a feature in a <em>hotfix</em> or <em>release</em> branch, you can use the optional <strong>base</strong> parameter to base the feature on that branch instead of the <em>develop</em> branch, which is the default.</li></ul><h3>3.4 Merging vs. Rebasing</h3><p>Follow these rules for which command to use to combine two branches:</p>
<ul>
<li>If both branches have already been pushed, then <strong>merge</strong>. There is no way around this, as you won’t be able to push a non-merged result back to the origin.</li>
<li>If you work with branches that are part of the standard branching model (e.g. release, feature, etc.), then <strong>merge</strong>.</li>
<li>If both you and someone else made changes to the same branch (e.g. develop), then <strong>rebase</strong>. This will be the default behavior during development</li></ul><h2>4 Development Process</h2><p>A <em>branching model</em> is required in order to successfully manage a non-trivial project.</p>
<p>Whereas a trivial project generally has a single branch and few or no tags, a non-trivial project has a stable release—with tags and possible hotfix branches—as well as a development branch—with possible feature branches.</p>
<p>A common branching model in the Git world is called <em>Git Flow</em>. Previous versions of this manual included more specific instructions for using the <em>Git Flow</em>-plugin for Git but experience has shown that a less complex branching model is sufficient and that using standard Git commands is more transparent.</p>
<p>However, since <em>Git Flow</em> is a very widely used branching model, retaining the naming conventions helps new developers more easily understand how a repository is organized.</p>
<h3>4.1 Branch Types</h3><p>The following list shows the branch types as well as the naming convention for each type:</p>
<ul>
<li><strong>master</strong> is the main development branch. All other branches should be merged back to this branch (unless the work is to be discarded). Developers may apply commits and create tags directly on this branch.</li>
<li><strong>feature/name</strong> is a feature branch. Feature branches are for changes that require multiple commits or coordination between multiple developers. When the feature is completed and stable, it is merged to the <em>master</em> branch after which it should be removed. Multiple simultaneous feature branches are allowed.</li>
<li><strong>release/vX.X.X</strong> is a release branch. Although a project can be released (and tagged) directly from the master branch, some projects require a longer stabilization and testing phase before a release is ready. Using a release branch allows development on the develop branch to continue normally without affecting the release candidate. Multiple simultaneous release branches are strongly discouraged.</li>
<li><strong>hotfix/vX.X.X</strong> is a hotfix branch. Hotfix branches are always created from the release tag for the version in which the hotfix is required. These branches are generally very short-lived. If a hotfix is needed in a feature or release branch, it can be merged there as well (see the optional arrow in the following diagram).</li></ul><p>The main difference from the <em>Git Flow</em> branching model is that there is no explicit stable branch. Instead, the last version tag serves the purpose just as well and is less work to maintain. For more information on where to develop code, see “3.3 – Developing New Code”.</p>
<h3>4.2 Example</h3><p>To get a better picture of how these branches are created and merged, the following diagram depicts many of the situations outlined above.</p>
<p>The diagram tells the following story:</p>
<ul>
<li>Development began on the master branch</li>
<li>v1.0 was released directly from the master branch</li>
<li>Development on feature “B” began</li>
<li>A bug was discovered in v1.0 and the v1.0.1 hotfix branch was created to address it</li>
<li>Development on feature “A” began</li>
<li>The bug was fixed, v1.0.1 was released and the fix was merged back to the master branch</li>
<li>Development continued on master as well as features “A” and “B”</li>
<li>Changes from master were merged to feature “A” (optional merge)</li>
<li>Release branch v1.1 was created</li>
<li>Development on feature “A” completed and was merged to the master branch</li>
<li>v1.1 was released (without feature “A”), tagged and merged back to the master branch</li>
<li>Changes from master were merged to feature “B” (optional merge)</li>
<li>Development continued on both the master branch and feature “B”</li>
<li>v1.2 was released (with feature “A”) directly from the master branch</li></ul><p><span style="width: 415px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3164/branching_model.png"><img src="https://www.earthli.com/data/news/attachments/entry/3164/branching_model.png" alt=" " style="width: 415px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3164/branching_model.png">Branching Model Example</a></span></span><br>
Legend:</p>
<ul>
<li>Circles depict <em>commits</em></li>
<li>Blue balloons are the first commit in a <em>branch</em></li>
<li>Grey balloons are a <em>tag</em></li>
<li>Solid arrows are a <em>required</em> merge</li>
<li>Dashed arrows are an <em>optional</em> merge</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3161</guid>
    <title><![CDATA[ReSharper Unit Test Runner 9.x update]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3161</link>
    <pubDate>Thu, 03 Sep 2015 12:30:57 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">3. Sep 2015 12:30:57 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Way back in February, I wrote about <a href="https://www.earthli.com/news/view_article.php?id=405">my experiences with ReSharper 9 when it first came out</a>. The following article provides an update, this time with version 9.2, released just last week.</p>
<p><strong><abbr title="Too Long; Didn't Read">tl;dr</abbr>:</strong> I&rsquo;m back to ReSharper 8.2.3 and am a bit worried about the state of the 9.x series of ReSharper. Ordinarily, JetBrains has eliminated performance, stability and functional issues by the first minor version-update (9.1), to say nothing of the second (9.2).</p>
<h2>Test Runner</h2><p>In the previous article, my main gripe was with the unit-test runner, which was unusable due to flakiness in the UI, execution and change-detection. With the release of 9.2, the UI and change-detection problems have been fixed, but the runner is still quite flaky at executing tests.</p>
<p>What follows is the text of the report that I sent to JetBrains when they asked me why I uninstalled R# 9.2.</p>
<blockquote class="quote quote-block "><div><p>As with 9.0 and 9.1, I am unable to productively use the 9.2 Test Runner with many of my NUnit tests. These tests are not straight-up, standard tests, but R# 8.2.3 handled them without any issues whatsoever.</p>
<p>What&rsquo;s special about my tests?</p>
<p>There are quite a few base classes providing base functionality. The top layers provide scenario-specific input via a generic type parameter.</p>
<pre class=" ">- <strong>TestsBase</strong>
  − <strong>OtherBase&lt;tmixin&gt;</strong>
     (7 of these, one with an NUnit CategoryAttribute)
    − <strong>ConcreteTests&lt;tmixin&gt;</strong>
       (defines tests with NUnit TestAttributes)
      − <strong>ProviderAConcreteTests&lt;tmixin&gt;</strong>
         (CategoryAttribute)
        − <strong>ProtocolAProviderAConcreteTests</strong>
          (TMixin = ProtocolAProviderA; TestFixtureAttribute, CategoryAttributes)
        − <strong>ProtocolBProviderAConcreteTests</strong>
          (TMixin = ProtocolBProviderA; TestFixtureAttribute, CategoryAttributes)
      − <strong>ProviderBConcreteTests&lt;tmixin&gt;</strong>
         (CategoryAttribute)
        − <strong>ProtocolAProviderBConcreteTests</strong>
          (TMixin = ProtocolAProviderB; TestFixtureAttribute, CategoryAttributes)
        − <strong>ProtocolBProviderBConcreteTests</strong>
          (TMixin = ProtocolBProviderB; TestFixtureAttribute, CategoryAttributes)</pre><p>The test runner in 9.2 is not happy with this at all. The test explorer shows all of the tests correctly, with the test counts correct. If I select a node for all tests for ProviderB and ProtocolA (696 tests in 36 fixtures), R# loads 36 non-expandable nodes into the runner and, after a bit of a wait, marks them all as inconclusive. Running an individual test-fixture node does not magically cause the tests to load or appear and also shows inconclusive (after a while; it seems the fixture setup executes as expected but the results are not displayed).</p>
<p>If I select a specific, concrete fixture and add or run those tests, R# loads and executes the runner correctly. If I select multiple test fixtures in the explorer and add them, they also show up as expandable nodes, with the correct test counts, and can be executed individually (per fixture). However, if I elect to run them all by running the parent node, R# once again marks everything as inconclusive.</p>
<p>As I mentioned, 8.2.3 handles this correctly and I feel R# 9.2 isn&rsquo;t far off—the unit-test explorer does, after all, show the correct tests and counts. In 9.2, it&rsquo;s not only inconvenient, but I&rsquo;m  worried that my tests are not being executed with the expected configuration.</p>
<p>Also, I really missed the StyleCop plugin for 9.2. There&rsquo;s a beta version for 9.1 that caused noticeable lag, so I&rsquo;m still waiting for a more unobtrusive version for 9.2 (or any version at all).</p>
</div></blockquote><p>While it&rsquo;s possible that there&rsquo;s something I&rsquo;m doing wrong, or there&rsquo;s something in my installation that&rsquo;s strange, I don&rsquo;t think that&rsquo;s the problem. As I mentioned, test-running for the exact same solution with 8.2.3 is error-free and a pleasure to use. In 9.2, the test explorer shows all of the tests correctly, so R# is clearly able to interpret the hierarchy and attributes (noted above) as I&rsquo;ve intended them to be interpreted. This feels very much like a bug or a regression for which JetBrains doesn&rsquo;t have test coverage. I will try to work with them to help them get coverage for this case.</p>
<h2>Real-Time StyleCop rules</h2><p>Additionally, the StyleCop plugin is absolutely essential for my workflow and there still isn&rsquo;t an official release for any of the 9.x versions. ReSharper 9.2 isn&rsquo;t supported at all yet, even in prerelease form. The <a href="http://stylecop.codeplex.com">official Codeplex page</a> shows the latest official version as 4.7, released in January of 2012 for ReSharper 8.2 and Visual Studio 2013. One would imagine that VS2015 support is in the works, but it&rsquo;s hard to say. There is a <a href="https://resharper-plugins.jetbrains.com/packages/ReSharper.StyleCop/">page for StyleCop in the ReSharper extensions gallery</a> but that shows a beta4, released in April of 2015, that only works with ReSharper 9.1.x, not 9.2. I tested it with 9.1.x, but it <em>noticeably</em> slowed down the UI. While typing was mostly unaffected, scrolling and switching file-tabs was very laggy. Since StyleCop is essential for so many developers, it&rsquo;s hard to see why the plugin gets so little love from either JetBrains or Microsoft.</p>
<h2>GoTo Word</h2><p>The <a href="https://github.com/controlflow/resharper-gotoword/issues/11">&ldquo;Go To Word&rdquo; plugin</a> is not <em>essential</em> but it is an extremely welcome addition, especially with so much more client-side work depending on text-based bindings that aren&rsquo;t always detected by ReSharper. In those cases, you can find—for example—all the references of a <a href="http://knockoutjs.com">Knockout template</a> by searching just as you would for a type or member. Additionally, you benefit from the speed of the ReSharper indexing engine and search UI instead of using the comparatively slow and ugly &ldquo;Find in Files&rdquo; support in Visual Studio. Alternatives suggested in the comments to the linked issue above all depend on building yet another index of data (e.g. <a href="https://visualstudiogallery.msdn.microsoft.com/06f39a31-20ce-408c-afee-8a02b484db1c">Sando Code Search Tool</a>). JetBrains has pushed off integrating go-to-word until version 10. Again, not a deal-breaker, but a shame nonetheless, as I&rsquo;ll have to do without it in 9.x until version 10 is released.</p>
<p>With so much more client-side development going on in Visual Studio and with dynamic languages and data-binding languages that use name-matching for data-binding, GoToWord is more and more essential. Sure, ReSharper can continue to integrate native support for finding such references, but until that happens, we&rsquo;re stuck with the inferior Find-in-Files dialog or other extensions that increase the memory pressure for larger solutions.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3142</guid>
    <title><![CDATA[v2.0-beta2: Code generation, IOC and configuration]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3142</link>
    <pubDate>Sat, 30 May 2015 23:51:19 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">30. May 2015 23:51:19 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The summary below describes major new features, items of note and breaking changes. The <a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=19704">full list of issues</a> is also available for those with access to the Encodo issue tracker.</p>
<h2>Highlights</h2><p>In <a href="https://www.earthli.com/news/view_article.php?id=3128">beta1</a>, we read about changes to configuration, the data driver architecture, DDL commands, and security and access control in web applications.</p>
<p>In beta-2, we made the following additional improvements:</p>
<ul>
<li>Introduced a <strong>new generated-code version</strong> that avoids all global references and provides a much-improved API for working with metadata. See below for more details. (<a href="https://secure.encodo.ch/jira/browse/QNO-4821">QNO-4821</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4820">QNO-4820</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4819">QNO-4819</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4818">QNO-4818</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4817">QNO-4817</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4816">QNO-4816</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4815">QNO-4815</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4814">QNO-4814</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4813">QNO-4813</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4812">QNO-4812</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4507">QNO-4507</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4506">QNO-4506</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4117">QNO-4117</a>)</li>
<li>Continued to update and <strong>standardize configuration</strong> and execution for applications, as documented in Encodo&rsquo;s configuration library for Quino: <a href="https://www.earthli.com/news/view_article.php?id=3132">part I</a>, <a href="https://www.earthli.com/news/view_article.php?id=3138">part II</a> and <a href="https://www.earthli.com/news/view_article.php?id=3137">part III</a>. (<a href="https://secure.encodo.ch/jira/browse/QNO-4834">QNO-4834</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4831">QNO-4831</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4809">QNO-4809</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4772">QNO-4772</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4663">QNO-4663</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4664">QNO-4664</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4360">QNO-4360</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4771">QNO-4771</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4676">QNO-4676</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4675">QNO-4675</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4673">QNO-4673</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-3765">QNO-3765</a>)</li>
<li><strong>Moved</strong> all <strong>globals</strong> and static classes with global dependencies to the application&rsquo;s <strong>IOC container</strong>. (<a href="https://secure.encodo.ch/jira/browse/QNO-4791">QNO-4791</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4792">QNO-4792</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4790">QNO-4790</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4784">QNO-4784</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4782">QNO-4782</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4778">QNO-4778</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4787">QNO-4787</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4774">QNO-4774</a>)</li>
<li><strong>Reduce direct dependencies</strong> and properties in <code>IApplication</code>, <code>ICoreApplication</code> and <code>IMetaApplication</code>. (<a href="https://secure.encodo.ch/jira/browse/QNO-4789">QNO-4789</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4788">QNO-4788</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4786">QNO-4786</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4785">QNO-4785</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4671">QNO-4671</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4669">QNO-4669</a>, , <a href="https://secure.encodo.ch/jira/browse/QNO-4668">QNO-4668</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4667">QNO-4667</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4660">QNO-4660</a>)</li>
<li>Removed references to GlobalContext and ServiceLocator from the <strong>Winforms components</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-4832">QNO-4832</a>)</li>
<li><strong>Standardized naming</strong> and namespaces to conform to industry, StyleCop and .NET conventions. (<a href="https://secure.encodo.ch/jira/browse/QNO-4807">QNO-4807</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4806">QNO-4806</a>)</li>
<li>Added support for <strong>parameterized custom SQL</strong> queries with the <code>ICustomCommandBuilder</code>. This was added by customer request, for applications that formulate queries that are beyond what the Quino ORM is currently capable of mapping. A blog post with more detail on how this works is forthcoming. (<a href="https://secure.encodo.ch/jira/browse/QNO-4802">QNO-4802</a>)</li>
<li>Further <strong>cleanup</strong> and consolidation in the <strong>data-driver</strong> hierarchy. This work was a direct result of Daniel Roth&rsquo;s Bachelor&rsquo;s thesis work in which he integrated NHibernate as an alternative ORM for Quino. (<a href="https://secure.encodo.ch/jira/browse/QNO-4808">QNO-4808</a>; still to do by RTM: <a href="https://secure.encodo.ch/jira/browse/QNO-4749">QNO-4749</a>)</li>
<li><strong>Discontinued</strong> support for <strong><code>DataContract</code></strong> and <code>DataMember</code> attributes in metadata and generated code. (<a href="https://secure.encodo.ch/jira/browse/QNO-4823">QNO-4823</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4826">QNO-4826</a>)</li></ul><h2>Goodbye, old friends</h2><p>This release addressed some issues that have been bugging us for a while (almost 3 years in one case).</p>
<ul>
<li><a href="https://secure.encodo.ch/jira/browse/QNO-3765">QNO-3765</a> (<strong>32 months</strong>): After a schema migration caused by a DatabaseException on login, restart the application</li>
<li><a href="https://secure.encodo.ch/jira/browse/QNO-4117">QNO-4117</a> (<strong>27 months</strong>): PreferredType registration for models is not always executed</li>
<li><a href="https://secure.encodo.ch/jira/browse/QNO-4408">QNO-4408</a> (<strong>18 months</strong>): When access to the remoting server is unauthorized, the web site should respond with an error</li>
<li><a href="https://secure.encodo.ch/jira/browse/QNO-4506">QNO-4506</a> (<strong>14 months</strong>): The code generator should generate the persistent object and metadata references in separate classes</li>
<li><a href="https://secure.encodo.ch/jira/browse/QNO-4507">QNO-4507</a> (<strong>14 months</strong>): Business objects for modules should not rely on GlobalContext in generated code</li></ul><p>You will not be missed.</p>
<h2>Breaking changes</h2><p>As we&rsquo;ve mentioned before, this release is absolutely merciless in regard to backwards compatibility. Old code is not retained as obsolete <code>Obsolete</code>. Instead, a project upgrading to 2.0 will encounter compile errors. </p>
<p>That said, if you arm yourself with a bit of time, ReSharper and the release notes (and possibly keep an Encodo employee on speed-dial), the upgrade is not difficult. It consists mainly of letting ReSharper update namespace references for you. In cases where the update is not so straightforward, we&rsquo;ve provided release notes.</p>
<h2>V1 generated code support</h2><p>One of the few things you&rsquo;ll be able to keep (at least for a minor version or two) is the old-style generated code. We made this concession because, while even a large solution can be upgraded from 1.13.0 to 2.0 relatively painlessly in about an hour (we&rsquo;ve converted our own internal projects to test), changing the generated-code format is potentially a much larger change. Again, an upgrade to the generated-code format isn&rsquo;t <em>complicated</em> but it might require more than an hour or two&rsquo;s worth of elbow grease to complete.</p>
<p>Therefore, you&rsquo;ll be able to not only retain your old generated code, but the code generator will continue support the old-style code-generation format for further development. Expect the grace period to be relatively short, though.</p>
<p>Regardless of whether you elect to keep the old-style generated code, you&rsquo;ll have to do a <em>little</em> bit of extra work just to be able to generate code again.</p>
<ol>
<li>Manually update a couple of generated files, as shown below.</li>
<li>Compile the solution</li>
<li>Generate code with the Quino tools</li></ol><p>Before you can regenerate, you&rsquo;ll have to manually update your previously generated code in the main model file, as shown below.</p>
<h3>Previous version</h3><pre class=" "><code>static MyModel()
{
  Messages = new InMemoryRecorder();
  Loader = new ModelLoader(() =&gt; Instance, () =&gt; Messages, new MyModelGenerator());
}

public static IMetaModel CreateModel(IExtendedRecorder recorder)
{
  if (recorder == null) { throw new ArgumentNullException("recorder"); }

  var result = Loader.Generator.CreateModel(recorder);

  result.Configure();

  return result;
}

// More code …

/// &lt;inheritdoc/&gt;
protected override void DoConfigure()
{
  base.DoConfigure();

  ConfigurePreferredTypes();
  ApplyCustomConfiguration();
}</code></pre><h3>Manually updated version</h3><pre class=" "><code>static MyModel()
{
  Messages = new InMemoryRecorder();
  <del>Loader = new ModelLoader(() =&gt; Instance, () =&gt; Messages, new MyModelGenerator());</del>
}

public static IMetaModel CreateModel(IExtendedRecorder recorder)
{
  if (recorder == null) { throw new ArgumentNullException("recorder"); }

  var result = <del>Loader.Generator</del><strong class="highlight">(MyModel)new MyModelGenerator()</strong>.CreateModel(
    <strong class="highlight">ServiceLocator.Current.GetInstance&lt;IExpressionParser&gt;(),
    ServiceLocator.Current.GetInstance&lt;IMetaExpressionFactory&gt;(),
    </strong>recorder
  );

  result.Configure<strong class="highlight">PreferredTypes();
  result.ApplyCustomConfiguration();</strong>

  return result;
}

<del>/// &lt;inheritdoc/&gt;
protected override void DoConfigure()
{
  base.DoConfigure();

  ConfigurePreferredTypes();
  ApplyCustomConfiguration();
}</del></code></pre><h3>Integrate into the model builder</h3><p>In the application configuration for the first time you generate code with Quino 2.0, you should use:</p>
<pre class=" "><code>ModelLoader = MyModel.Loader;
<strong class="highlight">this.UseMetaSimpleInjector();
this.UseModelLoader(MyModel.CreateModel);</strong></code></pre><p>After regenerating code, you should use the following for version-2 generated code:</p>
<pre class=" "><code><del>ModelLoader = MyModel.Loader;</del>
this.UseMetaSimpleInjector();
this.UseModelLoader(MyModel<strong class="highlight">Extensions</strong>.CreateModel<strong class="highlight">AndMetadata</strong>);</code></pre><p>…and the following for version-1 generated code:</p>
<pre class=" "><code><del>ModelLoader = MyModel.Loader;</del>
this.UseMetaSimpleInjector();
this.UseModelLoader(MyModel.CreateModel);</code></pre><h2>Still to do by RTM</h2><p>As you can see, we&rsquo;ve already done quite a bit of work in beta1 and beta2. We have a few more tasks planned for the feature-complete release candidate for 2.0</p>
<ul>
<li><div class=" "><p>Move the schema-migration <strong>metadata table to a module</strong>.</p>
<p>The Quino schema-migration extracts most of the information it needs from database schema itself. It also stores extra metadata in a special table. This table has been with Quino since before modules were supported (over seven years) and hence was built in a completely custom manner. Moving this support to a Quino metadata module will remove unnecessary implementation and make the migration process more straightforward.  (<a href="https://secure.encodo.ch/jira/browse/QNO-4888">QNO-4888</a>)<br>
&nbsp;</p>
</div></li>
<li><div class=" "><p><strong>Separate collection algorithm</strong> from storage/display method in <strong><code>IRecorder</code></strong> and descendants.</p>
<p>The recording/logging library has a very good interface but the implementation for the standard recorders has become too complex as we added support for multi-threading, custom disposal and so on. We want to clean this up to make it easier to extend the library with custom loggers. (<a href="https://secure.encodo.ch/jira/browse/QNO-4888">QNO-4888</a>)<br>
&nbsp;</p>
</div></li>
<li><div class=" "><p><strong>Split up</strong> Encodo and Quino <strong>assemblies</strong> based on functionality.</p>
<p>There are only a very dependencies left to untangle (<a href="https://secure.encodo.ch/jira/browse/QNO-4678">QNO-4678</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4672">QNO-4672</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4670">QNO-4670</a>); after that, we&rsquo;ll split up the two main Encodo and Quino assemblies along functional lines. (<a href="https://secure.encodo.ch/jira/browse/QNO-4376">QNO-4376</a>)<br>
&nbsp;</p>
</div></li>
<li><div class=" "><p><strong>Finish integrating</strong> building and publishing <strong>NuGet</strong> and symbol packages into Quino&rsquo;s release process.</p>
<p>And, finally, once we have the assemblies split up to our liking, we&rsquo;ll finalize the Nuget packages for the Quino library and leave the direct-assembly-reference days behind us, ready for Visual Studio 2015.<br>
(<a href="https://secure.encodo.ch/jira/browse/QNO-4376">QNO-4376</a>)<br>
&nbsp;</p>
</div></li></ul><p>That&rsquo;s all we&rsquo;ve got for now. See you next month for the next (and, hopefully, final update)!</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3137</guid>
    <title><![CDATA[Encodo's configuration library for Quino: part III]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3137</link>
    <pubDate>Sun, 17 May 2015 17:45:56 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. May 2015 17:45:56 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3137/applicationconfigurationlogo.png"><img src="https://www.earthli.com/data/news/attachments/entry/3137/applicationconfigurationlogo_tn.png" alt=" " class=" align-right"></a>This discussion about configuration spans three articles:</p>
<ol>
<li><strong><a href="https://www.earthli.com/news/view_article.php?id=3132">part I</a></strong> discusses the history of the configuration system in Quino as well as a handful of principles we kept in mind while designing the new system</li>
<li><strong><a href="https://www.earthli.com/news/view_article.php?id=3138">part II</a></strong> discusses the basic architectural changes and compares an example from the old configuration system to the new.</li>
<li><strong>part III</strong> takes a look at configuring the &ldquo;execution order&rdquo;—the actions to execute during application startup and shutdown</li></ol><h2>Introduction</h2><p>Registering with an IOC is all well and good, but <em>something</em> has to make calls <em>into</em> the IOC to get the ball rolling.</p>
<blockquote class="quote pullquote align-right right" style="width: 250px"><div>Something has to actually make calls into the IOC to get the ball rolling.</div></blockquote><p>Even service applications—which start up quickly and wait for requests to do most of their work—have basic operations to execute before declaring themselves ready.</p>
<p>Things can get complex when starting up registered components and performing basic checks and non-IOC configuration.</p>
<ul>
<li>In which order are the components and configuration elements executed?</li>
<li>How do you indicate dependencies?</li>
<li>How can an application replace a piece of the standard startup?</li>
<li>What kind of startup components are there?</li></ul><p>Part of the complexity of configuration and startup is that developers quickly forget all of the things that they&rsquo;ve come to expect from a mature product and start from zero again with each application. Encodo and Quino applications take advantage of prior work to include standard behavior for a lot of common situations.</p>
<h2>Configuration Patterns</h2><p>Some components can be configured once and directly by calling a method like <code>UseMetaTranslations(string filePath)</code>, which includes all of the configuration options directly in the composition call. This pattern is perfect for options that are used only by one action or that it wouldn&rsquo;t make sense to override in a subsequent action.</p>
<p>So, for simple actions, an application can just replace the existing action with its own, custom action. In the example above, an application for which translations had already been configured would just call <code>UseMetaTranslations()</code> again in order to override that behavior with its own.</p>
<blockquote class="quote pullquote align-left left" style="width: 250px"><div>Most application will replace standard actions or customize standard settings</div></blockquote><p>Some components, however, will want to expose settings that can be customized by actions before they are used to initialize the component.</p>
<p>For example, there is an action called <code>SetUpLoggingAction</code>, which configures logging for the application. This action uses <code>IFileLogSettings</code> and <code>IEventLogSettings</code> objects from the IOC during execution to determine which types of logging to configure.</p>
<p>An application is, of course, free to replace the entire <code>SetUpLoggingAction</code> action with its own, completely custom behavior. However, an application that just wanted to change the log-file behavior or turn on event-logging could use the <code>Configure&lt;TService&gt;()</code> method [1], as shown below.</p>
<pre class=" "><code>application.Configure&lt;IFileLogSettings&gt;(
  s =&gt; s.Behavior = LogFileBehavior.MultipleFiles
);
application.Configure&lt;IEventLogSettings&gt;(
  s =&gt; s.Enabled = true
);</code></pre><h2>Actions</h2><p>A Quino application object has a list of <code>StartupActions</code> and a list of <code>ShutdownActions</code>. Most standard middleware methods register objects with the IOC and add one or more actions to configure those objects during application startup.</p>
<p>Actions have existed for quite a while in Quino. In Quino 2, they have been considerably simplified and streamlined to the point where all but a handful are little more than a functional interface [2].</p>
<p>The list below will give you an idea of the kind of configuration actions we&rsquo;re talking about.</p>
<ul>
<li>Load configuration data</li>
<li>Process command line</li>
<li>Set up logging</li>
<li>Upgrade settings/configuration (e.g. silent upgrade)</li>
<li>Log a header (e.g. user/date/file locations/etc.; for console apps. this might be mirrored to the console)</li>
<li>Load plugins</li>
<li>Set up standard locations (e.g. file-system locations)</li></ul><p>For installed/desktop/mobile applications, there&rsquo;s also:</p>
<ul>
<li>Initialize UI components</li>
<li>Provide loading feedback</li>
<li>Check/manage multiple running instances</li>
<li>Check software update</li>
<li>Login/authentication</li></ul><p>Quino applications also have actions to configure metadata:</p>
<ul>
<li>Configure expression engine</li>
<li>Load metadata</li>
<li>Load metadata-overlays</li>
<li>Validate metadata</li>
<li>Check data-provider connections</li>
<li>Check/migrate schema</li>
<li>Generate default data</li></ul><p>Application shutdown has a smaller set of vital cleanup chores that:</p>
<ul>
<li>dispose of connection managers and other open resources</li>
<li>write out to the log, flush it and close it</li>
<li>show final feedback to the user</li></ul><h2>Anatomy of an Action</h2><p>The following example [3] is for the 1.x version of the relatively simple <code>ConfigureDisplayLanguageAction</code>.</p>
<pre class=" "><code>public class ConfigureDisplayLanguageAction&lt;TApplication&gt; 
  : ApplicationActionBase&lt;TApplication&gt;
  where TApplication : ICoreApplication
{
  public ConfigureDisplayLanguageAction()
    : base(CoreActionNames.ConfigureDisplayLanguage)
  {
  }

  protected override int DoExecute(
    TApplication application, ConfigurationOptions options, int currentResult)
  {
    // Configuration code…
  }
}</code></pre><p>What is wrong with this startup action? The following list illustrates the main points, each of which is addressed in more detail in its own section further below.</p>
<ul>
<li>The <code>ConfigurationOptions</code> parameter introduces an unnecessary layer of complexity</li>
<li>The generic parameter <code>TApplication</code> complicates declaration, instantiation and extension methods that use the action</li>
<li>The <code>int</code> return type along with the <code>currentResult</code> parameter are a bad way of controlling flow.</li></ul><p>The same startup action in Quino 2.x has the following changes from the Quino 1.x version above (legend: <strong class="highlight">additions</strong>; <del>deletions</del>).</p>
<pre class=" "><code>public class ConfigureDisplayLanguageAction<del>&lt;TApplication&gt;</del>
  : ApplicationActionBase<del>&lt;TApplication&gt;
  where TApplication : ICoreApplication</del>
{
  public ConfigureDisplayLanguageAction()
    : base(CoreActionNames.ConfigureDisplayLanguage)
  {
  }

  <strong class="highlight">public</strong><del>protected</del> override <strong class="highlight">void </strong><del>int Do</del>Execute(
    <del>TApplication application, ConfigurationOptions options, int currentResult</del>)
  {
    // Configuration code…
  }
}</code></pre><p>As you can see, quite a bit of code and declaration text was removed, all without sacrificing any functionality. The final form is quite simple, inheriting from a simple base class that manages the name of the action and overrides a single parameter-less method. It is now much easier to see what an action does and the barrier to entry for customization is much lower.</p>
<pre class=" "><code>public class ConfigureDisplayLanguageAction : ApplicationActionBase
{
  public ConfigureDisplayLanguageAction()
    : base(CoreActionNames.ConfigureDisplayLanguage)
  {
  }

  <strong class="highlight">public override void</strong> Execute()
  {
    // Configuration code…
  }
}</code></pre><p>In the following sections, we&rsquo;ll take a look at each of the problems indicated above in more detail.</p>
<h2>Remove the <code>ConfigurationOptions</code> parameter</h2><p>These options are a simple enumeration with values like <code>Client</code>, <code>Testing</code>, <code>Service</code> and so on. They were used only by a handful of standard actions.</p>
<p>These options made it more difficult to decide how to implement the action for a given task. If two tasks were completely different, then a developer would know to create two separate actions. However, if two tasks were similar, but could be executed differently depending on application type (e.g. testing vs. client), then the developer could still have used two separate actions, but could also have used the configuration options. Multiple ways of doing the exact same thing is all kinds of bad.</p>
<blockquote class="quote pullquote align-right right" style="width: 200px"><div>Multiple ways of doing the exact same thing is all kinds of bad.</div></blockquote><p>Parameters like this conflict conceptually with the idea of using <em>composition</em> to build an application. To keep things simple, Quino applications should be configured <em>exclusively</em> by composition. Composing an application with service registrations and startup actions and <em>then</em> passing options to the startup introduced an unneeded level of complexity.</p>
<p>Instead, an application now defines a separate action for each set of options. For example, most applications will need to set up the display language to use—be it for a GUI, a command-line or just to log messages in the correct language. For that, the application can add a <code>ConfigureDisplayLanguageAction</code> to the startup actions or call the standard method <code>UseCore()</code>. Desktop or single-user applications can use the <code>ConfigureGlobalDisplayLanguageAction</code> or call <code>UseGlobalCore()</code> to make sure that global language resources are also configured.</p>
<h2>Remove the <code>TApplication</code> generic parameter</h2><p>The generic parameter to this interface complicates the <code>IApplication&lt;TApplication&gt;</code> interface and causes no end of trouble in <code>MetaApplication</code>, which actually inherits from <code>IApplication&lt;IMetaApplication&gt;</code> for historical reasons.</p>
<blockquote class="quote pullquote align-left left" style="width: 150px"><div>There is no need to maintain statelessness for a single-use object.</div></blockquote><p>Originally, this parameter guaranteed that an action could be stateless. However, each action object is attached to exactly one application (in the <code>IApplication&lt;TApplication&gt;.StartupActions</code> list. So the action that is attached to an application is technically stateless, and a completely different application than the one to which the action is attached could be passed to the <code>IApplcationAction.Execute</code>…which makes no sense whatsoever.</p>
<p>Luckily, this never happens, and only the application to which the action is attached is passed to that method. If that&rsquo;s the case, though, why not just create the action with the application as a constructor parameter when the action is added to the <code>StartupActions</code> list? There is no need to maintain statelessness for a single-use object.</p>
<p>This way, there is no generic parameter for the <code>IApplication</code> interface, all of the extension methods are <em>much</em> simpler and applications are free to create custom actions that work with descendants of <code>IApplication</code> simply by requiring that type in the constructor parameter.</p>
<h2>Debugging is important</h2><blockquote class="quote pullquote align-left left" style="width: 120px"><div>A global exception handler is terrible for debugging</div></blockquote><p>The original startup avoided exceptions, preferring an integer return result instead.</p>
<p>In release mode, a global exception handler is active and is there to help the application exit more or less smoothly—e.g. by logging the error, closing resources where possible, and so on.</p>
<p>A global exception handler is terrible for debugging, though. For exceptions that are caught, the default behavior of the debugger is to stop where the exception is caught rather than where it is thrown. Instead, you want exceptions raised by your application to to stop the debugger from where they are <em>thrown</em>.</p>
<p>So that&rsquo;s part of the reason why the startup and shutdown in 1.x used return codes rather than exceptions.</p>
<h2>Multiple valid code paths</h2><p>The other reason Quino used result codes is that most non-trivial applications actually have multiple paths through which they could successfully run.</p>
<p>Exactly which path the application should take depends on startup conditions, parameters and so on. Some common examples are:</p>
<ul>
<li>Show command-line help</li>
<li>Migrate an application schema</li>
<li>Import, export or generate data</li></ul><p>To show command-line help, an application execute its startup actions in order. It reaches the action that checks whether the user requested command-line help. This action processes the request, displays that help and then wants to smoothly exit the application. The &ldquo;main&rdquo; path—perhaps showing the user a desktop application—should no longer be executed.</p>
<blockquote class="quote pullquote align-right right" style="width: 160px"><div>Non-trivial applications have multiple valid run profiles.</div></blockquote><p>Similarly, the action that checks the database schema determines that the schema in the data provider doesn&rsquo;t match the model. In this case, it would like to offer the user (usually a developer) the option to update the schema. Once the schema is updated, though, startup should be restarted from the beginning, trying again to run the main path.</p>
<p><span class="clear-both"></span></p>
<h2>Use exceptions to indicate errors</h2><p>Whereas the Quino 1.x startup addressed the design requirements above with return codes, this imposes an undue burden on implementors. There was also confusion as to when it was OK to actually throw an exception rather than returning a special code.</p>
<p>Instead, the Quino 2.x startup always uses exceptions to indicate errors. There are a few special types of exceptions recognized by the startup code that can indicate whether the application should silently—and successfully—exit or whether the startup should be attempted again.</p>
<h2>Conclusion</h2><p>There is of course more detail into which we could go on much of what we discussed in these three articles, but that should suffice for an overview of the Quino configuration library.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3137_1_body" class="footnote-number">[1]</span> If C# had them, that it is. See <a href="https://www.earthli.com/news/view_article.php?id=365">Java 8</a> for an explanation of what they are.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3137_2_body" class="footnote-number">[2]</span> This pattern is echoed in the latest beta of the ASP.NET libraries, as described in the article <a href="http://www.strathweb.com/2015/03/strongly-typed-routing-asp-net-mvc-6-iapplicationmodelconvention/">Strongly typed routing for ASP.NET MVC 6 with IApplicationModelConvention</a>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3137_3_body" class="footnote-number">[3]</span> Please note that formatting for the code examples has been adjusted to reduce horizontal space. The formatting does not conform to the <a href="https://www.earthli.com/news/documents.php#csharp-handbook">Encodo C# Handbook</a>.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3138</guid>
    <title><![CDATA[Encodo's configuration library for Quino: part II]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3138</link>
    <pubDate>Sun, 17 May 2015 17:45:20 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. May 2015 17:45:20 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">19. Sep 2015 07:13:29 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In this article, we&rsquo;ll continue the discussion about configuration started in <a href="https://www.earthli.com/news/view_article.php?id=3132">part I</a>. We wrapped up that part with the following principles to keep in mind while designing the new system.</p>
<ul>
<li>Consistency</li>
<li>Opt-in configuration</li>
<li>Inversion of Control</li>
<li>Configuration vs. Execution</li>
<li>Common Usage</li></ul><h2>Borrowing from ASP.NET vNext</h2><p>Quino&rsquo;s configuration inconsistencies and issues have been well-known for several versions—and years—but the opportunity to rewrite it comes only now with a major-version break.</p>
<p>Luckily for us, ASP.NET has been going through a similar struggle and evolution. We were able to model some of our terminology on the patterns from their next version. For example, ASP.NET has moved to a pattern where an application-builder object is passed to user code for configuration. The pattern there is to include <em>middleware</em> (what we call &ldquo;configuration&rdquo;) by calling extension methods starting with &ldquo;Use&rdquo;.</p>
<p>Quino has had a similar pattern for a while, but the method names varied: &ldquo;Integrate&rdquo;, &ldquo;Add&rdquo;, &ldquo;Include&rdquo;; these methods have now all been standardized to &ldquo;Use&rdquo; to match the prevailing .NET winds.</p>
<h2>Begone configuration and feedback</h2><p>Additionally, Quino used to make a distinction between an application instance and its &ldquo;configuration&rdquo;—the template on which an application is based. No more. Too complicated. This design decision, coupled with the promotion of a platform-specific &ldquo;Feedback&rdquo; object to first-level citizen, led to an explosion of generic type parameters. [1]</p>
<p>The distinction between configuration (template) and application (instance) has been removed. Instead, there is just an application object to configure.</p>
<p>The feedback object is now to be found in the service locator. An application registers a platform-specific feedback to use as it would any other customization.</p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3138_1_body" class="footnote-number">[1]</span> The <code>CustomWinformFeedback</code> in the Quino 1.x code at the end of this article provides a glaring example.</div><h2>Hello service locator</h2><p>ASP.NET vNext has made the service locator a first-class citizen. In ASP.NET, applications <em>receive</em> an <code>IApplicationBuilder</code> in one magic &ldquo;Configure&rdquo; method and <em>receive</em> an <code>IServiceCollection</code> in another magic &ldquo;ConfigureServices&rdquo; method.</p>
<p>In Quino 2.x, the application is in charge of creating the service container, though Quino provides a method to create and configure a standard one (SimpleInjector). That service locator is passed to the <code>IApplication</code> object and subsequently accessible there. </p>
<p>Services can of course be registered directly or by calling pre-packaged Middleware methods. Unlike ASP.NET vNext, Quino 2.x makes no distinction between configuring middleware and including the services required by that middleware.</p>
<h2>Begone configuration hierarchy</h2><p>Quino&rsquo;s configuration library has its roots in a time before we were using an IOC container. The configuration was defined as a hierarchy of configuration classes that modeled the following layers.</p>
<ul>
<li>A base implementation that makes only the most primitive assumptions about an application. For example, that it has a <code>RunMode</code> (&ldquo;debug&rdquo; or &ldquo;release&rdquo;) or an exit code or that it has a logging mechanism (e.g. <code>IRecorder</code>).</li>
<li>The &ldquo;Core&rdquo; layer comprises application components that are very common, but do not depend on Quino&rsquo;s metadata.</li>
<li>And, finally, the &ldquo;Meta&rdquo; layer includes configuration for application components that extend the core with metadata-dependent versions as well as specific components required by Quino applications.</li></ul><p>While these layers are still somewhat evident, the move to middleware packages has blurred the distinction between them. Instead of choosing a concrete configuration base class, an application now calls a handful of &ldquo;Use&rdquo; methods to indicate what kind of application to build.</p>
<p>There are, of course, still helpful top-level methods—e.g. <code>UseCore()</code> and <code>UseMeta()</code> methods—that pull in all of the middleware for the standard application types. But, crucially, the application is free to tweak this configuration with more granular calls to register custom configuration in the service locator.</p>
<p>This is a flexible and transparent improvement over passing esoteric parameters to monolithic configuration methods, as in the previous version.</p>
<h2>An example: Configure a software updater</h2><p>Just as a simple example, whereas a Quino 1.x standalone application would set <code>ICoreConfiguration.UseSoftwareUpdater</code> to <code>true</code>, a Quino 2.x application calls <code>UseSoftwareUpdater()</code>. Where a Quino 1.x Winform application would inherit from the <code>WinformFeedback</code> in order to return a customized <code>ISoftwareUpdateFeedback</code>, a Quino 2.x application calls <code>UseSoftwareUpdateFeedback()</code>.</p>
<p>The software-update feedback class is defined below and is used by both versions.</p>
<pre class=" "><code>public class CustomSoftwareUpdateFeedback
  : WinformSoftwareUpdateFeedback&lt;IMetaApplication&gt;
{
  protected override ResponseType DoConfirmUpdate(TApplication application, …)
  {
    …
  }
}</code></pre><p>That&rsquo;s where the similarities end, though. The code samples below show the stark difference between the old and new configuration systems. </p>
<h3>Quino 1.x</h3><p>As explained above, Quino 1.x did not allow registration of a sub-feedback like the software-updater. Instead, the application had to inherit from the main feedback and override a method to create the desired sub-feedback.</p>
<pre class=" "><code>class CustomWinformFeedback : WinformFeedback
{
  public virtual ISoftwareUpdateFeedback&lt;TApplication&gt;
  GetSoftwareUpdateFeedback&lt;TApplication, TConfiguration, TFeedback&gt;()
    where TApplication : ICoreApplication&lt;TConfiguration, TFeedback&gt;
    where TConfiguration : ICoreConfiguration
    where TFeedback : ICoreFeedback
  {
    return new CustomSoftwareUpdateFeedback(this);
  }
}

var configuration = new CustomConfiguration()
{
  UseSoftwareUpdater = true
}

WinformDxMetaConfigurationTools.Run(
  configuration,
  app =&gt; new CustomMainForm(app), 
  new CustomWinformFeedback()
);</code></pre><p>The method-override in the feedback was hideous and scared off a good many developers. not only that, the pattern was to use a magical, platform-specific <code>WinformDxMetaConfigurationTools.Run</code> method to create an application, run it and dispose it.</p>
<h3>Quino 2.x</h3><p>Software-update feedback-registration in Quino 2.x adheres to the principles outlined at the top of the article: it is <strong>consistent</strong> and uses <strong>common patterns</strong> (functionality is included and customized with methods named &ldquo;Use&rdquo;), configuration is <strong>opt-in</strong>, and the <strong>IOC</strong> container is used throughout (albeit implicitly with these higher-level configuration methods).</p>
<pre class=" "><code>using (var application = new CustomApplication())
{
  application.UseMetaWinformDx();
  application.UseSoftwareUpdater();
  application.UseSoftwareUpdaterFeedback(new CustomSoftwareUpdateFeedback());
  application.Run(app =&gt; new CustomMainForm(app));
}</code></pre><p>Additionally, the program has complete control over creation, running and disposal of the application. No more magic and implicit after-the-fact configuration.</p>
<h2>What comes after configuration?</h2><p>In the next and (hopefully) final article, we&rsquo;ll take a look at configuring execution—the actions to execute during startup and shutdown. Registering objects in a service locator is all well and good, but calls into the service locator have to be made in order for anything to actually <em>happen</em>.</p>
<p>Keeping this system flexible and addressing standard application requirements is a challenging but not insurmountable problem. Stay tuned.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3132</guid>
    <title><![CDATA[Encodo&rsquo;s configuration library for Quino: part I]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3132</link>
    <pubDate>Fri, 10 Apr 2015 15:36:06 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">10. Apr 2015 15:36:06 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In this article, I&rsquo;ll continue the discussion about configuration improvements mentioned in the <a href="https://www.earthli.com/news/view_article.php?id=3128">release notes for Quino 2.0-beta1</a>. With beta2 development underway, I thought I&rsquo;d share some more of the thought process behind the forthcoming changes.</p>
<h2>Software Libraries</h2><blockquote class="quote pullquote align-right right" style="width: 200px"><div>what sort of patterns integrate and customize the functionality of libraries in an application?</div></blockquote><p>An application comprises multiple tasks, only some of which are part of that application&rsquo;s actual domain. For those parts not in the application domain, software developers use libraries. A library captures a pattern or a particular way of doing something, making it available through an abstraction. These simplify and smooth away detail irrelevant to the application.</p>
<p>A runtime and its standard <em>libraries</em> provide many such abstractions: for reading/writing files, connecting to networks and so on. Third-party libraries provide others, like logging, <abbr title="Inversion of Control">IOC</abbr>, task-scheduling and more.</p>
<p>Because Encodo&rsquo;s been writing software for a long time, we have a lot of patterns that we&rsquo;ve come up with for our applications. These libraries are split into two main groups: </p>
<ul>
<li><strong>Encodo.*</strong>: extensions to the .NET framework or third-party libraries that don&rsquo;t depend on Quino metadata.</li>
<li><strong>Quino.*</strong>: extensions to the .NET framework, third-party libraries or Encodo libraries that depend on Quino metadata.</li></ul><p>A sort of &ldquo;meta&rdquo; library that lies on top of all of this is configuration and startup of applications that use these libraries. That is, what sort of patterns integrate and customize the functionality of libraries in an application?</p>
<h2>Balancing <abbr title="Keep It Simple, Stupid">K.I.S.S.</abbr> and <abbr title="Don't Repeat Yourself">D.R.Y</abbr></h2><p>Almost nowhere in an application is the balance between K.I.S.S. and D.R.Y. more difficult to maintain than in configuration and startup.</p>
<blockquote class="quote pullquote align-left left" style="width: 200px"><div>So if we already know all of that, why does Quino need a new configuration library?</div></blockquote><p>As mentioned above, there is a lot of commonality between applications in this area. An application will definitely want to incorporate such common configuration from a library. Updates and improvements to that library will then be applied as for any other. This is a good thing.</p>
<p>However, an application will <em>also</em> want to be able to tweak almost any given facet of this shared configuration. That is: just keep the good parts, have those upgraded when they&rsquo;re changed, but apply customization and extend functionality for the application&rsquo;s domain. Easy, right?</p>
<p>It is here that a good configuration library will find just the right level of <em>granularity</em> for customization. Too coarse? Then an application ends up throwing out too much common configuration in order to customize a small part of it. Too fine? Then the configuration system is too verbose or complex and the application avoids using it.</p>
<p>Instead, a configuration system should establish clear patterns—optimally, just one—for how to apply customization. </p>
<ul>
<li>The builder of the underlying configuration library has to consider the myriad situations that might face a library developer and distill those requirements to a common pattern.</li>
<li>The library developer needs to think about which parts an application might want to customize and think about how to expose them.</li></ul><p>So if we already know all of that, then why does Quino need a new configuration library? Well…</p>
<h2>History of Quino&rsquo;s Configuration Library</h2><p>It&rsquo;s really easy to make things over-complicated and muddy. It&rsquo;s really easy to end up growing several different kinds of extension systems over the years. Quino ended up with a generics-heavy API that made declaring new configuration components very wordy.</p>
<p>The core of Quino is the metadata definition for an application domain. That part has barely changed at all since we first wrote it lo so many years ago. We declared it to be our core business—the part that we are better than others at—the part we wanted to have under our own control. Our first draft [1] has held up remarkably well.</p>
<p>Many of the other components have undergone quite a bit of flux: changes in requirements and the components themselves as well as new development processes and patterns all contributed to change. Over time, various applications had different needs and made adjustments to a different iteration of the configuration library. We moved from supporting only single-threaded, single-user desktop applications to also supporting multi-user, multi-threaded services and web servers.</p>
<blockquote class="quote pullquote align-right right" style="width: 200px"><div><p>…we were left with an ugly configuration system that no-one wanted to extend or<br>
use—so yet another would be invented.</p>
</div></blockquote><p>For all of these different applications, we naturally wanted to maintain the common configuration where possible—but customizations for new platforms stretched the capabilities of the configuration library.</p>
<p>Customization would be made to a new version of that library, but applications that couldn&rsquo;t be upgraded immediately forced backwards-compatibility and thus resulted in several different concurrent ways of configuring a particular facet of an application. </p>
<p>In order to keep things in one place, we ended up breaking the interface-separation rule. Dependencies started clumping drastically, but it was OK because nobody was trying to use one thing without the other ten. But it was hard to see what was going on; customization became a black box for all but one or two gurus. On and on it went, until we were left with an ugly configuration system that no-one wanted to extend or use—so yet another would be invented, ad-hoc. And so it went.</p>
<h2>Principles for Quino 2.0 Configuration</h2><p>With Quino 2.0, we examined the existing system and came up with a list of principles.</p>
<ul>
<li><strong>Consistency:</strong> there should be only be one way of customizing settings and components. When a developer asks how to change something, the answer should always be the same pattern. If not, there better be a damned good reason (see &ldquo;Configuration vs. Execution&rdquo; below).</li>
<li><strong>Opt-in configuration:</strong> No more magic methods or base classes that automatically add components and settings in black boxes. Even if the application has to call one or two more methods, it&rsquo;s better to be declarative than clever™.</li>
<li><strong>Inversion of Control:</strong> Standardize configuration to use an IOC container or service locator wherever possible. Instead of clumping settings in configuration or application objects, create discrete settings and put them in the container. Make dependencies explicit (constructor parameters!) and resolved through the container wherever possible.</li>
<li><strong>Configuration vs. Execution:</strong> Be very aware of the difference between the &ldquo;configuration&rdquo; phase and the &ldquo;execution&rdquo; phase. During configuration, the service locator is used in <em>write-only</em> mode; during execution, the service locator is in <em>read-only</em> mode. Code executed during configuration must rely only on explicit dependency-injection via constructor.</li>
<li><strong>Common Usage:</strong> Establish a pattern for calling configuration methods, from least to most specific. E.g. call Quino&rsquo;s base configuration methods <em>before</em> any application-specific customization. Establish patterns for how to configure a single startup action or how to create settings for a larger component that could be further customized in subsequent phases.</li></ul><p>In the next part, we&rsquo;ll take a look at some concrete examples and documentation for the new patterns. [2]</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3132_1_body" class="footnote-number">[1]</span> To be fair, it wasn&rsquo;t our first attempt at metadata. In one way or another, we&rsquo;d been defining metadata structures for generic programming for more years than we&rsquo;d be comfortable divulging. A h/t of course to Opus Software&rsquo;s Atlas libraries—1 and 2—where many of us contributed. Also, I had experience with cross-platform, generic libraries in C++ stretching all the way back to the late 90s as well as the generalized/meta elements of the <a href="http://data.earthli.com/software/webcore/docs/developer/">earthli WebCore</a>. So it was more like the fourth or fifth shot at it, if we&rsquo;re going to be honest—but at least we got it right. :-)</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3132_2_body" class="footnote-number">[2]</span> In particular, I&rsquo;ll add more detail about &ldquo;Common Usage&rdquo; for those who might feel I&rsquo;ve left them hanging a bit in the last bullet point. Sorry &lsquo;bout that. The day is only so long. See you next time…</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3128</guid>
    <title><![CDATA[Quino v2.0-beta1: Configuration, services and web]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3128</link>
    <pubDate>Sat, 28 Mar 2015 23:26:29 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">28. Mar 2015 23:26:29 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The summary below describes major new features, items of note and breaking changes. The <a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=17403">full list of issues</a> is also available for those with access to the Encodo issue tracker.</p>
<h2>Highlights</h2><p>These are the big ones that forced a major-version change.</p>
<ul>
<li>Rewrote <strong>configuration and application API</strong>. (<a href="https://secure.encodo.ch/jira/browse/QNO-4666">QNO-4666</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4679">QNO-4679</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4659">QNO-4659</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4772">QNO-4772</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4663">QNO-4663</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4664">QNO-4664</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4360">QNO-4360</a>)</li>
<li>Data-driver architecture has been consolidated. All drivers, <strong>ADO, Mongo and Remote</strong>, now use the same base implementation, logic and optimization. (<a href="https://secure.encodo.ch/jira/browse/QNO-4461">QNO-4461</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-2913">QNO-2913</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4683">QNO-4683</a>)</li>
<li>Rewrote schema migration to return a list of <strong>DDL commands</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-4732">QNO-4732</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4726">QNO-4726</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4727">QNO-4727</a>) Also improved schema-migration and <strong>mapping to database</strong> (<a href="https://secure.encodo.ch/jira/browse/QNO-4708">QNO-4708</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4708">QNO-4709</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4605">QNO-4605</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4725">QNO-4725</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4605">QNO-4605</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4728">QNO-4728</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4720">QNO-4720</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4728">QNO-4728</a>)</li>
<li>Updated the entire <strong>security and access-control</strong> and <strong>authentication</strong> API, including adding extensive support for tokens for both ASP.NET MVC and WebAPI. (<a href="https://secure.encodo.ch/jira/browse/QNO-4754">QNO-4754</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4757">QNO-4757</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4747">QNO-4747</a>&gt;)</li>
<li>Renamed <code>IMessageRecorder</code> to <strong><code>IRecorder</code></strong>, <code>IMessageStore</code> to <code>IInMemoryRecorder</code> and consolidated <code>IFilteredMessageRecorder</code> to <code>IRecorder</code>. (<a href="https://secure.encodo.ch/jira/browse/QNO-4686">QNO-4686</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4696">QNO-4696</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4750">QNO-4750</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4557">QNO-4557</a>)</li></ul><p>Some smaller, but important changes:</p>
<ul>
<li>Added support for <strong><code>RunInTransaction</code></strong> attribute. Specify the attribute on any <code>IMetaTestFixture</code> to wrap a test or every test in a fixture in a transaction. (<a href="https://secure.encodo.ch/jira/browse/QNO-4682">QNO-4682</a>)</li>
<li><strong>Shared connection manager</strong> is now disposed when an application is disposed. (<a href="https://secure.encodo.ch/jira/browse/QNO-4752">QNO-4752</a>)</li></ul><h2>Breaking changes</h2><p>Oh yeah. You betcha. This is a major release and we&rsquo;ve knowingly made a decision not to maintain backwards-compatibility at all costs. Good news, though, the changes to make are relatively straightforward and easy to make if you&rsquo;ve got a tool like ReSharper that can update <code>using</code> statements automatically.</p>
<h3>Namespace changes</h3><p>As we saw in <a href="https://www.earthli.com/news/view_article.php?id=3058">part I</a> and <a href="https://www.earthli.com/news/view_article.php?id=3064">part II</a> of the guide to using <em>NDepend</em>, Quino 2.0 has unsnarled quite a few dependency issues. A large number of classes and interfaces have been moved out of the <code>Encodo.Tools</code> namespace. Many have been moved to <code>Encodo.Core</code> but others have been scattered into more appropriate and more specific namespaces.</p>
<p>This is one part of the larger changes, easily addressed by using ReSharper to <kbd>Alt</kbd> + <kbd>Enter</kbd> your way through the compile errors.</p>
<h3>Logging changes</h3><p>Another large change is in renaming <code>IMessageRecorder</code> to <code>IRecorder</code> and <code>IMessageStore</code> to <code>IInMemoryRecorder</code>. Judicious use of search/replace or just a bit of elbow grease will get you through these as well.</p>
<h3>Configuration changes</h3><p>Finally, probably the most far-reaching change is in merging <code>IConfiguration</code> into <code>IApplication</code>. In previous versions of Quino, applications would create a configuration object and pass that to a platform-dependent Quino <code>Run()</code> method. Some configuration was provided by the application and some by the platform-specific method.</p>
<p>The example for Quino 1.13.0 below comes from the JobVortex Winform application.</p>
<pre class=" "><code>var configuration = new JobVortexConfiguration
{
  MainSettings = Settings.Default
};

configuration.Add(new JobVortexClientConfigurationPackage());

if (!string.IsNullOrEmpty(Settings.Default.DisplayLanguage))
{
  configuration.DisplayLanguage = new Language(Settings.Default.DisplayLanguage);
}

WinformDxMetaConfigurationTools.Run(
  configuration, 
  app =&gt; new MainForm(app)
);</code></pre><p>In Quino 2.0, the code above has been rewritten as shown below.</p>
<pre class=" "><code>using (IMetaApplication application = new JobVortexApplication())
{
  application.MainSettings = Settings.Default;
  application.UseJobVortexClient();

  if (!string.IsNullOrEmpty(Settings.Default.DisplayLanguage))
  {
    application.DisplayLanguage = new Language(Settings.Default.DisplayLanguage);
  }

  application.Run(app =&gt; new MainForm(app));
}</code></pre><p>As you can see, instead of creating a configuration, the program creates an application object. Instead of using configuration packages mixed with extension methods named &ldquo;Integrate&rdquo;, &ldquo;Configure&rdquo; and so on, the new API uses &ldquo;Use&rdquo; everywhere. This should be comfortable for people familiar with the OWIN/Katana configuration pattern.</p>
<p>It does, however, mean that the <code>IConfiguration</code>, <code>ICoreConfiguration</code> and <code>IMetaConfiguration</code> don&rsquo;t exist anymore. Instead, use <code>IApplication</code>, <code>ICoreApplication</code> and <code>IMetaApplication</code> Again, a bit of elbow grease will be needed to get through these compile errors, but there&rsquo;s little to no risk or need for high-level decisions.</p>
<p>There are a lot of these prepackaged methods to help you create common kinds of applications:</p>
<ul>
<li><code>UseCoreConsole()</code> (a non-Quino application that uses the console)</li>
<li><code>UseMetaConsole()</code> (a Quino application that uses the console)</li>
<li><code>UseCoreWinformDx()</code> (a non-Quino application that uses Winform)</li>
<li><code>UseMetaWinformDx()</code> (a Quino application that uses Winform)</li>
<li><code>UseReporting()</code></li>
<li><code>UseRemotingServer()</code></li>
<li>Etc.</li></ul><p>I think you get the idea. Once we have a final release for Quino 2.0, we&rsquo;ll write more about how to use this new pattern.</p>
<h2>Looking ahead to 2.0 Final</h2><p>This is still just an internal beta of the 2.0 final version. More changes are on the way, including but not limited to:</p>
<ul>
<li>Remove <code>IConfigurationPackage</code> and standardize the configuration API to be named &ldquo;Use&rdquo; everywhere (<a href="https://secure.encodo.ch/jira/browse/QNO-4771">QNO-4771</a>)</li>
<li><code>GenericObject</code> improvements (<a href="https://secure.encodo.ch/jira/browse/QNO-4761">QNO-4761</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4762">QNO-4762</a>)</li>
<li>Change compile location for all projects (<a href="https://secure.encodo.ch/jira/browse/QNO-4756">QNO-4756</a>)</li>
<li>Move a lot of properties from <code>ICoreApplication</code> and <code>IMetaApplication</code> to configuration objects in the service locator. Also improve use of and configuration of service locator (<a href="https://secure.encodo.ch/jira/browse/QNO-4659">QNO-4659</a>)</li>
<li>More improvements to the recorders and logging (<a href="https://secure.encodo.ch/jira/browse/QNO-4688">QNO-4688</a>)</li>
<li>Changes to how ORM objects and metadata are generated. (<a href="https://secure.encodo.ch/jira/browse/QNO-4506">QNO-4506</a>)</li>
<li>Separate Encodo and Quino assemblies into multiple, smaller assemblies (<a href="https://secure.encodo.ch/jira/browse/QNO-4376">QNO-4376</a>)</li></ul><p>See you there!</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3125</guid>
    <title><![CDATA[C# 6 Features and C# 7 Design Notes]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3125</link>
    <pubDate>Fri, 13 Mar 2015 08:59:09 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Mar 2015 08:59:09 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Microsoft has recently made a lot of their .NET code open-source. Not only is the code for many of the base libraries open-source but also the code for the runtime itself. On top of that, basic .NET development is now much more open to community involvement.</p>
<p>In that spirit, even endeavors like designing the features to be included in the next version of C# are online and open to all: <a href="https://github.com/dotnet/roslyn/issues/98">C# Design Meeting Notes for Jan 21, 2015</a> by <cite>Mads Torgerson</cite> (<cite><a href="http://github.com/">GitHub</a></cite>).</p>
<h2>C# 6 Recap</h2><p>You may be surprised at the version number &ldquo;7&rdquo;—aren&rsquo;t we still waiting for C# 6 to be officially released? Yes, we are.</p>
<p>If you&rsquo;ll recall, the primary feature added to C# 5 was support for asynchronous operations through the <code>async</code>/<code>await</code> keywords. Most .NET programmers are only getting around to using this rather far- and deep-reaching feature, to say nothing of the new C# 6 features that are <em>almost</em> officially available.</p>
<p>C# 6 brings the following features with it and can be used in the CTP versions of <a href="https://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs.aspx">Visual Studio 2015</a> or downloaded from <a href="https://github.com/dotnet/roslyn">the Roslyn project</a> (<cite><a href="http://github.com/">GitHub</a></cite>).</p>
<p>Some of the more <a href="http://blogs.msdn.com/b/csharpfaq/archive/2014/11/20/new-features-in-c-6.aspx">interesting features of C# 6</a> are:</p>
<ul>
<li><strong>Auto-Property Initializers</strong>: initialize a property in the declaration rather than in the constructor or on an otherwise unnecessary local variable.</li>
<li><strong>Out Parameter Declaration</strong>: An <code>out</code> parameter can now be declared inline with <code>var</code> or a specific type. This avoids the ugly variable declaration outside of a call to a <code>Try*</code> method.</li>
<li><strong>Using Static Class</strong>: <code>using</code> can now be used with with a static class as well as a namespace. Direct access to methods and properties of a static class should clean up some code considerably.</li>
<li><strong>String Interpolation</strong>: Instead of using <code>string.Format()</code> and numbered parameters for formatting, C# 6 allows expressions to be embedded directly in a string (á la PHP): e.g. <code>&ldquo;{Name} logged in at {Time}&rdquo;</code></li>
<li><strong>nameof()</strong>: This language feature gets the name of the element passed to it; useful for data-binding, logging or anything that refers to variables or properties.</li>
<li><strong>Null-conditional operator</strong>: This feature reduces conditional, null-checking cruft by returning <code>null</code> when the target of a call is <code>null</code>. E.g. <code>company.People?[0]?.ContactInfo?.BusinessAddress.Street</code> includes three null-checks</li></ul><h2>Looking ahead to C# 7</h2><p>If the idea of using <code>await</code> correctly or wrapping your head around the C# 6 features outlined above doesn&rsquo;t already make your poor head spin, then let&rsquo;s move on to language features that aren&rsquo;t even <em>close</em> to being implemented yet.</p>
<p>That said, the <a href="https://github.com/dotnet/roslyn/issues/98">first set of design notes for C# 7</a> by <cite>Mads Torgerson</cite> (<cite><a href="http://github.com/">GitHub</a></cite>) include several interesting ideas as well.</p>
<ul>
<li><strong>Pattern-matching</strong>: C# has been ogling its similarly named colleague F# for a while. One of the major ideas on the table for C# is improving the ability to represent as well as match against various types of pure data, with an emphasis on immutable data.</li>
<li><div class=" "><p><strong>Metaprogramming</strong>: Another focus for C# is reducing boilerplate and capturing common code-generation patterns. They&rsquo;re thinking of delegation of interfaces through composition. Also welcome would be an improvement in the expressiveness of generic constraints. </p>
<p>Related User Voice issues:</p>
<ul>
<li><a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2122427-expand-generic-constraints-for-constructors">Expand Generic Constraints for constructors</a></li>
<li><a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2315417-proper-generic-type-alising">[p]roper (generic) type ali[a]sing</a></li></ul><p> </p>
</div></li>
<li><strong>Controlling Nullability</strong>: Another idea is to be able to declare reference types that can never be <code>null</code> at compile-time (where reasonable—they do acknowledge that they may end up with a <span class="quote-inline">&ldquo;less ambitious approach&rdquo;</span>).</li>
<li><strong>Readonly parameters and locals</strong>: Being able to express when change is allowed is a powerful form of expressiveness. C# 7 may include the ability to make local variables and parameters readonly. This will help avoid accidental side-effects.</li>
<li><div class=" "><p><strong>Lambda capture lists</strong>: One of the issues with closures is that they currently just <em>close</em> over any referenced variables. The compiler just makes this happen and for the most part works as expected. When it doesn&rsquo;t work as expected, it creates subtle bugs that lead to leaks, race conditions and all sorts of hairy situations that are difficult to debug.</p>
<p>If you throw in the increased use of and nesting of lambda calls, you end up with subtle bugs buried in frameworks and libraries that are nearly impossible to tease out.</p>
<p>The idea of this feature is to allow a lambda to <em>explicitly</em> capture variables and perhaps even indicate whether the capture is read-only. Any additional capture would be flagged by the compiler or tools as an error.</p>
</div></li>
<li><div class=" "><p><strong>Contracts(!)</strong>: And, finally, this is the feature I&rsquo;m most excited about because I&rsquo;ve been waiting for integrated language support for Design by Contract for literally <em>decades</em> [1], ever since I read the <a href="http://www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554/">Object-Oriented Software Construction 2</a> (<cite><a href="http://www.amazon.com/">Amazon</a></cite>) (OOSC2) for the first time. The design document doesn&rsquo;t say much about it, but mentions that <span class="quote-inline">&ldquo;.NET already has a contract system&rdquo;</span>, the weaknesses of which I&rsquo;ve <a href="https://www.earthli.com/news/view_article.php?id=2183">written about before</a>. Torgersen writes:</p>
<blockquote class="quote quote-block "><div>&ldquo;When you think about how much code is currently occupied with arguments and result checking, this certainly seems like an attractive way to reduce code bloat and improve readability.&rdquo;</div></blockquote><p>…and <em>expressiveness</em> and <em>provability</em>!</p>
<p>There are a bunch of User Voice issues that I can&rsquo;t encourage you enough to vote for so we can finally get this feature:</p>
<ul>
<li><a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2304022-integrate-code-contract-keywords-into-the-main-ne">Integrate Code Contracts more deeply in the .NET Framework</a></li>
<li><a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2304022-integrate-code-contract-keywords-into-the-main-ne">Integrate Code Contract Keywords into the main .Net Languages</a></li></ul></div></li></ul><p>With some or all of these improvements, C# 7 would move much closer to a provable language at compile-time, an improvement over being a safe language at run-time. </p>
<p>We can already indicate that instance data or properties are readonly. We can already mark methods as static to prevent the use of <code>this</code>. We can use ReSharper <code>[NotNull]</code> attributes to (kinda) enforce non-null references without using structs and incurring the debt of value-passing and -copying semantics.</p>
<p>I&rsquo;m already quite happy with C# 5, but if you throw in some or all of the stuff outlined above, I&rsquo;ll be even happier. I&rsquo;ll still have stuff I can think of to increase expressiveness—covariant return types for polymorphic methods or anchored types or relaxed contravariant type-conformance—but this next set of features being discussed sounds really, really good.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3125_1_body" class="footnote-number">[1]</span> <p>I love the features of the language <a href="https://www.eiffel.com">Eiffel</a>, but haven&rsquo;t ever been able to use it for work. The tools and IDE are a bit stuck in the past (very dated on Windows; X11 required on OS X). The language is super-strong, with native support for contracts, anchored types, null-safe programming, contravariant type-conformance, covariant return types and probably much more that C# is slowly but surely including with each version. Unfair? I&rsquo;ve been writing about this progress for years (from newest to oldest): </p>
<ul>
<li><a href="https://www.earthli.com/news/view_article.php?id=2857">.NET 4.5.1 and Visual Studio 2013 previews are available</a> in June 2013</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=2784">A provably safe parallel language extension for C#</a> in February 2013</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=2216">Waiting for C# 4.0: A casting problem in C# 3.5</a> in October 2009</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=2183">Microsoft Code Contracts: Not with a Ten-foot Pole</a> in June 2009</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=1586">Generics and Delegates in C#</a> in May 2007</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=1436">Wildcard Generics</a> in November 2006 (this one was actually about Java)</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=892">An analysis of C# language design</a> in April 2004</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=820">Static-typing for languages with covariant parameters</a> in June 2003</li>
<li><a href="https://www.earthli.com/news/view_article.php?id=367">What is .NET?</a> in February 2002</li></ul></div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3123</guid>
    <title><![CDATA[Quino Data Driver architecture, Part III: The Pipeline]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3123</link>
    <pubDate>Sat, 07 Mar 2015 08:11:14 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">7. Mar 2015 08:11:14 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In <a href="https://www.earthli.com/news/view_article.php?id=406">part I</a> of these series, we discussed applications, which provide the model and data provider, and sessions, which encapsulate high-level data context. In <a href="https://www.earthli.com/news/view_article.php?id=402">part II</a>, we covered command types and inputs to the data pipeline.</p>
<p>In this article, we&rsquo;re going to take a look at the <em>data pipeline</em> itself.</p>
<ol>
<li><a href="https://www.earthli.com/news/view_article.php?id=406">Applications &amp; Sessions</a></li>
<li><a href="https://www.earthli.com/news/view_article.php?id=402">Command types &amp; inputs</a></li>
<li><strong>The Data Pipeline</strong></li>
<li>Builders &amp; Commands</li>
<li>Contexts and Connections</li>
<li>Sessions, resources &amp; objects</li></ol><h2>Overview</h2><p><span style="width: 433px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3123/data_driver_structure_2015_02_02.png"><img src="https://www.earthli.com/data/news/attachments/entry/3123/data_driver_structure_2015_02_02.png" alt=" " style="width: 433px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3123/data_driver_structure_2015_02_02.png">Major Components of the Data <br>
Driver</a></span></span>The primary goal of the data pipeline is, of course, to <em>correctly</em> execute each query to retrieve data or command to store, delete or refresh data. The diagram to the right shows that the pipeline consists of several <em>data handlers</em>. Some of these refer to data sources, which can be anything: an SQL database or a remote service. [1]</p>
<p>The name &ldquo;pipeline&rdquo; is only somewhat appropriate: A command can jump out anywhere in the pipeline rather than just at the opposite end. A given command will be processed through the various <em>data handlers</em> until one of them pronounces the command to be &ldquo;complete&rdquo;.</p>
<h2>Command context: recap</h2><p>In the previous parts, we learned that the input to the pipeline is an <code>IDataCommandContext</code>. To briefly recap, this object has the following properties:</p>
<ul>
<li><strong>Session</strong>: Defines the context within which to execute the command</li>
<li><strong>Handler</strong>: Implements an abstraction for reading/writing values and flags to the objects (e.g. <code>SetValue(IMetaProperty)</code>); more detail on this later</li>
<li><strong>Objects</strong>:  The sequence of objects on which to operate (e.g. for save commands) or to return (e.g. for load commands)</li>
<li><strong>ExecutableQuery</strong>: The query to execute when loading or deleting objects</li>
<li><strong>MetaClass</strong>: The metadata that describes the root object in this command; more detail on this later as well</li></ul><h2>Handlers</h2><p>Where the pipeline metaphor holds up is that the command context will always start at the same end. The ordering of data handlers is intended to reduce the amount of work and time invested in processing a given command.</p>
<h3>Analyzers</h3><p>The first stage of processing is to quickly analyze the command to handle cases where there is nothing to do. For example,</p>
<ul>
<li>The command is to <em>save</em> or <em>delete</em>, but the sequence of <code>Objects</code> is empty</li>
<li>The command is to <em>save</em> or <em>reload</em>, but none of the objects in the sequence of <code>Objects</code> has changed</li>
<li>The command is to <em>load</em> data but the query restricts to a <code>null</code> value in the primary key or a foreign key that references a non-nullable, unique key.</li></ul><p>It is useful to capture these checks in one or more analyzers for the following reasons,</p>
<ol>
<li>All drivers share a common implementation for efficiency checks</li>
<li>Optimizations are applied independent of the data sources used</li>
<li>Driver code focuses on driver-specifics rather than general optimization</li></ol><h3>Caches</h3><p>If the analyzer hasn&rsquo;t categorically handled the command and the command is to <em>load</em> data, the next step is to check caches. For the purposes of this article, there are two things that affect how long data is cached:</p>
<ol>
<li>If the session is in a transacted state, then only immutable data, data that was loaded before the transaction began or data loaded within that transaction can be used. Data loaded/saved by other sessions—possibly to global caches—is not visible to a session in a transaction with an <code>isolationLevel</code> stricter than <code>RepeatableRead</code>.</li>
<li>The metadata associated with the objects can include configuration settings that control maximum caching lifetime as well as an access-timeout. The default settings are good for general use but can be tweaked for specific object types.</li></ol><p>Caches currently include the following standard handlers [2]:</p>
<ul>
<li>The <code>ValueListDataHandler</code> returns immutable data. Since the data is immutable, it can be used independent of the transaction-state of the session in which the command is executed.</li>
<li>The <code>SessionCacheDataHandler</code> returns data that&rsquo;s already been loaded or saved in this session, to avoid a call to a possibly high-latency back-end. This data is safe to use within the session with transactions because the cache is rolled back when a transaction is rolled back.</li></ul><h3>Data sources</h3><p>If the analyzer and cache haven&rsquo;t handled a command, then we&rsquo;re finally at a point where we can no longer avoid a call to a data source. Data sources can be internal or external.</p>
<h4>Databases</h4><p>The most common type is an external database:</p>
<ul>
<li>PostgreSql 8.x and higher (PostgreSql 9.x for schema migration)</li>
<li>Sql Server 2008 and higher (w/schema migration)</li>
<li>Mongo (no schema; no migration)</li>
<li>SQlite (not yet released)</li></ul><h4>Remoting</h4><p>Another standard data source is the Quino remote application server, which provides a classic interface- and method-based service layer as well as mapping nearly the full power of Quino&rsquo;s generalized querying capabilities to an application server. That is, an application can smoothly switch between a direct connection to a database to using the remoting driver to call into a service layer instead.</p>
<p>The remoting driver supports both binary and JSON protocols. Further details are also beyond the scope of this article, but this driver has proven quite useful for scaling smaller client-heavy applications with a single database to thin clients talking to an application server.</p>
<h4>Custom/Aspect-based</h4><p>And finally, there is another way to easily include &ldquo;mini&rdquo; data drivers in an application. Any metaclass can include an <code>IDataHandlerAspect</code> that defines its own data driver as well as its capabilities. Most implementations use this technique to bind in immutable lists of data. But this technique has also been used to load/save data from/to external APIs, like REST services. We can take a look at some examples in more detail in another article.</p>
<p>The mini data driver created for use with an aspect can relatively easily be converted to a full-fledged data handler.</p>
<h3>Local evaluation</h3><p>The last step in a command is what Quino calls &ldquo;local evaluation&rdquo;. Essentially, if a command cannot be handled entirely within the rest of the data pipeline—either entirely by an analyzer, one or more caches or the data source for that type of object—then the local analyzer completes the command.</p>
<p>What does this mean? Any orderings or restrictions in a query that cannot be mapped to the data source (e.g. a C# lambda is too complex to map to <dfn>SQL</dfn>) are evaluated on the client rather than the server. Therefore, any query that can be formulated in Quino can also be evaluated fully by the data pipeline—the question is only of how much of it can be executed on the server, where it would (usually) be more efficient to do so.</p>
<p>Please see the article series that starts with <a href="https://www.earthli.com/news/view_article.php?id=3003">Optimizing data access for high-latency networks</a> for specific examples.</p>
<p>In this article, we&rsquo;ve learned a bit about the ways in which Quino retrieves and stores data using the <em>data pipeline</em>. In the next part, we’ll cover the topic “Builders &amp; Commands”.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3123_1_body" class="footnote-number">[1]</span> E.g. Quino uses a ProtoBuf-like protocol to communicate with its standard application server.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3123_2_body" class="footnote-number">[2]</span> There is an open issue to <a href="https://secure.encodo.ch/jira/browse/QNO-4767">Introduce a global cache for immutable objects or objects used not in a transaction</a>.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3111</guid>
    <title><![CDATA[Quino Data Driver architecture, Part II: Command types &amp; inputs]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3111</link>
    <pubDate>Sat, 28 Feb 2015 18:36:41 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">28. Feb 2015 18:36:41 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In <a href="https://www.earthli.com/news/view_article.php?id=406">part I</a>, we discussed applications—which provide the model and data provider—and sessions—which encapsulate high-level data context.</p>
<p>In this article, we&rsquo;re going to take a look at the <em>command types &amp; inputs</em></p>
<ol>
<li><a href="https://www.earthli.com/news/view_article.php?id=406">Applications &amp; Sessions</a></li>
<li><strong>Command types &amp; inputs</strong> [1]</li>
<li>The Data Pipeline</li>
<li>Builders &amp; Commands</li>
<li>Contexts and Connections</li>
<li>Sessions, resources &amp; objects</li></ol><h2>Overview</h2><p><span style="width: 433px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3111/data_driver_structure_2015_02_02.png"><img src="https://www.earthli.com/data/news/attachments/entry/3111/data_driver_structure_2015_02_02.png" alt=" " style="width: 433px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3111/data_driver_structure_2015_02_02.png">Major Components of the Data <br>
Driver</a></span></span>Before we can discuss how the pipeline processes a given command, we should discuss what kinds of commands the data driver supports and what kind of inputs the caller can pass to it. As you can well imagine, the data driver can be used for CRUD—to create, read, update and delete and also to <em>refresh</em> data. </p>
<p>In the top-right corner of the diagram to the right, you can see that the only input to the pipeline is an <code>IDataCommandContext</code>. This object comprises the inputs provided by the caller as well as command-specific state used throughout the driver for the duration of the command.</p>
<h2>Command types</h2><p>A caller initiates a command with either a query or an object graph, depending on the type of command. The following commands and inputs are supported:</p>
<ul>
<li><strong>Load:</strong> returns a cursor for the objects that match a <em>query</em></li>
<li><strong>Count:</strong> returns the number of objects that match a <em>query</em></li>
<li><strong>Save:</strong> saves an <em>object graph</em></li>
<li><strong>Reload:</strong> refreshes the data in an <em>object graph</em></li>
<li><strong>Delete:</strong> deletes an <em>object graph</em> or the objects that match a <em>query</em></li></ul><p><span class="clear-both"></span></p>
<h2>Queries</h2><p>A query includes information about the data to return (or delete).</p>
<ul>
<li><strong>Metadata:</strong> The <em>meta-class</em> represents the type of the root object for the command. For example, a &ldquo;person&rdquo; or &ldquo;company&rdquo;.</li>
<li><strong>Filtering:</strong> Filters restrict the objects to return. A filter can address properties of the root object, but also properties of objects <em>related</em> to the root object. A caller can query for people whose first names start with the letter &ldquo;m&rdquo;—<code>FirstName %~ &lsquo;m&rsquo;</code> [2]—or the caller can find all people which belong to a company whose name starts with the letter &ldquo;e&rdquo;—<code>Company.FirstName %~ &lsquo;e&rsquo;</code>. The context for these expressions is naturally the meta-class mentioned above. Additionally, the metadata/model can also include default filters to include.</li>
<li><strong>Ordering:</strong> Orderings that determine in which order the data is returned. Orderings are also specified with the expression language, but are usually simpler, like ordering first by <code>LastName</code> and then by <code>FirstName</code>. More complex expressions are supported—for example, you could use the expression <code>&ldquo;{LastName}, {FirstName}&rdquo;</code>, which sorts by a formatted string [3]—but be aware that many data stores have limited support for complex expressions in orderings. Orderings are ignored in a query when used to delete objects.</li></ul><p>Queries are a pretty big topic and we&rsquo;ve only really scratched the surface so far. Quino has its own query language—QQL—the specification for which weighs in at over 80 pages, but that&rsquo;s a topic for another day.</p>
<h2>Object graphs</h2><p>An object graph consists of a sequence of root objects and the sub-objects available along relations defined in the metadata.</p>
<p>It&rsquo;s actually simpler than it perhaps sounds. </p>
<p>Let&rsquo;s use the example above: a person is related to a single company, so the graph of a single person will include the company as well (if the object is loaded and/or assigned). Additionally, the company defines a relation that describes the list of people that belong to it. The person=&gt;company relationship is <em>complementary</em> to the company=&gt;person relationship. We call person=&gt;company a 1-1 relation, while company=&gt;person is a 1-n relation.</p>
<p>The following code creates two new companies, assigns them to three people and saves everything at once.</p>
<pre class=" "><code>var encodo = new Company { Name = "Encodo Systems AG" };
var other = new Company { Name = "Not Encodo" };
var people = new [] 
{
  new Person { FirstName = "John", LastName = "Doe", Company = other },
  new Person { FirstName = "Bob", LastName = "Smith", Company = encodo },
  new Person { FirstName = "Ted", LastName = "Jones", Company = encodo }
};

Session.Save(people);</code></pre><p>The variable <code>people</code> above is an object graph. The variables <code>encodo</code> and <code>other</code> are also object graphs, but only to parts of the first one. From <code>people</code>, a caller can look up <code>people[0].Company</code>, which is <code>other</code>. The graph contains cycles, so <code>people[0].Company.People[0].Company</code> is also <code>other</code>. From <code>encodo</code>, the caller can get to other people in the same company, but not to people in the <code>other</code> company, for example, <code>encodo.People[0]</code> gets &ldquo;Bob Smith&rdquo; and <code>encodo.People[0].Company.People[1]</code> gets &ldquo;Ted Jones&rdquo;.</p>
<p>As with queries, object graphs are a big topic and are strongly bound to the kind of metadata available in Quino. Another topic for another day.</p>
<h2>Determining Inputs</h2><p>Phew. We&rsquo;re almost to the point where we can create an <code>IDataCommandContext</code> to send into the data pipeline.</p>
<ul>
<li>We have an <code>IDataSession</code> and <a href="https://www.earthli.com/news/view_article.php?id=406">know why we need it</a></li>
<li>We know what type of command we want to execute (e.g. &ldquo;Load&rdquo;)</li>
<li>We have either a <em>query</em> or an <em>object graph</em></li></ul><p>With those inputs, Quino has all it needs from the caller. A glance at the top-left corner of the diagram above shows us that Quino will <em>determine</em> an <code>IMetaClass</code> and an <code>IMetaObjectHandler</code> from these inputs and then use them to build the <code>IDataCommandContext</code>.</p>
<p>An <code>IQuery</code> has a <code>MetaClass</code> property, so that&rsquo;s easy. With the meta-class and the requested type of object, the data driver checks a list of registered object-handlers and uses the first one that says it supports that type. If the input is an object graph, though, the object-handler is determined first and then the meta-class is obtained from the object-handler using a root object from the graph.</p>
<p>Most objects will inherit from <code>GenericObject</code> which implements the <code>IPersistable</code> interface required by the standard object handler. However, an application is free to implement an object handler for other base classes—or no base class at all, using reflection to get/set values on POCOs. That is, however, an exercise left up to the reader.</p>
<p>At this point, we have all of our inputs and can create the <code>IDataCommandContext</code>.</p>
<p>In the next part, we&rsquo;ll take a look at the &ldquo;Data Pipeline&rdquo; through which this command context travels.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3111_1_body" class="footnote-number">[1]</span> You&rsquo;ll notice, perhaps, that this topic is new to this article. I&rsquo;m expanding the series as I go along, trying to provide enough information to understand the process while keeping the individual blog entries to a digestible size.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3111_2_body" class="footnote-number">[2]</span> &ldquo;%~&rdquo; is actually the case-insensitive begins-with operator. You can find out more about comparison operators in the <a href="https://secure.encodo.ch/quinodocs/">Quino documentation</a>. Browse to &ldquo;Encodo Base Library&rdquo; and then &ldquo;Expressions&rdquo;.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3111_3_body" class="footnote-number">[3]</span> For more information on how to use Quino&rsquo;s unique take on interpolated strings, see the documentation in the footnote above.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3109</guid>
    <title><![CDATA[Quino Data Driver architecture, Part I: Applications &amp; Sessions]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3109</link>
    <pubDate>Sat, 21 Feb 2015 08:02:16 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Feb 2015 08:02:16 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>One part of Quino that has undergone quite a few changes in the last few versions is the data driver. The data driver is responsible for CRUD: create, read, update and delete operations. One part of this is the ORM—the object-relational mapper—that marshals data to and from relational databases like PostgreSql, SQL Server and SQLite.</p>
<p>We&rsquo;re going to cover a few topics in this series:</p>
<ol>
<li>Applications &amp; Sessions</li>
<li>The Data Pipeline</li>
<li>Builders &amp; Commands</li>
<li>Contexts and Connections</li>
<li>Sessions, resources &amp; objects</li></ol><p>But first let&rsquo;s take a look at an example to anchor our investigation.</p>
<h2>Introduction</h2><p>An application makes a request to the data driver using commands like <code>Save()</code> to save data and <code>GetObject()</code> or <code>GetList()</code> to get data. How are these high-level commands executed? Quino does an excellent job of shielding applications from the details but it&rsquo;s still very interesting to know how this is achieved.</p>
<p>The following code snippet creates retrieves some data, deletes part of it and saves a new version.</p>
<pre class=" "><code>using (var session = application.CreateSession())
{
  var people = session.GetList&lt;Person&gt;();
  people.Query.WhereEquals(Person.Fields.FirstName, "john");
  session.Delete(people);
  session.Save(new Person { FirstName = "bob", LastName = "doe" });
}</code></pre><p>In this series, we&rsquo;re going to answer the following questions…and probably many more.</p>
<ul>
<li>Where does the data come from?</li>
<li>What kind of sources are supported? How?</li>
<li>Is at least some of the data cached?</li>
<li>Can I influence the cache?</li>
<li>What is a session? Why do I need one?</li>
<li>Wait…what is the application?</li></ul><p>Let&rsquo;s tackle the last two questions first.</p>
<h2>Application</h2><p>The application defines common configuration information. The most important bits for the ORM are as follows:</p>
<ul>
<li><strong>Model:</strong> The model is the central part of any Quino application. The model defines entities, their properties, relationships between entities and so on. Looking at the example above, the model will include a definition for a <code>Person</code>, which has at least the two properties <code>LastName</code> and <code>FirstName</code>. There is probably an entity named <code>Company</code> as well, with a one-to-many relationship to <code>Person</code>. As you can imagine, Quino uses this information to formulate requests to data stores that contain data in this format. [1] For drivers that support it, Quino also uses this information in order to <em>create</em> that underlying data schema. [2]</li>
<li><strong>DataProvider:</strong> The data provider encapsulates all of the logic and components needed to map the model to data sources. This is the part of the process on which this series will concentrate.</li>
<li><strong>ConfigurationData:</strong> The configuration data describes which parts of the model are connected to which parts of the data provider. The default is, of course, that the entire model is mapped to a single data source. However, even in that case, the configuration indicates <em>which</em> data source: Sql Server? PostgreSql? A remote application server (2nd tier)? With a high-level API as described above, all of these decisions can be made in the configuration rather than assumed throughout the application. Yes, this means that you can change your Quino application from a two-tier to a three-tier application with a single configuration change.</li></ul><h2>Sessions</h2><p>So that&rsquo;s the application. There is a single shared application for a process.</p>
<p>But in any non-trivial application—and any non-desktop application—we will have multiple data requests running, possibly in different threads of execution.</p>
<ul>
<li>Each request in a web application is a separate data context. Changes made in one request should not affect any other request. Each request may be authenticated as a different user.</li>
<li>A remote application-server is very similar to a web application. It handles requests from multiple users. Since it&rsquo;s generally the second layer, it will most likely have direct connections to one or more databases. In this case, it will probably be in charge of executing business logic, most likely in a database transaction. In that case, we definitely don&rsquo;t want one request using the transaction context from another request.</li>
<li>Even a non-web client-side application may want to execute some logic in the background or in a separate thread. In those cases, we probably want to keep the data used there separate from the data or objects used to render the other parts of the application.</li></ul><p>That&rsquo;s where sessions come in. The session encapsulates a <em>data context</em>, which contains the following information:</p>
<ul>
<li><strong>Application:</strong> The application will, as described above, tell the session which model and data provider to use.</li>
<li><strong>Current user:</strong> For those familiar with ASP.NET, this is very similar to the <code>HttpContext.Current.User</code> but generalized to be available in any Quino application. All data requests over a session are made in the context of this user.</li>
<li><strong>Access control:</strong> The access control provides information about the security context of an application. An application generally uses the access control to perform authorization checks.</li>
<li><strong>Cache:</strong> Each session also has its own cache. There are global caches, but those are for immutable data. The session&rsquo;s cache is always available, even when using transactions.</li>
<li><strong>ConnectionManager:</strong> Many external data sources have transactable/shared state in the form of a connection. As with data, connections can sometimes be shared between sessions and sometimes they can&rsquo;t. The connection manager takes care of knowing all of that for you.</li></ul><p>If we go back to the original code sample, we now know that creating a new session with <code>CreateSession()</code> creates a new data context, with its own user and its own data cache. Since we didn&rsquo;t pass in any credentials, the session uses the default credentials for the application. [3] All data access made on that session is nicely shielded and protected from any data access made in other sessions (where necessary, of course).</p>
<p>So now we&rsquo;re no closer to knowing how Quino works with data on our behalf, but we&rsquo;ve taken the first step: we know all about one of the main <em>inputs</em> to the data driver, the session.</p>
<p>In the next part, we&rsquo;ll cover the topic &ldquo;The Data Pipeline&rdquo;.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3109_1_body" class="footnote-number">[1]</span> The domain model is used for <em>everything</em> in a Quino application—not just the ORM and for schema-migration.  We use the model to generate C# code like concrete ORM objects, metadata references (e.g. the <code>Person.Fields.FirstName</code> in the example), or view models, DTOs or even client-side TypeScript definitions. We also use the model to generate user interfaces—both for entire desktop-application interfaces but also for HTML helpers to build MVC views.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3109_2_body" class="footnote-number">[2]</span> See the article <a href="https://www.earthli.com/news/view_article.php?id= 3049">Schema migration in Quino 1.13</a> for more information on how that works.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3109_3_body" class="footnote-number">[3]</span> <p>This is code that you might use in a single-user application. In a server application, you would most likely just use the session that was created for your request by Quino. If an application wants to create a new session, but using the same user as an existing session, it would call:</p>
<pre class=" "><code>var requestCredentials = requestSession.AccessControl.CurrentUser.CreateCredentials();
using (var session = application.CreateSession(requestCredentials))
{
  // Work with session
}</code></pre></div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3107</guid>
    <title><![CDATA[Are you ready for ReSharper 9? Not for testing, you aren't.]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3107</link>
    <pubDate>Wed, 11 Feb 2015 07:11:51 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">11. Feb 2015 07:11:51 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>We&rsquo;ve been using ReSharper at Encodo since version 4. And we regularly use a ton of other software from JetBrains [1]—so we&rsquo;re big fans.</p>
<h2>How to Upgrade R#</h2><p>As long-time users of ReSharper, we&rsquo;ve become accustomed to the following pattern of adoption for new major versions:</p>
<h3>EAP</h3><ol>
<li>Read about cool new features and improvements on the JetBrains blog</li>
<li>Check out the EAP builds page</li>
<li>Wait for star ratings to get higher than 2 out of 5</li>
<li>Install EAP of next major version</li>
<li>Run into issues/problems that make testing EAP more trouble than it&rsquo;s worth</li>
<li>Re-install previous major version</li></ol><h3>RTM</h3><ol>
<li>Major version goes RTM</li>
<li>Install <em>immediately</em>; new features! Yay!</li>
<li>Experience teething problems in x.0 version</li>
<li>Go through hope/disappointment cycle for a couple of bug-fix versions (e.g. x.0.1, x.0.2)</li>
<li>Install first minor-version release <em>immediately</em>; stability! Yay!</li></ol><p>This process can take anywhere from several weeks to a couple of months. The reason we do it <em>almost every time</em> is that the newest version of ReSharper almost always has a few killer features. For example, version 8 had initial TypeScript support. Version 9 carries with it a slew of support improvements for Gulp, TypeScript and other web technologies.</p>
<p>Unfortunately, if you need to continue to use the test-runner with C#, you&rsquo;re in for a bumpy ride.</p>
<h2>History of the Test Runner</h2><p>Any new major version of ReSharper can be judged by its test runner. The test runner seems to be rewritten from the ground-up in every major version. Until the test runner has settled down, we can&rsquo;t really use that version of ReSharper for C# development.</p>
<p>The 6.x and 7.x versions were terrible at the NUnit <code>TestCase</code> and <code>Values</code> attributes. They were so bad that we actually converted tests <em>back</em> from using those attributes. While 6.x had trouble reliably compiling and executing those tests, 7.x was better at noticing that something had changed without forcing the user to manually rebuild everything.</p>
<p>Unfortunately, this new awareness in 7.x came at a cost: it slowed editing in larger NUnit fixtures down to a crawl, using a tremendous amount of memory and sending VS into a 1.6GB+ memory-churn that made you want to tear your hair out.</p>
<p>8.x fixed all of this and, by 8.2.x was a model of stability and usefulness, getting the hell out of the way and reliably compiling, displaying and running tests.</p>
<h2>The 9.x Test Runner</h2><p>And then along came 9.x, with a whole slew of sexy new features that just had to be installed. I tried the new features and they were good. They were fast. I was looking forward to using the snazzy new editor to create our own formatting template. ReSharper seemed to be using less memory, felt snappier, it was lovely. </p>
<p>And then I launched the test runner.</p>
<p>And then I uninstalled 9.x and reinstalled 8.x.</p>
<p>And then I needed the latest version of DotMemory and was forced to reinstall 9.x. So I tried the test runner again, which inspired this post. [2]</p>
<p>So what&rsquo;s not to love about the test runner? It&rsquo;s faster and seems much more asynchronous. However, it gets quite confused about which tests to run, how to handle test cases and how to handle abstract unit-test base classes.</p>
<p>Just like 6.x, ReSharper 9.x can&rsquo;t seem to keep track of which assemblies need to be built based on changes made to the code and which test(s) the user would like to run.</p>
<p><span style="width: 164px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3107/abstract_tests_in_resharper_9_test_runner.png"><img src="https://www.earthli.com/data/news/attachments/entry/3107/abstract_tests_in_resharper_9_test_runner_tn.png" alt=" " style="width: 164px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3107/abstract_tests_in_resharper_9_test_runner.png">Abstract tests cannot be executed</a></span></span><span style="width: 119px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3107/real_tests_in_resharper_9_test_runner.png"><img src="https://www.earthli.com/data/news/attachments/entry/3107/real_tests_in_resharper_9_test_runner_tn.png" alt=" " style="width: 119px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3107/real_tests_in_resharper_9_test_runner.png">Here are the concrete test instances</a></span></span></p>
<p><span class="clear-both"></span>To be fair, we have some abstract base classes in our unit fixtures. For example, we define all ORM query tests in multiple abstract test-fixtures and then create concrete descendants that run those tests for each of our supported databases. If I make a change to a common assembly and run the tests for PostgreSql, then I expect—at the very least—that the base assembly and the PostgreSql test assemblies will be rebuilt. 9.x isn&rsquo;t so good at that yet, forcing you to &ldquo;Rebuild All&rdquo;—something that I&rsquo;d no longer had to do with 8.2.x.</p>
<h2>TestCases and the Unit Test Explorer</h2><p><span class="clear-both"></span>It&rsquo;s the same with <code>TestCases</code>: whereas 8.x was able to reliably show changes and to make sure that the latest version was run, 9.x suffers from the same issue that 6.x and 7.x had: sometimes the test is shown as a single node without children and sometimes it&rsquo;s shown with the wrong children. Running these tests results in a spinning cursor that never ends. You have to manually abort the test-run, rebuild all, reload the runner with the newly generated tests from the explorer and try again. This is a gigantic pain in the ass compared to 8.x, which just showed the right tests—if not in the runner, then at-least very reliably in the explorer.</p>
<p><span style="width: 65px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3107/unit_test_explorer_in_resharper_9_test_runner.png"><img src="https://www.earthli.com/data/news/attachments/entry/3107/unit_test_explorer_in_resharper_9_test_runner_tn.png" alt=" " style="width: 65px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3107/unit_test_explorer_in_resharper_9_test_runner.png">Huge scrollbar in the unit-test explorer</a></span></span><span style="width: 81px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3107/unit_test_explorer_in_resharper_9_test_runner_is_crazy.png"><img src="https://www.earthli.com/data/news/attachments/entry/3107/unit_test_explorer_in_resharper_9_test_runner_is_crazy_tn.png" alt=" " style="width: 81px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3107/unit_test_explorer_in_resharper_9_test_runner_is_crazy.png">The unit-test explorer likes to expand everything</a></span></span></p>
<p>And the explorer in 9.x! It&rsquo;s a hyperactive, overly sensitive, eager-to-please puppy that reloads, refreshes, expands nodes and scrolls around—all seemingly with a mind of its own! Tests wink in and out of existence, groups expand seemingly at random, the scrollbar extends and extends and extends to accommodate all of the wonderful things that the unit-test explorer wants you to see—<em>needs for you to see</em>. Again, it&rsquo;s possible that this is due to our abstract test fixtures, but this is new to 9.x. 8.2.x is perfectly capable of displaying our tests in a far less effusive and frankly hyperactive manner.</p>
<p><span class="clear-both"></span></p>
<h2>One last thing: output-formatting</h2><p>Even the output formatting has changed in 9.x, expanding all CR/LF pairs from single-spacing to double-spacing. It&rsquo;s not a deal-breaker, but it&rsquo;s annoying: copying text is harder, reading stack traces is harder. How could no one have noticed this in testing?</p>
<p><span style="width: 200px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3107/output_formatting_in_resharper_9_test_runner.png"><img src="https://www.earthli.com/data/news/attachments/entry/3107/output_formatting_in_resharper_9_test_runner_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3107/output_formatting_in_resharper_9_test_runner.png">Output formatting is double-spaced</a></span></span></p>
<h2>Conclusion</h2><p>The install/uninstall process is painless and supports jumping back and forth between versions quite well, so I&rsquo;ll keep trying new versions of 9.x until the test runner is as good as the one in 8.2.x is. For now, I&rsquo;m back on 8.2.3. Stay tuned.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3107_1_body" class="footnote-number">[1]</span> <p>In no particular order, we have used or are using:</p>
<ul>
<li>DotMemory</li>
<li>DotTrace</li>
<li>DotPeek</li>
<li>DotCover</li>
<li>TeamCity</li>
<li>PHPStorm</li>
<li>WebStorm</li>
<li>PyCharm</li></ul></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3107_2_body" class="footnote-number">[2]</span> Although I was unable to install DotMemory without upgrading to ReSharper 9.x, I <em>was</em> able to uninstall ReSharper 9.x afterwards and re-install ReSharper 8.x.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3064</guid>
    <title><![CDATA[The Road to Quino 2.0: Maintaining architecture with NDepend (part II)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3064</link>
    <pubDate>Sun, 16 Nov 2014 00:20:42 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">16. Nov 2014 00:20:42 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In the <a href="https://www.earthli.com/news/view_article.php?id=3058">previous article</a>, I explained how we were using NDepend to clean up dependencies and the architecture of our Quino framework. You have to start somewhere, so I started with the two base assemblies: Quino and Encodo. Encodo only has dependencies on standard .NET assemblies, so let&rsquo;s start with that one.</p>
<p>The first step in cleaning up the Encodo assembly is to remove dependencies on the Tools namespace. There seems to be some confusion as to what belongs in the Core namespace versus what belongs in the Tools namespace.</p>
<p>There are too many low-level classes and helpers in the Tools namespace. Just as a few examples, I moved the following classes from Tools to Core:</p>
<ul>
<li>BitTools</li>
<li>ByteTools</li>
<li>StringTools</li>
<li>EnumerableTools</li></ul><p>The names kind of speak for themselves: these classes clearly belong in a core component and not in a general collection of tools.</p>
<p>Now, how did I decide which elements to move to core? NDepend helped me visualize which classes are interdependent.</p>
<h2>Direct Dependencies</h2><p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3064/enumerable_tools_depends_on_string_tools.png"><img src="https://www.earthli.com/data/news/attachments/entry/3064/enumerable_tools_depends_on_string_tools_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3064/enumerable_tools_depends_on_string_tools.png">Enumerable tools depends on String Tools</a></span></span>We see that <code>EnumerableTools</code> depends on <code>StringTools</code>. I&rsquo;d just moved <code>EnumerableTools</code> to <code>Encodo.Core</code> to reduce dependence on <code>Encodo.Tools</code>. However, since <code>StringTools</code> is still in the <code>Tools</code> namespace, the dependency remains. This is how examining dependencies really helps clarify a design: it&rsquo;s now totally obvious that something as low-level as <code>StringTools</code> belongs in the <code>Encodo.Core</code> namespace and not in the <code>Encodo.Tools</code> namespace, which has everything but the kitchen sink in it.</p>
<p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3064/messagetools_and_encodo.tools.png"><img src="https://www.earthli.com/data/news/attachments/entry/3064/messagetools_and_encodo.tools_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3064/messagetools_and_encodo.tools.png">MessageTools and Encodo.Tools dependencies</a></span></span>Another example in the same vein is shown to the left, where we examine the dependencies of <code>MessageTools</code> on <code>Encodo.Tools</code>. The diagram explains that the colors correspond to the two dependency directions. [1]</p>
<p>We would like the <code>Encodo.Messages</code> namespace to be independent of the <code>Encodo.Tools</code> namespace, so we have to consider either (A) removing the references to <code>ExceptionTools</code> and <code>OperatingSystemTools</code> from <code>MessageTools</code> or (B) moving those two dependencies to the <code>Encodo.Core</code> namespace.</p>
<p>Choice (A) is unlikely while choice (B) beckons with the same logic as the example above: it&rsquo;s now obvious that tools like <code>ExceptionTools</code> and <code>OperatingSystemTools</code> belong in <code>Encodo.Core</code> rather than the kitchen-sink namespace.</p>
<h2>Indirect Dependencies</h2><p>Once you&rsquo;re done cleaning up your direct dependencies, you still can&rsquo;t just sit back on your laurels. Now, you&rsquo;re ready to get started looking at <em>indirect</em> dependencies. These are dependencies that involve more than just two namespaces that use each other directly. NDepend displays these as red bounding blocks. The documentation indicates that these are probably good component boundaries, assuming that the dependencies are architecturally valid.</p>
<p>NDepend can only show you information about your code but can&rsquo;t actually make the decisions for you. As we saw above, if you have what appear to be strange or unwanted dependencies, you have to decide how to fix them. In the cases above, it was obvious that certain code was just in the wrong namespace. In other cases, it may simply be a few bits of code are defined at too low a level.</p>
<h2>Improper use of namespaces</h2><p>For example, our standard practice for components is to put high-level concepts for the component at the <code>Encodo.&lt;ComponentName&gt;</code> namespace. Then we would use those elements from sub-namespaces, like <code>Encodo.&lt;ComponentName&gt;.Utils</code>. However, we also ended up placing types that then used that sub-namespace in the upper-level namespace, like <code>ComponentNameTools.SetUpEnvironment()</code> or something like that. The call to <code>SetUpEnvironment()</code> <em>references</em> the <code>Utils</code> namespace which, in turn, <code>references</code> the root namespace. This is a direct dependency, but if another namespace comes between, we have an indirect dependency.</p>
<p>This happens quite quickly for larger components, like <code>Encodo.Security</code>.</p>
<p>The screenshots below show a high-level snapshot of the indirect dependencies in the Encodo assembly and then also a detail view, with all sub-namespaces expanded. The detail view is much larger but shows you much more information about the exact nature of the cycle. When you select a red bounding box, another panel shows the full details and exact nature of the dependency.</p>
<p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3064/encodo_indirect_dependencies.png"><img src="https://www.earthli.com/data/news/attachments/entry/3064/encodo_indirect_dependencies_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3064/encodo_indirect_dependencies.png">Dependency Cycles in Encodo (Overview)</a></span></span><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3064/encodo_dependency_cycles.png"><img src="https://www.earthli.com/data/news/attachments/entry/3064/encodo_dependency_cycles_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3064/encodo_dependency_cycles.png">Dependency Cycles in Encodo (Detail)</a></span></span><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3064/encodo_dependency_cycles_dense_grid.png"><img src="https://www.earthli.com/data/news/attachments/entry/3064/encodo_dependency_cycles_dense_grid_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3064/encodo_dependency_cycles_dense_grid.png">Encodo Dependency Cycles (Dense detail)</a></span></span></p>
<p><span class="clear-both"></span></p>
<h2>Base Camp Two: base library <em>almost</em> cleaned up</h2><p><span class="clear-both"></span><span style="width: 200px; display: table" class=" align-right clear-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3064/core_and_others.png"><img src="https://www.earthli.com/data/news/attachments/entry/3064/core_and_others_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3064/core_and_others.png">App.Core.* and remaining dependencies</a></span></span><span style="width: 126px; display: table" class=" align-right clear-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3064/configuration_dependencies.png"><img src="https://www.earthli.com/data/news/attachments/entry/3064/configuration_dependencies_tn.png" alt=" " style="width: 126px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3064/configuration_dependencies.png">Configuration dependencies</a></span></span>After a bunch of work, I&rsquo;ve managed to reduce the dependencies to a set of interfaces that are clearly far too dependent on many subsystems.</p>
<ul>
<li><strong>ICoreConfiguration:</strong> references configuration options for optional subsystems like the software updater, the login, the incident reporter and more</li>
<li><strong>ICoreFeedback:</strong> references feedbacks for several optional processes, like software-update, logins and more</li>
<li><strong>ICoreApplication:</strong> references both the core configuration and feedback</li></ul><p>The white books for NDepend claim that <span class="quote-inline">&ldquo;[t]echnically speaking, the task of merging the source code of several assemblies into one is a relatively light one that takes just a few hours.&rdquo;</span> However, this assumes that the code has already been properly separated into non-interdependent namespaces that correspond to components. These components can then relatively easily be extracted to separate assemblies.</p>
<p>The issue that I have above with the Encodo assembly is a thornier one: the interfaces themselves embody a pattern that is inherently non-decoupling. I need to change how the configuration and feedback work completely in order to decouple this code.</p>
<p><span class="clear-both"></span></p>
<h2>Roadmap for startup and configuration</h2><p>To that end, I&rsquo;ve created an issue in the issue-tracker for Quino, <a href="https://secure.encodo.ch/jira/browse/QNO-4659">QNO-4659</a> [2], titled &ldquo;Re-examine how the configuration, feedback and application work together&rdquo;. The design of these components predates our introduction of a service locator, which means it&rsquo;s much more tightly coupled (as you can see above).</p>
<p>After some internal discussion, we&rsquo;ve decided to change the design of the Encodo and Quino library support for application-level configuration and state.</p>
<dl><dt class="field">Merge the <em>configuration</em> and <em>application</em></dt>
<dd>To date, the <em>configuration</em> has contained all of the information necessary to run an <em>application</em>. The configuration was more-or-less stateless and corresponded to the definition of an application, akin to how a <em>class</em> is the underlying stateless definition, while an <em>object</em> is an instance of that definition. In practice, though, we always use a single application per configuration and the distinction is irrelevant, for all practical purposes. This will simplify all referencing code, as we will no longer need to pass around an <code>IApplication&lt;TConfiguration, TFeedback&gt;</code>.</dd>
<dt class="field">Move the <em>feedback</em> to the service locator</dt>
<dd>Instead of treating the feedback like a first-class citizen, with a direct reference on the application, make consumers use the service locator to retrieve an instance. This will remove the remaining generic argument in the definition of <code>IApplication</code>, leaving us with a base interface that is free of generic arguments.</dd>
<dt class="field">Move specific configuration objects to the service locator</dt>
<dd><div class=" ">The specific sub-interfaces that introduce dependencies are as follows:<ul>
<li>IncidentReporter</li>
<li>SoftwareUpdater</li>
<li>CommandSetManager</li>
<li>LocationManager</li>
<li>ConnectionSettingsManager</li></ul><p>Any components that currently reference the properties on the <code>ICoreConfiguration</code> can use the service locator to retrieve an instance instead.</p>
</div></dd>
<dt class="field">Move specific settings to sub-objects</dt>
<dd><div class=" ">The configuration object is not only dependent on sub-objects, but is also overloaded with individual settings that are only used by very few specific sub-components. These will also be extracted into interfaces and moved into the service locator.<ul>
<li>ILoginConfiguration</li>
<li>ISoftwareUpdateConfiguration</li>
<li>IFileLogConfiguration</li></ul></div></dd>
</dl><p>As you can see, while NDepend is indispensable for <em>finding</em> dependencies, it can—along with a good refactoring tool (we use ReSharper)—really only help you clean up the low-hanging fruit. While I started out trying to split assemblies, I&rsquo;ve now been side-tracked into cleaning up an older and less–well-designed component—and that&rsquo;s a very good thing.</p>
<p>There are some gnarly knots that will feel nearly unsolvable—but with a good amount of planning, those can be re-designed as well. As I mentioned in the previous article, though, we can do so only because we&rsquo;re making a clean break from the 1.x version of Quino instead of trying to maintain backward compatibility.</p>
<p>It&rsquo;s worth it, though: the new design already looks much cleaner and is much more easily explained to new developers. Once that rewrite is finished, the Encodo assembly should be clean and I&rsquo;ll use NDepend to find good places to split up that rather large assembly into sensible sub-assemblies.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3064_1_body" class="footnote-number">[1]</span> There is a setting to turn off showing the green dependencies—where the row depends on the column—to make it easier to read the matrix. If you do that, though, you have to make sure to select the class from which you&rsquo;re trying to remove dependencies in the column. For example, if class <code>A</code> and <code>B</code> are interdependent, but <code>A</code> should not rely on <code>B</code>, you should make sure <code>A</code> is showing in the column. You can then examine dependencies on row <code>B</code>—and then remove them. This works very nicely with both direct and indirect dependencies.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3064_2_body" class="footnote-number">[2]</span> This link is to the Quino issue tracker, which requires a login.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3058</guid>
    <title><![CDATA[The Road to Quino 2.0: Maintaining architecture with NDepend (part I)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3058</link>
    <pubDate>Wed, 12 Nov 2014 22:23:25 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">12. Nov 2014 22:23:25 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <h2>Full disclosure</h2><p>A while back—this last spring, I believe—I downloaded <a href="http://www.ndepend.com">NDepend</a> to analyze code dependencies. The trial license is fourteen days; needless to say, I got only one afternoon in before I was distracted by other duties. That was enough, however, to convince me that it was worth the $375 to continue to clean up Quino with NDepend.</p>
<p>I decided to wait until I had more time before opening my wallet. In the meantime, however, Patrick Smacchia of NDepend approached me with a free license if I would write about my experiences using NDepend on Encodo&rsquo;s blog. I&rsquo;m happy to write about how I used the tool and what I think it does and doesn&rsquo;t do. [1]</p>
<h2>History &amp; Background</h2><p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3058/quino_first_commit.png"><img src="https://www.earthli.com/data/news/attachments/entry/3058/quino_first_commit_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3058/quino_first_commit.png">Quino&#039;s first commit</a></span></span>We started working on Quino in the fall of 2007. As you can see from the first commit, the library was super-small and comprised a single assembly.</p>
<p>Fast-forward seven years and Version 1.13 of Quino has 66 projects/assemblies. That&rsquo;s a lot of code and it was long past time to take a look a more <em>structured</em> look at how we&rsquo;d managed the architecture over the years.</p>
<p>I&rsquo;d already opened a branch in our Quino repository called <em>feature/dependencyChanges</em> and checked in some changes at the beginning of July. Those changes had come as a result of the first time I used NDepend to find a bunch of code that was in the wrong namespace or the wrong assembly, architecturally speaking. </p>
<h3>Sidebar: Keeping branches mergeable</h3><p>I wasn&rsquo;t able to continue using this branch, though, for the following reasons.</p>
<ol>
<li>I got the hang of NDepend relatively quickly and got a bit carried away. Using ReSharper, I was able to make a lot of changes and fixes in a relatively short amount of time.</li>
<li>I checked in all of these changes in one giant commit.</li>
<li>I did this all five months ago.</li>
<li>There have been hundreds of subsequent commits on the master branch, many of which also include global refactoring and cleanup.</li>
<li>As a result of the above, merging <em>master</em> into <em>feature/dependencyChanges</em> is more trouble than it&rsquo;s worth.</li></ol><h2>Release Methodology</h2><p>With each Quino change and release, we try our hardest to balance backward-compatibility with maintainability and effort. If it&rsquo;s easy enough to keep old functionality under an old name or interface, we do so. </p>
<p>We mark members and types obsolete so that users are given a warning in the compiler but can continue using the old code until they have time to upgrade. These obsolete members are removed in the next major or minor upgrade. </p>
<p>Developers who have not removed their references to obsolete members will at this point be greeted with compiler errors. In all cases, the user can find out from Quino&rsquo;s release notes how they should fix a warning or error.</p>
<p>The type of high-level changes that we have planned necessitate that we make a major version-upgrade, to Quino 2.0. In this version, we have decided not to maintain backward-compatibility in the code with <code>Obsolete</code> attributes. However, where we <em>do</em> make a breaking change—either by moving code to new or different assemblies or by changing namespaces—we want to maintain a usable change-log for customers who make the upgrade. The giant commit that I&rsquo;d made previously was not a good start.</p>
<h2>Take Two</h2><p>Since some of these changes will be quite drastic departures in structure, we want to come up with a plan to make merging from the <em>master</em> branch to the <em>feature/dependencyChanges</em> branch safer, quicker and all-around easier.</p>
<p>I want to include many of the changes I started in the <em>feature/dependencyChanges</em> branch, but would like to re-apply those changes in the following manner:</p>
<ul>
<li>Split the giant commit into several individual commits, each of which encapsulates exactly one change; smaller commits are <em>much</em> easier to merge</li>
<li>Document breaking changes in the release notes for Quino 2.0</li>
<li>Blog about/document the process of using NDepend to clean up Quino [2]</li></ul><p>So, now that I&rsquo;m ready to start cleaning up Quino for version 2.0, I&rsquo;ll re-apply the changes from the giant commit, but in smaller commits. At the same time, I&rsquo;ll use NDepend to find the architectural breaks that caused me to make those changes in the first place and document a bit of that process.</p>
<h2>Setting up the NDepend Project</h2><p>I created an NDepend project and attached it to my solution. Version 1.13 of Quino has 66 projects/assemblies, of which I chose the following &ldquo;core&rdquo; assemblies to analyze.</p>
<p><span style="width: 603px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3058/encodo_quino_core.png" alt=" " style="width: 603px"></span><span class="auto-content-caption">Initial assemblies</span></span></p>
<p>I can change this list at any time. There are a few ways to add assemblies. Unfortunately, the option to &ldquo;Add Assemblies from VS Solution(s)&rdquo; showed only 28 of the 66 projects in the Quino solution. I was unable to determine the logic that led to the other 38 projects not being shown. When I did select the projects I wanted from the list, the assemblies were loaded from unexpected directories. For example, it added a bunch of core assemblies (e.g. Encodo.Imaging) from the <code>src/tools/Quino.CodeGenerator/bin/</code> folder rather than the <code>src/libraries/Encodo.Imaging/bin</code> folder. I ended up just taking the references I was offered by NDepend and added references to <code>Encodo</code> and <code>Quino</code>, which it had not offered to add. [3]</p>
<h2>The NDepend Dashboard</h2><p>Let&rsquo;s take a look at the initial <em>NDepend Dashboard</em>.</p>
<p><span style="width: 642px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3058/encodo_quino_initial_dashboard.png"><img src="https://www.earthli.com/data/news/attachments/entry/3058/encodo_quino_initial_dashboard.png" alt=" " style="width: 642px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3058/encodo_quino_initial_dashboard.png">Initial NDepend Dashboard</a></span></span></p>
<p>There&rsquo;s a lot of detail here. The initial impression of NDepend can be a bit overwhelming, I supposed, but you have to remember the sheer amount of interdependent data that it shows. As you can see on the dashboard, not only are there a ton of metrics, but those metrics are also tracked on a time-axis. I only have one measurement so far.</p>
<p>Any assemblies not included in the NDepend project are considered to be &ldquo;third-party&rdquo; assemblies, so you can see external dependencies differently than internal ones. There is also support for importing test-coverage data, but I haven&rsquo;t tried that yet.</p>
<p>There are a ton of measurements in there, some of which interest me and others that don&rsquo;t, or with which I disagree. For example, over 1400 warnings are in the Quino* assemblies because the base namespace—Encodo.Quino—doesn&rsquo;t correspond to a file-system folder—it expects <em>Encodo/Quino</em>, but we use just <em>Quino</em>.</p>
<p>Another 200 warnings are to &ldquo;Avoid public methods not publicly visible&rdquo;, which generally means that we&rsquo;ve declared public methods on internal, protected or private classes. The blog post <a href="http://ericlippert.com/2014/09/15/internal-or-public/">Internal or public?</a> by <cite>Eric Lippert</cite> (<cite><a href="http://ericlippert.com/">Fabulous adventures in coding</a></cite>) covered this adequately and came to the same conclusion that we have: you actually <em>should</em> make methods public if they are public <em>within their scope</em>.</p>
<p>There are some <a href="http://www.ndepend.com/docs/white-books">White Books</a> about namespace and assembly dependencies that are worth reading if you&rsquo;re going to get serious about dependencies. There&rsquo;s a tip in there about turning off &ldquo;Copy Local&rdquo; on referenced assemblies to drastically increase compilation speed that we&rsquo;re going to look into.</p>
<h2>Dependencies and cycles</h2><p>One of the white books explains how to use namespaces for components and how to &ldquo;levelize&rdquo; an architecture. This means that the dependency graph is acyclic—that there are no dependency cycles and that there are <em>certainly</em> no direct interdependencies. The initial graphs from the Encodo and Quino libraries show that we have our work cut out for us.</p>
<p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3058/encodo_quino_dependency_matrix_simple.png"><img src="https://www.earthli.com/data/news/attachments/entry/3058/encodo_quino_dependency_matrix_simple_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3058/encodo_quino_dependency_matrix_simple.png">Encodo &amp; Quino Dependency Matrix</a></span></span><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3058/encodo_interdependencies.png"><img src="https://www.earthli.com/data/news/attachments/entry/3058/encodo_interdependencies_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3058/encodo_interdependencies.png">Encodo interdependencies</a></span></span><span style="width: 200px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3058/quino_interdependencies.png"><img src="https://www.earthli.com/data/news/attachments/entry/3058/quino_interdependencies_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3058/quino_interdependencies.png">Quino interdependencies</a></span></span></p>
<p><span class="clear-both"></span>The first matrix shows the high-level view of dependencies in the Encodo and Quino namespaces. Click the second and third to see some initial dependency issues within the Encodo and Quino assemblies.</p>
<p>That&rsquo;s as far as I&rsquo;ve gotten so far. Tune in next time for a look at how we managed to fix some of these dependency issues and how we use NDepend to track improvement over time.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3058_1_body" class="footnote-number">[1]</span> I believe that takes care of full disclosure.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3058_2_body" class="footnote-number">[2]</span> This is something I&rsquo;d neglected to do before. Documenting this process will help me set up a development process where we use NDepend more regularly—more than every seven years—and don&rsquo;t have to clean up so much code at once.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3058_3_body" class="footnote-number">[3]</span> After having read the recommendations in the NDepend White Book—<a href="http://www.ndepend.com/Res/NDependWhiteBook_Assembly.pdf">Partitioning code base through .NET assemblies and Visual Studio projects</a> (PDF)—it&rsquo;s clear why this happens: NDepend recommends using a single /bin folder for all projects in a solution.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3057</guid>
    <title><![CDATA[Optimizing compilation and execution for dynamic languages]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3057</link>
    <pubDate>Wed, 12 Nov 2014 22:14:18 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">12. Nov 2014 22:14:18 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">29. May 2025 23:49:58 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The long and very technical article <a href="https://www.webkit.org/blog/3362/introducing-the-webkit-ftl-jit/">Introducing the WebKit FTL JIT</a> by <cite>Filip Pizlo</cite> (<cite><a href="http://www.webkit.org/">Webkit Blog</a></cite>) provides a fascinating and in-depth look at how a modern execution engine optimizes code for a highly dynamic language like JavaScript.</p>
<p>To make a long story short: the compiler(s) and execution engine optimize by profiling and analyzing code and <em>lowering it</em> to runtimes of ever decreasing abstraction to run as the least dynamic version possible.</p>
<h2>A brief history lesson</h2><p>What does it mean to &ldquo;lower&rdquo; code? A programming language has a given level of abstraction and expressiveness. Generally, the more expressive it is, the more abstracted it is from code that can actually be run in hardware. A compiler transforms or translates from one language to another.</p>
<p>When people started programming machines, they used punch cards. Punch cards did not require any compilation because the programmer was directly speaking the language that the computer understood.</p>
<p>The first layer of abstraction that most of us—older programmers—encountered was assembly language, or assembler. Assembly code still has a more-or-less one-to-one correspondence between instructions and machine-language codes but there is a bit of abstraction in that there are identifiers and op-codes that are more human-readable.</p>
<p>Procedural languages introduced more types of statements like loops and conditions. At the same time, the syntax was abstracted further from assembler and machine code to make it easier to express more complex concepts in a more understandable manner.</p>
<p>At this point, the assembler (which assembled instructions into machine op-codes) became a compile which &ldquo;compiled&rdquo; a set of instructions from the more abstract language. A compiler made decisions about how to translate these concepts, and could make optimization decisions based on registers, volatility and other settings.</p>
<p>In time, we&rsquo;d graduated to functional, statically typed and/or object-oriented languages, with much higher levels of abstraction and much more sophisticated compilers.</p>
<p>Generally, a compiler still used assembly language as an intermediate format, which some may remember from their days working with C++ or Pascal compilers and debuggers. In fact, .NET languages are also compiled to <abbr>IL</abbr>—the &ldquo;Intermediate Language&rdquo;—which corresponds to the instruction set that the .NET runtime exposes. The runtime compiles IL to the underlying machine code for its processor, usually in a process called <abbr>JIT</abbr>—Just-In-Time compilation. That is, in .NET, you start with C#, for example, which the compiler transforms to IL, which is, in turn, transformed to assembler and then machine code by the .NET runtime.</p>
<h2>Static vs. Dynamic compilation</h2><p>A compiler and execution engine for a statically typed language can make assumptions about the types of variables. The set of possible types is known in advance and types can be checked very quickly in cases where it&rsquo;s even necessary. That is, the statically typed nature of the language allows the compiler to reason about a given program without making assumptions. Certain features of a program can be proven to be true. A runtime for a statically typed language can often avoid type checks entirely. It benefits from a significant performance boost without sacrificing any runtime safety.</p>
<p>The main characteristic of a dynamic language like JavaScript is that variables do not have a fixed type. Generated code must be ready for any eventuality and must be capable of highly dynamic dispatch. The generated code is highly virtualized. Such a runtime will execute much more slowly than a comparable statically compiled program.</p>
<h2>Profile-driven compilation</h2><p>Enter the profile-driven compiler, introduced in WebKit. From the article,</p>
<blockquote class="quote quote-block "><div>&ldquo;The only a priori assumption about web content that our engine makes is that past execution frequency of individual functions is a good predictor for those functions’ future execution frequency.&rdquo;</div></blockquote><p>Here a &ldquo;function&rdquo; corresponds to a particular overload of a set of instructions called with parameters with a specific set of types. That is, suppose a JavaScript function is declared with one parameter and is called once with a string and 100 times with an integer. WebKit considers this to be two function overloads and will (possibly) elect to optimize the second one because it is called much more frequently. The first overload will still handle all possible types, including strings. In this way, all possible code paths are still possible, but the most heavily used paths are more highly optimized.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;All of the performance is from the DFG’s type inference and LLVM’s low-level optimizing power. […]</p>
<p>&ldquo;Profile-driven compilation implies that we might invoke an optimizing compiler while the function is running and we may want to transfer the function’s execution into optimized code in the middle of a loop; to our knowledge the FTL is the first compiler to do on-stack-replacement for hot-loop transfer into LLVM-compiled code.&rdquo;</p>
</div></blockquote><p>Depending on the level of optimization, the code contains the following broad sections:</p>
<ul>
<li><strong>Original:</strong> code that corresponds to instructions written by the author</li>
<li><strong>Profiling:</strong> code to analyze which types actually appear in a given code path</li>
<li><strong>Switching:</strong> code to determine when a function has been executed often enough to warrant further optimization</li>
<li><strong>Bailout</strong> code to abandon an optimization level if any of the assumptions made at that level no longer apply</li></ul><p><span style="width: 615px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3057/ftl_pipeline.png" alt=" " style="width: 615px"></span><span class="auto-content-caption">FTL Pipeline</span></span></p>
<p>While WebKit has included some form of profile-driven compilation for quite some time, the upcoming version is the first to carry the same optimization to LLVM-generated machine code.</p>
<p>I recommend reading the <a href="https://www.webkit.org/blog/3362/introducing-the-webkit-ftl-jit/">whole article</a> if you&rsquo;re interested in more detail, such as how they avoided LLVM compiler performance issues and how they integrated this all with the garbage collector. It&rsquo;s really amazing how much that we take for granted the WebKit JS runtime treats as &ldquo;hot-swappable&rdquo;. The article is quite well-written and includes diagrams of the process and underlying systems.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3052</guid>
    <title><![CDATA[Quino v1.13.0: Schema migration, remoting, services and web apps]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3052</link>
    <pubDate>Fri, 31 Oct 2014 10:39:12 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">31. Oct 2014 10:39:12 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">1. Nov 2014 08:44:53 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The summary below describes major new features, items of note and breaking changes in <a href="http://encodo.com/en/quino.php">Quino</a>. The <a href="https://secure.encodo.ch/jira/secure/ReleaseNote.jspa?projectId=10006&amp;version=17404">full list of issues</a> is also available for those with access to the Encodo issue tracker.</p>
<h2>Highlights</h2><h3>Data &amp; Schema</h3><ul>
<li>Applications can now choose a <strong>base class</strong> for <strong>generated ORM objects</strong>. (<a href="https://secure.encodo.ch/jira/browse/QNO-3107">QNO-3107</a>)</li>
<li><strong>Data driver</strong>: made various bug fixes and improvements. (<a href="https://secure.encodo.ch/jira/browse/QNO-4538">QNO-4538</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4554">QNO-4554</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4551">QNO-4551</a>)</li>
<li>Improved schema migration for fields and constraint-violation messages under <strong>SQL Server</strong>. (<a href="https://secure.encodo.ch/jira/browse/QNO-4490">QNO-4490</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4111">QNO-4111</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4582">QNO-4582</a>)</li>
<li>Improved the <strong>console migrator</strong> and APIs, input queries and exit-code handling for console applications in general. Also changed the default command from [R]efresh to [S]how differences. (<a href="https://secure.encodo.ch/jira/browse/QNO-4649">QNO-4649</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4646">QNO-4646</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4648">QNO-4648</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4650">QNO-4650</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4651">QNO-4651</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4615">QNO-4615</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4645">QNO-4645</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4616">QNO-4616</a>)</li></ul><h3>Remoting &amp; services</h3><ul>
<li>Fixed several issues in the <strong>remoting</strong> driver (client and server parts). (<a href="https://secure.encodo.ch/jira/browse/QNO-4626">QNO-4626</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4630">QNO-4630</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4631">QNO-4631</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4388">QNO-4388</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4575">QNO-4575</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4629">QNO-4629</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4573">QNO-4573</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4625">QNO-4625</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4633">QNO-4633</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4575">QNO-4575</a>)</li>
<li>Added a runner for <strong>Windows services</strong> that allows debugging and shows logging output for applications that use the <code>CoreServiceBase</code>, which extends the standard .NET <code>ServiceBase</code>. The runner is available in the <code>Encodo.Service</code> assembly.</li></ul><h3>Web</h3><ul>
<li>Improved default and custom <strong>authentication</strong> in web applications and the remoting server. Also improved support for authorization for remote-method routes as well as MVC controllers.</li>
<li>Improved configuration, error-handling and stability of the <strong><code>HttpApplicationBase</code></strong>, especially in situations where the application fails to start. Error-page handling was also improved, including handling for <code>Windows Event Log</code> errors.</li>
<li>Improved appearance of the <strong>web-based schema migrator</strong>. (<a href="https://secure.encodo.ch/jira/browse/QNO-4559">QNO-4559</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4561">QNO-4561</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4563">QNO-4563</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4548">QNO-4548</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4487">QNO-4487</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4486">QNO-4486</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4488">QNO-4488</a>)</li></ul><h3>Winform</h3><ul>
<li><strong>Data-provider statistics</strong>: improved the WinForm-based statistics form. (<a href="https://secure.encodo.ch/jira/browse/QNO-4231">QNO-4231</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4545">QNO-4545</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4546">QNO-4546</a>)</li>
<li><strong>Standard forms</strong>: updated the standard WinForm about window and splash screen to use Encodo web-site CI. (<a href="https://secure.encodo.ch/jira/browse/QNO-4529">QNO-4529</a>)</li></ul><h3>System &amp; Tools</h3><ul>
<li>Removed the <strong>dependency</strong> on the <em>SmartWeakEvents</em> library from Quino. (<a href="https://secure.encodo.ch/jira/browse/QNO-4645">QNO-4645</a>); the Quino and Encodo assemblies now no longer have any external dependencies.</li>
<li><strong>Image handling</strong>: the Encodo and Quino libraries now use the Windows Imaging Components instead of System.Drawing. (<a href="https://secure.encodo.ch/jira/browse/QNO-4536">QNO-4536</a>)</li>
<li><strong>Window 8.1</strong>: fixed culture-handling for en-US and de-CH that is broken in Windows 8.1. (<a href="https://secure.encodo.ch/jira/browse/QNO-4534">QNO-4534</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4553">QNO-4553</a>)</li>
<li><strong>R# annotations</strong> have been added to the Encodo assembly. Tell R# to look in the <code>Encodo.Core</code> namespace to use annotations like <code>NotNull</code> and <code>CanBeNull</code> with parameters and results. (<a href="https://secure.encodo.ch/jira/browse/QNO-4508">QNO-4508</a>)</li>
<li><div class=" "><p><strong>Generated code</strong> now includes a property that returns a <code>ValueListObject</code> for each <code>enum</code> property in the metadata. For example, for a property named <code>State</code> of type <code>CoreState</code>, the generated code includes the former properties for the <code>enum</code> and the foreign key backing it, but now also includes the <code>ValueListObject</code> property. This new property provides easy access to the captions.</p>
<pre class=" "><code>public CoreState State { … }
<strong class="highlight">public ValueListObject StateObject { … }</strong>
public int? CoreStateIdId { … }</code></pre></div></li>
<li><div class=" "><p>Improved the <strong>nant fix</strong> command in the default build tools to fix the assembly name as well. The build tools are available in bin/tools/build. See the <code>src/demo/Demo.build</code> file for an example on how to use the Nant build scripts for your own solutions. To change the company name used by the &ldquo;fix&rdquo; command, for example, add the following task override:</p>
<pre class=" "><code>&lt;target name="fix.before"&gt;
  &lt;call target="fix.before.base"/&gt;
  &lt;property name="InfoCompanyName" value="Foobar Corporation"/&gt;
&lt;/target&gt;</code></pre></div></li>
<li>Fixed the implementation of <code>IntegrateRemotableMethods</code> to avoid a race condition with <strong>remote methods</strong>. Also improved the stability of the <code>DataProvider</code> statistics. (<a href="https://secure.encodo.ch/jira/browse/QNO-4599">QNO-4599</a>)</li></ul><p><span class="clear-both"></span></p>
<h2>Breaking changes</h2><ul>
<li>The generic argument <code>TRight</code> has been removed from all classes and interfaces in the <code>Encodo.Security.*</code> namespace. In order to fix this code, just remove the <code>int</code> generic parameter wherever it was used. For example, where before you used the interface <code>IUser&lt;int&gt;</code>, you should now use <code>IUser</code> (<a href="https://secure.encodo.ch/jira/browse/QNO-4576">QNO-4576</a>).</li>
<li>The overridable method <code>MetaAccessControl.DoGetAccessChecker()</code> has been renamed to <code>MetaAccessControl.GetAccessChecker()</code>.</li>
<li>Renamed the <code>Encodo.ServiceLocator.SimpleInjector.dll</code> to <code>Encodo.Services.SimpleInjector.dll</code> and <code>Quino.ServiceLocator.SimpleInjector.dll</code> to <code>Quino.Services.SimpleInjector.dll</code> Also changed the namespace <code>Quino.ServiceLocator</code> to <code>Encodo.Quino.Services</code>.</li>
<li>Renamed <code>HttpApplicationBase.StartMetaApplication()</code> to <code>CreateAndStartUpApplication()</code>.</li>
<li>Classes may no longer contain properties with names that conflict with properties of <code>IMetaReadable</code> (e.g. <code>Deleted</code>, <code>Persisted</code>). The model will no longer validate until the properties have been renamed and the code regenerated. (<a href="https://secure.encodo.ch/jira/browse/QNO-4185">QNO-4185</a>)</li>
<li>Removed <code>StandardIntRights</code> with integer constants and replaced it with <code>StandardRights</code> with string constants.</li>
<li>The <code>IAccessControl.Check()</code> and other related methods now accept a sequence of string rights rather than integers.</li>
<li><div class=" "><p><code>IMetaConfiguration.ConfigureSession()</code> has been deprecated. The method will still be called but may have undesired side-effects, depending on why it was overridden. The common use was to initialize a custom <code>AccessControl</code> for the session. Continuing to do so may overwrite the current user set by the default Winform startup. Instead, applications should use the <code>IDataSessionAccessControlFactory</code> and <code>IDataSessionFactory</code> to customize the data sessions and access controls returned for an application. In order to attach an access control, take care to only set your custom access control for sessions that correspond to your application model. [1]</p>
<pre class=" "><code>internal class JobVortexDataSessionAccessControlFactory : DataSessionAccessControlFactory
{
  public override IAccessControl CreateAccessControl(IDataSession session)
  {
    if (session.Application.Model.MetaId == JobVortexModelGenerator.ModelGuid)
    {
      return new JobVortexAccessControl(session);
    }

    return base.CreateAccessControl(session);
  }
}</code></pre></div></li>
<li><div class=" "><p>The default length of the <code>UserModule.User.PasswordHash</code> property has been increased from 100 characters to 1000. This default is more sensible for implementations that use much longer validations tokens instead of passwords. To avoid the schema migration, revert the change by setting the property default length back to 0 in your application model, after importing the security module, as shown below.</p>
<pre class=" "><code>var securityModule = Builder.Include&lt;SecurityModuleGenerator&gt;();      
securityModule.Elements.Classes.User.Properties[
  Encodo.Quino.Models.Security.Classes.SecurityUser.Fields.PasswordHash
].MaximumSize = 100;</code></pre></div></li>
<li><div class=" "><p><code>Application.Credentials</code> has been removed. To fix references, retrieve the <code>IUserCredentialsManager</code> from the service locator. For example, the following code returns the current user:</p>
<pre class=" "><code>Session.Application.Configuration.ServiceLocator.GetInstance&lt;IUserCredentialsManager&gt;().Current</code></pre><p>If your application uses the <code>WinformMetaConfigurationTools.IntegrateWinformPackages()</code> or <code>WinformDxMetaConfigurationTools.IntegrateWinformDxPackages()</code>, then the  <code>IDataSession.AccessControl.CurrentUser</code> will continue to be set correctly. If not, add the <code>SingleUserApplicationConfigurationPackage</code> to your application&rsquo;s configuration. The user in the remoting server will be set up correctly. Add the <code>WebApplicationConfigurationPackage</code> to web applications in order to ensure that the current user is set up correctly for each request. (<a href="https://secure.encodo.ch/jira/browse/QNO-4596">QNO-4596</a>)</p>
</div></li>
<li><code>IDataSession.SyncRoot</code> has been removed as it was no longer needed or used in Quino itself. Sessions should <em>not</em> be used in multiple threads, so there is no need for a <code>SyncRoot</code>. Code that uses it should be reworked to use a separate session for each thread.</li>
<li>Moved <code>IMetaApplication.CreateSession()</code> to an extension method. Add <code>Encodo.Quino.App</code> to the using clauses to fix any compile errors.</li>
<li>Removed <code>IMetaApplication.DataProvider</code>; use <code>IMetaApplication.Configuration.DataProvider</code> instead. (<a href="https://secure.encodo.ch/jira/browse/QNO-4604">QNO-4604</a>)</li>
<li>The schema migration API has been completely overhauled. <code>ISchemaChange</code> and descendents has been completely removed. <code>ISchemaAction</code> is no longer part of the external API, although it is still used internally. The <code>ISchemaChangeFactory</code> has been renamed to <code>ISchemaCommandFactory</code> and, instead of creating change objects, which are then applied directly, returns <code>ISchemaCommand</code> objects, which can be either executed or transformed in some other way. <code>IMigrateToolkit.GetActionFor()</code> has also been replace with <code>CreateCommands()</code>, which mirrors the rest of the API by returning a sequence of commands to address a given <code>ISchemaDifference</code>. This release still has some commands that cannot be transformed to pure SQL, but the goal is to be able to generate pure SQL for a schema migration. (<a href="https://secure.encodo.ch/jira/browse/QNO-993">QNO-993</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4579">QNO-4579</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4581">QNO-4581</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4588">4588</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4591">4591</a>, <a href="https://secure.encodo.ch/jira/browse/QNO-4594">QNO-4594</a>)</li>
<li><div class=" "><p><code>IMigrateSchemaAspect.Apply()</code> has been removed. All aspects will have to be updated to implement <code>GetCommands()</code> instead, or to use one of the available base classes, like <code>UpdateDataAspectBase</code> or <code>ConvertPropertyTypeSchemaAspect</code>. The following example shows how to use the <code>UpdateDataAspectBase</code> to customize migration for a renamed property.</p>
<pre class=" "><code>internal class ArchivedMigrationAspect : UpdateDataAspectBase
{
  public ArchivedMigrationAspect()
    : base("ArchivedMigrationAspect", DifferenceType.RenamedProperty, ChangePhase.Instead)
  {
  }

  protected override void UpdateData(IMigrateContext context, ISchemaDifference difference)
  {
    using (var session = context.CreateSession(difference))
    {
      session.ChangeAndSaveAll&lt;Project&gt;(UpdateArchivedFlag);
    }
  }

  private void UpdateArchivedFlag(Project obj)
  {
    obj.Archived = !obj.Archived;
  }
}</code></pre><p>The base aspects should cover most needs; if your functionality is completely customized, you can easily pass your previous implementation of <code>Apply()</code> to a <code>DelegateSchemaCommand</code> and return that from your implementation of <code>GetCommands()</code>. See the implementation of <code>UpdateDataAspectBase</code> for more examples. (<a href="https://secure.encodo.ch/jira/browse/QNO-4580">QNO-4580</a>)</p>
</div></li>
<li><code>MetaObjectIdEqualityComparer&lt;T&gt;</code> can no longer be constructed directly. Instead, use <code>MetaObjectIdEqualityComparer&lt;Project&gt;.Default</code>.</li>
<li>Renamed <code>MetaClipboardControlDx.UpdateColorSkinaware()</code> to <code>MetaClipboardControlDx.UpdateSkinAwareColors()</code>.</li>
<li><code>IMetaUnique.LogicalParent</code> has been moved to <code>IMetaBase</code>. Since <code>IMetaUnique</code> inherits from <code>IMetaBase</code>, it is unlikely that code is affected (unless reflection or some other direct means was used to reference the property). (<a href="https://secure.encodo.ch/jira/browse/QNO-4586">QNO-4586</a>)</li>
<li><code>IUntypedMessage</code> has been removed; the <code>AssociatedObject</code> formerly found there has been moved to <code>IMessage</code>.</li>
<li><code>ITypedMessage.AssociatedObject</code> has been renamed to <code>ITypedMessage.TypedAssociatedObject</code>. (<a href="https://secure.encodo.ch/jira/browse/QNO-4647">QNO-4647</a>)</li>
<li>Renamed <code>MetaObjectTools</code> to <code>MetaReadableTools</code>.</li>
<li>Redefined the protected methods <code>GenericObject.GetAsGuid()</code> and <code>GenericObject.GetAsGuidDefault</code> as extension methods in <code>MetaWritableTools</code>.</li>
<li><code>IMetaFeedback.CreateGlobalContext()</code> has been removed. Instead the <code>IGlobalContext</code> is created using the service locator.</li></ul><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3052_1_body" class="footnote-number">[1]</span> The schema migration creates a metadata model for your model—meta-metadata—and uses the Quino ORM to load data when importing a model from a database. If you aren&rsquo;t careful, as shown in the code example, then you&rsquo;ll attach your custom access control to the sessions created for the schema migration&rsquo;s data-access, which will more than likely fail when it tries to load user data from a table that does not exist in that model.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3049</guid>
    <title><![CDATA[Schema migration in Quino 1.13]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3049</link>
    <pubDate>Fri, 24 Oct 2014 12:26:25 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">24. Oct 2014 12:26:25 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>Quino is a metadata framework for .NET. It provides a means of defining an application-domain model in the form of metadata objects. Quino also provides many components and support libraries that work with that metadata to automate many services and functions. A few examples are an ORM, schema migration, automatically generated user interfaces and reporting tools.</p>
<h2>The schema-migration tool</h2><p>The component we&rsquo;re going to discuss is the automated schema-migration for databases. A question that recently came up with a customer was: what do all of the options mean in the console-based schema migrator?</p>
<p>Here&rsquo;s the menu you&rsquo;ll see in the console migrator:</p>
<pre class=" ">Advanced Options
(1) Show migration plan
(2) Show significant mappings
(3) Show significant mappings with unique ids
(4) Show all mappings
(5) Show all mappings with unique ids

Main Options
(R) Refresh status
(M) Migrate database
(C) Cancel</pre><p>The brief summary is:</p>
<ul>
<li>The only action that actually makes changes is (M)</li>
<li>Option (1) is the only advanced option you will every likely use; use this to show the changes that were detected</li></ul><p>The other advanced options are more for debugging the migration recommendation if something looks wrong. In order to understand what that means, we need to know what the migrator actually does.</p>
<p><span style="width: 603px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/3049/quino_schema_migration.png" alt=" " style="width: 603px"></span><span class="auto-content-caption">Schema migration overview</span></span></p>
<ol>
<li>Provide the application model as input</li>
<li>Import a model from the database as input</li>
<li>Generate a mapping between the two models</li>
<li>Create a migration plan to update the database to reflect the application model</li>
<li>Generate a list of commands that can be applied to the database to enact the plan</li>
<li>Execute the commands against the database</li></ol><p>The initial database-import and final command-generation parts of migration are very database-specific. The determination of differences is also partially database-specific (e.g. some databases do not allow certain features so there is no point in detecting a difference that cannot ever be repaired). The rest of the migration logic is database-independent.</p>
<h2>Gathering data for migration</h2><p>The migrator works with two models: the target model and a source model</p>
<ul>
<li>The target model is provided as part of the application and is usually loaded from a core assembly. The source model is imported from the database schema by the &ldquo;import handler&rdquo;</li></ul><p>Given these two models, the &ldquo;mapping builder&rdquo; creates a mapping. In the current implementation of Quino, there is no support for allowing the user to adjust mapping before a migration plan is built from it. However, it would be possible to allow the user to verify and possibly adjust the mapping. Experience has shown that this is not necessary. Anytime we thought we needed to adjust the mapping, the problem was instead that the target model had been configured incorrectly. That is, each time we had an unexpected mapping, it led us directly to a misconfiguration in the model.</p>
<p>The options to show mappings are used to debug exactly such situations. Before we talk about mapping, though, we should talk about what we mean by &ldquo;unique ids&rdquo;. Every schema-relevant bit of metadata in a Quino model is associated with a unique id, in the form of a Guid and called a &ldquo;MetaId&rdquo; in Quino.</p>
<h2>Importing a model from a database</h2><p>What happens during when the import handler generates a model?</p>
<p>The importer runs in two phases:</p>
<ol>
<li>Extract the &ldquo;raw model&rdquo; from the database schema</li>
<li>Enhance the &ldquo;raw model&rdquo; with data pulled from the application-specific Quino metadata table in the same database</li></ol><p>A Quino application named &ldquo;demo&rdquo; will have the following schema:</p>
<ul>
<li>All modeled tables are named &ldquo;demo__*&rdquo;</li>
<li>The metadata table is named &ldquo;demometadata__elementdescription&rdquo;</li></ul><p>The migrator reads the following information into a &ldquo;raw model&rdquo;</p>
<ul>
<li>Tables =&gt; MetaClasses</li>
<li>Fields/Columns =&gt; MetaProperties</li>
<li>Indexes =&gt; MetaIndexes</li>
<li>Foreign Keys =&gt; MetaPaths</li></ul><p>If there is no further information in the database, then the mapper will have to use the raw model only. If, however, the database was created or is being maintained by Quino, then there is additional information stored in the metadata table mentioned above. The importer <em>enhanced</em> the raw model with this information, in order to improve mapping and difference-recognition. The metadata table contains all of the Quino modeling information that is not reflected in a standard database schema (e.g. the aforementioned MetaId).</p>
<p>The data available in this table is currently:</p>
<ul>
<li><strong>SchemaIdentifier:</strong> the identifier used in the raw model/database schema</li>
<li>Identifier: the actual identifier of the metadata element that corresponds to the element identified by the <code>SchemaIdentifier</code></li>
<li><strong>MetaId:</strong> the unique id for the metadata element</li>
<li><strong>ObjectType:</strong> the type of metadata (one of: class, property, index, path, model)</li>
<li><strong>ParentMetaId:</strong> the unique id of the metadata element that is the logical parent of this one; only allowed to be empty for elements with ObjectType equal to &ldquo;model&rdquo;</li>
<li><strong>Data:</strong> Custom data associated with the element, as key/value pairs</li>
<li><strong>DataVersion:</strong> Identifies the format type of the &ldquo;Data&rdquo; element (1.0.0.0 corresponds to CSV)</li></ul><p>For each schema element in the raw model, the importer does the following:</p>
<ol>
<li>Looks up the data associated with that SchemaIdentifier and ObjectType (e.g. &ldquo;punchclock__person&rdquo; and &ldquo;class&rdquo;)</li>
<li>Updates the &ldquo;Identifier&rdquo;</li>
<li>Sets the &ldquo;MetaId&rdquo;</li>
<li>Loads the key/value pairs from the Data field and applies that data to the element</li></ol><h2>Generating a mapping</h2><p>At this point, the imported model is ready and we can create a mapping between it and the application model. The imported model is called the <em>source</em> model while the application model is called the <em>target</em> model because we&rsquo;re migrating the &ldquo;source&rdquo; to match the &ldquo;target&rdquo;.</p>
<p>We generate a mapping by iterating the target model:</p>
<ol>
<li>Find the corresponding schema element in the source model using MetaIds [1]</li>
<li>If an element can be found, create a mapping for those two elements</li>
<li>If no element can be found, create a mapping with the target element. This will cause the element to be <em>created</em> in the database.</li>
<li>For all elements in the source model that have no corresponding element in the target model, create a mapping with only the source element. This will cause the element to be <em>dropped</em> from the database.</li></ol><h2>Creating a migration plan</h2><p>The important decisions have already been made in the mapping phase. At this point, the migrator just generates a migration plan, which is a list of differences that must be addressed in order to update the database to match the target model.</p>
<ul>
<li><div>If the mapping has a source and target element<ul>
<li>Create a difference if the element has been <em>renamed</em></li>
<li>Create a difference if the element has been <em>altered</em> (e.g. a property has a different type or is now nullable; an index has new properties or is no longer unique; etc.)</li></ul></div>If the mapping has only a source, generate a difference that the element is <em>unneeded</em> and should be dropped.</li>
<li>If the mapping has only a target, generate a difference that the element is <em>missing</em> and should be created. </li></ul><p>This is the plan that is shown to the user by the various migration tools available with Quino. [2]</p>
<h2>The advanced console-migrator commands</h2><p>At this point, we can now understand what the advanced console-migrator commands  mean. <em>Significant mappings</em> are those mappings which correspond to a difference in the database (create, drop, rename or alter).</p>
<ul>
<li><strong>Show significant mappings</strong>: show significant mappings to see more detail about the names on each side</li>
<li><strong>Show significant mappings with unique ids</strong>: same as above, but also include the MetaIds for each side. Use this to debug when you suspect that you might have copy/pasted a MetaId incorrectly or inadvertently moved one.</li>
<li><strong>Show all mappings</strong>: Same detail level as the first option, but with <em>all</em> mappings, including those that are 100% matches</li>
<li><strong>Show all mappings with unique ids</strong>: same as above, but with MetaIds</li></ul><p>As already stated, the advanced options are really there to help a developer see why the migrator might be suggesting a change that doesn&rsquo;t correspond to expectations.</p>
<h2>Generating commands for the plan</h2><p>At this point, the migrator displays the list of differences that will be addressed by the migrator if the user chooses to proceed.</p>
<p>What happens when the user proceeds? The migrator generates database-specific commands that, when executed against the database, will modify the schema of the database. [3]</p>
<p>Commands are executed for different phases of the migration process. The phases are occasionally extended but currently comprise the following.</p>
<ul>
<li><strong>Initialize</strong>: perform any required initialization before doing anything to the schema</li>
<li><strong>DropConstraintsAndIndexes</strong>: drop all affected constraints and indexes that would otherwise prevent the desired modification of the elements involved in the migration.</li>
<li><strong>AddUpdateOrRenameSchema</strong>: Create new tables, columns and indexes and perform any necessary renaming. The changes in this phase are <em>non-destructive</em></li>
<li><strong>UpdateData</strong>: Perform any necessary data updates before any schema elements are removed. This is usually the phase in which custom application code is executed, to copy existing data from other tables and fields before they are dropped in the next phase. For example, if there is a new required 1–1 relation, the custom code might analyze the other data in the rows of that table to determine which value that row should have for the new foreign key.</li>
<li><strong>DropSchema</strong>: Drop any unneeded schema elements and data</li>
<li><strong>CreatePrimaryKeys</strong>: Create primary keys required by the schema. This includes both new primary keys as well as reestablishing primary keys that were temporarily dropped in the second phase.</li>
<li><strong>CreateConstraintsAndIndexes</strong>: Create constraints and indexes required by the schema. This includes both new constraints and indexes as well as reestablishing constraints and indexes that were temporarily dropped in the second phase.</li>
<li><strong>UpdateMetadata</strong>: Update the Quino-specific metadata table for the affected elements.</li></ul><h2>Executing the migration plan</h2><p>The commands are then executed and the results logged.</p>
<p>Afterward, the schema is imported again, to verify that there are no differences between the target model and the database. In some (always rarer) cases, there will still be differences, in which case, you can execute the new migration plan to repair those differences as well.</p>
<p>In development, this works remarkably well and often, without further intervention.</p>
<h2>Fixing failed migrations</h2><p>In some cases, there is data in the database that, while compatible with the current database schema, is incompatible with the updated schema. This usually happens when a new property or constraint is introduced. For example, a new required property is added that does not have a default value or a new unique index is added which existing data violates. </p>
<p>In these cases, there are two things that can be done:</p>
<ul>
<li>Either the database data is cleaned up in a way that makes it compatible with the target schema [4]</li>
<li>Or the developer must add custom logic to the metadata elements involved. This usually means that the developer must set a default value on a property. In rarer cases, the developer must attach logic to the affected metadata (e.g. the property or index that is causing the issue) that runs during schema migration to create new data or copy it from elsewhere in order to ensure that constraints are satisfied when they are reestablished at the end of the migration.</li></ul><p>In general, it&rsquo;s strongly advised to perform a migration against a replica of the true target database (e.g. a production database) in order to guarantee that all potential data situations have been anticipated with custom code, if necessary.</p>
<h2>Quino Migration versus EF Migrations</h2><p>It&rsquo;s important to point out that Quino&rsquo;s schema migration is considerably different from that employed by EF (which it picked up from the Active Migrations in Ruby, often used with Ruby on Rails). In those systems, the developer generates specific migrations to move from one model version to another. There is a clear notion of <em>upgrading</em> versus <em>downgrading</em>. Quino only recognizes <em>migrating</em> from an arbitrary model to another arbitrary model. This makes Quino&rsquo;s migration exceedingly friendly when moving between development branches, unlike EF, whose <a href="https://www.earthli.com/news/view_article.php?id=360">deficiencies in this area have been documented</a>.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3049_1_body" class="footnote-number">[1]</span> The default is to use <em>only</em> MetaIds. There is a mode in which identifiers are used as a fallback but it is used only for tools that import schemas that were not generated by Quino. Again, if the Quino metadata table hasn&rsquo;t been damaged, this strict form of mapping will work extremely well.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3049_2_body" class="footnote-number">[2]</span> The Winform and Web user interfaces for Quino both include built-in feedback for interacting with the schema migration. There are also two standalone tools to migrate database schemas: a Winform application and a Windows console application.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3049_3_body" class="footnote-number">[3]</span> The form of these commands is currently a mix of SQL and custom C# code. A future feature of the migration will be to have all commands available as SQL text so that the commands, instead of being executed directly, could be saved as a file and reviewed and executed by DBAs instead of letting the tool do it. We&rsquo;re not quite there yet, but proceeding nicely.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3049_4_body" class="footnote-number">[4]</span> This is generally what a developer does with his or her local database. The data contained therein can usually be more or less re-generated. If there is a conflict during migration, a developer can determine whether custom code is necessary or can sometimes determine that the data situation that causes the problem isn&rsquo;t something that comes up in production anyway and just remove the offending elements or data until the schema migration succeeds.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2978</guid>
    <title><![CDATA[EF Migrations troubleshooting]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2978</link>
    <pubDate>Mon, 20 Oct 2014 15:23:19 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Oct 2014 15:23:19 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <blockquote class="quote abstract "><div>The version of EF Migrations discussed in this article is 5.0.20627. The version of Quino is less relevant: the features discussed have been supported for years. For those in a hurry, there is a <a href="#tldr"><abbr>tl;dr</abbr> near the end of the article.</a></div></blockquote><p>We use Microsoft Entity Framework (EF) Migrations in one of our projects where we are unable to use Quino. We were initially happy to be able to automate database-schema changes. After using it for a while, we have decidedly mixed feelings.</p>
<p>As developers of our own schema migration for the Quino ORM, we&rsquo;re always on the lookout for new and better ideas to improve our own product. If we can&rsquo;t use Quino, we try to optimize our development process in each project to cause as little pain as possible.</p>
<h2>EF Migrations and branches</h2><p>We ran into problems in integrating EF Migrations into a development process that uses feature branches. As long as a developer stays on a given branch, there are no problems and EF functions relatively smoothly. [1]</p>
<p>However, if a developer switches to a different branch—with different migrations—EF Migrations is decidedly less helpful. It is, in fact, quite cryptic and blocks progress until you figure out what&rsquo;s going on.</p>
<p>Assume the following not-uncommon situation:</p>
<ul>
<li>The project is created in the <var>master</var> branch</li>
<li>The project has an initial migration <var>BASE</var></li>
<li>Developers A and B migrate their databases to <var>BASE</var></li>
<li>Developer A starts branch feature/A and includes migration <var>A</var> in her database</li>
<li>Developer B starts branch feature/B and includes migration <var>B</var> in his database</li></ul><p>We now have the situation in which two branches have different code <em>and</em> each has its own database schema. Switching from one branch to another with Git quickly and easily addresses the code differences. The database is, unfortunately, a different story.</p>
<p>Let&rsquo;s assume that developer A switches to branch feature/B to continue working there. The natural thing for A to do is to call &ldquo;update-database&rdquo; from the Package Manager Console [2]. This yields the following message—all-too-familiar to EF Migrations developers.</p>
<p><span style="width: 719px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/2978/ef_outdated_warning.png"><img src="https://www.earthli.com/data/news/attachments/entry/2978/ef_outdated_warning.png" alt=" " style="width: 719px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/2978/ef_outdated_warning.png">EF Migrations pending-changes warning</a></span></span></p>
<blockquote class="quote quote-block "><div>&ldquo;Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending changes to a code-based migration or enable automatic migration. […]&rdquo;</div></blockquote><p>This situation happens regularly when working with multiple branches. It&rsquo;s even possible to screw up a commit within a single branch, as illustrated in the following real-world example.</p>
<ul>
<li>Add two fields to an existing class</li>
<li>Generate a migration with code that adds two fields</li>
<li>Migrate the database</li>
<li>Realize that you don&rsquo;t need one of the two fields</li>
<li>Remove the C# code from the migration for that field</li>
<li>Tests run green</li>
<li>Commit everything and push it</li></ul><p>As far as you&rsquo;re concerned, you committed a single field to the model. When your co-worker runs that migration, it will be applied, but EF Migrations immediately thereafter complains that there are pending model changes to make. How can that be?</p>
<h2>Out-of-sync migrations != outdated database</h2><p>Just to focus, we&rsquo;re actually trying to get real work done, not necessarily debug EF Migrations. We want to answer the following questions:</p>
<ol>
<li>Why is EF Migrations having a problem updating the schema?</li>
<li>How do I quickly and reliably update my database to use the current schema if EF Migrations refuses to do it?</li></ol><p>The underlying reason why EF Migrations has problems is that it does not actually know what the schema of the database is. It doesn&rsquo;t read the schema from the database itself, but relies instead on a copy of the EF model that it stored in the database when it last performed a successful migration.</p>
<p>That copy of the model is also stored in the resource file generated for the migration. EF Migrations does this so that the migration includes information about which changes it needs to apply <em>and</em> about the model to which the change can be applied.</p>
<p>If the model stored in the database does not match the model stored with the migration that you&rsquo;re trying to apply, EF Migrations will not update the database. This is probably for the best, but leads us to the second question above: what do we have to do to get the database updated?</p>
<h2>Generate a migration for those &ldquo;pending changes&rdquo;</h2><p>The answer has already been hinted at above: we need to fix the model stored in the database for the last migration.</p>
<p>Let&rsquo;s take a look at the situation above in which your colleague downloaded what you thought was a clean commit.</p>
<p>From the Package Manager Console, run <code>add-migration foo</code> to scaffold a migration for the so-called &ldquo;pending changes&rdquo; that EF Migrations detected. That&rsquo;s interesting: EF Migrations thinks that your colleague should generate a migration to drop the column that you&rsquo;d only temporarily added but never checked in.</p>
<p>That is, the column isn&rsquo;t in his database, it&rsquo;s not in your database, but EF Migrations is convinced that it was once in the model and must be dropped.</p>
<p>How does EF Migrations even <em>know</em> about a column that you added to your own database but that you removed from the code before committing? What dark magic is this?</p>
<p>The answer is probably obvious: you <em>did</em> check in the change. The part that you can easily remove (the C# code) is only half of the migration. As mentioned above, the other part is a binary chunk stored in the resource file associated with each migration. These BLOBS are stored in the table <code>_MigrationHistory</code> table in the database. </p>
<p><span style="width: 216px; display: table" class=" align-left"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/2978/ef_migration_table.png" alt=" " style="width: 216px"></span><span class="auto-content-caption">DB Migration History table</span></span><span style="width: 332px; display: table" class=" align-left"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/2978/ef_binary_migration_data.png" alt=" " style="width: 332px"></span><span class="auto-content-caption">Migration data is stored as binary data</span></span></p>
<p><span class="clear-both"></span></p>
<h2><span id="tldr"></span>How to fix this problem and get back to work</h2><p>Here&rsquo;s the tl;dr: generate a &ldquo;fake&rdquo; migration, remove all of the C# code that would apply changes to the database (shown below) and execute <code>update-database</code> from the Package Manager Console.</p>
<p><span style="width: 341px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/2978/empty_migration.png" alt=" " style="width: 341px"></span><span class="auto-content-caption">An empty migration</span></span></p>
<p>This may look like it does exactly nothing. What actually happens is that it includes the current state of the EF model in the binary data for the <em>last</em> migration applied to the database (because you just applied it).</p>
<p>Once you&rsquo;ve applied the migration, <em>delete the files and remove them from the project</em>. This migration was only generated to fix your local database; do <em>not</em> commit it.</p>
<h2>Everything&rsquo;s cool now, right?</h2><p>Applying the fix above doesn&rsquo;t mean that you won&rsquo;t get database errors. If your database schema does <em>not</em> actually match the application model, EF will crash when it assumes fields or tables are available which do not exist in your database.</p>
<p>Sometimes, the only way to <em>really</em> clean up a damaged database—especially if you don&rsquo;t have the code for the migrations that were applied there [3]—is to remove the misapplied migrations from your database, undo all of the changes to the schema (manually, of course) and then generate a new migration that starts from a known good schema.</p>
<h2>Conclusions and comparison to Quino</h2><p>The obvious answer to the complaint &ldquo;it hurts when I do this&rdquo; is &ldquo;stop doing that&rdquo;. We would dearly love to avoid these EF Migrations-related issues but developing without any schema-migration support is even more unthinkable. </p>
<p>We&rsquo;d have to create upgrade scripts manually or would have to maintain scripts to generate a working development database and this in each branch. When branches are merged, the database-upgrade scripts have to be merged and tested as well. This would be a significant addition to our development process, has maintainability and quality issues and would probably slow us down even more.</p>
<p>And we&rsquo;re certainly not going to stop developing with branches, either.</p>
<p>We were hoping to avoid all of this pain by using EF Migrations. That EF Migrations makes us think of going back to manual schema migration is proof that it&rsquo;s not nearly as elegant a solution as our own Quino schema migration, which never gave us these problems.</p>
<p>Quino actually reads the schema in the database and compares that model directly against the current application model. The schema migrator generates a custom list of differences that map from the current schema to the desired schema and applies them. There is user intervention but it&rsquo;s hardly ever really required. This is an absolute godsend during development where we can freely switch between branches without any hassle. [4]</p>
<p>Quino doesn&rsquo;t recognize &ldquo;upgrade&rdquo; versus &ldquo;downgrade&rdquo; but instead applies &ldquo;changes&rdquo;. This paradigm has proven to be a much better fit for our agile, multi-branch style of development and lets us focus on our actual work rather than fighting with tools and libraries.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2978_1_body" class="footnote-number">[1]</span> EF Migrations as we use it is tightly bound to SQL Server. Just as one example, the inability of SQL Server to resolve cyclic cascade dependencies is in no way shielded by EF Migrations. Though the drawback originates in SQL Server, EF Migrations simply propagates it to the developer, even though it purports to provide an abstraction layer. Quino, on the other hand, does the heavy lifting of managing triggers to circumvent this limitation.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2978_2_body" class="footnote-number">[2]</span> As an aside, this is a spectacularly misleading name for a program feature. It should just be called &ldquo;Console&rdquo;.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2978_3_body" class="footnote-number">[3]</span> I haven&rsquo;t ever been able to use the <code>Downgrade</code> method that is generated with each migration, but perhaps someone with more experience could explain how to properly apply such a thing. If that doesn&rsquo;t work, the method outlined above is your only fallback.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2978_4_body" class="footnote-number">[4]</span> The aforementioned database-script maintenance or having only very discrete schema-update points or maintaining a database per branch and switching with configuration files or using database backups or any other schemes that end up distracting you from working.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3038</guid>
    <title><![CDATA[An introduction to PowerShell]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3038</link>
    <pubDate>Sun, 14 Sep 2014 16:09:45 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">14. Sep 2014 16:09:45 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>On Wednesday, August 27th, Tymon gave the rest of Encodo [1] a great introduction to PowerShell. I&rsquo;ve attached <a href="https://www.earthli.com/data/news/attachments/entry/3038/powershell_presentation_2014_08_27_tymon.zip">the presentation</a> but a lot of the content was in demonstrations on the command-line.</p>
<ol>
<li><a href="https://www.earthli.com/data/news/attachments/entry/3038/powershell_presentation_2014_08_27_tymon.zip" class="button">Download the presentation</a></li>
<li>Unzip to a local folder</li>
<li>Open <code>index.html</code> in a modern web browser (Chrome/Opera/Firefox work the best; IE has some rendering issues)</li></ol><p>We learned a few very interesting things:</p>
<ul>
<li>PowerShell is pre-installed on every modern Windows computer</li>
<li>You can PowerShell to other machines (almost like ssh!)</li>
<li>Windows developers should definitely learn how to use PowerShell.</li>
<li>Unix administrators who have to work on Windows machines should definitely learn how to use PowerShell. The underlying functionality of the operating system is much more discoverable via command line, <code>get-command</code> and <code>get-member</code> than the GUI.</li>
<li>You should definitely install ConEmu</li>
<li>When running ConEmu, make sure that you start a PowerShell session rather than the default Cmd session.</li>
<li>If you&rsquo;re writing scripts, you should definitely install and use the ISE, which is an IDE for PowerShell scripts with debugging, code-completion, lists of available commands and much better copy/paste than the standard console.</li>
<li>The <a href="https://www.earthli.com/data/news/attachments/entry/3038/powershell_langref_v3.pdf">PowerShell Language Reference v3</a> is a very useful and compact reference for beginners and even for more advanced users</li></ul><h2>ConEmu Setup</h2><p>The easiest way to integrate PowerShell into your workflow is to make it eminently accessible by installing ConEmu. ConEmu is a Windows command-line with a tabbed interface and offers a tremendous number of power-user settings and features. You can tweak it to your heart&rsquo;s content.</p>
<p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3038/conemu_in_quake_mode.png"><img src="https://www.earthli.com/data/news/attachments/entry/3038/conemu_in_quake_mode_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3038/conemu_in_quake_mode.png">ConEmu in Quake mode</a></span></span>I set mine up to look like the one that Tymon had in the demonstrations (shown on my desktop to the right).</p>
<ol>
<li>Download <a href="https://conemu.codeplex.com/">ConEmu</a> (<cite><a href="http://conemu.codeplex.com/">CodePlex</a></cite>); I installed version 140814, the most recent version marked as &ldquo;beta&rdquo;. There is no official release yet, but the software is quite mature.</li>
<li>Install it and run it. I didn&rsquo;t allow the <kbd>Win</kbd> + <kbd>Num</kbd> support because I know that I&rsquo;d never use it. YMMV and you can always change your choice from the preferences.</li>
<li>Show the settings to customize your installation. There are a ton of settings, so I listed the ones I changed below.</li>
<li><a href="https://www.earthli.com/data/news/attachments/entry/3038/conemu_settings_set_window_size.png"><img src="https://www.earthli.com/data/news/attachments/entry/3038/conemu_settings_set_window_size_tn.png" alt=" " class=" align-right clear-right"></a>Set the window size to something a bit larger than the standard settings, especially if you have a larger monitor. I use 120 × 40.</li>
<li><span class="clear-both"></span><a href="https://www.earthli.com/data/news/attachments/entry/3038/conemu_settings_color_scheme_powershell.png"><img src="https://www.earthli.com/data/news/attachments/entry/3038/conemu_settings_color_scheme_powershell_tn.png" alt=" " class=" align-right clear-right"></a>Choose the color scheme you want to use. I&rsquo;m using the standard PowerShell colors but a lot of popular, darker schemes are also available (e.g. Monokai).</li>
<li><span class="clear-both"></span><a href="https://www.earthli.com/data/news/attachments/entry/3038/conemu_settings_main_hotkey.png"><img src="https://www.earthli.com/data/news/attachments/entry/3038/conemu_settings_main_hotkey_tn.png" alt=" " class=" align-right clear-right"></a>Check out the hotkeys and set them up accordingly. The only key I plan on using is the one to show ConEmu. On the Swiss-German keyboard, it&rsquo;s <kbd>Ctrl</kbd> + <kbd>¨</kbd>.</li>
<li><span class="clear-both"></span><a href="https://www.earthli.com/data/news/attachments/entry/3038/conemu_settings_transparency.png"><img src="https://www.earthli.com/data/news/attachments/entry/3038/conemu_settings_transparency_tn.png" alt=" " class=" align-right clear-right"></a>The default console is not transparent, but there are those of us who enjoy a bit of transparency. Again, YMMV. I turned it on and left the slider at the default setting.</li>
<li><span class="clear-both"></span><a href="https://www.earthli.com/data/news/attachments/entry/3038/conemu_settings_quake_style_console.png"><img src="https://www.earthli.com/data/news/attachments/entry/3038/conemu_settings_quake_style_console_tn.png" alt=" " class=" align-right clear-right"></a>And, finally, you can turn on Quake-style console mode to make it drop down from the top of your primary monitor instead of appearing in a free-floating window.</li></ol><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3038_1_body" class="footnote-number">[1]</span> and one former Encodo employee—hey <a href="http://qontis.ch">Stephan</a>!</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3024</guid>
    <title><![CDATA[Should you return null or an empty list?]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3024</link>
    <pubDate>Fri, 08 Aug 2014 10:20:08 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Aug 2014 10:20:08 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I&rsquo;ve seen a bunch of articles addressing this topic of late, so I&rsquo;ve decided to weigh in.</p>
<p>The reason we frown on returning <code>null</code> from a method that returns a list or sequence is that we want to be able to freely use these sequences or lists with in a functional manner.</p>
<p>It seems to me that the proponents of &ldquo;no nulls&rdquo; are generally those who have a functional language at their disposal and the antagonists do not. In functional languages, we almost always return <em>sequences</em> instead of lists or arrays.</p>
<p>In C# and other functional languages, we want to be able to do this:</p>
<pre class=" "><code>var names = GetOpenItems()
  .Where(i =&gt; i.OverdueByTwoWeeks)
  .SelectMany(i =&gt; i.GetHistoricalAssignees()
    .Select(a =&gt; new { a.FirstName, a.LastName })
  );

foreach (var name in names)
{
  Console.WriteLine("{1}, {0}", name.FirstName, name.LastName);
}</code></pre><p>If either <code>GetHistoricalAssignees()</code> or <code>GetOpenItems()</code> <em>might</em> return <code>null</code>, then we&rsquo;d have to write the code above as follows instead:</p>
<pre class=" "><code><strong class="highlight">var openItems = </strong>GetOpenItems();
<strong class="highlight">if (openItems != null)
{</strong>
  var names = <strong class="highlight">openItems</strong>
  .Where(i =&gt; i.OverdueByTwoWeeks)
  .SelectMany(i =&gt; <strong class="highlight">(</strong>i.GetHistoricalAssignees() <strong class="highlight">?? Enumerable.Empty&lt;Person&gt;())</strong>
    .Select(a =&gt; new { a.FirstName, a.LastName })
  );

  foreach (var name in names)
  {
    Console.WriteLine("{1}, {0}", name.FirstName, name.LastName);
  }
<strong class="highlight">}</strong></code></pre><p>This seems like exactly the kind of code we&rsquo;d like to avoid writing, if possible. It&rsquo;s also the kind of code that calling clients are unlikely to write, which will lead to crashes with <code>NullReferenceExceptions</code>. As we&rsquo;ll see below, there are people that seem to think that&rsquo;s perfectly OK. I am not one of those people, but I digress.</p>
<p>The post, <a href="http://www.codeproject.com/Articles/794448/Is-it-Really-Better-to-Return-an-Empty-List-Instea">Is it Really Better to &lsquo;Return an Empty List Instead of null&rsquo;? / Part 1</a> by <cite>Christian Neumanns</cite> (<cite><a href="http://www.codeproject.com/">Code Project</a></cite>) serves as a good example of an article that seems to be providing information but is just trying to distract people into accepting it as a source of genuine information. He introduces his topic with the following vagueness.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;If we read through related questions in Stackoverflow and other forums, we can see that not all people agree. There are many different, sometimes truly opposite opinions. For example, the top rated answer in the Stackoverflow question Should functions return null or an empty object? (related to objects in general, not specifically to lists) tells us exactly the opposite:</p>
<p>&ldquo;Returning null is usually the best idea …&rdquo;</p>
</div></blockquote><p>The statement <span class="quote-inline">&ldquo;we can see that not all people agree&rdquo;</span> is a tautology. I would split the people into groups of those whose opinions we should care about and everyone else. The statement <span class="quote-inline">&ldquo;There are many different, sometimes truly opposite opinions&rdquo;</span> is also tautological, given the nature of the matter under discussion—namely, a question that can only be answered as &ldquo;yes&rdquo; or &ldquo;no&rdquo;. Such questions generally result in two camps with diametrically opposed opinions.</p>
<p>As the extremely long-winded pair of articles writes: sometimes you can&rsquo;t be sure of what an external API will return. That&rsquo;s correct. You have to protect against those with ugly, defensive code. But don&rsquo;t use that as an excuse to produce even <em>more</em> methods that may return <code>null</code>. Otherwise, you&rsquo;re just part of the problem.</p>
<p>The second article <a href="http://www.codeproject.com/Articles/797453/Is-it-Really-Better-to-Return-an-Empty-List-Inst">Is it Really Better to &lsquo;Return an Empty List Instead of null&rsquo;? − Part 2</a> by <cite>Christian Neumanns</cite> (<cite><a href="http://www.codeproject.com/">Code Project</a></cite>) includes many more examples.</p>
<p>I just don&rsquo;t know what to say about people that write things like <span class="quote-inline">&ldquo;Bugs that cause NullPointerExceptions are usually easy to debug because the cause and effect are short-distanced in space (i.e. location in source code) and time.&rdquo;</span> While this is kind of true, it&rsquo;s also even more true that you can&rsquo;t tell the difference between such an exception being caused by a savvy programmer who&rsquo;s using it to his advantage and a non-savvy programmer whose code is buggy as hell.</p>
<p>He has a ton of examples that try to distinguish between a method that returns an empty sequence being different from a method that cannot properly answer a question. This is a concern and a very real distinction to make, but the answer is not to return <code>null</code> to indicate nonsensical input. The answer is to <em>throw an exception</em>.</p>
<p>The method providing the sequence should not be making decisions about whether an empty sequence is acceptable for the caller. For sequences that cannot logically be empty, the method should throw an exception instead of returning null to indicate &ldquo;something went wrong&rdquo;.</p>
<p>A caller may impart semantic meaning to an empty result and also throw an exception (as in his example with a cycling team that has no members). If the display of such a sequence on a web page is incorrect, then that is the fault of the caller, not of the provider of the sequence.</p>
<ul>
<li>If data is not yet available, but should be, throw an exception</li>
<li>If data is not available but the provider isn&rsquo;t qualified to decide, return an empty sequence</li>
<li>If the caller receives an empty sequence and knows that it should not be empty, then it is responsible for indicating an error.</li></ul><p>That there exists calling code that makes assumptions about return values that are incorrect is no reason to start returning values that will make calling code crash with a <code>NullPointerException</code>.</p>
<p>All of his examples are similar: he tries to make the pure-data call to retrieve a sequence of elements simultaneously validate some business logic. That&rsquo;s not a good idea. If this is really necessary, then the validity check should go in another method.</p>
<p>The example he cites for getting the amount from a list of PriceComponents is exactly why most aggregation functions in .NET throw an exception when the input sequence is empty. But that&rsquo;s a much better way of handling it—with a precise exception—than by returning <code>null</code> to try to force an exception somewhere in the calling code.</p>
<p>But the upshot for me is: I am not going to write code that, when I call it, forces me to litter other code with null-checks. That&rsquo;s just ridiculous.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3006</guid>
    <title><![CDATA[Optimizing data access for high-latency networks: part IV]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3006</link>
    <pubDate>Fri, 08 Aug 2014 10:20:05 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Aug 2014 10:20:05 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3006/sample_calendar.png"><img src="https://www.earthli.com/data/news/attachments/entry/3006/sample_calendar_tn.png" alt=" " class=" align-left"></a>In the <a href="https://www.earthli.com/news/view_article.php?id=3005">previous</a> <a href="https://www.earthli.com/news/view_article.php?id=3004"> two articles</a>, we managed to  reduce the number of queries executed when opening the calendar of Encodo&rsquo;s time-tracking product Punchclock from one very slow query per person to a single very fast query. </p>
<p>Because we&rsquo;re talking about latency in these articles, we&rsquo;d also like to clear away a few other queries that aren&rsquo;t related to time entries but are still wasting time.</p>
<h2>Lazy-loading unneeded values</h2><p>In particular, the queries that &ldquo;Load values&rdquo; for person objects look quite suspicious. These queries don&rsquo;t take a lot of time to execute but they will definitely degrade performance in high-latency networks. [1]</p>
<p><span style="width: 771px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3006/person_queries_are_likely_harmless.png"><img src="https://www.earthli.com/data/news/attachments/entry/3006/person_queries_are_likely_harmless.png" alt=" " style="width: 771px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3006/person_queries_are_likely_harmless.png">Lazy-loads for people are very fast queries</a></span></span></p>
<p>As we did before, we can click on one of these queries to show the query that&rsquo;s being loaded. In the screenshot below, we see that the person&rsquo;s picture is being loaded for each person in the drop-down list.</p>
<p><span style="width: 795px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3006/person_picture_queries.png"><img src="https://www.earthli.com/data/news/attachments/entry/3006/person_picture_queries.png" alt=" " style="width: 795px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3006/person_picture_queries.png">Lazy-loading pictures</a></span></span></p>
<p>We&rsquo;re not showing pictures in the drop-down list, though, so this is an extravagant waste of time. On a LAN, we hardly notice how wasteful we are with queries; on a WAN, the product will feel…sluggish.</p>
<h2>What is a load-group?</h2><p>In order to understand the cause of these queries, you must first know that Quino allows a developer to put metadata properties into different <em>load-groups</em>. A load-group has the following behavior: If the value for a property in a load-group is requested on an object, the values for all of the properties in the load-group are retrieved with a single query and set on that object.</p>
<p>The default load-group of an object&rsquo;s metadata determine the values that are initially retrieved and applied to objects materialized by the ORM.</p>
<p>The metadata for a person puts the &ldquo;picture&rdquo; property of a person into a separate load-group so that the value is not loaded by default when people objects are loaded from the data driver. This is a good balance because business logic will avoid downloading a lot of unwanted picture data by default.</p>
<p>Business logic that needs the pictures can either explicitly include the picture in the query or let the value be lazy-loaded by the ORM when it is accessed. The proper solution depends on the situation.</p>
<h2>Lazy-loaded property values</h2><p>As before, we can check the stack trace of the query to figure out which application component is triggering the call. In this case, the culprit is the binding list that we are using to attach the list of people to the drop-down control.</p>
<p>The binding list binds the values for all of the properties in a metaclass (e.g. &ldquo;person&rdquo;), triggering a lazy load when it accesses the &ldquo;picture&rdquo; property. To avoid the lazy-load, we can create a <em>wrapper</em> of the default metadata for a person and remove/hide the property so that the binding list will no longer access it.</p>
<p>This is quite easy [2], as shown in the code below.</p>
<pre class=" "><code>var personMetaClass = new WrapMetaClass(Person.Metadata);
personMetaClass.Properties.Remove(Person.MetaProperties.Picture);
var query = new Query(personMetaClass);</code></pre><p>With this simple fix, the binding list no longer knows about the picture property, doesn&rsquo;t retrieve values for that property and therefore no longer triggers any queries to lazily load the pictures from the database for each person object.</p>
<p>The screenshot of the statistics window below shows up that we were successful. We have two main queries: one for the list of people to show in the dropdown control and one for the time entries to show in the calendar.</p>
<p><span style="width: 793px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3006/no_more_loading_pictures_for_people.png"><img src="https://www.earthli.com/data/news/attachments/entry/3006/no_more_loading_pictures_for_people.png" alt=" " style="width: 793px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3006/no_more_loading_pictures_for_people.png">Just a single query for person data</a></span></span></p>
<h2>Final version</h2><p>For completeness, here&rsquo;s the code that Punchclock is using in the current version of Quino (1.11).</p>
<pre class=" "><code>var personMetaClass = new WrapMetaClass(Person.Metadata);
personMetaClass.Properties.Remove(Person.MetaProperties.Picture);

var accessToolkit = new PostgreSqlMetaDatabase().AccessToolkit;

var query = new Query(personMetaClass);
query.CustomCommandText = new CustomCommandText();
query.CustomCommandText.SetSection(
  CommandTextSections.Where, 
  CommandTextAction.Replace,
  string.Format(
    "EXISTS (SELECT id FROM {0} WHERE {1} = {2})", 
    accessToolkit.GetName(TimeEntry.Metadata), 
    accessToolkit.GetField(TimeEntry.MetaProperties.PersonId), 
    accessToolkit.GetField(Person.MetaProperties.Id)
  )&gt;
);
var people = Session.GetList&lt;Person&gt;(query);</code></pre><h2>Future, improved version</h2><p>Once we fix the but in the <code>WhereExists</code> join type mentioned in the previous article and add the fluent methods for constructing wrappers mentioned in the footnote below, the code will be as follows:</p>
<pre class=" "><code>var personMetaClass = 
  Person.Metadata.
  Wrap().
  RemoveProperty(Person.MetaProperties.Picture);

var accessToolkit = new PostgreSqlMetaDatabase().AccessToolkit;

var people = 
  Session.GetList&lt;Person&gt;(
    new Query(personMetaClass).
    Join(Person.MetaRelations.TimeEntries, JoinType.WhereExists).
    Query
  );</code></pre><p>This concludes our investigation into performance issues with Quino and Punchclock.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3006_1_body" class="footnote-number">[1]</span> <p>You may have noticed that these calls to &ldquo;load values&rdquo; are technically lazy-loaded but don&rsquo;t seem to be marked as such in the screenshots. This was a bug in the statistics viewer that I discovered and addressed while writing this article.</p>
<p><span style="width: 468px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3006/load_values_are_now_lazy_loads.png"><img src="https://www.earthli.com/data/news/attachments/entry/3006/load_values_are_now_lazy_loads.png" alt=" " style="width: 468px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3006/load_values_are_now_lazy_loads.png">Calls to &#039;load values&#039; now marked as lazy loads</a></span></span></p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3006_2_body" class="footnote-number">[2]</span> <p>This is a rather old API and hasn&rsquo;t been touched with the &ldquo;fluent&rdquo; wand that we&rsquo;ve applied in other parts of the Quino API. A nicer way of writing it would be to create an extension methods called <code>Wrap()</code> and <code>RemoveProperty</code> that return the wrapper class, like so:</p>
<pre class=" "><code>var personMetaClass = 
  Person.Metadata.
  Wrap().
  RemoveProperty(Person.MetaProperties.Picture);

var query = new Query(personMetaClass);</code></pre><p>But that will have to wait for a future version of Quino.</p>
</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3005</guid>
    <title><![CDATA[Optimizing data access for high-latency networks: part III]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3005</link>
    <pubDate>Fri, 04 Jul 2014 09:09:05 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">4. Jul 2014 09:09:05 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3005/sample_calendar.png"><img src="https://www.earthli.com/data/news/attachments/entry/3005/sample_calendar_tn.png" alt=" " class=" align-left"></a>In the <a href="https://www.earthli.com/news/view_article.php?id=3004">previous article</a>, we partially addressed a performance problem in the calendar of Encodo&rsquo;s time-tracking product, Punchclock. While we managed to drastically reduce the amount of time taken by each query (&gt;95% time saved), we were still executing more queries than strictly necessary.</p>
<p>The query that we&rsquo;re trying to optimized further is shown below.</p>
<p><span class="clear-both"></span></p>
<pre class=" "><code>var people =
  Session.GetList&lt;Person&gt;().
  Where(p =&gt; Session.GetCount(p.TimeEntries.Query) &gt; 0).
  ToList();</code></pre><p>This query executes one query to get all the people and then one query per person to get the number of time entries per person. Each of these queries by itself is very fast. High latency will cause them to be slow. In order to optimize further, there&rsquo;s really nothing for it but to reduce the number of queries being executed.</p>
<p>Let&rsquo;s think back to what we&rsquo;re actually trying to accomplish: We want to get all people who have at least one time entry. Can&rsquo;t we get the database to do that for us? Some join or existence check or something? How about the code below?</p>
<pre class=" "><code>var people = 
  Session.GetList&lt;Person&gt;(
    Session.CreateQuery&lt;Person&gt;().
    Join(Person.MetaRelations.TimeEntries, JoinType.WhereExists).
    Query
  );</code></pre><p>What&rsquo;s happening in the code above? We&rsquo;re still getting a list of people but, instead of manipulating the related TimeEntries for each person <em>locally</em>, we&rsquo;re joining the TimeEntries relation with the Quino query <code>Join()</code> method and changing the join type from the default <code>All</code> to the restrictive <code>WhereExists</code>. This sounds like exactly what we want to happen! There is no local evaluation or manipulation with Linq and, with luck, Quino will be able to map this to a single query on the database.</p>
<p>This is the best possible query: it&rsquo;s purely declarative and will be executed as efficiently as the back-end knows how.</p>
<p>There&rsquo;s just one problem: the <code>WhereExists</code> join type is broken in Quino 1.11.</p>
<p>Never fear, though! We can still get it to work, but we&rsquo;ll have to do a bit of work until the bug is fixed in Quino 1.12. The code below builds on lessons learned in the earlier article, <a href="https://www.earthli.com/news/view_article.php?id=2987">Mixing your own SQL into Quino queries: part 2 of 2</a> to use custom query text to create the restriction instead of letting Quino do it.</p>
<pre class=" "><code>var accessToolkit = new PostgreSqlMetaDatabase().AccessToolkit;

var query = Session.CreateQuery&lt;Person&gt;();
query.CustomCommandText = new CustomCommandText();
query.CustomCommandText.SetSection(
  CommandTextSections.Where, 
  CommandTextAction.Replace,
  string.Format(
    "EXISTS (SELECT id FROM {0} WHERE {1} = {2})", 
    accessToolkit.GetName(TimeEntry.Metadata), 
    accessToolkit.GetField(TimeEntry.MetaProperties.PersonId), 
    accessToolkit.GetField(Person.MetaProperties.Id)
  )
);
var people = Session.GetList&lt;Person&gt;(query);</code></pre><p>A look at the statistics is very encouraging:</p>
<p><span style="width: 771px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3005/one_load_apiece_for_people_and_time_entries.png"><img src="https://www.earthli.com/data/news/attachments/entry/3005/one_load_apiece_for_people_and_time_entries.png" alt=" " style="width: 771px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3005/one_load_apiece_for_people_and_time_entries.png">One query for people; one for time-entries</a></span></span></p>
<p>We&rsquo;re down to one 29ms query for the people and an even quicker query for all the relevant time entries. [1] We can see our query text appears embedded in the SQL generated by Quino, just as we expected.</p>
<p>There are a few other security-related queries that execute very quickly and hardly need optimization.</p>
<p>We&rsquo;ve come much farther in this article and we&rsquo;re almost done. In the next article, we&rsquo;ll quickly clean up a few other queries that are showing up in the statistics and that have been nagging us since the beginning.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3005_1_body" class="footnote-number">[1]</span> The time-entry query is not representative because my testing data set didn&rsquo;t include time entries for the current day and I was too lazy to page around to older data.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3004</guid>
    <title><![CDATA[Optimizing data access for high-latency networks II]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3004</link>
    <pubDate>Fri, 27 Jun 2014 10:07:40 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">27. Jun 2014 10:07:40 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3004/sample_calendar.png"><img src="https://www.earthli.com/data/news/attachments/entry/3004/sample_calendar_tn.png" alt=" " class=" align-left"></a>In the <a href="https://www.earthli.com/news/view_article.php?id=3003">previous article</a>, we discussed a performance problem in the calendar of Encodo&rsquo;s time-tracking product, Punchclock.<br>
 <br>
Instead of guessing at the problem, we profiled the application using the database-statistics window available to all Quino applications. [1] We quickly discovered that most of the slowdown stems from the relatively innocuous line of code shown below.</p>
<p><span class="clear-both"></span></p>
<pre class=" "><code>var people = 
  Session.GetList&lt;Person&gt;().
  Where(p =&gt; p.TimeEntries.Any()).
  ToList();</code></pre><h2>First things first: what does the code do?</h2><p>Before doing anything else, we should establish what the code does. Logically, it retrieves a list of people in the database who have recorded at least one time entry.</p>
<p>The first question we should ask at this point is: does the application even need to do this? The answer in this case is &lsquo;yes&rsquo;. The calendar includes a drop-down control that lets the user switch between the calendars for different users. This query returns the people to show in this drop-down control.</p>
<p>With the intent and usefulness of the code established, let&rsquo;s dissect <em>how</em> it is accomplishing the task.</p>
<ol>
<li>The <code>Session.GetList&lt;Person&gt;()</code> portion retrieves a list of all people from the database</li>
<li>The <code>Where()</code> method is applied locally for each object in the list [2]</li>
<li>For a given person, the list of TimeEntries is accessed</li>
<li>This access triggers a lazy load of the list</li>
<li>The <code>Any()</code> method is applied to the full list of time entries</li>
<li>The <code>ToList()</code> method creates a list of all people who match the condition</li></ol><p>Though the line of code looks innocuous enough, it causes a huge number of objects to be retrieved, materialized and retained in memory—simply in order to check whether there is at least one object.</p>
<p>This is a real-world example of a performance problem that can happen to any developer. Instead of blaming the developer who wrote this line of code, its more important to stay vigilant to performance problems and to have tools available to quickly and easily find them.</p>
<h2>Stop creating all of the objects</h2><p>The first solution I came up with [3] was to stop creating objects that I didn&rsquo;t need. A good way of doing this and one that was covered in <a href="https://www.earthli.com/news/view_article.php?id=2951">Quino: partially-mapped queries</a> is to use <em>cursors</em> instead of <em>lists</em>. Instead of using the generated list <code>TimeEntries</code>, the following code retrieves a cursor on that list&rsquo;s query and materializes at most one object for the sub-query.</p>
<pre class=" "><code>var people = Session.GetList&lt;Person&gt;().Select(p =&gt;
{
  using (var cursor = Session.CreateCursor&lt;TimeEntry&gt;(p.TimeEntries.Query)) [4]
  {
    return cursor.Any();
  }
}).ToList();</code></pre><p>A check of the database statistics shows improvement, as shown below.</p>
<p><span style="width: 770px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3004/time_entry_queries_with_cursors.png"><img src="https://www.earthli.com/data/news/attachments/entry/3004/time_entry_queries_with_cursors.png" alt=" " style="width: 770px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3004/time_entry_queries_with_cursors.png">Time-entry queries with cursors</a></span></span></p>
<p>Just by using cursors, we&rsquo;ve managed to reduce the execution time for each query by about 75%. [5] Since all we&rsquo;re interested in finding out is whether there is at least one time entry for a person, we could also ask the database to count objects rather than to return them. That should be even faster. The following code is very similar to the example above but, instead of getting a cursor based on the <code>TimeEntries</code> query, it gets the count.</p>
<pre class=" "><code>var people =
  Session.GetList&lt;Person&gt;().
  Where(p =&gt; Session.GetCount(p.TimeEntries.Query) &gt; 0).
  ToList();</code></pre><p>How did we do? A check of the database statistics shows even more improvement, as shown below.</p>
<p><span style="width: 771px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3004/time_entry_queries_with_counts.png"><img src="https://www.earthli.com/data/news/attachments/entry/3004/time_entry_queries_with_counts.png" alt=" " style="width: 771px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3004/time_entry_queries_with_counts.png">Time-entry queries with COUNTs instead of SELECTs</a></span></span></p>
<p>We&rsquo;re now down to a few dozen milliseconds for all of our queries, so we&rsquo;re done, right? A 95% reduction in query-execution time should be enough. </p>
<p>Unfortunately, we&rsquo;re still executing just as many queries as before, even though we&rsquo;re taking far less time to execute them. This is better, but still not optimal. In high-latency situations, the user is still likely to experience a significant delay when opening the calendar since each query&rsquo;s execution time is increased by the latency of the connection. In a local network, the latency is negligible; on a WAN, we still have a problem.</p>
<p>In the next article, we’ll see if we can&rsquo;t reduce the number of queries being executed.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3004_1_body" class="footnote-number">[1]</span> This series of articles shows the statistics window as it appears in Winforms applications. The data-provider statistics are also available in Quino web applications as a Glimpse plug-in.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3004_2_body" class="footnote-number">[2]</span> <p>It is important for users of the Microsoft Entity Framework (EF) to point out that Quino does not have a Linq-to-Sql mapper. That means that any Linq expressions like <code>Where()</code> are evaluated locally instead of being mapped to the database. There are various reasons for this but the main one is that we ended up preferring a strict boundary between the mappable query API and the local evaluation API.</p>
<p>Anything formulated with the query API is guaranteed to be executed by the data provider (even if it must be evaluated locally) and anything formulated with Linq is naturally evaluated locally. In this way, the code is clear in what is sent to the server and what is evaluated locally. Quino only very, very rarely issues an &ldquo;unmappable query&rdquo; exception, unlike EF, which occasionally requires contortions until you&rsquo;ve figured out which C# formulation of a particular expression can be mapped by EF.</p>
</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3004_3_body" class="footnote-number">[3]</span> Well, the first answer I&rsquo;m going to pretend I came up with. I actually thought of another answer first, but then quickly discovered that Quino wasn&rsquo;t mapping that little-used feature correctly. I added an issue to tackle that problem at a later date and started looking for workarounds. That fix will be covered in the next article in this series.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3004_4_body" class="footnote-number">[4]</span> Please note that cursors are disposable and that the calling application is responsible for cleanup. Failure to dispose of a cursor that has been at least partially iterated will result in an open connection in the underlying database providers associated with the query and will eventually lead to connection-pool exhaustion on those databases.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3004_5_body" class="footnote-number">[5]</span> Please ignore the fact that we also dropped 13 person queries. This was not due to any fix that we made but rather that I executed the test slightly differently…and was too lazy to make a new screenshot. The 13 queries are still being executed and we&rsquo;ll tackle those in the last article in this series.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=3003</guid>
    <title><![CDATA[Optimizing data access for high-latency networks: part I]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=3003</link>
    <pubDate>Fri, 20 Jun 2014 10:44:29 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">20. Jun 2014 10:44:29 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">24. Jun 2014 13:27:18 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/3003/sample_calendar.png"><img src="https://www.earthli.com/data/news/attachments/entry/3003/sample_calendar_tn.png" alt=" " class=" align-left"></a>Punchclock is Encodo&rsquo;s time-tracking and invoicing tool. It includes a calendar to show time entries (shown to the left). Since the very first versions, it hasn&rsquo;t opened very quickly. It was fast enough for most users, but those who worked with Punchclock over the WAN through our VPN have reported that it often takes many seconds to open the calendar. So we have a very useful tool that is not often used because of how slowly it opens.</p>
<p>That the calendar opens slowly in a local network and even more slowly in a WAN indicates that there is not only a problem with executing many queries but also with retrieving too much data.</p>
<h2>Looking at query statistics</h2><p>This seemed like a solvable problem, so I fired up Punchclock in debug mode to have a look at the query-statistics window.</p>
<p>To set up the view shown below, I did the following:</p>
<ol>
<li>Start your Quino application (Punchclock in this case) in debug mode (so that the statistics window is available)</li>
<li>Open the statistics window from the debug menu</li>
<li>Reset the statistics to clear out anything logged during startup</li>
<li>Group the grid by &ldquo;Meta Class&rdquo;</li>
<li>Open the calendar to see what kind of queries are generated</li>
<li>Expand the &ldquo;TimeEntry&rdquo; group in the grid to show details for individual queries</li></ol><p><span style="width: 771px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3003/time_entry_queries_are_the_problem.png"><img src="https://www.earthli.com/data/news/attachments/entry/3003/time_entry_queries_are_the_problem.png" alt=" " style="width: 771px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3003/time_entry_queries_are_the_problem.png">Time-entry queries are the problem</a></span></span></p>
<p>I marked a few things on the screenshot. It&rsquo;s somewhat suspicious that there are 13 queries for data of type &ldquo;Person&rdquo;, but we&rsquo;ll get to that later. Much more suspicious is that there are 52 queries for time entries, which seems like quite a lot considering we&rsquo;re showing a calendar for a single user. We would instead expect to have a single query. More queries would be OK if there were good reasons for them, but I feel comfortable in deciding that 52 queries is definitely too many.</p>
<p>A closer look at the details for the time-entry queries shows very high durations for some of them, ranging from a tenth of a second to nearly a second. These queries are definitely the reason the calendar window takes so long to load.</p>
<h2>Why are these queries taking so long?</h2><p>If I select one of the time-entry queries and show the &ldquo;Query Text&rdquo; tab (see screenshot below), I can see that it retrieves all time entries for a single person, one after another. There are almost six years of historical data in our Punchclock database and some of our employees have been around for all of them. [1] That&rsquo;s a lot of time entries to load.</p>
<p><span style="width: 332px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3003/query_text_panel.png"><img src="https://www.earthli.com/data/news/attachments/entry/3003/query_text_panel.png" alt=" " style="width: 332px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3003/query_text_panel.png">Query text for all time entries for one person</a></span></span></p>
<p>I can also select the &ldquo;Stack Trace&rdquo; tab to see where the call originated in my source code. This feature lets me pinpoint the program component that is causing these slow queries to be executed.</p>
<p><span style="width: 770px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/3003/query_stack_trace.png"><img src="https://www.earthli.com/data/news/attachments/entry/3003/query_stack_trace.png" alt=" " style="width: 770px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/3003/query_stack_trace.png">Stack trace for superfluous time-entry queries</a></span></span></p>
<p>As with any UI-code stack, you have to be somewhat familiar with how events are handled and dispatched. In this stack, we can see how a <code>MouseUp</code> command bubbled up to create a new form, then a new control and finally, to trigger a call to the data provider during that control&rsquo;s initialization. We don&rsquo;t have line numbers but we see that the call originates in a lambda defined in the <code>DynamicSchedulerControl</code> constructor.</p>
<p>The line of code that I pinpoint as the culprit is shown below.</p>
<pre class=" "><code>var people = Session.GetList&lt;Person&gt;().Where(p =&gt; p.TimeEntries.Any()).ToList();</code></pre><p>This looks like a nicely declarative way of getting data, but to the trained eye of a Quino developer, it&rsquo;s clear what the problem is.</p>
<p>In the next couple of articles, we&rsquo;ll take a closer look at what exactly the problem is and how we can improve the speed of this query. We&rsquo;ll also take a look at how we can improve the Quino query API to make it harder for code like the line above to cause performance problems.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_3003_1_body" class="footnote-number">[1]</span> <p>Encodo just turned nine years old, but we used a different time-entry system for the first couple of years. If you&rsquo;re interested in our time-entry software history, here it is:</p>
<ol>
<li>06.2005—Start off with Open Office spreadsheets</li>
<li>04.2007—Switch to a home-grown, very lightweight time tracker based on an older framework we&rsquo;d written (Punchclock 1.0)</li>
<li>08.2008—Start development of Quino</li>
<li>04.2010—Initial version of Punchclock 2.0; start dogfooding Quino</li></ol></div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2997</guid>
    <title><![CDATA[Questions to consider when designing APIs: Part II]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2997</link>
    <pubDate>Wed, 18 Jun 2014 08:10:36 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">18. Jun 2014 08:10:36 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Jun 2016 20:51:27 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In the <a href="https://www.earthli.com/news/view_article.php?id=2996">previous article</a>, we listed a lot of questions that you should continuously ask yourself when you&rsquo;re writing code. Even when you think you&rsquo;re not designing anything, you&rsquo;re actually making decisions that will affect either other team members or <em>future versions of you</em>.</p>
<p>In particular, we&rsquo;d like to think about how we can reconcile a development process that involves asking so many questions and taking so many facets into consideration with <abbr title="You Ain't Gonna Need It">YAGNI</abbr>.</p>
<h2>Designing != Implementing</h2><p>The implication of this principle is, that if you aren&rsquo;t going to <em>need</em> something, then there&rsquo;s no point in even thinking about it. While it&rsquo;s absolutely commendable to adopt a YAGNI attitude, not <em>building</em> something doesn&rsquo;t mean not <em>thinking</em> about it and identifying potential pitfalls.</p>
<p>A feature or design concept can be discussed within a time-box. Allocate a fixed, limited amount of time to determine whether the feature or design concept needs to be incorporated, whether it would be nice to incorporate it or possibly to jettison it if it&rsquo;s too much work and isn&rsquo;t really necessary.</p>
<p>The overwhelming majority of time wasted on a feature is in the implementation, debugging, testing, documentation and maintenance of it, not in the design. Granted, a long design phase can be a time-sink—especially a &ldquo;perfect is the enemy of the good&rdquo; style of design where you&rsquo;re completely blocked from even starting work. With practice, however, you&rsquo;ll learn how to think about a feature or design concept (e.g. extensibility) without letting it ruin your schedule.</p>
<p>If you don&rsquo;t try to anticipate future needs at all while designing your API, you may end up preventing that API from being extended in directions that are both logical and could easily have been anticipated. If the API is not extensible, then it will not be used and may have to be rewritten in the future, losing more time at that point rather than up front. This is, however, only a consideration you must make. It&rsquo;s perfectly acceptable to decide that you currently don&rsquo;t care at all and that a feature will have to be rewritten at some point in the future. </p>
<p>You can&rsquo;t do this kind of cost-benefit analysis and risk-management if you haven&rsquo;t taken time to identify the costs, benefits or risks.</p>
<h2>Document your process</h2><p>At Encodo, we encourage the person who&rsquo;s already spent time thinking about this problem to simply document the drawbacks and concessions and possible ideas in an issue-tracker entry that is linked to the current implementation. This allows future users, maintainers or extenders of the API to be aware of the thought process that underlies a feature. It can also help to avoid misunderstandings about what the intended audience and coverage of an API are. </p>
<p>The idea is to eliminate <em>assumptions</em>. A lot of time can be wasted when maintenance developers make incorrect assumptions about the intent of code.</p>
<p>If you don&rsquo;t have time to do any of this, then you can write a quick note in a task list that you need to more fully document your thoughts on the code you&rsquo;re writing. And you should try to do that soon, while the ideas are still relatively fresh in your mind. If you don&rsquo;t have time to think about what you&rsquo;re doing even to that degree, then you&rsquo;re doing something wrong and need to get organized better.</p>
<p>That is, you if you can&rsquo;t think about the code you&rsquo;re writing and don&rsquo;t have time to document your process, even minimally, then you shouldn&rsquo;t be writing that code. Either that, or you implicitly accept that others will have to clean up your mess. And &ldquo;others&rdquo; includes future versions of <em>you</em>. (E.g. the you who, six months from now, is muttering, <span class="quote-inline">&ldquo;who <em>wrote</em> this crap?!?&rdquo;</span>)</p>
<h2>Be Honest about Hacking</h2><p>As an example, we can consider how we go from a specific feature in the context of a project to thinking about where the functionality could fit in to a suite of products—that may or may not yet exist. And remember, we&rsquo;re only <em>thinking</em> about these things. And we&rsquo;re thinking about them for a limited time—a time-box. You don&rsquo;t want to prevent your project from moving forward, but you also don&rsquo;t want to advance at all costs.</p>
<p>Advancing in an unstructured way is called hacking and, while it can lead to a short-term win, it almost always leads to short-to-medium term deficits. You can still write code that is hacked and looks hacked, if that is the highest current priority, but you&rsquo;re not allowed to forget that you did so. You must officially designate what you&rsquo;re doing as a hot-zone of hacking so that the Hazmat team can clean it up later, if needed.</p>
<p>A working prototype that is hacked together just so it works for the next demonstration is great as long as you don&rsquo;t think that you can take it into production without doing the design and documentation work that you initially skipped.</p>
<p>If you fail to document the deficits that prevent you from taking a prototype to production, then how will you address those deficits? It will cost you much more time and pain to determine the deficits after the fact. Not only that, but unless you do a very good job, it is your users that will most likely be finding deficits—in the form of bugs.</p>
<p>If your product is just a hacked mess of spaghetti code with no rhyme or reason, another developer will be faster and produce more reliable code by just starting over. Trying to determine the flaws, drawbacks and hacks through intuition and reverse-engineering is slower and more error-prone than just starting with a clean slate. Developers on such a project will not be able to save time—and money—by building on what you&rsquo;ve already made.</p>
<h2>A note on error-handling</h2><p>Not to be forgotten is a structured approach to error-handling. The more &ldquo;hacked&rdquo; the code, the more stringent the error-checking should be. If you haven&rsquo;t had time yet to write or test code sufficiently, then that code shouldn&rsquo;t be making broad decisions about what it thinks are acceptable errors.</p>
<p>Fail early, fail often. Don&rsquo;t try to make a hacked mess of code bullet-proof by catching all errors in an undocumented manner. Doing so is deceptive to testers of the product as well as other developers.</p>
<p>If you&rsquo;re building a demo, make sure the happy path works and stick to it during the demo. If you do have to break this rule, add the hacks to a demo-specific branch of the code that will be discarded later.</p>
<h2>Working with a documented project</h2><p>If, however, the developer can look at your code and sees accompanying notes (either in an issue tracker, as TODOs in the code or some other form of documentation), that developer knows where to start fixing the code to bring it to production quality.</p>
<p>For example, it&rsquo;s acceptable to configure an application in code as long as you do it in a central place and you document that the intent is to move the configuration to an external source when there&rsquo;s time. If a future developer finds code for support for multiple database connections and tests that are set to ignore with a note/issue that says &ldquo;extend to support multiple databases&rdquo;, that future developer can decide whether to actually implement the feature or whether to just discard it because it has been deprecated as a requirement.</p>
<p>Without documentation or structure or an indication which parts of the code were thought-through and which are considered to be hacked, subsequent developers are forced to make assumptions that may not be accurate. They will either assume that hacked code is OK or that battle-tested code is garbage. If you don&rsquo;t inform other developers of your intent when your&rsquo;re writing the code—best done with documentation, tests and/or a cleanly designed API—then it might be discarded or ignored, wasting even more time and money.</p>
<p>If you&rsquo;re on a really tight time-budget and don&rsquo;t have time to document your process correctly, then write a quick note that you think the design is OK or the code is OK, but tell your future self or other developers what they&rsquo;re looking at. It will only take you a few minutes and you&rsquo;ll be glad you did—and so will they.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2996</guid>
    <title><![CDATA[Questions to consider when designing APIs: Part I]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2996</link>
    <pubDate>Tue, 03 Jun 2014 10:25:46 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">3. Jun 2014 10:25:46 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>A big part of an agile programmer&rsquo;s job is API design. In an agile project, the architecture is defined from on high only in broad strokes, leaving the fine details of component design up to the implementer. Even in projects that are specified in much more detail, implementers will still find themselves in situations where they have to design <em>something</em>.</p>
<p>This means that programmers in an agile team have to be capable of weighing the pros and cons of various approaches in order to avoid causing performance, scalability, maintenance or other problems as the API is used and evolves.</p>
<p>When designing an API, we consider some of the following aspects. This is not meant to be a comprehensive list, but should get you thinking about how to think about the code you&rsquo;re about to write.</p>
<h2>Reusing Code</h2><ul>
<li>Will this code be re-used inside the project?</li>
<li>How about outside of the project?</li>
<li>If the code might be used elsewhere, where does that need lie on the time axis?</li>
<li>Do other projects already exist that could use this code?</li>
<li>Are there already other implementations that could be used?</li>
<li>If there are implementations, then are they insufficient?</li>
<li>Or perhaps not sufficiently encapsulated for reuse as written?</li>
<li>How likely is it that there will be other projects that need to do the same thing?</li>
<li>If another use is likely, when would the other project or projects need your API?</li></ul><h2>Organizing Code</h2><ul>
<li>Where should the API live in the code?</li>
<li>Is your API local to this class?</li>
<li>Is it private?</li>
<li>Protected?</li>
<li>Are you making it public in an extension method?</li>
<li>Or internal?</li>
<li>Which namespace should it belong to?</li>
<li>Which assembly?</li></ul><h2>Testing Code</h2><ul>
<li>What about testability?</li>
<li>How can the functionality be tested?</li></ul><p>Even if you don&rsquo;t have time to write tests right now, you should still build your code so that it can be tested. It&rsquo;s possible that you won&rsquo;t be writing the tests. Instead, you should prepare the code so that others can use it.</p>
<p>It&rsquo;s also possible that a future you will be writing the tests and will hate you for having made it so hard to automate testing.</p>
<h2>Managing Dependencies</h2><ul>
<li>Is multi-threading a consideration?</li>
<li>Does the API manage state?</li>
<li>What kind of dependencies does the API have?</li>
<li>Which dependencies does it really need?</li>
<li>Is the API perhaps composed of several aspects?</li>
<li>With a core aspect that is <em>extended</em> by others?</li>
<li>Can core functionality be extracted to avoid making an API that is too specific?</li></ul><h2>Documenting Code</h2><ul>
<li>How do callers use the API?</li>
<li>What are the expected values?</li>
<li>Are these expectations enforced?</li>
<li>What is the error mechanism?</li>
<li>What guarantees does the API make?</li>
<li>Is the behavior of the API enforced?</li>
<li>Is it at least documented?</li>
<li>Are known drawbacks documented?</li></ul><h2>Error-handling</h2><p>This is a very important one and involves how your application handles situations outside of the design.</p>
<ul>
<li>If you handle externally provided data, then you have to handle extant cases</li>
<li>Are you going to log errors?</li>
<li>In which format?</li>
<li>Is there a standard logging mechanism?</li>
<li>How are you going to handle and fix persistent errors?</li>
<li>Are you even going to handle weird cases?</li>
<li>Or are you going to fail early and fail often?</li>
<li>For which errors should your code even responsible?</li>
<li>How does your chosen philosophy (and you should be enforcing contracts) fit with the other code in the project?</li></ul><h2>Fail fast; enforce contracts</h2><p>While we&rsquo;re on the subject of error-handling, I want to emphasize that this is one of the most important parts of API design, regardless of which language or environment you use. [1]</p>
<p>Add preconditions for all method parameters; verify them as non-null and verify ranges. Do not catch all exceptions and log them or—even worse—ignore them. This is even more important in environments—I&rsquo;m looking at you client-side web code in general and JavaScript in particular—where the established philosophy is to run anything and to never rap a programmer on the knuckles for having written really knuckle-headed code.</p>
<p>You haven&rsquo;t tested the code, so you don&rsquo;t know what kind of errors you&rsquo;re going to get. If you ignore everything, then you&rsquo;ll also ignore assertions, contract violations, null-reference exceptions and so on. The code will never be improved if it never makes a noise. It will just stay silently crappy until someone notices a subtle logical error somewhere and must painstakingly track it down to your untested code.</p>
<p>You might say that production code shouldn&rsquo;t throw exceptions. This is true, but we&rsquo;re <em>explicitly</em> not talking about production code here. We&rsquo;re talking about code that has few to no tests and is acknowledged to be incomplete. If you move code like this into production, then it&rsquo;s better to crash than to silently corrupt data or impinge the user experience.</p>
<p>A crash will get attention and the code may even be fixed or improved. If you write code that will crash on all but the &ldquo;happy path&rdquo; and it never crashes? That&rsquo;s great. Do not program preemptively defensively in fresh code. If you have established code that interfaces with other (possibly external) components and you sometimes get errors that you can&rsquo;t work around in any other way, then it&rsquo;s OK to catch and log those exceptions rather than propagating them. At least you tried.</p>
<p>In the next article, we&rsquo;ll take a look at how all of these questions and considerations can at all be reconciled with <abbr title="You Ain't Gonna Need It">YAGNI</abbr>. Spoiler alert: we think that they can.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2996_1_body" class="footnote-number">[1]</span> I recently read <a href="https://medium.com/p/b5936dceb5e4">Erlang and code style</a> by <cite>Jesper L. Andersen</cite> (<cite><a href="http://medium.com/">Medium</a></cite>), which seems to have less to do with programming Erlang and much more to do with programming <em>properly</em>. The advice contained in it seems to be only for Erlang programmers, but the idea of strictly enforcing APIs between software components is neither new nor language-specific.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2994</guid>
    <title><![CDATA[Dealing with improper disposal in WCF clients]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2994</link>
    <pubDate>Sat, 31 May 2014 08:55:13 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">31. May 2014 08:55:13 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>There&rsquo;s an old problem in generated WCF clients in which the <code>Dispose()</code> method calls <code>Close()</code> on the client irrespective of whether there was a fault. If there was a fault, then the method should call <code>Abort()</code> instead. Failure to do so causes another exception, which masks the original exception. Client code will see the subsequent fault rather than the original one. A developer running the code in debug mode will have be misled as to what really happened.</p>
<p>You can see <a href="http://geekswithblogs.net/DavidBarrett/archive/2007/11/22/117058.aspx">WCF Clients and the &ldquo;Broken&rdquo; IDisposable Implementation</a> by <cite>David Barrett</cite> for a more in-depth analysis, but that&rsquo;s the gist of it.</p>
<p>This issue is still present in the <code>ClientBase</code> implementation in .NET 4.5.1. The linked article shows how you can add your own implementation of the <code>Dispose()</code> method in each generated client. An alternative is to use a generic adaptor if you don&rsquo;t feel like adding a custom dispose to every client you create. [1]</p>
<pre class=" "><code><strong>public class</strong> SafeClient&lt;T&gt; : IDisposable
  <strong>where</strong> T : ICommunicationObject, IDisposable
{
  <strong>public</strong> SafeClient(T client)
  {
    <strong>if</strong> (client == <strong>null</strong>) { <strong>throw new</strong> ArgumentNullException("client"); }

    Client = client;
  }
  
  <strong>public</strong> T Client { <strong>get</strong>; <strong>private set</strong>; }

  <strong>public void</strong> Dispose()
  {
    Dispose(<strong>true</strong>);
    GC.SuppressFinalize(<strong>this</strong>);
  }

  <strong>protected virtual void</strong> Dispose(<strong>bool</strong> disposing)
  {
    <strong>if</strong> (disposing)
    {
      <strong>if</strong> (Client != <strong>null</strong>)
      {
        <strong>if</strong> (Client.State == CommunicationState.Faulted) 
        {
          Client.Abort();
        }
        <strong>else</strong>
        {
          Client.Close();
        }

        Client = <strong>default</strong>(T);
      }
    }
  }  
}</code></pre><p>To use your WCF client safely, you wrap it in the class defined above, as shown below.</p>
<pre class=" "><code><strong>using</strong> (<strong>var</strong> safeClient = <strong>new</strong> SafeClient&lt;SystemLoginServiceClient&gt;(<strong>new</strong> SystemLoginServiceClient(…)))
{
  <strong>var</strong> client = safeClient.Client;
  // Work with "client"
}</code></pre><p>If you can figure out how to initialize your clients without passing parameters to the constructor, you could slim it down by adding a &ldquo;new&rdquo; generic constraint to the parameter T in <code>SafeClient</code> and then using the <code>SafeClient</code> as follows:</p>
<pre class=" "><code><strong>using</strong> (<strong>var</strong> safeClient = <strong>new</strong> SafeClient&lt;SystemLoginServiceClient&gt;())
{
  <strong>var</strong> client = safeClient.Client;
  // Work with "client"
}</code></pre><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2994_1_body" class="footnote-number">[1]</span> The code included in this article is a sketch of a solution and has not been tested. It does compile, though.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2995</guid>
    <title><![CDATA[REST API Status codes (400 vs. 500)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2995</link>
    <pubDate>Sat, 31 May 2014 08:55:09 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">31. May 2014 08:55:09 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In a project that we&rsquo;re working on, we&rsquo;re consuming REST APIs delivered by services built by another team working for the same customer. We had a discussion about what were appropriate error codes to return for various situations. The discussion boiled down to: should a service return a 500 error code or a 400 error code when a request cannot be processed?</p>
<p>I took a quick look at the documentation for a couple of the larger REST API providers and they are using the 500 code only for catastrophic failure and using the 400 code for anything related to query-input validation errors.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/azure/dd179357.aspx">Microsoft Azure Common REST API Error Codes</a></p>
<p>Code 400:</p>
<blockquote class="quote quote-block "><div><ul>
<li>The requested URI does not represent any resource on the server.</li>
<li>One of the request inputs is out of range.</li>
<li>One of the request inputs is not valid.</li>
<li>A required query parameter was not specified for this request.</li>
<li>One of the query parameters specified in the request URI is not supported.</li>
<li>An invalid value was specified for one of the query parameters in the request URI.</li></ul></div></blockquote><p>Code 500:</p>
<blockquote class="quote quote-block "><div><ul>
<li>The server encountered an internal error. Please retry the request.</li>
<li>The operation could not be completed within the permitted time.</li>
<li>The server is currently unable to receive requests. Please retry your request.</li></ul></div></blockquote><p><a href="https://dev.twitter.com/docs/error-codes-responses">Twitter Error Codes &amp; Responses</a></p>
<p>Code 400:</p>
<blockquote class="quote quote-block "><div>&ldquo;The request was invalid or cannot be otherwise served. An accompanying error message will explain further.&rdquo;</div></blockquote><p>Code 500:</p>
<blockquote class="quote quote-block "><div>&ldquo;Something is broken. Please post to the group so the Twitter team can investigate.&rdquo;</div></blockquote><p><a href="http://www.restapitutorial.com/httpstatuscodes.html">REST API Tutorial HTTP Status Codes</a></p>
<p>Code 400:</p>
<blockquote class="quote quote-block "><div>&ldquo;General error when fulfilling the request would cause an invalid state. Domain validation errors, missing data, etc. are some examples.&rdquo;</div></blockquote><p>Code 500: </p>
<blockquote class="quote quote-block "><div>&ldquo;A generic error message, given when no more specific message is suitable. The general catch-all error when the server-side throws an exception. Use this only for errors that the consumer cannot address from their end—never return this intentionally.&rdquo;</div></blockquote><p><a href="http://stackoverflow.com/questions/3290182/rest-http-status-codes">REST HTTP status codes</a></p>
<blockquote class="quote quote-block "><div>&ldquo;For input validation failure: 400 Bad Request + your optional description. This is suggested in the book &ldquo;RESTful Web Services&rdquo;.&rdquo;</div></blockquote>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2987</guid>
    <title><![CDATA[Mixing your own SQL into Quino queries: part 2 of 2]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2987</link>
    <pubDate>Thu, 17 Apr 2014 21:30:02 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">17. Apr 2014 21:30:02 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In the <a href="https://www.earthli.com/news/view_article.php?id=2985">first installment</a>, we covered the basics of mixing custom SQL with ORM-generated queries. We also took a look at a solution that uses direct ADO database access to perform arbitrarily complex queries.</p>
<p>In this installment, we will see more elegant techniques that make use of the <code>CustomCommandText</code> property of Quino queries. We&rsquo;ll approach the desired solution in steps, proceeding from attempt #1 – attempt #<a></a>5.</p>
<p><abbr title="Too long; didn't read">tl;dr</abbr>: Skip to attempt #5 to see the final result without learning <em>why</em> it&rsquo;s correct.  </p>
<h2>Attempt #1: Replacing the entire query with custom SQL</h2><p>An application can assign the <code>CustomCommandText</code> property of any Quino query to override some of the generated SQL. In the example below, we override <em>all</em> of the text, so that Quino doesn&rsquo;t generate any SQL at all. Instead, Quino is only responsible for sending the request to the database and materializing the objects based on the results.</p>
<pre class=" "><code>[Test]
public void TestExecuteCustomCommand()
{
  var people = Session.GetList&lt;Person&gt;();

  <strong class="highlight">people.Query.CustomCommandText = new CustomCommandText
  {
    Text = @"
SELECT ALL 
""punchclock__person"".""id"", 
""punchclock__person"".""companyid"", 
""punchclock__person"".""contactid"", 
""punchclock__person"".""customerid"", 
""punchclock__person"".""initials"", 
""punchclock__person"".""firstname"", 
""punchclock__person"".""lastname"", 
""punchclock__person"".""genderid"", 
""punchclock__person"".""telephone"", 
""punchclock__person"".""active"", 
""punchclock__person"".""isemployee"", 
""punchclock__person"".""birthdate"", 
""punchclock__person"".""salary"" 
FROM punchclock__person WHERE lastname = 'Rogers'"
  };</strong>

  Assert.That(people.Count, Is.EqualTo(9));
}</code></pre><p>This example solves two of the three problems outlined above:</p>
<ul>
<li>It uses only a single query.</li>
<li>It will work with a remote application server (although it makes assumptions about the kind of SQL expected by the backing database on that server).</li>
<li>But it is even more fragile than the previous example as far as hard-coded SQL goes. You&rsquo;ll note that the fields expected by the object-materializer have to be explicitly included <em>in the correct order</em>.</li></ul><p>Let&rsquo;s see if we can address the third issue by getting Quino to format the <code>SELECT</code> clause for us.</p>
<h2>Attempt #2: Generating the <code>SELECT</code> clause</h2><p>The following example uses the <code>AccessToolkit</code> of the <code>IQueryableDatabase</code> to format the list of properties obtained from the metadata for a <code>Person</code>. The application no longer makes assumptions about which properties are included in the select statement, what order they should be in or how to format them for the SQL expected by the database.</p>
<pre class=" "><code>[Test]
public virtual void TestExecuteCustomCommandWithStandardSelect()
{
  var people = Session.GetList&lt;Person&gt;();

  <strong class="highlight">var accessToolkit = DefaultDatabase.AccessToolkit;
  var properties = Person.Metadata.DefaultLoadGroup.Properties;
  var fields = properties.Select(accessToolkit.GetField);</strong>

  people.Query.CustomCommandText = new CustomCommandText
  {
    Text = <strong class="highlight">string.Format(
      @"SELECT ALL {0} FROM punchclock__person WHERE lastname = 'Rogers'",
      fields.FlattenToString()
    )</strong>
  };

  Assert.That(people.Count, Is.EqualTo(9));
}</code></pre><p>This example fixes the problem with the previous one but introduces a new problem: it no longer works with a remote application because it assumes that the client-side driver is a database with an <code>AccessToolkit</code>. The next example addresses this problem.</p>
<h2>Attempt #3: Using a hard-coded <code>AccessToolkit</code></h2><p>The version below uses a hard-coded <code>AccessToolkit</code> so that it doesn&rsquo;t rely on the external data driver being a direct ADO database. It still makes an assumption about the database on the server but that is usually quite acceptable because the backing database for most applications rarely changes. [1]</p>
<pre class=" "><code>[Test]
public void TestCustomCommandWithPostgreSqlSelect()
{
  var people = Session.GetList&lt;Person&gt;();

  var accessToolkit = <strong class="highlight">new PostgreSqlMetaDatabase().AccessToolkit;</strong>
  var properties = Person.Metadata.DefaultLoadGroup.Properties;
  var fields = properties.Select(accessToolkit.GetField);

  people.Query.CustomCommandText = new CustomCommandText
  {
    Text = string.Format(
      @"SELECT ALL {0} FROM punchclock__person WHERE lastname = 'Rogers'",
      fields.FlattenToString()
    )
  };

  Assert.That(people.Count, Is.EqualTo(9));
}</code></pre><p>We now have a version that satisfies all three conditions to a large degree. The application uses only a single query and the query works with both local databases and remoting servers. It still makes some assumptions about database-schema names (e.g. &ldquo;punchclock__person&rdquo; and &ldquo;lastname&rdquo;). Let&rsquo;s see if we can clean up some of these as well.</p>
<h2>Attempt #4: Replacing only the <code>where</code> clause</h2><p>Instead of replacing the entire query text, an application can replace individual sections of the query, letting Quino fill in the rest of the query with its standard generated SQL. An application can append or prepend text to the generated SQL or replace it entirely. Because the condition for our query is so simple, the example below replaces the entire <code>WHERE</code> clause instead of adding to it.</p>
<pre class=" "><code>[Test]
public void TestCustomWhereExecution()
{
  var people = Session.GetList&lt;Person&gt;();

  people.Query.CustomCommandText = new CustomCommandText<strong class="highlight">();
  people.Query.CustomCommandText.SetSection(
    CommandTextSections.Where, 
    CommandTextAction.Replace, 
    "lastname = 'Rogers'"
  );</strong>

  Assert.That(people.Count, Is.EqualTo(9));
}</code></pre><p>That&rsquo;s much nicer—still not perfect, but nice. The only remaining quibble is that the identifier <code>lastname</code> is <em>still</em> hard-coded. If the model changes in a way where that property is renamed or removed, this code will continue to compile but will fail at run-time. This is a not insignificant problem if your application ends up using these kinds of queries throughout its business logic.</p>
<h2>Attempt #5: Replacing the <code>where</code> clause with generated field names</h2><p>In order to fix this query and have a completely generic query that fails to compile should anything at all change in the model, we can mix in the technique that we used in attempts #2 and #3: using the <code>AccessToolkit</code> to format fields for SQL. To make the query 100% statically checked, we&rsquo;ll also use the generated metadata—<code>LastName</code>—to indicate which property we want to format as SQL.</p>
<pre class=" "><code>[Test]
public void TestCustomWhereExecution()
{
  var people = Session.GetList&lt;Person&gt;();

  <strong class="highlight">var accessToolkit = new PostgreSqlMetaDatabase().AccessToolkit;
  var lastNameField = accessToolkit.GetField(Person.MetaProperties.LastName);</strong>

  people.Query.CustomCommandText = new CustomCommandText();
  people.Query.CustomCommandText.SetSection(
    CommandTextSections.Where, 
    CommandTextAction.Replace, 
    <strong class="highlight">string.Format("{0} = </strong>'Rogers'"<strong class="highlight">, lastNameField)</strong>
  );

  Assert.That(people.Count, Is.EqualTo(9));
}</code></pre><p>The query above satisfies all of the conditions we outlined above. it&rsquo;s clear that the condition is quite simple and that real-world business logic will likely be much more complex. For those situations, the best approach is to fall back to using the direct ADO approach mixed with using Quino facilities like the <code>AccessToolkit</code> as much as possible to create a fully customized SQL text.</p>
<p><small class="notes">Many thanks to <a href="http://blogs.encodo.ch/news/view_user.php?name=Urs">Urs</a> for proofreading and suggestions on overall structure.</small></p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2987_1_body" class="footnote-number">[1]</span> If an application needs to be totally database-agnostic, then it will need to do some extra legwork that we won&rsquo;t cover in this post.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2985</guid>
    <title><![CDATA[Mixing your own SQL into Quino queries: part 1 of 2]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2985</link>
    <pubDate>Sun, 13 Apr 2014 17:38:59 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Apr 2014 17:38:59 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The Quino ORM [1] manages all CrUD—Create, Update, Delete—operations for your application. This basic behavior is generally more than enough for standard user interfaces.  When a user works with a single object in a window and saves it, there really isn&rsquo;t that much to optimize.</p>
<h2>Modeled methods</h2><p>A more complex editing process may include several objects at once and perhaps trigger events that create additional auditing objects. Even in these cases, there are still only a handful of save operations to execute. To keep the architecture clean, an application is encouraged to model these higher-level operations with methods in the metadata (modeled methods).</p>
<p>The advantage to using modeled methods is that they can be executed in an application server as well as locally in the client. When an application uses a remote application server rather than a direct connection to a database,  modeled methods are executed in the service layer and therefore have much less latency to the database.</p>
<h2>When Quino&rsquo;s query language isn&rsquo;t enough</h2><p>If an application needs even more optimization, then it may be necessary to write custom SQL—or even to use stored procedures to move the query into the database. Mixing SQL with an ORM can be a tricky business. It&rsquo;s even more of a challenge with an ORM like that in Quino, which generates the database schema and shields the user from tables, fields and SQL syntax almost entirely.</p>
<p>What are the potential pitfalls when using custom query text (e.g. SQL) with Quino?</p>
<ul>
<li><div><strong>Schema element names</strong>: An application needs to figure out the names of database objects like table and columns. It would be best not to hard-code them so that when the model changes, the custom code will be automatically updated.<ul>
<li>If the query is in a stored procedure, then the database may ensure that the code is updated or at least checked when the schema changes. [2]</li>
<li>If the query is in application code, then care can be taken to keep that query in-sync with the model</li></ul></div></li>
<li><strong>Materialization</strong>: In particular, the selected fields in a projection must match the expectations of the ORM exactly so that it can materialize the objects properly. We&rsquo;ll see how to ensure this in examples below.</li></ul><p>There are two approaches to executing custom code:</p>
<ul>
<li><strong>ADO</strong>: Get a reference to the underlying ADO infrastructure to execute queries directly without using Quino at all. With this approach, Quino can still help an application retrieve properly configured connections and commands.</li>
<li><strong>CustomCommandText</strong>: An application commonly adds restrictions and sorts to the  <code>IQuery</code> object using expressions, but can also add text directly to enhance or replace sections of the generated query.</li></ul><p><small class="notes">All of the examples below are taken directly from the Quino test suite. Some variables—like <code>DefaultDatabase</code>—are provided by the Quino base testing classes but their purpose, types and implementation should be relatively obvious.</small></p>
<h2>Using ADO directly</h2><p>You can use the <code>AdoDataConnectionTools</code> to get the underlying ADO connection for a given <code>Session</code> so that any commands you execute are guaranteed to be executed in the same transactions as are already active on that session. If you use these tools, your ADO code will also automatically use the same connection parameters as the rest of your application without having to use hard-coded connection strings.</p>
<p>The first example shows a test from the Quino framework that shows how easy it is to combine results returned from another method into a standard Quino query.</p>
<pre class=" "><code>[Test]
public virtual void TestExecuteAdoDirectly()
{
  var ids = GetIds().ToList();
  var people = Session.GetList&lt;Person&gt;();

  people.Query.Where(Person.MetaProperties.Id, ExpressionOperator.In, ids);

  Assert.That(people.Count, Is.EqualTo(9));
}</code></pre><p>The ADO-access code is hidden inside the call to <code>GetIds()</code>, the implementation for which is shown below. Your application can get the connection for a session as described above and then create commands using the same helper class. If you call <code>CreateCommand()</code> directly on the ADO connection, you&rsquo;ll have a problem when running inside a transaction on SQL Server. The SQL Server ADO implementation requires that you assign the active transaction object to each command. Quino takes care of this bookkeeping for you if you use the helper method.</p>
<pre class=" "><code>private IEnumerable&lt;int&gt; GetIds()
{
  using (var helper = AdoDataConnectionTools.GetAdoConnection(Session, "Name"))
  {
    using (var command = helper.CreateCommand())
    {
      command.AdoCommand.CommandText = 
        @"SELECT id FROM punchclock__person WHERE lastname = 'Rogers'";

      using (var reader = command.AdoCommand.ExecuteReader())
      {
        while (reader.Read())
        {
          yield return reader.GetInt32(0);
        }
      }
    }
  }
}</code></pre><p>There are a few drawbacks to this approach:</p>
<ul>
<li>Your application will make two queries instead of one.</li>
<li>The hard-coded SQL will break if you make model changes that affect those tables and fields.</li>
<li>The ADO approach only works if the application has a direct connection to the database. An application that uses ADO will not be able to switch to an application-server driver without modification.</li></ul><p>In the second part, we will improve on this approach by using the <code>CustomCommandText</code> property of a Quino query. This will allow us to use only a single query. We will also improve maintainability by reducing the amount of code that isn&rsquo;t checked by the compiler (e.g. the SQL text above).</p>
<p>Stay tuned for part 2, coming soon!</p>
<p><small class="notes">Many thanks to <a href="https://www.earthli.com/news/http/blogs.encodo.ch/news/view_user.php?name=Urs">Urs</a> for proofreading and suggestions on overall structure.</small></p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2985_1_body" class="footnote-number">[1]</span> This article uses features of Quino that will only become available in version 1.12. Almost all of the examples will also work in earlier versions but the <code>AdoDataConnectionTools</code> is not available until 1.12. The functionality of this class can, however, be back-ported if necessary.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2985_2_body" class="footnote-number">[2]</span> More likely, though, is that the Quino schema migration will be prevented from applying updates if there are custom stored procedures that use tables and columns that need to be changed.</div><p>Mixing your own SQL into Quino queries: part 1 of 2</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2977</guid>
    <title><![CDATA[Java 8]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2977</link>
    <pubDate>Fri, 28 Mar 2014 15:53:54 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">28. Mar 2014 15:53:54 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">28. Mar 2014 15:56:09 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/2977/java8_logo.png"><img src="https://www.earthli.com/data/news/attachments/entry/2977/java8_logo_tn.png" alt=" " class=" align-left" style="background-color: white"></a><small class="notes">This article discusses and compares the initial version of Java 8 and C# 4.5.1. I have not used Java 8 and I have not tested that any of the examples—Java or C#—even compile, but they should be pretty <em>close</em> to valid.</small></p>
<p>Java 8 has finally been released and—drum roll, please—it has closures/lambdas, as promised! I would be greeting this as champagne-cork–popping news if I were still a Java programmer. [1] As an ex-Java developer, I greet this news more with an ambivalent shrug than with any overarching joy. It&rsquo;s a sunny morning and I&rsquo;m in a good mood, so I&rsquo;m able to suppress what would be a more than appropriate comment: &ldquo;it&rsquo;s about time&rdquo;.</p>
<p>Since I&rsquo;m a C# programmer, I&rsquo;m more interested in peering over the fence at the pile of goodies that Java just received for its eighth birthday and see if it got something &ldquo;what I ain&rsquo;t got&rdquo;. I found a concise list of new features in the article <a href="http://ahmedsoliman.com/2014/03/26/will-java-8-kill-scala/">Will Java 8 Kill Scala?</a> by <cite>Ahmed Soliman</cite> and was distraught/pleased [2] to discover that Java had in fact gotten two presents that C# doesn&rsquo;t already have.</p>
<p>As you&rsquo;ll see, these two features aren&rsquo;t huge and the lack of them doesn&rsquo;t significantly impact design or expressiveness, but you know how jealousy works: </p>
<p>Jealousy doesn&rsquo;t care. </p>
<p>Jealousy is.</p>
<p>I&rsquo;m sure I&rsquo;ll get over it, but it will take time. [3]</p>
<h2>Default methods and static interface methods</h2><p>Java 8 introduces support for <em>static methods on interfaces</em> as well as <em>default methods</em> that, taken together, amount to functionality that is more or less what extensions methods brings to C#.</p>
<p>In Java 8, you can define static methods on an interface, which is nice, but it becomes especially useful when combined with the keyword <code>default</code> on those methods. As defined in <a href="http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html">Default Methods</a> (<cite><a href="http://docs.oracle.com/">Java Tutorials</a></cite>):</p>
<blockquote class="quote quote-block "><div>&ldquo;Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.&rdquo;</div></blockquote><p>In Java, you no longer have to worry that adding a method to an interface will break implementations of that interface in other jar files that have not yet been recompiled against the new version of the interface. You can avoid that by adding a default implementation for your method. This applies only to those methods where a default implementation is possible, of course.</p>
<p>The page includes an example but it&rsquo;s relatively obvious what it looks like:</p>
<pre class=" "><code><strong>public interface</strong> ITransformer
{
  <strong>string</strong> Adjust(<strong>string</strong> value);
  <strong>string</strong> NewAdjust(<strong>string</strong> value)
  {
    <strong>return</strong> value.Replace(' ', '\t');
  }
}</code></pre><p>How do these compare with extension methods in C#?</p>
<p>Extension methods are nice because they allow you to quasi-add methods to an interface without requiring an implementor to actually implement them. My rule of thumb is that any method that can be defined purely in terms of the public API of an interface should be defined as an extension method rather than added to the interface.</p>
<p>Java&rsquo;s default methods are a twist on this concept that addresses a limitation of extension methods. What is that limitation? That the method definition in the extension method can&rsquo;t be overridden by the actual implementation behind the interface. That is, the <em>default</em> implementation can be expressed purely in terms of the public interface, but perhaps a specific implementor of the interface would like to do that plus something more. Or would perhaps like to execute the extension method in a different way, but only for a specific implementation. There is no way to do this with extension methods.</p>
<p>Interface default methods in Java 8 allow you to provide a fallback implementation but also allows any class to actually implement that method and override the fallback.</p>
<h2>Functional Interfaces</h2><p>Functional interfaces are a nice addition, too, and something I&rsquo;ve wanted in C# for some time. <a href="http://en.wikipedia.org/wiki/Erik_Meijer_(computer_scientist)">Eric Meijer</a> of Microsoft doesn&rsquo;t miss an opportunity to point out that this is a must for functional languages (he&rsquo;s exaggerating, but the point is taken).</p>
<p>Saying that a language supports functional interface simply means that a lambda defined in that language can be assigned to any interface with a single method that has the same signature as that lambda.</p>
<p>An example in C# should make things clearer:</p>
<pre class=" "><code><strong>public interface</strong> ITransformer
{
  <strong>string</strong> Adjust(<strong>string</strong> value);
}

<strong>public static class</strong> Utility
{
  <strong>public static void</strong> WorkOnText(<strong>string</strong> text, ITransformer)
  {
    // Do work
  }
}</code></pre><p>In order to call <code>WorkOnText()</code> in C#, I am <em>required</em> to define a class that implements <code>ITransformer</code>. There is no other way around it. However, in a language that allows functional interfaces, I could call the method with a lambda directly. The following code looks like C# but won&rsquo;t actually compile.</p>
<pre class=" "><code>Utility.WorkOnText(
  "Hello world",
  s =&gt; s.Replace("Hello", "Goodbye cruel")
);</code></pre><p>For completeness, let&rsquo;s also see how much extra code it is do this in C#, which has no functional interfaces.</p>
<pre class=" "><code><strong class="highlight"><strong>public class</strong> PessimisticTransformer : ITransformer
{
  <strong>public string</strong> Adjust(<strong>string</strong> value)
  {
    <strong>return</strong> value.Replace("Hello", "Goodbye cruel");
  }
}</strong>

Utility.WorkOnText(
  "Hello world",
  <strong class="highlight"><strong>new</strong> PessimisticTransformer()</strong>
);</code></pre><p>That&rsquo;s quite a huge difference. It&rsquo;s surprising that C# hasn&rsquo;t gotten this functionality yet. It&rsquo;s hard to see what the downside is for this feature—it doesn&rsquo;t seem to alter semantics.</p>
<p>While it is supported in Java, there are other restrictions. The signature has to match exactly. What happens if we add an optional parameter to the interface-method definition?</p>
<pre class=" "><code><strong>public interface</strong> ITransformer
{
  <strong>string</strong> Adjust(<strong>string</strong> value<strong class="highlight">, ITransformer additional = <strong>null</strong></strong>);
}</code></pre><p>In the C# example, the class implementing the interface would have to be updated, of course, but the code at calling location remains unchanged. The functional interface&rsquo;s definition <em>is</em> the calling location, so the change would be closer to the implementation instead of more abstracted from it.</p>
<pre class=" "><code><strong>public class</strong> PessimisticTransformer : ITransformer
{
  <strong>public string</strong> Adjust(<strong>string</strong> value<strong class="highlight">, ITransformer additional = <strong>null</strong></strong>)
  {
    <strong>return</strong> value.Replace("Hello", "Goodbye cruel");
  }
}

// Using a class
Utility.WorkOnText(
  "Hello world",
  <strong>new</strong> PessimisticTransformer()
);

// Using a functional interface
Utility.WorkOnText(
  "Hello world",
  <strong class="highlight">(</strong>s<strong class="highlight">, a)</strong> =&gt; s.Replace("Hello", "Goodbye cruel")
);
</code></pre><p>I would take the functional interface any day.</p>
<h2>Java Closures</h2><p>As a final note, Java 8 has finally acquired closures/lambdas [4] but there is a limitation on which functions can be passed as lambdas. It turns out that the inclusion of functional interfaces is a workaround for not having first-class functions in the language.</p>
<p>Citing the article,</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] you cannot pass any function as first-class to other functions, the function must be explicitly defined as lambda or using Functional Interfaces&rdquo;</div></blockquote><p>While in C# you can assign any method with a matching signature to a lambda variable or parameter, Java requires that the method be first assigned to a variable that is <span class="quote-inline">&ldquo;explicitly assigned as lambda&rdquo;</span> in order to use. This isn&rsquo;t a limitation on expressiveness but may lead to clutter.</p>
<p>In C# I can write the following:</p>
<pre class=" "><code><strong>public string</strong> Twist(<strong>string</strong> value)
{ 
  <strong>return</strong> value.Reverse();
}

<strong>public string</strong> Alter(<strong>this string</strong> value, Func&lt;<strong>string</strong>, <strong>string</strong>&gt; func)
{
  <strong>return</strong> func(value);
}

<strong>public string</strong> ApplyTransformations(<strong>string</strong> value)
{
  <strong>return</strong> value.Alter(Twist).Alter(s =&gt; s.Reverse());
}</code></pre><p>This example shows how you can declare a <code>Func</code> to indicate that the parameter is a first-class function. I can pass the <code>Twist</code> function or I can pass an inline lambda, as shown in <code>ApplyTransformations</code>. However, in Java, I can&rsquo;t declare a <code>Func</code>: only functional interfaces. In order to replicate the C# example above in Java, I would do the following:</p>
<pre class=" "><code><strong>public</strong> String twist(String value)
{ 
  <strong>return new</strong> StringBuilder(value).reverse().toString();
}

<strong>public</strong> String alter(String value, <strong class="highlight">ITransformer transformer</strong>)
{
  <strong>return</strong> <strong class="highlight">transformer.adjust</strong>(value);
}

<strong>public</strong> String applyTransformations(String value)
{
  <strong>return</strong> <strong class="highlight">alter(alter(value, s -&gt; twist(s)), s -&gt; StringBuilder(s).reverse().toString();</strong>
}</code></pre><p>Note that the Java example cannot pass <code>Twist</code> directly; instead, it wraps it in a lambda so that it can be passed as a functional interface. Also, the C# example uses an extension method, which allows me to &ldquo;add&rdquo; methods to class <code>string</code>, which is not really possible in Java.</p>
<p>Overall, though, while these things feel like deal-breakers to a programming-language snob [5]—especially those who have a choice as to which language to use—Java developers can rejoice that their language has finally acquired features that both increase expressiveness and reduce clutter. [6]</p>
<p>As a bonus, as a C# developer, I find that I don&rsquo;t have to be so jealous after all.</p>
<p>Though I&rsquo;d still really like me some functional interfaces.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2977_1_body" class="footnote-number">[1]</span> Even if I were still a Java programmer, the champagne might still stay in the bottle because adoption of the latest runtime in the Java world is <em>extremely</em> slow-paced. Many projects and products require a specific, older version of the JVM and preclude updating to take advantage of newer features. The .NET world naturally has similar limitations but the problem seems to be less extreme.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2977_2_body" class="footnote-number">[2]</span> Distraught because the features look quite interesting and useful and C# doesn&rsquo;t have them and pleased because (A) I am not so immature that I can&rsquo;t be happy for others and (B) I know that innovation in other languages is an important driver in your own language.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2977_3_body" class="footnote-number">[3]</span> Totally kidding here. I&rsquo;m not insane. Take my self-diagnosis with a grain of salt.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2977_4_body" class="footnote-number">[4]</span> I know that lambdas and closures are not by definition the same and I&rsquo;m not supposed to use the interchangeably. I&rsquo;m trying to make sure that a C# developer who reads this article doesn&rsquo;t read &ldquo;closure&rdquo; (which is technically what a lambda in C# is because it&rsquo;s capable of &ldquo;closing over&rdquo; or capturing variables) and not understand that it means &ldquo;lambda&rdquo;.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2977_5_body" class="footnote-number">[5]</span> Like yours truly.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2977_6_body" class="footnote-number">[6]</span> Even if most of those developers won&rsquo;t be able to use those features for quite some time because they work on projects or products that are reluctant to upgrade.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2953</guid>
    <title><![CDATA[Quino: efficiency, hinting and local sorting]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2953</link>
    <pubDate>Thu, 13 Mar 2014 21:46:59 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">13. Mar 2014 21:46:59 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In <a href="https://www.earthli.com/news/view_article.php?id=2951">Quino: partially-mapped queries</a> we took a look at how Quino seamlessly maps as much as possible to the database, while handling unmappable query components locally as efficiently as possible.</p>
<h2>Correctness is more important than efficiency</h2><p><em>As efficiently as possible</em> can be a bit of a weasel statement. We saw that partial application of restrictions could significantly reduce the data returned. And we saw that efficient handling of that returned data could minimize the impact on both performance and memory, keeping in mind, of course, that the primary goal is correctness.</p>
<p>However, as we saw in the previous article, it&rsquo;s still entirely possible that even an optimally mapped query will result in an unacceptable memory-usage or performance penalty. In these cases, we need to be able to hint or warn the developer that something non-optimal is occurring. It would also be nice if the developer could indicate whether or not queries with such deficiencies should even be executed.</p>
<h2>When do things slow down?</h2><p>Why would this be necessary? Doesn&rsquo;t the developer have ultimate control over which queries are called? The developer has control over queries in business-logic code. But recall that the queries that we are using are somewhat contrived in order to keep things simple. Quino is a highly generic metadata framework: most of the queries are constructed by standard components from expressions defined in the metadata.</p>
<p>For example, the UI may piece together a query from various sources in order to retrieve the data for a particular view. In such cases, the developer has less direct control to &ldquo;repair&rdquo; queries with hand-tuning. Instead, the developer has to view the application holistically and make repairs in the metadata. This is one of many reasons why Quino has local evaluation and does not simply throw an exception for partially mapped queries, as EF does.</p>
<h2>Debugging data queries</h2><p><span style="width: 200px; display: table" class=" align-left"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/2953/data_provider_statistics_form.png"><img src="https://www.earthli.com/data/news/attachments/entry/2953/data_provider_statistics_form_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/2953/data_provider_statistics_form.png">Data-provider statistics window</a></span></span>It is, in general, far better to continue working while executing a <em>possibly</em> sub-optimal and performance-damaging query than it is to simply crash out. Such behavior would increase the testing requirements for generated UIs considerably. Instead, the UI always works and the developer can focus on optimization and fine-tuning in the model, using tools like the Statistics Viewer, shown to the left.</p>
<p><span style="width: 200px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/2953/webstats2.png"><img src="https://www.earthli.com/data/news/attachments/entry/2953/webstats2_tn.png" alt=" " style="width: 200px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/2953/webstats2.png">Data statistics in Glimpse (preview)</a></span></span>The statistics viewer shows all commands executed in an application, with a stack trace, messages (hints/warnings/info) and the original query and mapped SQL/remote statement for each command. The statistics are available for SQL-based data drivers, but also for remoting drivers for all payload types (including JSON).</p>
<p>The screenshot above is for the statistics viewer for Winform applications; we&rsquo;ve also integrated statistics into web applications using <a href="http://getglimpse.com/">Glimpse</a>, a plugin architecture for displaying extra information for web-site developers. The screenshot to the right shows a preview-release version that will be released with Quino 1.11 at the end of March.</p>
<p><span class="clear-both"></span></p>
<h2>Sorting is all or nothing</h2><p>One place where an application can run into efficiency problems is when the sort order for entities is too complex to map to the server.</p>
<p>If a single restriction cannot be mapped to the database, we can map all of the others and evaluate the unmappable ones locally. What happens if a single sort cannot be mapped to the database? Can we do the same thing? Again, to avoid being too abstract, let&rsquo;s start with an example.</p>
<pre class=" "><code>var query = Session.GetQuery&lt;Person&gt;();
query
  .Where(Person.Fields.LastName, ExpressionOperator.StartsWith[1], "M")
  <strong class="highlight">.OrderBy(Person.Fields.LastName)
  .OrderBy(Person.Fields.FirstName)</strong>
  .Join(Person.Relations.Company).WhereEqual(Company.Fields.Name, "IBM");

Assert.That(Session.GetList(query).Count, Is.Between(100, 120));</code></pre><p>Both of these sorts can be mapped to the server so the performance and memory hit is very limited. The ORM will execute a single query and will return data for and create about 100 objects.</p>
<p>Now, let&rsquo;s replace one of the mappable sorts with something unmappable:</p>
<pre class=" "><code>var query = Session.GetQuery&lt;Person&gt;();
query
  .Where(Person.Fields.LastName, ExpressionOperator.StartsWith[1], "M")
  <strong class="highlight">.OrderBy(new DelegateExpression(c =&gt; c.GetObject&lt;Person&gt;().FirstName)</strong>
  .OrderBy(Person.Fields.LastName)
  .Join(Person.Relations.Company).WhereEqual(Company.Fields.Name, "IBM");

Assert.That(Session.GetList(query).Count, Is.Between(100, 120));</code></pre><p>What&rsquo;s happening here? Instead of being able to map both sorts to the database, now only one can be mapped. Or can it? The primary sort can&rsquo;t be mapped, so there&rsquo;s obviously no point in mapping the secondary sort. Instead, <em>all</em> sorting must be applied locally.</p>
<p>What if we had been able to map the primary sort but not the secondary one? Then we could have the database apply the primary sort, returning the data partially ordered. We can apply the remaining sort in memory…but that won&rsquo;t work, will it? If we only applied the secondary sort in memory, then the data would end up sort <em>only</em> by that value. It turns out that, unlike restrictions, sorting is all-or-nothing. If we can&rsquo;t map <em>all</em> sorts to the database, then we have to apply them all locally. [1]</p>
<p>In this case, the damage is minimal because the restrictions <em>can</em> be mapped and guarantee that only about 100 objects are returned. Sorting 100 objects locally isn&rsquo;t likely to show up on the performance radar.</p>
<p>Still, sorting is a potential performance-killer: as soon as you stray from the path of standard sorting, you run the risk of either:</p>
<ul>
<li>Choosing a sort that is mappable but not covered by an index on the database</li>
<li>Choosing a sort that is unmappable and losing out on index-optimized sorting on the database</li></ul><p>In the next article, we&rsquo;ll discuss how we can extract slices from a result set—using <code>limit</code> and <code>offset</code>—and what sort of effect this can have on performance in partially mapped queries.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2953_1_body" class="footnote-number">[1]</span> The mapper also doesn&rsquo;t bother adding any ordering to the generated query if at least one ordering is unmappable. There&rsquo;s no point in wasting time on the database with a sort that will be re-applied locally.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2951</guid>
    <title><![CDATA[Quino: partially-mapped queries]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2951</link>
    <pubDate>Thu, 06 Mar 2014 22:33:32 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">6. Mar 2014 22:33:32 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In <a href="https://www.earthli.com/news/view_article.php?id=2950">Quino: an overview of query-mapping in the data driver</a> we took a look at some of the basics of querying data with Quino while maintaining acceptable performance and memory usage.</p>
<p>Now we&rsquo;ll take a look at what happens with partially-mapped queries. Before explaining what those are, we need a more concrete example to work with. Here&rsquo;s the most-optimized query we ended up with in the previous article:</p>
<pre class=" "><code>var query = Session.GetQuery&lt;Person&gt;();
query.Join(Person.Relations.Company).WhereEqual(Company.Fields.Name, "IBM");

Assert.That(Session.GetCount(query), Is.GreaterThanEqual(140000));</code></pre><p>With so many entries, we&rsquo;ll want to trim down the list a bit more before we actually create objects. Let&rsquo;s choose only people whose last names start with the letter &ldquo;M&rdquo;.</p>
<pre class=" "><code>var query = Session.GetQuery&lt;Person&gt;();
query
  <strong class="highlight">.Where(Person.Fields.LastName, ExpressionOperator.StartsWith [1], "M")</strong>
  .Join(Person.Relations.Company).WhereEqual(Company.Fields.Name, "IBM");

Assert.That(Session.GetCount(query), Is.Between(100, 120));</code></pre><p>This is the kind of stuff that works just fine in other ORMs, like Entity Framework. Where Quino goes just a little farther is in being more forgiving when a query can be only partially mapped to the server. If you&rsquo;ve used EF for anything beyond trivial queries, you&rsquo;ve surely run into an exception that tells you that some portion of your query could not be mapped. [2]</p>
<p>Instead of throwing an exception, Quino sends what it can to the database and uses LINQ to post-process the data sent back by the database to complete the query.</p>
<h2>Introducing unmappable expressions</h2><p>Unmappable code can easily sneak in through aspects in the metadata that define filters or sorts  using local methods or delegates that do not exist on the server. Instead of building a complex case, we&rsquo;re going to knowingly include an unmappable expression in the query.</p>
<pre class=" "><code>var query = Session.GetQuery&lt;Person&gt;();
query
  .Where(<strong class="highlight">new DelegateExpression [3](c =&gt; c.GetObject&lt;Person&gt;().LastName.StartsWith("M")</strong> [4])
  .Join(Person.Relations.Company).WhereEqual(Company.Fields.Name, "IBM");

Assert.That(Session.GetCount(query), Is.Between(100, 120));</code></pre><p>The new expression performs the same check as the previous example, but in a way that cannot be mapped to SQL. [5] With our new example, we&rsquo;ve provoked a situation where any of the following could happen:</p>
<ul>
<li>The ORM could throw up its hands and declare the query unmappable, pushing the responsibility for separating mappable from unmappable onto the shoulders of the developers. As noted above, this is what EF does.</li>
<li>The ORM could determine that the query is unmappable and <em>evaluate everything locally</em>, retrieving only the initial set of <code>Person</code> objects from the server (all several million of them, if you&rsquo;ll recall from the previous post).</li>
<li>The ORM could map part of the query to the database, retrieving the minimal set of objects necessary in order to guarantee the correct result. This is what Quino does. The strategy works in many cases, but is not without its pitfalls.</li></ul><p>What happens when we evaluate the query above? With partial mapping, we know that the restriction to &ldquo;IBM&rdquo; will be applied on the database. But we still have an additional restriction that must be applied locally. Instead of being able to get the count from the server without creating any objects, we&rsquo;re now forced to create objects in memory so that we can apply the local restrictions and only count the objects that match them all.</p>
<p>But as you&rsquo;ll recall from the previous article, the number of matches for &ldquo;IBM&rdquo; is 140,000 objects. The garbage collector just gave you a dirty look again.</p>
<h2>Memory bubbles</h2><p>There is no way to further optimized this query because of the local evaluation, but there is a way to avoid another particularly nasty issue: memory bubbles.</p>
<p>What is a memory bubble you might ask? It describes what happens when your application is using <em>n</em>MB and then is suddenly using <em>n</em> + 100MB because you created 140,000 objects <em>all at once</em>. Milliseconds later, the garbage collector is thrashing furiously to clean up all of these objects—and all because you created them only in order to filter and count them. A few milliseconds after that, your application is back at <em>n</em>MB but the garbage collector&rsquo;s fur is ruffled and it&rsquo;s still trembling slightly from the shock.</p>
<p>The way to avoid this is to <em>stream</em> the objects through your analyzer one at a time rather than to create them all at once. Quino uses lazily-evaluated <code>IEnumerable&lt;T&gt;</code> sequences throughout the data driver specifically to prevent memory bubbles.</p>
<h2>Streaming with <code>IEnumerable&lt;T&gt;</code> sequences</h2><p>Before tackling how the Quino ORM handles the <code>Count()</code>, let&rsquo;s look at how it would return the actual objects from this query.</p>
<ul>
<li>Map the query to create a <code>SELECT</code> statement</li>
<li>At this point, it doesn&rsquo;t matter whether the entire query could be mapped</li>
<li>Create an <code>IEnumerable&lt;T&gt;</code> sequence that represents the result of the mapped query</li>
<li>At this point, nothing has been executed and no objects have been returned</li>
<li>Wrap the sequence in another sequence that applies all of the &ldquo;unhandled&rdquo; parts of the query</li>
<li>Return that sequence as the result of executing the query</li>
<li>At this point, we <em>still</em> haven&rsquo;t actually executed anything on the database or created any objects</li></ul><p>Right, now we have an <code>IEnumerable&lt;T&gt;</code> that represents the result set, but we haven&rsquo;t lit the fuse on it yet.</p>
<p>How do we light the fuse? Well, the most common way to do so is to call <code>ToList()</code> on it. What happens then?</p>
<ul>
<li>The <code>IEnumerator&lt;T&gt;</code> requests an element</li>
<li>The query is executed against the database and returns an <code>IDataReader</code></li>
<li>The reader requests a row and creates a <code>Person</code> object from that row&rsquo;s data</li>
<li>The wrapper that performs the local evaluation applies its filter(s) to this <code>Person</code> and yields it if it matches</li>
<li>If it matched the local filters, the <code>Person</code> is added to the list</li>
<li>Control returns to the <code>IDataReader</code>, which requests another row</li>
<li>Repeat until no more rows are returned from the database</li></ul><p>Since the decision to add all objects to a list occurs <em>all the way at the very outer caller</em>, it&rsquo;s the caller that&rsquo;s at fault for the memory bubble not the driver. [6] We&rsquo;ll see in the section how to avoid creating a list when none is needed.</p>
<p><code>Using cursors to control evaluation</code></p>
<p>If we wanted to process data but perhaps offer the user a chance to abort processing at any time, we could even get an <code>IDataCursor&lt;T&gt;</code> from the Quino ORM so control iteration ourselves.</p>
<pre class=" "><code><strong>using</strong> (<strong>var</strong> cursor = Session.CreateCursor(query))
{
  <strong>foreach</strong> (<strong>var</strong> obj <strong>in</strong> cursor)
  {
    // Do something with obj

    <strong>if</strong> (userAbortedOperation) { <strong>break</strong>; }
  }
}</code></pre><h2>And finally, the count query</h2><p>But back to evaluating the query above. The Quino ORM handles it like this:</p>
<ul>
<li>Try to map the query to create a <code>COUNT</code> statement</li>
<li>Notice that at least one restriction could not be mapped</li>
<li>Create a cursor to SELECT all of the objects for the same query (shown above) and count all the objects returned by that instead</li></ul><p>So, if a count-query cannot be fully mapped to the database, the most efficient possible alternative is to execute a query that retrieves as few objects as possible (i.e. maps as much to the server as it can) and streams those objects to count them locally.</p>
<p>Tune in next time for a look at how to exert more control with <code>limit</code> and <code>offset</code> and how those work together with partial mapping.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2951_1_body" class="footnote-number">[1]</span> These exceptions are not always obvious, either. Often, the exception complains about not being able to call a static method on a non-static object or class, which occurs when mapping the Expression object to SQL. EF&rsquo;s error messages have in general gotten much better but the mapping failures can be quite confusing.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2951_2_body" class="footnote-number">[2]</span> If we were worried that the last names in our database might not necessarily be capitalized, we would use the <code>ExpressionOperator.StartsWithCI</code> to perform the check in a case-insensitive manner instead.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2951_3_body" class="footnote-number">[3]</span> A <code>DelegateExpression</code> simply wraps the lambda given in the constructor in a Quino expression object. The parameter <code>c</code> is an <code>IExpressionContext</code> that provides the target object, which is in this case a <code>Person</code>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2951_4_body" class="footnote-number">[4]</span> I&rsquo;m going to go ahead and assume that my database schema doesn&rsquo;t allow nulls for the <code>LastName</code> field.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2951_5_body" class="footnote-number">[5]</span> If Quino had a LINQ-to-SQL provider, there&rsquo;s a chance that more of these delegates could be mapped, but we don&rsquo;t have one…and they can&rsquo;t.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2951_6_body" class="footnote-number">[6]</span> Did we still create 140,000 objects? Yes we did, but not <em>all at once</em>. Now, there are probably situations where it is better to create several objects rather than streaming them individually, but I&rsquo;m confident that keeping this as the default is the right choice. If you find that your particular situation warrants different behavior, feel free to use <code>Session.CreateCursor()</code> to control evaluation yourself and create the right-sized batches of objects to count. The <code>ChangeAndSave()</code> extension method does exactly that to load objects in batches (size adjustable by an optional parameter) rather than one by one.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2965</guid>
    <title><![CDATA[LESS vs. SASS: Variable semantics]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2965</link>
    <pubDate>Mon, 24 Feb 2014 23:01:09 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">24. Feb 2014 23:01:09 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">24. Feb 2014 23:13:04 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I&rsquo;ve been using CSS since pretty much its inception. It&rsquo;s powerful but quite low-level and lacks support for <abbr title="Don't Repeat Yourself">DRY</abbr>. So, I switched to generating CSS with LESS a while back. This has gone quite well and I&rsquo;ve been pretty happy with it.</p>
<p>Recently, I was converting some older, theme stylesheets for earthli. A theme stylesheet provides no structural CSS, mostly setting text, background and border colors to let users choose the basic color set. This is a perfect candidate for LESS.</p>
<p>So I constructed a common stylesheet that referenced LESS variables that I would define in the theme stylesheet. Very basically, it looks like this:</p>
<div class="chart"><h3 class="chart-title">crimson.less</h3><div class="chart-body"><pre class=" "><code>@body_color: #800;
@import "theme-base";</code></pre></div></div><div class="chart"><h3 class="chart-title">theme-base.less</h3><div class="chart-body"><pre class=" "><code>body
{
  background-color: @body_color;
}</code></pre></div></div><p>This is just about the most basic use of LESS that even an amateur user could possibly imagine. I&rsquo;m keeping it simple because I&rsquo;d like to illustrate a <em>subtlety</em> to variables in LESS that tripped me up at first—but for which I&rsquo;m very thankful. I&rsquo;ll give you a hint: LESS treats variables as a stylesheet would, whereas SASS treats them as one would expect in a programming language.</p>
<p>Let&rsquo;s expand the <code>theme-base.less</code> file with some more default definitions. I&rsquo;m going to define some other variables in terms of the body color so that themes don&rsquo;t have to explicitly set all values. Instead, a theme can set a base value and let the base stylesheet calculate derived values. If a calculated value isn&rsquo;t OK for a theme, the theme can set that value explicitly to override.</p>
<p>Let&rsquo;s see an example before we continue.</p>
<div class="chart"><h3 class="chart-title">theme-base.less</h3><div class="chart-body"><pre class=" "><code><strong class="highlight">@title_color: darken(@body_color, 25%);
@border_color: @title_color;</strong>

body
{
  background-color: @body_color;
}

<strong class="highlight">h2
{
  color: @title_color;
  border: 1px solid @border_color;
}</strong></code></pre></div></div><p>You&rsquo;ll notice that I avoided setting a value for <code>@body_color</code> because I didn&rsquo;t want to override the value set previously in the theme. But then wouldn&rsquo;t it be impossible for the theme to override the values for <code>@title_color</code> and <code>@border_color</code>? We seem to have a problem here. [1]</p>
<p>I want to be able to set some values and just use defaults for everything that I don&rsquo;t want to override. There is a construct in SASS called <code>!default</code> that does exactly this. It indicates that an assignment should only take place if the variable has not yet been assigned. [2] Searching around for an equivalent in LESS took me to this page, <a href="https://github.com/less/less.js/issues/1706">Add support for &ldquo;default&rdquo; variables (similar to !default in SASS) #1706</a> (<cite><a href="http://github.com/">GitHub</a></cite>). There users suggested various solutions and the original poster became ever more adamant—<span class="quote-inline">&ldquo;Suffice it to say that we believe we need default variable setting as we&rsquo;ve proposed here&rdquo;</span>—until a LESS developer waded in to state that it would be <span class="quote-inline">&ldquo;a pointless feature in less&rdquo;</span>, which seemed harsh until an example showed that he was quite right.</p>
<p>The clue is further down in one of the answers:</p>
<blockquote class="quote quote-block "><div>&ldquo;If users define overrides after then it works as if it had a default on it. [T]hat&rsquo;s because even in the imported file it will take the last definition in the same way as css, <strong>even if defined after usage.</strong> (Emphasis added.)&rdquo;</div></blockquote><p>It was at this point that the lightbulb went on for me. I was thinking like a programmer where a file is processed top-down and variable values can vary depending on location in the source text. That the output of the following C# code is <code>12</code> should amaze no one.</p>
<pre class=" "><code><strong>var</strong> a = 1;
Console.Write(a);
a = 2;
Console.Write(a);
a = 3;</code></pre><p> </p>
<p>In fact, we would totally expect our IDE to indicate that the value in the final assignment is never used and can be removed. Using LESS variable semantics, though, where variables are global in scope [3] and assignment are treated as they are in CSS, we would get <code>33</code> as output. Why? Because the value of the variable <code>a</code> has the value 3 because that&rsquo;s the <em>last value assigned to it</em>. That is, LESS has a cascading approach to variable assignment.</p>
<p>This is exactly as the developer from LESS said: stop fighting it and just let LESS do what it does best. Do you want default values? Define the defaults first, then define your override values. The overridden value will be used even when used for setting the value of another default value that you <em>didn&rsquo;t even override</em>.</p>
<p>Now let&rsquo;s go fix our stylesheet to use these terse semantics of LESS. Here&rsquo;s a first cut at a setup that feels pretty right. I put the files in the order that you would read them so that you can see the overridden values and everything makes sense again. [4]</p>
<div class="chart"><h3 class="chart-title">theme-variables.less</h3><div class="chart-body"><pre class=" "><code>@body_color: white;
@title_color: darken(@body_color, 25%);
@border_color: @title_color;</code></pre></div></div><div class="chart"><h3 class="chart-title">crimson.less</h3><div class="chart-body"><pre class=" "><code><strong class="highlight">@import "theme-variables";</strong>
@body_color: #800;
@import "theme-base";</code></pre></div></div><div class="chart"><h3 class="chart-title">theme-base.less</h3><div class="chart-body"><pre class=" "><code>body
{
  background-color: @body_color;
}

h2
{
  color: @title_color;
  border: 1px solid @border_color;
}</code></pre></div></div><p>You can see in the example above that the required variables are all declared, then overridden and then used. From what we learned above, we know that the value of <code>@title_color</code> in the file <code>theme-variables.less</code> will use a value of <code>#800</code> for <code>@body_color</code> because that was the last value it was assigned.</p>
<p>We can do better though. The example above hasn&rsquo;t quite embraced the power of LESS fully. Let&rsquo;s try again.</p>
<div class="chart"><h3 class="chart-title">theme-base.less</h3><div class="chart-body"><pre class=" "><code>@body_color: white;
@title_color: darken(@body_color, 25%);
@border_color: @title_color;

body
{
  background-color: @body_color;
}

h2
{
  color: @title_color;
  border: 1px solid @border_color;
}</code></pre></div></div><div class="chart"><h3 class="chart-title">crimson.less</h3><div class="chart-body"><pre class=" "><code>@import "theme-base";
@body_color: #800;</code></pre></div></div><p>Boom! That&rsquo;s all you have to do. Set up <em>everything</em> in your base stylesheet file. Define all variables and define them in terms of each other in as convoluted a manner as you like. The final value of each value is determined <em>before</em> any CSS is generated.</p>
<p>This final version also has the added advantage that a syntax-checking IDE like JetBrains WebStorm or PHPStorm will be able to provide perfect assistance and validity checking. That wasn&rsquo;t true at all for any of the previous versions, where variable declarations were in different files.</p>
<p>Although I was seriously considering moving away from LESS and over to SASS—because at least they didn&rsquo;t leave out such a basic feature, as I had thought crossly to myself—I&rsquo;m quite happy to have learned this lesson and am more happy with LESS than ever.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2965_1_body" class="footnote-number">[1]</span> For those of you who already know how to fix this, stop smirking. I&rsquo;m writing this post because it wasn&rsquo;t intuitive for me—although now I see the utter elegance of it.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2965_2_body" class="footnote-number">[2]</span> I&rsquo;d also seen the same concept in NAnt <code>property</code> tasks where you can use the now-deprecated <code>overwrite=&ldquo;false&rdquo;</code> directive. For the curious, now you&rsquo;re supposed to use <code>unless=&ldquo;${property::exists(&lsquo;property-name&rsquo;)}&rdquo;</code> instead, which is just hideous.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2965_3_body" class="footnote-number">[3]</span> There are exceptions, but &ldquo;variables are global in LESS is a good rule of thumb&rdquo;. One example is that if a parameter for a mixin has the same name as a globally assigned variable, the value within that mixin is taken from the parameter rather than the global.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2965_4_body" class="footnote-number">[4]</span> Seriously, LESS experts, stop smirking. I&rsquo;m taking a long time to get there because a programmer&rsquo;s intuitive understanding of how variables work is a hard habit to break. Almost there.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2948</guid>
    <title><![CDATA[Rolling your own languages and frameworks]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2948</link>
    <pubDate>Sun, 09 Feb 2014 23:08:59 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">9. Feb 2014 23:08:59 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The blog post/article <a href="http://www.drdobbs.com/architecture-and-design/so-you-want-to-write-your-own-language/240165488">So You Want To Write Your Own Language?</a> by <cite>Walter Bright</cite> (<cite><a href="http://www.drdobbs.com/">Dr. Dobbs</a></cite>) contains a lot of interesting information, related to only to parsing, but also to runtime and framework design. Bright is well-known as the designer of the D programming language, so he&rsquo;s definitely worth a read.</p>
<p>I thought he jumped back and forth between topics a bit, so I summarized the contents for myself below:</p>
<h2>Parsing</h2><p>Bright identifies <em>Minimizing keystrokes</em>, <em>easy parsing</em> and <em>minimizing the number of keywords</em> as <strong>false gods</strong>. Do not waste any time trying to satisfy these requirements; instead, let them flow naturally from a good design.</p>
<p>Your language should consist of productions that have only a single non-terminal on the left-hand side. That is, strive to make your language <strong>context-free</strong>. [1] The implication is that you&rsquo;re actually going to define the grammar rather than just winging it. This means that you can can use a parser generator even though Bright says not to <span class="quote-inline">&ldquo;bother wasting time with lexer or parser generators and other so-called &lsquo;compiler compilers.&rsquo;&rdquo;</span></p>
<p>I instead agree with the article <a href="http://genericlanguage.wordpress.com/2014/02/04/advice-on-writing-a-programming-language/">Advice on writing a programming language</a> by <cite>Ted Kaminski&#039;</cite> (<cite><a href="http://genericlanguage.wordpress.com/">Generic Language</a></cite>), which advises providing a grammar that can be used with parser generators because <span class="quote-inline">&ldquo;many of those people eager to contribute either get stuck trying and failing to build a parser or trying and failing to learn to use the daunting internals of your compiler&rdquo;</span>.</p>
<p>You can either make it easy for people to build compilers for your language or you can maintain a very friendly API for your own compiler. If you choose the API route, it <em>might</em> force you to be more disciplined, but it might also cause you no end of backwards-compatibility headaches as your compiler quickly evolves. Not only that, but you&rsquo;d then have to make that API available for any number of languages and any number of platforms.</p>
<p>If you take the route of publishing the BNF, that may also not not be enough. This because it can still be daunting to convert a BNF to something that your compiler-generator can use, especially for non-trivial languages. Providing a grammar for a widely supported parser-generator like <a href="http://www.antlr.org">ANTLR</a> [2] will give those willing to build tools for your language a good jump-start.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;Use an LR parser generator. It’ll keep your language parsable, and make it easier to change early on. When your language becomes popular enough that you have the problem of parsing errors not being friendly enough for your users, celebrate that fact and hand-roll only then.</p>
<p>&ldquo;And then reap the benefit of all the tooling an easily parsed language gets, since you know you kept it LR(1).&rdquo;</p>
</div></blockquote><h2>Error-handling</h2><p>Introduce redundancy into the language definition (e.g. semicolons as line-terminators in addition to whitespace/newlines) in order to make error-message generation much easier and much more likely to produce friendly output.</p>
<p>Compilers can handle error messages in different ways: </p>
<dl><dt class="field">Bail out on the first error</dt>
<dd>This is a good fallback, but it saves the developer a lot of work if you identify all of the root errors in source—that is, errors that are not a consequence of another error.</dd>
<dt class="field">Collect multiple errors</dt>
<dd><div class=" "><p>In order to continue parsing/compiling after an error, the machine can take one of two approaches:</p>
<ul>
<li><span class="quote-inline">&ldquo;Guess what the programmer intended, repair the syntax trees, and continue.&rdquo;</span> (Bright) Bad guesses lead to spurious and inscrutable error messages which lead to developers no longer trusting their compilers. Avoid this approach as it is very difficult to get right.</li>
<li>Take the approach that Bright did with the D compiler: consider any part of the code that has an error as &ldquo;poisoned&rdquo;. He likens it to the way that <span class="quote-inline">&ldquo;floating-point NaNs are handled. Any operation with a NaN operand silently results in a NaN.&rdquo;</span> With this approach, <span class="quote-inline">&ldquo;the compiler is able to detect multiple errors as long as the errors are in sections of code with no dependency between them&rdquo;</span>, which yields only high-quality and relevant error messages for the developer.</li></ul></div></dd>
</dl><h2>Stand on the shoulders of giants</h2><p>Do not re-invent the syntax for everything in your language. Instead, as Bright says, <span class="quote-inline">&ldquo;[s]ave the divergence for features not generally seen before, which also signals the user that this is new.&rdquo;</span></p>
<h2>The runtime</h2><p>A language definition is nothing without a runtime. Bright recommends <span class="quote-inline">&ldquo;taking the common sense approach and using an existing back end, such as the JVM, CLR, gcc, or LLVM. (Of course, I can always set you up with the glorious Digital Mars back end!)&rdquo;</span> If you can avoid writing your own back-end, you should definitely do so. Similar to the approach recommended for parsing the language: start with a stock runtime and migrate to something custom if the needs of your project warrant it (they almost certainly won&rsquo;t). This is the approach taken by any number of other popular languages, like Scala.</p>
<h2>The framework</h2><p>And then there&rsquo;s the library/framework that accompanies the language and, arguably, helps to define it for people. Complaints about a language are often complaints about the standard runtime library/framework for the language. Developers quickly associate them and treat them as one entity. Bright&rsquo;s focus is on very low-level runtimes (such as the one for his language, D) and thus his advice focuses on fast I/O, fast and efficient memory allocation/de-allocation and robust/fast transcendental functions [3]. However, he also offers the following excellent rule of thumb for any framework:</p>
<blockquote class="quote quote-block "><div>&ldquo;My general rule is if the explanation for what the function does is more lines than the implementation code, then the function is likely trivia and should be booted out.&rdquo;</div></blockquote><p> </p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2948_1_body" class="footnote-number">[1]</span> See <a href="http://www.velocityreviews.com/forums/t610834-example-of-why-c-is-not-a-context-free-grammar.html">Example of why C++ is NOT a context free grammar?</a> by <cite>Kaz Kylheku</cite> (<cite><a href="http://www.velocityreviews.com/">Velocity Reviews</a></cite>) and <a href="http://en.wikipedia.org/wiki/Context-free_grammar">Context-free grammar</a> (<cite><a href="http://en.wikipedia.org/">Wikipedia</a></cite>) for more information.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2948_2_body" class="footnote-number">[2]</span> These are functions that cannot be composed of other functions in the framework, what I would call &ldquo;core&rdquo; or &ldquo;root&rdquo; functions. These are the functions that the developer would find it either impossible or incredibly difficult to replicate efficiently in the language itself.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2948_3_body" class="footnote-number">[3]</span> As of publication time, the current stable release of ANTLR for C# available via NuGet—and used by most other packages—is version 3.5.1. However, the official home page is now <a href="http://www.antlr.org">ANTLR</a> rather than <a href="http://www.antlr3.org">ANTLR3</a>. The NuGet packages for version 4 are in pre-release, but it&rsquo;s very nice to see some progress being made after years of relatively minor upgrades. In particular, the new version of the IDE <a href="http://tunnelvisionlabs.com/products/demo/antlrworks">ANTLRWorks</a> looks much nicer and seems to have been based on the JETBrains IDE framework. I&rsquo;m definitely looking forward to checking it out in more detail.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2950</guid>
    <title><![CDATA[Quino: an introduction to query-mapping in the ORM]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2950</link>
    <pubDate>Fri, 07 Feb 2014 09:57:07 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">7. Feb 2014 09:57:07 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">The following article was originally published on the <a href="http://encodo.com/en/blogs.php?entry_id=356">Encodo blogs</a> and is cross-published here.</small></p>
<p><hr></p>
<p>One of the most-used components of Quino is the ORM. An ORM is an Object-Relational Mapper, which accepts queries and returns data.</p>
<ul>
<li>Applications formulate queries in Quino using application metadata</li>
<li>The ORM maps this query to the query language of the target database</li>
<li>The ORM transforms the results returned by the database to objects (the classes for which were also generated from application metadata).</li></ul><p>This all sounds a bit abstract, so let&rsquo;s start with a concrete example. Let&rsquo;s say that we have millions of records in an employee database. We&rsquo;d like to get some information about that data using our ORM. With millions of records, we have to be a bit careful about how that data is retrieved, but let&rsquo;s continue with concrete examples.</p>
<h2>Attempt #1: Get your data and refine it locally</h2><p>The following example returns the correct information, but does not satisfy performance or scalability requirements. [1]</p>
<pre class=" "><code>var people = Session.GetList&lt;Person [2]&gt;().Where(p =&gt; p.Company.Name == "IBM");

Assert.That(people.Count(), Is.GreaterThanEqual(140000));</code></pre><p>What&rsquo;s wrong with the statement above? Since the call to <code>Where</code> occurs <em>after</em> the call to <code>GetList&lt;Person&gt;()</code>, the restriction cannot possibly have been passed on to the ORM. </p>
<p>The first line of code doesn&rsquo;t actually execute anything. It&rsquo;s in the call to <code>Count()</code> that the ORM and LINQ are called into action. Here&rsquo;s what happens, though:</p>
<ul>
<li>For each row in the <code>Person</code> table, create a <code>Person</code> object</li>
<li>For each person object, create a corresponding <code>Company</code> object</li>
<li>Count all people where the <code>Name</code> of the person&rsquo;s company is equal to &ldquo;IBM&rdquo;.</li></ul><p>The code above benefits from almost no optimization, instantiating a tremendous number of objects in order to yield a scalar result. The only side-effect that can be considered an optimization is that most of the related <code>Company</code> objects will be retrieved from cache rather than from the database. So that&rsquo;s a plus.</p>
<p>Still, the garbage collector is going to be running pretty hot and the database is going to see far more queries than necessary. [3]</p>
<h2>Attempt #2: Refine results on the database</h2><p>Let&rsquo;s try again, using Quino&rsquo;s fluent querying API. [4] The Quino ORM can map much of this API to SQL. Anything that is mapped to the database is not performed locally and is, by definition, more efficient. [5]</p>
<pre class=" "><code>var people = Session.GetList&lt;Person&gt;();
<strong class="highlight">people.Query.Join(Person.Relations.Company).WhereEqual(Company.Fields.Name, "IBM");</strong> [6]

Assert.That(people.Count, Is.GreaterThanEqual(140000));</code></pre><p>First, we get a list of people from the <code>Session</code>. As of the first line, we haven&rsquo;t actually gotten any data into memory yet—we&rsquo;ve only created a container for results of a certain type (<code>Person</code> in this case).</p>
<p>The default query for the list we created is to retrieve everything without restriction, as we saw in the first example. In this example, though, we restrict the <code>Query</code> to only the people that work for a company called &ldquo;IBM&rdquo;. At this point, we <em>still</em> haven&rsquo;t called the database.</p>
<p>The final line is the first point at which data is requested, so that&rsquo;s where the database is called. We ask the list for the number of entries that match it and it returns an impressive number of employees.</p>
<p>At this point, things look pretty good. In older versions of Quino, this code would already have been sufficiently optimized. It results in a single call to the database that returns a single scalar value with everything calculated on the database. Perfect.</p>
<h2>Attempt #3: Avoid creating objects at all</h2><p>However, since <a href="https://secure.encodo.ch/jira/browse/QNO-2939">v1.6.0</a> of Quino [7], the call to the property <code>IDataList.Count</code> has automatically populated the list with all matching objects as well. We made this change because the following code pattern was pretty common:</p>
<pre class=" "><code>var list = Session.GetList&lt;Person&gt;();
// Adjust query here
if (list.Count &gt; 0)
{
  // do something with all of the objects here
}</code></pre><p>That kind of code resulted in not one, but <em>two</em> calls to the database, which was killing performance, especially in high-latency environments.</p>
<p>That means, however, that the previous example is <em>still</em> going to pull 14,000 objects into memory, all just to count them and add them to a list that we&rsquo;re going to ignore. The garbage collector isn&rsquo;t a white-hot glowing mess anymore, but it&rsquo;s still throwing you a <a href="http://www.disapprovallook.com/">look of disapproval</a>.</p>
<p>Since we know that we don&rsquo;t want the objects in this case, we can get the old behavior back by making the following adjustment.</p>
<pre class=" "><code>var people = Session.GetList&lt;Person&gt;();
people.Query.Join(Person.Relations.Company).WhereEqual(Company.Fields.Name, "IBM");

Assert.That(<strong class="highlight">Session.GetCount(people.Query)</strong>, Is.GreaterThanEqual(140000));</code></pre><p>It would be even clearer to just forget about creating a list at all and work only with the query instead.</p>
<pre class=" "><code>var <strong class="highlight">query</strong> = Session.Get<strong class="highlight">Query</strong>&lt;Person&gt;();
<strong class="highlight">q</strong>uery.Join(Person.Relations.Company).WhereEqual(Company.Fields.Name, "IBM");

Assert.That(Session.GetCount(<strong class="highlight">query</strong>), Is.GreaterThanEqual(140000));</code></pre><p>Now that&rsquo;s a maximally efficient request for a number of people in Quino 1.10 as well.</p>
<p>Tune in next time for a look at what happens when a query can only be partially mapped to the database.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2950_1_body" class="footnote-number">[1]</span> I suppose it depends on what those requirements are, but if you think your application&rsquo;s performance requirements are so loose that it&rsquo;s OK to create millions of objects in memory just in order to count them, then you&rsquo;re probably not in the target audience for this article.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2950_2_body" class="footnote-number">[2]</span> Instead of using a code-first, Quino uses a &ldquo;metadata-first&rdquo; approach, so the  <code>Person</code> class used here is generated from the application metadata rather than written by the developer, as in other frameworks.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2950_3_body" class="footnote-number">[3]</span> <div class=" "><p>There are different strategies for retrieving associated data. Quino does not yet support retrieving anything other than root objects. That is, the associated <code>Company</code> object is not retrieved in the same query as the <code>Person</code> object.</p>
<p>In the example in question, the first indication that the ORM has that a <code>Company</code> is required is when the lambda retrieves them <em>individually</em>. Even if the original query had somehow indicated that the <code>Company</code> objects were also desired (e.g. using something like <code>Include(Person.Relations.Company)</code> as you would in EF), the most optimal mapping strategy is still not clear.</p>
<p>Should the mapper join the company table and retrieve that highly redundant data with each person? Or should it execute a single query for all companies and prime a cache with those? The right answer depends on the latency and bandwidth between the ORM and the database as well as myriad other conditions. When dealing with a lot of data, it&rsquo;s not hard to find examples where the default behavior of even a clever ORM isn&rsquo;t maximally efficient—or even very efficient at all.</p>
<p>As we already noted, though, the example in question does everything in memory. If we reasonably assume that the people belong to a relatively small number of companies—say q<span style="vertical-align: sub; font-size: smaller">c</span>—then the millions of calls to retrieve companies associated with people will result in a lot of cache hits and generate &ldquo;only&rdquo; q<span style="vertical-align: sub; font-size: smaller">c</span> + 1 queries.</p>
</div></div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2950_4_body" class="footnote-number">[4]</span> Quino does not have LINQ to SQL support. I&rsquo;m not even going to write &ldquo;yet&rdquo; at the end of that sentence because it&rsquo;s not at all clear that we&rsquo;re ever going to have it. Popular demand might convince us otherwise, but for now we&rsquo;re quite happy with our API (and soon-to-be-revealed query language QQL).</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2950_5_body" class="footnote-number">[5]</span> That&rsquo;s an assumption I&rsquo;m going to make for which counterexamples certainly exist, but none of which apply to the simple examples we&rsquo;ll address in this article.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2950_6_body" class="footnote-number">[6]</span> The <code>Person.Relations</code> and <code>Person.Fields</code> static fields are generated with the <code>Person</code> class. These correspond to the application metadata and change when the metadata changes. Developers are encouraged to use these generated constants so that even metadata-based queries can be validated by the compiler.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2950_7_body" class="footnote-number">[7]</span> That was in almost three years ago, in June of 2011.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2943</guid>
    <title><![CDATA[Generating JSON from Dart object graphs]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2943</link>
    <pubDate>Sat, 01 Feb 2014 17:09:41 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">1. Feb 2014 17:09:41 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/2943/dart_logo_270x270.png"><img src="https://www.earthli.com/data/news/attachments/entry/2943/dart_logo_270x270_tn.png" alt=" " class=" align-left"></a>A while back, I participated in an evaluation of languages that could replace JavaScript for our web front-end development language at <a href="http://encodo.com">Encodo</a>. We took a look at two contenders: Dart and TypeScript. At the time, Dart was weaker for the following reasons:</p>
<ul>
<li>It had not yet been released</li>
<li>It had little to no tool support</li>
<li>Integration with existing JS libraries was somewhat laborious</li></ul><p>Though TypeScript has its weaknesses (it has technically not yet hit a 1.0 release), we eventually decided to go in that direction. The tool support in Visual Studio and ReSharper are both improving steadily and have gotten quite good. We&rsquo;ve had quite positive results in one larger project.</p>
<p>Even with Dart in our wake, I am still curious to see how people are using it. I was surprised by the claims in the article <a href="http://maxhorstmann.net/2014/01/31/why-dart-should-learn-json-while-its-still-young/">Why Dart should learn JSON while it’s still young</a> by <cite>Max Horstmann</cite>.</p>
<p>Since Dart is not directly compatible with JavaScript, as TypeScript is, neither can a given JSON-formatted string be implicitly interpreted. Instead, you can import it using a library function. This is not really a problem, though one wonders if there are performance penalties for Dart that are not present in JavaScript/TypeScript.</p>
<p>Where the problem arises is in <em>exporting</em> JSON, which does not happen automagically. In non–client-side languages like C#, NewtonSoft&rsquo;s JSON.Net library can serialize pretty much anything using reflection. JSON isn&rsquo;t baked into the language, but that isn&rsquo;t too surprising. However, in Dart, positioned as a contender for taking over from JavaScript as the client-side language of choice, the solution recommended even by Dart language gurus is to implement <code>toJson()</code> on <em>all</em> objects that you want to export.</p>
<p>Either that, or use a probably non-optimized external library to serialize your object to JSON (likely using introspection, as JSON.Net does). I agree with the author of the blog that this is a red flag for using Dart in production projects. It&rsquo;s strange that Dart doesn&rsquo;t produce JSON without relying on external libraries. And the recommended library is, as of this writing, of pre-production/alpha quality—the version number is 0.1.0 and the TODO list includes a bullet point that exhorts the author to <span class="quote-inline">&ldquo;Write tests!&rdquo;</span>.</p>
<p>So I&rsquo;m still waiting to see what becomes of Dart, but the balkiness of the current solution for generating JSON not only makes it a bit of tough fit for many current web applications, but also makes us urge caution despite its having recently been released (1.0 came out in November 2013).</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2942</guid>
    <title><![CDATA[The Ruby language: where you can randomize your base class]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2942</link>
    <pubDate>Sat, 01 Feb 2014 12:38:27 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">1. Feb 2014 12:38:27 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><a href="https://www.earthli.com/data/news/attachments/entry/2942/ruby.png"><img src="https://www.earthli.com/data/news/attachments/entry/2942/ruby_tn.png" alt=" " class=" align-right"></a>I have never really examined Ruby in detail but it seems to be even more of a treasure-trove of ad-hoc features than PHP.</p>
<p>It takes full advantage of being evaluated at run-time to offer features that I haven&rsquo;t seen in even other dynamic languages. Some of these features seem like they might be nice shortcuts but also seem like they would be difficult  to optimize. Not only that, but they seem so obscure that they would likely will trip up even more seasoned users of the language.</p>
<p>At any rate, the one I found to be most brash was <a href="http://stackoverflow.com/questions/63998/hidden-features-of-ruby/474888#474888">methods in class definitions</a> by <cite>bjeanes</cite> (<cite><a href="http://stackoverflow.com/">StackOverflow</a></cite>). (The article is a treasure trove of other gems, no pun intended.)</p>
<p>The example below shows how that might work.</p>
<pre class=" "><code>class RandomSubclass &lt; [Array, Hash, String, Fixnum, Float, TrueClass].sample

end

RandomSubclass.superclass # could output one of 6 different classes.</code></pre><p>The language allows you to call methods from the &ldquo;extends&rdquo; clause. The example above creates an array of class names, then calls the <code>sample</code> method on them to yield a base class. The actual base class is not only unknown at compile time, it is also <em>unpredictable</em> at runtime.</p>
<p>The example above is contrived and makes the feature seem like it&rsquo;s only for the reckless. It&rsquo;s clear that serious software would have to forbid or strictly limit the use of such a feature, but I can see where it would be useful.</p>
<p>For example, you may want to change your base class depending on deployment parameters. If you&rsquo;re deploying to a testing or staging environment, you&rsquo;ll use a base class that includes more logging, profiling and debugging code. For production, you switch to a base class that&rsquo;s optimized. If the class interface remains the same, then using this feature wouldn&rsquo;t be as dangerous as it initially appeared.</p>
<p>Still, ensuring quality and enforcing architecture in software written in such a language would require a strict development process and discipline and vigilance from all involved.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2909</guid>
    <title><![CDATA[Apple Developer Videos]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2909</link>
    <pubDate>Sun, 05 Jan 2014 11:46:53 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">5. Jan 2014 11:46:53 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>It&rsquo;s well-known that Apple runs a walled garden. Apple makes its developers pay a yearly fee to get access to that garden. In fairness, though, they do provide some seriously nice-looking APIs for their iOS and OS X platforms. They&rsquo;ve been doing this for years, as listed in the post <a href="http://berzniz.com/post/72083083450/ios-7-only-is-the-only-sane-thing-to-do">iOS 7 only is the only sane thing to do</a> by <cite>Tal Bereznitskey</cite>. It argues that the new stuff in iOS 7 is compelling enough to make developers consider dropping support for all older operating systems. And this for pragmatic reasons, such as having far less of your own code to support and correspondingly making the product cost less to support. It&rsquo;s best to check your actual target market, but Apple users tend to upgrade very quickly and reliably, so an iOS 7-only strategy is a good option.</p>
<p>Among the improvements that Apple has brought in the recent past are blocks (lambdas), GCD (asynchronous execution management) and ARC (mostly automated memory management), all introduced in iOS 4 and OS X 10.6 Snow Leopard. OS X 10.9 Mavericks and iOS 7 introduced a slew of common UI improvements (e.g. AutoLayout and HTML strings for labels). [1]</p>
<p><small class="notes">To find the videos listed below, browse to <a href="https://developer.apple.com/videos/wwdc/2013/">WWDC 2013 Development Videos</a>.</small></p>
<p>For the web, Apple has improved developer tools and support in Safari considerably. There are two pretty good videos demonstrating a lot of these improvements:</p>
<dl><dt class="field">#601: Getting to Know Web Inspector</dt>
<dd>This video shows a lot of improvements to Safari 7 debugging, in the form of a much more fluid and intuitive Web Inspector and the ability to save changes made there directly back to local sources.</dd>
<dt class="field">#603: Getting the Most Out of Web Inspector</dt>
<dd>This video shows how to use the performance monitoring and analysis tools in Safari 7. The demonstration of how to optimize rendering and compositing layers was really interesting.</dd>
</dl><p>For non-web development, Apple has been steadily introducing libraries to provide support for common application tasks, the most interesting of which are related to UI APIs like Core Image, Core Video, Core Animation, etc.</p>
<p>Building on top of these, Apple presents the Sprite Kit—for building 2D animated user interfaces and games—and the Scene Kit—for building 3D animated user interfaces and games. There are some good videos demonstrating these APIs as well.</p>
<dl><dt class="field">#500: What’s New in Scene Kit</dt>
<dd>An excellent presentation content-wise; the heavily accented English is sometimes a bit difficult to follow, but the material is top-notch.</dd>
<dt class="field">#502: Introduction to Sprite Kit</dt>
<dd>This is a good introduction to nodes, textures, actions, physics and the pretty nice game engine that Apple delivers for 2D games.</dd>
<dt class="field">#503: Designing Games with Sprite Kit</dt>
<dd>The first half is coverage of tools and assets management along with more advanced techniques. The second half is with game designers Graeme Devine [2] and Spencer Lindsay, who designed the full-fledged online multi-player game <em>Adventure</em> to showcase the Sprite Kit.</dd>
</dl><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2909_1_body" class="footnote-number">[1]</span> Disclaimer: I work with C# for Windows and HTML5 applications of all stripes. I don&rsquo;t actually work with any of these technologies that I listed above. The stuff looks fascinating, though and, as a framework developer, I&rsquo;m impressed by the apparent cohesiveness of their APIs. Take recommendations with a grain of salt; it could very well be that things are a good deal less rosy when you actually have to work with these technologies.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2909_2_body" class="footnote-number">[2]</span> Formerly of Trilobyte and then id Software, now at Apple.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2904</guid>
    <title><![CDATA[Brilliant articles by the funniest guy at Microsoft]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2904</link>
    <pubDate>Sun, 29 Dec 2013 23:09:53 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">29. Dec 2013 23:09:53 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I recently stumbled upon some <a href="http://blogs.msdn.com/b/oldnewthing/archive/2013/12/24/10484402.aspx">Essays from the funniest man in Microsoft Research</a> by <cite>Raymond</cite> (<cite><a href="http://blogs.msdn.com/">Old New Thing</a></cite>). He is such a funny writer that this article, against convention, will consist mostly of citations rather than an even mix of citations and paraphrasing that I naturally consider to be much more lucid and pithy. I quote at length to do the material justice, for documentation and to ensure that you all download the PDFs to see if there is more where that came from (there is). All emphases have been added.</p>
<dl><dt><a href="http://research.microsoft.com/en-us/people/mickens/nestofhornets.pdf">Mobile Computing Research Is a Hornet’s Nest of Deception and Chicanery</a> by <cite>James Mickens</cite> (<cite><a href="http://research.microsoft.com/">Microsoft Research</a></cite>) (PDF)</dt>
<dd><div class=" "><p>On the delusions of the mobile-computing world:</p>
<blockquote class="quote quote-block "><div>&ldquo;Mobile computing researchers are a special kind of menace. They don’t smuggle rockets to Hezbollah, or clone baby seals and then make them work in sweatshops for pennies a day. That’s not the problem with mobile computing people. The problem with mobile computing people is that they have no shame. They write research papers with titles like “Crowdsourced Geolocation-based Energy Profiling for Mobile Devices,” <strong>as if the most urgent deficiency of smartphones is an insufficient composition of buzzwords.</strong>&rdquo;</div></blockquote><p>On browsing web pages:</p>
<blockquote class="quote quote-block "><div>&ldquo;When I use a mobile browser to load a web page, I literally have no expectation that anything will ever happen. A successful page load is so unlikely, so unimaginable, that <strong>mobile browsers effectively exist outside of causality</strong>—the browser is completely divorced from all action verbs, and can only be associated with sad, falling-tone sentences like “I had to give up after twenty seconds.” &rdquo;</div></blockquote><p>On the fragility of touchscreens:</p>
<blockquote class="quote quote-block "><div>&ldquo;Note that, when I say that you will “drop” your touchscreen, I do not mean “drop” in the layperson sense of “to release from a non-trivial height onto a hard surface.” I mean “drop” in the sense of “to place your touchscreen on any surface that isn’t composed of angel feathers and the dreams of earnest schoolchildren.” Phones and tablets apparently require Planck-scale mechanical alignments, such that merely looking at the touchscreen introduces fundamental, quantum dynamical changes in the touchscreen’s dilithium crystals. Thus, <strong>if you place your touchscreen on anything, ever, you have made a severe and irreversible life mistake.</strong>&rdquo;</div></blockquote><p>On the sheer <em>touchiness</em> of touchscreens:</p>
<blockquote class="quote quote-block "><div>&ldquo;On your touchscreen, your swipes will become pinches, and your pinches will become scrolls, and each one of your scrolls will become a complex thing never before seen on this earth, a <strong>leviathan meta-touch event of such breadth and complexity that your phone can only respond like Carrie White at the prom.</strong> So, your phone just starts doing stuff, all the stuff that it knows how to do, and it’s just going nuts, and your apps are closing and opening and talking to the cloud and configuring themselves in unnatural ways, and your phone starts vibrating and rumbling with its little rumble pack, and it will gently sing like a tiny hummingbird of hate, and you’ll look at the touchscreen, and <strong>you’ll see that things are happening, my god, there are so many happenings</strong>, and you’ll try to flip the phone over and take out the battery, because now you just want to kill it and move to Kansas and start over, […]&rdquo;</div></blockquote><p>On the uselessness of most mobile computing:</p>
<blockquote class="quote quote-block "><div>&ldquo;When you purchase a mobile device, you are basically saying, “<strong>I endorse the operational inefficiency of the modern bourgeoisie lifestyle</strong>, even though I could find a rock and tie a coat hanger around it and have a better chance of having a phone conversation that doesn’t sound like two monsters arguing about German poetry.”&rdquo;</div></blockquote></div></dd>
<dt><a href="http://research.microsoft.com/en-us/people/mickens/theslowwinter.pdf">The Slow Winter</a> by <cite>James Mickens</cite> (<cite><a href="http://research.microsoft.com/">Microsoft Research</a></cite>) (PDF)</dt>
<dd><div class=" "><p>On flying in the early 21st century:</p>
<blockquote class="quote quote-block "><div>&ldquo;The point is that flying in airplanes used to be fun, but now <strong>it resembles a dystopian bin-packing problem</strong> in which humans, carry-on luggage, and five dollar peanut bags compete for real estate while crying children materialize from the ether and make obscure demands in unintelligible, Wookie-like languages while <strong>you fantasize about who you won’t be helping when the oxygen masks descend.</strong>&rdquo;</div></blockquote><p>On how awesome it was being a hardware architect before things got all quantum and messy:</p>
<blockquote class="quote quote-block "><div>&ldquo;Of course, pride precedes the fall, and at some point, you realize that to implement aggressive out-of-order execution, you need to fit more transistors into the same die size, but then a material science guy pops out of a birthday cake and says YEAH WE CAN DO THAT, and by now, you’re touring with Aerosmith and throwing Matisse paintings from hotel room windows, because <strong>when you order two Matisse paintings from room service and you get three, that equation is going to be balanced.</strong> It all goes so well, and the party keeps getting better. When you retire in 2003, your face is wrinkled from all of the smiles, and even though you’ve been sued by several pedestrians who suddenly acquired rare paintings as hats, you go out on top, the master of your domain. &rdquo;</div></blockquote><p>On quantum-level effects in modern processors:</p>
<blockquote class="quote quote-block "><div>&ldquo;They randomly switched states; they leaked voltage; <strong>they fell prey to the seductive whims of cosmic rays that, unlike the cosmic rays in comic books, did not turn you into a superhero</strong>, but instead made your transistors unreliable and shiftless, like a surly teenager who is told to clean his room and who will occasionally just spray his bed with Lysol and declare victory.&rdquo;</div></blockquote><p>On scaling in cores when processor speed and more transistors became too messy:</p>
<blockquote class="quote quote-block "><div>&ldquo;John did what any reasonable person would do: he cloaked himself in a wall of denial and acted like nothing had happened. “Making processors faster is increasingly difficult,” John thought, “but maybe people won’t notice if I give them more processors.” This, of course, was a variant of the notorious Zubotov Gambit, <strong>named after the Soviet-era car manufacturer who abandoned its attempts to make its cars not explode, and instead offered customers two Zubotovs for the price of one</strong> […]&rdquo;</div></blockquote><p>On the main purpose that people have for their computers:</p>
<blockquote class="quote quote-block "><div>&ldquo;Lay people use their computers for precisely ten things, none of which involve massive computational parallelism, and seven of which <strong>involve procuring a vast menagerie of pornographic data</strong> and then curating that data using a variety of fairly obvious management techniques, like the creation of a folder called “Work Stuff,” which contains an inner folder called “More Work Stuff,” where “More Work Stuff” contains a series of ostensible documentaries that describe the economic interactions between people who don’t have enough money to pay for pizza and people who aren’t too bothered by that fact. &rdquo;</div></blockquote><p>A summary of the state of the world of hardware design and development:</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] you brought the fire down from Olympus, and the mortals do with it what they will. But now, all the easy giants were dead, and John was <strong>left to fight the ghosts that Schrödinger had left behind.</strong>&rdquo;</div></blockquote></div></dd>
<dt><a href="http://research.microsoft.com/en-us/people/mickens/thenightwatch.pdf">The Night Watch</a> by <cite>James Mickens</cite> (<cite><a href="http://research.microsoft.com/">Microsoft Research</a></cite>) (PDF)</dt>
<dd><div class=" "><p>What it&rsquo;s like to be a systems (low-level) programmer:</p>
<blockquote class="quote quote-block "><div>&ldquo;A systems programmer will know what to do when society breaks down, because <strong>the systems programmer already lives in a world without law.</strong>&rdquo;</div></blockquote><p>On why people still use C++ (or a response to the snotty question of: &ldquo;why don&rsquo;t you just use high-level language <em>X</em> instead?&rdquo;)</p>
<blockquote class="quote quote-block "><div>&ldquo;Why not use a modern language with garbage collection and functional programming and free massages after lunch? Here’s the answer: Pointers are real. They’re what the hardware understands. <strong>Somebody has to deal with them.</strong> You can’t just place a LISP book on top of an x86 chip and hope that the hardware learns about lambda calculus by osmosis. […] Pointers are like […] real, living things that must be dealt with so that polite society can exist. Make no mistake, I don’t want to write systems software in a language like C++. […] When it’s 3 A.M., and you’ve been debugging for 12 hours, and you encounter a virtual static friend protected volatile templated function pointer, you want to […] <strong>find the people who wrote the C++ standard and bring ruin to the things that they love.</strong>&rdquo;</div></blockquote><p>On being thankful for systems programmers:</p>
<blockquote class="quote quote-block "><div>&ldquo;That being said, if you find yourself drinking a martini and writing programs in garbage-collected, object-oriented Esperanto, be aware that <strong>the only reason that the Esperanto runtime works is because there are systems people who have exchanged any hope of losing their virginity</strong> for the exciting opportunity to think about hex numbers and their relationships with the operating system, the hardware, and ancient blood rituals that Bjarne Stroustrup performed at Stonehenge.&rdquo;</div></blockquote><p>On how difficult it is to work in extremely fragile territory (rather than a safe runtime):</p>
<blockquote class="quote quote-block "><div>&ldquo;Indeed, I would [have…checked the log files for errors] if I hadn’t broken every component that a logging system needs to log data. I have a network file system, and I have broken the network, and I have broken the file system, <strong>and my machines crash when I make eye contact with them.</strong> I HAVE NO TOOLS BECAUSE I’VE DESTROYED MY TOOLS WITH MY TOOLS.&rdquo;</div></blockquote><p>A backhanded swipe at the utter uselessness of many UI concerns:</p>
<blockquote class="quote quote-block "><div>&ldquo;I’m glad that people are working on new kinds of bouncing icons because <strong>they believe that humanity has solved cancer and homelessness and now lives in a consequence-free world</strong> of immersive sprites.&rdquo;</div></blockquote></div></dd>
</dl>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2890</guid>
    <title><![CDATA[How to fool people into giving up their email address]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2890</link>
    <pubDate>Thu, 07 Nov 2013 20:56:06 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">7. Nov 2013 20:56:06 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>On <a href="http://codecademy.com">Codecademy</a>, you can learn to program in various languages. It starts off very slowly and is targeted at non-technical users. That&rsquo;s their claim anyway—the material in the courses I looked at ramps up pretty quickly.</p>
<p>Anyway, the interesting thing I saw was in their introductory test. It struck me as a subtle way to get you to enter your email address. I&rsquo;d just recently discussed this on a project I&rsquo;m working on: how can we make it fun for the user to enter personal information? The goal is not to sell that information (not yet anyway, but who knows what the future holds), but to be able to enhance—nay, <em>personalize</em>—the service.</p>
<p>Personalizing has a bad reputation but can be very beneficial. For example, if you&rsquo;re using a site for free and you&rsquo;re going to see offers and advertisements anyway, isn&rsquo;t it better to enter a bit of data that will increase the likelihood that offers and ads are interesting? Each person can—and should—decide for the themselves what to make public, but the answer isn&rsquo;t always necessarily <em>no</em>.</p>
<h2>How Codecademy gets your email</h2><p><span style="width: 467px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/2890/first_prompt.png"><img src="https://www.earthli.com/data/news/attachments/entry/2890/first_prompt.png" alt=" " style="width: 467px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/2890/first_prompt.png">First prompt</a></span></span></p>
<p>Here they teach you how to use the &ldquo;length&rdquo; method by measuring your email address. Sneaky. I like it.</p>
<p><span style="width: 441px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/2890/second_prompt.png"><img src="https://www.earthli.com/data/news/attachments/entry/2890/second_prompt.png" alt=" " style="width: 441px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/2890/second_prompt.png">Second prompt</a></span></span></p>
<p>Even if you don&rsquo;t given them an address, they re-prompt you to enter your email, but it doesn&rsquo;t come across as pushy because you&rsquo;re taking a test.</p>
<p>I thought that this was pretty subtle. Because of the context, people who would ordinarily be sensitive to giving up their email might not even notice. Why? Because they want to answer the question *correctly*. They don&rsquo;t want the site to judge them for having entered something wrong, so they do as they&rsquo;re told.</p>
<p>Is Codecademy collecting emails this way? I have no way to be sure, but they&rsquo;d be silly not to.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2859</guid>
    <title><![CDATA[The HTML5 AppCache and HTTP Authentication]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2859</link>
    <pubDate>Sun, 03 Nov 2013 11:17:36 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">3. Nov 2013 11:17:36 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">The following article was originally published on the <a href="http://encodo.com/en/blogs.php?entry_id=313">Encodo blogs</a> and is cross-published here.</small></p>
<p><hr></p>
<blockquote class="quote abstract "><div>The following article outlines a solution to what may end up being a temporary problem. The conditions are very specific: no server-side logic; HTTP authentication; AppCache as it is implemented by the target platforms—Safari Mobile and Google Chrome—in late 2012/early 2013. The solution is not perfect but it&rsquo;s workable. We&rsquo;re sharing it here in the hope that it can help someone else or serve as a base for a better solution.</div></blockquote><h2>The HTML5 AppCache</h2><p>The application cache is a relatively new feature that is,</p>
<ul>
<li>Supported by all modern browsers</li>
<li>Uses a manifest file that indicates which files to cache</li>
<li>Browser checks manifest for changes</li>
<li>If there are changes, all files are refreshed</li>
<li>External links work when online</li>
<li>When offline, the application works with the local cache</li>
<li>External links to non-cached content are redirected to fallback links</li></ul><h2>AppCache Limitations</h2><p>Web applications can use the HTML5 application-cache to store local content, but different browsers apply different restrictions to the amount of space allocated per domain.</p>
<ul>
<li>Safari Mobile is limited to 50MB per domain. This means that the restriction will generally apply to all content packages downloaded from the same server/domain</li>
<li>Google Chrome is limited as well, but the actual limit is a bit of a moving target</li></ul><h2>Optimizing the HTML5 AppCache for Authenticated Content</h2><p>In particular, the Safari Mobile browser cannot update the application cache for files for which it must obtain authentication.</p>
<ul>
<li><div>Some requests do not trigger authentication<ul>
<li>Manifest file</li>
<li>Home-screen icons</li></ul></div></li>
<li>A lost connection or timeout can invalidate the authentication token</li>
<li><div>Version checks are not reliable<ul>
<li>Open pages/running apps do not check for status updates</li>
<li>Home-screen apps don’t reliably check on startup</li>
<li>This can lead to <strong>out-of-date</strong> or <strong>missing</strong> content</li></ul></div></li></ul><h2>Checking for and presenting updates to the user</h2><p>The graphic below illustrates the mechanism by which a content package in a web application can manage content updates and present them to the user.</p>
<ul>
<li>When online, the software regularly checks whether an update for the package is available</li>
<li>The user can determine whether to install an update</li>
<li>When an update has been found, the software stops checking for updates until the user has applied the latest update</li>
<li>If the user delays the update, the user interface displays an “update” button</li>
<li>The software will automatically start checking for updates whenever it detects that it is online</li>
<li>There is no way for a user to ignore updates</li>
<li>When the user proceeds with an update, the latest version is retrieved at that time, ensuring that the user has the latest version</li></ul><p><span style="width: 654px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/2859/update_activity_diagram.png" alt=" " style="width: 654px"></span><span class="auto-content-caption">Activity Diagram for Software Update Cycle</span></span></p>
<h2>Solving the problems with authenticated data and the AppCache</h2><p>In order to address the problems described above, the UA products use a separate version file to check for updates independent of the browser’s application-cache mechanism and to trigger this update only when authentication has been reestablished.<br>
 <br>
<span style="width: 598px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/2859/update.png" alt=" " style="width: 598px"></span><span class="auto-content-caption">Sequence Diagram for Software Update Cycle</span></span></p>
<ul>
<li>The cache.version.txt file is publicly available but is very small and includes only a unique version number that is also included in the cache.manifest file (both of which are generated by a deployment script).</li>
<li>The software compares this version number against the last known good version number. If it differs, it knows that the server has been updated with new content for this package</li>
<li>Before the software can kick off the HTML5 AppCache update process, it must ensure that the user is authenticated and authorized to retrieve the update package (because most browsers will simply fail silently if this is not the case).</li>
<li>The software pulls the force.password.txt file from the private zone with an explicit request. The browser will ask the user to authenticate, if necessary. This file is also very small to avoid needlessly downloading a large amount of data simply to force re-authentication.</li>
<li>Once the user has authenticated, the software lets the automated HTML5 AppCache update take over, retrieving first the cache.manifest file and then updating files as needed. The user is notified that this download is taking place asynchronously.</li>
<li>The software receives a notification from the browser that the update is complete and can record the version number and then notify the user that the update has been applied and is ready to use.</li></ul><p>This approach worked relatively well for us, although we continue to refine it based on feedback and experience.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2288</guid>
    <title><![CDATA[Entity Framework Generated SQL]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2288</link>
    <pubDate>Mon, 21 Oct 2013 22:56:04 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Oct 2013 22:56:04 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">12. Jun 2018 20:06:15 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">Microsoft just recently released <a href="http://weblogs.asp.net/scottgu/archive/2013/10/17/announcing-the-release-of-visual-studio-2013-and-great-improvements-to-asp-net-and-entity-framework.aspx">Visual Studio 2013</a>, which includes Entity Framework 6 and introduces <a href="http://msdn.microsoft.com/en-us/data/JJ574253">a lot of new features</a>. It reminded me of the following query that EF generated for me, way, way back when it was still version 3.5. Here&rsquo;s hoping that they&rsquo;ve taken care of this problem since then.</small></p>
<p>So, the other day EF (v3.5) seemed to be taking quite a while to execute a query on SQL Server. This was a pretty central query and involved a few joins and restrictions, but wasn&rsquo;t anything too wild. All of the restrictions and joins were on numeric fields backed by indexes.</p>
<p>In these cases, it&rsquo;s always best to just fire up the profiler and see what kind of SQL is being generated by EF. It was a pretty scary thing (I&rsquo;ve lost it unfortunately), but I did manage to take a screenshot of the query plan, shown below.</p>
<p><span style="width: 605px; display: table"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/2288/ef_sql.jpg"><img src="https://www.earthli.com/data/news/attachments/entry/2288/ef_sql.jpg" alt=" " style="width: 605px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/2288/ef_sql.jpg">EF Query Plan</a></span></span></p>
<p>It doesn&rsquo;t look too bad until you notice that the inset on the bottom right (the black smudgy thing) is a representation of the <em>entire query</em> … and that it just kept going on down the page.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2872</guid>
    <title><![CDATA[Ignoring files with Git]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2872</link>
    <pubDate>Mon, 15 Jul 2013 01:38:50 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">15. Jul 2013 01:38:50 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The helpful page, <a href="https://help.github.com/articles/ignoring-files">Ignoring files</a> (<cite><a href="http://help.github.com/">GitHub</a></cite>), taught me something I didn&rsquo;t know: there&rsquo;s a file you can use to ignore files in your local Git repository without changing anyone else&rsquo;s repository.</p>
<p>Just to recap, here are the ways to ignore a file:</p>
<ul>
<li><strong>Global <code>.gitignore</code></strong>: you can designate basic exclusion directives that apply to all repositories on your system. This file is not committed to any repository or shared with others. Execute <code>git config –global core.excludesfile ~/.gitignore_global</code> to set the file to <code>~/.gitignore_global</code> (for example). See the <a href="https://help.github.com/articles/ignoring-files">linked article</a> for sample directives.</li>
<li><strong>Per-repository global exclusions</strong>:  add directives to the <code>.git/info/exclude</code> file in any repository. These directives are combined with any system-global directives to form the base exclusions for that repository. This file is not committed with the repository. This is the one I&rsquo;d never heard of before.</li>
<li><strong><code>.gitignore</code></strong>: add a file with this name to any directory. The directives in that file are merged with those from the parent directory to define the patterns that are excluded in that directory and all child directories. This is definitely the most common way to exclude files.</li>
<li><strong>Exclude versioned files</strong>: and, finally, if your repository has files that are changed but not committed (e.g. configuration files), you can ignore future changes to those files with a call to <code>git update-index –assume-unchanged path/to/file.txt</code>. While this can be useful for legacy projects, it&rsquo;s best to structure new projects so developers don&rsquo;t have to rely on easily forgotten tricks like this.</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2870</guid>
    <title><![CDATA[Some new CSS length units (and some lesser-known ones)]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2870</link>
    <pubDate>Sun, 14 Jul 2013 23:17:53 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">14. Jul 2013 23:17:53 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I&rsquo;ve been using CSS since its inception and use many parts of the CSS3 specification for both personal work and work I do for <a href="http://encodo.com">Encodo</a>. Recently, I read about some length units I&rsquo;d never heard of in the article <a href="http://dev.opera.com/articles/view/css-viewport-units/">CSS viewport units: vw, vh, vmin and vmax</a> by <cite>Chris Mills</cite> (<cite><a href="http://dev.opera.com/">Dev.Opera</a></cite>).</p>
<ul>
<li><code>1vw</code>: 1% of viewport width</li>
<li><code>1vh</code>: 1% of viewport height</li>
<li><code>1vmin</code>: <code>1vw</code> or <code>1vh</code>, whatever is smallest</li>
<li><code>1vmax</code>: <code>1vw</code> or <code>1vh</code>, whatever is largest</li></ul><p>These should be eminently useful for responsive designs. While there is wide support for these new units, that support is only available in the absolute latest versions of browsers. See the article for a good example of how these can be used.</p>
<p>While the ones covered in the article are actually new, there are others that have existed for a while but that I&rsquo;ve never had occasion to use. The <a href="http://www.w3.org/TR/css3-values/#font-relative-lengths">Font-relative lengths: the ‘em’, ‘ex’, ‘ch’, ‘rem’ units</a> (<cite><a href="http://www.w3.org/">CSS Values and Units Module Level 3</a></cite>) section lists the following units:</p>
<ul>
<li><code>em</code>: This one is well-known: <code>1em</code> is equal to the <span class="quote-inline">&ldquo;computed value of the &lsquo;font-size&rsquo; property of the element on which it is used.&rdquo;</span></li>
<li><code>ex</code>: Equal to the height of the letter &lsquo;x&rsquo; in the font of the element on which it is used. This is useful when you want to size a container based on the height of a lower-case letter—i.e. tighter—rather than on the full size of the font (as you get with <code>em</code>).</li>
<li><code>ch</code>: <span class="quote-inline">&ldquo;Equal to the advance measure of the &ldquo;0&rdquo; (ZERO, U+0030) glyph found in the font used to render it.&rdquo;</span> Since all digits in a font should be the same width, this unit is probably useful for pages that need to measure and render numbers in a reliable vertical alignment.</li>
<li><code>rem</code>: The same as <code>em</code> but always returns the value for the root element of the page rather than the current element. Elements that use this unit will all scale against a common size, independently of the font-size of their contents. <a href="http://css-tricks.com/theres-more-to-the-css-rem-unit-than-font-sizing/">There’s more to the CSS rem unit than font sizing</a> by <cite>Roman Rudenko</cite> (<cite><a href="http://css-tricks.com/">CSS-Tricks</a></cite>) has a lot more information and examples, as well as an explanation of how <code>rem</code> can stand in for the still nascent support for <code>vw</code>.</li></ul>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2857</guid>
    <title><![CDATA[.NET 4.5.1 and Visual Studio 2013 previews are available]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2857</link>
    <pubDate>Sat, 29 Jun 2013 17:00:15 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">29. Jun 2013 17:00:15 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">29. Jun 2013 17:04:02 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">The following article was originally published on the <a href="http://encodo.com/en/blogs.php?entry_id=314">Encodo blogs</a> and is cross-published here.</small></p>
<p><hr></p>
<p>The article <a href="http://blogs.msdn.com/b/dotnet/archive/2013/06/26/announcing-the-net-framework-4-5-1-preview.aspx">Announcing the .NET Framework 4.5.1 Preview</a> provides an incredible amount of detail about a relatively exciting list of improvements for .NET developers.</p>
<h2>x64 Edit &amp; Continue</h2><p>First and foremost, the Edit-and-Continue feature is now available for x64 builds as well as x86 builds. Whereas an appropriate cynical reaction is that &ldquo;it&rsquo;s about damn time they got that done&rdquo;, another appropriate reaction is to just be happy that they will finally support x64-debugging as a first-class feature in Visual Studio 2013.</p>
<p>Now that they have feature-parity for all build types, they can move on to other issues in the debugger (see the list of suggestions at the end). </p>
<h2>Async-aware debugging</h2><p>We haven&rsquo;t had much opportunity to experience the drawbacks of the current debugger vis à vis asynchronous debugging, but the experience outlined in the call-stack screenshot below is one that is familiar to anyone who&rsquo;s done multi-threaded (or multi-fiber, etc.) programming.</p>
<p><span style="width: 580px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/2857/0880.clip_image003_4ba42578.jpg" alt=" " style="width: 580px"></span><span class="auto-content-caption">Regular Call stack (VS2012)</span></span></p>
<p>Instead of showing the actual stack location in the thread within which the asynchronous operation is being executed, the new and improved version of the debugger shows a higher-level interpretation that places the current execution point within the context of the asnyc operation. This is much more in keeping with the philosophy of the async/await feature in .NET 4.5, which lets developers write asynchronous code in what appears to be a serial fashion. This improved readability has been translated to the debugger now, as well.</p>
<p><span style="width: 580px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/2857/5078.clip_image004_004481b4.jpg" alt=" " style="width: 580px"></span><span class="auto-content-caption">Async-aware Call stack (VS2013)</span></span></p>
<h2>Return-value inspection</h2><p>The VS2013 debugger can now show the <span class="quote-inline">&ldquo;direct return values and the values of embedded methods (the arguments)&rdquo;</span> for the current line. [1] Instead of manually selecting the text segment and using the Quick Watch window, you can now just see the chain of values in the &ldquo;Autos&rdquo; debugger pane.</p>
<p><span style="width: 434px; display: table"><span class="auto-content-inline"><img src="https://www.earthli.com/data/news/attachments/entry/2857/0724.clip_image008_1053506b.jpg" alt=" " style="width: 434px"></span><span class="auto-content-caption">Automatic return-value inspection</span></span></p>
<h2>Nuget Improvements</h2><blockquote class="quote quote-block "><div>&ldquo;We are also releasing an update in Visual Studio 2013 Preview to provide better support for apps that indirectly depend on multiple versions of a single NuGet package. You can think of this as sane NuGet library versioning for desktop apps.&rdquo;</div></blockquote><p>We&rsquo;ve been bitten by the afore-mentioned issue and are hopeful that the solution in Visual Studio 2013 will fill the gaps in the current release. The article describes several other improvements to the Nuget services, including integration with Windows Update for large-scale deployment. They also mentioned <span class="quote-inline">&ldquo;a curated list of Microsoft .NET Framework NuGet Packages to help you discover these releases, published in OData format on the NuGet site&rdquo;</span>, but don&rsquo;t mention whether the Nuget UI in VS2013 has been improved. The current UI, while not as awful and slow as initial versions, is still not very good for discovery and is quite clumsy for installation and maintenance.</p>
<h2>User Voice for Visual Studio/.NET</h2><p>You&rsquo;re not limited to just waiting on the sidelines to see which feature Microsoft has decided to implement in the latest version of .NET/Visual Studio. You should head over to the <a href="http://visualstudio.uservoice.com">User Voice for Visual Studio</a> site to get an account and vote for the issues you&rsquo;d like the to work on next.</p>
<p>Here&rsquo;s a list of the ones I found interesting, and some of which I&rsquo;ve voted on.</p>
<ul>
<li><strong>Support Edit &amp; Continue for all method bodies:</strong> While it is, to some degree, understandable that methods, fields and constants cannot be added or removed easily without restarting the debugger, method bodies can be modified. Unless they include lambdas or generics. Experience has shown that this means that we can&rsquo;t use Edit &amp; Continue for most of our code. VS needs to <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/4079440-edit-continue-allow-the-modification-of-lambda-">allow the modification of lambdas and anonymous methods</a> or the even higher-rated issue, <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2049821-debug-lambda-expressions">Debug Lambda expressions</a>. The other missing piece of this puzzle is to add <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/4030943-edit-continue-support-for-generics">Support for generics under Edit &amp; Continue</a>.</li>
<li><strong>Better Generics and Design-by-Contract support:</strong> Language feature requests include <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2122427-expand-generic-constraints-for-constructors">Expand Generic Constraints for constructors</a>, allow <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2315417-proper-generic-type-alising">[p]roper (generic) type ali[a]sing</a> and, near and dear to my heart, <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2304022-integrate-code-contract-keywords-into-the-main-ne">Integrate Code Contracts more deeply in the .NET Framework</a> or <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2304022-integrate-code-contract-keywords-into-the-main-ne">Integrate Code Contract Keywords into the main .Net Languages</a>.</li>
<li>There seem to be a lot of people asking Microsoft to work on <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3556619-silverlight-6">Silverlight 6</a>. Having developed several applications in Silverlight 5, we wouldn&rsquo;t be averse to seeing continued support rather than obsolescence for those projects. [2]</li>
<li><strong>Make Visual Studio run faster and leaner:</strong> There are also pleas to <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2255208-decrease-the-memory-footprint">Decrease the Memory Footprint</a> (of Visual Studio) or <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2255206-make-visual-studio-startup-and-shutdown-faster">Make Visual Studio startup and shutdown faster</a> and <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2197975-make-solutions-load-faster">Make [Visual Studio] Solutions Load Faster</a> or at least <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2255632-improve-performance-of-visual-studio-builds-and-ot">Improve performance of Visual Studio builds and other uses better when working with solutions with several projects (ex. 40+)</a>. Other ideas in this vein are add a <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2627855-visual-studio-task-manager">Visual Studio Task Manager</a> so we can at least see which components, plugins and panes are causing trouble. If all else fails, just <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2255687-make-vs-scalable-by-switching-to-64-bit">[m]ake VS scalable by switching to 64 bit</a>.</li></ul><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2857_1_body" class="footnote-number">[1]</span> In a similar vein, I found the issue <a href="http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3440221-bring-back-classic-visual-basic-an-improved-versi">Bring back Classic Visual Basic, an improved version of VB6</a> to be interesting, simply because of the large number of votes for it (1712 at the time of writing). While it&rsquo;s understandable that VB6 developers don&rsquo;t understand the programming paradigm that came with the transition to .NET, the utterly reactionary desire to go back to VB6 is somewhat unfathomable. It&rsquo;s 2013, you can&rsquo;t put the dynamic/lambda/jitted genie back in the bottle. If you can&rsquo;t run with the big dogs, you&rsquo;ll have to stay on the porch…and stop being a developer. There isn&rsquo;t really any room for software written in a glorified batch language anymore.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2857_2_body" class="footnote-number">[2]</span> This feature has been available for the unmanaged-code debugger (read: C++) for a while now.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2849</guid>
    <title><![CDATA[Deleting multiple objects in Entity Framework]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2849</link>
    <pubDate>Sat, 08 Jun 2013 09:43:11 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Jun 2013 09:43:11 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">9. Jun 2013 09:38:28 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">The following article was originally published on the <a href="http://encodo.com/en/blogs.php?entry_id= 311">Encodo blogs</a> and is cross-published here.</small></p>
<p><hr></p>
<p>Many improvements have been made to Microsoft&rsquo;s Entity Framework (EF) since I last used it in production code. In fact, we&rsquo;d last used it waaaaaay back in 2008 and 2009 when EF had just been released. Instead of EF, I&rsquo;ve been using the <a href="https://www.earthli.com/news/quino">Quino</a> ORM whenever I can.</p>
<p>However, I&rsquo;ve recently started working on a project where EF5 is used (EF6 is in the late stages of release, but is no longer generally available for production use). Though I&rsquo;d been following the latest EF developments via the <a href="http://blogs.msdn.com/b/adonet/">ADO.Net blog</a>, I finally had a good excuse to become more familiar with the latest version with some hands-on experience.</p>
<h2>Our history with EF</h2><p><a href="https://www.earthli.com/news/view_article.php?entry_id=158">Entity Framework: Be Prepared</a> was the first article I wrote about working with EF. It&rsquo;s quite long and documents the pain of using a 1.0 product from Microsoft. That version support only a database-first approach, the designer was slow and the ORM SQL-mapper was quite primitive. Most of the tips and advice in the linked article, while perhaps amusing, are no longer necessary (especially if you&rsquo;re using the Code-first approach, which is highly recommended).</p>
<p>Our next update, <a href="https://www.earthli.com/news/view_article.php?entry_id=163">The Dark Side of Entity Framework: Mapping Enumerated Associations</a>, discusses a very specific issue related to mapping enumerated types in an entity model (something that Quino does very well). This shortcoming in EF has also <a href="http://msdn.microsoft.com/en-us/data/hh859576.aspx">been addressed</a> but I haven&rsquo;t had a chance to test it yet.</p>
<p>Our final article was on performance, <a href="https://www.earthli.com/news/view_article.php?entry_id=178">Pre-generating Entity Framework (EF) Views</a>, which, while still pertinent, no longer needs to be done manually (there&rsquo;s an <a href="http://visualstudiogallery.msdn.microsoft.com/72a60b14-1581-4b9b-89f2-846072eff19d">Entity Framework Power Tools</a> extension for that now).</p>
<p>So let&rsquo;s just assume that that was the old EF; what&rsquo;s the latest and greatest version like?</p>
<p>Well, as you may have suspected, you&rsquo;re not going to get an article about Code-first or database migrations. [1] While a lot of things have been fixed and streamlined to be not only much more intuitive but also work much more smoothly, there are still a few operations that aren&rsquo;t so intuitive (or that aren&rsquo;t supported by EF yet).</p>
<h2>Standard way to delete objects</h2><p>One such operation is deleting multiple objects in the database. It&rsquo;s not that it&rsquo;s not possible, but that the only solution that immediately appears is to,</p>
<ul>
<li>load the objects to delete into memory,</li>
<li>then remove these objects from the context</li>
<li>and finally save changes to the context, which will remove them from the database</li></ul><p>The following code illustrates this pattern for a hypothetical list of users.</p>
<pre class=" "><code>var users = context.Users.Where(u =&gt; u.Name == "John");

foreach (var u in users)
{
  context.Users.Remove(u);
}

context.SaveChanges();</code></pre><p>This seems somewhat roundabout and quite inefficient. [2]</p>
<h2>Support for batch deletes?</h2><p>While the method above is fine for deleting a small number of objects—and is quite useful when removing different types of objects from various collections—it&rsquo;s not very useful for a large number of objects. Retrieving objects into memory only to delete them is neither intuitive nor logical.</p>
<p>The question is: is there a way to tell EF to delete objects based on a query from the database?</p>
<p>I found an example attached as an answer to the post <a href="http://stackoverflow.com/questions/9582632/simple-delete-query-using-ef-code-first">Simple delete query using EF Code First</a> (<cite><a href="http://stackoverflow.com/">Stack Overflow</a></cite>). The gist of it is shown below.</p>
<pre class=" "><code>context.Database.SqlQuery&lt;User&gt;(
  "DELETE FROM Users WHERE Name = @name",
  new [] { new SqlParameter("@name", "John") }
);</code></pre><p>To be clear right from the start, using ESQL is already sub-optimal because the identifiers are not statically checked. This query will cause a run-time error if the model changes so that the &ldquo;Users&rdquo; table no longer exists or the &ldquo;Name&rdquo; column no longer exists or is no longer a string.</p>
<p>Since I hadn&rsquo;t found anything else more promising, though, I continued with this approach, aware that it might not be usable as a pattern because of the compile-time trade-off.</p>
<p>Although the answer had four up-votes, it is not clear that either the author or any of his fans have actually tried to execute the code. The code above returns an <code>IEnumerable&lt;User&gt;</code> but doesn&rsquo;t actually <em>do</em> anything.</p>
<p>After I&rsquo;d realized this, I went to MSDN for more information on the <code>SqlQuery</code> method. The documentation is not encouraging for our purposes (still trying to <em>delete</em> objects without first <em>loading</em> them), as it describes the method as follows (emphasis added),</p>
<blockquote class="quote quote-block "><div>&ldquo;Creates a raw SQL query that will <strong>return</strong> elements of the given generic type. The type can be any type that has properties that match the names of the <strong>columns returned from</strong> the query, or can be a simple primitive type.&rdquo;</div></blockquote><p>This does not bode well for deleting objects using this method. Creating an enumerable does very little, though. In order to actually execute the query, you have to evaluate it. </p>
<p><em>Die Hoffnung stirbt zuletzt</em> [3] as we like to say on this side of the pond, so I tried evaluating the enumerable. A <code>foreach</code> should do the trick.</p>
<pre class=" "><code><strong class="highlight">var users = </strong>context.Database.SqlQuery&lt;User&gt;(
  "DELETE FROM Users WHERE Name = @name", 
  new [] { new SqlParameter("@name", "John") }
);

foreach (var u in users)
{
  // NOP?
}</code></pre><p>As indicated by the &ldquo;NOP?&rdquo; comment, it&rsquo;s unclear what one should actually <em>do</em> in this loop because the query already includes the command to delete the selected objects.</p>
<p>Our hopes are finally extinguished with the following error message:</p>
<div class="error ">System.Data.EntityCommandExecutionException : The data reader is incompatible with the specified &lsquo;Demo.User&rsquo;. A member of the type, &lsquo;Id&rsquo;, does not have a corresponding column in the data reader with the same name.</div><p>That this approach does not work is actually a relief because it would have been far too obtuse and confusing to use in production.</p>
<p>It turns out that the <code>SqlQuery</code> only works with <code>SELECT</code> statements, as was strongly implied by the documentation.</p>
<pre class=" "><code>var users = context.Database.SqlQuery&lt;User&gt;(
  "<strong class="highlight">SELECT *</strong> FROM Users WHERE Name = @name",
  new [] { new SqlParameter("@name", "John") }
);</code></pre><p>Once we&rsquo;ve converted to this syntax, though, we can just use the much clearer and <em>compile-time–checked</em> version that we started with, repeated below.</p>
<pre class=" "><code>var users = context.Users.Where(u =&gt; u.Name == "John");

foreach (var u in users)
{
  context.Users.Remove(u);
}

context.SaveChanges();</code></pre><p>So we&rsquo;re back where we started, but perhaps a little wiser for having tried.</p>
<h2>Deleting objects with Quino</h2><p>As a final footnote, I just want to point out how you would perform multiple deletes with the Quino ORM. It&rsquo;s quite simple, really. Any query that you can use to <em>select</em> objects you can also use to <em>delete</em> objects [4].</p>
<p>So, how would I execute the query above in Quino?</p>
<pre class=" "><code>Session.Delete(Session.CreateQuery&lt;User&gt;().WhereEquals(User.MetaProperties.Name, "John").Query);</code></pre><p>To make it a little clearer instead of showing off with a one-liner:</p>
<pre class=" "><code>var query = Session.CreateQuery&lt;User&gt;();
query.WhereEquals(User.MetaProperties.Name, "John");
Session.Delete(query);</code></pre><p>Quino doesn&rsquo;t support using Linq to create queries, but its query API is still more statically checked than ESQL. You can see how the query could easily be extended to restrict on much more complex conditions, even including fields on joined tables.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2849_1_body" class="footnote-number">[1]</span> As I wrote, We&rsquo;re using Code-first, which is <em>much</em> more comfortable than using the database-diagram editor of old. We&rsquo;re also using the nascent &ldquo;Migrations&rdquo; support, which has so far worked OK, though it&rsquo;s nowhere near as convenient as Quino&rsquo;s automated schema-migration.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2849_2_body" class="footnote-number">[2]</span> Though it is inefficient, it&rsquo;s better than a lot of other examples out there, which almost unilaterally include the call to <code>context.SaveChanges()</code> <em>inside</em> the <code>foreach</code>-loop. Doing so is wasteful and does not give EF an opportunity to optimize the delete calls into a single SQL statement (see footnote below).</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2849_3_body" class="footnote-number">[3]</span> Translates to: &ldquo;Hope is the last (thing) to die.&rdquo;</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2849_4_body" class="footnote-number">[4]</span> <p>With the following caveats, which generally apply to all queries with any ORM:</p>
<ul>
<li>Many databases use a different syntax and provide different support for <code>DELETE</code> vs. <code>SELECT</code> operations.</li>
<li>Therefore, it is more likely that more complex conditions are not supported for <code>DELETE</code> operations on some database back-ends</li>
<li>Since the syntax often differs, it&rsquo;s more likely that a more complex query will fail to map properly in a <code>DELETE</code> operation than in a <code>SELECT</code> operation simply because that particular combination has never come up before.</li>
<li>That said, Quino has quite good support for deleting objects with restrictions not only on the table from which to delete data but also from other, joined tables.</li></ul><p>Some combination of these reasons possibly accounts for EF&rsquo;s lack of support for batch deletes.</p>
</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2823</guid>
    <title><![CDATA[Merge conflicts in source control]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2823</link>
    <pubDate>Sun, 05 May 2013 21:36:02 +0200</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">5. May 2013 21:36:02 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I was recently asked a question about merge conflicts in source-control systems.</p>
<blockquote class="quote quote-block "><div>&ldquo;[…] there keep being issues of files being over written, changes backed out etc. from people coding in the same file from different teams.&rdquo;</div></blockquote><p>My response was as follows:</p>
<blockquote class="quote abstract "><div><p>tl;dr: The way to prevent this is to keep people who have no idea what they&rsquo;re doing from merging files.</p>
</div></blockquote><h2>Extended version</h2><p>Let&rsquo;s talk about bad merges happening accidentally. Any source-control worth its salt will support at least some form of automatic merging.</p>
<p>An automatic merge is generally not a problem because the system will <em>not</em> automatically merge when there are conflicts (i.e. simultaneous edits of the same lines, or edits that are &ldquo;close&rdquo; to one another in the base file).</p>
<p>An automatic merge can, however, introduce <em>semantic</em> issues.</p>
<p>For example if both sides declared a method with the same name, but in different places in the same file, an automatic merge will include both copies but the resulting file won&rsquo;t compile (because the same method was declared twice).</p>
<p>Or, another example is as follows:</p>
<div class=" align-left left"><h2>Base file</h2><pre class=" "><code>public void A(B b)
{
  var a = new A();

  b.Do(a);
  b.Do(a);
  b.Do(a);
}</code></pre></div><div class=" align-left left" style="margin-left: 30px"><h2>Team One version</h2><pre class=" "><code>public void A(B b)
{
  var a = new A();

  b.Do(a);
  b.Do(a);
  b.Do(a);
  <strong class="highlight">a.Do();</strong>
}</code></pre></div><div class=" align-left left" style="margin-left: 30px"><h2>Team Two version</h2><pre class=" "><code>public void A(B b)
{
  var a = <strong class="highlight">null</strong>;

  b.Do(a);
  b.Do(a);
  b.Do(a);
}</code></pre></div><div class=" align-left left" style="margin-left: 30px"><h2>Automatic merge</h2><pre class=" "><code>public void A(B b)
{
  var a = <strong class="highlight">null</strong>;

  b.Do(a);
  b.Do(a);
  b.Do(a);
  <strong class="highlight">a.Do();</strong>
}</code></pre></div><div class=" " style="clear: both"><p>The automatically merged result will compile, but it will crash at run-time. Some tools (like ReSharper) will display a warning when the merged file is opened, showing that a method is being called on a provably null variable. However, if the file is never opened or the warning ignored or overlooked, the program will crash when run.</p>
</div><p>In my experience, though, this kind of automatic-merge &ldquo;error&rdquo; doesn&rsquo;t happen very often. Code-organization techniques like putting each type in its own file and keeping methods bodies relatively compact go a long way toward preventing such conflicts. They help to drastically reduce the likelihood that two developers will be working in the same area in a file.</p>
<p>With these relatively rare automatic-merge errors taken care of, let&rsquo;s move on to errors introduced deliberately through maliciousness or stupidity. This kind of error is also very rare, in my experience, but I work with very good people.</p>
<blockquote class="quote quote-block "><div><p>&ldquo;Let&rsquo;s say we have two teams:<br>
Team One − branch one<br>
&gt; Works on file 1<br>
Team Two − branch two<br>
&gt; Works on file 1<br>
Team One promotes file 1 into the Master B branch, there are some conflicts that they are working out but the file is promoted.&rdquo;</p>
</div></blockquote><p>I originally answered that I wasn&rsquo;t sure what it meant to &ldquo;promote&rdquo; a file while still working on it. How can a file be commited or checked in without having resolved all of the conflicts?</p>
<p>As it turns out, it can&rsquo;t. As documented in <a href="http://stackoverflow.com/questions/15222550/tfs-server-2012-and-promoting-changes">TFS Server 2012 and Promoting changes</a> (<cite><a href="http://stackoverflow.com/">Stack Overflow</a></cite>), promotion simply means telling TFS to pick up local changes and add them to the list of &ldquo;Pending Changes&rdquo;. This is part of a new TFS2012 feature called &ldquo;Local Workspaces&rdquo;. A promoted change corresponds to having added a file to a change list in Perforce or having staged a file in Git.</p>
<p>The net effect, though, is that the change is purely local. That is has been promoted has nothing to do with merging or committing to the shared repository. Other users cannot see your promoted changes. When you pull down new changes from the server, conflicts with local &ldquo;promoted&rdquo; changes will be indicated as usual, even if TFS has already indicated conflicts between a previous change and another promoted, uncommitted version of the same file. Any other behavior else would be madness. [1]</p>
<blockquote class="quote quote-block "><div>&ldquo;Team Two checks in their file 1 into the Master B branch. They back out the changes that Team One made without telling anyone anything.&rdquo;</div></blockquote><p>There&rsquo;s your problem. This should never happen unless Team Two has truly determined that their changes have replaced all of the work that Team One did or otherwise made it obsolete. If people don&rsquo;t know how to deal with merges, then they should not be merging.</p>
<p>Just as Stevie Wonder&rsquo;s not allowed behind the wheel of a car, neither should some developers be allowed to deal with merge conflicts. In my opinion, though, any developer who can&rsquo;t deal with merges in code that he or she is working on should be moved another team or, possibly, job. You have to know your own code and you have to know your tools. [2]</p>
<blockquote class="quote quote-block "><div>&ldquo;Team One figures out the conflicts in their branch and re-promotes file one (and other files) to Master B branch. The source control system remembers that file 1 was backed out by Team Two so it doesn&rsquo;t promote file 1 but doesn&rsquo;t let the user know.&rdquo;</div></blockquote><p>This sounds insane. When a file is promoted—i.e. added to the pending changes—it is assumed that the current version is added to the pending changes, akin to staging a file in Git. When further changes are made to the file locally, the source-control system should indicate that it has changed since having been promoted (i.e. staged).</p>
<p>When you re-promote the file (re-stage it), TFS should treat that as the most recent version in your workspace. When you pull down the changes from Team 2, you will have all-new conflicts to resolve because your newly promoted file will still be in conflict with the changes they made to &ldquo;file 1&rdquo;—namely that they threw away all of the changes that you&rsquo;d made previously.</p>
<p>And, I&rsquo;m not sure how it works in TFS, but in Git, you can&rsquo;t &ldquo;back out&rdquo; a commit without leaving a trail:</p>
<ul>
<li>Either there is a merge commit where you can see that Team Two chose to &ldquo;accept their version&rdquo; rather than &ldquo;merge&rdquo; or &ldquo;accept other version&rdquo;</li>
<li>Or, there is a &ldquo;revert&rdquo; commit that &ldquo;undoes&rdquo; the changes from a previous commit</li></ul><p>Either way, your local changes will cause a conflict because they will have altered the same file in the same place as either the &ldquo;merge&rdquo; or &ldquo;revert&rdquo; commit and—this is important—will have done so <em>after</em> that other commit.</p>
<p>To recap, let me summarize what this sounds like:</p>
<ul>
<li><strong>T1</strong>: I want to check in file1</li>
<li><strong>TFS</strong>: You have conflicts</li>
<li><strong>T1</strong>: Promote file1 so that TFS knows about (other users can&rsquo;t see it yet because it hasn&rsquo;t been committed)</li>
<li><strong>TFS</strong>: Okie dokie</li>
<li><strong>T2</strong>: I want to check in file1</li>
<li><strong>TFS</strong>: You have conflicts</li>
<li><strong>T2</strong>: Fuck that. Use my version. Oh, and, fuck T1.</li>
<li><strong>TFS</strong>: I hear and obey. T2/file1 it is.</li>
<li><strong>T1</strong>: OK, I resolved conflicts; here&rsquo;s the final version of file1</li>
<li><strong>TFS</strong>: Thanks! *tosses T1/file1 out the window*</li></ul><p>I don&rsquo;t believe that this is really possible—even with TFS—but, if this is a possibility with your source-control, then you have two problems:</p>
<ol>
<li>You have team members who don&rsquo;t know how to merge</li>
<li>Your source control is helping them torpedo development</li></ol><p>There is probably a setting in your source-control system that disallows simultaneous editing for files. This is a pretty huge restriction, but if your developers either can&rsquo;t or won&rsquo;t play nice, you probably have no choice.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2823_1_body" class="footnote-number">[1]</span> This is not to rule out such behavior 100%, especially in a source-control system with which I am largely unfamiliar. It only serves to indicate the degree to which I would be unwilling to work with any system that exhibits this kind of behavior.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2823_2_body" class="footnote-number">[2]</span> Different companies can have different grace periods for learning these two things, of course. I <em>suppose</em> that grace period can be interminably long, but…</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2784</guid>
    <title><![CDATA[A provably safe parallel language extension for C#]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2784</link>
    <pubDate>Tue, 12 Feb 2013 21:44:37 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">12. Feb 2013 21:44:37 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">12. Apr 2013 10:01:17 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>The paper <a href="http://research.microsoft.com/apps/pubs/default.aspx?id=170528">Uniqueness and Reference Immutability for Safe Parallelism</a> by <cite>Colin S. Gordon, Matthew J. Parkinson, Jared Parsons, Aleks Bromfield, Joe Duffy</cite> (<cite><a href="http://research.microsoft.com/">Microsoft Research</a></cite>) is quite long (26 pages), detailed and involved. To be frank, most of the notation was foreign to me—to say nothing of making heads or tails of most of the proofs and lemmas—but I found the higher-level discussions and conclusions quite interesting.</p>
<p>The abstract is concise and describes the project very well:</p>
<blockquote class="quote quote-block "><div>&ldquo;A key challenge for concurrent programming is that side-effects (memory operations) in one thread can affect the behavior of another thread. In this paper, we present a type system to restrict the updates to memory to prevent these unintended side-effects. We provide a novel combination of immutable and unique (isolated) types that ensures safe parallelism (race freedom and deterministic execution). The type system includes support for polymorphism over type qualifiers, and can easily create cycles of immutable objects. Key to the system&rsquo;s flexibility is the ability to recover immutable or externally unique references after violating uniqueness without any explicit alias tracking. Our type system models a prototype extension to C# that is in active use by a Microsoft team. We describe their experiences building large systems with this extension. We prove the soundness of the type system by an embedding into a program logic.&rdquo;</div></blockquote><p>The project proposes a type-system extension with which developers can write provably safe parallel programs—i.e. <span class="quote-inline">&ldquo;race freedom and deterministic execution&rdquo;</span>—with the amount of actual parallelism determined when the program is analyzed and compiled rather than decided by a programmer creating threads of execution.</p>
<h2>Isolating objects for parallelism</h2><p>The &ldquo;isolation&rdquo; part of this type system reminds me a bit of the way that SCOOP addresses concurrency. That system also allows programs to designate objects as &ldquo;separate&rdquo; from other objects while also releasing the program from the onus of actually creating and managing separate execution contexts. That is, the syntax of the language allows a program to be written in a provably correct way (at least as far as parallelism is concerned; see the &ldquo;other provable-language projects&rdquo; section below). In order to execute such a program, the runtime loads not just the program but also another file that specifies the available virtual processors (commonly mapped to threads). Sections of code marked as &ldquo;separate&rdquo; can be run in parallel, depending on the available number of virtual processors. Otherwise, the program runs serially. </p>
<p>In SCOOP, methods are used as a natural isolation barrier, with input parameters marked as &ldquo;separate&rdquo;. See <a href="http://www.eiffel.com/products/concurrency/scoop.html">SCOOP: Concurrency for Eiffel</a> (<cite><a href="http://www.eiffel.com/">Eiffel.com</a></cite>) and <a href="http://en.wikipedia.org/wiki/SCOOP_(software)">SCOOP (software)</a> (<cite><a href="http://en.wikipedia.org/">Wikipedia</a></cite>) for more details. The paper also contains an entire section listing other projects—many implemented on the the JVM—that have attempted to make provably safe programming languages.</p>
<p>The system described in this paper goes much further, adding immutability as well as isolation (the same concept as &ldquo;separate&rdquo; in SCOOP). An interesting extension to the type system is that isolated object trees are free to have references to immutable objects (since those can&rsquo;t negatively impact parallelism). This allows for globally shared immutable state and reduces argument-passing significantly. Additionally, there are readable and writable references: the former can only be read but may be modified by other objects (otherwise it would be immutable); the latter can be read and written and is equivalent to a &ldquo;normal&rdquo; object in C# today. In fact, <span class="quote-inline">&ldquo;[…] writable is the default annotation, so any single-threaded C# that does not access global state also compiles with the prototype.&rdquo;</span></p>
<h2>Permission types</h2><p>In this safe-parallel extension, a standard type system is extended so that every type can be assigned such a permission and there is <span class="quote-inline">&ldquo;support for polymorphism over type qualifiers&rdquo;</span>, which means that the extended type system includes the permission in the type, so that, given <code>B =&gt; A</code>, a reference to <code>readable B</code> can be passed to a method that expects an <code>immutable A</code>. In addition, covariance is also supported for generic parameter types.</p>
<p>When they say that the <span class="quote-inline">&ldquo;[k]ey to the system&rsquo;s flexibility is the ability to recover immutable or externally unique references after violating uniqueness without any explicit alias tracking&rdquo;</span>, they mean that the type system allows programs to specify sections that accept isolated references as input, lets them convert to writable references and then convert back to isolated objects—all without losing provably safe parallelism. This is quite a feat since it allows programs to benefit from isolation, immutability and provably safe parallelism without significantly changing common programming practice. In essence, it suffices to decorate variables and method parameters with these permission extensions to modify the types and let the compiler guide you as to further changes that need to be made. That is, an input parameter for a method will be marked as <code>immutable</code> so that it won&rsquo;t be changed and subsequent misuse has to be corrected.</p>
<p>Even better, they found that, in practice, it is possible to use extension methods to allow parallel and standard implementations of collections (lists, maps, etc.) to share most code.</p>
<blockquote class="quote quote-block "><div>&ldquo;A fully polymorphic version of a map() method for a collection can coexist with a parallelized version pmap() specialized for immutable or readable collections. […] Note that the parallelized version can still be used with writable collections through subtyping and framing as long as the mapped operation is pure; no duplication or creation of an additional collection just for concurrency is needed.&rdquo;</div></blockquote><h2>Real projects and performance impact</h2><p>Much of the paper is naturally concerned with proving that their type system actually does what it says it does. As mentioned above, at least 2/3 of the paper is devoted to lemmas and large swaths of notation. For programmers, the more interesting part is the penultimate section that discusses the extension to C# and the experiences in using it for larger projects.</p>
<blockquote class="quote quote-block "><div>&ldquo;A source-level variant of this system, as an extension to C#, is in use by a large project at Microsoft, as their primary programming language. The group has written several million lines of code, including: core libraries (including collections with polymorphism over element permissions and data-parallel operations when safe), a webserver, a high level optimizing compiler, and an MPEG decoder.&rdquo;</div></blockquote><p>Several million lines of code is, well, it&rsquo;s an enormous amount of code. I&rsquo;m not sure how many programmers they have or how they&rsquo;re counting lines or how efficiently they write their code, but millions of lines of code suggests generated code of some kind. Still, taken with the next statement on performance, that much code more than proves that the type system is viable.</p>
<blockquote class="quote quote-block "><div>&ldquo;These and other applications written in the source language are performance-competitive with established implementations on standard benchmarks; we mention this not because our language design is focused on performance, but merely to point out that heavy use of reference immutability, including removing mutable static/global state, has not come at the cost of performance in the experience of the Microsoft team.&rdquo;</div></blockquote><p>Not only is performance not impacted, but the nature of the typing extensions allows the compiler to know much more about which values and collections can be changed, which affects how aggressively this data can be cached or inlined.</p>
<blockquote class="quote quote-block "><div>&ldquo;In fact, the prototype compiler exploits reference immutability information for a number of otherwise-unavailable compiler optimizations. […] Reference immutability enables some new optimizations in the compiler and runtime system. For example, the concurrent GC can use weaker read barriers for immutable data. The compiler can perform more code motion and caching, and an MSIL-to-native pass can freeze immutable data into the binary.&rdquo;</div></blockquote><h2>Incremental integration (&ldquo;unstrict&rdquo; blocks)</h2><p>In the current implementation, there is an <code>unstrict</code> block that allows the team at Microsoft to temporarily turn off the new type system and to ignore safety checks. This is a pragmatic approach which allows the software to be run before it has been proven 100% parallel-safe. This is still better than having no provably safe blocks at all. Their goal is naturally to remove as many of these blocks as possible—and, in fact, this requirement drives further refinement of the type system and library.</p>
<blockquote class="quote quote-block "><div>&ldquo;We continue to work on driving the number of unstrict blocks as low as possible without over-complicating the type system’s use or implementation.&rdquo;</div></blockquote><p>The project is still a work-in-progress but has seen quite a few iterations, which is promising. The paper was written in 2012; it would be very interesting to take it for a test drive in a CTP.</p>
<h2>Other provable-language projects</h2><p>A related project at Microsoft Research <a href="http://research.microsoft.com/en-us/projects/specsharp/">Spec#</a> contributed a lot of basic knowledge about provable programs. The authors even state that the <span class="quote-inline">&ldquo;[…] type system grew naturally from a series of efforts at safe parallelism. […] The earliest version was simply copying Spec#’s [Pure] method attribute, along with a set of carefully designed task-and data-parallelism libraries.&rdquo;</span> Spec#, in turn, is a <span class="quote-inline">&ldquo;[…] formal language for API contracts (influenced by JML, AsmL, and Eiffel), which extends C# with constructs for non-null types, preconditions, postconditions, and object invariants&rdquo;</span>. </p>
<p>Though the implementation of this permissions-based type system may have started with Spec#, the primary focus of that project was more a valiant attempt to bring Design-by-Contract principles (<a href="http://encodo.com/en/dev-design-by-contract.php">examples and some discussion here</a> (<cite><a href="http://encodo.com/">encodo.com</a></cite>)) to the .NET world via C#. Though spec# has <a href="http://specsharp.codeplex.com/">downloadable code</a> (<cite><a href="http://specsharp.codeplex.com/">CodePlex</a></cite>), the project hasn&rsquo;t really been updated in years. This is a shame, as support for <a href="http://eiffel.com">Eiffel</a> [1] in .NET, mentioned above as one of the key influences of spec#, was dropped by ISE Eiffel long ago. </p>
<p>Spec#, in turn, was mostly replaced by Microsoft Research&rsquo;s <a href="http://research.microsoft.com/en-us/projects/contracts/">Contracts</a> project (an older version of which was covered in depth in <a href="http://earthli.com/news/view_article.php?id=2183">Microsoft Code Contracts: Not with a Ten-foot Pole</a> (<cite><a href="http://earthli.com/">earthli.com</a></cite>)). The Contracts project seems to be alive and well: the most recent release is from October, 2012. I have not checked it out since my initial thumbs-down review (linked above) but did note in passing that the implementation is still (A) library-only and (B) does not support Visual Studio 2012.</p>
<p>The library-only restriction is particularly galling, as such an implementation can lead to repeated code and unwieldy anti-patterns. As documented in the <a href="http://research.microsoft.com/en-us/projects/contracts/faq.aspx">Contracts FAQ</a>, the current implementation of the <span class="quote-inline">&ldquo;tools take care of enforcing consistency and proper inheritance of contracts&rdquo;</span> but this is presumably accomplished with compiler errors that require the programmer to include contracts from base methods in overrides.</p>
<p>The seminal work <em>Object-oriented Software Construction</em> by <em>Bertrand Meyer</em> (vol. II in particular) goes into tremendous detail on a type system that incorporates contracts directly. The type system discussed in this article covers only parallel safety: null-safety and other contracts are not covered at all. If you&rsquo;re at all interested in these types of language extensions, the vol.2 of OOSC is a great read. The examples are all in <a href="http://en.wikipedia.org/wiki/Eiffel_(programming_language)">Eiffel</a> but should be relatively accessible. Though some features—generics, notably but also tuples, once routines and <a href="http://earthli.com/news/view_article.php?id=1586">agents</a> (<cite><a href="http://earthli.com/">earthli.com</a></cite>)—have since made their way into C# and other more commonly used languages, many others—such as contracts, anchored types (contravariance is far too constrained in C# to allow them), covariant return types, covariance everywhere, multiple inheritance, explicit feature removal, loop variants and invariants, etc.—are still not available. Subsequent interesting work has also been done on extensions that allow creation of <a href="http://earthli.com/news/view_article.php?id=820">provably null-safe programs</a> (<cite><a href="http://earthli.com/">earthli.com</a></cite>), something also addressed in part by Microsoft Research&rsquo;s <a href="http://research.microsoft.com/en-us/projects/contracts/">Contracts</a> project.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2780</guid>
    <title><![CDATA[Programming in the moderncurrent age]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2780</link>
    <pubDate>Sun, 03 Feb 2013 23:04:09 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">3. Feb 2013 23:04:09 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>In order to program in 2013, it is important not to waste any time honing your skills with outdated tools and work-flows. What are the essential pieces of software for developing software in 2013?</p>
<dl><dt class="field">Runtime</dt>
<dd>A runtime is a given for all but the most esoteric of programming exercises. Without something to execute your code, there is almost no point in writing it.</dd>
<dt class="field">Debugger</dt>
<dd>Programming without an integrated debugger can be very time-consuming, error-prone and will quite frankly suck the fun right out of the whole endeavor. And, by &ldquo;debugger&rdquo; I mean a source-level single-step debugger with call-stack and variable/object/structure inspection as well as expression evaluation. Poring through logs and inserting print statements is not a viable long-term or even medium-term solution. You shouldn&rsquo;t be writing in a language without one of these unless you absolutely can&rsquo;t avoid it (<em>NAnt</em> build scripts come to mind).</dd>
<dt class="field">Compiler/Checker</dt>
<dd>A syntax/semantics checker of some sort integrated into the editor ensures a tighter feedback/error-finding loop and saves time, energy and frustration. I was deliberately cagey with the &ldquo;checker&rdquo; because I understand that some languages, like Javascript [1], do not have a compiled form. Duck-typed languages like Python or Ruby also limit static checking but <em>anything</em> is better than nothing.</dd>
<dt class="field">Versioning</dt>
<dd>A source-control system is essential in order to track changes, test ideas and manage releases. A lot of time can be wasted—and effort lost—without good source control. <em>Great</em> source control decreases timidity, encourages experimentation and allows for interruptible work-flows. I will argue below that private branches and history rewriting are also essential.</dd>
</dl><p>Even for the smallest projects, there is no reason to forgo any of these tools.</p>
<h2>Managing your Source Code</h2><blockquote class="quote abstract "><div><span title="too long; didn't read">tl;dr</span>: It&rsquo;s 2013 and your local commit history is not sacrosanct. No one wants to see how you arrived at the solution; they just want to see clean commits that explain your solution as clearly as possible. Use git; use rebase; use &ldquo;rebase interactive&rdquo;; use the index; stage hunks; squash merge; go nuts. [2]</div></blockquote><p> </p>
<p><span style="width: 374px; display: table" class=" align-right"><span class="auto-content-inline"><a href="https://www.earthli.com/data/news/attachments/entry/2780/branching_model.png"><img src="https://www.earthli.com/data/news/attachments/entry/2780/branching_model.png" alt=" " class="frame" style="width: 374px"></a></span><span class="auto-content-caption"><a href="https://www.earthli.com/data/news/attachments/entry/2780/branching_model.png">Encodo&#039;s Branching Model</a></span></span>I would like to focus on the &ldquo;versioning&rdquo; part of the tool-chain. Source control tells the <em>story</em> of your code, showing how it evolved to where it is at any given point. If you look closely at the &ldquo;Encodo Branching Model&rdquo; [3] diagram (click to enlarge), you can see the story of the source code:</p>
<ol>
<li>All development was done in the master branch until v1.0 was released</li>
<li>Work on B was started in a feature branch</li>
<li>Work on hotfix v1.0.1 was started in a hotfix branch</li>
<li>Work on A was started in another feature branch</li>
<li>Hotfix v1.0.1 was released, tagged and merged back to the master branch</li>
<li>Development continued on master and both feature branches</li>
<li>Master was merged to feature branch A (includes hotfix v1.0.1 commits)</li>
<li>Finalization for release v1.1 was started in a release branch</li>
<li>Feature A was completed and merged back to the master branch</li>
<li>Version v1.1 was released, tagged and merged back to the master branch</li>
<li>Master was merged to feature branch B (includes v1.1 and feature A commits)</li>
<li>Development continued on master and feature B</li>
<li>Version v1.2 was released and tagged</li></ol><p>Small, precise, well-documented commits are essential in order for others to understand the project—especially those who weren&rsquo;t involved in developing the code. It should be obvious from which commits you made a release. You should be able to go back to any commit and easily start working from there. You should be able to maintain multiple lines of development, both for maintenance of published versions and for development of new features. The difficulty of merging these branches should be determined by the logical distance between them rather than by the tools. Merging should almost always be automatic.</p>
<p><em>Nowhere</em> in those requirements does it say that you&rsquo;re not allowed to lie about how you got to that pristine tree of commits.</p>
<h2>Why you should be using private branches and history rewriting</h2><p>A few good articles about Git have recently appeared—<a href="http://sandofsky.com/blog/git-workflow.html">Understanding the Git Workflow</a> by <cite>Benjamin Sandofsky</cite> is one such—explaining better than ever <em>why</em> rewriting history is better than server-side, immutable commits.</p>
<p>In the article cited above, Sandofsky divides his work up into <span class="quote-inline">&ldquo;Short-lived work […] larger work […] and branch bankrupty.&rdquo;</span> These concepts are documented to some degree in the <em>Branch Management</em> chapter of the <a href="http://encodo.com/en/documents.php#git-handbook">Encodo Git Handbook</a> (of which I am co-author). I will expand on these themes below.</p>
<p><small class="notes">Note: The linked articles deal exclusively with the command line, which isn&rsquo;t everyone&rsquo;s favorite user interface (I, for one, like it). We use the <a href="http://www.syntevo.com/smartgithg/index.html">SmartGit/Hg</a> client for visualizing diffs, organizing commits and browsing the log. We also use the command-line for a lot of operations, but SmartGit is a very nice tool and version 3 supports nearly all of the operations described in this article.</small></p>
<h2>What is rebasing?</h2><p>As you can see from the diagram above, a well-organized and active project will have multiple <code>branches</code>. <code>Merging</code> and <code>rebasing</code> are two different ways of getting commits from one branch into another.</p>
<p>Merging commits into a branch creates a <em>merge commit</em>, which shows up in the history to indicate that <em>n</em> commits were made on a separate branch. Rebasing those commits instead re-applies those commits to the head of the indicated branch without a merge commit. In both cases there can be conflicts, but one method doesn&rsquo;t pose a greatest risk of them than the other. [4] You cannot tell from the history that rebased commits were developed in a separate branch. You <em>can</em>, however, tell that the commits were rebased because the <em>author date</em> (the time the commit was originally created) differs from the <em>commit date</em> (the last time that the commit was applied).</p>
<h2>What do you recommend?</h2><p>At <a href="http://encodo.com">Encodo</a>, we primarily work in the master branch because we generally work on very manageable, bite-sized issues that can easily be managed in a day. Developers are free to use local branches but are not required to do so. If some other requirement demands priority, we shunt the pending issue into a private branch. Such single-issue branches are focused and involve only a handful of files. It is not at all important to &ldquo;remember&rdquo; that the issue was developed in a branch rather than the master branch. If there are several commits, it may be important for other users to know that they were developed together and a merge-commit can be used to indicate this. Naturally, larger changes are developed in feature branches, but those are generally the exception rather than the rule.</p>
<blockquote class="quote pullquote align-right right" style="width: 200px"><div>Remember: <em>Nowhere</em> in those requirements does it say that you&rsquo;re not allowed to lie about how you got to that pristine tree of commits.</div></blockquote><p>Otherwise? Local commit history is absolutely not sacrosanct. We rebase like crazy to avoid unwanted merge commits. That is, when we pull from the central repository, we rebase our local commits on top of the commits that come form the origin. This has worked well for us.</p>
<p>If the local commit history is confusing—and this will sometimes come up during the code review—we use an interactive rebase to reorganize the files into a more soothing and/or understandable set of commits. See <a href="http://sandofsky.com/blog/git-workflow.html">Sandofsky&rsquo;s article</a> for a good introduction to using interactive rebasing to combine and edit commits.</p>
<p>Naturally, we weigh the amount of confusion caused by the offending commits against the amount of effort required to clean up the history. We don&rsquo;t use bisect [5] very often, so we don&rsquo;t invest a lot of time in enforcing the clean, compilable commits required by that tool. For us, the history is interesting, but we rarely go back farther than a few weeks in the log. [6]</p>
<h2>When to merge? When to rebase?</h2><p>At Encodo, there are only a few reasons to retain a merge commit in the official history:</p>
<ol>
<li>If we want to remember which commits belonged to a particular feature. Any reasonable tool will show these commits graphically as a separate strand running alongside the master branch.</li>
<li>If a rebase involves too much effort or is too error-prone. If there are a lot of commits in the branch to be integrated, there may be subtle conflicts that resolve more easily if you merge rather than rebase. Sometimes we just pull the e-brake and do a merge rather than waste time and effort trying to get a clean rebase. This is not to say that the tools are lacking or at fault but that we are <strong>pragmatic</strong> rather than <strong>ideological</strong>. [7]</li>
<li>If there are merge commits in a feature branch with a large number of well-organized commits and/or a large number of changes or affected files. In this case, using a squash merge and rebuilding the commit history would be onerous and error-prone, so we just merge to avoid issues that can arise when rebasing merge commits (related to the point above).</li></ol><h2>When should I use private branches? What are they exactly?</h2><p>There are no rules for local branches: you can name them whatever you like. However, if you promote a local branch to a <em>private</em> branch, at Encodo we use the developer&rsquo;s initials as the prefix for the branch. My branches are marked as &ldquo;mvb/feature1&rdquo;, for example.</p>
<p>What&rsquo;s the difference between the two? Private branches may get pushed to our common repository. Why would you need to do that? Well, I, for example, have a desktop at work and, if I want to work at home, I have to transfer my workspace somehow to the machine at home. One solution is to work on a virtual machine that&rsquo;s accessible to both places; another is to remote in to the desktop at work from home; the final one is to just push that work to the central repository and pull it from home. The offline solution has the advantage of speed and less reliance on connectivity.</p>
<p>What often happens to me is that I start work on a feature but can only spend an hour or two on it before I get pulled off onto something else. I push the private branch, work on it a bit more at home, push back, work on another, higher-priority feature branch, merge that in to master, work on master, whatever. A few weeks later and I&rsquo;ve got a private branch with a few ugly commits, some useful changes and a handful of merge commits from the master branch. The commit history is a disgusting mess and I have a sneaking suspicion that I&rsquo;ve only made changes to about a dozen files but have a dozen commits for those changes.</p>
<p>That&rsquo;s where the aforementioned &ldquo;branch bankruptcy&rdquo; comes in. You&rsquo;re not obligated to keep that branch; you can keep the changes, though. As shown in the <a href="http://sandofsky.com/blog/git-workflow.html">referenced article</a>, you execute the following git commands:</p>
<pre class=" "><code>git checkout master
git checkout -b cleaned_up_branch
git merge --squash private_feature_branch
git reset</code></pre><p>The <code>--squash</code> tells git to squash all of the changes from the <code>private_feature_branch</code> into the index (staging) and <code>reset</code> the index so that those changes are in the working tree. From here, you can make a single, clean, well-written commit <em>or</em> several commits that correspond logically to the various changes you made.</p>
<p>Git also lets you lose your attachment to checking in all the changes in a file at once: if a file has changes that correspond to different commits, you can add only selected differences in a file to the index (staging). <a href="http://plasmasturm.org/log/gitidxpraise/">In praise of Git’s index</a> by <cite>Aristotle Pagaltzis</cite> (<cite><a href="http://plasmasturm.org/">Plasmasturm</a></cite>) provides a great introduction. If you, like me, regularly take advantage of refactoring and cleanup tools while working on something else, you&rsquo;ll appreciate the ability to avoid checking in dozens of no-brainer cleanup/refactoring changes along with a one-liner bug-fix. [8]</p>
<h2>One final example: cherry picking and squashing</h2><p>I recently renamed several projects in our solution, which involved renaming the folders as well as the project files and all references to those files and folders. Git automatically recognizes these kind of renames as long as the old file is removed and the new file is added in the same commit.</p>
<p>I selected all of the files for the rename in SmartGit and committed them, using the index editor to stage only the hunks from the project files that corresponded to the rename. Nice and neat. I selected a few other files and committed those as a separate bug-fix. Two seconds later, the UI refreshed and showed me a large number of deleted files that I should have included in the first commit. Now, one way to go about fixing this is to revert the two commits and start all over, picking the changes apart (including playing with the index editor to stage individual hunks).</p>
<p>Instead of doing that, I did the following:</p>
<ol>
<li>I committed the deleted files with the commit message &ldquo;doh!&rdquo; (to avoid losing these changes in the reset in step 3)</li>
<li>I created a &ldquo;temp&rdquo; branch to mark that commit (to keep the commit visible once I reset in step 3)</li>
<li>I hard-reset my master branch to the origin</li>
<li>I cherry-picked the partial-rename commit to the workspace</li>
<li>I cherry-picked the &ldquo;doh!&rdquo; commit to the workspace</li>
<li>Now the workspace had the rename commit I&rsquo;d wanted in the first place</li>
<li>I committed that with the original commit message</li>
<li>I cherry-picked and committed the separate bug-fix commit</li>
<li>I deleted the &ldquo;temp&rdquo; branch (releasing the incorrect commits on it to be garbage-collected at some point)</li></ol><p>Now my master branch was ready to push to the server, all neat and tidy. And nobody was the wiser.</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2780_1_body" class="footnote-number">[1]</span> There are alternatives now, though, like Microsoft&rsquo;s TypeScript, that warrant a look if only because they help tighten the error-finding feedback loop and have the potential to make you more efficient (the efficiency may be robbed immediately back, however, if debugging generated code becomes difficult or even nightmarish).</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2780_2_body" class="footnote-number">[2]</span> Once you&rsquo;ve pushed, though? No touchie. At that point, you&rsquo;ve handed in your test and you get graded on that.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2780_3_body" class="footnote-number">[3]</span> According to my business card, I&rsquo;m a &ldquo;senior developer and partner&rdquo; at <a href="http://encodo.com">Encodo System AG</a>.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2780_4_body" class="footnote-number">[4]</span> With the exception, mentioned elsewhere as well, that rebasing merge-commits can sometimes require you to re-resolve previously resolved conflicts, which can be error-prone if the conflicts were difficult to resolve in the first place. Merging merge-commits avoids this problem.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2780_5_body" class="footnote-number">[5]</span> <code>bisect</code> is a git feature that executes a command against various commits to try to localize the commit that caused a build or test failure. Basically, you tell it the last commit that worked and git uses a binary search to find the offending commit. Of course, if you have commits that don&rsquo;t compile, this won&rsquo;t work very well. We haven&rsquo;t used this feature very much because we know the code in our repositories well and using <code>blame</code> and <code>log</code> is much faster. Bisect is much more useful for maintainers that don&rsquo;t know the code very well, but still need to figure out at which commit it stopped working.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2780_6_body" class="footnote-number">[6]</span> To be clear: we&rsquo;re only so cavalier with our private repositories to which access is restricted to those who already know what&rsquo;s going on. If we commit changes to public, open-source or customer repositories, we make sure that every commit compiles. See <a href="http://plasmasturm.org/log/gitidxpraise/">Aristotle&rsquo;s index article</a> (cited above) for tips on building and testing against staged files to ensure that a project compiles, runs and passes all tests before making a commit—even if you&rsquo;re not committing all extant changes.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2780_7_body" class="footnote-number">[7]</span> That said, with experience we&rsquo;ve learned that an interactive rebase and judicious squashing will create commits that avoid these problems. With practice, these situations crop up more and more rarely.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2780_8_body" class="footnote-number">[8]</span> Of course, you can also create a separate branch for your refactoring and merge it all back together, but that&rsquo;s more work and is in my experience rarely necessary.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=758</guid>
    <title><![CDATA[Are all errors exceptions?]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=758</link>
    <pubDate>Thu, 22 Nov 2012 23:24:02 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">22. Nov 2012 23:24:02 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <blockquote class="quote abstract "><div>The following ruminations were written seven years ago but have held up remarkably well. They have been published with minor updates.</div></blockquote><p>This article deals with the situation illustrated below, specifically the question raised in the comment.</p>
<pre class=" "><code>if (! $folder_id)
{
  $this-&gt;db-&gt;logged_query (&ldquo;SELECT folder_id FROM&rdquo; .
                           $this-&gt;app-&gt;table_names-&gt;objects .
                           &ldquo;WHERE id = $obj-&gt;object_id&rdquo;);
  if ($this-&gt;db-&gt;next_record ())
    $folder_id = $this-&gt;db-&gt;f (&ldquo;folder_id&rdquo;);
  else
    // raise exception? ignore? what to do?
}</code></pre><p>Above we see a situation in which you may decide against a stricter enforcement because whereas the error is clear, the reaction is not. This is also a big part of working with contracts: deferring reactions. Often—especially when developing libraries—you&rsquo;re in code so deep that the desired reaction could be one of many depending on the deployment of that code.</p>
<p>The code above is taken from the publishing loop in the <a href="https://www.earthli.com/software/webcore">webcore</a>; it&rsquo;s used to publish comments. In effect, the code has detected that a comment object id has been passed in that doesn&rsquo;t correspond to anything in the system. It&rsquo;s bogus. It&rsquo;s wrong.</p>
<p>Some deployments—I would hazard most—would just like to silently ignore the error and publish as much as possible. Silently ignoring an error will always bite you in the ass in the end (pun intended). The key here is that whereas the person deploying the final system should be perfectly free to ignore the error, you, as the library developer, can and must not.</p>
<p>Let&rsquo;s see what kind of reactions we could have here. Well, isn&rsquo;t that what exceptions were invented for? They&rsquo;re for transmitting error conditions up out of deep library code. Problem solved. For more severe errors in which the code cannot continue, the answer is quite clear: you simply throw an exception. However, in the situation above, it&rsquo;s not so clear.</p>
<p>The problem is easily skipped and most of the rest of the job can be finished. Here is where deferral comes in. Just call a function that will handle it later. This function can log the error or warning, display it to the user, ask to abort/retry/ignore, consult a table for same, throw an exception or just ignore it. It&rsquo;s not your problem to dispatch solutions to encountered errors. It&rsquo;s your job to detect them and maintain the integrity of the running code. </p>
<p>Simply throwing an exception no matter what the error condition is, in effect, making a decision about how the error will be handled. Control is lost because the exception handler is necessarily higher up. This is a bad thing if you&rsquo;d actually like the code to do the best it can. As any experience at all will have shown you, some errors are just warnings or hints. It&rsquo;s not just black and white, error or not. Many deployments of the system containing the code above will actually treat the issue as a warning and log it for the database techs to address.</p>
<p>However, to assume the opposite, that callers want errors to be swallowed, cheats those callers as well. It cheats them because it becomes incredibly hard to find errors; they must be detected by subtle logic or data problems (e.g. Hmmm…the log shows it only sent 500 emails, I thought there were 503 subscribers…). If the system never complains or logs anything, the end user calls you first. It cheats you because you can never adequately test your system because it never complains. Everything&rsquo;s OK. It kind of works. It <em>mostly</em> works.</p>
<p>The desire for safety or avoiding crashes or exceptions on the client side should never override the desire to have correct code that detects error conditions. If you write library code or end-user code, that code deals mostly with detecting and reporting misused functions. The functionality itself is generally straightforward; it&rsquo;s wrapping the interface around it that&rsquo;s hard. The only thing that you&rsquo;ll probably spend more time on is hunting down memory bugs—and, yes, even if you&rsquo;re using a garbage-collected runtime, you can still have memory bugs. What would you call it if the memory required by your publication script increases in proportion to the number of subscribers and mails?</p>
<p>If you&rsquo;re wondering what I ended up doing in the case above, I decided on a function call &lsquo;raise&rsquo;. It sounds like an exception, and that&rsquo;s usually what happens: it breaks the code on that line, but a little more elegantly than the usual PHP <code>die</code> statement. While the default handler for exceptions simply issues a fancy <code>die</code> statement, that handler can be replaced with a different one, one that redirects to an HTML page with a nicely formatted error printout and a form for submitting the error.</p>
<p>Since this code is likely to run inside a script that just wants to send subscriptions and doesn&rsquo;t care about data integrity errors, the handler would probably be replaced with something that suppresses the exception, but logs the error. That way, once the subscription run is done, you can view the error log and see if there are data integrity problems, and, perhaps more importantly, you see them all at once instead of just one at a time. And, more importantly still, those subscribers for whom there were no problems received their mail on time.</p>
      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2720</guid>
    <title><![CDATA[A scalable pattern for building metadata]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2720</link>
    <pubDate>Thu, 22 Nov 2012 19:45:47 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">22. Nov 2012 19:45:47 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p><small class="notes">The following article was originally published on the <a href="http://encodo.com/en/blogs.php?entry_id=196">Encodo blogs</a> and is cross-published here.</small></p>
<p><hr></p>
<p>In the latest version of Quino—version 1.8.5—we took a long, hard look at the patterns we were using to create metadata. The metadata for an application includes all of the usual Quino stuff: classes, properties, paths, relations. With each version, though we&rsquo;re able to use the metadata in more places. That means that the metadata definition code grows and grows. We needed some way to keep a decent overview of that metadata without causing too much pain when defining it.</p>
<p>In order to provide some background, the following are the high-level requirements that we kept in mind while designing the new pattern and supporting framework.</p>
<dl><dt class="field">Manage complexity</dt>
<dd>A simple model should be easy and straightforward to build, with no cumbersome boilerplate; complex models should support multiple layers and provide an overview</dd>
<dt class="field">Leverage existing knowhow</dt>
<dd>Our users don&rsquo;t want to learn a new language/IDE in order to create metadata; neither do we want to provide support for our own metadata-definition language</dd>
<dt class="field">Support modularization</dt>
<dd>Modules can be used to hide complexity but are also sometimes necessary to define hard boundaries in the application metadata</dd>
<dt class="field">Support extensibility</dt>
<dd>Interdependent modules and overlays will need to refer to elements in other modules; there needs to be a standard mechanism for defining and accessing metadata elements that doesn&rsquo;t rely on string constants [1]</dd>
<dt class="field">Support refactoring</dt>
<dd>Rely on convention and name-matching as little as possible to avoid subtle errors</dd>
<dt class="field">Support introspection</dt>
<dd>Developers that stick to the pattern should be able to maximize efficiency using common navigation and introspection [2] tools like Visual Studio or ReSharper.</dd>
</dl><h2>Definition Language</h2><p>Quino metadata has always been defined using a .NET language—in our case, we always use C# to define the metadata, using the <code>MetaBuilder</code> or <code>InMemoryMetaBuilder</code> to compose the application model. This approach satisfies the need to leverage existing tools, refactoring and introspection.</p>
<p>Since Quino metadata is an in-memory construct, there will always be a .NET API for creating metadata. This is not to say that there will never be a DSL to define Quino metadata but that such an approach is not the subject of this post.</p>
<h2>Modularization</h2><p>Quino applications have always been able to define and integrate metadata modules (e.g. reporting or security) using an <code>IMetaModuleBuilder</code>. Modules solved interdependency issues by splitting the metadata-generation into several phases:</p>
<ul>
<li>Add classes and foreign keys</li>
<li>Add paths between classes (depends on foreign keys)</li>
<li>Add calculated properties and relations (depends on paths)</li>
<li>Add layouts (depends on all properties)</li></ul><p>In this way, when a module needed to add a path between a class that it had defined and a class defined in another module, it could be guaranteed that classes and foreign keys for <em>all</em> modules had been defined before any paths were created. Likewise for classes that wanted to define relations based on paths defined in other modules.</p>
<p>The limitation of the previous implementation was that a module generator always created its own module and builder and could not simply re-use those created by another generator. Basically, there was no &ldquo;lightweight&rdquo; way of splitting metadata-generation into separate files for purely organizational purposes.</p>
<p>There were also a few issues with the implementation of the main model-generation code as well. The previous pattern depended heavily on local variables, all defined within one mammoth function. Separating code into individual method calls was ad-hoc—each project did it a little differently—and involved a lot of migration of local variables to instance variables. With all code in a single method, file-structure navigation tools couldn&rsquo;t help at all. The previous pattern prescribed using file comments or regions that could be located using &ldquo;find in file&rdquo;. This was clearly sub-optimal.</p>
<h2>The new pattern</h2><p>The new pattern that can be applied for all models, bit or small includes the following parts:</p>
<dl><dt class="field">Model generator</dt>
<dd>As before, there is a class that implements the <code>IMetaModelGenerator</code> interface. This class is used by the application configuration and various tools (e.g. the code generator or UML generator) to create the model.</dd>
<dt class="field">Model elements</dt>
<dd>Metadata that is referenced from multiple steps in the metadata-generation process is stored <em>in a separate object</em> (or objects) called the <dfn>model elements</dfn>. (E.g. classes are created in the <code>AddClasses()</code> step and referenced in the <code>AddPaths</code>, <code>AddProperties</code> and <code>AddLayouts</code> steps.) The model elements typically has two properties called <code>Classes</code> and <code>Paths</code>.</dd>
<dt class="field">Metadata generators</dt>
<dd>Module generators still exist, but there are now also metadata generators that are lightweight, using a metadata builder and <em>elements</em> defined by another generator (typically a module generator or the model generator itself).</dd>
</dl><p>This may sound like a lot of overhead for a simple application, but it&rsquo;s really not that much extra code. The benefits are:</p>
<ul>
<li>Models, modules and lightweight parts all use the same pattern, with the same phases and method names. That makes it far easier to know where to look for a definition</li>
<li>Since the pattern is the same, it&rsquo;s easy to move functionality from one module to another or to split one module into multiple lightweight parts without doing a lot of refactoring</li>
<li>A small model will naturally grow to a medium or large model, all while using the same pattern. There is no moment during development where you have to do a major refactoring in order to get organized: the pattern will naturally support a clean coding style.</li></ul><h2>Building a model, step by step</h2><p>But enough chatter; let&rsquo;s take a look at the absolute minimum boilerplate for an empty model.</p>
<h2>Step zero: create the boilerplate</h2><pre class=" "><code>public class DemoModelElements
{
  public DemoModelElements()
  {
    Classes = new DemoModelClasses();
    Paths = new DemoModelPaths();
  }

  public DemoModelClasses Classes { get; private set; }
  public DemoModelPaths Paths { get; private set; }
}

public class DemoModelPaths
{
}

public class DemoModelClasses
{
}

public class DemoCoreGenerator : DependentMetadataGeneratorBase&lt;DemoModelGenerator, DemoModelElements, MetaBuilder&gt;
{
}

public class DemoModelGenerator : MetaBuilderBasedModelGeneratorBase&lt;DemoModelElements&gt;
{
  protected override void AddMetadata()
  {
    Builder.Include&lt;DemoCoreGenerator&gt;();
  }
}</code></pre><p>The code above is functional but doesn&rsquo;t actually create any metadata. So what <em>does</em> it do?</p>
<ol>
<li>It uses the generic <code>MetaBuilderBasedModelGeneratorBase</code> to indicate the type of <em>Elements</em> that will be exposed by this model generator. The elements class is created automatically and is available as the property <code>Elements</code> (as we&rsquo;ll see in the examples below). Additionally, we&rsquo;re using a <code>ModelGeneratorBase</code> that is based on a <code>MetaBuilder</code> which means that the property <code>Builder</code> is also available and is of type <code>MetaBuilder</code>.</li>
<li>It includes the <code>DemoCoreGenerator</code> which is a <em>dependent</em> generator—it&rsquo;s lightweight and uses the elements and builder from its owner. The exact types are shown in the class declaration; it can be read as: get elements of type <code>DemoModelElements</code> and a builder of type <code>MetaBuilder</code> from the generator with type <code>DemoModelGenerator</code>. The initial generic argument can be any other metadata generator that implements the <code>IElementsProvider&lt;TElements, TBuilder&gt;</code> interface.</li>
<li>The model generator overrides <code>AddMetadata</code> to include the metadata created by <code>DemoCoreGenerator</code> in the model.</li></ol><p>Even though it&rsquo;s not very much code, you can create a snippet or a file template with Visual Studio or a Live Template or file template with ReSharper to quickly create a new model.</p>
<h2>Step one: define the model</h2><p>Now, let&rsquo;s fill the empty model with some metadata. The first step is to define the model that we&rsquo;re going to build. That part goes in the <code>AddMetadata()</code> method. [3]</p>
<pre class=" "><code>public class DemoModelGenerator : MetaBuilderBasedModelGeneratorBase&lt;DemoModelElements&gt;
{
  protected override void AddMetadata()
  {
    <strong class="highlight">Builder.CreateModel&lt;DemoModel&gt;("Demo", /*Guid*/);
    Builder.CreateMainModule("Encodo.Quino");</strong>

    Builder.Include&lt;DemoCoreGenerator&gt;();
  }
}</code></pre><h2>Step two: add a class</h2><p>A typical next step is to define a class. Let&rsquo;s do that.</p>
<pre class=" "><code>public class DemoModelClasses
{
  <strong class="highlight">public IMetaClass Company { get; set; }</strong>
}

public class DemoCoreGenerator : DependentMetadataGeneratorBase&lt;DemoModelGenerator, DemoModelElements, MetaBuilder&gt;
{
  <strong class="highlight">protected override void AddClasses()
  {
    Elements.Classes.Company = Builder.AddClassWithDefaultPrimaryKey("Company", /*Guid*/, /*Guid*/);
  }</strong>
}</code></pre><p>As you can see, we added a new class to the elements and created and assigned it in the <code>AddClasses()</code> phase of metadata-generation. </p>
<h2>Step three: add another class and a path</h2><p>An obvious next step is to create another class and define a path between them.</p>
<pre class=" "><code>public class DemoModelClasses
{
  public IMetaClass Company { get; set; }
  <strong class="highlight">public IMetaClass Person { get; set; }</strong>
}

public class DemoCoreGenerator : DependentMetadataGeneratorBase&lt;DemoModelGenerator, DemoModelElements, MetaBuilder&gt;
{
  protected override void AddClasses()
  {
    Elements.Classes.Company = Builder.AddClassWithDefaultPrimaryKey("Company", /*Guid*/, /*Guid*/);
    <strong class="highlight">Elements.Classes.Person = Builder.AddClassWithDefaultPrimaryKey("Person", /*Guid*/, /*Guid*/);
    Builder.AddInvisibleProperty(Elements.Classes.Person, "CompanyId", MetaType.Key, true, /*Guid*/);</strong>
  }

  <strong class="highlight">protected override void AddPaths()
  {
    Elements.Paths.CompanyPersonPath = Builder.AddOneToManyPath(
      Elements.Classes.Company, "Id",
      Elements.Classes.Person, "CompanyId",
      /*Guid*/, /*Guid*/
    );    
  }</strong>
}</code></pre><h2>Step four: add relations</h2><p>Having a path is not enough, though. We can also define how the relations on that path are exposed in the classes.</p>
<pre class=" "><code>public class DemoCoreGenerator : DependentMetadataGeneratorBase&lt;DemoModelGenerator, DemoModelElements, MetaBuilder&gt;
{
  protected override void AddClasses()
  {
    Elements.Classes.Company = Builder.AddClassWithDefaultPrimaryKey("Company", /*Guid*/, /*Guid*/);
    Elements.Classes.Person = Builder.AddClassWithDefaultPrimaryKey("Person", /*Guid*/, /*Guid*/);
    Builder.AddInvisibleProperty(Elements.Classes.Person, "CompanyId", MetaType.Key, true, /*Guid*/);
  }

  protected override void AddPaths()
  {
    Elements.Paths.CompanyPersonPath = Builder.AddOneToManyPath(
      Elements.Classes.Company, "Id",
      Elements.Classes.Person, "CompanyId",
      /*Guid*/, /*Guid*/
    );    
  }

  <strong class="highlight">protected override void AddProperties()
  {
    Builder.AddRelation(Elements.Classes.Company, "People", "", Elements.Paths.CompanyPersonPath);
    Builder.AddRelation(Elements.Classes.Person, "Company", "", Elements.Paths.CompanyPersonPath);
  }</strong>
}</code></pre><p>OK, now we have a model with two entities—companies and people—that are related to each other so that a company has a list of people and each person belongs to a company.</p>
<h2>Step five: add translations</h2><p>Now we&rsquo;d like to make the metadata support German as well as English. Quino naturally supports more generalized ways of doing this (e.g. importing from files), but let&rsquo;s just add the metadata manually to see what that would look like (unaffected methods are left off for brevity).</p>
<pre class=" "><code>public class DemoModelElements
{
  public DemoModelElements()
  {
    Classes = new DemoModelClasses();
    Paths = new DemoModelPaths();
  }

  <strong class="highlight">public ILanguage English { get; set; }
  public ILanguage German { get; set; }</strong>
  public DemoModelClasses Classes { get; private set; }
  public DemoModelPaths Paths { get; private set; }
}

public class DemoCoreGenerator : DependentMetadataGeneratorBase&lt;DemoModelGenerator, DemoModelElements, MetaBuilder&gt;
{
  <strong class="highlight">protected override void AddCoreElements()
  {
    Elements.English = Builder.AddDisplayLanguage("en-US", "English");
    Elements.German = Builder.AddDisplayLanguage("de-CH", "Deutsch");
  }</strong>

  protected override void AddClasses()
  {
    <strong class="highlight">var company = </strong>Elements.Classes.Company = Builder.AddClassWithDefaultPrimaryKey("Company", /*Guid*/, /*Guid*/);
    <strong class="highlight">company.Caption.SetValue(Elements.English, "Company");
    company.Caption.SetValue(Elements.German, "Firma");
    company.PluralCaption.SetValue(Elements.English, "Companies");
    company.PluralCaption.SetValue(Elements.German, "Firmen");</strong>

    <strong class="highlight">var person = </strong>Elements.Classes.Person = Builder.AddClassWithDefaultPrimaryKey("Person", /*Guid*/, /*Guid*/);
    Builder.AddInvisibleProperty(<strong class="highlight">person</strong>, "CompanyId", MetaType.Key, true, /*Guid*/);
    <strong class="highlight">person.Caption.SetValue(Elements.English, "Person");
    person.Caption.SetValue(Elements.German, "Person");
    person.PluralCaption.SetValue(Elements.English, "People");
    person.PluralCaption.SetValue(Elements.German, "Personen");</strong>
  }
}</code></pre><p>Note that I created a local variable for both company and person. I did this for two reasons:</p>
<ul>
<li>The code is shorter and easier to read</li>
<li>There are fewer references to the <code>Elements.Classes.Person</code> and <code>Elements.Classes.Company</code> properties. It&rsquo;s useful to keep the number of references to a minimum in order to make searching for usages with a tool like ReSharper of maximum benefit. Otherwise, there&rsquo;s a lot of noise to signal and you&rsquo;ll get hundreds of references when there are only actually a few dozen &ldquo;real&rdquo; references.</li></ul><h2>Step six: using private methods</h2><p>You can see that the metadata-generation code is still manageable, but it&rsquo;s growing. Once we&rsquo;ve filled out all of the properties, relations, translations, layouts and view aspects for the person and company classes, we&rsquo;ll have a file that&rsquo;s several hundred lines long. A file of that size is still manageable and, since we have methods, it&rsquo;s eminently navigable with a file-structure browser.</p>
<p>If we don&rsquo;t mind keeping—or we&rsquo;d rather keep—everything in one file, we can see more structure by splitting the code into more methods. This is really easy to do because we&rsquo;re using the elements to reference other parts of metadata instead of local variables. For example, let&rsquo;s move the class initialization code for the person and company entities to separate methods (unaffected methods are left off for brevity).</p>
<pre class=" "><code>public class DemoCoreGenerator : DependentMetadataGeneratorBase&lt;DemoModelGenerator, DemoModelElements, MetaBuilder&gt;
{
  protected override void AddClasses()
  {
    <strong class="highlight">AddCompany();</strong>
    <strong class="highlight">AddPerson();</strong>
  }

  <strong class="highlight">private void AddCompany()
  {</strong>
    var company = Elements.Classes.Company = Builder.AddClassWithDefaultPrimaryKey("Company", /*Guid*/, /*Guid*/);
    company.Caption.SetValue(Elements.English, "Company");
    company.Caption.SetValue(Elements.German, "Firma");
    company.PluralCaption.SetValue(Elements.English, "Companies");
    company.PluralCaption.SetValue(Elements.German, "Firmen");
  <strong class="highlight">}</strong>

  <strong class="highlight">private void AddPerson()
  {</strong>
    var person = Elements.Classes.Person = Builder.AddClassWithDefaultPrimaryKey("Person", /*Guid*/, /*Guid*/);
    Builder.AddInvisibleProperty(person, "CompanyId", MetaType.Key, true, /*Guid*/);
    person.Caption.SetValue(Elements.English, "Person");
    person.Caption.SetValue(Elements.German, "Person");
    person.PluralCaption.SetValue(Elements.English, "People");
    person.PluralCaption.SetValue(Elements.German, "Personen");
  <strong class="highlight">}</strong>
}</code></pre><h2>Step seven: using multiple generators</h2><p>While this is a good technique for small models—with anywhere up to five entities—most models are larger and include entities with sizable metadata definitions. Another thing to consider is that, when working with larger teams, it&rsquo;s often best to keep a central item like the metadata definition as modular as possible.</p>
<p>To scale the pattern up for larger models, we can move code for larger entity definitions into separate generators. As soon as we move an entity to its own generator, we&rsquo;re faced with the question of where we should create paths for that entity. A path doesn&rsquo;t really <em>belong</em> to one class or another; in which generate should it go? </p>
<p>Well, we thought about that and came to the conclusion that the pattern should be to just create a separate generator for all paths in the model (or multiple path-only generators if you have a larger model). That is, when a model gets a bit larger, it should include the following generators (using the name &ldquo;Demo&rdquo; from the examples above):</p>
<ul>
<li><code>DemoCoreGenerator</code></li>
<li><code>DemoPathGenerator</code></li>
<li><code>DemoCompanyGenerator</code></li>
<li><code>DemoPersonGenerator</code></li></ul><p>The <code>DemoCoreGenerator</code> will create metadata and assign elements like the display languages. It&rsquo;s also recommended to define base types like enumerations and very simple classes [4] in the core as well. Obviously, as the model grows, the core generator may also get larger. This isn&rsquo;t a problem: just split the contents logically into multiple generators.</p>
<p>For the purposes of this example, though, we only have a single core and a single path generator and two entity generators. Since these generators will all be dependent on the model&rsquo;s builder and elements, the first step is to define a base class that will be used by the other generators.</p>
<pre class=" "><code><strong class="highlight">internal class DemoDependentGenerator : DependentMetadataGeneratorBase&lt;DemoModelGenerator, DemoModelElements, MetaBuilder&gt;
{
}</strong>

public class DemoCoreGenerator : <strong class="highlight">DemoDependentGenerator</strong>
{
  protected override void AddCoreElements()
  {
    Elements.English = Builder.AddDisplayLanguage("en-US", "English");
    Elements.German = Builder.AddDisplayLanguage("de-CH", "Deutsch");
  }
}

<strong class="highlight">public class DemoPathGenerator : DemoDependentGenerator
{</strong>
  protected override void AddPaths()
  {
    Elements.Paths.CompanyPersonPath = Builder.AddOneToManyPath(
      Elements.Classes.Company, "Id",
      Elements.Classes.Person, "CompanyId",
      /*Guid*/, /*Guid*/
    );
  }
<strong class="highlight">}</strong>

<strong class="highlight">public class DemoCompanyGenerator : DemoDependentGenerator
{
  protected override void AddClasses()
  {</strong>
    var company = Elements.Classes.Company = Builder.AddClassWithDefaultPrimaryKey("Company", /*Guid*/, /*Guid*/);
    company.Caption.SetValue(Elements.English, "Company");
    company.Caption.SetValue(Elements.German, "Firma");
    company.PluralCaption.SetValue(Elements.English, "Companies");
    company.PluralCaption.SetValue(Elements.German, "Firmen");
  <strong class="highlight">}

  protected override void AddProperties()
  {</strong>
    Builder.AddRelation(Elements.Classes.Person, "Company", "", Elements.Paths.CompanyPersonPath);
  <strong class="highlight">}
}</strong>

<strong class="highlight">public class DemoPersonGenerator : DemoDependentGenerator
{
  protected override void AddClasses()
  {</strong>
    var person = Elements.Classes.Person = Builder.AddClassWithDefaultPrimaryKey("Person", /*Guid*/, /*Guid*/);
    Builder.AddInvisibleProperty(person, "CompanyId", MetaType.Key, true, /*Guid*/);
    person.Caption.SetValue(Elements.English, "Person");
    person.Caption.SetValue(Elements.German, "Person");
    person.PluralCaption.SetValue(Elements.English, "People");
    person.PluralCaption.SetValue(Elements.German, "Personen");
  <strong class="highlight">}

  protected override void AddProperties()
  {</strong>
    Builder.AddRelation(Elements.Classes.Company, "People", "", Elements.Paths.CompanyPersonPath);
  <strong class="highlight">}
}</strong>

MetaBuilderBasedModelGeneratorBase&lt;DemoModelElements&gt;
{
  protected override void AddMetadata()
  {
    Builder.CreateModel&lt;DemoModel&gt;("Demo", /*Guid*/);
    Builder.CreateMainModule("Encodo.Quino");

    Builder.Include&lt;DemoCoreGenerator&gt;();
    <strong class="highlight">Builder.Include&lt;DemoPathGenerator&gt;();
    Builder.Include&lt;DemoCompanyGenerator&gt;();
    Builder.Include&lt;DemoPersonGenerator&gt;();</strong>
  }
}</code></pre><p>You&rsquo;ll note that we only moved code around and didn&rsquo;t have to change any implementation or add any new elements or anything that might introduce subtle errors in the metadata. Please note, the classes are all shown in a single code block above, but the pattern dictates that each class should be in its own file.</p>
<h2>Step eight: integrating external modules</h2><p>So far, we&rsquo;ve only worked with generators that are <em>dependent</em> on the model generator. How do we access information—and elements—generated in other modules? For example, let&rsquo;s include the security module and change a translation for a caption.</p>
<pre class=" "><code>public class DemoModelElements
{
  public DemoModelElements()
  {
    Classes = new DemoModelClasses();
    Paths = new DemoModelPaths();
  }

  public ILanguage English { get; set; }
  public ILanguage German { get; set; }
  <strong class="highlight">public SecurityModuleElements Security { get; set; }</strong>
  public DemoModelClasses Classes { get; private set; }
  public DemoModelPaths Paths { get; private set; }
}

public class DemoCoreGenerator : DemoDependentGenerator
{
  protected override void AddCoreElements()
  {
    Elements.English = Builder.AddDisplayLanguage("en-US", "English");
    Elements.German = Builder.AddDisplayLanguage("de-CH", "Deutsch");
    <strong class="highlight">Elements.Security = Builder.Include&lt;SecurityModuleGenerator&gt;().Elements;</strong>
  }

  <strong class="highlight">protected override void AddProperties()
  {
    Elements.Security.Classes.User.Caption.SetValue(Elements.German, "Benutzer");
  }</strong>
}</code></pre><p>This approach works well with any module that has adhered to the pattern and exposes its elements in a standardized way. [5] In this case, the core module includes the security module and retains a reference to its elements. Any code that uses the core module will now have access not only to the core elements but also to the security elements, as well.</p>
<p>Another major benefit to using this pattern is that the resulting code is quite self-explanatory: it&rsquo;s no mystery to what the <code>Elements.Security.Classes.User.Caption</code> is referring.</p>
<h2>One last thing: folder structure</h2><p>The previous pattern had a single monolithic file. The new pattern increases the number of files—possibly by quite a lot. It&rsquo;s recommended to put these new files into the following structure:</p>
<pre class=" ">[-] Models
    [+] Aspects
    [+] Elements
    [+] Generators</pre><p>The &ldquo;Aspects&rdquo; folder isn&rsquo;t new to this pattern, but it&rsquo;s worth mentioning that any model-specific aspects should go into a separate folder.</p>
<p>That&rsquo;s all for now. Happy modeling!</p>
<p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2720_1_body" class="footnote-number">[1]</span> Naturally, the <code>IMetaModel</code> is always available and any part of the generation process can access metadata in the model at any time. However, the API for the model is quite generic and requires knowledge of the unique identifier or index for a piece of metadata.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2720_2_body" class="footnote-number">[2]</span> By introspection, we mean that if metadata is accessed through .NET code structures—like properties or constants—we should be able to find all usages of a particular metadata element without resorting to a &ldquo;find in files&rdquo; for a particular string.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2720_3_body" class="footnote-number">[3]</span> It doesn&rsquo;t <em>have</em> to go there. The <code>DemoCoreGenerator</code> could also set up the builder (since it&rsquo;s using the same builder object). To do that, you&rsquo;d override <code>AddCoreElements()</code> and set up the model there. However, it&rsquo;s clearer to keep it in the generator that actually owns the builder that is being configured.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2720_4_body" class="footnote-number">[4]</span> Simple classes generally have few extra properties and no layouts or short description classes.</div><div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2720_5_body" class="footnote-number">[5]</span> Through the <code>IElementProvider</code> mentioned above</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2718</guid>
    <title><![CDATA[Updating to a touch-friendly UI]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2718</link>
    <pubDate>Wed, 21 Nov 2012 23:08:51 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">21. Nov 2012 23:08:51 (GMT-5)</span>
</p>
<p>
Updated by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Mar 2013 09:44:48 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>I was recently redesigning a web page and wanted to make it easier to use from touch-screen browsers. Links made only of text are relatively easy to click with a mouse, but tend to make poor touch targets. If the layout has enough space around the link, this can be remedied by applying CSS.</p>
<h2>The basic box</h2><div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; width: 50%"><a href="#" style="padding: 0px 20px; color: goldenrod; background-color: #8F8F8F">First</a><a href="#" style="padding: 0px 20px; color: gold; background-color: #8F8F8F">Second</a><a href="#" style="padding: 0px 20px; color: yellowgreen; background-color: #8F8F8F">Third</a></div><p>Suppose we have a box with three links in it, as shown to the right.</p>
<h2>Setting the height</h2><p>The first step is to make this box taller, so the logical thing to do is to set the height. We&rsquo;ll have to pick a value, so set <code>height: 40px</code> on the gray box.</p>
<div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; width: 50%; height: 40px"><a href="#" style="padding: 0px 20px; color: goldenrod; background-color: #8F8F8F">First</a><a href="#" style="padding: 0px 20px; color: gold; background-color: #8F8F8F">Second</a><a href="#" style="padding: 0px 20px; color: yellowgreen; background-color: #8F8F8F">Third</a></div><h2>Aligning vertically</h2><p>This isn&rsquo;t exactly what we want, though; we&rsquo;d rather have the vertical space equally distributed. Also, if you hover over the links, you can see that the space below the text is not active. Maybe we can try to add <code>vertical-align: middle</code> to align the content.</p>
<div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; width: 50%; height: 40px; vertical-align: middle"><a href="#" style="padding: 0px 20px; color: goldenrod; background-color: #8F8F8F">First</a><a href="#" style="padding: 0px 20px; color: gold; background-color: #8F8F8F">Second</a><a href="#" style="padding: 0px 20px; color: yellowgreen; background-color: #8F8F8F">Third</a></div><p>Unfortunately, this doesn&rsquo;t have the desired effect. The <code>vertical-align</code> property works when used this way in table cells, but otherwise has no effect for block elements. Knowing that, we can set <code>display: table-cell</code> for the gray box.</p>
<div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; width: 50%; height: 40px; vertical-align: middle; display: table-cell"><a href="#" style="padding: 0px 20px; color: goldenrod; background-color: #8F8F8F">First</a><a href="#" style="padding: 0px 20px; color: gold; background-color: #8F8F8F">Second</a><a href="#" style="padding: 0px 20px; color: yellowgreen; background-color: #8F8F8F">Third</a></div><p>And now the box has become longer, because the 50% width of the box is calculated differently for table cells than for regular boxes (especially when a table cell is found outside of a table).</p>
<h2>Relative positioning</h2><p>Let&rsquo;s abandon the vertical-alignment approach and try using positioning instead. Set <code>position: relative</code> and <code>top: 25%</code> to center the links vertically.</p>
<div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; width: 50%; height: 40px"><a href="#" style="padding: 0px 20px; position: relative; top: 25%; color: goldenrod; background-color: #8F8F8F">First</a><a href="#" style="padding: 0px 20px; position: relative; top: 25%; color: gold; background-color: #8F8F8F">Second</a><a href="#" style="padding: 0px 20px; position: relative; top: 25%; color: yellowgreen; background-color: #8F8F8F">Third</a></div><p>Now that looks much better, but the space above and below the links is still not active. Perhaps we can use the height trick again, to make the individual links taller as well. So we set <code>height: 100%</code> on each of the links.</p>
<div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; width: 50%; height: 40px"><a href="#" style="padding: 0px 20px; position: relative; top: 25%; color: goldenrod; background-color: #8F8F8F; height: 100%">First</a><a href="#" style="padding: 0px 20px; position: relative; top: 25%; color: gold; background-color: #8F8F8F; height: 100%">Second</a><a href="#" style="padding: 0px 20px; position: relative; top: 25%; color: yellowgreen; background-color: #8F8F8F; height: 100%">Third</a></div><p>We didn&rsquo;t get the expected result, but we should have expected that: the links are <code>inline</code> elements and can only have a height set if we set <code>display: inline-block</code> on each link as well. We use <code>inline-block</code> rather than <code>block</code> so that the links stay on the same line.</p>
<div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; width: 50%; height: 40px"><a href="#" style="padding: 0px 20px; position: relative; top: 25%; color: goldenrod; background-color: #8F8F8F; height: 100%; display: inline-block">First</a><a href="#" style="padding: 0px 20px; position: relative; top: 25%; color: gold; background-color: #8F8F8F; height: 100%; display: inline-block">Second</a><a href="#" style="padding: 0px 20px; position: relative; top: 25%; color: yellowgreen; background-color: #8F8F8F; height: 100%; display: inline-block">Third</a></div><p>The links are now the right size, but they stick out below the gray box, which isn&rsquo;t what we wanted at all. We&rsquo;re kind of out of ideas with this approach, but there is another way we can get the desired effect.</p>
<h2>Positive padding and negative margins</h2><p>Let&rsquo;s start with the original gray box and, instead of choosing a random height as we did above—<code>40px</code>—let&rsquo;s set <code>padding: 8px</code> on the gray box to make room above and below the links.</p>
<div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; padding: 8px 0; width: 50%"><a href="#" style="padding: 0px 20px; color: goldenrod; background-color: #8F8F8F">First</a><a href="#" style="padding: 0px 20px; color: gold; background-color: #8F8F8F">Second</a><a href="#" style="padding: 0px 20px; color: yellowgreen; background-color: #8F8F8F">Third</a></div><p>With just one CSS style, we&rsquo;ve already got the links nicely aligned and, as an added benefit, this technique scales even if the font size is changed. The 8-pixel padding is preserved regardless of how large the font gets. [1]</p>
<div class=" " style="font-size: 14pt; background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; padding: 8px 0; width: 50%"><a href="#" style="padding: 0 20px; color: goldenrod; background-color: #8F8F8F">First</a><a href="#" style="padding: 0 20px; color: gold; background-color: #8F8F8F">Second</a><a href="#" style="padding: 0 20px; color: yellowgreen; background-color: #8F8F8F">Third</a></div><p>This approach seems promising, but the links are still not tall enough. The naive approach of setting <code>height: 100%</code> on the links probably won&rsquo;t work as expected, but let&rsquo;s try it anyway.</p>
<div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; padding: 8px 0; width: 50%"><a href="#" style="padding: 0 20px; color: goldenrod; background-color: #8F8F8F; height: 100%">First</a><a href="#" style="padding: 0 20px; color: gold; background-color: #8F8F8F; height: 100%">Second</a><a href="#" style="padding: 0 20px; color: yellowgreen; background-color: #8F8F8F; height: 100%">Third</a></div><p>It looks like the links were already 100% of the height of the container; in hindsight it&rsquo;s obvious, since the height of the gray box is determined by the height of the links. The 100% height refers to the client area of the gray box, which doesn&rsquo;t include the padding.</p>
<p>We&rsquo;d actually like the links to have padding above and below just as the gray box has. As we saw above, the links will only honor the padding if they also have <code>display: inline-block</code>, so let&rsquo;s set that in addition to <code>padding: 8px</code>.</p>
<div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; padding: 8px 0; width: 50%"><a href="#" style="padding: 0 20px; color: goldenrod; background-color: #8F8F8F; padding-top: 8px; padding-bottom: 8px; display: inline-block">First</a><a href="#" style="padding: 0 20px; color: gold; background-color: #8F8F8F; padding-top: 8px; padding-bottom: 8px; display: inline-block">Second</a><a href="#" style="padding: 0 20px; color: yellowgreen; background-color: #8F8F8F; padding-top: 8px; padding-bottom: 8px; display: inline-block">Third</a></div><p>We&rsquo;re almost there. The only thing remaining is to make the vertical padding of the links overlap with the vertical padding of the gray box. We can do this by using a <em>negative</em> vertical margin, setting <code>margin: -8px</code>.</p>
<div class=" " style="background-color: gray; border: 1px solid black; border-width: 1px 0; text-align: center; padding: 8px 0; width: 50%"><a href="#" style="padding: 0 20px; color: goldenrod; background-color: #8F8F8F; padding: 8px 20px; display: inline-block; margin: -8px 0">First</a><a href="#" style="color: gold; background-color: #8F8F8F; padding: 8px 20px; display: inline-block; margin: -8px 0">Second</a><a href="#" style="color: yellowgreen; background-color: #8F8F8F; padding: 8px 20px; display: inline-block; margin: -8px 0">Third</a></div><p>We finally have the result we wanted. The links are now large enough for the average finger to strike without trying too hard. Welcome to the CSS-enabled touch-friendly world of web design.</p>
<p>The code for the final example is shown below, with the sizing/positioning styles highlighted:</p>
<pre class=" "><code>.gray-box
{
  background-color: gray;
  border: 1px solid black;
  border-width: 1px 0;
  width: 50%;
  text-align: center;
  <strong class="highlight">padding: 8px</strong> 0;
}

.gray-box a
{
  background-color: #8F8F8F;
  <strong class="highlight">display: inline-block;
  padding: 8px</strong> 20px;
  <strong class="highlight">margin: -8px</strong> 0;
}

&lt;div class="gray-box"&gt;
  &lt;a href="#" style="color: goldenrod"&gt;First&lt;/a&gt;
  &lt;a href="#" style="color: gold"&gt;Second&lt;/a&gt;
  &lt;a href="#" style="color: yellowgreen"&gt;Third&lt;/a&gt;
&lt;/div&gt;</code></pre><p><hr></p>
<div class="footnote-reference"><span id="footnote_DRAFTABLE_ENTRY_2718_1_body" class="footnote-number">[1]</span> Naturally, we could also use <code>.8em</code> instead and then the padding will scale with the font size. This would work just as well with the height. Let&rsquo;s pretend that we&rsquo;re working with a specification that requires an 8-pixel padding instead of a flexible one.</div>      </div>
  ]]></description>
  </item>
  <item>
    <guid>https://www.earthli.com/news/view_article.php?id=2605</guid>
    <title><![CDATA[Solving problems]]></title>
    <link>https://www.earthli.com/news/view_article.php?id=2605</link>
    <pubDate>Sun, 08 Jan 2012 17:13:18 +0100</pubDate>
    <description><![CDATA[<div class="info-box-top">
<p>
Published by <a href="https://www.earthli.com/news/view_user.php?name=marco" title="Marco von Ballmoos" class="visible">marco</a> on <span class="date-time">8. Jan 2012 17:13:18 (GMT-5)</span>
</p>
</div>
      <div class="text-flow wide">
  <p>This graphic <a href="http://www.howtogeek.com/102420/geeks-versus-non-geeks-when-doing-repetitive-tasks-funny-chart/">Geeks versus Non-Geeks when Doing Repetitive Tasks</a> (<cite><a href="http://www.howtogeek.com/">How-to Geek</a></cite>) illustrates quite nicely how programmers approach the world of problem-solving.</p>
<p><img src="https://www.earthli.com/data/news/attachments/entry/2605/geeks-vs-nongeeks-repetitive-tasks.png" alt=" " class="frame"></p>
<p>The chart does <em>not</em> show just much time must be spent before the programmer wins, that being dependent on the complexity of the task. The probability that the task will recur is also highly relevant, as automation of a smallish, one-time task is useless. Neither of those things will stop a determined programmer, though, who will automate no matter what.</p>
      </div>
  ]]></description>
  </item>
  </channel>
</rss>
