<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Domenico Luciani</title>
    <description>The latest articles on DEV Community by Domenico Luciani (@dlion).</description>
    <link>https://dev.to/dlion</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F72859%2F4384a834-e8fc-4b07-91e5-f179e82e748b.png</url>
      <title>DEV Community: Domenico Luciani</title>
      <link>https://dev.to/dlion</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dlion"/>
    <language>en</language>
    <item>
      <title>How to create an always up to date alias for your Mastodon account</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Sat, 19 Nov 2022 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/how-to-create-an-always-up-to-date-alias-for-your-mastodon-account-21gj</link>
      <guid>https://dev.to/dlion/how-to-create-an-always-up-to-date-alias-for-your-mastodon-account-21gj</guid>
      <description>&lt;p&gt;Mastodon is a new hot-trend topic, so I spent some time trying to wrap my head around it.&lt;br&gt;&lt;br&gt;
The decentralisation is an exciting part of Mastodon; if tomorrow I don’t like the instance where my account resides anymore, I can always switch to another instance and bring all my data seamlessly. It’s fantastic, except that now it’s like having another account with a different address, so I need to share it with my “audience” again and again.&lt;br&gt;&lt;br&gt;
Doing some research, I discover how to create a custom alias for my Mastodon account to have it always pointing to my current account; let’s see how!&lt;/p&gt;
&lt;h2&gt;
  
  
  How is it look like?
&lt;/h2&gt;

&lt;p&gt;The alias I created for my account is &lt;code&gt;dlion@domenicoluciani.com&lt;/code&gt; where &lt;code&gt;dlion&lt;/code&gt; is my nickname, and &lt;code&gt;domenicoluciani.com&lt;/code&gt; is my custom domain.&lt;br&gt;&lt;br&gt;
If you try to search it on Mastodon, you will find my current account, which resides on &lt;code&gt;mastodon.social&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pd8ywwf26aagr6os5z7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pd8ywwf26aagr6os5z7.png" alt="Mastodon Search" width="800" height="142"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Behind the scene
&lt;/h2&gt;

&lt;p&gt;I discovered that Mastodon uses ActivityPub to communicate between different actors and that those actors are found using WebFinger, a way to attach information to a specific email address or other online resources.&lt;br&gt;&lt;br&gt;
So I just needed to implement the WebFinger spec on my domain to have it working.&lt;/p&gt;

&lt;p&gt;On your Mastodon instance, you have an endpoint called &lt;code&gt;.well-known/webfinger&lt;/code&gt;, which accepts a query parameter that allows other Mastodon instances to get information around a particular account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;youmastodonaddress&amp;gt;/.well-known/webfinger?resource=acct:&amp;lt;yournick&amp;gt;@&amp;lt;youmastodonaddress&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For instance, in my case, doing a curl GET request to this URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://mastodon.social/.well-known/webfinger?resource=acct:dlion@mastodon.social

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I get the WebFinger response for my account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"aliases"&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="s2"&gt;"https://mastodon.social/@dlion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"https://mastodon.social/users/dlion"&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="nl"&gt;"links"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"href"&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="s2"&gt;"https://mastodon.social/@dlion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"rel"&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="s2"&gt;"http://webfinger.net/rel/profile-page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"type"&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="s2"&gt;"text/html"&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="nl"&gt;"href"&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="s2"&gt;"https://mastodon.social/users/dlion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"rel"&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="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"type"&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="s2"&gt;"application/activity+json"&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="nl"&gt;"rel"&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="s2"&gt;"http://ostatus.org/schema/1.0/subscribe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"template"&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="s2"&gt;"https://mastodon.social/authorize_interaction?uri={uri}"&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="nl"&gt;"subject"&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="s2"&gt;"acct:dlion@mastodon.social"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I need to put this response on my server under the same directory and inside the same file and that’s it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to do it on a Jekyll website
&lt;/h2&gt;

&lt;p&gt;For my blog, I use GitHub for the hosting; specifically, I use &lt;code&gt;github-pages&lt;/code&gt; which means using &lt;code&gt;Jekyll&lt;/code&gt;, a static site generator.&lt;/p&gt;

&lt;p&gt;To have your Mastodon alias in your custom domain using Jekyll, you need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the root of your repo, create a directory called &lt;code&gt;.well-known&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inside the directory &lt;code&gt;.well-known&lt;/code&gt;, create a new file called &lt;code&gt;webfinger&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inside the &lt;code&gt;webfinger&lt;/code&gt; file, put the response you get when you curl your actual Mastodon instance WebFinger endpoint, as mentioned before.&lt;/li&gt;
&lt;li&gt;In your &lt;code&gt;_config.yml&lt;/code&gt;, add &lt;code&gt;include: ["/.well-known"]&lt;/code&gt; to include that directory in your rendering.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And it’s done. Just push and wait a bunch of minutes. Your alias will be founded as &lt;code&gt;anything@your-custom-domain.whatever&lt;/code&gt; by Mastodon, redirecting everyone to your actual account.&lt;/p&gt;




&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;If you want to know more about WebFinger, you can have a look at the original website of the spec and at the Mastodon’s documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://webfinger.net/" rel="noopener noreferrer"&gt;https://webfinger.net/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.joinmastodon.org/spec/webfinger/" rel="noopener noreferrer"&gt;https://docs.joinmastodon.org/spec/webfinger/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found out about this method thanks to this article by &lt;a href="https://blog.maartenballiauw.be/" rel="noopener noreferrer"&gt;Maarten Balliauw&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.maartenballiauw.be/post/2022/11/05/mastodon-own-donain-without-hosting-server.html" rel="noopener noreferrer"&gt;https://blog.maartenballiauw.be/post/2022/11/05/mastodon-own-donain-without-hosting-server.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>life</category>
      <category>mastodon</category>
      <category>social</category>
    </item>
    <item>
      <title>Misleading Pair Programming</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Fri, 22 Jul 2022 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/misleading-pair-programming-2999</link>
      <guid>https://dev.to/dlion/misleading-pair-programming-2999</guid>
      <description>&lt;p&gt;I often read tweets, threads and posts full of complaints about this weird practice called &lt;strong&gt;Pair Programming&lt;/strong&gt; , frequently due to a lack of understanding and wrong implementation.&lt;br&gt;&lt;br&gt;
Today I’d like to spend some time clarifying why those complaints are misleading and why you should keep doing pair programming.&lt;/p&gt;




&lt;h2&gt;
  
  
  It’s tiring!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Do you use pair programming? How do you do it?  &lt;/p&gt;

&lt;p&gt;It often feels like a more tiring way to move slower to me. Great for solving gnarly bugs together, but not for coding.&lt;/p&gt;

&lt;p&gt;— Swizec Teller encouraging you to Be An Expert (@Swizec) &lt;a href="https://twitter.com/Swizec/status/1363938310276583430?ref_src=twsrc%5Etfw"&gt;February 22, 2021&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I heard people complaining that 8 hours of pair programming are a nightmare. It is ruining their life, draining all their mental energies, and making them brainless at the end of the day. Let me tell you a thing, and I want to make it clear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are doing 8 hours of straight pair programming, you are doing it wrong!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Take breaks!
&lt;/h3&gt;

&lt;p&gt;Pair programming is a powerful and brain energy-consuming activity; therefore, having breaks &lt;strong&gt;IS KEY&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
One technique I like is the &lt;a href="https://en.wikipedia.org/wiki/Pomodoro_Technique"&gt;Pomodoro&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Essentially it forces you to have breaks every 25 minutes of straight pair programming. The break usually lasts 5 minutes whenever you shouldn’t do anything related to that specific task.&lt;br&gt;&lt;br&gt;
Of course, you can be flexible according to your needs, but you shouldn’t push too hard on that limit. Taking breaks is part of this activity; you and your pair should have it as frequently as possible. It’s essential to have breaks and rest. Please do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s slow!
&lt;/h2&gt;

&lt;p&gt;Another false assumption is that pairing slows you down.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why have two people on the same task when you can have two people on two different tasks and speed up the development?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3oriO7A7bt1wsEP4cw/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3oriO7A7bt1wsEP4cw/giphy.gif" alt="slow" width="320" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It seems a fair statement, but it doesn’t take into consideration the result of doing that, let’s explore a few of them:&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Reviews
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o7WTL4qQCbbLLV2Pm/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o7WTL4qQCbbLLV2Pm/giphy.gif" alt="code review" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Doing code reviews is a common practice. Once you are done with your story, another (or more than just one) person has to review and accept your code to be merged.&lt;br&gt;&lt;br&gt;
What are the pitfalls of this practice?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lack of context&lt;/strong&gt; : the person reviewing your code doesn’t have the same context as you, it will lead to possible misunderstanding or long debates due to this deficiency, delaying the integration and having a longer feedback loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It requires another person’s availability&lt;/strong&gt; : waiting for another person to review your code leads to a significant delay creating a bottleneck within the team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context Switch&lt;/strong&gt; : the other person probably is busy doing something else, like working on a different task. That person, just for unblocking you, has to do a context switch, review your code and then get back to the task by doing another context switch again. It has been proved that doing context switching often leads to spending lots of time restoring concentration and getting back on track.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fake Code Reviews&lt;/strong&gt; : Reading others’ code is complex, and it requires concentration, especially without the context becoming time-consuming, so what do usually people do? Read quickly through the code, acting like a linter or a compiler. It is like doing a fake code review. It doesn’t add any value; it can lead to side problems in the codebase and give the team a fake feeling of security. It often happens, especially when the team is in a rush due to imposed deadlines or constraints.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bus Factor and Collective Ownership
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/9qnogucSKuQ8g/giphy-downsized-large.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/9qnogucSKuQ8g/giphy-downsized-large.gif" alt="bus factor" width="480" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Working alone on a task is cool until the rest of the team needs to know what you have done and how but you are not available.&lt;br&gt;&lt;br&gt;
Handing over your knowledge around that task will require spending some time with the team explaining to them the code you have written, giving them the context and the choices you have made, and hoping they get it quickly. It could involve having different sessions with different people, drawing flows and having multiple discussions.&lt;/p&gt;

&lt;p&gt;All the things you can mitigate by having another person pair with you.&lt;br&gt;&lt;br&gt;
In that scenario, two people are getting the same knowledge around a specific task; frequently rotating helps to spread this knowledge increasing the collective ownership of the codebase.&lt;br&gt;&lt;br&gt;
Are you off tomorrow? No worries, you are covered by another person who knows what you know without the need to wait for you to be back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sometimes I don’t think that pairing is a good idea!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Then don’t do it!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pairing is a valuable activity with multiple benefits, but it has to be used whenever it has sense; otherwise, it’s just another practice you follow because of some “rules” written somewhere that someone is telling you to respect.&lt;br&gt;&lt;br&gt;
If you see a task that doesn’t require pairing, then you can just go ahead and do it by yourself. It is okay to have a sole moment, and it’s up to you to decide whether or not to pair with someone else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remotely is harder!
&lt;/h2&gt;

&lt;p&gt;True, remote pairing is more complicated than pairing physically, and it is a fact. However, nowadays, we have some tools, precautions and equipment to overcome this situation as much as possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Slow internet connection&lt;/strong&gt; : Be ensure to have an internet connection that can support your pairing activities seamlessly. Without a good internet connection, the whole pairing activity will degrade, and it is no longer working anymore.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-quality audio channel&lt;/strong&gt; : pairing forces you to communicate as much as possible. It’s about sharing your thoughts; it’s about having discussions and telling what you will do while driving. During the pairing sessions, &lt;strong&gt;properly communicating is key&lt;/strong&gt;. Having a good headset with a good microphone (with noise reductions, for example) will allow you to not bother your pair with annoying noises and, on the other hand, to have a smooth call listening to your colleague seamlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-quality camera&lt;/strong&gt; : The body language is an essential part of the pairing session; it allows you to understand what the other person thinks (even unconsciously) and whether that person is following you or not. It will enable you to have a more human centre experience.
These critical factors are missing during the remote pairing session. For this reason, it is essential to emulate the physical pairing as much as possible, having the camera on and streaming high-quality video.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having the camera on allows you to see the other person’s expression and feeling of not being alone. It helps you to ensure to be listened to and force the other person to not be distracted. Turning your camera off is okay &lt;em&gt;if you need it or if you have a problem with your internet connection&lt;/em&gt;. It’s okay turning it off during your breaks, and it’s okay if you are not feeling comfortable, but be conscious that you will lose lots of communication, making the session harder.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use the right tool&lt;/strong&gt; : Don’t stick with a single tool; if you need to use multiple tools, do it. The smoother the session is, the better. For instance, if you find the Zoom screen sharing pretty bad, try to use Visual Studio Live Code and use Zoom just for the call. Sure, you will use more resources, but it is the right thing to do if it improves your pairing session. Nowadays, there are a lot of tools you can try; use the one you and your pair find more comfortable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Breaks breaks breaks!&lt;/strong&gt; : Pairing is a brain power-consuming activity, so if by default you need breaks, when remote, you need it even more. Don’t be shy and ask whenever you need a break preventing zoom’s fatigue or, in general, being exhausted at the end of the day.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I have less experience than my pair
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/qQJ1xyQXVuVfW/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/qQJ1xyQXVuVfW/giphy.gif" alt="less experience" width="480" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pairing is not only about showing what you know but also showing what you don’t know.&lt;br&gt;&lt;br&gt;
It’s totally fine saying “I don’t know” during a pairing session. It’s fine admitting you have less experience or are just blocked. Your pair have to support, unblock and guide you.&lt;br&gt;&lt;br&gt;
Pairing has this colossal benefit that cultivation is part of this activity. It helps juniors grow together by getting more confident, and it allows seniors to learn from less experienced engineers (it happens frequently).&lt;br&gt;&lt;br&gt;
Pairing is about trust and being honest and open with your pair, so don’t be afraid. Learning is a beautiful journey, and pairing is the safest way to do so.&lt;/p&gt;

&lt;h2&gt;
  
  
  I have more experience than my pair
&lt;/h2&gt;

&lt;p&gt;Having more experience than your pair shouldn’t be a problem; it should be an occasion to do mentoring and cultivation.&lt;br&gt;&lt;br&gt;
As a more experienced person, you should adjust your speed accordingly.&lt;br&gt;&lt;br&gt;
The pairing session is also an excellent way to clarify whether or not you understood something; if you can explain it in simple words, then you understood it. It is a perfect way to improve your skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Yara Yara
&lt;/h2&gt;

&lt;p&gt;I’m pretty sure there are many other complaints we can consider and address, but the result will always be the same.&lt;br&gt;&lt;br&gt;
Pair programming brings to your team tons of benefits if it is done correctly.&lt;br&gt;&lt;br&gt;
My advice would also be to set the right expectations at the beginning of the session. Let’s agree on what the pairing session would look like and clarify the style with your pair to avoid wrong assumptions and behaviours that can degrade the experience for both of you.&lt;/p&gt;

&lt;p&gt;Happy Pairing!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/toXKzaJP3WIgM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/toXKzaJP3WIgM/giphy.gif" alt="happy" width="490" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Other resources
&lt;/h2&gt;

&lt;p&gt;Here there are some resources you can find useful to convince your boss that doing pair programming is the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tanzu.vmware.com/developer/learningpaths/application-development/pair-programming/"&gt;https://tanzu.vmware.com/developer/learningpaths/application-development/pair-programming/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/articles/on-pair-programming.html"&gt;https://martinfowler.com/articles/on-pair-programming.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.extremeprogramming.org/rules/pair.html"&gt;http://www.extremeprogramming.org/rules/pair.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>pairing</category>
    </item>
    <item>
      <title>How to mock with Jest and Typescript</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Fri, 17 Jun 2022 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/how-to-mock-with-jest-and-typescript-ojg</link>
      <guid>https://dev.to/dlion/how-to-mock-with-jest-and-typescript-ojg</guid>
      <description>&lt;p&gt;As an Extreme Programmer I used to jumping often into different engagements, each of them has challenges I need to overcome and problems I need to solve.&lt;br&gt;&lt;br&gt;
This time I jumped into an engagement with a legacy codebase composed mainly by AWS lambdas written in Typescript. Language and technology I’ve never used before.&lt;br&gt;&lt;br&gt;
How can I learn the language and at the same time being able to quickly deliver value?&lt;br&gt;&lt;br&gt;
The answer in my head was clear: &lt;strong&gt;let’s create some tests, the rest will follow!&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;Disclaimer: I’m still learning the language so any feedback would be very welcomed, I’m writing this article to describe my journey and what I learned so far, so any suggestion and correction will be definitely appreciated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Jest Testing Framework
&lt;/h2&gt;

&lt;p&gt;Working on a legacy code often means you have to use whatever it’s already there and in this case the testing framework that has been installed &lt;strong&gt;but that I’ve never used before&lt;/strong&gt; was &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Luckily most of these frameworks are quite similar but definitely have a look into the documentation, helps.&lt;/p&gt;
&lt;h2&gt;
  
  
  Let me test, let me teeest!
&lt;/h2&gt;

&lt;p&gt;One of the problems we have working on a legacy code is that testing it is quite tricky due the fact the code wasn’t made to be tested at first place.&lt;br&gt;&lt;br&gt;
So you find these gigantic classes full of large methods that are impossible to test with a lot of dependencies, a big ball of mud.&lt;br&gt;&lt;br&gt;
A legacy codebase can be composed by thousands of classes, composed by hundreds of methods and lines of code, so where should we start from?&lt;/p&gt;
&lt;h2&gt;
  
  
  Core Business Logic
&lt;/h2&gt;

&lt;p&gt;My first step into a legacy codebase is about identifying the core business logic, the critical one. I work with the client’s team to identify which part should &lt;strong&gt;never&lt;/strong&gt; break and which part delivers value.&lt;br&gt;&lt;br&gt;
Once identified, I start retrofitting some unit tests, trying to cover the main use-cases ensuring that everything work as expected and start creating my safety-net.&lt;br&gt;&lt;br&gt;
Working without a safety-net is risky, will slow us down and increase the likelihood that we are going to break something.&lt;/p&gt;
&lt;h2&gt;
  
  
  Mock Mock Mock
&lt;/h2&gt;

&lt;p&gt;Often you have lots of dependencies you need to take care of and most of the time those dependencies are doing lot’s of weird stuff you don’t know anything about so the safest way to test everything without worrying how those dependencies behave is to mock them, brutally.&lt;/p&gt;

&lt;p&gt;In the following sections you can find some snippets of code I found useful during my journey on that project, handling legacy code could be tricky and having the right snippets at the right moment could be life saver.&lt;/p&gt;
&lt;h2&gt;
  
  
  Typescript, what are you doing??
&lt;/h2&gt;

&lt;p&gt;I found out that compared with other languages Typescript allows you to mock an object easily thanks to the &lt;a href="https://www.geeksforgeeks.org/typescript-duck-typing/"&gt;duck-typing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s see an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;readlDependency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;functionIneedToMock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;anotherFunctionIwantToMock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&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="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can just create a new object which reflects the same properties composition of the dependency we need to mock and that’s it, Typescript compiler will identify that object as the same type automagically allowing us to use it seamless . ✨&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockedDependency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;functionIneedToMock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;anotherFunctionIwantToMock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can notice, I’ve replaced the implementation with &lt;a href="https://jestjs.io/docs/jest-object#jestfnimplementation"&gt;&lt;code&gt;jest.fn()&lt;/code&gt;&lt;/a&gt; which allows us to mock that function using jest functionality.&lt;/p&gt;

&lt;p&gt;Let’s see a more concrete example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should test something&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockedDependency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;functionIneedToMock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;anotherFunctionIwantToMock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ClassUnderTest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;methodUnderTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockedDependency&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockedDependency&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functionIneedToMock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the previous example we want to be sure to have our mocked function called 2 times. Easy right?&lt;br&gt;&lt;br&gt;
How about the implementation? Easy peasy!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockedDependency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;functionIneedToMock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;anotherFunctionIwantToMock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;jest.fn(implementation)&lt;/code&gt; is a shorthand for  &lt;code&gt;jest.fn().mockImplementation(implementation)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Mocking imported dependencies
&lt;/h2&gt;

&lt;p&gt;Everything look nice when you can inject your dependencies but in the Typescript world you can avoid passing parameters and just import whatever you need and use it wherever you want more or less, how can we mock or spy on those dependencies? Let’s see an example how to do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MessageService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../message-service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messageService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MessageService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Manager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;methodWhichUseLotsOfDependencies&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;....&lt;/span&gt;
    &lt;span class="nx"&gt;messageService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publishMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;....&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then let’s try to spy on our dependency using Jest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MessageService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../message-service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spiedPublishMessageService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;MessageService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;publishMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should publish the message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Manager&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;methodWhichUseLotsOfDependencies&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spiedPublishMessageService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple and clean, essentially we are spying on our dependency, specifically on the &lt;code&gt;publishMessage&lt;/code&gt; method and then asserting that it receives &lt;code&gt;hello&lt;/code&gt; as parameter.&lt;br&gt;&lt;br&gt;
Of course we can always program the mocked dependency behaviour since the &lt;code&gt;jest.spyOn&lt;/code&gt; method returns a Jest mock 🏋🏻‍♂️&lt;/p&gt;
&lt;h2&gt;
  
  
  What if the class contains static methods?
&lt;/h2&gt;

&lt;p&gt;Often in legacy codebases we may find multiple static methods, used improperly.&lt;br&gt;&lt;br&gt;
How can we handle them with Jest?&lt;br&gt;&lt;br&gt;
Here an example:&lt;/p&gt;

&lt;p&gt;We have a &lt;code&gt;Mapper&lt;/code&gt; class with a static &lt;code&gt;mapSomethingToSomethingElse&lt;/code&gt; method that we want to mock, for instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Mapper&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;mapSomethingToSomethingElse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;our mock:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Mapper&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../mappers/mapper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../mappers/mapper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;Mapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;mapSomethingToSomethingElse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dummyMock&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then we can perform some assertions like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expect(Mapper.mapSomethingToSomethingElse)
.toHaveBeenCalledTimes(1);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What about AWS Lambda handlers?
&lt;/h2&gt;

&lt;p&gt;Testing an AWS Lambda handler is very similar to what we already done, for instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ApiGatewayDoSomethingWithLambdaHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIGatewayProxyEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;APIGatewayProxyResult&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="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our test will look like something similar:&lt;br&gt;&lt;br&gt;
Let say we want to spy on our AuthService providing dummy dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockedAuthService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkPermissions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should test the handler&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;dummyProxyEvent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;APIGatewayProxyEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dummyToken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dummyBody&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;dummyContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;awsRequestId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dummyAwsRequestId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ApiGatewayDoSomethingWithLambdaHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;dummyProxyEvent&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;APIGatewayProxyEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;dummyContext&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockedAuthService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see we used the &lt;a href="https://www.typescriptlang.org/docs/handbook/utility-types.html"&gt;&lt;code&gt;Partial&lt;/code&gt;&lt;/a&gt; type to avoid moking every property of those objects and then passing them to our handler, asserting that one of our mock has been called correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Just the tip of the iceberg
&lt;/h2&gt;

&lt;p&gt;I still need to learn more than a bunch of things around this very powerful language and I’ve just scratched the top of the iceberg and I’m looking forward continuing exploring this world called Typescript.&lt;/p&gt;

</description>
      <category>programming</category>
    </item>
    <item>
      <title>InnerSpace 🚀</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Tue, 11 Jan 2022 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/innerspace-4iai</link>
      <guid>https://dev.to/dlion/innerspace-4iai</guid>
      <description>&lt;p&gt;This year one of my annual resolutions was to be more present online.&lt;br&gt;&lt;br&gt;
I want to be more visible and share more content.&lt;br&gt;&lt;br&gt;
I want to create more articles and share them with more people.&lt;br&gt;&lt;br&gt;
Learn from feedback and grow the number of people with whom I interact.&lt;/p&gt;

&lt;p&gt;So, today I decided to create my newsletter called: InnerSpace 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  RSS? Can you eat it?
&lt;/h2&gt;

&lt;p&gt;I don’t know how many people still use feed RSS nowadays.&lt;br&gt;&lt;br&gt;
I’ve been using them for a while, but I don’t see many people speaking about them anymore, so I decided to find another way to share my blog posts regularly without the need to share them everywhere.&lt;br&gt;&lt;br&gt;
I have a RSS feed just &lt;a href="https://domenicoluciani.com/feed.xml"&gt;right here&lt;/a&gt; maybe someone who is still using them could find it useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Revue
&lt;/h2&gt;

&lt;p&gt;I discovered &lt;a href="https://www.getrevue.co/"&gt;https://www.getrevue.co/&lt;/a&gt;, a simple tool that helped me to create my newsletter, customise it and even have a fixed subdomain where to find all the issues, for free. The experience was quite smoothly so far, let’s see how it goes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Topics
&lt;/h2&gt;

&lt;p&gt;I will share my blog posts about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;extreme programming&lt;/li&gt;
&lt;li&gt;system design&lt;/li&gt;
&lt;li&gt;security&lt;/li&gt;
&lt;li&gt;IoT&lt;/li&gt;
&lt;li&gt;thoughts, useful links and articles&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Insights
&lt;/h2&gt;

&lt;p&gt;Revue also gives some insights about my articles, receiving passive feedback.&lt;br&gt;&lt;br&gt;
Here I don’t have analytics and I think that I’m missing a lot of feedback from them.&lt;br&gt;&lt;br&gt;
I think would be nice verifying which content you like most.&lt;br&gt;&lt;br&gt;
For you to obtain more tuned content and for me to understand you better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subscription
&lt;/h2&gt;

&lt;p&gt;It’s free, you just need to subscribe, and once in a while, you will receive my issues.&lt;br&gt;&lt;br&gt;
I don’t have a specific plan for them, I don’t want to put to myself any kind of constraint and I don’t want to set any kind of expectation.&lt;/p&gt;

&lt;p&gt;You can find the newsletter here: &lt;a href="https://innerspace.domenicoluciani.com"&gt;InnerSpace 🚀&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don’t know how it goes, but I’m looking forward to seeing it!&lt;/p&gt;

&lt;p&gt;And as always any feedback is super appreciated!&lt;/p&gt;

</description>
      <category>life</category>
      <category>newsletter</category>
      <category>security</category>
      <category>tdd</category>
    </item>
    <item>
      <title>How to sync your Obsidian vault on your Android</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Fri, 31 Dec 2021 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/how-to-sync-your-obsidian-vault-on-your-android-48b6</link>
      <guid>https://dev.to/dlion/how-to-sync-your-obsidian-vault-on-your-android-48b6</guid>
      <description>&lt;p&gt;I recently &lt;a href="https://domenicoluciani.com/2021/12/17/why-did-i-switch-from-notion-to-obsidian.html"&gt;moved from Notion to Obsidian&lt;/a&gt; and one big problem I’ve had to face was how to sync my desktop instance with my android mobile one without having a paid plan on Obsidian.&lt;br&gt;&lt;br&gt;
After some researches, I discovered how to do it smoothly…&lt;/p&gt;

&lt;p&gt;The main tool that I use for my backup/sync is git and specifically, I use a private repo on Github to store my vault.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I don’t have any sensitive information in my vault, so be aware that even tho your vault is inside a private repo, it won’t be encrypted.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Computer
&lt;/h2&gt;

&lt;p&gt;There is an amazing plugin called &lt;a href="https://github.com/denolehov/obsidian-git"&gt;Obsidian Git&lt;/a&gt; which automatically commit and push toward my repo each 10minutes.&lt;br&gt;&lt;br&gt;
Make sure that the &lt;code&gt;Disable push&lt;/code&gt; option is deactivated.&lt;br&gt;&lt;br&gt;
It works out of the box if you have already set your credentials on your computer and of course, you always need to initialise your git repo first with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init
git remote add origin &amp;lt;your repo's address&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obsidian Git will automatically pull new changes when you start Obsidian, you can also pull it by yourself through the command line or the hotkey ctrl+p searching for “Obsidian Git: Pull”.&lt;/p&gt;

&lt;p&gt;I would suggest to put in your &lt;code&gt;.gitignore&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.obsidian/workspaces.json
.obsidian/workspace
.obsidian/cache
.trash/
.DS_Store
.vault-stats

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can just commit and push&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "First commit"
git push

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the Obsidian vault is on Github 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Android
&lt;/h2&gt;

&lt;p&gt;Okay, the vault is online, but how can we sync it on your android mobile phone?&lt;br&gt;&lt;br&gt;
We can install &lt;a href="https://termux.com/"&gt;https://termux.com/&lt;/a&gt; to get a Linux shell on your Android, then you can install &lt;code&gt;git&lt;/code&gt; and clone the repo.&lt;br&gt;&lt;br&gt;
You can install termux from the Play Store and then execute it, installing and configuring what we need with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; pkg install git #to install git
&amp;gt; termux-setup-storage #to make storage available

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s configure the Github credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  Github credentials
&lt;/h3&gt;

&lt;p&gt;First of all, you need to generate an ssh key for the Android mobile phone&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-keygen -t ed25519 -C "email@provider.com"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t add a passphrase, just press enter&lt;br&gt;&lt;br&gt;
If you don’t have ssh installed type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pkg install openssh

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you need to add the ssh key to the Github’s account, just following these instructions: &lt;a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account"&gt;https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get the ssh key you can just type on termux &lt;code&gt;cat .ssh/id_ed25519.pub&lt;/code&gt; copying the key and pasting it into the &lt;code&gt;key&lt;/code&gt; field of Github’s form adding the ssh key to your account.&lt;/p&gt;

&lt;p&gt;Once we have followed these steps we can try to clone the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:YOUR_USER/YOUR_REPO_NAME.git

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then let’s move it to the shared folder so you can access it from any Android application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv YOUR_REPO_NAME/ storage/shared/

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can just open the directory from your Obsidian application and here we go, we have the vault up to date with the latest changes.&lt;br&gt;&lt;br&gt;
I also suggest putting inside your vault a &lt;code&gt;.nomedia&lt;/code&gt; file so you won’t see the image contained in your vault in your gallery.&lt;/p&gt;

&lt;p&gt;But how can make this process simpler?&lt;/p&gt;

&lt;p&gt;Let’s first create a soft link to the repo to simplify the process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ln -s storage/shared/YOUR_REPO_NAME YOUR_REPO_NAME

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then let’s create a &lt;code&gt;pull.sh&lt;/code&gt; script that you will run to pull the latest changes from the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd YOUR_REPO_NAME/
git pull -r

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the &lt;code&gt;push.sh&lt;/code&gt; script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd YOUR_REPO_NAME/
git add .
git commit -m "synched with android on $(date)"
git push

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then let’s make them executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x push.sh pull.sh

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From now on, you can push and pull executing those scripts with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./pull.sh
./push.sh

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be aware that this solution doesn’t handle possible conflicts which I try to avoid as much as possible resetting my mobile vault considering the desktop one as the most up to date (having regular backups helps me to validate this assumption easily).&lt;/p&gt;

&lt;p&gt;Of course, there is surely a window of improvement on this solution but I’m ok right now with this one, it’s easy to open termux, type &lt;code&gt;./pull.sh&lt;/code&gt; and then exit right after that I updated my vault.&lt;/p&gt;

</description>
      <category>life</category>
    </item>
    <item>
      <title>Why did I switch from Notion to Obsidian</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Fri, 17 Dec 2021 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/why-did-i-switch-from-notion-to-obsidian-3l44</link>
      <guid>https://dev.to/dlion/why-did-i-switch-from-notion-to-obsidian-3l44</guid>
      <description>&lt;p&gt;It’s been a while when I started using notional tools for my day to day. I use these tools constantly, trying to use it as a second brain.&lt;/p&gt;

&lt;p&gt;I used Notion for 3 months and it was amazing. I could organize my entire life creating my life’s dashboard, work section and so on.&lt;br&gt;&lt;br&gt;
I could track everything quite smoothly for those 3 months and it’s been an happy journey till I found myself on an airplane. Above the clouds I wanted to track something down in my Notion instance, but then I realized the worst: Notion doesn’t have the offline support.&lt;/p&gt;

&lt;p&gt;My second brain was for offline, was unreachable, and let’s say for a so important organ being offline it’s a shame.&lt;/p&gt;

&lt;p&gt;Once back to the interconnected world I decided that I wanted to have my second brain always available, always there for my needs, always up and running.&lt;/p&gt;

&lt;p&gt;I started googling around and I found a bunch of Notion alternatives, one of these is &lt;strong&gt;Obsidian&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Obsidian
&lt;/h2&gt;

&lt;p&gt;Obsidian is a powerful notional tool where everything is a markdown file which means you have the file always available, being able to edit your files with any editor on any platform. You don’t have a fricking database, instead you have a directory called &lt;code&gt;vault&lt;/code&gt; which contains all your sub-directories and files.&lt;br&gt;&lt;br&gt;
You can find it here: &lt;a href="https://obsidian.md/" rel="noopener noreferrer"&gt;https://obsidian.md&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;p&gt;One of the most outstanding Obsidian feature is the one which allows you to link markdown files between them, also using hashtag visualizing the connections in a graph that is generated by a core plugin. It helps to visualize your “ideas”, clarify the connections between ideas, topics and thoughts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdomenicoluciani.com%2Fassets%2Fimages%2Fposts%2Fobsidian-graph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdomenicoluciani.com%2Fassets%2Fimages%2Fposts%2Fobsidian-graph.png" alt="Obsidian-graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdomenicoluciani.com%2Fassets%2Fimages%2Fposts%2Fobsidian-link.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdomenicoluciani.com%2Fassets%2Fimages%2Fposts%2Fobsidian-link.png" alt="Obsidian-link"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;Out of the box obsidian does its amazing job but it’s quite limited to a basic usage, if you want customize more your second brain you have to work a bit on the configuration which is very simple thanks to the amazing work done on the GUI&lt;/p&gt;

&lt;h3&gt;
  
  
  Plugins
&lt;/h3&gt;

&lt;p&gt;One of the best part of the tool is the community behind it. You can find literally thousands of plugins made by the community for the community.&lt;br&gt;&lt;br&gt;
Most of the authors use their plugins which are open source, so it means that the whole community can contribute, review and approve them.&lt;/p&gt;

&lt;p&gt;You can find the available plugins on Settings → Community Plugins → Browse&lt;br&gt;&lt;br&gt;
I really recommend to use few plugins to enrich your experience according to your needs.&lt;/p&gt;

&lt;p&gt;My favorite plugins are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calendar&lt;/li&gt;
&lt;li&gt;Kanban&lt;/li&gt;
&lt;li&gt;Admonition&lt;/li&gt;
&lt;li&gt;Banners&lt;/li&gt;
&lt;li&gt;Highlightr&lt;/li&gt;
&lt;li&gt;Natural Language Dates&lt;/li&gt;
&lt;li&gt;Reminder&lt;/li&gt;
&lt;li&gt;Obsidian Git&lt;/li&gt;
&lt;li&gt;Dictionary&lt;/li&gt;
&lt;li&gt;Zettelcasten prefixer&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Themes
&lt;/h3&gt;

&lt;p&gt;You can customize the Obsidian’s theme using different themes made by the community, having a comfortable environment is the key.&lt;br&gt;&lt;br&gt;
You can find them on Settings → Appearance → Manage&lt;/p&gt;

&lt;h2&gt;
  
  
  How to move from Notion to Obsidian
&lt;/h2&gt;

&lt;p&gt;I had lots of Notion’s notes so I needed an hand to move everything from there to Notion but luckily the community already thought about that, I found a nice script made by a member of the community to move all my Notion notes to my Obsidian vault.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can find the script here: &lt;a href="https://forum.obsidian.md/t/import-from-notion/636/2" rel="noopener noreferrer"&gt;(https://forum.obsidian.md/t/import-from-notion/636/2)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You can find the whole documentation about how to do that here: &lt;a href="https://forum.obsidian.md/t/notion-2-obsidian-migration-instructions/2728" rel="noopener noreferrer"&gt;https://forum.obsidian.md/t/notion-2-obsidian-migration-instructions/2728)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;For the generic import you can find everything on the Obsidian documentation: &lt;a href="https://help.obsidian.md/How+to/Import+data" rel="noopener noreferrer"&gt;https://help.obsidian.md/How+to/Import+data&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Backup
&lt;/h2&gt;

&lt;p&gt;I backup my vault using a personal repo on Github and the &lt;a href="https://github.com/denolehov/obsidian-git" rel="noopener noreferrer"&gt;Obsidian Git&lt;/a&gt; plugin. It backups my files every 15minutes with a specific commit.&lt;br&gt;&lt;br&gt;
You can customize your settings as you prefer and it is fully integrated with your git instance so you don’t need to provide any kind of token or credential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mobile App
&lt;/h2&gt;

&lt;p&gt;There is also a mobile application that you can use: &lt;a href="https://obsidian.md/mobile" rel="noopener noreferrer"&gt;https://obsidian.md/mobile&lt;/a&gt;&lt;br&gt;&lt;br&gt;
I found a way to integrate my backup on my mobile phone using the free plan but that is a topic for another article.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Obsidian
&lt;/h2&gt;

&lt;p&gt;This is a screenshot of my Obsidian instance when I was writing this article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdomenicoluciani.com%2Fassets%2Fimages%2Fposts%2Fobsidian-mine.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdomenicoluciani.com%2Fassets%2Fimages%2Fposts%2Fobsidian-mine.png" alt="Obsidian-mine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I find Obsidian very flexible and simple enough to stick with it for a while.&lt;br&gt;&lt;br&gt;
Of course there are always windows of improvement but I’m happy about my choice so far.&lt;br&gt;&lt;br&gt;
I think that all the hype around Notion is very well deserved but still it has downside which forced me to think about the future of my notes.&lt;br&gt;&lt;br&gt;
Obsidian is a way to be sure to have my notes &lt;strong&gt;forever&lt;/strong&gt; and you should think about it too if you don’t want to find yourself in a particular uncomfortable situation where you can’t get your note and you need it.&lt;/p&gt;

</description>
      <category>life</category>
    </item>
    <item>
      <title>The Fifteen-Factor App</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Sat, 30 Oct 2021 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/the-fifteen-factor-app-14i1</link>
      <guid>https://dev.to/dlion/the-fifteen-factor-app-14i1</guid>
      <description>&lt;p&gt;Have you ever wondered how to deliver good Software As A Service? Nowadays, as developers, we spend most of our time delivering software as a service, but it brings a lot of uncertainties about how to do it properly. Do you know that we already have 15 tips that can help us to achieve that visionary goal?&lt;br&gt;&lt;br&gt;
I’ve been reading a lot about it, and I decided to summarise them in a small article. Let’s dig deeper and find more about this methodology and the fifteen factors which belong to it…&lt;/p&gt;

&lt;h1&gt;
  
  
  Wait, fifteen?
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;I thought we had only twelve factors. Who added the other three?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The idea of extending the twelve-factor has been thought of by Kevin Hoffman, explaining them in his book &lt;a href="https://www.oreilly.com/library/view/beyond-the-twelve-factor/9781492042631/"&gt;Beyond The Twelve Factor&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Codebase
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A version control system like Git always tracks the fifteen-factor app.&lt;/li&gt;
&lt;li&gt;If we have multiple codebases, it’s not an app but a distributed system.&lt;/li&gt;
&lt;li&gt;If multiple apps share the same code, it violates the fifteen-factor. The solution is to add the shared code as a dependency.&lt;/li&gt;
&lt;li&gt;There is only one codebase per app, but there are many deploys of the app. The app is the same across all deploys, but different versions may be active in each deploy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Dependencies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A fifteen-factor app declares all dependencies, completely and exactly, via a dependency declaration manifest. It simplifies the setup for developers new to the app. The new developers will set up everything by running the app’s code with a deterministic build command.&lt;/li&gt;
&lt;li&gt;A fifteen-factor app doesn’t rely on the implicit existence of any system tools. If the app needs to shell out to a system tool, that tool should be vendored into the app.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Config
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Never store constants in the code. To be fifteen-factor compliant requires a strict separation of config from code.&lt;/li&gt;
&lt;li&gt;Config varies across deploys; code doesn’t.&lt;/li&gt;
&lt;li&gt;Always prefer storing the config in environment variables; environment variables are easy to change between deploys without changing any code.&lt;/li&gt;
&lt;li&gt;Environment variables are fully orthogonal to other environment variables; they are never grouped but independently managed for each deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Backing Services
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Backing Service: any service the app consumes over the network as part of its normal operation.&lt;/li&gt;
&lt;li&gt;Systems administrators who deploy the app’s runtime manage the backing services.&lt;/li&gt;
&lt;li&gt;There are local and third-party services, and a fifteen-factor app doesn’t make any distinction between them.&lt;/li&gt;
&lt;li&gt;Deploy a fifteen-factor app should swap out a local backing service with one managed by a third party without any changes to the app’s code.&lt;/li&gt;
&lt;li&gt;Each particular backing service is a resource, called attached-resource.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Build, release, run
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The build stage is a process that converts a code repo into an executable bundle known as a build.&lt;/li&gt;
&lt;li&gt;The release stage takes the build and combines it with the deploy’s current config.&lt;/li&gt;
&lt;li&gt;The run stage runs the app in the execution environment.&lt;/li&gt;
&lt;li&gt;Each stage is strongly separated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Processes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fifteen-factor processes are stateless and share-nothing. We have to use a stateful backing service whether we want to store any data.
We can use the memory space or filesystem as a temporary, single-transaction cache.&lt;/li&gt;
&lt;li&gt;Never use sticky sessions. Never assume that anything cached in memory or disk will be available on a future request or job.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Port binding
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The fifteen-factor app is completely self-contained.&lt;/li&gt;
&lt;li&gt;The web application exports HTTP as a service by binding to a specific port and listening to requests coming in on that port.
Note also that the port-binding approach means that one app can become the backing service for another app.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Concurrency
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Processes are first-class citizens.&lt;/li&gt;
&lt;li&gt;We should design our application to distribute workload across multiple processes. Individual processes can leverage a concurrency model like Thread internally.&lt;/li&gt;
&lt;li&gt;Fifteen-factor app processes should never daemonize or write PID files, instead, rely on the operating system’s process manager.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. Disposability
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The application should be disposable; it means that we can start or stop it at any moment.&lt;/li&gt;
&lt;li&gt;We should aim to minimize startup time. The process should take a few seconds from the time the launch command is executed until the process is up and ready to receive requests or jobs.&lt;/li&gt;
&lt;li&gt;Processes should also be robust against sudden death. A fifteen-factor app is designed to handle unexpected terminations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10. Dev/prod parity
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The fifteen-factor app is designed for continuous deployment by keeping the gap between development and production small.&lt;/li&gt;
&lt;li&gt;The time between deploys should be just hours than weeks.&lt;/li&gt;
&lt;li&gt;The author of the code and who deploy the application is the same person.&lt;/li&gt;
&lt;li&gt;Dev env and prod env should be as similar as possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  11. Logs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Logs are the stream of aggregated, time-ordered events collected from the output streams of all running processes and backing services.&lt;/li&gt;
&lt;li&gt;Fifteen-factor app never concerns itself with routing or storage of its output stream. The application should write its event stream, unbuffered to the standard output.&lt;/li&gt;
&lt;li&gt;The stream can be sent to a log indexing and analysis system like Splunk to find past events, graph trends, and active alerting.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  12. Admin processes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One-off admin processes should be run in an identical environment as the regular long-running processes of the app.&lt;/li&gt;
&lt;li&gt;Admin code must ship with application code to avoid synchronization issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  13. API First
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We should define the service contract first to help our consumers understand what to send and receive, defining a common contract.&lt;/li&gt;
&lt;li&gt;This approach enables consumers and service developers to work in parallel.&lt;/li&gt;
&lt;li&gt;It helps avoid bottlenecks and facilitates the virtualization of the APIs so the consumers can run the tests against the mocks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  14. Telemetry
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Monitoring our microservices, containers, and env help us to scale, self-heal and manage alerts for end-users and platform operators.&lt;/li&gt;
&lt;li&gt;We can use machine learning towards those metrics to derive future business strategies.&lt;/li&gt;
&lt;li&gt;We can observe the application’s performance, stream of events and data, health checks, when the application starts, scales, and so on.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  15. Authentication
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make sure all security policies are in place. Developers tend to underestimate the importance that security has.&lt;/li&gt;
&lt;li&gt;APIs should be secured using OAuth, RBAC, etc.&lt;/li&gt;
&lt;li&gt;Web content should be exposed externally on HTTPS&lt;/li&gt;
&lt;li&gt;MFA&lt;/li&gt;
&lt;li&gt;Database protection&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://12factor.net"&gt;12 Factor App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.oreilly.com/library/view/beyond-the-twelve-factor/9781492042631/"&gt;Beyond the Twelve-Factor App&lt;/a&gt; by Kevin Hoffman&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>microservices</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>Distributed Tracing</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Mon, 13 Sep 2021 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/distributed-tracing-489m</link>
      <guid>https://dev.to/dlion/distributed-tracing-489m</guid>
      <description>&lt;p&gt;Recently I’ve seen a thread on Twitter regarding distributed tracing systems. I recognise that sometimes it’s an underestimated topic, so I thought to write a short and introductory article about it…&lt;/p&gt;

&lt;p&gt;Scrolling my TL, I’ve seen a thread by &lt;a href="https://twitter.com/rakyll"&gt;Jaana Dogan&lt;/a&gt; regarding distributed tracing systems; under that thread, I’ve read many people asking about it or just interested in that topic, so here we go.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SpC1aG9X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://domenicoluciani.com/assets/images/posts/rakyll-thread.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SpC1aG9X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://domenicoluciani.com/assets/images/posts/rakyll-thread.png" alt="rakyll-thread"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is distributed tracing?
&lt;/h2&gt;

&lt;p&gt;One of the advantages of having a monolithic application is that we don’t need to worry too much about tracing our incoming requests because everything is self-contained.&lt;/p&gt;

&lt;p&gt;However, when a request comes into a microservice, that could result in a cascading chain of calls to various other services, and there the tracing could become a very complex task.&lt;/p&gt;

&lt;p&gt;Distributed tracing allows the logs to span servers, not only through multiple instances of a single service but through multiple instances of multiple services establishing a correlation between them.&lt;/p&gt;

&lt;p&gt;By the book, the tracing system should allow scalability and have low overhead and application-level transparency. Ideally, it should enable quick analysis of the tracing data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Example
&lt;/h2&gt;

&lt;p&gt;Let’s see a diagram of what can happen in a real use case scenario&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p8Rd7inY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://domenicoluciani.com/assets/images/posts/distributed-tracing-diagram.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p8Rd7inY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://domenicoluciani.com/assets/images/posts/distributed-tracing-diagram.png" alt="diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To track and monitor this entire request flow, considering that we have multiple instances of the web app and other services running, an &lt;code&gt;origination id&lt;/code&gt; is needed that spans the request as the whole flow.&lt;br&gt;&lt;br&gt;
Each step must generate and use &lt;code&gt;span ids&lt;/code&gt; to helps us to view each step is still considered as part of a bigger request flow.&lt;/p&gt;

&lt;p&gt;For instance:&lt;br&gt;&lt;br&gt;
A user requests a webpage, so we will generate an &lt;code&gt;Origination Id: 123&lt;/code&gt; and a &lt;code&gt;Span Id: 1&lt;/code&gt;, then the page calls another service to get the profile detail, so we are going to have an &lt;code&gt;Origination Id: 123&lt;/code&gt; and a &lt;code&gt;Span Id: 2&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;This is important to trace logs to reverse a sequence diagram from the available data for any request. Having enough context will be simpler and faster, helping us to react quickly when needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to implement it
&lt;/h2&gt;

&lt;p&gt;The implementation is relatively straightforward. For every incoming request, examine the HTTP headers. If there is a trace id, we know we are already tracing it down; if there isn’t, create a new one. Always create a new span id and then make the trace and span context available to our code to add metrics and helpful information for later.&lt;/p&gt;

&lt;p&gt;I really recommend not reinvent the wheel. Nowadays, there are many already well-known solutions, and most of them work very well for most scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;Distributed tracing is essential for troubleshooting microservices applications; most modern distributed tracing solutions are based on the &lt;a href="https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/36356.pdf"&gt;Google Dapper Whitepaper&lt;/a&gt; that I suggest reading.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>distributedtracing</category>
    </item>
    <item>
      <title>Save 5 minutes web scraping with Rust</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Fri, 30 Apr 2021 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/save-5-minutes-web-scraping-with-rust-ka0</link>
      <guid>https://dev.to/dlion/save-5-minutes-web-scraping-with-rust-ka0</guid>
      <description>&lt;p&gt;Often I read that for simple tasks Rust is not a good choice. Go is more adopted when we need to create a small script to automatize our jobs. But is it true?&lt;/p&gt;

&lt;p&gt;Read the &lt;a href="https://domenicoluciani.com/2021/04/30/save-5-minutes-web-scraping-with-rust.html"&gt;article&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>programming</category>
    </item>
    <item>
      <title>Stop the data mess with the data mesh</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Tue, 20 Apr 2021 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/stop-the-data-mess-with-the-data-mesh-4bco</link>
      <guid>https://dev.to/dlion/stop-the-data-mess-with-the-data-mesh-4bco</guid>
      <description>&lt;p&gt;One of the hottest topics of the moment in Big Data is undoubtedly the Data Mesh, but what is it? Why is this better than the solutions we had before? Do we need it? Should we adopt it?&lt;/p&gt;

&lt;p&gt;Read the &lt;a href="https://domenicoluciani.com/2021/04/20/stop-the-data-mess-with-the-data-mesh.html"&gt;article&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>programming</category>
    </item>
    <item>
      <title>Manage your learning process with Toby</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Sat, 27 Mar 2021 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/manage-your-learning-process-with-toby-2j0b</link>
      <guid>https://dev.to/dlion/manage-your-learning-process-with-toby-2j0b</guid>
      <description>&lt;p&gt;As a greedy learner, I used to find myself full of bookmarks of stuff I want to read or watch. I’ve never had a good place to keep all the things I read/watched until I found Toby.&lt;/p&gt;

&lt;p&gt;Read the &lt;a href="https://domenicoluciani.com/2021/03/27/manage-your-learning-process-with-toby.html"&gt;article&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>life</category>
    </item>
    <item>
      <title>Hacktoberfest 2020</title>
      <dc:creator>Domenico Luciani</dc:creator>
      <pubDate>Sun, 31 Jan 2021 08:00:00 +0000</pubDate>
      <link>https://dev.to/dlion/hacktoberfest-2020-2mj1</link>
      <guid>https://dev.to/dlion/hacktoberfest-2020-2mj1</guid>
      <description>&lt;p&gt;Ah shit, here we go again. Another year passed, and another Hacktoberfest is over. I’ve just received my swag, and I can’t be more excited!&lt;/p&gt;

&lt;p&gt;Since 2014, every year I try to find the time to contribute to some open-source projects that need help, &lt;a href="https://domenicoluciani.com/2018/01/10/hacktoberfest-swag.html"&gt;every&lt;/a&gt; &lt;a href="https://domenicoluciani.com/2019/02/10/hacktoberfest-18.html"&gt;year&lt;/a&gt; &lt;a href="https://domenicoluciani.com/2019/10/25/hack-week-2019.html"&gt;I get swag&lt;/a&gt; and an awesome t-shirt from &lt;a href="https://github.com/DigitalOcean"&gt;@DigitalOcean&lt;/a&gt; in exchange of my contributions. Amazing, eh?&lt;/p&gt;

&lt;p&gt;Read the &lt;a href="https://domenicoluciani.com/2021/01/31/hacktoberfest2020.html"&gt;article&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>life</category>
    </item>
  </channel>
</rss>
