<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adam Warski</title>
    <description>The latest articles on DEV Community by Adam Warski (@adamw).</description>
    <link>https://dev.to/adamw</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F451909%2Fe509024d-d771-4fa7-b9fe-bf6dc22bd70d.jpeg</url>
      <title>DEV Community: Adam Warski</title>
      <link>https://dev.to/adamw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adamw"/>
    <language>en</language>
    <item>
      <title>What is Dependency Injection?</title>
      <dc:creator>Adam Warski</dc:creator>
      <pubDate>Tue, 13 Apr 2021 18:58:47 +0000</pubDate>
      <link>https://dev.to/softwaremill/what-is-dependency-injection-10j5</link>
      <guid>https://dev.to/softwaremill/what-is-dependency-injection-10j5</guid>
      <description>&lt;p&gt;"&lt;em&gt;Dependency Injection is just passing parameters&lt;/em&gt;", "&lt;em&gt;Spring is necessary to do Dependency Injection properly&lt;/em&gt;", "&lt;em&gt;Dependency Injection is a way to escape from functional programming&lt;/em&gt;": these are just some of the quotes circulating about Dependency Injection. As for a technical pattern, it seems quite controversial. Is there any substance in Dependency Injection (DI)? Is this something you should be using in your application? Or maybe using DI makes you a bad programmer?&lt;/p&gt;

&lt;p&gt;These are all good questions! However, what's often missing from discussions is an accurate description of what Dependency Injection exactly is. A good, &lt;strong&gt;precise definition&lt;/strong&gt; might stop many arguments before they begin.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://martinfowler.com/articles/injection.html"&gt;classic article&lt;/a&gt; by Martin Fowler is a good start, however it's quite dated and although quite long, does not give an exact definition. Moreover, our usage of &lt;em&gt;Object Orientation&lt;/em&gt; (OO) has evolved since 2004, and is increasingly blended with &lt;em&gt;Functional Programming&lt;/em&gt; (FP), hence an update might be in order. Popular answers on &lt;a href="https://stackoverflow.com/questions/130794/what-is-dependency-injection"&gt;Stack Overflow&lt;/a&gt; and the &lt;a href="https://en.wikipedia.org/wiki/Dependency_injection"&gt;Wikipedia&lt;/a&gt; entry provide reasonable benefits on why to consider using DI in an application, but fail to succinctly capture the main goals of the pattern, or as many critics of DI point out, describe nothing else than passing a parameter to a function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's try to clear things up!
&lt;/h2&gt;

&lt;p&gt;The classes and objects that we create and use in our applications tend to fall in two categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Service objects&lt;/strong&gt;. These are "bags of methods" or "sets of functions", and are used to modularize the code base. Good examples of service objects might be &lt;code&gt;UserRepository&lt;/code&gt;, &lt;code&gt;EmailSender&lt;/code&gt;, &lt;code&gt;ProfileManager&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Data objects&lt;/strong&gt;, either pure data or data combined with behavior ("proper" OO). Examples include &lt;code&gt;Product&lt;/code&gt;, &lt;code&gt;Invoice&lt;/code&gt;, &lt;code&gt;UserVisitor&lt;/code&gt;, …&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both types of objects are created at different times in the application and used in different ways.&lt;/p&gt;

&lt;p&gt;Service objects tend to be created &lt;strong&gt;once&lt;/strong&gt; at the &lt;strong&gt;start&lt;/strong&gt; of the application. They don't change during the execution of the program. In other words, service objects are the &lt;strong&gt;modules&lt;/strong&gt; from which your application logic is composed. Services might &lt;strong&gt;depend&lt;/strong&gt; on one another, forming a &lt;strong&gt;dependency graph&lt;/strong&gt;. Moreover, specific implementations of services might be &lt;strong&gt;interchangeable&lt;/strong&gt;, depending on configuration, environment, command-line options, etc.&lt;/p&gt;

&lt;p&gt;The crucial property of the service/module graph is that it is &lt;strong&gt;created statically&lt;/strong&gt;. Only when the graph of services is wired, the application is usually ready to serve user requests. Hence the service objects/modules are static and &lt;strong&gt;global&lt;/strong&gt;, as well as typically &lt;strong&gt;stateless&lt;/strong&gt;. They only contain methods, without any (mutable) data, except maybe for configuration and pre-computed values. There are exceptions as well, such as cache services.&lt;/p&gt;

&lt;p&gt;Data objects, on the other hand, are created &lt;strong&gt;dynamically&lt;/strong&gt;, either in response to user interaction, API invocation, scheduled tasks, etc. They usually have a short, &lt;strong&gt;local&lt;/strong&gt; lifespan. They &lt;strong&gt;carry and manipulate&lt;/strong&gt; the data that the application processes. They might combine data and behavior, or be pure, "thin", data structures.&lt;/p&gt;

&lt;p&gt;Summing up, we have the following properties of &lt;strong&gt;service&lt;/strong&gt; vs &lt;strong&gt;data&lt;/strong&gt; objects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;static — dynamic&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;global — local&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;stateless — stateful&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But we were supposed to talk about dependency injection, where is it then?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Dependency Injection is the process of creating the static, stateless graph of service objects, where each service is parametrised by its dependencies.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it! This definition has several implications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;First of all&lt;/strong&gt;, a direct consequence is that DI doesn't mandate the use of any framework. It's perfectly feasible to do dependency injection &lt;a href="http://di-in-scala.github.io"&gt;"by hand", using just constructors&lt;/a&gt;. Whether doing manual dependency injection, &lt;a href="https://gitter.im/adamw/macwire"&gt;compile-time&lt;/a&gt; dependency injection, or run-time DI, is an implementation detail.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Frameworks are of course allowed as well. For example, &lt;a href="http://spring.io"&gt;Spring&lt;/a&gt; is a DI framework, which uses annotations, xml and reflection to create the static service (component) graph, so it definitely matches the definition. Whether it make sense to sacrifice control over how you create objects and rely on runtime reflection is exchange for a little less code, is another debate.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secondly&lt;/strong&gt;, by requiring that the services are parametrised by their dependencies, we mandate &lt;em&gt;inversion of control&lt;/em&gt; (IoC). This makes the dependencies interchangeable (e.g. for testing, or by configuration). Moreover, it's up to the wiring code (the code that creates the static object graph) to decide which specific implementation is used to satisfy a dependency; this responsibility is outside of the control of the service; the dependencies are provided  &lt;em&gt;externally&lt;/em&gt;  by the DI process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dependency injection isn't just passing function parameters. Passing function parameters can be used to implement DI, but what matters here is &lt;strong&gt;why&lt;/strong&gt; we are passing these parameters in the first place: to create the static graph of modules at the start of the application. Parameter passing is an implementation detail.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As I've also &lt;a href="https://softwaremill.com/reader-monad-constructor-dependency-injection-friend-or-foe/"&gt;argued before&lt;/a&gt;, DI is different than other approaches for managing dependencies, such as the reader monad. The reader monad is a mechanism that is &lt;strong&gt;complementary&lt;/strong&gt; to dependency injection, as it makes the dependencies explicit, while with DI the dependency graph is created upfront and hides the dependencies from normal method/function calls. Both mechanisms are useful for different purposes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, DI and FP are orthogonal, and DI is a perfectly valid and useful concept when doing Functional Programming. The functions that are used in FP also often need to be grouped in "modules", which is another way of saying that functions are grouped as methods into classes; they need to be parametrised by other sets of functions (other modules); and they need to be substituted depending on configuration, or in tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nothing in the definition of DI forces us to use mutable data, side-effects, frameworks, impure functions etc.&lt;/p&gt;

&lt;p&gt;To sum up, is DI machinery created to avoid FP constructs? No! It can use that machinery, for a clearly stated goal: &lt;strong&gt;creating the (usually static) module graph on application startup&lt;/strong&gt;. It's not a mandatory part of every application: it's definitely viable to write good, readable code without it. But as the codebase grows, modularising the code and adding a startup step which wires all of the modules can improve the readability, explorability and maintainability of the project.&lt;/p&gt;

</description>
      <category>di</category>
      <category>spring</category>
      <category>dependencyinjection</category>
    </item>
    <item>
      <title>Starting with Scala 3 macros: a short tutorial</title>
      <dc:creator>Adam Warski</dc:creator>
      <pubDate>Fri, 09 Apr 2021 13:58:17 +0000</pubDate>
      <link>https://dev.to/softwaremill/starting-with-scala-3-macros-a-short-tutorial-11cb</link>
      <guid>https://dev.to/softwaremill/starting-with-scala-3-macros-a-short-tutorial-11cb</guid>
      <description>&lt;p&gt;&lt;a href="https://www.scala-lang.org" rel="noopener noreferrer"&gt;Scala 3&lt;/a&gt;, also known by its development name &lt;a href="https://dotty.epfl.ch" rel="noopener noreferrer"&gt;Dotty&lt;/a&gt;, is expected to ship by the end of April 2021. One of its flagship features is &lt;a href="https://dotty.epfl.ch/docs/reference/metaprogramming/toc.html" rel="noopener noreferrer"&gt;principled metaprogramming&lt;/a&gt;. This includes macros — &lt;strong&gt;compile-time code generation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Macros have been pioneered through an &lt;a href="https://docs.scala-lang.org/overviews/macros/usecases.html" rel="noopener noreferrer"&gt;experimental API&lt;/a&gt; since Scala 2.10. Even though the API was experimental, macros have become a useful tool, leveraged by a number of libraries. &lt;a href="https://medium.com/why-scala-a6ac8c98c541" rel="noopener noreferrer"&gt;Scala is a flexible&lt;/a&gt; and scalable language; still, macros allow to further reduce boilerplate code in a number of use-cases.&lt;/p&gt;

&lt;p&gt;Given their popularity, it doesn't come as a surprise that the next major revision of the Scala language keeps metaprogramming capabilities, however in an improved form. The new approach is &lt;strong&gt;no longer experimental&lt;/strong&gt;, and draws from the experiences from previous macros implementation.&lt;/p&gt;

&lt;p&gt;At the code level, Scala 3 macros are unfortunately quite different from the previous version; however, this mostly affects library code, as that's where macros were predominantly used.&lt;/p&gt;

&lt;p&gt;The scope of metaprogramming in Dotty / Scala 3 is also different from what we've seen in Scala 2. In some areas it is broader, in some — more constrained. For example, Scala 3 brings extensive &lt;strong&gt;inlining support&lt;/strong&gt;. On the other hand, &lt;strong&gt;macro annotations&lt;/strong&gt; are no longer there.&lt;/p&gt;

&lt;h1&gt;
  
  
  A simple macro
&lt;/h1&gt;

&lt;p&gt;Let's see how we can start developing a simple macro for Scala 3! I did a &lt;a href="https://www.warski.org/blog/2012/12/starting-with-scala-macros-a-short-tutorial/" rel="noopener noreferrer"&gt;similar tutorial&lt;/a&gt; for the Scala 2.10 macros, 8 years ago! Back then, we were writing a macro which improves on println-debugging.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo3wx2c4il45li3am8ep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo3wx2c4il45li3am8ep.png" alt="8 years of Scala and counting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Turns out, 8 years later, &lt;code&gt;println&lt;/code&gt;-debugging is still one of the main debugging methods that I'm using. Quite often, we want to print some message and labeled values, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"Funds transferred, from = $from, to = $to, amount = $amount"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It would be nice if we didn't have to duplicate the names of the values used. Our goal is to write a macro which will automatically print the value labels. The syntax that we'd like to achieve is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Funds transferred"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why do we need a macro here? We need to access the abstract syntax tree (AST) of our code, so that we can find out what the names are. Let's see how we can implement the macro step-by-step. All of the code is &lt;a href="https://github.com/softwaremill/scala3-macro-debug" rel="noopener noreferrer"&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Project setup
&lt;/h1&gt;

&lt;p&gt;Each project starts with a build; same here, we'll be using &lt;a href="https://www.scala-sbt.org" rel="noopener noreferrer"&gt;sbt&lt;/a&gt; (version 1.5.0), but any other tool which supports Scala3/Dotty can be used as well.&lt;/p&gt;

&lt;p&gt;The only property that we need to specify in &lt;code&gt;build.sbt&lt;/code&gt; is the Scala version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="n"&gt;scalaVersion&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"3.0.0-RC1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we have that, we can import the project into &lt;a href="https://www.jetbrains.com/idea/" rel="noopener noreferrer"&gt;IntelliJ&lt;/a&gt; or &lt;a href="https://scalameta.org/metals/" rel="noopener noreferrer"&gt;Metals&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Hello, world!
&lt;/h1&gt;

&lt;p&gt;We'll be working with two source files. First, &lt;code&gt;Debug.scala&lt;/code&gt; is going to be where the debug macro will be implemented. Second, &lt;code&gt;Test.scala&lt;/code&gt; will be where we'll be testing the code we've written. We need two separate files, as these need to be compiled separately by the compiler: we can't use code-generating code (the macro) before it has been compiled itself!&lt;/p&gt;

&lt;p&gt;Let's start with an even simpler task: writing code which will generate a &lt;code&gt;println("Hello, world!")&lt;/code&gt; when invoked. This is quite trivial:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Debug&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
  &lt;span class="kt"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="kt"&gt;hello&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Test&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
  &lt;span class="kt"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Debug._&lt;/span&gt;
  &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Did we actually write a macro? Not really. Instead, we've taken advantage of a new Scala 3 / Dotty metaprogramming feature: &lt;a href="https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html" rel="noopener noreferrer"&gt;inlining&lt;/a&gt;. Notice that the &lt;code&gt;hello&lt;/code&gt; method is prefixed with the &lt;code&gt;inline&lt;/code&gt; modifier. This instructs the compiler (and it's not only a suggestion — but a &lt;strong&gt;requirement&lt;/strong&gt;), that upon compilation, the method body should be inlined at the call-site.&lt;/p&gt;

&lt;p&gt;Hence, when we compile the above and inspect the bytecode, we won't see a &lt;code&gt;hello()&lt;/code&gt; invocation in our &lt;code&gt;Test&lt;/code&gt; application. Instead, the bytecode will contain directly &lt;code&gt;println("Hello, world!")&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In a way, inlining as described above is a way to do &lt;strong&gt;static metaprogramming&lt;/strong&gt; — the code is generated, but basing on statically available information, without any computation. Let's see how we can take it one step further, and do some &lt;strong&gt;dynamic&lt;/strong&gt; &lt;strong&gt;metaprogramming&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Single-parameter debug
&lt;/h1&gt;

&lt;p&gt;Our goal will now be to write a &lt;code&gt;debugSingle&lt;/code&gt; method, which will expand a &lt;code&gt;debugSingle(x)&lt;/code&gt; call into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value of x is "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inlining is no longer enough. We need to access the name (or code fragment) that is passed to our method — not its value. We start out similarly as before, with a method that should be inlined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="n"&gt;inline&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debugSingle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the method that the user will invoke. However, the implementation will need to operate on a representation of the parameter which gives access to information available at compile-time: the textual representation of the code, to generate the label.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that this is quite different from the run-time representation; at compile-time, we manipulate trees corresponding to expressions. At run-time, we manipulate values to which the expressions are evaluated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The mechanism to convert between the compile-time and run-time representations is called &lt;strong&gt;quoting&lt;/strong&gt; &amp;amp; &lt;strong&gt;splicing&lt;/strong&gt;. When we quote a value (by prepending the expression with&lt;code&gt;'&lt;/code&gt;), we get back the abstract syntax tree (AST; a value of type &lt;code&gt;Expr[_]&lt;/code&gt;), representing the expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="ss"&gt;'expr&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;In case of Scala macros, the AST is our code represented as data, which we can inspect. &lt;code&gt;Expr&lt;/code&gt; is the root type; each Scala construct corresponds to a subclass of this type. As these can be nested (e.g. an &lt;code&gt;If&lt;/code&gt; expression has child expressions), our code can be represented as a tree.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When we splice a value using &lt;code&gt;${ }&lt;/code&gt;, we go back to the run-time land:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="n"&gt;anotherExpr&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="o"&gt;]}&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can think of quoting as a function &lt;code&gt;T =&amp;gt; Expr[T]&lt;/code&gt;, transforming code into an abstract syntax tree which can be manipulated at compile-time. Dually, splicing is a function &lt;code&gt;Expr[T] =&amp;gt; T&lt;/code&gt;, transforming an abstract syntax tree into code that will be compiled and evaluated at run-time, into a value of the given type.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A crucial property that is enforced by the compiler is the &lt;strong&gt;phase consistency principle&lt;/strong&gt;. It makes sure that you can only access the AST during compile time (at run-time, this information is no longer available!), and that you are not trying to access the value of an expression when a macro is being invoked (as the values are only available at run-time).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The implementation of the &lt;code&gt;debugSingle&lt;/code&gt; macro will operate on abstract syntax trees. Hence, its signature is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debugSingleImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="o"&gt;])(&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="nc"&gt;Quotes&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;**using** QuoteContext&lt;/code&gt; value: it is provided implicitly by the compiler, and allows e.g. to report error messages that might occur during macro invocation.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;debugSingleImpl&lt;/code&gt; method takes an AST representing the expression that's been passed in as a parameter. This can be a simple value reference (&lt;code&gt;x&lt;/code&gt;), or anything more complex (e.g. &lt;code&gt;x+y*2&lt;/code&gt;). It returns an AST — code represented as data, of type &lt;code&gt;Expr[Unit]&lt;/code&gt;— which when evaluated, returns a unit (a side-effect).&lt;/p&gt;

&lt;p&gt;Here's the implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debugSingleImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="o"&gt;])(&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="nc"&gt;Quotes&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; 
  &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value of "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;show&lt;/span&gt;&lt;span class="o"&gt;)}&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" is "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;$expr&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The outer operation is quoting (&lt;code&gt;'{ ... }&lt;/code&gt;): converting code it contains (of any type &lt;code&gt;T&lt;/code&gt;) to a value of type &lt;code&gt;Expr[T]&lt;/code&gt;; that is, an abstract syntax tree — representing the code as data. For example, &lt;code&gt;'{ println("Hello, world!") }&lt;/code&gt; would return a value of type &lt;code&gt;Expr[Unit]&lt;/code&gt; (&lt;code&gt;Unit&lt;/code&gt; as that's the type returned by &lt;code&gt;println&lt;/code&gt;), which represents the AST corresponding to the invocation of &lt;code&gt;println&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, inside the code for which we are generating the AST, we want to &lt;strong&gt;embed&lt;/strong&gt; some expressions, represented as data: the string literal corresponding to the name of the value (the label), and the expression which computes the value.&lt;/p&gt;

&lt;p&gt;This first is done using &lt;code&gt;expr.show&lt;/code&gt;. This will be evaluated at compile-time, and converts the AST of &lt;code&gt;expr&lt;/code&gt; into a &lt;code&gt;String&lt;/code&gt;: the textual representation of the code. We create an AST fragment — an expression which represents a constant string with the given value using &lt;code&gt;Expr(expr.show)&lt;/code&gt;, and finally we &lt;strong&gt;splice&lt;/strong&gt; (embed) it into the code that we are generating.&lt;/p&gt;

&lt;p&gt;The second is done by splicing the (unchanged) AST of &lt;code&gt;expr&lt;/code&gt; into the generated code. Any code that is passed as a parameter to &lt;code&gt;debugSingleImpl&lt;/code&gt;, will end up unchanged in the generated code. For example, calling &lt;code&gt;debugSingle(x+y)&lt;/code&gt; will generate, at compile-time, the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value of "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"x.+(y)"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" is "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One final task remains: calling &lt;code&gt;debugSingleImpl&lt;/code&gt; from &lt;code&gt;debugSingle&lt;/code&gt;. To do that, we need to quote the &lt;code&gt;expr&lt;/code&gt; so that the AST is passed to the macro implementation (we can access that since the method is inlined), and splice the result, converting the AST back into code that will be compiled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="n"&gt;inline&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debugSingle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;debugSingleImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;'expr&lt;/span&gt;&lt;span class="o"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Are we done? Not quite. We need to require that the compiler will inline any usages of the &lt;code&gt;expr&lt;/code&gt; parameter, instead of creating a temporary value with its value; that would spoil our labels! This is done by adding &lt;code&gt;inline&lt;/code&gt; to the parameter as well. Here's the whole implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="n"&gt;inline&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debugSingle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inline&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;debugSingleImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;'expr&lt;/span&gt;&lt;span class="o"&gt;)}&lt;/span&gt; 

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debugSingleImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="o"&gt;])(&lt;/span&gt;
  &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="nc"&gt;Quotes&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; 
  &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value of "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;expr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;show&lt;/span&gt;&lt;span class="o"&gt;)}&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" is "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;$expr&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Multi-parameter debug
&lt;/h1&gt;

&lt;p&gt;We can now improve our implementation so that it works with multiple parameters. Additionally, if a parameter is a string literal, we'd like to simply include it in the output, without the label.&lt;/p&gt;

&lt;p&gt;First, let's define the user-facing method. We'll use varargs so that it can be called with multiple parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="n"&gt;inline&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inline&lt;/span&gt; &lt;span class="n"&gt;exprs&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any*&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;debugImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;'exprs&lt;/span&gt;&lt;span class="o"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea is the same: we have an inlined method which splices the result of a computation involving code represented as ASTs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This follows the &lt;a href="https://dotty.epfl.ch/docs/reference/metaprogramming/macros.html" rel="noopener noreferrer"&gt;definition from the Dotty docs&lt;/a&gt;: a macro is an inline function that contains a splice operation outside an enclosing quote.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Varargs are represented as a sequence, hence the signature of the macro implementation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debugImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exprs&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Seq&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="o"&gt;]])(&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="nc"&gt;Quotes&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the implementation itself, we first have to inspect the passed &lt;code&gt;exprs&lt;/code&gt; tree and verify if it corresponds to multiple parameters passed as varargs. This can be done with &lt;strong&gt;pattern matching&lt;/strong&gt;, using the &lt;code&gt;Varargs&lt;/code&gt; extractor provided by the Scala 3 standard library. As a result, we get a sequence of trees (from &lt;code&gt;Expr[Seq[Any]]&lt;/code&gt;, we get &lt;code&gt;Seq[Expr[Any]]&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;stringExps&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Seq&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exprs&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; 
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Varargs&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;es&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// macro implementation called with varargs&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// macro implementation called with other parameters&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the extraction is successful, we map each expression corresponding to subsequent parameters, using pattern matching again. This time, we inspect the underlying term tree, to check if it corresponds to a constant value (such as a constant string literal).&lt;/p&gt;

&lt;p&gt;If so, we return an expression containing that constant (as a string). Otherwise, we convert the expression to a string containing the label and value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Varargs&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;es&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; 
  &lt;span class="nv"&gt;es&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;map&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;asTerm&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Literal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Constant&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;showWithValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why one time do we have to match on expressions, and the other on terms? &lt;code&gt;Varargs&lt;/code&gt; is a special construct used to handle this type of parameters. In all other cases, if we want to inspect the shape of the code that was passed in (the Abstract Syntax Tree), we'll have to match on the expression's term — as above.&lt;/p&gt;

&lt;p&gt;And we're almost done; the last step is converting the &lt;code&gt;stringExps: Seq[Expr[String]]&lt;/code&gt; to an &lt;code&gt;Expr[String]&lt;/code&gt; by &lt;strong&gt;generating code&lt;/strong&gt; which will concatenate all of the strings. Two string expressions can be concatenated by splicing both expressions, combining them as any other two strings, and quoting the result. More generally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;concatenatedStringsExp&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stringExps&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;reduceOption&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;$e1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;$e2&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getOrElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And so we arrive at our final implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="n"&gt;inline&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inline&lt;/span&gt; &lt;span class="n"&gt;exprs&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Any*&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;debugImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;'exprs&lt;/span&gt;&lt;span class="o"&gt;)}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;debugImpl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exprs&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Seq&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="o"&gt;]])(&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="nc"&gt;Quotes&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; 
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;showWithValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; 
    &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;show&lt;/span&gt;&lt;span class="o"&gt;)}&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" = "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;stringExps&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Seq&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exprs&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; 
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Varargs&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;es&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; 
      &lt;span class="nv"&gt;es&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;map&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;asTerm&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Literal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Constant&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;showWithValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;showWithValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;

  &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;concatenatedStringsExp&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stringExps&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;reduceOption&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;$e1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;$e2&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getOrElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;

  &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;$concatenatedStringsExp&lt;/span&gt;&lt;span class="o"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  What's next
&lt;/h1&gt;

&lt;p&gt;We've just scratched the surface of metaprogramming capabilities in Scala 3 / Dotty. First of all, inlining (the "static" metaprogramming variant) has quite a lot of interesting features, as described in &lt;a href="https://dotty.epfl.ch/docs/reference/metaprogramming/toc.html" rel="noopener noreferrer"&gt;Dotty docs&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;recursive inline methods&lt;/li&gt;
&lt;li&gt;specialized inline methods&lt;/li&gt;
&lt;li&gt;using conditionals &amp;amp; matches in inlined methods&lt;/li&gt;
&lt;li&gt;selective summoning (conditional logic depending on available implicits)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Macros also have other features which we haven't covered, such as quoting &amp;amp; splicing types, summoning implicits in macros and more extensive pattern matching involving quoted patterns. Finally, there's multi-stage programming support, which enables constructing code at run-time.&lt;/p&gt;

&lt;p&gt;As mentioned before, all of the code presented here is &lt;a href="https://github.com/softwaremill/scala3-macro-debug" rel="noopener noreferrer"&gt;available on GitHub&lt;/a&gt;. Have fun exploring Scala 3 / Dotty!&lt;/p&gt;

</description>
      <category>scala</category>
      <category>metaprogramming</category>
      <category>macros</category>
    </item>
    <item>
      <title>3 reasons to adopt Event Sourcing</title>
      <dc:creator>Adam Warski</dc:creator>
      <pubDate>Thu, 01 Apr 2021 12:42:17 +0000</pubDate>
      <link>https://dev.to/softwaremill/3-reasons-to-adopt-event-sourcing-1dh7</link>
      <guid>https://dev.to/softwaremill/3-reasons-to-adopt-event-sourcing-1dh7</guid>
      <description>&lt;p&gt;Event Sourcing is everywhere. Almost every architectural problem in an IT system can be solved using Event Sourcing. Is that true? Of course not! Still, the pattern is proving to be very useful in a number of situations. When to consider using event sourcing? What are the scenarios, where this pattern works best?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i03-Gric--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xr505o6jlgcvq0xlccyu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i03-Gric--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xr505o6jlgcvq0xlccyu.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a couple of great articles on the basics of event sourcing, such as the &lt;a href="https://docs.microsoft.com/en-us/previous-versions/msp-n-p/jj591559(v=pandp.10)?redirectedfrom=MSDN"&gt;introduction on MSDN&lt;/a&gt;, &lt;a href="https://martinfowler.com/eaaDev/EventSourcing.html"&gt;another one by Martin Fowler&lt;/a&gt;, or the documentation of &lt;a href="https://doc.akka.io/docs/akka/current/typed/persistence.html"&gt;Akka Persistence&lt;/a&gt; and &lt;a href="https://eventstore.com/docs/event-sourcing-basics/index.html"&gt;EventStore&lt;/a&gt;. Event sourcing is a rich pattern, and as you might see, each article might focus on a different use-case.&lt;/p&gt;

&lt;p&gt;In this article, we'll first briefly introduce Event Sourcing, and then take a look at three possible use-cases, which might prompt adopting Event Sourcing in your system.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Event Sourcing?
&lt;/h1&gt;

&lt;p&gt;An event is a &lt;strong&gt;fact&lt;/strong&gt;, which describes a state change that &lt;strong&gt;occurred&lt;/strong&gt; to some entity. Notice the past tense! An event is something that already happened. As such, it cannot be modified — events, just like facts, are &lt;strong&gt;immutable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In a system which is based on event sourcing, the &lt;strong&gt;primary source of truth&lt;/strong&gt; is the stream of events. All state is derived from this stream. This includes the "current" state of entities, which is often the basis on which the system's business logic operates.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A good introduction connecting the concepts of event sourcing, stream processing, CEP and reactive can be found in &lt;a href="https://martin.kleppmann.com/2015/01/29/stream-processing-event-sourcing-reactive-cep.html"&gt;Martin Kleppmann's article&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For any entity, its current state can be derived by &lt;strong&gt;folding&lt;/strong&gt; — or in other words, applying — all events relating to this entity, starting with some initial "empty" state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ygKGpyUh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f0jjj8ho6r11avaqyvef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ygKGpyUh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f0jjj8ho6r11avaqyvef.png"&gt;&lt;/a&gt;&lt;br&gt;A rare &lt;strong&gt;event&lt;/strong&gt;: &lt;a href="https://github.com/softwaremill/tapir"&gt;tapirs&lt;/a&gt; jumping over a &lt;strong&gt;stream&lt;/strong&gt;, by Zofia Warska  (illustrations are very loosely related to the article)
  &lt;/p&gt;

&lt;p&gt;Implementing event sourcing might make sense globally in a system, but quite probably you'll want to use it &lt;strong&gt;selectively&lt;/strong&gt;. Event sourcing can peacefully co-exists with other methods of handling state in a system; it's not a binary, all-or-nothing choice.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Performance
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ssEe7TME--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsn1569o4iugelqtfme2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ssEe7TME--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsn1569o4iugelqtfme2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Performance might be the most-cited and well-publicised use-case for Event Sourcing. While it is true that this pattern might help in designing a high-performance system, nothing comes for free. There are still challenges that lie ahead, and tradeoffs to be made!&lt;/p&gt;

&lt;p&gt;This might be exemplified by the fact that there are "event-sourcing rescue projects" as well:&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IPm7OXaW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/EO-n9g9X0AEEfV-.png" alt="unknown tweet media content"&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ynvzE41D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1246801773/Headshot3_normal.png" alt="Jimmy Bogard 🍻 profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Jimmy Bogard 🍻
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="comment-mentioned-user" href="https://dev.to/jbogard"&gt;@jbogard&lt;/a&gt;

      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      every Event Sourcing rescue project i've been on was also promised these things and found them not to be true (for their scenario) 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      16:12 PM - 23 Jan 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1220378776753885185" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1220378776753885185" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1220378776753885185" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Remember though, that "rescue projects" usually have a couple of problems, and give a skewed picture of a technology. Reality is not &lt;strong&gt;that harsh&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;In a system under heavy load, event sourcing can be useful thanks to two of its characteristics: separating read and write models, and natural sharding. Let's look at both of these.&lt;/p&gt;

&lt;h2&gt;
  
  
  1.1. Separating read and write models
&lt;/h2&gt;

&lt;p&gt;Not only each system is different, but individual functionalities/endpoints in a system might see radically different usage characteristics. In a system which receives a lot of traffic, you might see a lot of writes, as compared to reads. Or, only relatively few writes, but a lot of reads; or, you might see one component of the system to be used much more often than others.&lt;/p&gt;

&lt;p&gt;To properly deal with performance requirements, while maintaining sane operational costs, we might need to scale the components of the system &lt;strong&gt;independently&lt;/strong&gt;. Again, depending on the traffic pattern, we might want to scale only the write-part. Or, we might want to scale only reads. Finally, we might want to scale only a small fraction of the overall read functionality that the system enables.&lt;/p&gt;

&lt;p&gt;We might also want to scale both reads &amp;amp; writes. The good thing is that with event sourcing, we can again do so independently, using different approaches. It's this &lt;strong&gt;freedom&lt;/strong&gt; when it comes to deciding what to scale and how, which makes event sourcing so useful to implement performance-related requirements.&lt;/p&gt;

&lt;p&gt;How might this look in practice? As our primary source of truth is the stream of events, a write operation can be made as simple as &lt;strong&gt;appending an event&lt;/strong&gt; to a log-like database. This might be Kafka, EventStore, Cassandra, or even SQL with a good archiving and sharding strategy: each technology has its pros and cons. An append is typically a very fast operation, comparing to e.g. typical usage of a relational database, which has to deal with locks, transactions, read and write clients etc. Hence, the system might have good overall performance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For a more in-depth view on why writes in a database often used for event sourcing — Apache Cassandra — are so fast, take a look at Andrzej Ludwikowski's article "&lt;a href="https://blog.softwaremill.com/cassandra-writes-in-depth-6ea8d7581eb"&gt;Cassandra writes in depth&lt;/a&gt;".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To implement and scale reads, we can create various &lt;strong&gt;views&lt;/strong&gt; of the event stream; this is also called &lt;strong&gt;read models&lt;/strong&gt; or &lt;strong&gt;projections&lt;/strong&gt;. Some views might store data in a relational database, so that it can be accessed using SQL. Other views might analyse the data and feed it to Spark, Hadoop, Kafka or any other data analytics framework. Finally, read models which will be under heavy load might be created in multiple copies (to balance traffic), using either in-memory or NoSQL storage.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Some tips on implementing read models when using Akka Persistence can be found in &lt;a href="https://blog.softwaremill.com/scalable-read-model-updates-in-akka-persistence-5042cdd7dce4"&gt;another article by Andrzej&lt;/a&gt;. Also, check out our &lt;a href="https://softwaremill.com/reactive-event-sourcing-akka-online-training/"&gt;reactive event sourcing training&lt;/a&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One formalisation of the above architecture is &lt;strong&gt;CQRS&lt;/strong&gt; (&lt;a href="https://microservices.io/patterns/data/cqrs.html"&gt;Command Query Responsibility Segregation&lt;/a&gt;; see also the much more comprehensive &lt;a href="https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf"&gt;e-book by Greg Young&lt;/a&gt;). This pattern is often used in combination with event sourcing, to implement high-performance systems. The &lt;a href="https://www.reactivemanifesto.org"&gt;reactive movement&lt;/a&gt; is also closely related, as event sourcing might directly implement the &lt;strong&gt;message-passing&lt;/strong&gt; paradigm, and is one way of building &lt;strong&gt;responsive&lt;/strong&gt;, &lt;strong&gt;resilient&lt;/strong&gt; and &lt;strong&gt;elastic&lt;/strong&gt; systems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9-FQdWkt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ys2r6842bw372hix69v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9-FQdWkt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ys2r6842bw372hix69v.png"&gt;&lt;/a&gt;&lt;br&gt;A surprising &lt;strong&gt;event&lt;/strong&gt;, by Zofia Warska
  &lt;/p&gt;

&lt;p&gt;Where's the catch, then? Well, there's a couple of catches, in fact. First of all, in a distributed setting, appending data to a log isn't that easy. First, you need to make your log distributed. Again, &lt;a href="https://kafka.apache.org"&gt;Kafka&lt;/a&gt;/&lt;a href="http://cassandra.apache.org"&gt;Cassandra&lt;/a&gt;/&lt;a href="https://eventstore.com"&gt;EventStore&lt;/a&gt; make this possible, however, whenever you start dealing with distributed data, you‘re introducing new operational and implementation complexity.&lt;/p&gt;

&lt;p&gt;Second, you might encounter &lt;strong&gt;eventual consistency&lt;/strong&gt;. Data that you write doesn't have to be immediately available when read, as it first needs to be written to the read models. A write is considered successful when it's appended to the log, not when all read models get updated. This flexibility in implementing the data views also brings its challenges, ranging from user experience, through request deduplication, to ensuring data consistency on the business logic level.&lt;/p&gt;

&lt;h2&gt;
  
  
  1.2. Natural sharding of data by grouping events by entities
&lt;/h2&gt;

&lt;p&gt;A related technique, which can be used in systems with high data volume or a large number of entities, for which state has to be stored, is a combination of event sourcing and the &lt;strong&gt;actor model&lt;/strong&gt;. This approach is the basis e.g. of &lt;a href="https://doc.akka.io/docs/akka/current/typed/persistence.html"&gt;Akka persistence&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Each actor in such a system stores data for a single entity. The data is stored in-memory. Any updates to the actor's state arrive as events. These events are persisted in a database (which might also be distributed, e.g. Cassandra), and then the actor updates its internal state based on the data in the event.&lt;/p&gt;

&lt;p&gt;Hence, the actor's state can be &lt;strong&gt;entirely reconstructed&lt;/strong&gt; from the events relating to that single entity. The longer the event history, the more costly this might be, that's why it's usually desired to also store actor-state snapshots for fast recovery and migration of actor/entity state.&lt;/p&gt;

&lt;p&gt;What makes this architecture fast? First of all, all reads are done from memory (assuming the actor for a particular entity is materialised). Second, all writes are simple append operations. Thirdly, it's trivial to &lt;strong&gt;shard the data&lt;/strong&gt; in the system, taking the entity id as the shard key.&lt;/p&gt;

&lt;p&gt;That is, the only data routing requirement is that all events for a single entity should be directed to a single node in the cluster. We thus need a &lt;strong&gt;coordinator&lt;/strong&gt; which knows which actors/entities are assigned to which nodes, and that's it! These coordinators can be clustered as well, to remove a single point of failure. That way, we can implement a data storage and processing system which scales horizontally — just by adding more computing power. &lt;a href="https://blog.softwaremill.com/when-do-you-need-akka-cluster-5885d43e901b"&gt;You don't always need such as setup&lt;/a&gt;, but when you do, event sourcing might be a good choice!&lt;/p&gt;

&lt;h2&gt;
  
  
  1.3. Turning the database inside-out
&lt;/h2&gt;

&lt;p&gt;The implications of an event-first approach when designing data storage system has been studied in depth by Martin Kleppmann. A good reference in that area is his book, "&lt;a href="https://dataintensive.net"&gt;Designing data intensive applications&lt;/a&gt;".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qk2w0OIr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yftsojbafsg0kqxm81bw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qk2w0OIr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yftsojbafsg0kqxm81bw.png"&gt;&lt;/a&gt;&lt;br&gt;A recommended read! &lt;a href="https://dataintensive.net"&gt;https://dataintensive.net&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;In a traditional database, internally the transactional (e.g. write-ahead) logs are already based on events. However, what a relational database gives us, is a projection of the events so that it's possible to conveniently work with the "current" state of the entities using SQL.&lt;/p&gt;

&lt;p&gt;Martin's core idea of "turning the database &lt;strong&gt;inside-out&lt;/strong&gt;" is to work with this log of events directly; this way we can scale writes to the log, and create projections as necessary. While this approach is more scalable and more performant, it also removes all of the goodness that relational databases give us: SQL and ACID transactions. Also, it's not that new, as Martin himself notes:&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ax_Z9evJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1328001242963058689/Ei18OQpr_normal.jpg" alt="Martin Kleppmann profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Martin Kleppmann
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @martinkl
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Such a powerful idea; keeps getting reinvented under different names (event sourcing; lambda/kappa architecture; database inside-out/unbundled; state machine replication; etc). &lt;a href="https://t.co/EoD9F1PsnZ"&gt;twitter.com/neil_conway/st…&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      07:33 AM - 11 May 2018
    &lt;/div&gt;

      &lt;div class="ltag__twitter-tweet__quote"&gt;
        &lt;div class="ltag__twitter-tweet__quote__header"&gt;
          &lt;span class="ltag__twitter-tweet__quote__header__name"&gt;
            Neil Conway
          &lt;/span&gt;
          @neil_conway
        &lt;/div&gt;
        Reflecting on the fact that I've built some flavor of the "immutable, append-only log + materialized views" pattern into every non-trivial software project I've built since 2006.
      &lt;/div&gt;

    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=994842956443111424" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=994842956443111424" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=994842956443111424" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;This "inside-out" approach might also be a good candidate for an &lt;strong&gt;intra-microservice, asynchronous communication pattern&lt;/strong&gt;. By making the events (and their schema) public, each microservice can arbitrarily use the data emitted by others.&lt;/p&gt;

&lt;p&gt;We get very loose coupling, without the need for an upfront design of e.g. an HTTP API, with pre-determined data projections that are made available. Opinions differ, however. As &lt;a href="https://dev.to/olibutzki/why-event-sourcing-is-a-microservice-anti-pattern-3mcj"&gt;Oliver Libutzki notes in his article&lt;/a&gt;, while Domain Events (more on this later) can be used for communication between services/bounded contexts, event sourcing should be kept as a service-local implementation detail.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Data modelling
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bk4FfyfU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kv7j5tcuaxo9d4tlo6l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bk4FfyfU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kv7j5tcuaxo9d4tlo6l.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When looking from a data modelling perspective, event sourcing shows other benefits. Designing a system where the stream of events is the central source of truth forces you to &lt;strong&gt;think differently&lt;/strong&gt; about the flow of the data through the application.&lt;/p&gt;

&lt;p&gt;In CRUD applications based on relational databases, various forms of "events" are often added as an after-thought. As we implement our applications, we discover that otherwise separate components must be notified of a change that took place somewhere else in the system. Or, we need to update an external system to keep it in sync with our data, but for performance reasons we do it in the background. If you've worked on business applications before, the above probably sounds familiar!&lt;/p&gt;

&lt;p&gt;Event sourcing reverses the relationship between data and events. Events no longer are secondary, derived from the changing reference data. It's the events that &lt;strong&gt;drive all of the business logic&lt;/strong&gt;, and it's the read models that are derived from the event stream. Greg Young explains it in a somewhat simplified form:&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--5y0wzq8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1293293549702782979/mblOE8kH_normal.jpg" alt="Greg Young profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Greg Young
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="comment-mentioned-user" href="https://dev.to/gregyoung"&gt;@gregyoung&lt;/a&gt;

      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      want to learn event sourcing? &lt;br&gt;&lt;br&gt;f(state, event) =&amp;gt; state
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      18:37 PM - 17 Mar 2013
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=313358540821647360" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=313358540821647360" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=313358540821647360" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;The consequences of this change are much more far-reaching than only data modelling. The &lt;strong&gt;whole structure&lt;/strong&gt; of an application written using event sourcing might be different, ranging from code organisation, through defining boundaries of modules, ending in extracting whole microservices, which might process a data stream independently.&lt;/p&gt;

&lt;p&gt;Think of a simple shopping system, where you can buy socks. In a traditional system, you would have a &lt;code&gt;/buy/socks&lt;/code&gt; API endpoint. Upon invocation, this would update the &lt;code&gt;SOCKS&lt;/code&gt; inventory table, perform an insert to the order table, send an email and perform another API call to the fulfillment service. However, each modification of the process, however trivial, involves changing this core logic.&lt;/p&gt;

&lt;p&gt;With event sourcing, we start thinking a bit differently. We no longer have an incoming request that arrives at our system, and database tables to be updated. Instead, we are dealing with a &lt;code&gt;UserBoughtSocks&lt;/code&gt; event (or with a command, that creates the event).&lt;/p&gt;

&lt;p&gt;It's something that &lt;strong&gt;already happened&lt;/strong&gt; (the user clicked the big green "Buy" button), and now we must deal with it. We might have synchronous event listeners which verify, that we actually have the socks in stock. We might have asynchronous event listeners, which send emails, create other events for the fulfillment service, or aggregate metrics.&lt;/p&gt;

&lt;p&gt;If we start thinking in terms of immutable events, that already happened, instead of thinking in terms of requests and mutable database tables, we'll soon discover that our code takes a much different shape. We'll see that individual functionalities become more &lt;strong&gt;loosely coupled&lt;/strong&gt;, as they are driven by incoming events, not by a central request controller. We might also see &lt;strong&gt;workflows&lt;/strong&gt; that start emerging, probably somehow mirroring the business process that is happening behind the scenes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KTeqxdfM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fmdydocd5d5hlusdc2ix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KTeqxdfM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fmdydocd5d5hlusdc2ix.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;strong&gt;Stream&lt;/strong&gt;, by Hanna Fałkowska
  &lt;/p&gt;

&lt;p&gt;Event sourcing gives us a new degree of flexibility, thanks to the &lt;strong&gt;separation of the action from effect&lt;/strong&gt; (see &lt;a href="https://medium.com/@hydraconference/the-big-interview-with-martin-kleppmann-figuring-out-the-future-of-distributed-data-systems-28a680d99ae6"&gt;this interview&lt;/a&gt; with Martin Kelppmann). We have flexibility in reacting to events happening in other parts of the system; we also have the flexibility of creating multiple read models.&lt;/p&gt;

&lt;p&gt;We are no longer constrained by a one-size-fits-all data model. We can create many redundant read models, duplicating data as needed (the event stream is always the primary source of truth anyway), aggregating and indexing data as required by a particular functionality. Here, event sourcing is truly liberating.&lt;/p&gt;

&lt;p&gt;Moreover, existing read models can be recreated and new read models can be created &lt;strong&gt;retrospectively&lt;/strong&gt;, taking into account all the data that is available in the event stream — taking advantage of full information. However, make sure to test such scenarios as well!&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--nYncdQbD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/566316156076568576/rSFBISh6_normal.jpeg" alt="Udi Dahan profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Udi Dahan
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @udidahan
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      This has been one of my main complaints around the "just replay the event stream" solution presented to many things in the event-sourcing community. &lt;a href="https://t.co/L5xuDdsMlb"&gt;twitter.com/tjaskula/statu…&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      09:11 AM - 21 Aug 2019
    &lt;/div&gt;

      &lt;div class="ltag__twitter-tweet__quote"&gt;
        &lt;div class="ltag__twitter-tweet__quote__header"&gt;
          &lt;span class="ltag__twitter-tweet__quote__header__name"&gt;
            Tomasz Jaskuλa
          &lt;/span&gt;
          &lt;a class="comment-mentioned-user" href="https://dev.to/tjaskula"&gt;@tjaskula&lt;/a&gt;

        &lt;/div&gt;
        The hard part is to figure out what actions that user took on those false event streams are actually relevant and how to keep them in rewriting process.
      &lt;/div&gt;

    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1164102728618074113" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1164102728618074113" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1164102728618074113" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;No discussion of data modelling can be complete without a mention of &lt;a href="https://martinfowler.com/tags/domain%20driven%20design.html"&gt;DDD&lt;/a&gt; (Domain Driven Design). And indeed, event sourcing fits like a glove. The central concepts of DDD is that of an &lt;strong&gt;aggregate&lt;/strong&gt;: defined sets of data, which capture an important business concept.&lt;/p&gt;

&lt;p&gt;When modelling a system, one natural way is to define the aggregates together with the &lt;strong&gt;aggregate events&lt;/strong&gt;. Such an event captures a single step of a business process, or one transition in a workflow, or part of the aggregate's lifecycle.&lt;/p&gt;

&lt;p&gt;Defining the (many) aggregates is a discovery process, necessarily involving the business! This is done together with sketching interactions that occur between them through events; following this methodology, we might soon discover the &lt;strong&gt;bounded contexts&lt;/strong&gt; of our system. &lt;a href="https://www.eventstorming.com"&gt;Event Storming&lt;/a&gt; is a related technique (not only through its name!): both a workshop format and design approach for modelling complex business domains.&lt;/p&gt;

&lt;p&gt;Where's the catch? When modelling data, designing a system and most importantly evolving a system, it's important to retain a &lt;strong&gt;clear view&lt;/strong&gt; of the interactions between various components. The liberty of reacting to events might need to be constrained.&lt;/p&gt;

&lt;p&gt;With event sourcing we get looser coupling of components, but that might also end up as a tangled mess of hard-to-follow relationships. The business logic might get decentralised. Keep in mind, that while sending an email is a concern that is probably completely separate from updating the inventory service, quite often business logic is a &lt;strong&gt;series of steps&lt;/strong&gt;, that need to be done in sequence: that's just the nature of the world. Don't try to hide the fact by artificially creating multiple events.&lt;/p&gt;

&lt;p&gt;You might also look at other patterns, that try to address the above mentioned issue and that are being used in DDD. One is the &lt;a href="https://microservices.io/patterns/data/saga.html"&gt;Saga pattern&lt;/a&gt;, both in the choreography and orchestration variants. Another is &lt;a href="https://www.infoq.com/articles/ddd-contextmapping/"&gt;context mapping&lt;/a&gt;, which helps to identify relationships between bounded contexts.&lt;/p&gt;

&lt;p&gt;The interactions between aggregates and events, where events are produced and where they are consumed can't always be expressed only in code. Other means of conveying information might be needed here: diagrams, drawings, conventions. Self-documenting code is good, but documentation is sometimes still needed.&lt;/p&gt;

&lt;p&gt;Putting both the specific DDD techniques, and the potential modelling problems aside, I think the "Data Modelling" section is best &lt;a href="https://blog.jessitron.com/2020/01/24/capturing-the-world-in-software/"&gt;summarised by Jessica Kerr&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Event Sourcing gives you a complete, consistent model of the slice of the world modeled by your software. That's pretty attractive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  3. Auditing
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--893PwOGS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/28q1p7mthffaunidcx8b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--893PwOGS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/28q1p7mthffaunidcx8b.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Data auditing is the process of storing historical data, or capturing the changes performed to a dataset, along with metadata such as timestamps or user identifiers. Thanks to a data audit we can find out who made a particular change, when, and in some cases where or how.&lt;/p&gt;

&lt;p&gt;The need for a data audit may come from a couple of sources. First, this might a &lt;strong&gt;regulatory requirement&lt;/strong&gt;. If we are dealing with, for example, a financial application, we might be required to store all historical data for a certain period of time.&lt;/p&gt;

&lt;p&gt;Audits might also be a security-related &lt;strong&gt;feature available for users&lt;/strong&gt;. Every time you can browse through your recent actions, such as logins, profile changes, settings updates, you are in fact browsing an audit of your actions.&lt;/p&gt;

&lt;p&gt;Finally, audit data might prove to be very valuable for &lt;strong&gt;analytics&lt;/strong&gt;. It can help in understanding how a system is being used, what are the most common behaviours, taking into account both the timeline and quantity of actions.&lt;/p&gt;

&lt;p&gt;There's a couple of approaches to implementing a data audit, and event sourcing provides one elegant way. Looking at the event stream from another angle, it's in fact the &lt;strong&gt;audit trail&lt;/strong&gt; of our application. The audit is not an after-thought that's added to the system in the last few sprints; &lt;strong&gt;the audit drives the application&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Beyond all of that for me, the focus tends to be on the current state based model when the system is really &lt;strong&gt;event&lt;/strong&gt; centric. This may sound like a nitpicky issue but I find teams doing this look at events with less importance than those who use events as storage as well as the latter &lt;strong&gt;only&lt;/strong&gt; use events they are extremely event centric.&lt;br&gt;
Greg Young, "&lt;a href="http://codebetter.com/gregyoung/2010/02/20/why-use-event-sourcing/"&gt;Why use Event Sourcing?&lt;/a&gt;"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We've seen above that event sourcing can change the way we think about data modelling, as well as our approach to system design, going as low level as impacting code organisation. The same is true for data audits; the roles get &lt;strong&gt;reversed&lt;/strong&gt; comparing to other solutions. It's the audit trail from which all other data are derived.&lt;/p&gt;

&lt;p&gt;One immediate gain from such a situation is that it's impossible to forget to audit a specific operation, as no operation can happen in an event-sourced system without an event being written to the event log. That way, we make sure that &lt;strong&gt;no information is being lost&lt;/strong&gt;. That's quite a good trait, given that we all work in Information Technology (IT)!&lt;/p&gt;

&lt;p&gt;It's worth keeping in mind that the event stream itself stores only "raw data". Making this data useful will most probably involve some kind of transformation. If it's a requirement to present a user's security audit trail in an application, we should probably create a projection (a read model) which will store the appropriate data, and index them in a form that's useful for the audit view. Same for security or analytical audits.&lt;/p&gt;

&lt;p&gt;Another benefit of a fully-audited/event-sourced system surface when we are faced with the need to &lt;strong&gt;debug a problem&lt;/strong&gt;. Not only we have additional information on exactly what changed and when, we can also re-create the system state at any point in time, by replaying events up to the problematic one. This might prove valuable when trying to reproduce an issue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mHcWSvNG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hn9kacszdd4qgxwc75bo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mHcWSvNG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hn9kacszdd4qgxwc75bo.png"&gt;&lt;/a&gt;&lt;br&gt;A &lt;strong&gt;stream&lt;/strong&gt; flowing through a valley full of sunshine, by Zofia Warska
  &lt;/p&gt;

&lt;p&gt;What kind of problems we might expect when using event sourcing for data auditing? First of all, we'll never be able to &lt;strong&gt;track everything&lt;/strong&gt;. There's always decisions to be made, as to what should be captured as an event. Any changes to the data, that have been performed by the user result in an obvious event.&lt;/p&gt;

&lt;p&gt;How about page views? That's probably too fine-grained. We would quickly run into problems with our data storage running out of space. An audit trail shouldn't be used to perform website traffic analysis. However, we might want to capture the fact that a user has viewed some sensitive data. The answers here are very application-specific.&lt;/p&gt;

&lt;p&gt;Another group of problems relates to &lt;strong&gt;deleting data&lt;/strong&gt;. Either because we want to be nice to our users, or because we want to comply with privacy regulation in the EU and US, we might need to implement a feature of removing all data for a particular user. This is in obvious contradiction with the immutability of the event stream. In addition, some systems of storing a distributed log make it hard or impossible to modify data that is already written.&lt;/p&gt;

&lt;p&gt;There are several solutions: using log compaction, periodically rewriting the event stream, or using encryption keys which are "forgotten" when a user requires their data to be deleted. Again, there are no universal solutions, and each use-case might require slightly different approach.&lt;/p&gt;

&lt;p&gt;Finally, in the introduction we said that we can apply event-sourcing selectively, only where this is truly needed. When implementing an audit trail using events, this stops being true; event sourcing is becoming much more "&lt;strong&gt;viral&lt;/strong&gt;" as all places that require capturing the audit need to use event sourcing.&lt;/p&gt;

&lt;p&gt;If you're interested in other approaches to data auditing, check out our &lt;a href="https://softwaremill.com/ebooks/audit-whitepaper/"&gt;whitepaper on the subject&lt;/a&gt;!&lt;/p&gt;

&lt;h1&gt;
  
  
  Where to store the data
&lt;/h1&gt;

&lt;p&gt;Event sourcing is often discussed in combination with NoSQL databases and messaging systems, such as EventStore, Cassandra and Kafka. But does event sourcing mandate the use of these storage systems? Is it necessary to introduce the high operational cost of a distributed or "NoSQL" database, just to use event sourcing? No!&lt;/p&gt;

&lt;p&gt;Event sourcing can as well be implemented on top of a traditional, &lt;strong&gt;relational database&lt;/strong&gt;. It's just as good for &lt;strong&gt;low-volume&lt;/strong&gt;, &lt;strong&gt;internal applications&lt;/strong&gt;, as well as for &lt;strong&gt;high-performance&lt;/strong&gt;, &lt;strong&gt;mission-critical&lt;/strong&gt; systems (however, the reasons for introducing event sourcing would be radically different).&lt;/p&gt;

&lt;p&gt;The datastore options range from using relational databases both for events and the read model (and leveraging transactions in the process! &lt;a href="https://softwaremill.com/entry-level-event-sourcing/"&gt;See here for an example implementation&lt;/a&gt; using Scala), all the way to fully distributed databases and separate read&amp;amp;write models.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;Above we've presented three common scenarios, where using event sourcing might be beneficial. Nothing comes for free! As with any other technology, it's easy to &lt;a href="http://natpryce.com/articles/000819.html"&gt;make mistakes&lt;/a&gt; when implementing event sourcing.&lt;/p&gt;

&lt;p&gt;Hence whether you are looking at event sourcing from the perspective of &lt;strong&gt;performance&lt;/strong&gt;, &lt;strong&gt;data modelling&lt;/strong&gt; or &lt;strong&gt;data auditing&lt;/strong&gt;, keep in mind the tradeoffs that will need to be made.&lt;/p&gt;

&lt;p&gt;However, a lot of factors speak in favour of the pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  the ability to scale reads and writes independently&lt;/li&gt;
&lt;li&gt;  natural sharding of data&lt;/li&gt;
&lt;li&gt;  the liberty of creating arbitrary, tailored read models&lt;/li&gt;
&lt;li&gt;  data-centric approach do system modelling&lt;/li&gt;
&lt;li&gt;  loose coupling of business logic&lt;/li&gt;
&lt;li&gt;  audit-driven applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, event sourcing might be your gateway to a flexible, no-information-lost, unconstrained, but audited future!&lt;/p&gt;

</description>
      <category>eventsourcing</category>
      <category>ddd</category>
      <category>audit</category>
      <category>kafka</category>
    </item>
    <item>
      <title>Shelly: under the hood</title>
      <dc:creator>Adam Warski</dc:creator>
      <pubDate>Thu, 25 Mar 2021 19:36:50 +0000</pubDate>
      <link>https://dev.to/softwaremill/shelly-under-the-hood-15nf</link>
      <guid>https://dev.to/softwaremill/shelly-under-the-hood-15nf</guid>
      <description>&lt;p&gt;&lt;a href="https://shelly.dev" rel="noopener noreferrer"&gt;Shelly&lt;/a&gt; — a programming language for drawing — is one of our side-projects that we work on in-between &lt;a href="https://softwaremill.com" rel="noopener noreferrer"&gt;other engagements&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It features the &lt;strong&gt;challenge&lt;/strong&gt; mode, where through a series of step-by-step tutorials you can learn both the Shelly language, as well as the basics of programming. There's also the &lt;strong&gt;creative&lt;/strong&gt; mode, where you can draw whatever you like, and share it with others as an image, code (to allow modifications), or as a custom challenge — can others reproduce your painting?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6p9ctganwffui48o1kul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6p9ctganwffui48o1kul.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;a href="https://shelly.dev/p/adamw/47fc197c3154" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://shelly.dev/p/adamw/47fc197c3154" rel="noopener noreferrer"&gt;https://shelly.dev/p/adamw/47fc197c3154&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;Shelly delivers the well-known concept of turtle graphics in a modern package, with a friendly interface, instant drawing, rich sharing options, and gamification. You write the program, and Shelly the turtle immediately reflects the new code on the canvas — live programming!&lt;/p&gt;

&lt;p&gt;The Shelly language is a mix between &lt;a href="https://en.wikipedia.org/wiki/Logo_(programming_language)" rel="noopener noreferrer"&gt;Logo&lt;/a&gt; and more modern programming languages. Due to its educational character, it's kept simple: we've got expressions, named functions, loops, conditionals, recursion, and that's about it! Still, even using these basic constructs, you can create some really interesting images.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffes346rf9gfddutaekju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffes346rf9gfddutaekju.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;a href="https://shelly.dev/p/adamw/27e55b6e028d" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://shelly.dev/p/adamw/27e55b6e028d" rel="noopener noreferrer"&gt;https://shelly.dev/p/adamw/27e55b6e028d&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;You might be wondering: what's under the hood? What kind of technologies can one use to build such a live-coding environment?&lt;/p&gt;

&lt;p&gt;Shelly itself is built with &lt;a href="https://www.typescriptlang.org" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;. The types bring some sanity to the otherwise untyped JavaScript/browser domain, integrating nicely with the whole rest of the ecosystem.&lt;/p&gt;

&lt;p&gt;For the skeleton of the application, we've made a popular choice, that is &lt;a href="https://reactjs.org" rel="noopener noreferrer"&gt;React&lt;/a&gt;. Nothing non-standard, though as the application has grown, we've seen that our reliance on &lt;a href="https://reactjs.org/docs/context.html" rel="noopener noreferrer"&gt;Context API&lt;/a&gt; to manage state has reached its limits. That's why we're considering porting that aspect to &lt;a href="https://redux.js.org" rel="noopener noreferrer"&gt;Redux&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqzrtnmql5bqg0qnlhnn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqzrtnmql5bqg0qnlhnn.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;a href="https://shelly.dev/p/adamw/608a6168c983" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://shelly.dev/p/adamw/608a6168c983" rel="noopener noreferrer"&gt;https://shelly.dev/p/adamw/608a6168c983&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;Second, we've got the editor. Here, we are using the &lt;a href="https://microsoft.github.io/monaco-editor/" rel="noopener noreferrer"&gt;Monaco Editor&lt;/a&gt;, which is the editor that's also used in &lt;a href="https://code.visualstudio.com" rel="noopener noreferrer"&gt;VisualStudio Code&lt;/a&gt;. To configure the editor for a custom language, you have to provide the keywords, symbols, operators and configure the tokenizer. We also get auto-complete out-of-the-box — you just need to provide the completion function, which can be context-sensitive or not.&lt;/p&gt;

&lt;p&gt;Monaco also gives us the possibility to manage errors (underlying them and showing glyphs) and provides contextual editor extensions. In Shelly, this is used to show a palette of available colors and pen patterns, whenever the user writes &lt;code&gt;pen&lt;/code&gt; or &lt;code&gt;fill&lt;/code&gt;. Try it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdtczqss3ublz2mmxz8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdtczqss3ublz2mmxz8m.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;a href="https://shelly.dev/p/adamw/992d937596c3" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://shelly.dev/p/adamw/992d937596c3" rel="noopener noreferrer"&gt;https://shelly.dev/p/adamw/992d937596c3&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;Monaco has quite good documentation, though sometimes you'll end up digging through GitHub looking for usage examples to see how to best configure the parser, provide styling or manage the web workers.&lt;/p&gt;

&lt;p&gt;Let's move to the canvas. Here, the main job is done by &lt;a href="https://konvajs.org" rel="noopener noreferrer"&gt;Konva&lt;/a&gt;, which provides us with a simple and performant layer on top of the raw HTML &lt;code&gt;canvas&lt;/code&gt; element. Shelly uses a rather basic subset of Konva, as Shelly's drawings are composed mainly of lines, arches, basic figures, and SVG patterns (hearts, stars, cars, etc.). One aspect that was especially challenging, however, was properly handling the zoom &amp;amp; pan, using both on-screen controls and the mouse wheel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxb50rv5ktz8shju3912u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxb50rv5ktz8shju3912u.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;a href="https://shelly.dev/p/adamw/62d98bc06139" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://shelly.dev/p/adamw/62d98bc06139" rel="noopener noreferrer"&gt;https://shelly.dev/p/adamw/62d98bc06139&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;What about the drawing/programming language itself? Even though it's quite simple, we still need a tokenizer and an interpreter. We've chosen &lt;a href="https://www.antlr.org" rel="noopener noreferrer"&gt;ANTLR&lt;/a&gt; to define the grammar, with &lt;a href="https://github.com/tunnelvisionlabs/antlr4ts" rel="noopener noreferrer"&gt;antlr4ts&lt;/a&gt; as the target. That is, when running the ANTLR tool, the input is a file containing the grammar definition, and as the output, we get TypeScript files that handle the parsing of arbitrary text into an AST (Abstract Syntax Tree).&lt;/p&gt;

&lt;p&gt;However, we are not using the ANTLR-defined AST directly when doing the interpretation (that is, actually &lt;strong&gt;running&lt;/strong&gt; the program), but we're translating it to yet another representation, which is more flexible in the result type — and we need that flexibility to implement arbitrary-depth recursion. Here, we've used &lt;a href="https://blog.logrocket.com/using-trampolines-to-manage-large-recursive-loops-in-javascript-d8c9db095ae3/" rel="noopener noreferrer"&gt;trampolining&lt;/a&gt;, thanks to which you can loop and loop without blowing the browser's JS stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth3zt0xl8khcxv0svj9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth3zt0xl8khcxv0svj9f.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;a href="https://shelly.dev/p/adamw/f08a8c07a102" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://shelly.dev/p/adamw/f08a8c07a102" rel="noopener noreferrer"&gt;https://shelly.dev/p/adamw/f08a8c07a102&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;The downside of using ANTLR with the TypeScript backend is that the resulting package is quite large — which means a large download, and a longer wait for the initial page load. That's why we might consider writing a parser by hand in the future, which won't have any third-party dependencies.&lt;/p&gt;

&lt;p&gt;Shelly's frontend is built using &lt;a href="https://webpack.js.org" rel="noopener noreferrer"&gt;webpack&lt;/a&gt;, tested with &lt;a href="https://jestjs.io" rel="noopener noreferrer"&gt;jest&lt;/a&gt; and &lt;a href="https://github.com/microsoft/playwright" rel="noopener noreferrer"&gt;playwright&lt;/a&gt;, and deployed using &lt;a href="https://www.netlify.com" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;. The whole process of connecting a GitHub repository, configuring CI, &lt;a href="https://www.netlify.com/blog/2016/07/20/introducing-deploy-previews-in-netlify/" rel="noopener noreferrer"&gt;pull request previews&lt;/a&gt;, custom domains, and, finally, the production build is really painless. And makes the development so much easier!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4m8ge45d2gs3x1e1ra6y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4m8ge45d2gs3x1e1ra6y.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;a href="https://shelly.dev/p/adamw/b896560155c3" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://shelly.dev/p/adamw/b896560155c3" rel="noopener noreferrer"&gt;https://shelly.dev/p/adamw/b896560155c3&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;Finally, on the backend, we've got a simple &lt;a href="https://www.scala-lang.org" rel="noopener noreferrer"&gt;Scala&lt;/a&gt;-based application, deployed on &lt;a href="https://heroku.com" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;. The database is &lt;a href="http://postgresql.org" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;, but the application is not a straightforward CRUD as you might expect, but instead uses &lt;a href="https://softwaremill.com/entry-level-event-sourcing/" rel="noopener noreferrer"&gt;SQL-based, transactional event sourcing&lt;/a&gt;. Probably overkill, but — if we ever want to create a new view basing on the events (which include e.g. program creation in creative mode, or solving a challenge) — for sure we'll have the data available!&lt;/p&gt;

&lt;p&gt;And that's it. &lt;a href="https://shelly.dev" rel="noopener noreferrer"&gt;Give Shelly a try&lt;/a&gt;, solve the challenges or create a drawing in creative mode. Then, let us know what you think, what you'd improve, change or add!&lt;/p&gt;

</description>
      <category>learntocode</category>
      <category>javascript</category>
      <category>turtlegraphics</category>
      <category>programming</category>
    </item>
    <item>
      <title>Never write a UserService again</title>
      <dc:creator>Adam Warski</dc:creator>
      <pubDate>Mon, 22 Mar 2021 15:40:36 +0000</pubDate>
      <link>https://dev.to/softwaremill/never-write-a-userservice-again-1hao</link>
      <guid>https://dev.to/softwaremill/never-write-a-userservice-again-1hao</guid>
      <description>&lt;p&gt;Recently at our semi-regular architecture discussion group, we've been looking at the &lt;a href="https://auth0.com"&gt;Auth0&lt;/a&gt; service: what it is, how it works and when it might be a good idea to use it.&lt;/p&gt;

&lt;p&gt;I'd like to focus on the last aspect, using Auth0 as a case-study for the more general problem of when to use &lt;strong&gt;external services&lt;/strong&gt; in our microservices mix, and when to roll your own.&lt;/p&gt;

&lt;p&gt;On one hand, it's totally reasonable not to write yet another &lt;code&gt;UserService&lt;/code&gt; which handles user authentication and authorization. It's been done before, and we all like to reuse code. On the other, using an external service requires us to let go of the otherwise total control we have over our system.&lt;/p&gt;

&lt;p&gt;It's a tradeoff. How to decide, when to use one option or the other?&lt;/p&gt;

&lt;h1&gt;
  
  
  Auth0
&lt;/h1&gt;

&lt;p&gt;Before diving into tradeoffs, let's make a very quick introduction to Auth0, which we'll use as our running example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://auth0.com"&gt;Auth0&lt;/a&gt; is a service which manages identities of the system's users, providing both authentication and authorization.&lt;/p&gt;

&lt;p&gt;Users can be &lt;a href="https://auth0.com/docs/login"&gt;authenticated&lt;/a&gt; in a variety of ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;using traditional username/password&lt;/li&gt;
&lt;li&gt;through various social identity providers (Google, Facebook, Twitter, … )&lt;/li&gt;
&lt;li&gt;passwordless, with login links sent by e-mail&lt;/li&gt;
&lt;li&gt;multi-factor (such as push, e-mail or voice notifications, one-time passwords)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Auth0 can manage the database of the users for you, or you can connect your own datastore. There's a number of integration options available, calling in either directly to the DB instance, or through an API. If the built-in options are not sufficient, you can always provide integration code yourself (in JavaScript).&lt;/p&gt;

&lt;p&gt;For authorization, Auth0 offers &lt;a href="https://auth0.com/docs/authorization/rbac"&gt;role-based access control&lt;/a&gt; (again, with roles &amp;amp; permissions stored in Auth0's database, or externally), as well as extension points to provide your own mechanisms (through &lt;a href="https://auth0.com/docs/rules"&gt;rules&lt;/a&gt;, &lt;a href="https://auth0.com/docs/hooks"&gt;hooks&lt;/a&gt; and &lt;a href="https://auth0.com/docs/extensions"&gt;extensions&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;You have the option to use Auth0-hosted login screens (a component that is very important for the end-user experience), which can be &lt;a href="https://auth0.com/docs/brand-and-customize"&gt;themed&lt;/a&gt; so that they match your site; or you can roll your own, and just call Auth0 APIs.&lt;/p&gt;

&lt;p&gt;Finally, Auth0 uses the &lt;a href="https://oauth.net/2/"&gt;OAuth2&lt;/a&gt; standard for authorization, and the identity layer conforms to &lt;a href="https://openid.net/connect/"&gt;OpenID Connect&lt;/a&gt; (see also &lt;a href="https://developer.okta.com/blog/2017/06/21/what-the-heck-is-oauth"&gt;this introduction&lt;/a&gt; to the standards).&lt;/p&gt;

&lt;p&gt;What does that mean? OAuth2 defines a number of &lt;a href="https://auth0.com/docs/authorization/which-oauth-2-0-flow-should-i-use"&gt;flows&lt;/a&gt;, which should be used depending on the type of the client (if the client's execution environment can be trusted or not), whether the client is an end-user or a machine, and what kind of session we want to establish (one-off, temporary or long-running).&lt;/p&gt;

&lt;p&gt;Auth0 endpoints behave as specified by OAuth2, hence we know what to expect when interacting with them. Which OAuth2 flow to use depends on the concrete use case, which can be such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  regular web app, with a server-side component&lt;/li&gt;
&lt;li&gt;  single-page-app, with client-side sessions only&lt;/li&gt;
&lt;li&gt;  mobile apps&lt;/li&gt;
&lt;li&gt;  machine-to-machine (service-to-service)&lt;/li&gt;
&lt;li&gt;  single-sign-on (SSO)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OAuth2 relies on signed tokens being passed between interested parties. The tokens that Auth0 creates are &lt;a href="https://jwt.io/"&gt;JWT&lt;/a&gt; tokens, hence in an almost-human readable JSON format. That's yet another standard, which you can encounter when implementing the security layer of your application.&lt;/p&gt;

&lt;p&gt;Finally, what are the alternatives to Auth0? It's not the only service implementing such functionality. Other options that you might want to check out if you are surveying the authentication landscape are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  as-a-service: &lt;a href="https://www.okta.com"&gt;Okta&lt;/a&gt;, &lt;a href="https://aws.amazon.com/cognito/"&gt;Amazon Cognito&lt;/a&gt;, &lt;a href="https://www.onelogin.com"&gt;onelogin&lt;/a&gt;, &lt;a href="https://www.pingidentity.com"&gt;PingIdentity&lt;/a&gt;, &lt;a href="https://fusionauth.io"&gt;FusionAuth&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  self-hosted: &lt;a href="https://www.keycloak.org"&gt;KeyCloak&lt;/a&gt;, &lt;a href="https://www.gluu.org"&gt;Gluu&lt;/a&gt;, &lt;a href="https://www.freeipa.org/page/Main_Page"&gt;FreeIPA&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  External microservices
&lt;/h1&gt;

&lt;p&gt;Modern systems are typically composed of multiple services of various sizes. Deployments vary, from Kubernetes on one end, through Heroku and bare metal on the other. However and wherever the services are deployed, they usually communicate using HTTP APIs, or at least offer the possibility to communicate with them this way.&lt;/p&gt;

&lt;p&gt;Hence, replacing one of the (micro)services with an external API shouldn't create huge changes in the system architecture. Still, there's a number of factors to consider when deciding "if" and choosing "which" service to bet on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replaceability
&lt;/h2&gt;

&lt;p&gt;The absolute first thing to consider is how easy it is to replace a potential external microservice. Nobody likes vendor lock-in: integrating too much with an external provider, we are then forced to use their services for better or worse, as the cost of switching is too high or would cause too much disruption.&lt;/p&gt;

&lt;p&gt;Hence, we need to check whether the APIs that the service exposes conform to open, or at least "emergent" standards — and if these open standards are really used throughout the industry. Does the competition support the same standards as well? That is, what would it take to switch to another vendor?&lt;/p&gt;

&lt;p&gt;How does Auth0 score in replaceability? On the plus sides, we've got the OAuth2 and OpenID Connect standards, which are not only a codified specification, but they are indeed used across the industry. Basing your authentication flows on OAuth2 will ensure that you will be able to switch both to other identity service vendors, or to roll your own: there's a lot of OAuth2-supporting open-source projects (and a couple of close-source ones probably as well).&lt;/p&gt;

&lt;p&gt;However, it's not all roses. Auth0 does extend or adjust the standard slightly. For example to implement role-based access control, the permissions calculated from user roles are returned in the &lt;code&gt;permissions&lt;/code&gt; claim of the access tokens, which are non-standard. While adding custom claims is something the standard does allow of course, in the event of migration, you'd need to replicate that functionality.&lt;/p&gt;

&lt;p&gt;Another point where you might encounter some vendor lock-in are the SDKs. Auth0 provides a &lt;a href="https://auth0.com/docs/libraries"&gt;rich set of libraries&lt;/a&gt; which allow interacting with the service from a number of programming languages, both to perform client or server-side authentication, parse access tokens and interact with the Auth0 management API. That's a very useful feature when developing applications: however, you should be aware that using them might tie you to the Auth0 service itself. If you were to create your own user service, you might have to amend the code to use a different or custom SDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;p&gt;Since we are delegating some part of the system's data and functionality to an external provider, security should be one of our main concerns. Looking through the company blog, documentation and regulatory compliance (&lt;a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation"&gt;GDPR&lt;/a&gt;/&lt;a href="https://en.wikipedia.org/wiki/California_Consumer_Privacy_Act"&gt;CCPA&lt;/a&gt;/&lt;a href="https://en.wikipedia.org/wiki/Online_Privacy_Protection_Act"&gt;CalOPPA&lt;/a&gt;/…) should provide some initial background into how seriously a given service takes security.&lt;/p&gt;

&lt;p&gt;Further, we might want to investigate previous incidents (if any). If there were security incidents, this doesn't yet eliminate the service — we should check how the incident was handled, if a post-mortem was published, how transparent the company was about things that went wrong, and what are the conclusions for the future.&lt;/p&gt;

&lt;p&gt;Even the presence of a simple status dashboard gives some insight into how the company communicates with their users.&lt;/p&gt;

&lt;p&gt;Auth0 is in a special position, as their service itself deals with security, so in this case, security of the service is double important. Take a look at their &lt;a href="https://auth0.com/security"&gt;compliance&lt;/a&gt; and &lt;a href="https://status.auth0.com"&gt;status&lt;/a&gt; pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Latency
&lt;/h2&gt;

&lt;p&gt;When services are deployed together, they usually enjoy the benefits of communicating within a local or almost-local network. This changes when you use an external service. If it's being used a lot, what is the additional price per request that you have to pay for using the service?&lt;/p&gt;

&lt;p&gt;And the price I'm talking about here is not measured in USD, but in milliseconds — every additional millisecond of latency might directly translate to user happiness (and we end up with USD again). Using an external service might mean an additional network hop or multiple hops — e.g. if the service looks up data in our database, at our datacenter, through an extension point.&lt;/p&gt;

&lt;p&gt;Hence, does the external service provider offer endpoints in various regions? Quite often we have US and EU-based servers, but what about other continents — what if we want to deploy the rest of our services in Australia, Asia, Africa or non-US America?&lt;/p&gt;

&lt;p&gt;You might also want to check if the external service is deployed on the infrastructure of a specific cloud provider. If it's e.g. AWS, you'll get great connectivity when hosting your services in the same AWS region, but probably worse when using a different region or GCP/Azure.&lt;/p&gt;

&lt;p&gt;In case of Auth0, all of their public infrastructure is &lt;a href="https://auth0.com/blog/auth0-architecture-running-in-multiple-cloud-providers-and-regions/"&gt;hosted on AWS&lt;/a&gt;. They offer four regions: US, US-2, EU and AU. It's also worth noting that you can choose a private cloud &lt;a href="https://auth0.com/docs/get-started/deployment-options"&gt;deployment option&lt;/a&gt; (which of course is more expensive).&lt;/p&gt;

&lt;h2&gt;
  
  
  Extensibility
&lt;/h2&gt;

&lt;p&gt;External microservices put a focus on making the most common use cases easy to configure and pleasant to use, so that they can attract the widest possible audience (it's a business which has to make a profit, after all).&lt;/p&gt;

&lt;p&gt;This might mean that, like many web frameworks in popular programming languages, bootstraping a project is rapid and leads to a very effective initial iteration. Even implementing 90% of the required functionality might be a breeze. However, the pain and hacking starts when we are left with the remaining non-standard 10%.&lt;/p&gt;

&lt;p&gt;That's where extensibility of the external service comes into play. What are the available extension points? Can you plug-in into each step in the lifecycle of a managed data entity or into each step of a request? What are the constraints on the integrations?&lt;/p&gt;

&lt;p&gt;Looking at Auth0, there are &lt;a href="https://auth0.com/docs/rules"&gt;rules&lt;/a&gt;, which run after a user is authenticated. There are also &lt;a href="https://auth0.com/docs/hooks"&gt;hooks&lt;/a&gt;, which run at pre-defined extension points; some of them run synchronously, some asynchronously. Finally, there are &lt;a href="https://auth0.com/docs/extensions"&gt;extensions&lt;/a&gt;, which allow to integrate with third-party applications such as logging services (which is an important aspect as well!).&lt;/p&gt;

&lt;p&gt;As already mentioned, the custom extension code is written using JavaScript, and can interact with any API, and use one of the &lt;a href="https://auth0-extensions.github.io/canirequire/"&gt;many available libraries&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We've successfuly started using Auth0 at &lt;a href="https://softwaremill.com"&gt;SoftwareMill&lt;/a&gt; and the available extension points have been sufficient so far. But more projects and more production experience is needed to verify if anything important is missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost
&lt;/h2&gt;

&lt;p&gt;In the end, it all boils down to costs. For systems with low or medium traffic, using an external service will almost always be way cheaper than the cost of developing a custom implementation.&lt;/p&gt;

&lt;p&gt;It's worth noting, however, that usage costs (which are typically sized proportionally to the number of users or API requests) are not the only cost associated with using an external service. There's still development costs, which include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  configuring the service&lt;/li&gt;
&lt;li&gt;  integrating the system's codebase with the service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on the quality of the documentation, the UX of the administration panel, and automation options (see also below), this might require smaller or larger amounts of training. Same with integration costs — a good SDK which matches the ecosystem (both language and libraries) that you are using to develop the rest of the system will save a lot of development time. However, as already mentioned, it might also tighten vendor lock-in.&lt;/p&gt;

&lt;p&gt;In case of Auth0, &lt;a href="https://auth0.com/pricing/"&gt;pricing&lt;/a&gt; is something you'll have to calculate for your use-case yourself, I'll refrain from giving any advice here. As for the development costs when using the service — OAuth2 and OpenID are both non-trivial standards to understand, and they take time to learn. However, this knowledge is largely vendor-independent. Getting to know Auth0 concepts still takes some time (the distinction between tenants, apps, etc. for example), but given solid background in open authentication standards, this shouldn't be too challenging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automation
&lt;/h2&gt;

&lt;p&gt;When initially setting up the service, we'll probably be happy with a nice-looking administration UI, clicking around exploring the various options and discovering the features.&lt;/p&gt;

&lt;p&gt;However later, as we dig deeper and start developing our system, integrating with the given external service more seriously, clicking in the UI will stop being fun and become frustrating instead. Moreover, if we are configuring multiple environments, doing this manually will not only be a waste of time, but also very error-prone.&lt;/p&gt;

&lt;p&gt;That's why it's crucial that a service exposes all of their features through an API. AWS got this right, and even went a step further: the UI sometimes gives only some of the functionality, that is available when using the API programmatically. And that's the right approach. Having a well-documented configuration API is a must. If there are ready-to-use SDKs ready in popular programming languages, even better.&lt;/p&gt;

&lt;p&gt;But that's only one aspect of automation. Another is infrastructure-as-code tools, such as &lt;a href="https://www.terraform.io"&gt;Terraform&lt;/a&gt;, &lt;a href="https://www.ansible.com"&gt;Ansible&lt;/a&gt; or &lt;a href="https://www.chef.io"&gt;Chef&lt;/a&gt;. Using these we can describe the target configuration of the external system, which is typically stored in one or multiple files. These files can then be part of our version control system, and the configuration can be partially dynamic, depending e.g. on the target environment. A separate tool-dependent process then applies the configuration to the external service, adjusting the "current" state with the "desired" state.&lt;/p&gt;

&lt;p&gt;Auth0 exposes a comprehensive &lt;a href="https://auth0.com/docs/api/management/v2"&gt;management API&lt;/a&gt;, so everything looks good on this front. It also allows connecting a &lt;a href="https://auth0.com/docs/extensions/github-deployments?_ga=2.142432370.1790535558.1599642533-38370158.1599061193"&gt;git repository&lt;/a&gt; storing configuration, which is automatically applied on push. The configuration files in the repository must follow a pre-defined structure. Finally, there's a &lt;a href="https://www.terraform.io/docs/providers/auth0/index.html"&gt;Terraform Auth0&lt;/a&gt; provider, which can be used to fully manage Auth0 configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Let's not forget about testing! Since we are externalising part of our system, we will no longer be able to run everything on our laptop. But that ship might have sailed long ago, if our system is truly composed of a non-trivial amount of microservices. We'll need service stubs for local development anyway.&lt;/p&gt;

&lt;p&gt;That said, we'll still need to configure the external system in a couple of copies, to setup production/staging/development environments. As mentioned above, automation is crucial here. The external service should make it easy enough to quickly and dynamically create a fresh copy.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summing up
&lt;/h1&gt;

&lt;p&gt;As we move towards fine-grained single-responsibility microservices, it's increasingly feasible to use an external service for the "standard" parts of each system.&lt;/p&gt;

&lt;p&gt;We're commonly doing this with logging, using services such as &lt;a href="https://www.loggly.com"&gt;Loggly&lt;/a&gt; or &lt;a href="http://datadoghq.com"&gt;DataDog&lt;/a&gt;. We're using managed databases, be it on AWS, Heroku or database-vendor-specific solutions. We're storing binaries on S3. Externalising user authentication and authorization might be a good candidate as well.&lt;/p&gt;

&lt;p&gt;There still might be cases where developing your own &lt;code&gt;UserService&lt;/code&gt; will be a better option — if you have very non-standard requirements, need to replace an existing API, or due to legal/regulatory requirements. However, chances are high that for quite a lot of systems using an external service will be the most cost-efficient and future-proof solution.&lt;/p&gt;

</description>
      <category>auth0</category>
      <category>security</category>
      <category>oauth2</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Structured concurrency and pure functions</title>
      <dc:creator>Adam Warski</dc:creator>
      <pubDate>Fri, 19 Mar 2021 10:08:00 +0000</pubDate>
      <link>https://dev.to/softwaremill/structured-concurrency-and-pure-functions-26nh</link>
      <guid>https://dev.to/softwaremill/structured-concurrency-and-pure-functions-26nh</guid>
      <description>&lt;p&gt;A function or a method is &lt;strong&gt;pure&lt;/strong&gt;, if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it has no side effects&lt;/li&gt;
&lt;li&gt;the returned value depends only on the provided arguments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will be most interested in the first property, that is &lt;strong&gt;lack of side effects&lt;/strong&gt;. An example of a side effect is anything that changes the "state of the world", such as modifying a global variable or performing any kind of I/O.&lt;/p&gt;

&lt;p&gt;Pure functions are widely described, see for example the article &lt;a href="https://en.wikipedia.org/wiki/Pure_function"&gt;on Wikipedia&lt;/a&gt;, a &lt;a href="https://blog.knoldus.com/functional-java-understanding-pure-functions-with-java/"&gt;blog post using Java&lt;/a&gt;, or &lt;a href="https://wiki.haskell.org/Pure"&gt;Haskell docs page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Purity doesn't have to be a &lt;strong&gt;binary property&lt;/strong&gt;, though. There are some side effects that we care more about than others. For example, logging isn't often counted as a side effect (even though it performs I/O), and hence a function which makes some computations and performs logging might be still considered pure.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Structured concurrency&lt;/strong&gt; is a property of concurrent programs, where (following the &lt;a href="http://libdill.org/structured-concurrency.html"&gt;definition by Martin Sústrik&lt;/a&gt;) the lifetimes of concurrent functions are cleanly nested. That is, if a function &lt;code&gt;foo&lt;/code&gt; starts running a function &lt;code&gt;bar&lt;/code&gt; in the background (&lt;code&gt;bar&lt;/code&gt; runs concurrently to &lt;code&gt;foo&lt;/code&gt;), then &lt;code&gt;bar&lt;/code&gt; must finish before &lt;code&gt;foo&lt;/code&gt; completes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FWe3677Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dcqr3oi0p9g3m8aru4ww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FWe3677Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dcqr3oi0p9g3m8aru4ww.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This ensures that the scopes of functions running concurrently are cleanly nested. This might seem like a reasonable property, however concurrent code is rarely written in that style in practice. Computations, in the forms of &lt;em&gt;threads&lt;/em&gt;, &lt;em&gt;fibers&lt;/em&gt;, &lt;em&gt;coroutines&lt;/em&gt; or &lt;em&gt;processes&lt;/em&gt; — depending on the language and framework used — are started in the background and left running without supervision or joining.&lt;/p&gt;

&lt;p&gt;Nathaniel J. Smith makes a successful comparison between &lt;code&gt;goto&lt;/code&gt; and &lt;code&gt;go&lt;/code&gt; (which here stands for unconstrained forking of concurrent computations) in his blog "&lt;a href="https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/"&gt;Notes on structured concurrency, or: Go statement considered harmful&lt;/a&gt;". The article provides an alternative introduction to structured concurrency; by avoiding &lt;code&gt;goto&lt;/code&gt; we make sure we can read and try to understand the source code without arbitrary jumps. Similarly, by avoiding &lt;code&gt;go&lt;/code&gt; we can avoid even worse kid of jumping: to &lt;strong&gt;multiple locations at once&lt;/strong&gt;, again making the code easier to read.&lt;/p&gt;

&lt;p&gt;Another way of looking at the structured concurrency property is that lifetimes of concurrently running functions must follow the syntactic layout of the program. Hence the name: the scope of &lt;strong&gt;concurrency&lt;/strong&gt; follows the &lt;strong&gt;structure&lt;/strong&gt; of the code.&lt;/p&gt;




&lt;p&gt;Do the two properties described above relate? Yes! &lt;strong&gt;Starting a thread&lt;/strong&gt; and leaving it running after the function completes &lt;strong&gt;is a side-effect&lt;/strong&gt;. Not only we change the state of the world by creating a new thread, the thread itself must perform some state-changing actions to do any meaningful work (if all it did was running a pure function, it wouldn't make sense to start it at all). That's all under the assumption that the lifetime of the thread exceeds the lifetime of the function call.&lt;/p&gt;

&lt;p&gt;What structured concurrency specifies is that this cannot happen: &lt;strong&gt;thread-related side effects&lt;/strong&gt; are not permitted. Any threads that are started by the function, must complete before the function completes. In other words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A function that satisfies the &lt;strong&gt;structured concurrency&lt;/strong&gt; property is a function that is &lt;strong&gt;pure wrt threading side-effects&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That way, threading becomes an &lt;strong&gt;implementation detail&lt;/strong&gt; of the function. It's the responsibility of the function to decide whether threads must be started (either for performance, or to implement its logic), and it's also its responsibility to ensure that these threads to terminate (by waiting for them to complete, or interrupting them).&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;pure&lt;/strong&gt; function might still use side-effecting logic internally, such as using mutable state for performance, but it cannot mutate anything that's global. Similarly, a &lt;strong&gt;threading-pure&lt;/strong&gt; function might create concurrent threads of execution internally, but they cannot be left running after the function completes.&lt;/p&gt;

&lt;p&gt;Other side effects might happen in a threading-pure function; it doesn't have to be pure wrt to all kinds of side effects.&lt;/p&gt;




&lt;p&gt;What if the function at hand returns a &lt;code&gt;Future&lt;/code&gt; or a &lt;code&gt;Promise&lt;/code&gt;: that is, a value representing a computation running in the background, that will eventually yield a result? Can such functions be structurally concurrent?&lt;/p&gt;

&lt;p&gt;They might be, but we need to adjust our definition a bit; requiring that a function returning a &lt;code&gt;Future&lt;/code&gt; doesn't leave any concurrent threads running after it completes, would defeat the purpose of using &lt;code&gt;Future&lt;/code&gt;s in the first place.&lt;/p&gt;

&lt;p&gt;Hence, a &lt;code&gt;Futue&lt;/code&gt;-returning function will satisfy the structural concurrency property as long as the returned future will complete &lt;strong&gt;only once all other futures/promises&lt;/strong&gt; created by the function are complete as well (successfully or with an error).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FJAnwelw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ytps9eyvx0n21fcvhboi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FJAnwelw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ytps9eyvx0n21fcvhboi.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, this translates to the fact that no threads of execution are left running in the background, but this time when the computation returned by the function completes. In the same way, we can extend the definition of threading-purity.&lt;/p&gt;

&lt;p&gt;What about functional effects, that is various forms of &lt;code&gt;IO&lt;/code&gt;s? Unlike &lt;code&gt;Future&lt;/code&gt;s, such values are &lt;strong&gt;descriptions&lt;/strong&gt; of computations (not &lt;strong&gt;running&lt;/strong&gt; computations), which might have side-effects once interpreted. That is, &lt;code&gt;IO&lt;/code&gt;s are lazy, while &lt;code&gt;Future&lt;/code&gt;s are eager.&lt;/p&gt;

&lt;p&gt;By a similar extension to the one we've done before, a function returning an &lt;code&gt;IO&lt;/code&gt; is structurally concurrent if the computation that is &lt;strong&gt;described&lt;/strong&gt; by the value doesn't leave any threads running as a side-effect (once it is complete). This makes the described computation "self-contained".&lt;/p&gt;




&lt;p&gt;Structured concurrency is a promising concept, which provides a great tool for writing correct concurrent programs and reading them afterwards. It's being implemented in Java (see &lt;a href="https://wiki.openjdk.java.net/display/loom/Structured+Concurrency"&gt;project Loom&lt;/a&gt;), &lt;a href="https://medium.com/@elizarov/structured-concurrency-722d765aa952"&gt;Kotlin&lt;/a&gt;, &lt;a href="https://ziverge.com/blog/zio-1.0"&gt;Scala&lt;/a&gt;, &lt;a href="https://trio.readthedocs.io/en/stable/"&gt;Python&lt;/a&gt;, &lt;a href="http://libdill.org/structured-concurrency.html"&gt;C&lt;/a&gt; and &lt;a href="https://trio.discourse.group/t/structured-concurrency-resources/21"&gt;other languages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pure functions&lt;/strong&gt; are the basic building block of &lt;strong&gt;Functional Programming&lt;/strong&gt; (FP). That's where FP takes its power from; code which uses pure functions is easier to read, follow and understand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structured concurrency&lt;/strong&gt;, seen as a &lt;strong&gt;specialisation of function purity&lt;/strong&gt; to the domain of threading, is one more example of this property. It's easier to understand and write correct code where threads can't exceed the lifetime of the function in which they are started.&lt;/p&gt;

&lt;p&gt;Which might make you wonder: maybe the same applies to other side effects, such as I/O or global state? That's what the FP community has been saying for a long time, and depending on the complexity of the problem at hand, indeed avoiding such side effects in functions might be beneficial to the maintainability and long-term evolution of a codebase.&lt;/p&gt;

</description>
      <category>functional</category>
      <category>java</category>
      <category>scala</category>
      <category>kotlin</category>
    </item>
  </channel>
</rss>
