<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[André Lademann – Software Engineer from Europe]]></title><description><![CDATA[Greetings from Europe, Germany from our beautiful spaceship Earth 🚀]]></description><link>https://blog.andrelademann.de</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1627731482381/hKOGeJs-4.png</url><title>André Lademann – Software Engineer from Europe</title><link>https://blog.andrelademann.de</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 11 May 2026 11:22:44 GMT</lastBuildDate><atom:link href="https://blog.andrelademann.de/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Let's get serial]]></title><description><![CDATA[The Web Serial API is a browser-based interface that makes it possible to communicate with hardware devices via the serial interface. It is mainly used for communication with development boards such as the ESP32 or Arduino Uno to send and receive dat...]]></description><link>https://blog.andrelademann.de/lets-get-serial</link><guid isPermaLink="true">https://blog.andrelademann.de/lets-get-serial</guid><category><![CDATA[web-serial]]></category><category><![CDATA[#Serial Communications]]></category><category><![CDATA[serial port]]></category><category><![CDATA[arduino]]></category><category><![CDATA[ESP32]]></category><category><![CDATA[example]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Thu, 14 Mar 2024 22:01:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1710450216439/f1169144-a99e-4df9-89a0-d9617974cc8d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The Web Serial API is a browser-based interface that makes it possible to communicate with hardware devices via the serial interface. It is mainly used for communication with development boards such as the ESP32 or Arduino Uno to send and receive data.</p>
<p>If you want to make configurations on an ESP32 via the Web Serial API, you must first ensure that the ESP32 is programmed so that it can receive commands via its serial interface and respond to them accordingly. This usually requires firmware that has been specially developed to interpret commands and implement settings or actions on the device.</p>
<h2 id="heading-lets-do-it">Let's do it!</h2>
<p>I've prepared a all in one Demo for you. All you need is a Computer with a Chromium based browser, an microcontroller and a USB cable to connect both devices.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710452868136/f574eea6-295a-4356-9143-5e87b95726b9.png" alt class="image--center mx-auto" /></p>
<p>At first, let's give it a try:<br /><a target="_blank" href="https://vergissberlin.github.io/example-serial-web-api/">https://vergissberlin.github.io/example-serial-web-api/</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1710451843464/8907a470-4396-4e14-90f9-43e9f99d340b.png" alt="Example page to show how to work with web serial" class="image--center mx-auto" /></p>
<p>If you are interested in learning more about this particular example, take a look at the code: <a target="_blank" href="https://github.com/vergissberlin/example-serial-web-api">https://github.com/vergissberlin/example-serial-web-api</a></p>
<p>If you want to know how to get started in general, read on.</p>
<h2 id="heading-how-it-works-in-short">How it works in short</h2>
<h3 id="heading-establish-a-connection">Establish a connection</h3>
<p>Firstly, we establish a connection to the microcontroller:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> port;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">connect</span>(<span class="hljs-params"></span>) </span>{
    port = <span class="hljs-keyword">await</span> navigator.serial.requestPort();
    <span class="hljs-keyword">await</span> port.open({ <span class="hljs-attr">baudRate</span>: <span class="hljs-number">9600</span> });

    <span class="hljs-comment">// Event listener for incoming data</span>
    port.addEventListener(<span class="hljs-string">'input'</span>, <span class="hljs-function">(<span class="hljs-params">{ data }</span>) =&gt;</span> {
        <span class="hljs-keyword">let</span> decoder = <span class="hljs-keyword">new</span> TextDecoder();
        <span class="hljs-keyword">let</span> text = decoder.decode(data);
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Received:'</span>, text);
    });
}

connect(); <span class="hljs-comment">// Call connect() when your application starts</span>
</code></pre>
<h3 id="heading-send-data">Send data</h3>
<p>Now we can send data like so:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">send</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span> (!port) <span class="hljs-keyword">return</span>;
    <span class="hljs-keyword">let</span> data = <span class="hljs-string">"Hello Arduino!"</span>;
    <span class="hljs-keyword">const</span> writer = port.writable.getWriter();
    <span class="hljs-keyword">await</span> writer.write(<span class="hljs-keyword">new</span> TextEncoder().encode(data));
    <span class="hljs-keyword">await</span> writer.releaseLock();
}
</code></pre>
<h3 id="heading-receive-the-data-with-you-controller">Receive the data with you controller</h3>
<p>Receiving the data is surprisingly easy:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setup</span><span class="hljs-params">()</span> </span>{
  Serial.begin(<span class="hljs-number">9600</span>);
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">loop</span><span class="hljs-params">()</span> </span>{
  <span class="hljs-keyword">if</span> (Serial.available() &gt; <span class="hljs-number">0</span>) {
    String receivedData = Serial.readString();
    Serial.println(<span class="hljs-string">"Received: "</span> + receivedData);
  }
}
</code></pre>
<p><code>Serial.readString()</code> can be used to pull the data directly from the stream.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">📖</div>
<div data-node-type="callout-text">There are more example in the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API">MDN documentation</a>.</div>
</div>

<h2 id="heading-summary">Summary</h2>
<p>The Web Serial API facilitates browser-based communication with hardware devices via the serial interface, commonly used with development boards like ESP32 or Arduino Uno for data exchange.</p>
<p>Configuring an ESP32 via the Web Serial API requires programming it to receive and respond to commands through its serial interface, typically with specialized firmware.</p>
<p>Check out this all-in-one demo: <a target="_blank" href="https://vergissberlin.github.io/example-serial-web-api/">Web Serial API Demo</a> and explore the code on GitHub for deeper insights. Establishing a connection and sending/receiving data is straightforward, as demonstrated through the provided JavaScript and Arduino examples.</p>
]]></content:encoded></item><item><title><![CDATA[What is pubspec.lock for]]></title><description><![CDATA[It is good practice to version the pubspec.lock file in a Flutter project. The pubspec.lock file contains an accurate record of the versions of the dependencies (packages) used in your Flutter project. By versioning this file, you ensure that your pr...]]></description><link>https://blog.andrelademann.de/what-is-pubspeclock-for</link><guid isPermaLink="true">https://blog.andrelademann.de/what-is-pubspeclock-for</guid><category><![CDATA[Flutter]]></category><category><![CDATA[version control]]></category><category><![CDATA[lock files]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Tue, 12 Sep 2023 10:17:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1694513695868/492a14b5-ce55-402b-a22c-74b1fe1eb759.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It is good practice to version the <code>pubspec.lock</code> file in a Flutter project. The <code>pubspec.lock</code> file contains an accurate record of the versions of the dependencies (packages) used in your Flutter project. By versioning this file, you ensure that your project will work consistently with the specified package versions in the future.</p>
<p>Here are some reasons why you should version the <code>pubspec.lock</code> file:</p>
<ol>
<li><p><strong>Reproducibility</strong>: By versioning the <code>pubspec.lock</code> file, you can ensure that other developers working on your project use the exact same versions of the dependencies. This ensures that your project works consistently in different environments.</p>
</li>
<li><p><strong>Protection against changes</strong>: If you do not version the <code>pubspec.lock</code> file and instead use only the <code>pubspec.yaml</code> file to define dependencies, updates to package versions can cause unexpected problems. The <code>pubspec.lock</code> file ensures that the defined versions are maintained until you deliberately update them.</p>
</li>
</ol>
<p>Continuous Integration (CI): If you are using Continuous Integration in your development process, the <code>pubspec.lock</code> file is important to ensure that the CI environment uses the same dependencies as your local development environment.</p>
<ol>
<li><strong>Versioning the SDK</strong>: The <code>pubspec.lock</code> file also contains information about the version of the Flutter SDK used for your project. This is important to ensure that your project is compatible with the correct Flutter SDK version.</li>
</ol>
<p>To ensure that the <code>pubspec.lock</code> file is versioned correctly, you should make sure that you commit it along with the <code>pubspec.yaml</code> file in your version control system (like Git). This ensures that other developers use the same package versions when they check out the project and install the dependencies.</p>
]]></content:encoded></item><item><title><![CDATA[Custom ChatGPT with OpenAI API]]></title><description><![CDATA[OpenAI's API is surprisingly easy to use. It is no different from other REST APIs. So integrating AI into your own software is easy, and we will see AI being integrated into more and more applications. Be it in ticket systems, email clients, content ...]]></description><link>https://blog.andrelademann.de/custom-chatgpt-with-openai-api</link><guid isPermaLink="true">https://blog.andrelademann.de/custom-chatgpt-with-openai-api</guid><category><![CDATA[chatgpt]]></category><category><![CDATA[Vue.js]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Thu, 05 Jan 2023 09:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1672909100092/da5f5fa7-c62d-4af7-9bbe-a7fa8b4c939a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>OpenAI's API is surprisingly easy to use. It is no different from other REST APIs. So integrating AI into your own software is easy, and we will see AI being integrated into more and more applications. Be it in ticket systems, email clients, content management systems (CMS) or programs to help with tax returns. Wherever there is a lot of text to be written, AI will be indispensable.<br />To test the integration, I developed my own chat with an AI:</p>
<p><a target="_blank" href="https://vergissberlin.github.io/example-openai-vuejs/">https://vergissberlin.github.io/example-openai-vuejs/</a></p>
<h2 id="heading-wanna-know-how">Wanna know how?</h2>
<p>For a chat with a bot, all you need is a GET request that contains the request and an API key. I decided to route the request through a proxy so that I don't have to make my API key public.</p>
<p><strong>Roughly speaking, the following steps are currently necessary:</strong></p>
<ol>
<li><p>First you have to register with OpenAI and get an API key.</p>
</li>
<li><p>then you have to install the OpenAI module for NodeJS by executing the following command: <code>npm install openai</code>.</p>
</li>
<li><p>then you have to import the OpenAI module into the NodeJS application and initialise the API key:</p>
</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> openai = <span class="hljs-built_in">require</span>(<span class="hljs-string">'openai'</span>); openai.apiKey = <span class="hljs-string">"API key"</span>;
</code></pre>
<ol>
<li><p>Now you can use the various functions of the OpenAI API by calling the appropriate methods on the OpenAI object. For example, one could generate the text of a document with the generate() method:</p>
<pre><code class="lang-javascript"> openai.generate({
     <span class="hljs-attr">prompt</span>: <span class="hljs-string">"text used as a template"</span>,
     <span class="hljs-attr">model</span>: <span class="hljs-string">"Name of the model used"</span>,
     <span class="hljs-attr">temperature</span>: <span class="hljs-number">0.5</span> 
 }, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error, response</span>) </span>{
     <span class="hljs-keyword">if</span> (error) <span class="hljs-built_in">console</span>.error(error);
     <span class="hljs-keyword">else</span> <span class="hljs-built_in">console</span>.log(response.text);
 });
</code></pre>
<p> <strong>That's it!</strong></p>
<h2 id="heading-cost">Cost</h2>
<p> The cost of using the OpenAI API varies depending on the specific API you are using. Some of the APIs are free to use, while others have a cost associated with them. It's also worth noting that the cost of using the API may change over time. I recommend checking the pricing page on the OpenAI website for the most up-to-date information on the cost of using the API.</p>
<p> Here is a link to the pricing page: <a target="_blank" href="https://beta.openai.com/pricing"><strong>https://beta.openai.com/pricing</strong></a></p>
<p> To take control of your cost, they provide a nice tool where you can set limits, and you can see the current usage:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672908443984/5f3b563e-2826-42fa-a95b-0d3b7924e353.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-dive-deeper">Dive deeper</h2>
<p> If you want to know more about it,</p>
<ol>
<li><p>take a look into my repo: <a target="_blank" href="https://github.com/vergissberlin/example-openai-vuejs">https://github.com/vergissberlin/example-openai-vuejs</a></p>
</li>
<li><p>Take a look into the API documentation at: <a target="_blank" href="https://beta.openai.com/docs/quickstart/build-your-applicationTranslated">https://beta.openai.com/docs/quickstart/build-your-application</a></p>
</li>
</ol>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Custom fake data generator]]></title><description><![CDATA[In 2019 (and still in 2022), we probably do not need to create data, we just need to print out one of the famous Twitter channels. Just kidding. :) Sometimes we need millions, I mean gigabytes of test data, which are really close to the data we are u...]]></description><link>https://blog.andrelademann.de/custom-fake-data-generator</link><guid isPermaLink="true">https://blog.andrelademann.de/custom-fake-data-generator</guid><category><![CDATA[faker]]></category><category><![CDATA[#test data management]]></category><category><![CDATA[etc]]></category><category><![CDATA[anonymous data]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Fri, 28 Oct 2022 10:00:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627045563858/PUdSyAJ4u.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In 2019 (and still in 2022), we probably do not need to create data, we just need to print out one of the famous Twitter channels. Just kidding. :) Sometimes we need millions, I mean gigabytes of test data, which are really close to the data we are using later for our new hyper big data application. There is a need for, because you wanna test then the performance of your stack, and you want to omit to use real data because of data privacy and licence restrictions. Thankfully, there is a group of developers out there which have created a creation tool called faker. Or should I say created a concept? Because it is implemented in various programming languages.</p>
<p>In this article, we will try out the <strong>faker</strong> implementations in NodeJS, Python and Ruby.</p>
<p>Why these languages? To be honest, I am not an expert with these languages, but these languages are known for being able to work on parallel processes and that's what we need! Because faker needs a lot of power for calculations and memory. We also need a fast hard drive, because we will work with files and that produces a lot of IO processes.</p>
<h2 id="heading-how-much-falsified-data-does-a-man-need">How much-falsified data does a man need?</h2>
<p>That depends of course on your project. To measure changes in the performance between commit, I suggest using so many items that your test does not run longer than 10 minutes on average. But for a full integration test, you should use nearly the same amount + 10% as like you have later in production. My use case is that I need 20 million users, divided into CSV files with 10 thousand users in each file. That means at least, the outcome is 200 hundred files, 19 GB of test data. So let's get do it!</p>
<h2 id="heading-parallel-processes">Parallel processes</h2>
<p>Women are known to be capable of multitasking. Developer's best friend can do this too! My lovely Mac has 4 CPUs. That means we can run 4 processes of generating the fake data in parallel without overloading him. Here is an output from HTOP, which is an advanced version of top, the process monitor for the CLI. On the top left, you can see, that my for cores waiting for orders.</p>
<h3 id="heading-output-from-htop">output from HTOP</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627045970199/FB8tTOvRV.png" alt="Terminal - htop - one thread.png" /> 
Wai Ting Loooooong!
 <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627045883093/JsNMQUhQU.png" alt="Terminal - htop - full load.png" /> With parallel processes</p>
<h2 id="heading-nodejs">NodeJS</h2>
<p>… is known to run asynchronously. But unfortunately not truly on parallel processes. In runs all in the same process, but asynchronous. The gives use not the benefit we want, with a high performance 12 core processors on board because JavaScript is a single-threaded language. We can use only one of them, except we work with child processes or workers!
I could work with workers or child processes directly, but the library worker pool gives us a nice wrapper API to play around easily with the different techniques.</p>
<h3 id="heading-worker-types">Worker types</h3>
<p>With worker pool, you have the option to choose between the worker types process and thread. In case of 'process', child_process will be used. In case of 'thread', worker_threads will be used. 
I was curious to find out if child_process or worker_threads is better for generating test data.
1st test: 90,000 test users</p>
<p>In my first test 90000 test users are generated. They are distributed over 18 CSV files.
Surprisingly for me, processes are a little bit faster than threads (child processes). But that already counts when you generate gigabytes of test data!</p>
<p>In my second test, I generated larger amounts of data. 5 million test users spread over 50 CSV files. So there are 100,000 test users in each file.</p>
<h2 id="heading-fake-it-yourself">Fake it yourself!</h2>
<p>You come so far now it's time to give it a try on your own! Checkout the repository:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/hashnode/hashnode-cli">https://github.com/hashnode/hashnode-cli</a></div>
<h2 id="heading-summary">Summary</h2>
<p>Faker is an awesome concept. It is developed in many programming languages. In that cases, I tested the JavaScript version, and I am pretty happy with the outcome. Now I am curious how faker performs in other languages like Python, Ruby, PHP, Java or go! Sounds like a good contest to me :) 
Give it a try! 
With parallel processing, it was almost 4 times faster than on a single process in my tests. And child_processes are up to 5% faster than worker_threads.
Download and try Download the example project, and try it on your machine!</p>
]]></content:encoded></item><item><title><![CDATA[Gamification has a lot of potential for companies!]]></title><description><![CDATA[Inspired by my famous CSS YouTuber 
 Kevin Powell and his CSS battles on YouTube, I organised a CSS battle in my company, Netresearch. Why? I noticed how quickly after a few tasks on CSS-battle, I was up to speed again. I learned so many new things, ...]]></description><link>https://blog.andrelademann.de/gamification-has-a-lot-of-potential-for-companies</link><guid isPermaLink="true">https://blog.andrelademann.de/gamification-has-a-lot-of-potential-for-companies</guid><category><![CDATA[CSS]]></category><category><![CDATA[coding challenge]]></category><category><![CDATA[learning]]></category><category><![CDATA[Company]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Fri, 06 May 2022 09:48:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635931092087/gGY-u_2cV.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Inspired by my famous CSS YouTuber 
 <a target="_blank" href="https://www.youtube.com/channel/UCJZv4d5rbIKd4QHMPkcABCw">Kevin Powell</a> and his CSS battles on YouTube, I organised a CSS battle in my company, Netresearch. Why? I noticed how quickly after a few tasks on CSS-battle, I was up to speed again. I learned so many new things, and it was great fun.
Having fun and learning something with friends is of course even better, I thought to myself and started the challenge in our company.</p>
<p><strong>Knowledge sharing is one of the keys to sustainable, successful businesses.</strong> Maybe my approach will help you and your colleagues to reach this goal faster and happier. </p>
<h2 id="heading-rules">Rules</h2>
<ol>
<li>one round lasts 20 minutes</li>
<li>afterwards there is a 10-minute evaluation</li>
<li>everyone writes human-readable code (no compression)</li>
<li>use of any documentation is allowed</li>
<li>The entire event is recorded. A moderator switches to the participants' screens via screen-sharing and asks questions.</li>
</ol>
<h2 id="heading-entertainment">Entertainment</h2>
<p>To entertain the spectators and participants during the competition, the participants take turns describing what they are currently working on. Furthermore, they are asked prepared questions. Here are a few examples:</p>
<p><strong>Pot 1 – Serious questions</strong></p>
<ul>
<li>What are your tasks at Netresearch?</li>
<li>Have you had another job before?</li>
<li>What else do you do when you are not programming?</li>
<li>What is your favourite programming language?</li>
</ul>
<p><strong>Pot 2 – Fun questions / tasks</strong></p>
<ul>
<li>Tell a joke!</li>
<li>What profession would your parents have imagined for you?</li>
<li>If you had become a girl/boy, what would your first name be?</li>
</ul>
<p><strong>Pot 3 – Tricky questions</strong></p>
<ul>
<li>What can you find on http://info.cern.ch ? – The first website ever.</li>
<li>Have you ever peed standing up?</li>
<li>Have you ever stolen a sweet from a colleague's desk?</li>
<li>What was your most embarrassing experience at work?</li>
</ul>
<p><strong>Pot 4 – Nasty questions for an applicant</strong></p>
<ul>
<li>How do you feel about being criticised?</li>
<li>What was your biggest mistake - and what have you learned from it?</li>
<li>When was the last time you disregarded a rule or regulation, and why?</li>
<li>What added value would your attitude bring to our company?</li>
</ul>
<h2 id="heading-tools">Tools</h2>
<p><strong>To participate in the event</strong>, the opponents will need the following items:</p>
<ul>
<li>Video conferencing software with the possibility to share the screen</li>
<li>Microphone and a webcam</li>
<li>A browser</li>
</ul>
<p><strong>To organise such an event, you will need</strong></p>
<ul>
<li>Video conferencing software with screen sharing capability</li>
<li><a target="_blank" href="https://obsproject.com/">OBS</a> for recording and streaming</li>
<li>Voting tool</li>
<li>Coding Battle platform such as <a target="_blank" href="https://cssbattle.dev/">cssbattle.dev</a></li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651752852548/YqR4cnR-w.png" alt="image.png" /></p>
<h2 id="heading-prizes">Prizes</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651753871514/Opaa-WIGW.png" alt="image.png" /></p>
<p>At the end of a competition, the award ceremony is always a crowning event. The appreciation of the winner's performance by all participants. For our first battle, I chose CSS. Getting the frontend developers excited wasn't particularly difficult, but I wanted to get more colleagues on board from the backend as well, so I asked our marketing department for prizes for the winners.</p>
<ul>
<li>Audience Award (Voting)</li>
<li><strong>The Highest score</strong> in CSS Battle platform</li>
</ul>
<h2 id="heading-summary">Summary</h2>
<p>Imparting knowledge in a playful way is not a new invention. My goal with this article is to show that this can also work for knowledge exchange in companies in the IT sector. At our first Coding Battle, we had a lot of fun and learned a lot. Organising an event like this takes a lot of effort the first time. The second time, it's much easier. So the key to success is regularity.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651751131444/uRrggukjy.png" alt="image.png" /></p>
<p>I would be pleased if you would also conduct a battle in your company and tell me about your experiences! 
You want to know more about it?  Get in touch with me!</p>
<h2 id="heading-this-is-how-it-looks-like">This is how it looks like</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=20QiX8rmHnU&amp;feature=emb_imp_woyt">https://www.youtube.com/watch?v=20QiX8rmHnU&amp;feature=emb_imp_woyt</a></div>
]]></content:encoded></item><item><title><![CDATA[Using MJML to improve your email in Node-RED]]></title><description><![CDATA[Sending emails with Node-RED is very easy. The email node is easy to configure. Variables can be used in the content area, which we can use to include sensor data, for example.
If you want to send an email in HTML format, there is a lot to consider, ...]]></description><link>https://blog.andrelademann.de/using-mjml-to-improve-your-email-in-node-red</link><guid isPermaLink="true">https://blog.andrelademann.de/using-mjml-to-improve-your-email-in-node-red</guid><category><![CDATA[Node.js]]></category><category><![CDATA[No Code]]></category><category><![CDATA[email]]></category><category><![CDATA[HTML Emails]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Thu, 05 May 2022 11:06:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1643238565640/0YzkqMb8H6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sending emails with Node-RED is very easy. The email node is easy to configure. Variables can be used in the content area, which we can use to include sensor data, for example.</p>
<p>If you want to send an email in HTML format, there is a lot to consider, because the different email clients have certain expectations about how the HTML code of the email should be structured. To make this task easier, there is MJML. <em>MJML</em> stands for Mailjet Markup Language to help developers code emails in a simpler and more efficient way. And to facilitate the use of MJML in Node-RED, I have written a node.</p>
<p>In this article, we will install the node and send a well-structured, beautiful-looking email as an example.</p>
<h1 id="heading-node-red-contrib-mjml">node-red-contrib-mjml</h1>
<h2 id="heading-installation">Installation</h2>
<p>As a requirement, you need to have Node-RED <a target="_blank" href="https://nodered.org/docs/getting-started/local">to be installed</a>. Then change directory to your Node-RED installation and run:</p>
<pre><code class="lang-shell">npm install @vergissberlin/node-red-contrib-mjml
</code></pre>
<p><strong>OR</strong> go to your pallet settings in your Node-RED admin UI and search for "mjml".</p>
<h2 id="heading-basic-template-example">Basic template example</h2>
<p>Let's now set up a basic flow with which we can send our first mail.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643238680160/CcKIe9xY6.png" alt="image.png" /></p>
<ol>
<li>Copy and import the following flow into your Node-RED: https://github.com/vergissberlin/node-red-contrib-mjml/blob/main/examples/Parse%20node%20example.json</li>
<li>Configure the credentials and receiver address in the email node and press the deploy button</li>
<li>Use the button one the debug node to trigger the email proccess.</li>
</ol>
<p>You will get an email which looks like this:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643239000985/yPBbX5I3f.png" alt="image.png" /></p>
<p><strong>Pretty cool, right?</strong></p>
<h2 id="heading-deep-look-into-the-markup-and-how-to-use-it">Deep look into the markup and how to use it</h2>
<p><em>MJML</em> has a great <a target="_blank" href="https://documentation.mjml.io/">documentation</a>, and an <a target="_blank" href="https://mjml.io/try-it-live/templates/basic">online-editor</a> where you can create your email templates easily. There are other pretty fancy looking, ready to use and bulletproof templates available on their <a target="_blank" href="https://mjml.io/templates">website</a>.</p>
<p>MJML is a markup language like HTML and here is the example we use in our flow:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">mjml</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">mj-body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">mj-section</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">mj-column</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">mj-image</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"100px"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/assets/img/logo-small.png"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">mj-image</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">mj-divider</span> <span class="hljs-attr">border-color</span>=<span class="hljs-string">"#F45E43"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">mj-divider</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">mj-text</span> <span class="hljs-attr">font-size</span>=<span class="hljs-string">"20px"</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"#F45E43"</span> <span class="hljs-attr">font-family</span>=<span class="hljs-string">"helvetica"</span>&gt;</span>
            Hello World
        <span class="hljs-tag">&lt;/<span class="hljs-name">mj-text</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">mj-text</span>&gt;</span>
          Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem 
          Ipsum has been the industry's standard dummy text ever since the 1500s, when 
          an unknown printer took a galley of type and scrambled it to make a type 
          specimen book. It has survived not only five centuries, but also the leap into 
          electronic typesetting, remaining essentially unchanged. It was popularised in the 
          1960s with the release of Letraset sheets containing Lorem Ipsum passages, and 
          more recently with desktop publishing software like Aldus PageMaker including 
          versions of Lorem Ipsum.
        <span class="hljs-tag">&lt;/<span class="hljs-name">mj-text</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">mj-column</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mj-section</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">mj-body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">mjml</span>&gt;</span>
</code></pre>
<p>Now we can use variables for sensor data like so:</p>
<pre><code class="lang-html">[…]
        <span class="hljs-tag">&lt;<span class="hljs-name">mj-text</span>&gt;</span>Random number: {msg.payload}<span class="hljs-tag">&lt;/<span class="hljs-name">mj-text</span>&gt;</span>
[…]
</code></pre>
<h2 id="heading-summary">Summary</h2>
<p>Send beautiful, well-structured email with Node-RED is now an easy task to do.
If you like to take a look into the source code, you can do it. It's open source and published on <a target="_blank" href="https://github.com/vergissberlin/node-red-contrib-mjml/">GitHub</a>.</p>
<h2 id="heading-links">Links</h2>
<ul>
<li><a target="_blank" href="https://flows.nodered.org/node/@vergissberlin/node-red-contrib-mjml">Node-RED repository</a></li>
<li><a target="_blank" href="http://nodered.org/">Node-RED</a></li>
<li><a target="_blank" href="https://documentation.mjml.io/">MJML documentation</a></li>
<li><a target="_blank" href="https://mjml.io/templates">MJML templates</a></li>
</ul>
<h3 id="heading-repository-on-github">Repository on GitHub</h3>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/vergissberlin/node-red-contrib-mjml">https://github.com/vergissberlin/node-red-contrib-mjml</a></div>
]]></content:encoded></item><item><title><![CDATA[Benchmark - What is the quickest way to copy files?]]></title><description><![CDATA[Purpose
In software development, there is sometimes a need to copy a large amount of file from one directory to another. For instance, when you have shared volumes in a Docker environment with different services, some services need to have access to ...]]></description><link>https://blog.andrelademann.de/benchmark-what-is-the-quickest-way-to-copy-files</link><guid isPermaLink="true">https://blog.andrelademann.de/benchmark-what-is-the-quickest-way-to-copy-files</guid><category><![CDATA[Benchmark]]></category><category><![CDATA[files]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Mon, 02 May 2022 22:02:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651528821122/RjPzzuvRp.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-purpose">Purpose</h2>
<p>In software development, there is sometimes a need to copy a large amount of file from one directory to another. For instance, when you have shared volumes in a <a target="_blank" href="https://docker.com/">Docker</a> environment with different services, some services need to have access to the application source files, you put the source code in a volume which is shared between these services. On an initial boot up, or on an update of the app image, there is a need to update the files in the volume.</p>
<h3 id="heading-test-arrangement">Test arrangement</h3>
<p>For our testing scenario, we try to use a common use case. It is an application image with 140195 files. I used an installed Magento 2 within its all its dependencies.</p>
<p>As a benchmark tool for the CLI, I used <a target="_blank" href="https://github.com/sharkdp/hyperfine">hyperfine</a> on macOS.</p>
<h3 id="heading-test-use-cases">Test use cases</h3>
<ol>
<li>On an initial boot up, the target directory is empty. We have to copy all files from one directory to another.</li>
<li>The second use case to just update files where is a change.</li>
</ol>
<h2 id="heading-cp">CP</h2>
<p><a target="_blank" href="http://manpages.ubuntu.com/manpages/cosmic/man1/cp.1.html">CP</a> is a very basic functionality in Linux based shells. It’s made to copy files. It is possible to copy recursively. It keeps the directory structure. The target directory should be empty. Perfect! Let’s get do it!</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>parameter</td><td>description</td></tr>
</thead>
<tbody>
<tr>
<td>-R, -r, --recursive</td><td>copy directories recursively</td></tr>
<tr>
<td>-u, --update</td><td>copy only when the SOURCE file is newer than  the  destination  file  or  when  the destination file is missing</td></tr>
<tr>
<td>-p, --preserve[=ATTR_LIST]</td><td>preserve the specified attributes (default: mode, ownership, timestamps), if possible additional attributes: context, links, xattr, all</td></tr>
</tbody>
</table>
</div><h3 id="heading-test-with-cp">Test with <code>cp</code></h3>
<pre><code class="lang-bash">hyperfine \
    <span class="hljs-string">'cp -upr --sparse=never src tmp-cp'</span> \
    <span class="hljs-string">'cp -upr --sparse=never src tmp-cp'</span>
</code></pre>
<p>It copies file by file from source to target without checking if there are any changes in it.</p>
<pre><code class="lang-bash">hyperfine <span class="hljs-string">'cp -upr --sparse=never src tmp-cp'</span> <span class="hljs-string">'cp -upr --sparse=never src tmp-cp'</span>
Benchmark <span class="hljs-comment">#1: cp -upr --sparse=never src tmp-cp</span>
  Time (mean ± σ):     11.744 s ± 32.450 s    [User: 775.2 ms, System: 2396.0 ms]
  Range (min … max):    1.284 s … 104.094 s

Benchmark <span class="hljs-comment">#2: cp -upr --sparse=never src tmp-cp</span>
  Time (mean ± σ):      1.397 s ±  0.086 s    [User: 326.0 ms, System: 1033.2 ms]
  Range (min … max):    1.308 s …  1.511 s
</code></pre>
<h2 id="heading-rsync">rsync</h2>
<p><a target="_blank" href="http://manpages.ubuntu.com/manpages/cosmic/man1/rsync.1.html">Rsync</a> copies files either to or from a remote host, or locally on the current host as like CP. It tries to improve the speed by using an index file. Rsync finds files that need to be transferred using a "quick check" algorithm that looks for files that have changed in size or in last-modified time.  Any changes in the other preserved attributes (as requested by options) are made on the destination file directly when the quick check indicates that the file’s data does not need to be updated.</p>
<p>So we assume that there is no improvement on the first copy, but on updating files.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>parameter</td><td>description</td></tr>
</thead>
<tbody>
<tr>
<td>-u, --update</td><td>skip files that are newer on the receiver</td></tr>
<tr>
<td>-p, --perms</td><td>preserve permissions</td></tr>
<tr>
<td>--del, --delete</td><td>delete extraneous files from dest dirs</td></tr>
<tr>
<td>--force</td><td>force deletion of dirs even if not empty</td></tr>
<tr>
<td>--size-only</td><td>skip files that match in size</td></tr>
<tr>
<td>-r, --recursive</td><td>recurse into directories</td></tr>
<tr>
<td>-q, --quiet</td><td>suppress non-error messages</td></tr>
<tr>
<td>-z, --compress</td><td>compress file data during the transfer</td></tr>
</tbody>
</table>
</div><h3 id="heading-test-with-rsync">Test with rsync</h3>
<pre><code class="lang-bash">hyperfine \
    <span class="hljs-string">'rsync -a src tmp-rsync'</span> \
    <span class="hljs-string">'rsync -a src tmp-rsync'</span>

Benchmark <span class="hljs-comment">#1: rsync -a src tmp-rsync</span>
  Time (mean ± σ):      7.710 s ± 19.948 s    [User: 1.330 s, System: 2.346 s]
  Range (min … max):    1.254 s … 64.481 s

Benchmark <span class="hljs-comment">#2: rsync -a src tmp-rsync</span>
  Time (mean ± σ):      1.424 s ±  0.147 s    [User: 543.1 ms, System: 837.6 ms]
  Range (min … max):    1.281 s …  1.779 s
</code></pre>
<h2 id="heading-tar">Tar</h2>
<p><a target="_blank" href="http://manpages.ubuntu.com/manpages/cosmic/man1/tar.1.html">tar</a> creates and manipulates streaming archive files.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Parameter</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>-f file</td><td>Read the archive from or write the archive to the specified file.</td></tr>
<tr>
<td>-q (--fast-read)</td><td>Extract, or list only the first archive entry that matches each pattern or filename operand.  Exit as soon as each specified pattern or filename has been matched.  By default, the archive is always read to the very end, since there can be multiple entries with the same name and, by convention, later entries overwrite earlier entries. This option is provided as a performance optimization.</td></tr>
<tr>
<td>-x</td><td>Extract to disk from the archive.  If a file with the same name appears more than once in the archive, each copy will be extracted, with later copies overwriting (replacing) earlier copies.</td></tr>
<tr>
<td>-C, --directory=DIR</td><td>Change  to  DIR  before performing any operations.  This option is order-sensitive, i.e. it affects all options that follow.</td></tr>
</tbody>
</table>
</div><h3 id="heading-test-with-tar">Test with tar</h3>
<pre><code class="lang-bash">hyperfine <span class="hljs-string">'tar -qxf src.tar -C tmp-tar'</span> <span class="hljs-string">'tar -qxf src.tar -C tmp-tar'</span>
Benchmark <span class="hljs-comment">#1: tar -xf src.tar</span>
  Time (mean ± σ):     53.214 s ±  4.403 s    [User: 3.303 s, System: 12.450 s]
  Range (min … max):   50.510 s … 65.249 s
Benchmark <span class="hljs-comment">#1: tar -xf src.tar -C tmp-tar</span>
  Time (mean ± σ):     54.455 s ±  0.434 s    [User: 3.551 s, System: 12.724 s]
  Range (min … max):   54.006 s … 55.305 s
</code></pre>
<hr />
<h2 id="heading-consumption">Consumption</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651527850616/3iln6ez4a.png" alt="image.png" /></p>
<p>These tests have shown that <em>CP</em> is slightly faster than <em>RSYNC</em> when updating. However, <strong>CP takes significantly more time to initially copy the files</strong>. TAR is faster on the first copy as CP, but it has no advantages over RSYNC.</p>
]]></content:encoded></item><item><title><![CDATA[The reversed .gitignore]]></title><description><![CDATA[The .gitignore is there to prevent files from ending up in git's version management that have no business being there. You can find them in most repositories in the world.
Creating these is a tedious and sometimes tricky task.
For example, files that...]]></description><link>https://blog.andrelademann.de/the-reversed-gitignore</link><guid isPermaLink="true">https://blog.andrelademann.de/the-reversed-gitignore</guid><category><![CDATA[Git]]></category><category><![CDATA[version control]]></category><category><![CDATA[versioning]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Thu, 18 Nov 2021 12:56:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1637240111672/WhQh-_uLI.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <code>.gitignore</code> is there to prevent files from ending up in git's version management that have no business being there. You can find them in most repositories in the world.
Creating these is a tedious and sometimes tricky task.
For example, files that the operating system creates, files that our various IDEs create, plus language and project specific files and directories. Entries must be made for all of these variations  <strong>and so the list gets longer and longer.</strong></p>
<p>In addition, there may also be security-relevant files such as <code>.env</code>, which may contain passwords. Once such a file has been versioned, it could be somewhat difficult to get it out of the version history.</p>
<p>There are several generators on the web to create a <code>.gitignore</code> file. There are also prefabricated templates on  <a target="_blank" href="https://github.com">GitHub</a>  that you can choose from when creating a repository.
There are many files to think about. </p>
<p><strong>But that doesn't have to be the case!</strong> Instead of excluding all files that you don't like, you can also explicitly specify in the <code>.gitignore</code> which files should end up in the version management.</p>
<h3 id="pros-and-cons">Pros and cons</h3>
<p>✅ Protection against unintentional commit of files of OS, IDE or test files</p>
<p>✅ Improve security (exclude .env files automatically)</p>
<p>❌ On commit, take care that all your files are included</p>
<h2 id="how-to-do-it-the-other-way-around">How to do it the other way around</h2>
<p>First we ignore all files</p>
<pre><code><span class="hljs-comment"># Ignore all files</span>
/*
</code></pre><p>to then exclude the files that we really want to have versioned. You can specify individual files, but also entire directories.</p>
<pre><code><span class="hljs-comment"># Ignore all files</span>
<span class="hljs-string">/*</span>

<span class="hljs-comment"># Except these files</span>
<span class="hljs-type">!/app/</span>
<span class="hljs-type">!/README.md</span>
</code></pre><p><strong>Beware!</strong> There is one special thing to note here. All files are really excluded. Including the <code>.gitignore</code> file itself. We must therefore also explicitly add it to the list of wanted files.</p>
<pre><code><span class="hljs-comment"># Ignore all files</span>
<span class="hljs-string">/*</span>

<span class="hljs-comment"># Except these files</span>
<span class="hljs-type">!/app/</span>
<span class="hljs-type">!/README.md</span>
<span class="hljs-type">!/.gitignore</span>
</code></pre><h3 id="ignore-files-within-a-subdirectory">Ignore files within a subdirectory</h3>
<p>That use case is al little bit tricky. Imagine you have a file in the APP directory that you want to ignore, but not the other files it contains. Than you have to do that</p>
<pre><code><span class="hljs-comment"># Ignore all files</span>
<span class="hljs-string">/*</span>

<span class="hljs-comment"># Except these files</span>
<span class="hljs-type">!/app/</span>
<span class="hljs-type">!/README.md</span>
<span class="hljs-type">!/.gitignore</span>

<span class="hljs-comment"># But ignore this file without the allowed path</span>
<span class="hljs-string">/app/.env</span>
</code></pre><h2 id="conclusion">Conclusion</h2>
<p>With the other way around in the <code>.gitignore</code> you have full control what's going into the repository. You do not check in files accidentally. <strong>But</strong> if you create files, you may have to think about it more than before if it is not within the ignore path!
This change brings some advantages. At the beginning, however, it takes a little getting used to for many people to always remember to expand the file list when they add a new file or directory.
This is a principle that can also be used for other software. As for example in the <code>.dockerignore</code>.</p>
<p><img src="https://i.giphy.com/media/26gscNQHswYio5RBu/giphy-downsized-large.gif" alt="Clean up" /></p>
]]></content:encoded></item><item><title><![CDATA[Trainees in the IT industry in Germany]]></title><description><![CDATA[Today I was having lunch with IT colleagues and we were talking about our trainee. One colleague who previously worked in another industry thought that his manner was inappropriate for a trainee. When I was an apprentice, I could not have allowed mys...]]></description><link>https://blog.andrelademann.de/trainees-in-the-it-industry-in-germany</link><guid isPermaLink="true">https://blog.andrelademann.de/trainees-in-the-it-industry-in-germany</guid><category><![CDATA[training]]></category><category><![CDATA[Culture]]></category><category><![CDATA[internships]]></category><category><![CDATA[leadership]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Tue, 02 Nov 2021 20:11:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635871297630/sB-xcUoEv.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today I was having lunch with IT colleagues and we were talking about our trainee. One colleague who previously worked in another industry thought that his manner was inappropriate for a trainee. When I was an apprentice, I could not have allowed myself to disagree when most of the colleagues had a different opinion." This is a culture that I did not have experienced in IT companies yet.
If someone says "Is PHP the right language to solve the problem?" then it's good for us to think about it again. Even if the answer is "yes" afterwards, it's good to question yourself again and again and even more so when the question comes from a trainee who has a fresh perspective on things.
After thinking about it for a while, I have come to the conclusion that <strong>nay-sayers promote innovation even if they are sometimes annoying</strong>. Yay-sayers are just as important for getting things done. As always, it depends on a good mix in the team. Like yin and yang.</p>
<p><img src="https://i.giphy.com/media/Drm4jtLn5SWwFaimGV/giphy.webp" alt="Just say no" /></p>
<p>In an industry with complex problems, we need people who think and act independently. In the wiki of my employer  <a target="_blank" href="https://netresearch.de">Netresearch</a>  there is an appropriate graphic that describes the company culture well. Or the aspired corporate culture as presented self-critically.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635883368490/H8lBdKCA4.png" alt="Alignment enables autonomy.png" /></p>
<p>I am very happy to work in the IT industry, that became clear to me again today.</p>
<p>Best regards
André</p>
<hr />
<h2 id="credits-and-links">Credits and links</h2>
<h3 id="cliparts">Cliparts</h3>
<ul>
<li>Mean Boss Cliparts #2867138 http://clipart-library.com/clipart/880897.htm</li>
<li>Mean Boss Cliparts #2867116 http://clipart-library.com/clipart/880641.htm</li>
<li>Mean Boss Cliparts #2867135 http://clipart-library.com/clipart/880874.htm</li>
<li>Boss Cliparts #34897 http://clipart-library.com/clipart/271303.htm</li>
</ul>
<h3 id="book">Book</h3>
<ul>
<li>The Art of Action: How Leaders Close the Gaps between Plans, Actions and Results https://amzn.to/2ZS5uWC</li>
</ul>
<h3 id="video">Video</h3>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=_qIh2sYXcQc">https://www.youtube.com/watch?v=_qIh2sYXcQc</a></div>
]]></content:encoded></item><item><title><![CDATA[VS Code includes GitHub's CoPilot  and I just love it!]]></title><description><![CDATA[The year is 2021, and  Elon Musk  is so  scared about AI and its danger to humanity that he is pushing to build big rockets 🚀 to land on Mars as soon as possible. And he has to know it, he is one of the investors in OpenAI, a company (largely owned ...]]></description><link>https://blog.andrelademann.de/vs-code-includes-githubs-copilot-and-i-just-love-it</link><guid isPermaLink="true">https://blog.andrelademann.de/vs-code-includes-githubs-copilot-and-i-just-love-it</guid><category><![CDATA[AI]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[Visual Studio Code]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Wed, 28 Jul 2021 22:12:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627502419567/N07MP5fHG.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The year is 2021, and  <a target="_blank" href="https://twitter.com/elonmusk">Elon Musk</a>  is so  <a target="_blank" href="https://www.youtube.com/watch?v=KdTTeR4TyMc">scared about AI</a> and its danger to humanity that he is pushing to build <a target="_blank" href="https://en.wikipedia.org/wiki/SpaceX_Starship">big rockets</a> 🚀 to land on Mars as soon as possible. And he has to know it, he is one of the investors in <em>OpenAI</em>, a company (largely owned by Microsoft) that has developed an AI program called <a target="_blank" href="https://en.wikipedia.org/wiki/GPT-3">GPT-3</a>.
This AI is now used by GitHub in Microsoft's editor <em>Visual Studio Code</em> to write code, based on comments we write in the document.
To this day, most programmers do not use this technology to write their code. Everything is <em>handwritten</em> (more or less, or copied from somewhere on the net). I imagine that in the near future, we will smile about this as much as about programmers with <a target="_blank" href="https://blog.patracompany.com/the-history-of-the-computer-bug">real bugs</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Punched_card">punch cards</a>. 🤣</p>
<p><img src="https://media.giphy.com/media/l0HlMDr5SOKGpNu5a/source.gif" alt="Punch card reader" /></p>
<h2 id="so-why-i-am-so-excited">So, why I am so excited?</h2>
<p>I can imagine myself laughing at myself one day when I read this in the distant future, or I cry and say to my granddaughter "We used to write code by hand, and it was legible, clear and beautiful, not like what the AI does today."</p>
<p>When I tried AI for the first time, I was so amazed! One line after the other filled with meaningful content (aka code), and I just pressed the tab key, tab key, tab key …</p>
<p><strong>Even a chicken can program in that way!</strong>
<img src="https://media.giphy.com/media/l3vR9IEU6nYAmZyoM/giphy.gif" alt="Programmer chicken" /></p>
<p>If CoPilot where allowed to bring the sentence <strong>"From today's perspective, […]"</strong> to an end, it would write:</p>
<pre><code class="lang-python">we can see the AI <span class="hljs-keyword">as</span> a tool that can help us write code 
that <span class="hljs-keyword">is</span> more readable, more maintainable, <span class="hljs-keyword">and</span> more efficient.
</code></pre>
<p><strong>Oh shit wait!</strong> It really completed the 🤖🤖🤖 <code>sentence, and it is more readable, more maintainable, and more efficient!</code> 🤖🤖🤖</p>
<p><img src="https://media.giphy.com/media/WgIcdi8Wf2Ywq5dWOI/source.gif" alt="AI fights back" /></p>
<p><strong>STOP!! Go away! Arrrrgghhh!</strong></p>
<h3 id="the-sorcerers-apprentice-gothe-der-zauberlehrling-1798">The Sorcerer's Apprentice, <em>(Göthe, Der Zauberlehrling, 1798)</em></h3>
<blockquote>
<p>I have need of Thee!
from the spirits that I called
Sir, deliver me!</p>
<p>Back now, broom,
into the closet!
Be thou as thou
wert before!
Until I, <strong>the real master</strong>
call thee forth to serve once more!</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627506520743/4oQvELgaD.gif" alt="copilots-never-die-downsized_large.gif" /></p>
<h2 id="links">Links</h2>
<ul>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/GPT-3">GPT-3 on Wikipedia</a> </li>
<li><a target="_blank" href="https://openai.com/">OpenAI</a> </li>
<li><a target="_blank" href="https://copilot.github.com/">GitHub CoPilot</a> </li>
<li><a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a> </li>
</ul>
<hr />
<p><em>Note: The co-pilot usually sits on the right-hand side.</em></p>
<hr />
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=4duqI8WyfqE">https://www.youtube.com/watch?v=4duqI8WyfqE</a></div>
]]></content:encoded></item><item><title><![CDATA[Pair programming]]></title><description><![CDATA[In pair programming, two developers work simultaneously on one source code. The method helps to develop better software products. 
Advantages
At Netresearch, we use this method and derive many advantages from it:

Direct knowledge exchange about meth...]]></description><link>https://blog.andrelademann.de/pair-programming</link><guid isPermaLink="true">https://blog.andrelademann.de/pair-programming</guid><category><![CDATA[pair programming]]></category><category><![CDATA[communication]]></category><category><![CDATA[remote]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Wed, 28 Jul 2021 08:44:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627334092061/n6o-qbpil.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In pair programming, two developers work simultaneously on one source code. The method helps to develop better software products. </p>
<h2 id="advantages">Advantages</h2>
<p>At Netresearch, we use this method and derive many advantages from it:</p>
<ul>
<li>Direct knowledge exchange about methods, tools used and ways of working.</li>
<li>Improvement of code quality through direct code review, which leads to more robust code.</li>
<li>Improving collaboration through communication </li>
<li>When you have to describe approaches verbally, new ideas come up and thinking errors are noticed.</li>
<li>In dialogue, the best solution can be found.</li>
<li>A shared sense of achievement makes people more satisfied with the result.</li>
</ul>
<h2 id="stereotype">Stereotype</h2>
<p>In the short term, you might think that you need twice as much development time for a feature, but in fact, <strong>the elimination of a code review, the exchange of knowledge and the more robust code do not result in additional costs in the long term</strong>.</p>
<h2 id="disadvantages">Disadvantages</h2>
<p>The strong feeling that you are desperate to get to the keyboard because you just can't seem to describe the problem in a way that your co-pilot understands. This can take years of your life and lead to grey hair! Also, your nails may break if you grip the seat cushion of your office chair too hard.</p>
<h2 id="rules">Rules</h2>
<p>You and your boss are convinced, and you wonder how to start?  There are a few rules for pair programming that you should follow:</p>
<ol>
<li>Switch keyboard control at least every 15 Minutes. It helps that both programmers are on track, the hole time.</li>
<li>Writing code is accompanied by language.</li>
<li>You have to pinch yourself to say, "I'll do it quickly".</li>
<li>Pair programming is not a must. Sometimes there are routine tasks where knowledge cannot be shared.</li>
<li>Tidy up your desk to prepare that you are not alone.</li>
<li>If your meat each other in real life, take a shower in the morning :D</li>
</ol>
<h2 id="pair-programming-remotely">Pair programming remotely</h2>
<p>Sitting together at a computer is probably the most beautiful thing of all. Probably many stock photos were taken during pair programming, where one of the developers smiles and points at the monitor. Something silly  <a target="_blank" href="https://www.netresearch.de/blog/webseiten-bauen-im-schuelerpraktikum-bei-netresearch/">like that</a>  ... or  <a target="_blank" href="https://www.netresearch.de/blog/schuelerpraktikum-bei-netresearch/">this</a> ! tsss ...</p>
<p>But how does pair programming work when the workplaces are kilometres apart? There are a few techniques for this, such as  <a target="_blank" href="https://www.remotemobprogramming.org/">git handover</a>, but what I would like to introduce today is <strong>Code With Me</strong> by JetBrains. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627335529466/C7DFm2PMj.png" alt="image-20210521-081647.png" /></p>
<p>One day I actually read through one of the tips that pop up when you open <em>Android Studio</em> / <em>WebStorm</em> / <em>PHPStorm</em> / <em>RubyMine</em> / <em>PyCharm</em> / <em>GoLand</em> / <em>CLine</em> or another derivate of IntelliJ IDE and discovered this feature. There are already several other editors that allow you to work together on a file, but with <em>Code With Me</em>, JetBrains from the Czech Republic has taken it to a new level. </p>
<ol>
<li>Invitations to a pair programming session via a link,</li>
<li>control of access rights,</li>
<li>audio and video chat are also integrated.</li>
<li>A follow-up mode, in which you can also follow when your partner opens a new file or scrolls down.</li>
</ol>
<p>You can start a pair programming session by clicking on the user icon in the top right-hand corner.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627335740553/w5uJC2jTv.png" alt="image-20210521-082055.png" /></p>
<hr />
<h2 id="summary">Summary</h2>
<p>I don't want to repeat the prejudice, but you should know them if your project manager counter-argues with the following arguments in order to be prepared.
The prejudice "One problem to solve + two programmers working on it = twice the effort" is false. 
You improve code quality, which mean at least less bugs. You share knowledge and improve your communication skills.</p>
<h2 id="questions">Questions</h2>
<p>Have you ever tried <em>couples programming</em> or even <em>mob programming</em> at regular intervals? What are your experiences with it? How have your bosses reacted?</p>
]]></content:encoded></item><item><title><![CDATA[DRY 🍸️ – design pattern]]></title><description><![CDATA[Excuses to do it

"It's another project. I don't know much about it. Don't wanna break something, so I just copied it."
"I don't have time, maybe later …"
"Maybe later on, I want to have something different in each function/template/class, so it's be...]]></description><link>https://blog.andrelademann.de/dry-design-pattern</link><guid isPermaLink="true">https://blog.andrelademann.de/dry-design-pattern</guid><category><![CDATA[design patterns]]></category><category><![CDATA[design principles]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Tue, 27 Jul 2021 11:30:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627330795432/ZxwFTJZjm.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="excuses-to-do-it">Excuses to do it</h2>
<ul>
<li>"It's another project. I don't know much about it. Don't wanna break something, so I just copied it."</li>
<li>"I don't have time, maybe later …"</li>
<li>"Maybe later on, I want to have something different in each function/template/class, so it's better to copy it."</li>
</ul>
<h2 id="advantages-to-keep-it-dry">Advantages - to keep it DRY</h2>
<ul>
<li>If you have to change something later on, you may have to do it twice (or even multiple times) to achieve your goal. So it is easier to maintain.</li>
<li>Less code - is better code.  Just remember, if you copy something, you must copy the tests as well! You do test, don't you? 🤨</li>
</ul>
<h2 id="ways-to-take-care-about-it-without-even-thinking">Ways to take care about it without even thinking</h2>
<p><strong>Automatization</strong> is the key. No matter which language do you use in your current project, there is a <em>copy paste detector</em> out there. There are some for specific languages:</p>
<ul>
<li>JavaScript  <a target="_blank" href="https://www.npmjs.com/package/jscpd">jscpd</a> </li>
<li>PHP  <a target="_blank" href="https://phpqa.io/projects/phpcpd.html">phpcpd</a> </li>
</ul>
<p>… and some with cross language support like  <a target="_blank" href="https://pmd.github.io/">PMD</a>  or  <a target="_blank" href="https://github.com/kucherenko/basta">Basta</a>.</p>
<h3 id="usage">Usage</h3>
<p>Easy to install and simple to use. You can even export machine-readable reports to show the results in a graph over time, for example. In my case, I used XML for my C++ report, which is compatible with good old Jenkins.</p>
<pre><code class="lang-bash">./run.sh cpd --files /path/to/<span class="hljs-built_in">source</span> --language cpp --format xml
</code></pre>
<h2 id="summary">Summary</h2>
<p><img src="https://i.imgflip.com/5hn72r.jpg" alt="Dry not shaken" /></p>
<p>It doesn't take much effort to keep things dry. Just pull up your pants and take care of it! Automation with tests and copy-and-paste detectors can help to improve your code quality and the maintainability of your software.</p>
<h2 id="questions">Questions</h2>
<ol>
<li>Are you try? Sometimes?</li>
<li>Do you inspect your code automatically?</li>
<li>If yes, which tool do you use to visualize the results?</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[KISS 😘 – design pattern]]></title><description><![CDATA[Yah, that's a very emotional speech for a programming design pattern. As a side note, it tells us about the many stories in which they have struggled through complex programming code of their colleagues or even themselves from the past.
keep it small...]]></description><link>https://blog.andrelademann.de/kiss</link><guid isPermaLink="true">https://blog.andrelademann.de/kiss</guid><category><![CDATA[design patterns]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Mon, 26 Jul 2021 19:57:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627329461471/R8bAgQbO-.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Yah, that's a very emotional speech for a programming design pattern. As a side note, it tells us about the many stories in which they have struggled through complex programming code of their colleagues or even themselves from the past.
<strong>keep it small and simple</strong> describes it a little better, but it sounds not so remarkable.</p>
<h2 id="example">Example</h2>
<p>You may say the answer to that question is easy? <strong>But it's not what you think!</strong></p>
<p>For better testing, we split our function, so that any function hast a single responsibility. So, each function is very readable and easy to test with unit tests. As an example, let's create a primitive calculator, which is able to add, subtract, multiply or divide two arguments each other.</p>
<h3 id="good-example">Good example?</h3>
<pre><code class="lang-javascript"><span class="hljs-comment">// Add two arguments to each other</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">a, b</span>) </span>{
    <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-comment">// Subtraction of two numbers</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">subtract</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a - b;
}

<span class="hljs-comment">// Multiply the first argument by the second</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multiply</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a * b;
}

<span class="hljs-comment">// Divides the first argument by the second</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">divide</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a / b;
}

<span class="hljs-comment">// Delegate two numbers and their operant to the correct function</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculator</span>(<span class="hljs-params">a, b, operator</span>) </span>{
  <span class="hljs-keyword">switch</span> (operator) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'+'</span>:
      <span class="hljs-keyword">return</span> add(a, b);
    <span class="hljs-keyword">case</span> <span class="hljs-string">'-'</span>:
      <span class="hljs-keyword">return</span> subtract(a, b);
    <span class="hljs-keyword">case</span> <span class="hljs-string">'*'</span>:
      <span class="hljs-keyword">return</span> multiply(a, b);
    <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>:
      <span class="hljs-keyword">return</span> divide(a, b);
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-string">'Error'</span>;
  }
}
</code></pre>
<h3 id="bad-example">Bad example?</h3>
<pre><code class="lang-javascript"><span class="hljs-comment">// caclulator which can add, subtract, multiply and divide two numbers</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculator</span>(<span class="hljs-params">a, b, operator</span>) </span>{
    <span class="hljs-keyword">let</span> result = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">switch</span> (operator) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">"+"</span>:
            result = a + b;
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> <span class="hljs-string">"-"</span>:
            result = a - b;
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> <span class="hljs-string">"*"</span>:
            result = a * b;
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> <span class="hljs-string">"/"</span>:
            result = a / b;
            <span class="hljs-keyword">break</span>;
    }
    <span class="hljs-keyword">return</span> result;
}
</code></pre>
<p>At first glance, the 2nd example is much easier to read, and it would be correct if there were no future with users and their new function requests, such as combining operators and rules like dot before dash.
If you start to implement the new functions in that way, you will run in trouble pretty quickly.</p>
<h2 id="summary">Summary 🌈</h2>
<p><img src="https://i.giphy.com/nC85rvTM2qrbVotTRR.gif" alt="Keep it simple, Stupid" /></p>
<p>If someone in the future ask you what the hell KISS means, do you know the answer? Probably not when it comes to the details because not everyone likes it as colourful as you do. Pair programming can help you and your friends to get better programmer with (a) KISS 💋</p>
<ol>
<li>Your code should be easy to read</li>
<li>The complexity (nested &lt;=3) should be low</li>
</ol>
<h2 id="question">Question</h2>
<p>Which one is easier to read? The second one? Do you see shades between? Leave a comment!</p>
]]></content:encoded></item><item><title><![CDATA[Job with a daily dose of goose bumps]]></title><description><![CDATA[What I love about my job is that I can listen to my favourite music at any time. I bought extra over-ear headphones because I want to wear them as long as possible without pain. In what other job would I have goose bumps early in the morning?
This mo...]]></description><link>https://blog.andrelademann.de/job-with-a-daily-dose-of-goose-bumps</link><guid isPermaLink="true">https://blog.andrelademann.de/job-with-a-daily-dose-of-goose-bumps</guid><category><![CDATA[music]]></category><category><![CDATA[jobs]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Mon, 26 Jul 2021 07:22:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627327294547/5imFkl0Ed.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>What I love about my job is that I can listen to my favourite music at any time. I bought extra over-ear headphones because I want to wear them as long as possible without pain. In what other job would I have goose bumps early in the morning?
This morning from a cover of a song by <em>Heinz Rudolf Kunze</em>. Even if you don't understand the lyrics, you'll get goosebumps anyway, didn't you? Who would have thought that German can sound so tender. So turn on your headphones and enjoy 🙂+🎧️= 🦆</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=hy0zPEgaO7o">https://www.youtube.com/watch?v=hy0zPEgaO7o</a></div>
]]></content:encoded></item><item><title><![CDATA[Okay let's blog]]></title><description><![CDATA[@adriantwarog told me in his article "Programmers That Don't Blog Should Start Right Now"  to start blogging because every developer should do it. Maybe not all, but I agree that every developer I know who blogs is a good developer. And since I want ...]]></description><link>https://blog.andrelademann.de/okay-lets-blog</link><guid isPermaLink="true">https://blog.andrelademann.de/okay-lets-blog</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Blogging]]></category><dc:creator><![CDATA[André Lademann]]></dc:creator><pubDate>Sun, 25 Jul 2021 15:44:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627227822916/RJ5M5TdEA.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>@adriantwarog told me in his article "<a target="_blank" href="https://adriantwarog.com/programmers-that-dont-blog-should-start-right-now">Programmers That Don't Blog Should Start Right Now</a>"  to start blogging because every developer should do it. Maybe not all, but I agree that every developer I know who blogs is a good developer. And since I want to call myself a good developer too, here we go today.
What content do I want to publish? I have a long list of ideas. I've been carrying those around in front of me for years. Many of the topics are now outdated. Therefore, I have a new approach. I'm actually going to use it like a logbook. Like the captain on the Enterprise, I say "Engage."</p>
<h2 id="and-now">And now</h2>
<p><strong><a target="_blank" href="https://hashnode.com/@vergissberlin/joinme">Create your account on hashnode</a></strong> and do it like the same! It's for free …</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=3jd1Ih8EUmw">https://www.youtube.com/watch?v=3jd1Ih8EUmw</a></div>
]]></content:encoded></item></channel></rss>