<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rebeja</title><link>https://rebeja.eu/</link><description>Single threaded stories.</description><atom:link href="https://rebeja.eu/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:petru.rebeja@gmail.com"&gt;Petru Rebeja&lt;/a&gt; </copyright><lastBuildDate>Tue, 24 Feb 2026 17:58:28 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>How I use Emacs to keep a developer journal</title><link>https://rebeja.eu/posts/how-i-use-emacs-to-keep-a-developer-journal/</link><dc:creator>Petru Rebeja</dc:creator><description>&lt;div id="outline-container-org1dcefe4" class="outline-2"&gt;
&lt;h2 id="org1dcefe4"&gt;Why keep a developer journal?&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org1dcefe4"&gt;
&lt;p&gt;
I won't expand on what a developer journal is, or on what the benefits of keeping a developer journal are; there are plenty of resources for that online (&lt;a href="https://blog.invidelabs.com/what-is-a-developer-diary/"&gt;What is a Developer Diary&lt;/a&gt;, &lt;a href="https://opensource.com/article/19/4/what-developer-journal"&gt;What is a developer journal?&lt;/a&gt;, &lt;a href="https://stackoverflow.blog/2024/12/24/you-should-keep-a-developer-s-journal/"&gt;You should keep a developer’s journal&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=Xw3SkhB4dMk"&gt;Everything Starts with a Note-taking System&lt;/a&gt;). But let me tell you what made me start keeping a developer journal.
&lt;/p&gt;

&lt;p&gt;
You see, I am one of those people that like to start each day from a blank page. This means that at the end of the work day I shut down my computer such that at the beginning of the next day I can start anew. The problem with starting anew each day is that &lt;i&gt;you don't always get to finish everything by the end of the day&lt;/i&gt;. And in this case, starting anew the next day is, so to say, nothing else than loading state onto blank memory (I know; I am a nerd).
&lt;/p&gt;

&lt;p&gt;
This is where keeping a developer journal shines for me. I log in my developer journal all the useful snippets that I employ whilst working on a task, be it a SQL query, an URL which references some documentation, a milestone, a summary of a conversation with a colleague, an Eureka! moment, or a small progress — anything that can help me restore the context at the current moment in the future. And the great part is that when I say future I don't necessarily mean tomorrow, or Monday — I mean months into the future.
&lt;/p&gt;

&lt;p&gt;
Be aware however, that I am limiting the time frame to months only. As years go by, time takes its toll and it is harder and harder to recall the &lt;i&gt;exact&lt;/i&gt; context of a specific task, regardless of how detailed the journal logs are.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org1c0d65e" class="outline-2"&gt;
&lt;h2 id="org1c0d65e"&gt;Why Emacs?&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org1c0d65e"&gt;
&lt;p&gt;
For some time already I have been using &lt;code&gt;org-agenda&lt;/code&gt; to track the time I spend on each of my tasks in the most simple way possible: I add each task to a file from which &lt;code&gt;org-agenda&lt;/code&gt; reads its data, call &lt;code&gt;org-clock-in&lt;/code&gt; on that task when I start working on it, and call &lt;code&gt;org-clock-out&lt;/code&gt; when I am not working on that task anymore.
&lt;/p&gt;

&lt;p&gt;
Naturally, I wanted to build up from there. Also, I wanted to start with something simple that would allow me to do what I want and improve the workflow afterwards. In other words, and as cliché it may sound, I wanted to be agile in setup — start small and let it evolve in the right direction. And, to the best of my knowledge, Emacs is the only piece of software that provides this flexibility.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org86f4239" class="outline-2"&gt;
&lt;h2 id="org86f4239"&gt;The setup&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org86f4239"&gt;
&lt;p&gt;
I do use &lt;code&gt;org-roam&lt;/code&gt; which would have fit the requirements for a developer journal setup. However, I refrained from using it for a few reasons:
&lt;/p&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;I wanted to keep everything in a single file because I liked the idea of how &lt;code&gt;org-capture&lt;/code&gt; can file entries under a &lt;a href="https://orgmode.org/manual/Template-elements.html#FOOT84"&gt;date tree&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I would have polluted my Zettelkasten because I may need to create multiple entries for a single task which would not have been linked to the rest of the knowledge graph.&lt;/li&gt;
&lt;li&gt;I wanted to keep my developer journal separated from the Zettelkasten.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
As such, once I excluded &lt;code&gt;org-roam&lt;/code&gt; from the list of candidates, I got back to the basics — an &lt;code&gt;org-capture&lt;/code&gt; template. But a simple capture template was not enough. During a work day I can switch between multiple tasks, and before switching from one task to another I would log the latest state of affairs for the current task into my developer journal. As such, I would need a way to distinguish between which tasks are referenced in my logs.
&lt;/p&gt;

&lt;p&gt;
After digging a bit through the documentation, I found a simple solution to this problem — store a link to the current development task, and use that link in the capture template.
&lt;/p&gt;

&lt;p&gt;
The &lt;code&gt;org&lt;/code&gt; package already provides a function for this — &lt;code&gt;org-store-link&lt;/code&gt;; so all I had to do was to add a key-binding to it — &lt;code&gt;C-c l&lt;/code&gt; in my case:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;org&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;:defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;t&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;:bind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;:map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;global-map&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"C-c c"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;org-capture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"C-c a"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;org-agenda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nv"&gt;:map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;org-mode-map&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"C-c l"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;org-store-link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nv"&gt;:map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;org-agenda-mode-map&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"C-c l"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;org-store-link&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
Unbeknownst to me, this solution proved to be a really good fit into my workflow, but more on this in the next section.
&lt;/p&gt;

&lt;p&gt;
At this point, my setup was ready; after storing a link to the task I was currently working on, I was able to capture whatever bits of information I considered relevant for the task at hand. However, there were some nuisances in how the capture environment presented itself so, after digging through the documentation again I found out that I can provide a function to setup the environment before starting the capture. So I created the following function to do just that — configure the capture environment as I like it:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;start &lt;code&gt;olivetti-mode&lt;/code&gt; with a body width of 120 to avoid line wrap in source code blocks,&lt;/li&gt;
&lt;li&gt;change the dictionary to US English, and start &lt;code&gt;flyspell-mode&lt;/code&gt; (I try to have as little spelling mistakes as I can)&lt;/li&gt;
&lt;li&gt;last but not least, delete other windows to avoid clutter.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defun&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rp/setup-work-journal-capture&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;"Prepare an environment for capturing work journal entries."&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;progn&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;olivetti-mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;setq-local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;olivetti-body-width&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ispell-change-dictionary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"en_US"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;flyspell-mode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;delete-other-windows&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
With all the above in place, this is how my final capture template looks like:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add-to-list&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;org-capture-templates&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"w"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Work related items"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wj"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Journal entry"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;entry&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;file+olp+datetree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"~/org/gtd/work.org"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Journal"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;"* %a &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;%U&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;%?"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;:hook&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;rp/setup-work-journal-capture&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org57cdbd6" class="outline-2"&gt;
&lt;h2 id="org57cdbd6"&gt;The workflow&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org57cdbd6"&gt;
&lt;p&gt;
As I mentioned in the previous section, this setup proved to be a really good fit for my workflow, and became a seamless extension to it because I was using &lt;code&gt;org-agenda&lt;/code&gt; and &lt;code&gt;org-clock&lt;/code&gt; to schedule my tasks and track the time spent on each of them.
&lt;/p&gt;

&lt;p&gt;
While my previous workflow was: add the task to &lt;code&gt;org-agenda&lt;/code&gt;, schedule it, and use &lt;code&gt;org-clock-in&lt;/code&gt; and &lt;code&gt;org-clock-out&lt;/code&gt; to track the time, the new workflow is as follows:
&lt;/p&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;Add the task to &lt;code&gt;org-agenda&lt;/code&gt; and schedule it properly using a capture template&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;org-clock-in&lt;/code&gt; when starting to work on a task (bound to &lt;code&gt;I&lt;/code&gt; in the &lt;code&gt;*Org Agenda*&lt;/code&gt; buffer)&lt;/li&gt;
&lt;li&gt;When I want to add a new developer entry for that task, I:
&lt;ul class="org-ul"&gt;
&lt;li&gt;switch to the &lt;code&gt;*Org Agenda*&lt;/code&gt; buffer using &lt;code&gt;C-x b&lt;/code&gt; (or &lt;code&gt;M-x switch-to-buffer&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;in the agenda buffer I call &lt;code&gt;org-clock-go-to&lt;/code&gt; by pressing &lt;code&gt;C-c C-x C-j&lt;/code&gt;, then:
&lt;ul class="org-ul"&gt;
&lt;li&gt;&lt;code&gt;C-l&lt;/code&gt; to store the link to the current item&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-c c&lt;/code&gt; to start &lt;code&gt;org-capture&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;w j&lt;/code&gt; to select the developer journal capture template&lt;/li&gt;
&lt;li&gt;input all the important information&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-c C-c&lt;/code&gt; to finalize the capture.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
Although it may seem complicated at first, I felt no resistance in internalizing this workflow because it became a natural extension of the previous workflow. And yes, there are a lot of keys to press. But for someone who types a lot (as all developers do), pressing all those keys takes a very small amount of time but the benefit it brings is &lt;i&gt;huge&lt;/i&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org1b8d466" class="outline-2"&gt;
&lt;h2 id="org1b8d466"&gt;My developer journal&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org1b8d466"&gt;
&lt;p&gt;
I write several entries per day in my developer journal and after keeping it for a year already I can say for sure that this habit improved my life as a developer in several ways. Besides being able to quickly start each day from a blank page, it forces me to think beforehand instead of just diving head-first into the implementation. As a result of this, my implementation has less kludge and is easier to modify/maintain. Furthermore, my developer journal helps the entire team because I am able to extract from it information that goes into the project wiki. Last but not least, &lt;i&gt;I feel&lt;/i&gt; that my writing skills have improved as a result of keeping a developer journal.
&lt;/p&gt;


&lt;p&gt;
The excerpt is from a blog post about how the author uses Emacs to keep a developer journal. They explain why they find it helpful to keep a developer journal and why they chose to use Emacs for this purpose. They also describe their Emacs setup for keeping a developer journal, including the key bindings and functions they use. They conclude by discussing the benefits of keeping a developer journal.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>developer journal</category><category>Emacs</category><category>productivity</category><guid>https://rebeja.eu/posts/how-i-use-emacs-to-keep-a-developer-journal/</guid><pubDate>Thu, 31 Jul 2025 13:10:32 GMT</pubDate></item><item><title>Handling automatic update of concurrency tokens in Entity Framework Core</title><link>https://rebeja.eu/posts/handling-automatic-update-of-concurrency-tokens-in-entity-framework-core/</link><dc:creator>Petru Rebeja</dc:creator><description>&lt;div id="outline-container-org5b48340" class="outline-2"&gt;
&lt;h2 id="org5b48340"&gt;Introduction&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org5b48340"&gt;
&lt;p&gt;
If your application uses &lt;a href="https://learn.microsoft.com/en-us/ef/core/"&gt;Entity Framework Core&lt;/a&gt; and has a business logic that is of medium or higher complexity, at some point, you may want to bake into that business logic some mechanism for &lt;a href="https://learn.microsoft.com/en-us/ef/core/saving/concurrency"&gt;handling concurrency&lt;/a&gt; when persisting the data into the database.
&lt;/p&gt;

&lt;p&gt;
If your software uses SQL Server as the database management system  then things are really simple. All you need to do in to implement the following steps:
&lt;/p&gt;

&lt;ol class="org-ol"&gt;
&lt;li&gt;Create a &lt;code&gt;RowVersion&lt;/code&gt; property in your entities,&lt;/li&gt;
&lt;li&gt;Configure that property as a concurrency token  in the entity configuration, and&lt;/li&gt;
&lt;li&gt;Run the migration scripts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
Once all of the above are done the concurrency management works out of the box.
&lt;/p&gt;

&lt;p&gt;
However, in any other circumstances the things get complicated. This post is about one of those other circumstances, namely when the database management system is Oracle Server, and the version property is an integer value.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org7b9db3f" class="outline-2"&gt;
&lt;h2 id="org7b9db3f"&gt;Automatic update of concurrency tokens&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org7b9db3f"&gt;
&lt;p&gt;
The hint on how to approach such use-case lies buried in the &lt;a href="https://learn.microsoft.com/en-us/ef/core/saving/concurrency"&gt;documentation&lt;/a&gt;, behind a simple link, which contains the keyword for the actual solution: &lt;b&gt;&lt;a href="https://learn.microsoft.com/en-us/ef/core/logging-events-diagnostics/interceptors#savechanges-interception"&gt;use an interceptor when saving changes&lt;/a&gt; to automatically update the value of the property that holds the concurrency token&lt;/b&gt;. And since that documentation suffers from too much obscurity for my taste, below are the steps on how to achieve the same goal.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id="outline-container-orga88063c" class="outline-3"&gt;
&lt;h3 id="orga88063c"&gt;Prerequisites&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-orga88063c"&gt;
&lt;p&gt;
Let's say we have an entity named &lt;code&gt;Person&lt;/code&gt; in our code-base with the following structure:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
where we want the property &lt;code&gt;Version&lt;/code&gt; to act as a concurrency token which will be updated automatically each time the data of the entity is updated.
&lt;/p&gt;

&lt;p&gt;
If we have more than one entity for which we want to implement the automatic update of concurrency tokens we can extract an interface to define the concurrency token property:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IConcurrencyAwareEntity&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
After defining the interface, we use it to mark all desired entities as being concurrency aware:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IConcurrencyAwareEntity&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org33479a6" class="outline-3"&gt;
&lt;h3 id="org33479a6"&gt;Entity configuration&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-org33479a6"&gt;
&lt;p&gt;
We need to tell Entity Framework Core to enable the concurrency checking mechanism for the &lt;code&gt;Person&lt;/code&gt; entity by specifying that the &lt;code&gt;Version&lt;/code&gt; property is a concurrency token in the entity configuration:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;internal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;PersonEntityConfiguration&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IEntityTypeConfiguration&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EntityTypeBuilder&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasColumnName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"VERSION"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasColumnType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NUMBER"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsConcurrencyToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgeec75a7" class="outline-3"&gt;
&lt;h3 id="orgeec75a7"&gt;Interceptor implementation&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-orgeec75a7"&gt;
&lt;p&gt;
With the entity properly configured, it is time to implement the interceptor that will increment the value of the &lt;code&gt;Version&lt;/code&gt; property automatically when the entity is saved into the database.
&lt;/p&gt;

&lt;p&gt;
To do so, we need to create a class that derives from the &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.diagnostics.savechangesinterceptor?view=efcore-9.0"&gt;&lt;code&gt;SaveChangesInterceptor&lt;/code&gt;&lt;/a&gt; class. This class will override the &lt;code&gt;SavingChanges&lt;/code&gt;, and &lt;code&gt;SavingChangesAsync&lt;/code&gt; methods in order to:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;iterate through all updated or inserted items from the change tracker of the database context,&lt;/li&gt;
&lt;li&gt;for each entity, check if it implements the &lt;code&gt;IConcurrencyAwareEntity&lt;/code&gt; interface&lt;/li&gt;
&lt;li&gt;if yes — increment the &lt;code&gt;Version&lt;/code&gt; property.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;internal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ConcurrencyEntitySaveChangesInterceptor&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SaveChangesInterceptor&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;InterceptionResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SavingChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;DbContextEventData&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eventData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;InterceptionResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IncrementVersionOfConcurrencyAwareEntities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;eventData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SavingChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ValueTask&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;InterceptionResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;SavingChangesAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;DbContextEventData&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eventData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;InterceptionResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IncrementVersionOfConcurrencyAwareEntities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;eventData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SavingChangesAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;eventData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;IncrementVersionOfConcurrencyAwareEntities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;DbContext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetEntriesToUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IConcurrencyAwareEntity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EntityState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Added&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OriginalValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;EntityEntry&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetEntriesToUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;DbContext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChangeTracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entries&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IConcurrencyAwareEntity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EntityState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Added&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;                            &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EntityState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Modified&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
While the method &lt;code&gt;GetEntriesToUpdate()&lt;/code&gt; from above is self-explanatory, the method &lt;code&gt;IncrementVersionOfConcurrencyAwareEntities()&lt;/code&gt; requires a bit of commentary on what it does to each &lt;code&gt;EntityEntry&lt;/code&gt; instance.
&lt;/p&gt;

&lt;p&gt;
If the entity does not exist in the database (i. e. when the corresponding entry has the state &lt;code&gt;EntityState.Added&lt;/code&gt;) we just need to set the value of the property &lt;code&gt;Version&lt;/code&gt; to 1, and nothing else because when the entity will be persisted Entity Framework Core will issue an &lt;code&gt;INSERT&lt;/code&gt; statement.
&lt;/p&gt;

&lt;p&gt;
However, when an entity that has concurrency handling enabled needs to be persisted, and it exists in the database already, when issuing the &lt;code&gt;UPDATE&lt;/code&gt; statement Entity Framework Core will include in the &lt;code&gt;WHERE&lt;/code&gt; clause a condition on the value of the concurrency token alongside the primary key of the entity. In the case of the &lt;code&gt;Person&lt;/code&gt; entity declared above, the &lt;code&gt;UPDATE&lt;/code&gt; statement would look like this:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;persons&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Doe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
The value &lt;code&gt;2&lt;/code&gt; in the example above is the value that the &lt;code&gt;Version&lt;/code&gt; property had when the entity was loaded from the database. This is the reason why the method &lt;code&gt;IncrementVersionOfConcurrencyAwareEntities&lt;/code&gt; contains these two lines:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OriginalValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
These lines signal Entity Framework Core that it should update the row that has the value of the &lt;code&gt;Version&lt;/code&gt; property equal to the value it had &lt;i&gt;before incrementing it&lt;/i&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgecd7378" class="outline-3"&gt;
&lt;h3 id="orgecd7378"&gt;Add the interceptor to the &lt;code&gt;DbContext&lt;/code&gt;&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-orgecd7378"&gt;
&lt;p&gt;
Now that we have an interceptor to automatically increment the value of the &lt;code&gt;Version&lt;/code&gt; property, all we need to do is to add it to the database context. This is done quite easily:
&lt;/p&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;Register your interceptor class in the dependency injection framework&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
Inject the interceptor into your &lt;code&gt;DbContext&lt;/code&gt; class
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;PersonsDbContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;ConcurrencyEntitySaveChangesInterceptor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interceptor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interceptor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interceptor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
Add the interceptor to the context class in &lt;code&gt;OnConfiguring&lt;/code&gt; method
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;protected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;OnConfiguring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;DbContextOptionsBuilder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;optionsBuilder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnConfiguring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;optionsBuilder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;optionsBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddInterceptors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interceptor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
Once the interceptor is registered, you should see the value of the &lt;code&gt;Version&lt;/code&gt; property increase automatically each time an entity marked with &lt;code&gt;IConcurrencyAwareEntity&lt;/code&gt; interface is updated.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org50263a6" class="outline-2"&gt;
&lt;h2 id="org50263a6"&gt;Concurency handling&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org50263a6"&gt;
&lt;p&gt;
At this point concurrency handling kicks-in out of the box thanks to the two aforementioned lines from the &lt;code&gt;IncrementVersionOfConcurrencyAwareEntities&lt;/code&gt; method:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OriginalValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
The lines above encapsulate the essence of the concurrency handling mechanism. They signal Entity Framework (in a bit of a contrived way admittedly) that we want to update the entity &lt;i&gt;if and only if&lt;/i&gt; the entity in the database has the value of the concurrency token (&lt;code&gt;Version&lt;/code&gt; property in our case) equal to the original value of the property when the entity was loaded, i.e. the value of the &lt;code&gt;Version&lt;/code&gt; property before incrementing it.
&lt;/p&gt;

&lt;p&gt;
If there is no row in the database table that satisfies the condition above, then no rows are updated, and subsequently Entity Framework Core throws a &lt;code&gt;DbUpdateConcurrencyException&lt;/code&gt; which, as its name tells, signals that the row we are trying to update was changed in the meanwhile.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org0ba71de" class="outline-2"&gt;
&lt;h2 id="org0ba71de"&gt;Conclusion&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org0ba71de"&gt;
&lt;p&gt;
Entity Framework Core has a built-in mechanism for handling concurrency that works great out of the box when the application uses the default types for concurency tokens, and SQL Server as the database management system. This mechanism relies on comparing the values of the concurrency token for each database operation; if the value supplied by the application is not the same as the value from the database this is considered to be a concurrency conflict.
&lt;/p&gt;

&lt;p&gt;
But once you stray off the beaten path, things become more complicated as this post shows while trying to provide a guide on how to automatically update the value of the concurrency tokens in non-default scenarios. Fortunately, the concurrency handling mechanism from Entity Framework Core is designed to accommodate a wide range of use-cases, and with a slight adjustment through a custom interceptor that updates the value of concurrency tokens when saving entities to the database, we can ensure the conflict handling mechanism operates as originally intended
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>c#</category><category>concurrency</category><category>Entity Framework Core</category><category>interceptor</category><guid>https://rebeja.eu/posts/handling-automatic-update-of-concurrency-tokens-in-entity-framework-core/</guid><pubDate>Thu, 26 Jun 2025 05:57:09 GMT</pubDate></item><item><title>Introducing the Specialized Workers pattern</title><link>https://rebeja.eu/posts/specialized-workers-pattern/</link><dc:creator>Petru Rebeja</dc:creator><description>&lt;div id="outline-container-org5dc3734" class="outline-2"&gt;
&lt;h2 id="org5dc3734"&gt;Introduction&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org5dc3734"&gt;
&lt;p&gt;
Some years ago, in my &lt;a href="https://rebeja.eu/posts/using-enums-in-c-sharp/"&gt;blog post about using enums in C#&lt;/a&gt; I mentioned that I like using what I called at that time &lt;code&gt;specialized builders&lt;/code&gt; to refactor the &lt;code&gt;switch&lt;/code&gt; statement into a series of classes that implement a common interface and are specialized for a specific &lt;code&gt;case&lt;/code&gt; of the &lt;code&gt;switch&lt;/code&gt; statement.
&lt;/p&gt;

&lt;p&gt;
For the past few years I have been showing to my colleagues a slightly improved version of this approach (the topic of this post) and they all seem to agree that this is indeed a cleaner, and more elegant approach which, unlike the infamous &lt;code&gt;switch&lt;/code&gt; statement does abide by the &lt;a href="https://en.wikipedia.org/wiki/Open/closed_principle"&gt;Open/Closed principle&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
As such, I am excited to introduce to the world the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org4a67125" class="outline-2"&gt;
&lt;h2 id="org4a67125"&gt;Specialized Workers Pattern&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org4a67125"&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgb3c2f58" class="outline-3"&gt;
&lt;h3 id="orgb3c2f58"&gt;Description and usage&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-orgb3c2f58"&gt;
&lt;p&gt;
The &lt;code&gt;Specialized Workers&lt;/code&gt; pattern aims to distribute the logic of a business operation that requires choosing between one or multiple tasks to be executed, into a collection of specialized classes, while keeping the knowledge about the task(s) to be executed into a single place.
&lt;/p&gt;

&lt;p&gt;
Under these circumstances each worker knows about the data just enough to know whether it &lt;i&gt;can accomplish the task&lt;/i&gt;, and &lt;i&gt;how to accomplish&lt;/i&gt; it.
&lt;/p&gt;

&lt;p&gt;
Usually (at least from my experience), the decision to delegate a certain sub task was made by the unit that is in charge of delegating. In an abstract representation the code would look something like this:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SomeCondition&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;DoWorkForConditionAbove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
where the method that contains the snippet above &lt;i&gt;delegates&lt;/i&gt; the processing to the &lt;code&gt;DoWorkForConditionAbove()&lt;/code&gt; method.
&lt;/p&gt;

&lt;p&gt;
However, when the decision whether to delegate to a specific unit or not depends on the data that is to be processed, taking that decision couples both the delegator, and the worker unit to the structure of the data.
&lt;/p&gt;

&lt;p&gt;
It is normal for the worker to be coupled to the structure of the data because it has to know the structure in order to be able to process it but the delegator, which now becomes a coordinator, doesn't have to know the structure of the data.
&lt;/p&gt;

&lt;p&gt;
Consider the example of an unit that has to parse an &lt;code&gt;HTML&lt;/code&gt; element and has to make the following decision:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;if the current node is a &lt;code&gt;div&lt;/code&gt; then &lt;code&gt;ParseDivElement()&lt;/code&gt; should be called,&lt;/li&gt;
&lt;li&gt;if the current node is a &lt;code&gt;table&lt;/code&gt; then &lt;code&gt;ParseTableElement()&lt;/code&gt; should be called, and&lt;/li&gt;
&lt;li&gt;if the current element is none of the above, it should just ignore it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Put differently than at the beginning of this section,  the purpose of &lt;code&gt;Specialized Workers&lt;/code&gt; pattern is to:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;delegate the work to a single place, and&lt;/li&gt;
&lt;li&gt;enclose in a single place &lt;i&gt;the knowledge about being able to perform a specific task&lt;/i&gt; and &lt;i&gt;the knowledge required to perform that task&lt;/i&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-implementation" class="outline-3"&gt;
&lt;h3 id="implementation"&gt;Implementation&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-implementation"&gt;
&lt;p&gt;
Now that we established what &lt;code&gt;Specialized Workers&lt;/code&gt; pattern is, let's see how it can be implemented.
&lt;/p&gt;

&lt;p&gt;
It goes without saying that when implementing this pattern, the  amount of work directly depends on how many workers the business case requires (i.e. how many &lt;code&gt;switch&lt;/code&gt; cases are there) but, in broad lines, to implement the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern you'll need to:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Define a interface for the worker exposing two methods — &lt;code&gt;CanProcess()&lt;/code&gt;, and &lt;code&gt;Process()&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ISpecializedWorker&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;CanProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Add a class for each use-case:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;internal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;MondayPayloadWorker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ISpecializedWorker&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;CanProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DayOfWeek&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DayOfWeek&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Monday&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ProcessInternal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Inject the workers into the calling class (the &lt;code&gt;Employer&lt;/code&gt;), and delegate:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;internal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Employer&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;readonly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ISpecializedWorker&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_workers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Employer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ISpecializedWorker&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;_workers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_workers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SingleOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CanProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// This is the equivalent of the default case&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// in the switch statement.&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s"&gt;"Cannot process the provided payload."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
And that's all there is to it. Now, the &lt;code&gt;Employer&lt;/code&gt; class is agnostic of how the &lt;code&gt;payload&lt;/code&gt; is processed; it just delegates the processing to the worker that can handle it. If no workers that are able to process the &lt;code&gt;payload&lt;/code&gt; are found, the &lt;code&gt;Employer&lt;/code&gt; class can choose to signal this by either raising an exception, returning a default value or any other mechanism that is suited to the other patterns used in the code-base. More on this in section &lt;a href="https://rebeja.eu/posts/specialized-workers-pattern/#adaptations"&gt;Adaptations&lt;/a&gt;. Furthermore, the &lt;code&gt;Employer&lt;/code&gt; class doesn't have to know how many workers are there; as such, the workers can be added or removed without any change to the &lt;code&gt;Employer&lt;/code&gt; class, which means that the class is &lt;i&gt;decoupled&lt;/i&gt; from the workers.
&lt;/p&gt;

&lt;p&gt;
On the other hand, each worker class is, as the name of the pattern suggests it, &lt;i&gt;specialized&lt;/i&gt; to do one thing — work on the specific use-case it knows all about: whether it can process it, and if yes, then it also knows how to process it.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org35c53e2" class="outline-2"&gt;
&lt;h2 id="org35c53e2"&gt;Discussion&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org35c53e2"&gt;
&lt;/div&gt;
&lt;div id="outline-container-org98784a2" class="outline-3"&gt;
&lt;h3 id="org98784a2"&gt;How is it different from the &lt;code&gt;Strategy&lt;/code&gt; pattern?&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-org98784a2"&gt;
&lt;p&gt;
At this moment you may be wondering how the &lt;code&gt;Specialized Workers&lt;/code&gt; is different from the &lt;code&gt;Strategy&lt;/code&gt; pattern? After all, each worker implements and applies a different strategy in the processing of the data.
&lt;/p&gt;

&lt;p&gt;
To put it simply, the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern is not different from the &lt;code&gt;Strategy&lt;/code&gt; design pattern; it evolves from it, with the added behavior that the caller (coordinator — the &lt;code&gt;Employee&lt;/code&gt; class from above) doesn't have to know explicitly which worker to employ. The worker to employ is selected based on its knowledge of the payload (i.e. based on the workers' "expertise") which, as mentioned before, makes the coordinator agnostic of the payload. As such, all the knowledge that is related to how to do a specific processing is kept in the same class where the processing happens.
&lt;/p&gt;

&lt;p&gt;
There is however, a difference in the nomenclature: &lt;code&gt;Strategy&lt;/code&gt; is a &lt;i&gt;design pattern&lt;/i&gt; whilst &lt;code&gt;Specialized Workers&lt;/code&gt; is an &lt;i&gt;implementation pattern&lt;/i&gt;. The difference between a design pattern and an implementation pattern deserves a dedicated post but to put it shortly, an implementation pattern tells you how you should write your code while a design pattern specifies how the application should be structured.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgb409a82" class="outline-3"&gt;
&lt;h3 id="orgb409a82"&gt;Why not use a &lt;code&gt;Factory method&lt;/code&gt;?&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-orgb409a82"&gt;
&lt;p&gt;
Okay, you might say, then why not use a &lt;code&gt;Factory method&lt;/code&gt; to build directly the worker that knows how to handle the specific use-case?
&lt;/p&gt;

&lt;p&gt;
Well, because the answer to this question is actually one of the benefits that come with implementing the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern, namely that it keeps the specialized logic within the same class.
&lt;/p&gt;

&lt;p&gt;
When applying the &lt;code&gt;Factory method&lt;/code&gt;, the decision on which instance to build is separated from the actual processing that needs to take place. From the point of view of the separation of concerns this is OK; however one might argue that, in order to decide which worker to build, the factory has to either apply some business knowledge, or be coupled to the data (by being aware of its structure). When applying the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern, all the business logic that is coupled to the data is in a single place, i. e. the class of the specialized worker.
&lt;/p&gt;

&lt;p&gt;
Furthermore, when implementing the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern, you don't need to create instances of workers by hand as you do with the &lt;code&gt;Factory method&lt;/code&gt;; the creation of the workers can be delegated to the &lt;code&gt;Dependency Injection&lt;/code&gt; frameworks.
&lt;/p&gt;

&lt;p&gt;
However, if the instantiation of the specialized workers depends o some parameters that cannot be easily built using the &lt;code&gt;Dependency Injection&lt;/code&gt; framework, you'll need to use &lt;code&gt;Factory method&lt;/code&gt;. In this case you can combine these two approaches: use the &lt;code&gt;Factory method&lt;/code&gt; to build the specialized workers, and then pass them to the coordinator class that needs them. Keep in mind that this approach of combining the two patterns works if building each worker is an &lt;i&gt;inexpensive&lt;/i&gt; operation; otherwise you'll end-up spending resources to create instances that may not be used.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-drawbacks" class="outline-2"&gt;
&lt;h2 id="drawbacks"&gt;Drawbacks&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-drawbacks"&gt;
&lt;p&gt;
As we all know, there are no perfect solutions, especially in software development. This is also the case for the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern, and as such, it has a few drawbacks listed below.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id="outline-container-no-guarantee-of-the-same-parameters" class="outline-3"&gt;
&lt;h3 id="no-guarantee-of-the-same-parameters"&gt;No guarantee of the same parameters&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-no-guarantee-of-the-same-parameters"&gt;
&lt;p&gt;
The first drawback of the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern stems from the fact that the methods &lt;code&gt;CanProcess()&lt;/code&gt;, and &lt;code&gt;Process()&lt;/code&gt; are not constrained in any way to be called in the specific order they are meant to be called. Furthermore, there is also no guarantee whatsoever that these methods are called with the same parameter. The lack of constraints on the order of the calls, and on the parameters means that the caller may choose to ignore the results of the &lt;code&gt;CanProcess()&lt;/code&gt; method, or not call it at all, and then invoke the &lt;code&gt;Process()&lt;/code&gt; method.
&lt;/p&gt;

&lt;p&gt;
There are (at least) two ways to work around this misuse: to combine the two methods into a single one, as presented in sub-section &lt;a href="https://rebeja.eu/posts/specialized-workers-pattern/#using-a-single-method"&gt;Using a single method&lt;/a&gt;, and to simply  guard against invalid arguments using &lt;code&gt;Debug.Assert()&lt;/code&gt; or any of its equivalents:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CanProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Do the work&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-sensitivity-to-collections" class="outline-3"&gt;
&lt;h3 id="sensitivity-to-collections"&gt;Sensitivity to collections&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-sensitivity-to-collections"&gt;
&lt;p&gt;
While using the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern, you should be cautions when calling &lt;code&gt;CanProcess()&lt;/code&gt; on collections. Ideally, the method &lt;code&gt;CanProcess()&lt;/code&gt; should take the decision without iterating any collection of items. There are two intertwined reasons for that:  performance, and lazy loading.
&lt;/p&gt;

&lt;p&gt;
If you have a heterogeneous collection, you can iterate through it in the delegator and call &lt;code&gt;CanProcess()&lt;/code&gt; on each item in the collection. At the end, the delegator aggregates the results.
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Employer&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;readonly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ISpecializedWorker&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_workers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Employer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ISpecializedWorker&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;_workers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ProcessCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;partialResults&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;itemResults&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_workers&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CanProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;partialResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;itemResults&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;partialResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Aggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
This ensures that the collection is iterated only once thus avoiding any odd results due to lazy evaluation.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-adaptations" class="outline-2"&gt;
&lt;h2 id="adaptations"&gt;Adaptations&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-adaptations"&gt;
&lt;p&gt;
Despite its drawbacks, the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern is quite flexible in its implementation. As such, it can be adapted for some specific scenarios discussed below. Of course, it goes without saying that the list is not exclusive.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id="outline-container-using-a-single-method" class="outline-3"&gt;
&lt;h3 id="using-a-single-method"&gt;Using a single method&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-using-a-single-method"&gt;
&lt;p&gt;
For the cases when the processing is lightweight, you can combine the two methods into a single one that returns a tuple like this:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;canProcess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;CanProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ProcessInternal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;CanProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// take decision here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
As mentioned in the sub-section &lt;a href="https://rebeja.eu/posts/specialized-workers-pattern/#no-guarantee-of-the-same-parameters"&gt;No guarantee of the same parameters&lt;/a&gt;, combining the two methods into a single one guards against calling the &lt;code&gt;CanProcess()&lt;/code&gt; and &lt;code&gt;Process()&lt;/code&gt; methods in the opposite order or with different parameters.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-non-exclusive-workers" class="outline-3"&gt;
&lt;h3 id="non-exclusive-workers"&gt;Non-exclusive workers&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-non-exclusive-workers"&gt;
&lt;p&gt;
You can have multiple workers capable of processing the same payload; in this case, the caller (the delegator) is responsible for aggregating the results:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_workers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CanProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org8b8e3f7" class="outline-2"&gt;
&lt;h2 id="org8b8e3f7"&gt;Ending thoughts&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org8b8e3f7"&gt;
&lt;p&gt;
As you can see from this quite lengthy post, the &lt;code&gt;Specialized Workers&lt;/code&gt; pattern, provides both a way to cluster business logic into specialized classes, and a good degree of flexibility in order to adapt the implementation to different situations. Despite its flexibility however, it is my &lt;i&gt;subjective&lt;/i&gt; opinion that the original form of the pattern (the one shown in the &lt;a href="https://rebeja.eu/posts/specialized-workers-pattern/#implementation"&gt;Implementation&lt;/a&gt; section) is the most elegant and eloquent, which is why I use that version most of the time. But, especially as a software developer, I am aware that each person has its own preferences in regards to how something should be done or implemented. As such, I hope you find this pattern useful, and if so, feel free to apply it in whichever way suits you best.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>c#</category><category>implementation</category><category>pattern</category><category>specialized workers</category><guid>https://rebeja.eu/posts/specialized-workers-pattern/</guid><pubDate>Sun, 12 May 2024 08:09:45 GMT</pubDate></item><item><title>Don't release to Production, release to QA</title><link>https://rebeja.eu/posts/release-to-qa-not-production/</link><dc:creator>Petru Rebeja</dc:creator><description>&lt;p&gt;
&lt;b&gt;Automate your release workflow to such extent that the QA engineers from your team become the users of the application.&lt;/b&gt;
&lt;/p&gt;
&lt;div id="outline-container-org0c2fa9c" class="outline-2"&gt;
&lt;h2 id="org0c2fa9c"&gt;Introduction&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org0c2fa9c"&gt;
&lt;p&gt;
It's Friday afternoon, the end of the sprint, and a few hours before the weekend starts, and the QA engineers are performing the required tests on the last Sprint Backlog Item (SBI). The developer responsible for that item, confident that the SBI meets all acceptance criteria, is already in the weekend mood.
&lt;/p&gt;

&lt;p&gt;
Suddenly, a notification pops up — there is an issue with the feature being tested. The developer jumps on it to see what the problem is, and after discussing with the QA engineer he/she finds out that the issue is caused by some leftover data from the previous SBI.
&lt;/p&gt;

&lt;p&gt;
Having identified the problem, the developer spends a few minutes to craft a SQL script that will clean the data, and gives it to the QA engineer. The QA engineer runs the script on the QA database, starts testing the SBI from the beginning, and then confirms that the system is "back to normal".
&lt;/p&gt;

&lt;p&gt;
Both sigh in relief while the SBI is marked as "Done" and the weekend starts. Bliss!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orga4995f2" class="outline-2"&gt;
&lt;h2 id="orga4995f2"&gt;Getting to the root problem&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orga4995f2"&gt;
&lt;p&gt;
Although the day and the sprint goal were saved, I would argue that applying the cleanup script just fixed an issue but left the root problem untouched. And to get to the root problem, let's take a closer look on what happened.
&lt;/p&gt;

&lt;p&gt;
The database issue stems from the fact that instead of being kept as close as possible to production data (as the best practices suggest) the database grew to become an entity of its own through not being kept tidy by the team.
&lt;/p&gt;

&lt;p&gt;
When testing a SBI involves changing some of the data from the database, it is not very often that those changes are reverted as soon as the SBI leaves the QA environment. With each such change the two databases (production and QA) grow further and further apart, and the probability of having to apply a workaround script increases each time. However  the paradox is that the cleanup script, although it solves the issue, is &lt;i&gt;yet another change to the data&lt;/i&gt; which widens even more the gap between QA and production databases.
&lt;/p&gt;

&lt;p&gt;
And there lies our problem: not within the workaround script itself, but within the practice of applying workarounds to patch the proverbial broken pipes instead of building actual deployment pipelines.
&lt;/p&gt;

&lt;p&gt;
But this problem goes one level deeper; sure, we can fix the problem at hand by restoring the database from a production backup but to solve the issue once and for all we need to change how we look at QA environment.
&lt;/p&gt;

&lt;p&gt;
But our root-cause analysis is not complete yet. We can't just say "let's never apply workarounds" because workarounds are some sort of necessary evil. Let's look at why that is, shall we?
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orged4a61e" class="outline-2"&gt;
&lt;h2 id="orged4a61e"&gt;Why and when do we apply workarounds in production?&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orged4a61e"&gt;
&lt;p&gt;
In Production environment a workaround is applied &lt;i&gt;only in critical situations&lt;/i&gt; due to high risk of breaking the running system by making ad-hoc changes to it.
&lt;/p&gt;

&lt;p&gt;
Unlike the QA environment where, when the system breaks only a few users are affected — namely the QA engineers, when the system halts in Production the costs of the downtime are much, much higher. An improper or forgotten &lt;code&gt;where&lt;/code&gt; condition in a delete script which wipes out whole tables of data, and renders the system unusable, in the happiest case will lead only to frustrated customers that can't use the thing they paid for.
&lt;/p&gt;

&lt;p&gt;
As such, in every critical situation first and foremost comes the assessment: is a workaround really needed?
&lt;/p&gt;

&lt;p&gt;
When the answer is yes (i.e., there is no other way of fixing the issue now), then &lt;i&gt;usually&lt;/i&gt; there are some procedures to follow. Sticking with the database script example, the minimal procedure would be to:
&lt;/p&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;create the workaround script,&lt;/li&gt;
&lt;li&gt;have that script &lt;i&gt;reviewed and approved by at least one additional person&lt;/i&gt;, and&lt;/li&gt;
&lt;li&gt;have the script executed on Production by someone with proper access rights.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
OK, now we're settled: workarounds are necessary &lt;i&gt;in critical situations&lt;/i&gt;, and are applied after &lt;i&gt;assessment&lt;/i&gt;, &lt;i&gt;review&lt;/i&gt;, and &lt;i&gt;approval&lt;/i&gt;. Then, going back to our story, the following question arises:
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org0262d2f" class="outline-2"&gt;
&lt;h2 id="org0262d2f"&gt;Why do we apply workarounds in QA environment?&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org0262d2f"&gt;
&lt;p&gt;
QA environment is isolated from Production environment, and by definition it has way fewer users. Furthermore, those users have a lot of technical knowledge of how the system runs, and always have something else to do (like designing/writing test cases) while the system is being brought to normal again.
&lt;/p&gt;

&lt;p&gt;
Looking from this point of view, there is almost never a &lt;i&gt;critical&lt;/i&gt; situation that would require applying a workaround in QA environment.
&lt;/p&gt;

&lt;p&gt;
Sure, missing the sprint goal may seem like a critical situation because commitments are important. But on the other hand, and going back to our example — if we're applying a workaround in QA just to promote some feature towards Production, are we &lt;i&gt;really&lt;/i&gt; sure that the feature is ready?
&lt;/p&gt;

&lt;p&gt;
Now that the assessment of criticality is done, let's get back to our topic and ask:
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org1018764" class="outline-2"&gt;
&lt;h2 id="org1018764"&gt;What if we treated QA environment like Production?&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org1018764"&gt;
&lt;p&gt;
Production and QA environments are different (&lt;i&gt;very&lt;/i&gt; different I may add); there's no doubt about that. What makes them different, from the point of view of our topic, is the fact that when a feature is deployed in Production environment, &lt;i&gt;all&lt;/i&gt; the prerequisites are known, and all preliminary steps are executed.
&lt;/p&gt;

&lt;p&gt;
On the other hand, when deploying to QA environment we don't always have this knowledge, nor do we have all the preliminary steps completed at all times. Furthermore, deploying on QA may require additional steps than on Production, e.g.: restoring the database to the last backup from Production, data anonymization etc.
&lt;/p&gt;

&lt;p&gt;
But the difference between the number of unknowns can be compensated by the difference between number of deployments, and the fact that a failure in QA environment is not critical. In other words, what we lack in knowledge when deploying to QA environment can be compensated by multiple deployment trials, where each deployment trial gets closer and closer to success.
&lt;/p&gt;

&lt;p&gt;
And when it comes to doing repetitive tasks…
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org1ac100a" class="outline-2"&gt;
&lt;h2 id="org1ac100a"&gt;Automation is key&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org1ac100a"&gt;
&lt;p&gt;
To alleviate the difference between (successive) environments you only need to do one thing, although I must say from the start that achieving that one thing &lt;i&gt;can be really hard&lt;/i&gt; — &lt;b&gt;automate everything&lt;/b&gt;.
&lt;/p&gt;

&lt;p&gt;
If a release workflow is properly (read &lt;i&gt;fully&lt;/i&gt;) automated, then the difference between various environments is reduced mainly to:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;The group of people who have proper access rights to run the workflow on the specific environment. With today's' tools on the market the difference becomes simplified further — it is in the group of people that are allowed to see or to push the "Deploy" button.&lt;/li&gt;
&lt;li&gt;The number and order of "Deploy" buttons a person has to push for the deploy to succeed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Although we strive to have our environments behave all the same, they are still inherently different. As such, it goes without saying that not everyone may have rights to deploy to Production, and — due to some constraints — on some environment there may be additional actions required to deploy. Nonetheless, the objective remains the same: &lt;i&gt;avoid manual intervention as much as possible&lt;/i&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgfa9d108" class="outline-2"&gt;
&lt;h2 id="orgfa9d108"&gt;The Snowball Effect&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orgfa9d108"&gt;
&lt;p&gt;
Once achieved, the effects of this objective of having minimal manual intervention ripple through and start a &lt;a href="https://en.wikipedia.org/wiki/Snowball_effect"&gt;snowball effect&lt;/a&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id="outline-container-org34a3851" class="outline-3"&gt;
&lt;h3 id="org34a3851"&gt;Efficiency&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-org34a3851"&gt;
&lt;p&gt;
At first, you gain efficiency — there is no checklist to go through when deploying, no time needed to spend doing the tedious steps of deployment; the computers will perform those steps as quickly as possible and &lt;i&gt;always&lt;/i&gt; in the same order without skipping any of them or making the errors that humans usually do when performing tedious work.
&lt;/p&gt;

&lt;p&gt;
With a click of a button, or on a certain event the deployment starts and while it runs the people from the team are free to do whatever they want in the time it takes to deploy: they can have a cup of coffee, can make small talk with a colleague, or can mind the more important business like the overall quality of the product they're working on.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org68101f8" class="outline-3"&gt;
&lt;h3 id="org68101f8"&gt;Speed&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-org68101f8"&gt;
&lt;p&gt;
Furthermore, besides efficiency you can gain speed — just by delegating the deployment process to computers you gain time because computers do boring stuff a lot quicker than humans.
&lt;/p&gt;

&lt;p&gt;
With efficiency and speed comes reduced &lt;a href="https://martinfowler.com/articles/branching-patterns.html#integration-friction"&gt;integration friction&lt;/a&gt;. A common effect of reduced integration friction is an increase in integration frequency. High integration frequency coupled with workflow automation leads to an increase in the number of deployments that are made.
&lt;/p&gt;

&lt;p&gt;
And this is where the magic unravels.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgef0dd86" class="outline-3"&gt;
&lt;h3 id="orgef0dd86"&gt;Tight feedback loop&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-orgef0dd86"&gt;
&lt;p&gt;
Once you automate the repetitive tasks you free-up the time of the QA engineer, which allows him/her to spend more time with the system(s) they are testing. In other words, the time gained through workflow automation is invested into the actual Quality Assurance of the system under test.
&lt;/p&gt;

&lt;p&gt;
And when the QA engineer invests more time into the testing process, he/she will be able to spot more issues. With enough repetitions enabled by quick deployments, the QA engineer acquires a certain amount of skills which will enable him/her to spot defects faster. The sooner a defect is spotted, the sooner it is reported, and subsequently, the sooner it gets fixed.
&lt;/p&gt;

&lt;p&gt;
We have a name for this thing — it's called a &lt;i&gt;feedback loop&lt;/i&gt;. The feedback loop is not introduced by automation — it was long present in the project, but once workflow automation is introduced it tightens the feedback loop, which means we, as developers, have to wait less time to see the effects of the changes we introduced into the system. In our specific case, we have to wait less because workflow automation reduces the time of the deployment to QA environment to minimum.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orga0e7f5d" class="outline-3"&gt;
&lt;h3 id="orga0e7f5d"&gt;Improved user experience&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-orga0e7f5d"&gt;
&lt;p&gt;
But wait, there's more! The time that the QA engineer gets to invest into growing his/her skills is spent using the system under test. With more time spent using the system under test, the QA engineer gets closer and closer to the mindset of the real users of the system. And while in this mindset, the QA engineer not only understands what the system does for the user but also understands what the user wants to do.
&lt;/p&gt;

&lt;p&gt;
Of course, this understanding is bound by a certain maximum but nonetheless, the effect it has on the development process is enormous.
&lt;/p&gt;

&lt;p&gt;
First and foremost, there is an increase in the quality of the system: when the QA engineers have a sound understanding of what the user wants to do they will make sure that the system indeed caters to the needs of its users. This in itself is a huge win for the users alone but this also benefits the entire team — the knowledge about the system gets disseminated within the whole team (including developers), and the Product Owner (PO) is not  the bottleneck anymore.
&lt;/p&gt;

&lt;p&gt;
Furthermore, with more time spent in the mindset of a user, the QA engineer will start striving for an improved user experience because he/she, like the real users of the system, will strive to do thing faster.
&lt;/p&gt;

&lt;p&gt;
As such, the QA engineer starts suggesting some usability improvements of the system. These improvements are small — e.g., change the order of the menu items, add the ability to have custom shortcuts on the homepage etc, but they do improve the experience of the user.
&lt;/p&gt;

&lt;p&gt;
Sure, all of those changes must be  discussed with the team &lt;i&gt;and&lt;/i&gt; approved by the PO but those who get approved bring the system closer to what the &lt;i&gt;actual users&lt;/i&gt; want.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org6f83ced" class="outline-2"&gt;
&lt;h2 id="org6f83ced"&gt;Allow the QA engineer to be an user of the system&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org6f83ced"&gt;
&lt;p&gt;
The main role of a QA engineer is to ensure that the system under test satisfies the needs of its users. As such, the QA engineer needs to think like a user, to act like a user, and to be able to quickly shift from the mindset of the user to the mindset of the problem analyst required by the job description.
&lt;/p&gt;

&lt;p&gt;
But if you take from the QA engineer all the hassle of deployment and fiddling with making the system run properly in the testing environment you are unlocking more time for him/her to spend in the mindset of an actual user, and having a user of the system close by is a treasure trove for building it in such a way that the system accomplishes its purpose — catering to the needs of his users.
&lt;/p&gt;

&lt;p&gt;
As a developer, it may be strange to look at your colleague — the QA engineer — like at an user of the system you're both working on. After all, you both know a lot more of what's under the hood of that system for any of you to be considered just a simple user of it.
&lt;/p&gt;

&lt;p&gt;
But it is a change worth making. And, as the saying goes, to change the world you need to start with changing yourself. This change comes when you treat QA environment as production environment and make all the efforts needed to uphold the delivery to QA to the same rigor as delivery to production. In essence, it's nothing but a shift in the mindset that was already mentioned in the title — don't release to Production, release to QA.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><guid>https://rebeja.eu/posts/release-to-qa-not-production/</guid><pubDate>Tue, 29 Nov 2022 12:14:25 GMT</pubDate></item><item><title>Keep the tools separate from the domain of your application</title><link>https://rebeja.eu/posts/separate-tools-from-domain/</link><dc:creator>Petru Rebeja</dc:creator><description>&lt;p&gt;
At my previous job we had an Architecture club where we held regular meetings to discuss issues related to the architectural decisions of various applications, be it an application developed within the company or elsewhere. One of the latest topics discussed within the architecture club was whether to use or not MediatR (and implicitly the &lt;code&gt;Mediator&lt;/code&gt; pattern) in a project based on &lt;code&gt;CQRS&lt;/code&gt; architecture.
&lt;/p&gt;

&lt;p&gt;
If you're not familiar with &lt;a href="https://github.com/jbogard/MediatR"&gt;MediatR&lt;/a&gt;, it's a library that relays messages to their destination in an easy to use and elegant manner in two ways: it dispatches requests to their handlers and sends notifications to subscribers.
&lt;/p&gt;

&lt;p&gt;
The &lt;code&gt;Mediator&lt;/code&gt; pattern itself is &lt;a href="https://www.dofactory.com/net/mediator-design-pattern"&gt;defined&lt;/a&gt; as follows:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
I'm going to step a bit back and give some additional context regarding this meeting. I wasn't able to attend the meetings of the club since mid February because the meetings overlapped with a class I teach. In an afternoon my colleague George, the founder of the club, told me that the topic of the next meeting will be whether to use or not MediatR and knowing that I use MediatR on my side project it would be nice for me to weigh-in my opinion.
&lt;/p&gt;

&lt;p&gt;
At first, I must confess, I was taken aback — for me there was never a doubt; MediatR is a great tool and &lt;span class="underline"&gt;should&lt;/span&gt; be used in a CQRS architecture. This is why I said I would really like to hear what other members have to say — especially those opposing the use of MediatR.
&lt;/p&gt;

&lt;p&gt;
As the discussion went on I concluded that the problem wasn't whether to use or not to use MediatR but rather &lt;i&gt;how it was used&lt;/i&gt;. And it was used as the centerpiece of the big ball of mud.
&lt;/p&gt;

&lt;p&gt;
The discussion started with back-referencing a presentation at a local IT event, where the same topic was put upfront: &lt;b&gt;to use or not to use MediatR&lt;/b&gt;? Afterwards, the focus of the discussion switched to a project where the mediator pattern was imposed to be used for &lt;i&gt;every&lt;/i&gt; call pertaining to business logic and even more than that — even the calls to &lt;a href="https://github.com/jbogard/automapper"&gt;&lt;code&gt;AutoMapper&lt;/code&gt;&lt;/a&gt; were handled via the mediator. In other words, the vast majority of what should have been simple method calls became calls to &lt;code&gt;mediator.Send(new SomeRequest{...})&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
In order to avoid being directly coupled to &lt;code&gt;MediatR&lt;/code&gt; library the project was hiding the original &lt;code&gt;IMediator&lt;/code&gt; interface behind a custom interface (let's call it &lt;code&gt;ICustomMediator&lt;/code&gt;) thus ensuring a low coupling to the original interface. The problem is that, although the initial intention was good, the abundance of calls to the custom mediator creates a dependency of application modules upon the custom defined interface. And this is wrong.
&lt;/p&gt;

&lt;p&gt;
Why is that wrong?, you may ask. After all, the &lt;code&gt;Dependency Inversion principle&lt;/code&gt; explicitly states that "classes should depend on interfaces" and since in the aforementioned project classes depend on an &lt;code&gt;ICustomMediator&lt;/code&gt; interface which doesn't change even when the original interface changes then it's all good, right?
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Wrong&lt;/b&gt;. That project &lt;i&gt;did not avoid coupling&lt;/i&gt;, it just changed the contract it couples to from an interface defined in a third-party library to an interface defined within. That's it; it is still tightly coupled with a single interface. Even worse, that interface has become the centerpiece of the whole application, the &lt;i&gt;God service&lt;/i&gt;, which hides the target from the caller behind at least two (vertical) layers and tangles the operations of a business transaction into a big ball of mud. While doing so, it practically obliterates the boundaries between the modules which changes application modules from being highly cohesive pieces to lumps of code which "belong together".
&lt;/p&gt;

&lt;p&gt;
Furthermore, and this is the worst part, the &lt;code&gt;ICustomMediator&lt;/code&gt; has changed its role from being a tool which relays commands to their respective handlers to being part of the application domain, i.e. the role of mediator changed from &lt;i&gt;implementation detail&lt;/i&gt; to &lt;i&gt;first class citizen&lt;/i&gt; of the application. This shift is subtle but dangerous and not that easy to observe because the change creeps in gradually akin to the gradual increase of the temperature of water in the &lt;a href="https://en.wikipedia.org/wiki/Boiling_frog"&gt;boiling frog&lt;/a&gt; fable.
&lt;/p&gt;

&lt;p&gt;
The shift happens because all the classes that need to execute a business operation which is not available as a method to invoke will have a reference to the mediator in order to call the aforementioned operation. As per &lt;a href="https://en.wikipedia.org/wiki/Law_of_Demeter"&gt;Law of Demeter&lt;/a&gt; (only talk to your immediate friends) that makes the &lt;code&gt;ICustomMediator&lt;/code&gt; a friend of &lt;i&gt;all&lt;/i&gt; the classes involved in implementing some business logic. And a friend of a domain object (entity, service etc.) &lt;i&gt;is a domain object&lt;/i&gt; itself. Or at least it should be.
&lt;/p&gt;

&lt;p&gt;
OK, you might say, then what's the &lt;i&gt;right&lt;/i&gt; way to use the mediator here? I'm glad you asked. Allow me to explain myself by taking (again) a few steps back.
&lt;/p&gt;

&lt;p&gt;
Ever since I discovered &lt;b&gt;MediatR&lt;/b&gt; I've seen it as the &lt;b&gt;great tool&lt;/b&gt; it is. I remember how, while pondering upon the examples from  MediatR documentation and how I could adapt those for my project I started running some potential usage scenarios in my head. After a short time some clustering patterns started to emerge from those usage scenarios. The patterns weren't that complicated — a handler that handles a payment registration should somehow belong together with a handler that queries the balance of an account, whereas the handler that deals with customer information should belong somewhere else.
&lt;/p&gt;

&lt;p&gt;
These patterns are nothing else than a high degree of cohesion between each of the classes implementing the &lt;code&gt;IHandler&lt;/code&gt; interface from MediatR and to isolate them I've organized each such cluster into a separate assembly.
&lt;/p&gt;

&lt;p&gt;
Having done that another pattern emerged from all the handlers within an assembly: each of the handlers were handling an operation of a single service.
&lt;/p&gt;

&lt;p&gt;
Obviously, the next logical thing was to actually define the service interface which listed all the operations performed by the handlers within that assembly. And since the interface needs an implementation I've created a class for each service which calls &lt;code&gt;mediator.Send()&lt;/code&gt; with the proper parameters for the specific handler and returns the results. This is how it looks:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IAccountingService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;RegisterPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RegisterPaymentCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;paymentDetails&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;GetAccountBalanceResponse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;GetAccountBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetAccountBalanceRequest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;GetAllPaymentsResponse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;GetAllPayments&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;AccountingService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IAccountingService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;readonly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IMediator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_mediator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;AccountingService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IMediator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mediator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;_mediator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mediator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;RegisterPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RegisterPaymentCommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;paymentDetails&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;_mediator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentDetails&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetAccountBalanceResponse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;GetAccountBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetAccountBalanceRequest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_mediator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetAccountBalanceRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetAllPaymentsResponse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;GetAllPayments&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_mediator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetAllPaymentsRequest&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
As a result I &lt;i&gt;do have more boilerplate code&lt;/i&gt; but on the upside I have:
&lt;/p&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;A separation of the domain logic from the plumbing handled by MediatR. If I want to switch the interface implemented by each handler I can use search and replace with a regex and I'm done.&lt;/li&gt;
&lt;li&gt;A cleaner service interface. For the service above, the handler that returns all payments should look like this:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GetAllPaymentsRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GetAllPaymentsResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GetAllPaymentsResponse&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Payments&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetAllPaymentsRequestHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RequestHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GetAllPaymentsRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetAllPaymentsResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;protected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetAllPaymentsResponse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetAllPaymentsRequest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
In order to call this handler you must provide an empty instance of &lt;code&gt;GetAllPaymentsRequest&lt;/code&gt; to mediator but such restriction doesn't need to be imposed on the service interface. Thus, the consumer of &lt;code&gt;IAccountingService&lt;/code&gt; calls &lt;code&gt;GetAllPayments()&lt;/code&gt; without being forced to provide an empty instance which, from consumers' point of view, is useless.
&lt;/p&gt;

&lt;p&gt;
However, the greatest benefit from introducing this new service is that &lt;i&gt;it is a domain service&lt;/i&gt; and does not break the Law of Demeter while abstracting away the technical details. Whichever class will have a reference to an instance of &lt;code&gt;IAccountingService&lt;/code&gt;, it will be working with something pertaining to the &lt;code&gt;Accounting&lt;/code&gt; domain thus when invoking a method from the &lt;code&gt;IAccountingService&lt;/code&gt; &lt;i&gt;it will call a friend&lt;/i&gt;.
&lt;/p&gt;

&lt;p&gt;
This pattern also makes the code a lot more understandable. Imposing a service over the handlers that are related to each-other unifies them and makes their purpose more clear. It's easier to understand that I need to call &lt;code&gt;subscriptionsService&lt;/code&gt; to get a subscription but it becomes a little more cluttered when I call &lt;code&gt;mediator.Send(new GetSubscriptionRequest{SubscriptionId = id})&lt;/code&gt; because it raises a lot of questions. Who gives me that subscription in the end and where it resides? Is this a database call or a network call? And who the hell is this &lt;code&gt;mediator&lt;/code&gt; dude?
&lt;/p&gt;

&lt;p&gt;
Of course, the first two questions may rise when dealing with any interface and they should be always on the mind of programmers because the implementation may affect the performance, but performance concerns aside, it's just easier to comprehend the relationships and interactions when all the details fit together. And in a class dealing with &lt;code&gt;Accounting&lt;/code&gt; domain a call to &lt;code&gt;mediator&lt;/code&gt; just doesn't fit.
&lt;/p&gt;

&lt;p&gt;
Back to the main point, there's the question of what if I &lt;i&gt;need&lt;/i&gt; to make a request through a queue (&lt;code&gt;RabbitMq&lt;/code&gt; for example)? Let's assume I have a class which needs to get some details using a call to mediator but afterwards needs to write some data to a queue within the same business transaction. In such case, I have to either:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;inject into my class an instance that knows how to talk to the queue and an instance of mediator or&lt;/li&gt;
&lt;li&gt;have another mediator handler which does the write and perform two separate calls to mediator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
By doing this I'm polluting the application logic with entities like mediator, queue writer etc., entities which are pertaining to application infrastructure not application domain. In other words, they are tools not building blocks. And tools should be replaceable. But how do I replace them if I have references to them scattered all over the code-base? With maximum effort, as Deadpool says.
&lt;/p&gt;

&lt;p&gt;
This is why you need to separate tools from application domain. And this is how I achieved this separation: by hiding the implementation details (i.e. tooling) behind a service interface which brings meaning to the domain. This way, when you change the tools, the meaning (i.e. intention) stays the same.
&lt;/p&gt;


&lt;p&gt;
&lt;b&gt;Acknowledgments&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
I would like to thank my colleagues for their reviews of this blog post. Also a big thank you goes to all the members of Centric Architecture Club for starting the discussion which led to this blog post.
&lt;/p&gt;</description><guid>https://rebeja.eu/posts/separate-tools-from-domain/</guid><pubDate>Mon, 22 Jun 2020 13:56:02 GMT</pubDate></item><item><title>Building a Python IDE with Emacs and Docker</title><link>https://rebeja.eu/posts/python-ide-with-emacs-and-docker/</link><dc:creator>Petru Rebeja</dc:creator><description>&lt;div id="outline-container-org327f678" class="outline-2"&gt;
&lt;h2 id="org327f678"&gt;Prologue&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org327f678"&gt;
&lt;p&gt;
I am a fan of &lt;a href="https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux"&gt;&lt;code&gt;Windows Subsystem for Linux&lt;/code&gt;&lt;/a&gt;. It brings the power of Linux command-line tools to Windows which is something a developer cannot dislike but that isn't the main reason I'm fond of it. I like it because it allows me to run Emacs (albeit in console mode) at its full potential.
&lt;/p&gt;

&lt;p&gt;
As a side-note, on my personal laptop I use Emacs on Ubuntu whereas on the work laptop I use Emacs from Cygwin. And although Cygwin does a great job in providing the powerful Linux tools on Windows, some of them are really slow compared to the native ones. An example of such a tool is &lt;code&gt;git&lt;/code&gt;. I heavily use &lt;a href="https://magit.vc/manual/magit"&gt;&lt;code&gt;Magit&lt;/code&gt;&lt;/a&gt; for a lot of my projects but working with it in Emacs on Cygwin is a real pain. Waiting for a simple operation to finish knowing that the same operation completes instantly on Linux is exhausting. Thus, in order to avoid such unpleasant experience whenever I would need to use Magit I would use it from Emacs in &lt;code&gt;Ubuntu Bash on Windows&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Furthermore, I use &lt;code&gt;Ubuntu Bash on Windows&lt;/code&gt; to work on my Python projects simply because I can do everything from within Emacs there — from editing input files in &lt;code&gt;csv-mode&lt;/code&gt;, to writing code using &lt;code&gt;elpy&lt;/code&gt; with &lt;code&gt;jedi&lt;/code&gt; and pushing the code to a GitHub repo using &lt;code&gt;magit&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
All was good until an update for Windows &lt;a href="https://github.com/microsoft/terminal/issues/210"&gt;messed up the console output on &lt;code&gt;WSL&lt;/code&gt;&lt;/a&gt; which rendered both my Python setup and Emacs unusable. And if that wasn't bad enough, I got affected by this issue before a very important deadline for one of the Python projects.
&lt;/p&gt;

&lt;p&gt;
Faced with the fact that there nothing I could do at that moment to fix the console output and in desperate need for a solution, I asked myself:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Can't I create the same setup as in &lt;code&gt;WSL&lt;/code&gt; using &lt;code&gt;Docker&lt;/code&gt;?
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
The answer is &lt;b&gt;Yes&lt;/b&gt;. If you want to see only the final &lt;code&gt;Dockerfile&lt;/code&gt;, head directly to the &lt;a href="https://rebeja.eu/posts/python-ide-with-emacs-and-docker/#tldr"&gt;&lt;b&gt;TL;DR&lt;/b&gt;&lt;/a&gt; section. Otherwise, please read along. In any case — thanks for reading!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org6a4b1ba" class="outline-2"&gt;
&lt;h2 id="org6a4b1ba"&gt;How&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org6a4b1ba"&gt;
&lt;p&gt;
Since I already have been using Emacs as a Python IDE in Ubuntu Bash, replicating this setup in Docker would imply:
&lt;/p&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;Providing remote access via &lt;code&gt;ssh&lt;/code&gt; to the container and&lt;/li&gt;
&lt;li&gt;Installing the same packages for both the OS and Emacs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
I already knew more or less how to do the later (or so I thought) so obviously I started with the former: ssh access to a Docker container.
&lt;/p&gt;

&lt;p&gt;
Luckily, Docker already has an &lt;a href="https://docs.docker.com/engine/examples/running_ssh_service/"&gt;example of running &lt;code&gt;ssh&lt;/code&gt; service&lt;/a&gt; so I started with the Dockerfile provided there. I copied the instructions into a local Dockerfile, built the image and ran the container. But when I tried to connect to the container I ran into the first issue addressed in this post:
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgf231677" class="outline-2"&gt;
&lt;h2 id="orgf231677"&gt;Issue #1: SSHD refuses connection&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orgf231677"&gt;
&lt;p&gt;
This one was easy — there's a typo in the example provided by Docker. I figured it out after inspecting the contents of &lt;code&gt;sshd_config&lt;/code&gt; file.
&lt;/p&gt;

&lt;p&gt;
After a while I noticed that the line containing &lt;code&gt;PermitRootlogin&lt;/code&gt; was commented-out and thus &lt;code&gt;sed&lt;/code&gt; wasn't able to match the pattern and failed to replace the permission.
&lt;/p&gt;

&lt;p&gt;
Since I was connecting as &lt;code&gt;root&lt;/code&gt; the &lt;code&gt;sshd&lt;/code&gt; refused connection.
&lt;/p&gt;

&lt;p&gt;
The fix for this is to include the &lt;code&gt;#&lt;/code&gt; in the call to &lt;code&gt;sed&lt;/code&gt; as below:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;RUN&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'s/#PermitRootLogin prohibit-password/PermitRootLogin yes/'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/ssh/sshd_config
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Having done the change, I rebuilt the image and started the container. As the tutorial mentioned, I ran in console &lt;code&gt;docker port &amp;lt;container-name&amp;gt; 22&lt;/code&gt;. This command gave me the port on which to connect so I ran &lt;code&gt;ssh root@localhost -p &amp;lt;port&amp;gt;&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Success.
&lt;/p&gt;

&lt;p&gt;
Even though the &lt;code&gt;sshd&lt;/code&gt; was running and accepting connections, the fact that the root password was hard-coded in plain text &lt;i&gt;really&lt;/i&gt; bothered me so I made a small tweak to the &lt;code&gt;Dockerfile&lt;/code&gt;:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;ARG&lt;span class="w"&gt; &lt;/span&gt;password

&lt;span class="w"&gt;  &lt;/span&gt;RUN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"root:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;chpasswd
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
What this does is it declares a variable &lt;code&gt;password&lt;/code&gt; whose value is supplied when building the image like this:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;image-tag&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;--build-arg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-password-here&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;.
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
This way, the root password isn't stored in clear text and in plain-sight anymore. Now I was ready to move to the next step.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org4d83181" class="outline-2"&gt;
&lt;h2 id="org4d83181"&gt;Issue #2: Activating virtual environment inside container&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org4d83181"&gt;
&lt;p&gt;
The second item of my quest was to setup and activate a Python virtual environment. This environment will be used to install all the dependencies required for the project I'm working on.
&lt;/p&gt;

&lt;p&gt;
Also, this environment will be used by Emacs and &lt;code&gt;elpy&lt;/code&gt; to provide the features of an IDE.
&lt;/p&gt;

&lt;p&gt;
A this point I asked myself: do I actually need a virtual environment? The Ubuntu Docker image comes with Python preinstalled so why not install the dependencies system-wide? After all, Docker containers and images are somewhat disposable — I can always recreate the image and start a new container for another project.
&lt;/p&gt;

&lt;p&gt;
I decided I &lt;i&gt;need&lt;/i&gt; a virtual environment because otherwise things would get messy and I like well organized stuff.
&lt;/p&gt;

&lt;p&gt;
So I started looking out how to setup and activate a virtual environment inside a Docker container. And by looking up I mean googling it or, in my case — googling it with Bing.
&lt;/p&gt;

&lt;p&gt;
I got lucky since one of the first results was the article that led to my solution: &lt;a href="https://pythonspeed.com/articles/activate-virtualenv-dockerfile/"&gt;Elegantly activating a virtualenv in a Dockerfile&lt;/a&gt;. It has a great explanation of what needs to be done and what's going under the hood when activating a virtual environment.
&lt;/p&gt;

&lt;p&gt;
The changes pertaining to my config are the following:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;ENV&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;VIRTUAL_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/venv
&lt;span class="w"&gt;  &lt;/span&gt;RUN&lt;span class="w"&gt; &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;virtualenv&lt;span class="w"&gt; &lt;/span&gt;--python&lt;span class="o"&gt;=&lt;/span&gt;/usr/bin/python3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;ENV&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;RUN&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--upgrade&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;setuptools&lt;span class="w"&gt; &lt;/span&gt;wheel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;numpy&lt;span class="w"&gt; &lt;/span&gt;tensorflow&lt;span class="w"&gt; &lt;/span&gt;scikit-learn&lt;span class="w"&gt; &lt;/span&gt;gensim&lt;span class="w"&gt; &lt;/span&gt;matplotlib&lt;span class="w"&gt; &lt;/span&gt;pyyaml&lt;span class="w"&gt; &lt;/span&gt;matplotlib-venn&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;elpy&lt;span class="w"&gt; &lt;/span&gt;jedi&lt;span class="w"&gt; &lt;/span&gt;rope&lt;span class="w"&gt; &lt;/span&gt;yapf&lt;span class="w"&gt; &lt;/span&gt;importmagic&lt;span class="w"&gt; &lt;/span&gt;flake8&lt;span class="w"&gt; &lt;/span&gt;autopep8&lt;span class="w"&gt; &lt;/span&gt;black
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
As described in the article linked above, activating a Python virtual environment in its essence is just setting some environment variables.
&lt;/p&gt;

&lt;p&gt;
What the solution above does is to define where the virtual environment will be created and store it into the &lt;code&gt;VIRTUAL_ENV&lt;/code&gt; variable. Next, create the environment at the specified path using &lt;code&gt;python3 -m virtualenv $VIRTUAL_ENV&lt;/code&gt;. The &lt;code&gt;--python=/usr/bin/python3&lt;/code&gt; argument just makes sure that the python interpreter to use is indeed &lt;code&gt;python3&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Activating the virtual environment means just prepending its &lt;code&gt;bin&lt;/code&gt; directory to the &lt;code&gt;PATH&lt;/code&gt; variable: &lt;code&gt;ENV PATH="$VIRTUAL_ENV/bin:$PATH"&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Afterwards, just install the required packages as usual.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org80f106f" class="outline-2"&gt;
&lt;h2 id="org80f106f"&gt;Issue #3: Emacs monolithic configuration file&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org80f106f"&gt;
&lt;p&gt;
After setting up and activating the virtual environment, I needed to configure Emacs for python development to start working.
&lt;/p&gt;

&lt;p&gt;
Luckily, I have my Emacs (semi-literate) config script in a &lt;a href="https://github.com/repierre/.emacs.d"&gt;GitHub repository&lt;/a&gt; and all I need to do is jut clone the repo locally and everything should work. Or so I thought.
&lt;/p&gt;

&lt;p&gt;
I cloned the repository containing my config, which at that time was just a single file &lt;code&gt;emacs-init.org&lt;/code&gt; bootstrapped by &lt;code&gt;init.el&lt;/code&gt;, logged into the container and started Emacs.
&lt;/p&gt;

&lt;p&gt;
After waiting for all the packages to install I was greeted by a plethora of errors and warnings: some packages were failing to install due to being incompatible with the Emacs version installed in the container, some weren't properly configured to run in console and so on and so forth.
&lt;/p&gt;

&lt;p&gt;
Not willing to spend a lot of time on this (I had a deadline after all) I decided to take a shortcut: why don't I just split the configuration file such that I would be able to only activate packages related to Python development? After all, the sole purpose of this image is to have a setup where I can do some Python development the way I'm used to. Fortunately, this proved to be a good decision.
&lt;/p&gt;

&lt;p&gt;
So I split my &lt;code&gt;emacs-init.org&lt;/code&gt; file into four files: one file for tweaks and packages that I want to have everywhere, one file for &lt;code&gt;org-mode&lt;/code&gt; related stuff, one file for Python development and lastly one file for tweaks and packages that I would like when I'm using Emacs GUI. The &lt;code&gt;init.el&lt;/code&gt; file looked like this:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;'package&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;package-initialize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;org-babel-load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expand-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"~/.emacs.d/common-config.org"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;org-babel-load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expand-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"~/.emacs.d/python-config.org"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;org-babel-load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expand-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"~/.emacs.d/org-config.org"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;org-babel-load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expand-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"~/.emacs.d/emacs-init.org"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Now I can use &lt;code&gt;sed&lt;/code&gt; on the &lt;code&gt;init.el&lt;/code&gt; file to delete the lines that were loading troublesome packages:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/^.*emacs-init.*$/d'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./.emacs.d/init.el&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/^.*org-config.*$/d'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./.emacs.d/init.el
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
After starting a container from the new image I started getting some odd errors about failing to verify package signature. Again, googling the error message with Bing got me a quick-fix: &lt;a href="https://emacs.stackexchange.com/a/53142/14110"&gt;&lt;code&gt;(setq package-check-signature nil)&lt;/code&gt;&lt;/a&gt;. This fix is actually a security risk but since it would be applied to an isolated environment I didn't bother looking for a better way.
&lt;/p&gt;

&lt;p&gt;
However, another problem arose — how can I apply this fix without committing it to the GitHub repository?
&lt;/p&gt;

&lt;p&gt;
Looking back at how I used &lt;code&gt;sed&lt;/code&gt; to remove some lines from &lt;code&gt;init.el&lt;/code&gt; file one of the first ideas that popped into my head was to replace an empty line from &lt;code&gt;init.el&lt;/code&gt; with the quick-fix, but after giving it some more thought I decided to use a more general solution that involves a little bit of (over) engineering.
&lt;/p&gt;

&lt;p&gt;
Since I'm interested in altering Emacs behavior before installing packages it would be good to have a way to inject more Lisp code than a single line. Furthermore, in cases where such code consists of multiple lines I could just add it using Dockers' &lt;code&gt;ADD&lt;/code&gt; command instead of turning into a maintenance nightmare with multiple &lt;code&gt;sed&lt;/code&gt; calls.
&lt;/p&gt;

&lt;p&gt;
Don't get me wrong: &lt;code&gt;sed&lt;/code&gt; is great but I prefer to have large chunks of code in a separate file without the added complexity of them being intertwined with &lt;code&gt;sed&lt;/code&gt; calls.
&lt;/p&gt;

&lt;p&gt;
The solution to this problem is quite simple: before loading configuration files, check if a specific file exists; in my case it would be &lt;code&gt;config.el&lt;/code&gt; (not a descriptive name, I know) located in &lt;code&gt;.emacs.d&lt;/code&gt; directory. If file exists load it. Afterwards load the known configuration files. And since we're doing this, why not do the same for after loading the known configuration files?
&lt;/p&gt;

&lt;p&gt;
Thus, the resulting &lt;code&gt;init.el&lt;/code&gt; looks like this (I promise to fix those names sometimes):
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;'package&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;package-initialize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expand-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"config.el"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;user-emacs-directory&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;file-exists-p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;file-name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;file-name&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;org-babel-load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expand-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"~/.emacs.d/common-config.org"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;org-babel-load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expand-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"~/.emacs.d/python-config.org"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;org-babel-load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expand-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"~/.emacs.d/org-config.org"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;org-babel-load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expand-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"~/.emacs.d/emacs-init.org"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expand-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"after-init.el"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;user-emacs-directory&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;file-exists-p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;file-name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;file-name&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Now I just need to create the file and apply the fix:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(setq package-check-signature nil)"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;./.emacs.d/config.el
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
And since I can run custom code after loading the known configuration files I can set &lt;code&gt;elpy-rpc-virtualenv-path&lt;/code&gt; variable in the same way:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(setq elpy-rpc-virtualenv-path \"&lt;/span&gt;&lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;&lt;span class="s2"&gt;\")"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;./.emacs.d/after-init.el
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
The Dockerfile code for this section is below:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;RUN cd /root/ &amp;amp;&amp;amp; \
    git clone https://github.com/RePierre/.emacs.d.git .emacs.d &amp;amp;&amp;amp; \
    echo "(setq package-check-signature nil)" &amp;gt;&amp;gt; ./.emacs.d/config.el &amp;amp;&amp;amp; \
    sed -i '/^.*emacs-init.*$/d' ./.emacs.d/init.el &amp;amp;&amp;amp; \
    sed -i 's/(shell . t)/(sh . t)/' ./.emacs.d/common-config.org &amp;amp;&amp;amp; \
    sed -i '/^.*org-config.*$/d' ./.emacs.d/init.el &amp;amp;&amp;amp; \
    sed -i 's/\:defer\ t//' ./.emacs.d/python-config.org &amp;amp;&amp;amp; \
    echo "(setq elpy-rpc-virtualenv-path \"$VIRTUAL_ENV\")" &amp;gt;&amp;gt; ./.emacs.d/after-init.el
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
It does one more thing not mentioned previously: a &lt;code&gt;sed&lt;/code&gt; call to remove lazy loading of packages from &lt;code&gt;python-config.org&lt;/code&gt; file.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org7a5d885" class="outline-2"&gt;
&lt;h2 id="org7a5d885"&gt;Issue #4: Using SSH keys to connect to GitHub&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org7a5d885"&gt;
&lt;p&gt;
Now that I have Emacs running on Ubuntu (albeit terminal only) I can enjoy a smooth workflow without having to wait too much for Magit or other application that took forever on Cygwin to finish.
&lt;/p&gt;

&lt;p&gt;
But there's an issue. I mount the repository I'm working on as a separate volume in the Docker container which allows &lt;code&gt;Magit&lt;/code&gt; to read all required info (like user name etc.) directly from the repository. However, I cannot push changes to GitHub because I'm not authorized.
&lt;/p&gt;

&lt;p&gt;
To authorize the current container to push to GitHub I need to generate a pair of keys for the SSH authentication on GitHub. But this can become, again, a maintenance chore: for each new container I need to create the keys, add them to my GitHub account and &lt;b&gt;remember to delete them when I'm finished with the container&lt;/b&gt;.
&lt;/p&gt;

&lt;p&gt;
Instead of generating new keys each time, I decided to reuse the keys I already added to my GitHub account; the image I'm building will not leave my computer so there's no risk of someone getting ahold of my keys.
&lt;/p&gt;

&lt;p&gt;
I found how to do so easily: there's a StackOverflow &lt;a href="https://stackoverflow.com/a/42125241/844006"&gt;answer&lt;/a&gt; for that. Summing it up is that you need to declare two build arguments that will hold the values for the private and public keys and write the values to their respective files. Of course, this implies creating the proper directories and assigning proper rights to the files. As an added bonus, the &lt;a href="https://stackoverflow.com/a/42125241/844006"&gt;answer&lt;/a&gt; shows a way to add GitHub to the known hosts.  This is how it looks in the Dockerfile:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;ARG&lt;span class="w"&gt; &lt;/span&gt;ssh_prv_key
&lt;span class="w"&gt;  &lt;/span&gt;ARG&lt;span class="w"&gt; &lt;/span&gt;ssh_pub_key

&lt;span class="w"&gt;  &lt;/span&gt;RUN&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/root/.ssh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0700&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/root/.ssh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;ssh-keyscan&lt;span class="w"&gt; &lt;/span&gt;github.com&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/root/.ssh/known_hosts
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
To provide the values for the keys use &lt;code&gt;--build-arg&lt;/code&gt; parameter when building your image like this:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;image-tag&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;--build-arg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ssh_prv_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;~/.ssh/id_rsa&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;--build-arg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ssh_pub_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;~/.ssh/id_rsa.pub&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;.
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org926b8c7" class="outline-2"&gt;
&lt;h2 id="org926b8c7"&gt;Issue #5: Install Emacs packages once and done&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org926b8c7"&gt;
&lt;p&gt;
After another build of the Docker image I started a container from it, logged in via ssh into the container, started Emacs and noticed yet another issue.
&lt;/p&gt;

&lt;p&gt;
The problem was that at each start of the container I had to wait for Emacs to download and install all the packages from the configuration files which, as you can guess may take a while.
&lt;/p&gt;

&lt;p&gt;
Since looking-up the answer on the Web did not return any meaningful results I started refining my question to the point where I came-up with the answer. Basically, when after several failed attempts I started typing in the search bar &lt;code&gt;how to load Emacs packages in background&lt;/code&gt; I remembered reading somewhere that Emacs can be used in a client-server setup where the server runs in background.
&lt;/p&gt;

&lt;p&gt;
This is a feature of Emacs called &lt;a href="https://www.emacswiki.org/emacs/EmacsAsDaemon"&gt;daemon mode&lt;/a&gt;. I have never used it myself but went on a whim and decided to try it just to see what would happen.
&lt;/p&gt;

&lt;p&gt;
So I changed my &lt;code&gt;Dockerfile&lt;/code&gt; to start Emacs as a daemon:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;RUN&lt;span class="w"&gt; &lt;/span&gt;emacs&lt;span class="w"&gt; &lt;/span&gt;--daemon
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
And to my great surprise, when rebuilding the image I saw the output of Emacs packages being downloaded and installed.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgff57943" class="outline-2"&gt;
&lt;h2 id="orgff57943"&gt;Issue #6: Terminal colors&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orgff57943"&gt;
&lt;p&gt;
Being confident that everything should work now (it's the same setup I had on &lt;code&gt;WSL&lt;/code&gt;) I started a new container to which I mounted the GitHub repo as a volume and got cracking.
&lt;/p&gt;

&lt;p&gt;
Everything went swell until I decided to commit the changes and invoked &lt;code&gt;magit-status&lt;/code&gt;. Then I got a real eyesore: the colors of the text in the status buffer were making it really hard to understand what changed and where.
&lt;/p&gt;

&lt;p&gt;
At this point I just rage-quit and started looking for an answer. Fortunately, the right &lt;a href="https://stackoverflow.com/a/64585/844006"&gt;StackOverflow answer&lt;/a&gt; popped up quickly and I applied the fix which just sets the &lt;code&gt;TERM&lt;/code&gt; environment variable:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;ENV&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;TERM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xterm-256color
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
And only after this, I was able to fully benefit from having the Python IDE I'm used to on a native platform.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-tldr" class="outline-2"&gt;
&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-tldr"&gt;
&lt;p&gt;
The full Dockerfile described in this post is below:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;FROM&lt;span class="w"&gt; &lt;/span&gt;ubuntu:18.04

RUN&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;--no-install-recommends&lt;span class="w"&gt; &lt;/span&gt;openssh-server&lt;span class="w"&gt; &lt;/span&gt;tmux&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;emacs&lt;span class="w"&gt; &lt;/span&gt;emacs-goodies.el&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;python3-pip&lt;span class="w"&gt; &lt;/span&gt;python3-virtualenv&lt;span class="w"&gt; &lt;/span&gt;python3-dev&lt;span class="w"&gt; &lt;/span&gt;build-essential

ARG&lt;span class="w"&gt; &lt;/span&gt;password

RUN&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;/var/run/sshd
RUN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"root:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;chpasswd
RUN&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'s/#PermitRootLogin prohibit-password/PermitRootLogin yes/'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/ssh/sshd_config

&lt;span class="c1"&gt;# SSH login fix. Otherwise user is kicked off after login&lt;/span&gt;
RUN&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'s@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;/etc/pam.d/sshd

ENV&lt;span class="w"&gt; &lt;/span&gt;NOTVISIBLE&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"in users profile"&lt;/span&gt;
RUN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"export VISIBLE=now"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/profile

&lt;span class="c1"&gt;# From https://pythonspeed.com/articles/activate-virtualenv-dockerfile/&lt;/span&gt;
ENV&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;VIRTUAL_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/venv
RUN&lt;span class="w"&gt; &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;virtualenv&lt;span class="w"&gt; &lt;/span&gt;--python&lt;span class="o"&gt;=&lt;/span&gt;/usr/bin/python3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;
ENV&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
RUN&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--upgrade&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;setuptools&lt;span class="w"&gt; &lt;/span&gt;wheel&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;numpy&lt;span class="w"&gt; &lt;/span&gt;tensorflow&lt;span class="w"&gt; &lt;/span&gt;scikit-learn&lt;span class="w"&gt; &lt;/span&gt;gensim&lt;span class="w"&gt; &lt;/span&gt;matplotlib&lt;span class="w"&gt; &lt;/span&gt;pyyaml&lt;span class="w"&gt; &lt;/span&gt;matplotlib-venn&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;elpy&lt;span class="w"&gt; &lt;/span&gt;jedi&lt;span class="w"&gt; &lt;/span&gt;rope&lt;span class="w"&gt; &lt;/span&gt;yapf&lt;span class="w"&gt; &lt;/span&gt;importmagic&lt;span class="w"&gt; &lt;/span&gt;flake8&lt;span class="w"&gt; &lt;/span&gt;autopep8&lt;span class="w"&gt; &lt;/span&gt;black

RUN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/root/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/RePierre/.emacs.d.git&lt;span class="w"&gt; &lt;/span&gt;.emacs.d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(setq package-check-signature nil)"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;./.emacs.d/config.el&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/^.*emacs-init.*$/d'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./.emacs.d/init.el&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'s/(shell . t)/(sh . t)/'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./.emacs.d/common-config.org&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/^.*org-config.*$/d'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./.emacs.d/init.el&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'s/\:defer\ t//'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./.emacs.d/python-config.org&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(setq elpy-rpc-virtualenv-path \"&lt;/span&gt;&lt;span class="nv"&gt;$VIRTUAL_ENV&lt;/span&gt;&lt;span class="s2"&gt;\")"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;./.emacs.d/after-init.el

&lt;span class="c1"&gt;# From https://stackoverflow.com/a/42125241/844006&lt;/span&gt;
ARG&lt;span class="w"&gt; &lt;/span&gt;ssh_prv_key
ARG&lt;span class="w"&gt; &lt;/span&gt;ssh_pub_key
&lt;span class="c1"&gt;# Authorize SSH Host&lt;/span&gt;
RUN&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/root/.ssh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0700&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/root/.ssh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;ssh-keyscan&lt;span class="w"&gt; &lt;/span&gt;github.com&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/root/.ssh/known_hosts

&lt;span class="c1"&gt;# Add the keys and set permissions&lt;/span&gt;
RUN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ssh_prv_key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/root/.ssh/id_rsa&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ssh_pub_key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/root/.ssh/id_rsa.pub&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/root/.ssh/id_rsa&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/root/.ssh/id_rsa.pub

RUN&lt;span class="w"&gt; &lt;/span&gt;emacs&lt;span class="w"&gt; &lt;/span&gt;--daemon

&lt;span class="c1"&gt;# Set terminal colors https://stackoverflow.com/a/64585/844006&lt;/span&gt;
ENV&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;TERM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xterm-256color

EXPOSE&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;
CMD&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/usr/sbin/sshd"&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-D"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
To build the image use this command:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;image-tag&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;--build-arg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ssh_prv_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;~/.ssh/id_rsa&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;--build-arg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ssh_pub_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;~/.ssh/id_rsa.pub&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;--build-arg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-password-here&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;.
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-org6aa7a6c" class="outline-2"&gt;
&lt;h2 id="org6aa7a6c"&gt;Epilogue&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org6aa7a6c"&gt;
&lt;p&gt;
Looking back at this sort of quest of mine, I have nothing else to say than it was, overall, a fun experience.
&lt;/p&gt;

&lt;p&gt;
Sure, it also has some additional benefits that are important in my day-to-day life as a developer: I got a bit more experience in building &lt;code&gt;Docker&lt;/code&gt; images and I &lt;i&gt;got to learn a big deal of stuff&lt;/i&gt;. It is also worth noting that this setup did help me a lot in meeting the deadline, a fact which by itself states how much of an improvement this setup is (also taking in consideration the time I've spent to make it work).
&lt;/p&gt;

&lt;p&gt;
But the bottom line is that it was a great deal of fun involved which luckily resulted in a new tool in my shed — while working on this post, I used this setup as the default for all new Python experiments and I will probably use it for future projects as well.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgd687a6f" class="outline-2"&gt;
&lt;h2 id="orgd687a6f"&gt;References&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orgd687a6f"&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/examples/running_ssh_service/"&gt;Dockerize an SSH service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pythonspeed.com/articles/activate-virtualenv-dockerfile/"&gt;Elegantly activating a virtualenv in a Dockerfile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/a/42125241/844006"&gt;SO answer on using SSH keys inside Docker container&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/a/64585/844006"&gt;Setting terminal colors in Emacs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-orgbfd59b1" class="outline-2"&gt;
&lt;h2 id="orgbfd59b1"&gt;Acknowledgments&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orgbfd59b1"&gt;
&lt;p&gt;
I would like to thank my colleague &lt;a href="https://www.linkedin.com/in/ionelabarbuta/"&gt;Ionela Bărbuță&lt;/a&gt; for proofreading this post and for the tips &amp;amp; tricks she gave me in order to improve my writing.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>Docker</category><category>Dockerfile</category><category>Emacs</category><category>IDE</category><category>Python</category><category>ssh</category><guid>https://rebeja.eu/posts/python-ide-with-emacs-and-docker/</guid><pubDate>Tue, 03 Mar 2020 05:19:45 GMT</pubDate></item><item><title>Declutter the way of working</title><link>https://rebeja.eu/posts/declutter-the-way-of-working/</link><dc:creator>Petru Rebeja</dc:creator><description>&lt;p&gt;
Like many other people I strive to be as productive as I can. Being productive means two things for me:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Getting the most out of my tools and,&lt;/li&gt;
&lt;li&gt;Spending less time on useless things.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Getting the most of my tools is the reason I continuously invest in learning &lt;a href="https://www.gnu.org/software/emacs/"&gt;Emacs&lt;/a&gt; (which has proven to have a great return of investment) and in learning &lt;a href="http://visualstudioshortcuts.com/2017/"&gt;Visual Studio shortcuts.&lt;/a&gt; It was for the same reason I was happy like a kid with a chocolate bar when Visual Studio introduced the &lt;code&gt;Ctrl+Q&lt;/code&gt; shortcut for the &lt;code&gt;Quick Launch&lt;/code&gt; menu which allowed me to launch various utilities from Visual Studio without bothering to learn shortcuts that aren't often used and without spending time navigating through the menu items looking for the one I had in mind.
&lt;/p&gt;

&lt;p&gt;
Spending less time on useless things means having a good workflow and &lt;i&gt;I was not happy with mine&lt;/i&gt;. And my workflow was quite simple — after getting to work, I would start my workstation, open Outlook and whatever instant messaging applications I needed to use, open Visual Studio, get latest sources from TFS, open required solutions and start coding. In between any of those steps I would make myself a cup of tea from which I would sip occasionally while working. It took me some time to do all those required steps before being able to actually read, write or debug some piece of code and albeit in time I got ahold of more powerful machines which loaded things faster, I wasn't happy with the sensation of &lt;i&gt;having to wait to start working&lt;/i&gt;.
&lt;/p&gt;

&lt;p&gt;
I started thinking on how to avoid waiting and I turned to the simplest solution for my problem — for every application that I needed to start at the beginning of the day I would put a shortcut in the Windows startup folder. This way, after getting to work I needed to boot my computer, log in and go make the tea while the applications were loading automatically. I couldn't load &lt;i&gt;all&lt;/i&gt; the required applications that way — most of the time I needed to run Visual Studio with elevated permissions which halted the load of other applications due to the UAC settings — but I was happy to open all other applications automatically while making my tea and open Visual Studio manually.
&lt;/p&gt;

&lt;p&gt;
Meanwhile I switched the workstation with a laptop and got the opportunity to work on a data science project at work, alongside the main project I'm assigned to. Having a laptop brings a great deal of flexibility and having a high-performance laptop with great battery life tends to make me want to work on it for &lt;i&gt;all&lt;/i&gt; my projects.
&lt;/p&gt;

&lt;p&gt;
And that's when things started to get complicated workflow-wise. The two projects I work on at my job have different technology stacks (&lt;code&gt;C#&lt;/code&gt; with &lt;code&gt;.net core&lt;/code&gt; on the main project and &lt;code&gt;Python&lt;/code&gt; with &lt;code&gt;Azure ML&lt;/code&gt; for the data science one) which means different workflows but still using the same applications for communication and other secondary tasks. In my spare time — early in the morning or late at night — I work on personal projects and that's when I feel the most infuriated with the plethora of applications that are starting automatically but are totally useless at that moment and do nothing more than consume resources.
&lt;/p&gt;

&lt;p&gt;
At some point I realized that the time I used to spend a while ago to open the applications I needed, I now waste on closing the applications which are configured to start automatically but are of no use to me. Then I remembered that a while ago I read a &lt;a href="https://bash.im/quote/436725"&gt;story about Russian DevOps engineer who would automate a task if it required more that 1.5 minutes of his time&lt;/a&gt; (the English version and implementations of the scripts are available on &lt;a href="https://github.com/NARKOZ/hacker-scripts"&gt;GitHub&lt;/a&gt;). That story got me thinking:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
Can I change which applications are loaded automatically based on the project I'm working?
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Unfortunately, the answer is &lt;b&gt;no&lt;/b&gt;. That's because my laptop won't know on which project I'll be working next. But my schedule might give a hint: all week except Thursday, from 9:00 to 18:00 I work on the main project at my job, on Thursdays from 9:00 to 18:00 I work on a secondary project and outside business hours I work on my other projects.
&lt;/p&gt;

&lt;p&gt;
OK, and how do I use that information? Up until now I used to place shortcuts in Windows startup folder but that doesn't do it for me anymore. The problem with placing shortcuts in Windows startup folder is that there's no way to specify &lt;i&gt;when&lt;/i&gt; to start the application — it will start all the time.
&lt;/p&gt;

&lt;p&gt;
So I had to look elsewhere for a solution. The next place I looked was Windows Task Scheduler which provides more options for starting a task but unfortunately the triggers of Task Scheduler are either too simple to encode the ranges from my schedule or too complicated to bother with.
&lt;/p&gt;

&lt;p&gt;
Thinking of how to make this decision simple I turned to PowerShell. I created two scripts, in each of them testing the following conditions:
&lt;/p&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Is current time between 9:00 and 18:00 and current day is a work day but not Thursday? If yes, then this means I'm at my job, working for the main project and thus:
&lt;ul class="org-ul"&gt;
&lt;li&gt;The first script will:
&lt;ul class="org-ul"&gt;
&lt;li&gt;navigate to the directory mapped to TFS project,&lt;/li&gt;
&lt;li&gt;get latest version and&lt;/li&gt;
&lt;li&gt;open the solution in Visual Studio.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The second script will load other work-related applications like Outlook, MS Teams etc.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Is current day Thursday and time is between 9:00 and 18:00? If yes, then I'm at my job working on the data science project and:
&lt;ul class="org-ul"&gt;
&lt;li&gt;The first script will open &lt;code&gt;Ubuntu bash&lt;/code&gt; from &lt;code&gt;WSL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The second script will open the &lt;code&gt;Azure ML workspace&lt;/code&gt; in a browser.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Each of these scripts is invoked by Windows Task Scheduler at logon; the only difference being that the first one is executed with elevated privileges. I still need to run Visual Studio as administrator and by running the script with highest privileges I don't get the UAC dialog anymore.
&lt;/p&gt;

&lt;p&gt;
None of the aforementioned scripts do anything outside working hours — in that period I choose on which project to work based on what I feel like doing (to keep me engaged after a day at work) and various other factors. But the fact that, in those late or early hours I don't need to close some pesky little applications that keep distracting me, makes me be happy again with my workflow.
&lt;/p&gt;</description><guid>https://rebeja.eu/posts/declutter-the-way-of-working/</guid><pubDate>Thu, 12 Sep 2019 15:25:23 GMT</pubDate></item><item><title>EUROLAN 2019 Summer School</title><link>https://rebeja.eu/posts/eurolan-2019/</link><dc:creator>Petru Rebeja</dc:creator><description>&lt;p&gt;
I started drafting this post in the last day of &lt;a href="http://eurolan.info.uaic.ro/2019/index.html"&gt;EUROLAN 2019 Summer School&lt;/a&gt;; while the participants were about to take the last &lt;a href="https://kahoot.it/"&gt;Kahoot!&lt;/a&gt; quiz and fill the feedback form.
&lt;/p&gt;

&lt;p&gt;
This was the first summer school where I was on the other side — in the organization committee and I have to admit that I liked it very much.
&lt;/p&gt;

&lt;p&gt;
I liked the joy and enthusiasm of the participants which were as if they embarked for an adventure. Is some sense, this was an adventure for them, which could be seen from their attitude for handling the exercices — each task was tackled with maximum involvment and seriosity by everyone.
&lt;/p&gt;

&lt;p&gt;
&lt;img src="https://rebeja.eu/images/eurolan2019.jpg" alt="nil"&gt;
&lt;/p&gt;

&lt;p&gt;
The exercices were meant to cover a wide range of activities for computational linguistics — from manually annotating a small corpus of trainig phrases to training a machine learning model.
&lt;/p&gt;

&lt;p&gt;
The mission of our micro-team (&lt;a href="https://github.com/tiberiu44"&gt;Tiberiu Boroș&lt;/a&gt;, &lt;a href="https://github.com/cristian904"&gt;Cristian Pădurariu&lt;/a&gt; and myself) was to teach the participants how to train a Machine Learning model using &lt;a href="https://github.com/adobe/NLP-Cube"&gt;NLP-Cube&lt;/a&gt; - a Natural Language Processing Framework where Tiberiu is the main contributor.
&lt;/p&gt;

&lt;p&gt;
Knowing that there will be participants with both Windows and Mac OS, we settled in our discussions on enclosing &lt;a href="https://github.com/RePierre/eurolan-2019"&gt;&lt;code&gt;NLP-Cube&lt;/code&gt; into a Docker image&lt;/a&gt; which would be built by each participant in order to train the model.
&lt;/p&gt;

&lt;p&gt;
Unfortunately, despite our best efforts and the great presentation made by Tiberiu the results were disastrous — the laptops of over a half of participants didn't met Docker requirements; from the reamaining people a lot did not have enough disk space for the various transformations of the corpus and additional utilities. Overall, only a few persons were able to start the training process.
&lt;/p&gt;

&lt;p&gt;
At the end of the school, the organization committee setup a small contest with for the participants: each team would have to come up with an idea of an application and after refining the idea they would get exactly 5 minutes to pitch the idea to the ad-hoc jury. The application was subject to the constraints of being somewhat feasible to develop and should use as many topics taught during the summer school as possible.
&lt;/p&gt;

&lt;p&gt;
The ideas were great; the one that I liked the most was about an application that would do speech recognition for people suffering from some form of heavy speech impediment.
&lt;/p&gt;

&lt;p&gt;
When a part of the jury went to deliberate over which team should get which prize, &lt;a href="https://www.facebook.com/gabihaja"&gt;Gabriela Haja&lt;/a&gt; started the closing speech. It was a simple, elegant and beautifull talk where she praised the ideas of the participants but also advised them that they would need to work hard on the ideas themselves and on the skills of the authors in order to see their idea put to practice.
&lt;/p&gt;

&lt;p&gt;
Overall it was a great experience and I'm gratefull for the opportunity to participate. And now with the school long gone, I'm reviewing/archiving the to-do-list of activities for the summer school and building the list of…
&lt;/p&gt;
&lt;div id="outline-container-org55a6471" class="outline-2"&gt;
&lt;h2 id="org55a6471"&gt;Lessons learned&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org55a6471"&gt;
&lt;dl class="org-dl"&gt;
&lt;dt&gt;Infrastructure &lt;i&gt;is&lt;/i&gt; a problem&lt;/dt&gt;&lt;dd&gt;We learned the hard way that not everyone has high-end laptops that can run resource-heavy applications.&lt;/dd&gt;
&lt;dt&gt;Murphy's law is still applicable&lt;/dt&gt;&lt;dd&gt;"Anything that can go wrong, will go wrong", Murphy's las states. And indeed, we had a participant that couldn't build the docker image for some reason but when we tried to load an already built image into docker via a USB stick, the USB port failed.&lt;/dd&gt;
&lt;dt&gt;Think and tailor your workshop for the audience&lt;/dt&gt;&lt;dd&gt;Being heavily involvment into software development, Tiberiu and I made some wrong assumptions — &lt;i&gt;people will know how to install Docker on their machines&lt;/i&gt;, &lt;i&gt;the participants will know how to execute the command lines we provided&lt;/i&gt; etc. The vast majority of the participants were linguists at core and such tasks that are perceived as trivial by us are surely not trivial for them.&lt;/dd&gt;
&lt;dt&gt;You learn a lot while teaching&lt;/dt&gt;&lt;dd&gt;This is something that cannot be overstated. I knew I will be learning a lot of new stuff from the collaboration with Tiberiu (I did not knew &lt;code&gt;NLP-Cube&lt;/code&gt; existed befor this summer school) but to my great suprise I also learned a great deal of stuff just by being present and helping people.&lt;/dd&gt;
&lt;dt&gt;Allow yourself to fail&lt;/dt&gt;&lt;dd&gt;The dissapointing results of our endeavor to train a Machine Learning model had an impact on my morale but while discussing with the more experienced members of the committee (who were also in charge with feedback analysis) I found out that it wasn't as bad as I thought it was; the attendees were really happy to come in contact with Machine Learning, which, despite technical difficulties, is better than no contact at all.&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/div&gt;</description><guid>https://rebeja.eu/posts/eurolan-2019/</guid><pubDate>Fri, 24 May 2019 11:49:19 GMT</pubDate></item><item><title>Automating custom workflow in Emacs</title><link>https://rebeja.eu/posts/automating-custom-workflow-in-emacs/</link><dc:creator>Petru Rebeja</dc:creator><description>&lt;p&gt;
Due to the lack of human resources in a research project I'm involved the team decided to take upon itself the semantic comparison of 3000 pairs of papers from the medical domain.
&lt;/p&gt;

&lt;p&gt;
Each paper is a &lt;code&gt;json&lt;/code&gt; file with structured contents of the publication like in the picture below:
&lt;img src="https://rebeja.eu/images/publication-json.png" alt="nil"&gt;
&lt;/p&gt;

&lt;p&gt;
Since we also want to do &lt;span class="underline"&gt;at least some&lt;/span&gt; cross-validation we decided that each member of the team should compare 2000 pairs of publications so that each pair will be compared by two out of three persons from the team.
So we split the 3000 publication pairs into 3 sets which were saved into &lt;code&gt;csv&lt;/code&gt; files with the following structure: &lt;code&gt;file1, file2, similarity_score&lt;/code&gt;; where &lt;code&gt;file1&lt;/code&gt; and &lt;code&gt;file2&lt;/code&gt; are the names of the files and &lt;code&gt;similarity_score&lt;/code&gt; is to be filled with the semantic similarity score.
&lt;/p&gt;

&lt;p&gt;
My first idea was to have Emacs split into three windows to allow for both registering the score and a side-by-side comparison of files:
&lt;img src="https://rebeja.eu/images/comparison-layout.png" alt="nil"&gt;
&lt;/p&gt;

&lt;p&gt;
For each pair of files from the left window I would:
&lt;/p&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;Copy the name of the first file using &lt;code&gt;C-a C-SPC C-u 2 M-f M-w&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Go the the top window on the right using &lt;code&gt;C-x o 2&lt;/code&gt; (I'm using &lt;code&gt;ace-window&lt;/code&gt; thus after pressing &lt;code&gt;C-x o&lt;/code&gt; I can select the window to switch to by pressing it's number key)&lt;/li&gt;
&lt;li&gt;Open the file using &lt;code&gt;C-x C-f&lt;/code&gt; then navigating to the directory and yanking the file name at the end&lt;/li&gt;
&lt;li&gt;Move back to the first window using &lt;code&gt;C-x o 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy the name of the second file by first moving over the first comma with &lt;code&gt;C-f&lt;/code&gt; then &lt;code&gt;C-u 2 M-f M-w&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Go to the bottom window on the right using &lt;code&gt;C-x o 3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Repeat step 3&lt;/li&gt;
&lt;li&gt;Repeat step 4&lt;/li&gt;
&lt;li&gt;Compare publications and register score in &lt;code&gt;similarity_score&lt;/code&gt; column&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
Although this workflow seems quite laborious due to so many steps I've gotten used quite rapidly (from the second pair) to it and managed to form some sort of temporary muscle memory for opening files in the sense that I was doing that on full auto-pilot, &lt;i&gt;without thinking that I'm opening files&lt;/i&gt;.
&lt;/p&gt;

&lt;p&gt;
However, there was a problem with this workflow: the directory in which the files to be compared are located contains around 100 K such &lt;code&gt;json&lt;/code&gt; files and on my 5400 RPM hard-disk it took what seemed like forever to scan the directory when pressing &lt;code&gt;C-x C-f&lt;/code&gt; in order to give me the benefit of autocompletion which I did not need because I &lt;i&gt;already knew the files names&lt;/i&gt;. So basically for each pair of publications I was stuck waiting twice for the directory to be scanned.
&lt;/p&gt;

&lt;p&gt;
And then I got an idea: &lt;b&gt;I already knew the file names; the directory containing them is the same so wouldn't it be faster to send the full path (obtained by concatenating file name and directory path) to &lt;code&gt;find-file&lt;/code&gt; function instead of waiting for a directory scan?&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
I switched to the &lt;code&gt;*scratch*&lt;/code&gt; buffer and evaluated a &lt;code&gt;find-file&lt;/code&gt; call with the full path of a file and of course, the file was loaded instantly.
&lt;/p&gt;

&lt;p&gt;
So I decided to take it a bit further: &lt;b&gt;Can't I, while on a line in left window open the files on that line in the other two windows?&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
Of course I can because &lt;b&gt;Emacs is awesome&lt;/b&gt;. All I need to do is write some code lisp code that will do what I want.
&lt;/p&gt;

&lt;p&gt;
Fisrt things first, I declared a (global) variable to hold the full path to the directory containing the files:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defvar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;*compare-publications-dir*&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;directory-path&amp;gt;"&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;"The location of files to compare."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
Then I created a function to get the whole line from the &lt;code&gt;csv&lt;/code&gt; file:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defun&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;get-current-line&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;progn&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;beginning-of-visual-line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;point&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;end-of-visual-line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;buffer-substring-no-properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;point&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
This function moves the point to the beginning of the line by calling &lt;code&gt;(beginning-of-visual-line)&lt;/code&gt; then saves the position in a local variable &lt;code&gt;start&lt;/code&gt; and moves to the end of the line via a call to &lt;code&gt;(end-of-visual-line)&lt;/code&gt;. In the end it returns the substring which is between &lt;code&gt;start&lt;/code&gt; position and the position returned by &lt;code&gt;(point)&lt;/code&gt; function.
&lt;/p&gt;

&lt;p&gt;
Having the line of text I need to:
a) Split the line by &lt;code&gt;,&lt;/code&gt;
b) Store first and second parts of the line into two variables called &lt;code&gt;file-1&lt;/code&gt; and &lt;code&gt;file-2&lt;/code&gt;
c) Move to the top-right window
d) Concatenate the values of &lt;code&gt;*compare-publications-dir*&lt;/code&gt; and &lt;code&gt;file-1&lt;/code&gt; and pass the result to &lt;code&gt;(find-file-readonly)&lt;/code&gt; (I don't want to accidentally change the files being compared)
e) Move to the bottom-right window
f) Repeat d) with &lt;code&gt;file-2&lt;/code&gt; instead of &lt;code&gt;file-1&lt;/code&gt;
g) Return to the left window
&lt;/p&gt;

&lt;p&gt;
This was also implemented with a function which can be called interactively via &lt;code&gt;M-x&lt;/code&gt;:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defun&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;compare-publications&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;interactive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;files&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;csv-split-string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-current-line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;file-1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;files&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;file-2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cdr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;files&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;other-window&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;find-file-read-only&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;*compare-publications-dir*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;file-1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;other-window&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;find-file-read-only&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;*compare-publications-dir*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;file-2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;other-window&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
And that's it. After calling &lt;code&gt;eval&lt;/code&gt; on the functions above I have an automated workflow. Now, to compare two files, I just navigate to a line in the &lt;code&gt;csv&lt;/code&gt; file and from there type &lt;code&gt;M-x compare-publications&lt;/code&gt;. The only thing left to do manually (beside the comparison itself) is to press the key for the &lt;code&gt;similarity_score&lt;/code&gt; of files from that line.
&lt;/p&gt;</description><category>automation</category><category>awesome</category><category>custom workflow</category><category>Emacs</category><guid>https://rebeja.eu/posts/automating-custom-workflow-in-emacs/</guid><pubDate>Sat, 02 Jun 2018 22:00:00 GMT</pubDate></item><item><title>ServiceActivationException when auto-starting WCF services with AutofacServiceHostFactory</title><link>https://rebeja.eu/posts/serviceactivationexception-autofacservicehostfactory/</link><dc:creator>Petru Rebeja</dc:creator><description>&lt;p&gt;
I switched teams at work and as a welcome gift into the new team I got to investigate the following error:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
  Exception: System.ServiceModel.ServiceActivationException: The service '/AuthorisationService.svc' cannot be activated due to an exception during compilation.  The exception message is: The AutofacServiceHost.Container static property must be set before services can be instantiated.. —&amp;gt; System.InvalidOperationException: The AutofacServiceHost.Container static property must be set before services can be instantiated.
   at Autofac.Integration.Wcf.AutofacHostFactory.CreateServiceHost(String constructorString, Uri[] baseAddresses)
   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.CreateService(String normalizedVirtualPath, EventTraceActivity eventTraceActivity)
   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(ServiceActivationInfo serviceActivationInfo, EventTraceActivity eventTraceActivity)
   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity)
   — End of inner exception stack trace —
   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity)
   at System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(String relativeVirtualPath, EventTraceActivity eventTraceActivity)
Process Name: w3wp
Process ID: 9776
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
The troublesome service is hosted in an &lt;code&gt;ASP.NET&lt;/code&gt; web application and it's preloaded with a custom implementation of &lt;a href="https://msdn.microsoft.com/en-us/library/system.web.hosting.iprocesshostpreloadclient(v=vs.110).aspx"&gt;&lt;code&gt;IProcessHostPreloadClient&lt;/code&gt;&lt;/a&gt; which more or less does what's described in &lt;a href="http://lazynreclined.blogspot.nl/2014/09/enable-autostart-in-iis-75-without.html"&gt;this blog post&lt;/a&gt;.
Since the project hosting the service is using AutoFac as it's DI framework/library the service is setup to use &lt;code&gt;AutofacServiceHostFactory&lt;/code&gt; as the service factory:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;%&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ServiceHost&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"AuthorizationServiceImpl, AuthorizationService"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Factory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
After some googling for the error I turned out to the &lt;a href="http://docs.autofac.org/en/latest/integration/wcf.html#was-hosting-and-non-http-activation"&gt;AutoFac documentation page&lt;/a&gt; where I got the first idea of what is happening:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
When hosting WCF Services in WAS (Windows Activation Service), you are not given an opportunity to build your container in the Application&lt;sub&gt;Start&lt;/sub&gt; event defined in your Global.asax because WAS doesn’t use the standard ASP.NET pipeline.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
Ok, great! Now I know that &lt;code&gt;ServiceHostingEnvironment.EnsureServiceAvailable()&lt;/code&gt; method (which is called to activate the service) doesn't use the HTTP pipeline from ASP.NET. A solution to this issue is in the next paragraph of the documentation:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
The alternative approach is to place a code file in your &lt;code&gt;App_Code&lt;/code&gt; folder that contains a type with a &lt;code&gt;public static void AppInitialize()&lt;/code&gt; method.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
And that's what I did. I went to to the project in Visual Studio, added a &lt;code&gt;special ASP.NET folder&lt;/code&gt; named &lt;code&gt;App_Code&lt;/code&gt; and added a class named &lt;code&gt;AppStart&lt;/code&gt; to it with a single method &lt;code&gt;public static void AppInitialize()&lt;/code&gt; which contained all the required bootstrapping logic for AutoFac. I redeployed the application on but the error kept popping and it's after &lt;b&gt;carefully&lt;/b&gt; reading the comments from &lt;a href="https://stackoverflow.com/a/330720/844006"&gt;this StackOverflow answer&lt;/a&gt; and &lt;a href="https://blogs.msdn.microsoft.com/wenlong/2006/01/11/how-to-initialize-hosted-wcf-services/"&gt;this blog post on how to initialize WCF services&lt;/a&gt; I found why the &lt;code&gt;AppInitialize&lt;/code&gt; method wasn't invoked: &lt;b&gt;it was because the &lt;code&gt;AppStart.cs&lt;/code&gt; needs it's build action to be &lt;code&gt;Content&lt;/code&gt; not Compile&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
So when getting the &lt;code&gt;ServiceActivationexception&lt;/code&gt; with the error message &lt;code&gt;The AutofacServiceHost.Container static property must be set before services can be instantiated&lt;/code&gt; make sure to have the following:
&lt;/p&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;The special ASP.NET folder &lt;code&gt;App_Code&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A class in &lt;code&gt;App_Code&lt;/code&gt; having a method with this signature &lt;code&gt;public static void AppInitialize()&lt;/code&gt; which contains all the required initialization code&lt;/li&gt;
&lt;li&gt;The build action of the file containing the above method is set to &lt;code&gt;Content&lt;/code&gt; as shown in the picture below&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&lt;img src="https://rebeja.eu/images/appinitialize.png" alt="nil"&gt;
&lt;/p&gt;</description><category>AutoFacServiceHostFactory</category><category>Service Activation</category><category>WCF</category><guid>https://rebeja.eu/posts/serviceactivationexception-autofacservicehostfactory/</guid><pubDate>Wed, 16 May 2018 22:00:00 GMT</pubDate></item></channel></rss>