<?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[KRUD.dev]]></title><description><![CDATA[krud.dev is a development team dedicated to building great open source products. We are proud to launch our first library. ShapeShift – A lightweight, modular, ]]></description><link>https://krud.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1659974002906/GEB9qmEF-.png</url><title>KRUD.dev</title><link>https://krud.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 11:23:21 GMT</lastBuildDate><atom:link href="https://krud.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Introducing Ostara]]></title><description><![CDATA[What is Ostara
Ostara is a modern tool for managing and monitoring actuator-enabled microservices that aims to make the process more user-friendly and straightforward.
One of our main goals with Ostara was to create a tool that just works out of the ...]]></description><link>https://krud.dev/introducing-ostara</link><guid isPermaLink="true">https://krud.dev/introducing-ostara</guid><category><![CDATA[Devops]]></category><category><![CDATA[Springboot]]></category><category><![CDATA[Java]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[monitoring]]></category><dc:creator><![CDATA[Idan Elhalwani]]></dc:creator><pubDate>Tue, 18 Apr 2023 11:21:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1683792827369/d871acec-a353-4e2c-aeb1-4ac935d51ed5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yy026tbh42628fxh7nhk.png" alt="Boost UI" /></p>
<h2 id="heading-what-is-ostara">What is Ostara</h2>
<p>Ostara is a modern tool for managing and monitoring actuator-enabled microservices that aims to make the process more user-friendly and straightforward.</p>
<p>One of our main goals with Ostara was to create a tool that just works out of the box, without needing anything besides a functioning Actuator API on the other end.</p>
<p>Ostara allows you to gain insights into the performance and health of your microservices by providing real-time monitoring of critical metrics such as CPU and memory usage.</p>
<p>One of the key benefits of Ostara is its simplicity. The tool is designed to be easy to use and requires minimal setup. All you need is a running instance of your microservice with Actuator enabled, and you can start monitoring and managing it with Ostara.</p>
<h2 id="heading-why">Why?</h2>
<p>The first question to ask is <strong>why even use Ostara, when excellent tools such as Spring Boot Admin already exist?</strong></p>
<p>As Spring Boot Admin users, we had to ask ourselves this question before embarking on the development journey of Ostara.</p>
<p>For all its greatness, one thing Spring Boot Admin that cannot be said about Spring Boot Admin is that it's plug and play or 'off-the-shelf'.</p>
<p>To setup Spring Boot Admin, we start by having to create Spring project for the server itself (In our case, which is true for many, also meant we have to setup a full CI/CD flow, complete with Helm charts and Docker images in order to create a full production flow)</p>
<p>If we needed additional features such as authentication, notifications and so on, we would need to add them directly to the project.</p>
<p>All of this, despite the infinite versatility it offers (because it is essentially a blank slate), raises the startup costs of Spring Boot Admin considerably and even more so when you remember that you have to continually maintain this project as with any other project within your code ecosystem, either due to security updates to unrelated dependencies you may have needed to add, or in order to update Spring to match your main project(s).</p>
<p>But aren't there ready-made images of Spring Boot Admin Server? A quick Google search will show a few (often outdated) pre-built ones that people in the community have created for different scenarios, including this official <code>codecentric/spring-boot-admin</code> Docker image which states:</p>
<blockquote>
<p>This repository contains pre-build Docker Images containing basic and hence not production-ready builds of Spring Boot Admin.</p>
</blockquote>
<p>Now onto the client, in order to register instances on Spring Boot Admin, you have to add the <code>spring-boot-admin-starter-client</code> dependency to your app and point it at the admin server. From personal production experience in mature projects, this isn't always a pleasant, straightforward experience.</p>
<p>If your project guards Actuator's endpoints with Spring Security, you also have to configure the client to send the server the credentials it will need when registering itself.</p>
<p>Alternatively, if you use Spring Cloud Discovery within your ecosystem you will be able to use that in order to discover instances, dependency free, but not hassle free, as you will again have to add this to your server's project and configure on both ends.</p>
<p>The second part is performance. Spring Boot Admin lacks in a lot of areas when it comes to performance. The simplest example is the Thread Dump page, where if you stick around long enough without refreshing, it will eventually crash your tab.</p>
<p>With Ostara, we aimed for a solution that just <em>works</em> performantly with your existing setups, no matter their size or scale and without requiring any prior modifications in your code or environment with the only prerequisite being the presence of Spring Actuator.</p>
<h2 id="heading-feature-overview">Feature Overview</h2>
<ul>
<li><p>A robust and user-friendly UI for an ever-growing list of Actuator endpoints (<a target="_blank" href="https://docs.ostara.dev/features/instance-features/insights">Full list</a>)</p>
</li>
<li><p>Health monitoring of your applications and their individual instances</p>
</li>
<li><p>Neatly organize your applications and instances into different folders, with color coding and unique icons</p>
</li>
<li><p>Modify the loggers of your applications and individual instances on the fly</p>
</li>
<li><p>Evict caches from applications and individual instances on the fly</p>
</li>
<li><p>View cache statistics</p>
</li>
<li><p>View HTTP request statistics</p>
</li>
<li><p>Bean dependency visualization</p>
</li>
<li><p>Spring Integration Graph visualization</p>
</li>
<li><p>Application Security built in, interact with your secured Actuator instances with no extra code</p>
</li>
</ul>
<h2 id="heading-the-future">The Future</h2>
<p>Some of our planned features for future releases:</p>
<ul>
<li><p>Service discovery support</p>
</li>
<li><p>Notifications</p>
</li>
<li><p>Custom themes</p>
</li>
<li><p>A plugin ecosystem for custom Actuator endpoints</p>
</li>
<li><p>Support for non-official actuator endpoints, such as <a target="_blank" href="https://www.togglz.org/documentation/spring-boot-starter.html">Togglz</a></p>
</li>
<li><p>Native support for non-Spring Actuator facades such as <a target="_blank" href="https://gitlab.com/mikeyGlitz/gohealth">gohealth</a>, <a target="_blank" href="https://github.com/rcruzper/express-actuator">express-actuator</a> and <a target="_blank" href="https://github.com/SolarEdgeTech/pyctuator">pyctuator</a></p>
</li>
</ul>
<h2 id="heading-setting-up-ostara">Setting up Ostara</h2>
<p>Setting up Ostara is super simple, simply head over and download the <a target="_blank" href="https://github.com/krud-dev/ostara/releases/latest">latest release</a> for your OS and follow the <a target="_blank" href="https://docs.ostara.dev/getting-started/quick-start">Quick Start</a> to create your first instance and begin monitoring with Ostara</p>
<h2 id="heading-contributions">Contributions</h2>
<p>Ostara is in pre release so we would greatly appreciate any feedback, recommendations and/or requests as well as any contributions. We would also love to hear from other Spring Boot developers. Head to the <a target="_blank" href="https://github.com/krud-dev/ostara">repository</a> to participate!</p>
]]></content:encoded></item><item><title><![CDATA[Strategy Design Pattern with Spring Boot + Kotlin - Cleaner code with no boilerplate]]></title><description><![CDATA[The Strategy Pattern
If you already know the strategy pattern just jump to "The Library" section.
What is it?
According to Wikipedia, the strategy pattern is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead...]]></description><link>https://krud.dev/strategy-design-pattern-with-spring-boot-kotlin-cleaner-code-with-no-boilerplate</link><guid isPermaLink="true">https://krud.dev/strategy-design-pattern-with-spring-boot-kotlin-cleaner-code-with-no-boilerplate</guid><category><![CDATA[oop]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[Springboot]]></category><dc:creator><![CDATA[Aviv Mor]]></dc:creator><pubDate>Thu, 02 Mar 2023 10:04:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677751434261/4a787e66-69e6-4a01-bf76-787db71e6a87.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-the-strategy-pattern">The Strategy Pattern</h1>
<p>If you already know the strategy pattern just jump to "The Library" section.</p>
<h2 id="heading-what-is-it">What is it?</h2>
<p>According to <a target="_blank" href="https://en.wikipedia.org/wiki/Strategy_pattern">Wikipedia</a>, the strategy pattern is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.</p>
<p>In simple words, the strategy pattern is used to specify how something should be done by providing a specific algorithm. For example, a strategy for payment could be Credit Card, PayPal, or any other payment provider.</p>
<h2 id="heading-why-should-we-use-it">Why should we use it?</h2>
<p>The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it (<a target="_blank" href="https://fjp.at/design-patterns/strategy">source</a>).</p>
<p>In short, it makes our code cleaner, easier to maintain, and reusable.</p>
<h1 id="heading-the-strategy-pattern-in-code">The Strategy Pattern in Code</h1>
<p>Implementations of the pattern consist of an interface defining the strategy, multiple concrete implementations of the strategy and a context using the strategy.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/4/45/W3sDesign_Strategy_Design_Pattern_UML.jpg" alt="Strategy Pattern UML DiagramBy Vanderjoe - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=60733582" class="image--center mx-auto" /></p>
<p>By Vanderjoe - Own work, CC BY-SA 4.0, <a target="_blank" href="https://commons.wikimedia.org/w/index.php?curid=60733582">https://commons.wikimedia.org/w/index.php?curid=60733582</a></p>
<h2 id="heading-code-example">Code Example</h2>
<p>Let's look at the following simplified scenario:</p>
<ul>
<li><p>We have an application with users and we need to send them verification codes for 2FA.</p>
</li>
<li><p>The application supports multiple communication options for receiving the verification code: Email, SMS, Notifications...</p>
</li>
<li><p>Each user selects its preferred communication method.</p>
</li>
</ul>
<p>First we will define our strategy interface:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">VerificationCodeCommunicationStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>, code: <span class="hljs-type">String</span>)</span></span>
}
</code></pre>
<p>Now let's add our implementations:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmailCommunicationStrategy</span> : <span class="hljs-type">VerificationCodeCommunicationStrategy {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>, code: <span class="hljs-type">String</span>)</span></span> {
        emailClient.sendEmail(user.email, <span class="hljs-string">"Verification code"</span>, <span class="hljs-string">"Your verification is <span class="hljs-variable">$code</span>."</span>)
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SmsCommunicationStrategy</span> : <span class="hljs-type">VerificationCodeCommunicationStrategy {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>, code: <span class="hljs-type">String</span>)</span></span> {
        smsClient.sendSMS(user.phone, <span class="hljs-string">"Your verification is <span class="hljs-variable">$code</span>."</span>)
    }
}

<span class="hljs-comment">// ...</span>
</code></pre>
<p>All that's left is to use the strategy.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">enum</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CommunicationMethod</span> </span>{
    Email, SMS, Notification
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VerificationCodeService</span> </span>{
    <span class="hljs-keyword">val</span> verificationCodeStrategyMap: Map&lt;CommunicationMethod, VerificationCodeCommunicationStrategy&gt; = mapOf(
        CommunicationMethod.Email to EmailCommunicationStrategy(),
        CommunicationMethod.SMS to SmsCommunicationStrategy(),
        <span class="hljs-comment">// ...</span>
    )

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>)</span></span> {
        <span class="hljs-keyword">val</span> code = generateVerificationCode()

        <span class="hljs-keyword">val</span> verificationCodeStrategy = verificationCodeStrategyMap[user.preferredCommunicationMethod]
        verificationCodeStrategy?.sendVerificationCode(user, code)
    }
}
</code></pre>
<p>We can see how the code is clean and easy to maintain. Adding a new communication method would be easy and will not need to change existing code other than adding it to the map of strategies.</p>
<h1 id="heading-the-library">The Library</h1>
<p>We use the strategy pattern a-looot in our projects. Moreover, like all developers we are lazy and want to make our life as easy as possible. This is why we created our <a target="_blank" href="https://github.com/krud-dev/spring-componentmap">library</a>.</p>
<h2 id="heading-code-example-without-the-library">Code Example WITHOUT the library</h2>
<p>Let's revise the previous example for a regular Spring Boot implementation.</p>
<p>When using the strategy pattern in a Spring Boot application the context and strategy implementations are usually Spring components.</p>
<p>We will start with the strategies:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">VerificationCodeCommunicationStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>, code: <span class="hljs-type">String</span>)</span></span>
}

<span class="hljs-meta">@Component</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmailCommunicationStrategy</span> : <span class="hljs-type">VerificationCodeCommunicationStrategy {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>, code: <span class="hljs-type">String</span>)</span></span> {
        emailClient.sendEmail(user.email, <span class="hljs-string">"Verification code"</span>, <span class="hljs-string">"Your verification is <span class="hljs-variable">$code</span>."</span>)
    }
}

<span class="hljs-meta">@Component</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SmsCommunicationStrategy</span> : <span class="hljs-type">VerificationCodeCommunicationStrategy {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>, code: <span class="hljs-type">String</span>)</span></span> {
        smsClient.sendSMS(user.phone, <span class="hljs-string">"Your verification is <span class="hljs-variable">$code</span>."</span>)
    }
}

<span class="hljs-comment">// ...</span>
</code></pre>
<p>The interface remains the same and the implementations receive the <code>@Component</code> annotation.</p>
<p>Now let's move on to the verification service.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VerificationCodeServiceImpl</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> emailCommunicationStrategy: EmailCommunicationStrategy,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> smsCommunicationStrategy: SmsCommunicationStrategy
) {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> verificationCodeStrategyMap: Map&lt;CommunicationMethod, VerificationCodeCommunicationStrategy&gt; = mapOf(
        CommunicationMethod.Email to emailCommunicationStrategy,
        CommunicationMethod.SMS to smsCommunicationStrategy
    )

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>)</span></span> {
        <span class="hljs-keyword">val</span> code = generateVerificationCode()

        <span class="hljs-keyword">val</span> verificationCodeStrategy = verificationCodeStrategyMap[user.preferredCommunicationMethod]
        verificationCodeStrategy?.sendVerificationCode(user, code)
    }
}
</code></pre>
<p>We need to add the strategy implementations to the constructor and build the map manually. That's no fun!</p>
<h2 id="heading-code-example-with-the-library">Code Example WITH the library</h2>
<p>The entire objective of the library is to make our life easier and the code cleaner and less bug prone. It does it by simply building the strategy map automatically.</p>
<p>We will start by modifying the strategy interface.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">VerificationCodeCommunicationStrategy</span> </span>{
    <span class="hljs-meta">@get:ComponentMapKey</span>
    <span class="hljs-keyword">val</span> method: CommunicationMethod

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>, code: <span class="hljs-type">String</span>)</span></span>
}
</code></pre>
<p>As you can see we have added a new field <code>method</code> with the annotation <code>@ComponentMapKey</code>. This informs the library which field is the key for the strategy map.</p>
<p>Let's update the implementations according to the modified interface.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Component</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmailCommunicationStrategy</span> : <span class="hljs-type">VerificationCodeCommunicationStrategy {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> method = CommunicationMethod.Email

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>, code: <span class="hljs-type">String</span>)</span></span> {
        emailClient.sendEmail(user.email, <span class="hljs-string">"Verification code"</span>, <span class="hljs-string">"Your verification is <span class="hljs-variable">$code</span>."</span>)
    }
}

<span class="hljs-meta">@Component</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SmsCommunicationStrategy</span> : <span class="hljs-type">VerificationCodeCommunicationStrategy {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> method = CommunicationMethod.SMS

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>, code: <span class="hljs-type">String</span>)</span></span> {
        smsClient.sendSMS(user.phone, <span class="hljs-string">"Your verification is <span class="hljs-variable">$code</span>."</span>)
    }
}

<span class="hljs-comment">// ...</span>
</code></pre>
<p>Now let's modify the service to use the library.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VerificationCodeServiceImpl</span> </span>{
    <span class="hljs-meta">@ComponentMap</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> verificationCodeStrategyMap: Map&lt;CommunicationMethod, VerificationCodeCommunicationStrategy&gt;

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sendVerificationCode</span><span class="hljs-params">(user: <span class="hljs-type">User</span>)</span></span> {
        <span class="hljs-keyword">val</span> code = generateVerificationCode()

        <span class="hljs-keyword">val</span> verificationCodeStrategy = verificationCodeStrategyMap[user.preferredCommunicationMethod]
        verificationCodeStrategy?.sendVerificationCode(user, code)
    }
}
</code></pre>
<p>That's it! All we had to do is to add the <code>@ComponentMap</code> annotation to the strategy map and voila! The map is built automatically from the components. No boiler-plate code. To add a new strategy all you need to do is to create a new implementation and it will be "magically" added to all relevant strategy maps.</p>
<h1 id="heading-final-words">Final Words</h1>
<p>This <a target="_blank" href="https://github.com/krud-dev/spring-componentmap">library</a> is the most used library in our projects. Although it's not life changing, it's just useful, helps us keep our code clean and prevents lots of recurring bugs from forgetting to add new strategies to their appropriate maps.</p>
<p>If you would like to use it you can start with the <a target="_blank" href="https://componentmap.krud.dev/introduction/quick-start">quick start guide</a>.</p>
<p>We develop open source because we love it and want to contribute to the cause. If you would like to support us please consider starring <a target="_blank" href="https://github.com/krud-dev/spring-componentmap">the repository</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Introducing ShapeShift: A lightweight, modular, performant and extensible object mapping library for Kotlin/Java]]></title><description><![CDATA[WHY
The short answer
We needed a simple to use, minimal boiler plate mapping engine, that is also flexible and supports the most advanced use cases.
The long answer
A few years ago we got tired of developing the same boiler plate code for CRUD and de...]]></description><link>https://krud.dev/introducing-shapeshift-a-lightweight-modular-performant-and-extensible-object-mapping-library-for-kotlinjava</link><guid isPermaLink="true">https://krud.dev/introducing-shapeshift-a-lightweight-modular-performant-and-extensible-object-mapping-library-for-kotlinjava</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Java]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[architecture]]></category><dc:creator><![CDATA[Aviv Mor]]></dc:creator><pubDate>Wed, 12 Oct 2022 12:17:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1665576853762/SZ6FjodKv.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-why">WHY</h1>
<h2 id="heading-the-short-answer">The short answer</h2>
<p>We needed a simple to use, minimal boiler plate mapping engine, that is also flexible and supports the most advanced use cases.</p>
<h2 id="heading-the-long-answer">The long answer</h2>
<p>A few years ago we got tired of developing the same boiler plate code for CRUD and decided to develop a generic CRUD framework.</p>
<p>As a part of this framework we needed an object mapping library and could not find one that answered all of our requirements.</p>
<p>The first iteration of the library was part of the entire CRUD framework. However, some time ago we decided we want to start contributing to the open source community and we thought "What is the best way to contribute if not to release our CRUD framework?". The issue with this thought is that the framework is huge and contains lots of code, polishing it and getting it ready to be published as open source would take a lot of time (documentation anyone?).</p>
<p>Our solution was to separate the framework into multiple smaller libraries we can polish and publish in smaller time frames. The first of these libraries is <a target="_blank" href="https://shapeshift.krud.dev/">ShapeShift</a>.</p>
<h1 id="heading-what">WHAT</h1>
<h2 id="heading-the-short-answer">The short answer</h2>
<p>ShapeShift will help you transform object of type A to object of type B easily, fast and without boiler plate code.</p>
<p>ShapeShift main features:</p>
<ul>
<li>Auto mapping</li>
<li>Custom field transformers</li>
<li>Default transformers</li>
<li>Deep mapping</li>
<li>Multiple mapping targets</li>
<li>Conditional mapping</li>
<li>Mapping decorators</li>
<li>Seamless spring integration</li>
<li>Native Kotlin DSL API</li>
<li>Java builder API</li>
<li>Annotations API</li>
<li>Native Android support</li>
</ul>
<h2 id="heading-the-longer-answer">The longer answer</h2>
<p>ShapeShift's job seems simple, convert object of type A to object of type B. But to do its job in the best way possible, the library offers lots of features, to name a few: </p>
<ul>
<li><a target="_blank" href="https://shapeshift.krud.dev/features/auto-mapping">Advanced auto mapping</a> - Automatically map fields with the same name from the source object to the target object. Control wether to map only fields of the same type or use the advanced <a target="_blank" href="https://shapeshift.krud.dev/features/transformers#default-transformers">default transformers</a> feature to auto map fields of different types!</li>
<li><a target="_blank" href="https://shapeshift.krud.dev/guides/spring-usage">Seamless Spring integration</a> - ShapeShift's Spring Boot library allows to integrate it with Spring easily. Use Spring's power to create custom transformers beans with access to DB or other resources.</li>
</ul>
<p>More about the advanced features with code examples is available in <a target="_blank" href="https://krud.dev/object-mapping-advanced-features-qol-with-kotlin">Kotlin version</a> and <a target="_blank" href="https://krud.dev/object-mapping-advanced-features-qol-with-java">Java version</a>.</p>
<h1 id="heading-how">HOW</h1>
<h2 id="heading-the-short-answer">The short answer</h2>
<p>ShapeShift supports multiple APIs to configure your mappings.
<a target="_blank" href="https://shapeshift.krud.dev/api-documentation/annotations">Annotations</a>, <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/dsl">Kotlin DSL</a> and <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/java-builder">Java Builder</a>.</p>
<h2 id="heading-the-long-answer">The long answer</h2>
<p>ShapeShift's documentation is available <a target="_blank" href="https://shapeshift.krud.dev/">here</a>. You can check our <a target="_blank" href="https://shapeshift.krud.dev/introduction/quick-start">Quick Start</a> guide to get it up and running in 5 minutes.</p>
<p>Built with <strong>Kotlin</strong> in mind, ShapeShift was designed around its ecosystem and best practices. The library APIs for mapping with Kotlin:</p>
<ul>
<li><a target="_blank" href="https://shapeshift.krud.dev/api-documentation/annotations">Annotations</a> - Fully featured annotation based mapping, just add annotations to your objects and ShapeShift handles the rest. Including using custom field transformers, conditional mapping, advanced object decoration and much more.</li>
<li><a target="_blank" href="https://shapeshift.krud.dev/api-documentation/dsl">Kotlin DSL</a> - Allowing you to define the relations between objects. This allows you to map objects you can't change (or don't want to), like objects from 3rd party libraries. Additionally you can define inline transformations, conditions and decorations, enabling deep customization and very advanced mapping.</li>
</ul>
<p>ShapeShift also has full <strong>Java</strong> support available with multiple APIs for mapping:</p>
<ul>
<li><a target="_blank" href="https://shapeshift.krud.dev/api-documentation/annotations">Annotations</a> - Same API as Kotlin with full Java support.</li>
<li><a target="_blank" href="https://shapeshift.krud.dev/api-documentation/java-builder">Java Builder</a> - The equivalent Java API for the Kotlin DSL. Allowing you to define the relations between objects without modifying their code, and map objects you can't change (or don't want to).</li>
</ul>
<h1 id="heading-final-words">Final words</h1>
<p>We poured our love, time, knowledge and what not into ShapeShift. I'm proud of the result and our greatest achievement is to be able to help others with their work.</p>
<p>If you would like to contribute, please feel free to open issues, join as a contributor or star the <a target="_blank" href="https://github.com/krud-dev/shapeshift/">repository</a>. Thanks in advance!</p>
]]></content:encoded></item><item><title><![CDATA[Good code is like an onion, it has layers]]></title><description><![CDATA[The stack — Java, GWT, Mysql
The Experience — 11 Years
The Job — Senior Developer at Startup
—
Teaching some new recruits
It was my 3rd year at the startup, things were going well, the company was growing. We needed more working hands, so like any co...]]></description><link>https://krud.dev/good-code-is-like-an-onion-it-has-layers</link><guid isPermaLink="true">https://krud.dev/good-code-is-like-an-onion-it-has-layers</guid><category><![CDATA[Learning Journe]]></category><category><![CDATA[Programming Blog]]></category><category><![CDATA[Developer beginner learn]]></category><category><![CDATA[career switch]]></category><dc:creator><![CDATA[TheWizKid]]></dc:creator><pubDate>Tue, 11 Oct 2022 13:29:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1665494924278/0G0Nt2ylm.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The stack — Java, GWT, Mysql</p>
<p>The Experience — 11 Years</p>
<p>The Job — Senior Developer at Startup</p>
<p>—</p>
<h2 id="heading-teaching-some-new-recruits">Teaching some new recruits</h2>
<p>It was my 3rd year at the startup, things were going well, the company was growing. We needed more working hands, so like any company, we hired a new group of devs, straight off the assembly line (because why spread it out, or get someone with experience). I don't exactly remember how it came to be, but I was in charge of getting them up to speed. This was my first true taste of teaching and leading.</p>
<p>I was always good at winging explanations, and presentations, so it was no different here. I showed them the ropes, the way things were put together, and what talked to what and how.</p>
<p>The problem came when I needed to explain the way the code was written, and why it was written that way. We were using GWT, and for those who don't know, it allowed us to write the client code as JAVA and use the same entities as we do with the DB.</p>
<p>To say that it was useful was an understatement, but like everything in life, this had its drawbacks. Namely everything you save in the DB is sent to the client. This could and did cause many performance issues, and looking back I'm pretty sure there were security issues stemming from this behavior. This code was not layered correctly, but I didn't quite know it yet.</p>
<h2 id="heading-the-code-that-forced-me-to-look-and-understand-layers">The code that forced me to look and understand layers</h2>
<p>It was around this time that my friend started working on another startup, there he worked with this outsourced dev. She had written the main structure of the server code, and had very distinct layers and separation.</p>
<p>I try not to go too deep in technical terms in these posts, but I kind of need to here. There are a few different actors in our story, and each has some specific needs and talents.</p>
<h3 id="heading-the-db">The DB</h3>
<p>The job of the DB is simple, save the objects you need to, and allow you to query them when needed. So naturally, this is where you need to think of how to save things, how they are connected to the other entities in the system, and how you are going to query them.</p>
<h3 id="heading-the-server">The Server</h3>
<p>Its main job is to process things, take requests from the client, do some logic, and save it to the DB. This is the man in the middle, between the client and the DB.</p>
<h3 id="heading-the-client">The Client</h3>
<p>This is where things are displayed, not everything you need to do the job needs to be displayed. Sometimes you want to display things as a mix of other things.</p>
<p>Now I want to focus on the server, this is where my expertise is, and this is where the layers are most prevalent. It's the server's job to get tasks from the client and process them, update the DB, and send the results back for display. Let's break this down into meaningful layers.</p>
<p>[API] ← RO (Representation Object)→ [Service] ← Entity/RO → [Handler] ←  Entity → [Dao/DB]</p>
<p>The client does requests against the server, this is deserialized to a RO.</p>
<p>This RO is then used by the service to do logic, this is where processes are done.</p>
<p>The service in turn works with the handlers, where short and transactional logic can be performed. </p>
<p>They in turn can use the DAO (Data Access Object) to persist and fetch data from the DB.</p>
<p>I'll dig deeper into the different layers, and what they are in charge of, and why they use the Objects they do to talk to the other layers.</p>
<h3 id="heading-the-api">The API</h3>
<p>This is a facade, facing the client. Not all data needs to be transferred in order to do the requested action. For example, there could be fields on an object that are immutable, and there is no reason for the client to send them over when updating an object. Or there could be fields in the server that are only required for server logic, no reason to send them back via the API. This is why this layer works with ROs aka Representation Objects. They can have less fields, or aggregated fields, that can be used by the client.</p>
<p>This layer should be kept as “stupid” as you can, allowing the system to have multiple different types of APIs that call the same logic. The logic is based on the Service layer, and the API calls upon that layer to achieve its goals.</p>
<h3 id="heading-service-layer">Service Layer</h3>
<p>This is where most of the business logic lives, the different processes that constitute a system. These processes can be long, and can require multiple entities within the system. It's the service layer's responsibility to map the ROs into something more useful for handling the logic.</p>
<p>The service layer calls different Handlers, each with its own domain of responsibility to run the logic. These processes can be long, and should not be transactional (Create locks in the DB).</p>
<h3 id="heading-handlers">Handlers</h3>
<p>Handlers have very well defined responsibilities, they usually work with only 1 entity, and they are the ones that can do transactional actions. They are also the only ones that talk to the DAO/DB. </p>
<p>As you know, DB transactions can cause locks. One of the things we strive for in good system design, is to minimize lock time and scope. This is why the handlers are separated from the services. In the handlers is where you will find the code most optimized, and single goal oriented.</p>
<h3 id="heading-daodb">DAO/DB</h3>
<p>This is where persistence occurs. This layer is similar to the API layer in that it should be as simple and “stupid” as possible. Correct implementation of this allows us to simply (relatively) change DB by just re-implementing the DAO layer.</p>
<p>An example:</p>
<p>Lets take for example a process of publishing a new version of a post. This process is triggered by a request from the client, all that is needed is the post_id and version_number. So we have an RO with those fields only.</p>
<p>The process starts with some validation</p>
<p>Does that post_id exist?</p>
<p>Can the user requesting the publishing perform that action?</p>
<p>Is there a version_number like that?</p>
<p>Is it already published?</p>
<p>You can think of some more….</p>
<p>Now of course at the end of this, we want to transactionally update the is_published flag at the same time on the old version as the new. But during the time we are doing validations there is no reason to open a write transaction in the DB, and lock the entities. It is much better to do the validation process, call the handler just to do the swap, then continue after the transaction to create the result for the client. </p>
<p>This way we gained a few key points.</p>
<p>Shortest transaction time possible.</p>
<p>No connection to DB used if the request fails in the validation phase.</p>
<p>Code reuse - the method that publishes in the handler can later be used by different services (for example an automated time publisher).</p>
<p>Clear single responsibilities for each layer.</p>
<h2 id="heading-practice-what-i-preach">Practice what I preach</h2>
<p>Over the years I have honed this layered design (I will get into it in later posts), but the basics remain. This code forced me to look at my code differently, and implement the layers, and I have to tell you, this has made my code much more readable and maintainable as well. It has also increased my development speed, because I can write each layer's interface, and then start filling in the methods. </p>
<p>I won't lie, it took me a while to get used to working this way, and even longer to get it right (I would put things in the handler that could have been in a service and split among multiple handlers), but it's a process. I urge you to try and split some code you are working on using these principals. Everyone has that 1 method that is so big that nobody wants to touch it. Go ahead, give it a go, I'm confident that after some time (and banging your head against the wall) you will be able to split it up and have much better code at the end.</p>
<p>Please check out my <a target="_blank" href="https://github.com/krud-dev/shapeshift/">open source library</a> and maybe even star it. I would appreciate it greatly!</p>
]]></content:encoded></item><item><title><![CDATA[Object Mapping advanced features & QoL with Java]]></title><description><![CDATA[This is the Java version of the Kotlin article.
When working with multi-layered applications, external libraries, a legacy code base or external APIs, we are often required to map between different objects or data structures.
In this tutorial, we wil...]]></description><link>https://krud.dev/object-mapping-advanced-features-qol-with-java</link><guid isPermaLink="true">https://krud.dev/object-mapping-advanced-features-qol-with-java</guid><category><![CDATA[Open Source]]></category><category><![CDATA[oop]]></category><category><![CDATA[Java]]></category><category><![CDATA[architecture]]></category><dc:creator><![CDATA[Aviv Mor]]></dc:creator><pubDate>Thu, 08 Sep 2022 12:11:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662638994380/1cLphfca5.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the Java version of the <a target="_blank" href="https://dev.to/krud/object-mapping-advanced-features-qol-with-kotlin-5dgn">Kotlin article</a>.</p>
<p>When working with multi-layered applications, external libraries, a legacy code base or external APIs, we are often required to map between different objects or data structures.</p>
<p>In this tutorial, we will check out some Object Mapping libraries advanced features to simplify this task while saving development and maintenance time.</p>
<p>In our examples we will use the library <a target="_blank" href="https://github.com/krud-dev/shapeshift/">ShapeShift</a>. It's a light-weight object mapping library for Java/Kotlin with lots of cool features.</p>
<h1 id="heading-auto-mapping">Auto Mapping</h1>
<p>We will start with a bang. Auto mapping can and will save you lots of time and boiler-plate code. Some applications require manual mapping between objects, but most applications will save tons of time working on boring boiler-plate by just using this one feature. And it gets even better, with ShapeShift's default transformers we can even use automatic mapping between different data types.</p>
<h2 id="heading-simple-mapping">Simple Mapping</h2>
<p>Let's start with a simple example for auto mapping. We have our two objects, imagine they could also have tens, hundreds, or even thousands (for the crazy people here) of fields.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">private</span> String id;
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> String email;
    <span class="hljs-keyword">private</span> String phone;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">private</span> String id;
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> String email;
    <span class="hljs-keyword">private</span> String phone;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}
</code></pre>
<p>We want to map all the field from <code>User</code> to <code>UserDTO</code>. Using auto mapping we don't need to write any boiler-plate code. The mapper will be defined as follow:</p>
<pre><code class="lang-java">MappingDefinition mappingDefinition = <span class="hljs-keyword">new</span> MappingDefinitionBuilder(User.class, UserDTO.class)
        .autoMap(AutoMappingStrategy.BY_NAME_AND_TYPE)
        .build();
</code></pre>
<p>Voila! All the fields will be mapped automatically without any manual boiler-plate code.</p>
<h2 id="heading-advanced-mapping">Advanced Mapping</h2>
<p>In this example we will use the power of <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/transformers#default-transformers">default transformers</a> to take auto mapping even further.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">private</span> String id;
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> Date birthDate;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">private</span> String id;
    <span class="hljs-keyword">private</span> String fullName;
    <span class="hljs-keyword">private</span> Long birthDate;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}
</code></pre>
<p>Note that the types of the <code>birthDate</code> field are different in the source and destination classes. But using the power of default transformers we can still use auto mapping here.</p>
<pre><code class="lang-java">MappingDefinition mappingDefinition = <span class="hljs-keyword">new</span> MappingDefinitionBuilder(User.class, UserDTO.class)
        .autoMap(AutoMappingStrategy.BY_NAME)
        .build();
</code></pre>
<p>We changed the auto mapping strategy to <code>BY_NAME</code> so it will map fields also with different types. Now we need to register a default transformer to the <code>ShapeShift</code> instance in order for it to know how to transform <code>Date</code> to <code>Long</code>.</p>
<pre><code class="lang-java">ShapeShift shapeShift = <span class="hljs-keyword">new</span> ShapeShiftBuilder()
        .withTransformer(
                Date.class, 
                Long.class, 
                <span class="hljs-keyword">new</span> DateToLongMappingTransformer(), 
                <span class="hljs-keyword">true</span> <span class="hljs-comment">// Default Transformer</span>
        )
        .build();
    }
</code></pre>
<p>We can also add manual mapping on top of the auto mapping in order to add/change behavior. The source and destination classes have different names for the <code>name</code> field so we will add manual mapping for it.</p>
<pre><code class="lang-java">MappingDefinition mappingDefinition = <span class="hljs-keyword">new</span> MappingDefinitionBuilder(User.class, UserDTO.class)
        .autoMap(AutoMappingStrategy.BY_NAME)
        .mapField(<span class="hljs-string">"name"</span>, <span class="hljs-string">"fullName"</span>)
        .build();
</code></pre>
<p>Auto mapping is great for use cases that does not require specific mapping. It helps reduce the amount manual boiler-plate code needed to configure mapping and also helps you keep your sanity.</p>
<h1 id="heading-transformers">Transformers</h1>
<p>Transformers are very useful feature that allows you to transform the type/value of a field to a different type/value when mapping a field.</p>
<p>Some use cases we have been using widely:</p>
<ul>
<li>Transform date to long and vice versa between server and client objects.</li>
<li>Transform JSON string to it's actual type and vice versa between server and client objects.</li>
<li>Transform comma separated string to list of enums.</li>
<li>Transform another object id to its object or one of its fields from the DB using Spring transformers.</li>
</ul>
<h2 id="heading-basic-transformers">Basic Transformers</h2>
<p>We will start with a simple transformer example. Date-to-Long  and Long-to-Date transformers:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DateToLongMappingTransformer</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MappingTransformer</span>&lt;<span class="hljs-title">Date</span>, <span class="hljs-title">Long</span>&gt; </span>{
    <span class="hljs-meta">@Nullable</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Long <span class="hljs-title">transform</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> MappingTransformerContext&lt;? extends Date&gt; context)</span> </span>{
        <span class="hljs-keyword">return</span> context.getOriginalValue() != <span class="hljs-keyword">null</span> ? context.getOriginalValue().getTime() : <span class="hljs-keyword">null</span>;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LongToDateMappingTransformer</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MappingTransformer</span>&lt;<span class="hljs-title">Long</span>, <span class="hljs-title">Date</span>&gt; </span>{
    <span class="hljs-meta">@Nullable</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Date <span class="hljs-title">transform</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> MappingTransformerContext&lt;? extends Long&gt; context)</span> </span>{
        <span class="hljs-keyword">return</span> context.getOriginalValue() != <span class="hljs-keyword">null</span> ? <span class="hljs-keyword">new</span> Date(context.getOriginalValue()) : <span class="hljs-keyword">null</span>;
    }
}
</code></pre>
<p>All we need to do now is to <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/transformers#registering-transformers">register</a> them.</p>
<pre><code class="lang-java">ShapeShift shapeShift = <span class="hljs-keyword">new</span> ShapeShiftBuilder()
        .withTransformer(Date.class, Long.class, <span class="hljs-keyword">new</span> DateToLongMappingTransformer(), <span class="hljs-keyword">true</span>) <span class="hljs-comment">// "true" is optional, we are registering the transformers as default transformers, more on that later.</span>
        .withTransformer(Long.class, Date.class, <span class="hljs-keyword">new</span> LongToDateMappingTransformer(), <span class="hljs-keyword">true</span>)
        .build();
</code></pre>
<p>That's it! We can now use the transformers when mapping objects.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">private</span> String id;
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> Date birthDate;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">private</span> String id;
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> Long birthDate;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}

MappingDefinition mappingDefinition = <span class="hljs-keyword">new</span> MappingDefinitionBuilder(User.class, UserDTO.class)
        .mapField(<span class="hljs-string">"id"</span>, <span class="hljs-string">"id"</span>)
        .mapField(<span class="hljs-string">"name"</span>, <span class="hljs-string">"name"</span>)
        .mapField(<span class="hljs-string">"birthDate"</span>, <span class="hljs-string">"birthDate"</span>).withTransformer(DateToLongMappingTransformer.class) <span class="hljs-comment">// We don't have to state the transformer here because it is a default transformer</span>
        .build();
</code></pre>
<h2 id="heading-inline-transformers">Inline Transformers</h2>
<p>In some use cases we want to transform the value but we don't need a reusable transformer and we don't want to create a class just for a one time use.</p>
<p>Inline transformers for the rescue! Inline transformers allow to transform the value without the need to create and register and transformer.</p>
<pre><code class="lang-java">MappingDefinition mappingDefinition = <span class="hljs-keyword">new</span> MappingDefinitionBuilder(Source.class, Target.class)
        .mapField(<span class="hljs-string">"birthDate"</span>, <span class="hljs-string">"birthYear"</span>).withTransformer(context -&gt; context.getOriginalValue() != <span class="hljs-keyword">null</span> ? ((Date) context.getOriginalValue()).getYear() : <span class="hljs-keyword">null</span>)
        .build();
</code></pre>
<h2 id="heading-advanced-transformers">Advanced Transformers</h2>
<p>Transformers also allow us to do transformations with the DB or other data sources.</p>
<p>In this example we will use the power of the <a target="_blank" href="https://shapeshift.krud.dev/guides/spring-usage">Spring Boot integration</a> to create transformers with DB access.</p>
<p>We have three models:</p>
<ul>
<li>Job - DB entity.</li>
<li>User - DB entity.</li>
<li>UserDTO - Client model.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Job</span> </span>{
    <span class="hljs-keyword">private</span> String id;
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">private</span> String id;
    <span class="hljs-keyword">private</span> String jobId;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">private</span> String id;
    <span class="hljs-keyword">private</span> String jobName;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}
</code></pre>
<p>We want to convert the <code>jobId</code> on <code>User</code> to <code>jobName</code> on <code>UserDTO</code> by querying the job from the DB and setting it on the DTO.</p>
<p>In Spring's case, you generally avoid interaction with the application context from static functions or functions on domain objects.</p>
<p>We will use a ShapeShift's <a target="_blank" href="https://shapeshift.krud.dev/guides/spring-usage">Spring integration</a> to create a component as a transformer to access our DAO bean.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Component</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">JobIdToNameTransformer</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MappingTransformer</span>&lt;<span class="hljs-title">String</span>, <span class="hljs-title">String</span>&gt; </span>{

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> JobDao jobDao;

    <span class="hljs-meta">@Nullable</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">transform</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> MappingTransformerContext&lt;? extends String&gt; context)</span> </span>{
        <span class="hljs-keyword">if</span> (context.getOriginalValue() == <span class="hljs-keyword">null</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }
        Job job = jobDao.findJobById(context.getOriginalValue());
        <span class="hljs-keyword">return</span> job.getName();
    }
}
</code></pre>
<p>All that's left to do is to use this transformer in our mapping.</p>
<pre><code class="lang-java">MappingDefinition mappingDefinition = <span class="hljs-keyword">new</span> MappingDefinitionBuilder(User.class, UserDTO.class)
        .mapField(<span class="hljs-string">"id"</span>, <span class="hljs-string">"id"</span>)
        .mapField(<span class="hljs-string">"jobId"</span>, <span class="hljs-string">"jobName"</span>).withTransformer(JobIdToNameTransformer.class)
        .build();
</code></pre>
<p>Another bonus of using transformers is their reusability. In some use cases, We could create more generic transformers that will have application-wide usage.</p>
<h2 id="heading-default-transformers">Default Transformers</h2>
<p>When registering transformers you can indicate wether a transformer is a <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/transformers#default-transformers">default transformer</a>. A default transformer of types \ is used when you map a field of type \ to field of type \ without specifying a transformer to be used.</p>
<p>As we already seen, default transformers are useful for recurring transformations and especially for automatic mapping.</p>
<h1 id="heading-deep-mapping">Deep Mapping</h1>
<p>What if we want to map from/to fields that available inside a field which is an object? We can even do that, easily.</p>
<p>In order to access child classes we can use the full path of a field. Let's look at the following example.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">From</span> </span>{

    <span class="hljs-keyword">private</span> Child child = <span class="hljs-keyword">new</span> Child();
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> </span>{
        <span class="hljs-keyword">private</span> String value;
        <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">To</span> </span>{
    <span class="hljs-keyword">private</span> String childValue;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}
</code></pre>
<p>We want to map the <code>value</code> field in <code>Child</code> class inside the <code>From</code> class to the <code>childValue</code> field in the <code>To</code> class. We will use the full path of <code>value</code> which is <code>child.value</code>.</p>
<pre><code class="lang-java">MappingDefinition mappingDefinition = <span class="hljs-keyword">new</span> MappingDefinitionBuilder(From.class, To.class)
        .mapField(<span class="hljs-string">"child.value"</span>, <span class="hljs-string">"childValue"</span>)
        .build();
</code></pre>
<p>The full path is supported in both source and destination fields, it also supports multi level depth (e.g. <code>x.y.z</code>).</p>
<h1 id="heading-conditional-mapping">Conditional Mapping</h1>
<p>Conditions allow us to add a predicate to a specific field mapping to determine whether this field should be mapped.</p>
<p>Using this feature is as easy as creating a condition.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NotBlankStringCondition</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MappingCondition</span>&lt;<span class="hljs-title">String</span>&gt; </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isValid</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> MappingConditionContext&lt;String&gt; context)</span> </span>{
        <span class="hljs-keyword">return</span> context.getOriginalValue() != <span class="hljs-keyword">null</span> &amp;&amp; !context.getOriginalValue().trim().isEmpty();
    }
}
</code></pre>
<p>And adding the condition to the desired field mapping.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SimpleEntity</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SimpleEntityDisplay</span> </span>{
    <span class="hljs-keyword">private</span> String name = <span class="hljs-string">""</span>;
    <span class="hljs-comment">// Getters, Setters, Constructors, Equals...</span>
}

MappingDefinition mappingDefinition = <span class="hljs-keyword">new</span> MappingDefinitionBuilder(SimpleEntity.class, SimpleEntityDisplay.class)
        .mapField(<span class="hljs-string">"name"</span>, <span class="hljs-string">"name"</span>)
        .withCondition(NotBlankStringCondition.class)
        .build();
</code></pre>
<h2 id="heading-inline-conditions">Inline Conditions</h2>
<p>Like transformers, conditions can also be added inline using a function.</p>
<pre><code class="lang-java">MappingDefinition mappingDefinition = <span class="hljs-keyword">new</span> MappingDefinitionBuilder(SimpleEntity.class, SimpleEntityDisplay.class)
        .mapField(<span class="hljs-string">"name"</span>, <span class="hljs-string">"name"</span>)
        .withCondition(context -&gt; context.getOriginalValue() != <span class="hljs-keyword">null</span> &amp;&amp; !((String) context.getOriginalValue()).trim().isEmpty())
        .build();
</code></pre>
<h1 id="heading-annotations-mapping">Annotations Mapping</h1>
<p>This specific feature receives lots of hate because it breaks the separation of concerns principle. Agreed, this could be an issue in some applications, but in some use cases where all objects are part of the same application it can also be very useful to configure the mapping logic on top of the object. Check out the <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/annotations">documentation</a> and decide for yourself.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Object mapping libraries are not the solution for every application. For small, simple applications using boiler-plate mapping functions are more than enough. But, when developing larger, more complex applications, object mapping libraries can take your code to the next level, saving you development and maintenance time. All of these while reducing the amount of boiler-plate code and overall improving the development experience.</p>
<p>On a personal note, I used to work with manual mapping functions and was ok with it. It was "just" some simple lines of code. After upgrading our applications to use object mapping as part of our "boiler-plate free" framework (We will discuss that framework at a later time), I can't go back. Now we spend more time on what's important and interesting and almost no time on boring boiler-plate code.</p>
]]></content:encoded></item><item><title><![CDATA[My First Real Job]]></title><description><![CDATA[The stack — Java, Mysql
The Experience — 9 Years
The Job — Junior Developer at Startup
—
My first job interview
In my last year of uni Aviv (my now best friend and business partner) told me he is working at a startup that is now growing, and I should...]]></description><link>https://krud.dev/my-first-real-job</link><guid isPermaLink="true">https://krud.dev/my-first-real-job</guid><category><![CDATA[Programming Blog]]></category><category><![CDATA[Developer beginner learn]]></category><category><![CDATA[Learning Journey]]></category><category><![CDATA[career advice]]></category><dc:creator><![CDATA[TheWizKid]]></dc:creator><pubDate>Tue, 06 Sep 2022 13:30:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662470994028/UBRryfAc9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The stack — Java, Mysql</p>
<p>The Experience — 9 Years</p>
<p>The Job — Junior Developer at Startup</p>
<p>—</p>
<h2 id="heading-my-first-job-interview">My first job interview</h2>
<p>In my last year of uni Aviv (my now best friend and business partner) told me he is working at a startup that is now growing, and I should join him working there. I was nervous for my first job interview, they were working with a different stack than I had experience with, and let's just say I'm a little weird. A little background, I live and had grown up in a rural farming area, I wear shorts, and sandals (even in the dead of winter), not exactly “professional” looking. Anyway I vividly remember taking long pants and shoes in the car with me to the interview, thinking I would change right before I went in, to look the part. At the last moment I changed my mind, and told myself, “You should not try to pretend you are something you are not, they will either take you with your quirks or it's not the right place for you”. So I walked into the interview with the CEO of the company, in shorts and sandals. Lucky for me, the CEO was wearing torn jeans, and dirty worn sneakers, I felt right at home. </p>
<p>All this was to say something simple, but not easy. Be true to yourself, if you go work somewhere you won’t give your 100% if you feel out of place. I'm not saying you need to reject any job that isn't perfect, it's more like, find a job that doesn't compromise on your core, and be flexible about the “less important” stuff. In the long run this will be much better for you and the company.</p>
<h2 id="heading-java-you-say">Java you say</h2>
<p>My first day on the job was an interesting one, I got to the new office, they gave me a laptop, and told me to install my environment. Easier said than done, till now it was a visual studio, now I needed this weird eclipse thing. Then I got the code and nothing runs :/ weird. After some back and forth, I learned that for java and eclipse I need to download the JDK (Java development toolkit), fine. Still nothing… Just a reminder it was my first day on the job, in a language/stack I didn't know, and I didnt want to be the new “idiot” they hired. Safe to say it took me the whole day or maybe even 2 just to get the code up and running.</p>
<p>Later that week I got my first task, I needed to copy some functionality that existed in the client area to the back office. This was actually a perfect first task, for many reasons, most of all it was 70% copy paste. This was great because I had barely knew how to read the java code I was looking at. Additionally the adaptation needed in the back office project was simple and existed in one form or another in different areas of the code. So basically the task was like a big jigsaw puzzle, I got 1 big piece, now I need to go hunt down some smaller ones and put it all together.</p>
<h3 id="heading-a-small-tangent">A small tangent</h3>
<p>Over the years this “jigsaw puzzle” approach has really sunk in, and today I can tell you with confidence, if you structure the tasks given to developers (especially juniors) in this way, a few good things happen:</p>
<ol>
<li>They get into the code much faster.</li>
<li>They write less buggy code.</li>
<li>They build confidence in their abilities.
Finally as a business owner I can tell you from my experience, it takes a lot less time to see a positive ROI for their time.</li>
</ol>
<p>This has led me to a core belief of mine (in regards to development). A good programmer needs to know 3 things:</p>
<ol>
<li>How to read and understand code.</li>
<li>Be proficient in google searches for solutions to the problem at hand.</li>
<li>Know how to adapt other code to meet their current needs.</li>
</ol>
<p>A great programmer is one that knows how/why things are done in this way, and understands optimization and deep diving into frameworks they use. While a good programmer just needs to know how to use the framework, and not how it works.</p>
<h2 id="heading-what-is-this-spring-magic-using-frameworks">What is this Spring magic - using frameworks</h2>
<p>The project we were writing was built upon Spring (a hugely popular dependency injection framework in Java). Now frameworks are powerful tools, but they hide many things under the hood. Over the years I have learned in depth how/why Spring works, but truth be told, as a junior developer back then it seemed like magic to me. </p>
<p>I want to take you through a few different stages of understanding that I use today when I am faced with a new framework.</p>
<h3 id="heading-step-1-basics-the-what">Step 1 - Basics (The what)</h3>
<p>In this step it is most important NOT to try to understand how it works, just to understand the tools and capabilities it provides. I have seen it many times that a junior gets “stuck” on trying to understand the depths of the framework, and the truth is they are just not ready to. They don’t fully understand WHAT the framework can do, so they have no chance to understand how.</p>
<h3 id="heading-step-2-advanced-usage-the-how">Step 2 - Advanced Usage (The how)</h3>
<p>Almost every framework I have used has many different features that compliment each other (makes sense). This stage is focused on that, using the framework to its fullest. Mixing and matching different features, making the whole greater than the sum of its parts. This is where the developer truly learns HOW to use the framework correctly.</p>
<h3 id="heading-step-3-down-the-rabbit-hole-the-why">Step 3 - Down the rabbit hole (The why)</h3>
<p>Here is where things get truly interesting. There comes a time when you reach the limits of the framework and try to do something you think should be possible, but turns out it isn't. This is when you download the source code and start the deep dive to understand the WHY. Sometimes it's something at the core of how it's built, but other times it's just on the fringes of what the framework can do, and that means, no examples, no documentation. Then the only answer is to understand why the framework works the way it does.</p>
<h3 id="heading-step-4-building-upon-the-framework">Step 4 - Building upon the framework</h3>
<p>This is the final stage, where you can start using the tools the framework gives you to build your own mini framework upon. Or even build your own libraries from scratch. This is where you start contributing to the framework, or start releasing some open source of your own.</p>
<h2 id="heading-generalization-is-a-powerful-tool">Generalization is a powerful tool</h2>
<p>After a year or 2 in the company, I got a new task, implementing a new PSP (Payment service provider), basically adding something like paypal to the clients payment options. This was a new area in the code for me, something I had no experience with. So off to the races, I went and looked at the implementation of a few different PSPs, and to my shock, I saw a ton of very similar code, makes sense since it doesn't really matter how the money comes in, we still need to update billing, create the relevant logs, and credit the account. All this was done time and time again, in the different PSPs, this was mainly because the objects we were getting back from the PSP api were so different.</p>
<p>Interfaces to the rescue, this is one of my first epiphanies, this has led me to proper code layers, and a few “new” design patterns (really just classes that give me a mix of design patterns with no boilerplate code). So I told my boss I needed more time to rewrite it correctly, and set to work. I created a handler that was in charge of the process of communication with the PSPs. It had methods for the different actions, like charge or refund and so forth. It managed the different steps of the process and called upon the different classes of the PSP for interpretation of the response received via API.</p>
<p>I don't want to get into the code (this is not the point of the post), but basically there was a PspResponse that all PSPs needed to inherit from, and then methods like:
getIsSuccess()
getErrorText()
getAmount()</p>
<p>This took some time to refactor the old code, but in the long run reduced implementation time for new PSPs drastically, all the while reducing the amount of bugs (mainly because someone would always forget to update the new logic in some old PSP).</p>
<p>The experience I gained designing and implementing this led me down the path to becoming an architect. I felt so proud from my new creation, and caused me to look at code in a different way. This is a pivotal point in my career, and has caused me to think about how to write code correctly in the long run, and not just this feature.</p>
<p>Please check out my <a target="_blank" href="https://github.com/krud-dev/shapeshift/">open source library</a> and maybe even star it. I would appreciate it greatly!</p>
]]></content:encoded></item><item><title><![CDATA[What I learned in Uni]]></title><description><![CDATA[The stack — C#
The Experience — 7 Years
The Job — Uni Student + Freelancer
—
My first paying job
Let me set the mood, poor uni student, first year physics major, tooo many courses at the same time, not enough sleep; I think you get the idea (and poss...]]></description><link>https://krud.dev/what-i-learned-in-uni</link><guid isPermaLink="true">https://krud.dev/what-i-learned-in-uni</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Learning Journey]]></category><category><![CDATA[Career]]></category><category><![CDATA[Programming Blog]]></category><dc:creator><![CDATA[TheWizKid]]></dc:creator><pubDate>Thu, 25 Aug 2022 13:24:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1661433912560/_uE_nvOJK.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The stack — C#</p>
<p>The Experience — 7 Years</p>
<p>The Job — Uni Student + Freelancer</p>
<p>—</p>
<h2 id="heading-my-first-paying-job">My first paying job</h2>
<p>Let me set the mood, poor uni student, first year physics major, tooo many courses at the same time, not enough sleep; I think you get the idea (and possibly what it feels like). Now I know we would all love to have some money, to go out with, and enjoy our time. We can all find some minimum wage 9-5, but I was looking for something better, and thought I could use my skills as a developer to land some work.</p>
<p>Luckily for me, a family friend was looking for someone to develop something for them. The job was a good mix of my knowledge and skills. This friend owned a factory that builds custom water treatment and purification equipment, and he had a bottleneck in his quoting division. Every quote the sales team needed required an engineer to write up plans, then someone needed to calculate not only the costs of the different parts, but things like length of welds, amount of paint needed, amount of bolts needed, and so forth. Till this point it was done in excels with lookups and required a lot of know-how.</p>
<p>My job (should I choose to accept it) was to create a visual tool, that the sales agent can drag and drop to the parts needed, including piping and such, and the output would be a detailed quote, including everything mentioned above and more.</p>
<h2 id="heading-working-withfor-a-client-as-a-freelancer">Working with/for a client as a freelancer</h2>
<p>Now for all you developers out there, I'm sure you are thinking, “OK, he got some requirement documents on how/what to build”. That couldn't be farther from the truth (and surprisingly more common than I had expected). I had to basically interview all the people involved in the company, to try and get a feel of what was needed. After that I would sit down and write my own basic requirement documents, that I would then go over with the client. </p>
<h3 id="heading-if-there-is-one-thing-you-take-away-from-this-always-go-over-the-requirements-with-the-client-in-writing">If there is one thing you take away from this: “Always go over the requirements with the client in writing”</h3>
<p>This has saved my @$$ many times.
It took some time learning how to deal with clients, and I learned a ton. This first client helped me learn, the development skills aren't the only thing important, it is important to understand the clients needs, pain points, and where to focus my efforts, this has rang true throughout my career.</p>
<p>I was lucky (in a sadistic kind of way) that my first client had no idea on how to write requirements, and how to handle a development cycle. In the years to come, I would receive many “requirements” of the type “put a button there that does that”; and 9/10 times there is a better way to do things that answers the clients problems in a better way. I urge you to look at anything you are developing, and try to understand the business use case behind it, and look at the bigger picture. You will be surprised to find that this will help you tremendously write better code.</p>
<p>Just for an example, I was told to make a button for export of the quote, sounds reasonable enough, but then it would be the sales agent's job to send copies to the client, the management, and the project manager. I wouldn't have known this if I just would have developed the button. Instead I suggested that the system have projects in it, with the project managers info, and have a “send to email” button. This may seem minor, but after talking to the CEO I found out it saved him tons of heartache, because more than once, the wrong quote was sent to the wrong client, just because the agent attached the wrong file.</p>
<h2 id="heading-what-you-cant-learn-in-uni">What you can’t learn in Uni</h2>
<p>During my time at uni, I learned a ton of things, in many different subjects, including programming. A few caveats to this is the fact that most of the time, the languages that were taught were out of date, and the professors didn't really know how to program a product, more like write blocks of code. Sadly there is more truth than I had hoped for in the old saying “Those who can't, teach”.</p>
<p>I think I can confidently say I learned more in my first freelance job, then everything uni could teach. There is nothing like getting your hands “dirty” and just doing some work. Here is a small list of the top things I “learned on the job”:</p>
<ol>
<li>Understand the business - Like I stated before, understand “why” your client needs the feature, not just how they see the feature implemented</li>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Pareto_principle">80/20 principle</a> - Try and spend your time wisely covering most of the needs, and leaving “known issues” for the really rare edge cases. </li>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/KISS_principle">KISS</a> - “Keep it, simple stupid” (or somtimes I think it’s “Keep it simple, stupid”), try to simplify your code, break it into smaller bite sized pieces, that will pay dividends in the long run.</li>
<li>Performance isn't everything (or even important most of the time) - Today's computers are fast (like really really fast) and that fancy Binary search algorithm you learned, doesn't really matter in real life (most of the time), when you filter a list of even a few 10s of thousands, it’s not really going to change the runtime.</li>
<li>Use open source wherever you can - There are so many amazing open source projects out there, and they can cut your programming time by a huge factor. Additionally they can (usually) do it better then if you tried to write it yourself.</li>
</ol>
<p>Please check out my <a target="_blank" href="https://github.com/krud-dev/shapeshift/">open source library</a> and maybe even star it. I would appreciate it greatly!</p>
]]></content:encoded></item><item><title><![CDATA[They don't call it intelligence for nothing]]></title><description><![CDATA[The stack — C#, Oracle
The Experience — 4 Years
The Job — The intelligence corps

It's my time to serve
This may be doxing myself a little, but where I live there is a mandatory military service, for 3 f%$#ing years. Luckily for me, I had some skills...]]></description><link>https://krud.dev/they-dont-call-it-intelligence-for-nothing</link><guid isPermaLink="true">https://krud.dev/they-dont-call-it-intelligence-for-nothing</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Learning Journey]]></category><category><![CDATA[Career]]></category><dc:creator><![CDATA[TheWizKid]]></dc:creator><pubDate>Wed, 17 Aug 2022 14:29:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660746527287/ngBGGOJbR.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The stack — C#, Oracle</p>
<p>The Experience — 4 Years</p>
<p>The Job — The intelligence corps</p>
<hr />
<h2 id="heading-its-my-time-to-serve">It's my time to serve</h2>
<p>This may be doxing myself a little, but where I live there is a mandatory military service, for 3 f%$#ing years. Luckily for me, I had some skills, computer skills. It works here like this, you go do a lot of tests, intelligence tests, aptitude tests, physical tests, and at the end you get stationed somewhere (usually NOT where you want to be). I was in the running for a few different positions, and then one day out of the blue, I got a phone call. Come now to interview for a new position, nothing that I ever heard of, well of course I went. They were looking for someone with programming experience that they didn't need to send to the military academy to learn, and I fit the bill…</p>
<p>One thing led to another, and within the week I found myself in basic training on my way to the intelligence corps, as a developer in a small unit. After a few weeks of basic training (even us developers go through boot camp), I arrived at my unit. This is where I found out that just me and 1 other guy are the only people in the unit that can “speak computer”, and no I don't just mean program. We were in charge of the whole system there, from the network, to the servers, and of course the software.</p>
<h2 id="heading-how-to-learn-c-in-3-easy-steps">How to learn C# in 3 easy steps</h2>
<ol>
<li>Get enlisted to the military, to a plush desk job as a programmer.</li>
<li>Be 1 of 2 people in charge of the whole system.</li>
<li>Never forget that if you don't get on top of things within a few months, they will ship you out to somewhere much worse.</li>
</ol>
<p>Easy right?</p>
<p>But in all seriousness, I had to teach myself C# on the job. At least I had the running code, and the coveted PC on the internet. You see in the intelligence corps, and probably most military installations, no one has internet access on their PC. Well technically neither did I, but what I did have was access to the only PC (that was air gapped from the network) which had internet access. </p>
<p>By this time of my life (luckily for me), google was a thing already, and there were more and more resources online about programming. Even more for things like C#, because it was Microsoft's. But (I hate it that there is always a “but”)… The computer in question is air gapped, so no copy paste.</p>
<h2 id="heading-into-the-deep-end">Into the deep end</h2>
<p>This was the first time I truly worked with a DB (I don't really count MS Access). It was my first time, and they threw me into the deep end (without floats). Our systems used Oracle, till this day I think it's an amazing DB, but it's a beast. Our system was complex, and today, I would have never built it this way (I didn't build it back then either, the system was operational when I got there). </p>
<p>I know I'm going to spark some debate about this, but I dont think business logic is supposed to be in stored procedures (there I said it). This architecture caused some very weird side effects, for example, releasing versions requiring simultaneous release of new stored procedures, or updates to old ones. Triggers that can cause chain reactions of events, and you can't quite see them in any IDE. </p>
<p>If that wasn't bad enough, we didn't really have a server side. The C# was a desktop app, installed via group policy to all PCs on the network. The server was basically the stored procedures in Oracle. So things like creating thread pools to handle large tasks, or locks on editing were all out of the question.</p>
<p>This is where I started thinking about how code should be built, and it was the start of the path to architecture. Even if it still took a few years to find out what I should do, at least now, I know what I shouldn't. It was an important realization, one that I have since seen on some of the juniors I mentored. Writing code without bugs is important, but writing code in a maintainable way, is just as important.</p>
<h2 id="heading-my-partner-in-crime">My partner in crime</h2>
<p>About half way through my service, the other guy I was with finished his tour. It was up to me to find a replacement. I had access to candidates (and it's not like they had CVs, they are all 18 year old fresh out of high school), I gave them tests to do, asked them questions. Remember back then I couldn't send them anything online, all by phone, or in person.</p>
<p>After a few weeks, and at least 50 candidates, I had found him, my new partner. Again we couldn't send him to learn in any course, so I had to find someone with the knowhow from home. Additionally even after I selected him, it took months for him to get to me. He had to get security clearance, and go through boot camp. So months later he was finally here, I would like to introduce you to a new character (that will have a recurring role in the articles to come), my business partner (and best friend).</p>
<p>Like any relationship it was rocky at first. I won't go into the details, but what I can say is that we went through a lot together. Things that built our relationship strong. Little did I know (spoilers) that we would be working together till this day (over 16 years).</p>
<p>Please check out our <a target="_blank" href="https://github.com/krud-dev/shapeshift/">open source library</a>  and maybe even star it ;-)
We would appreciate it greatly.</p>
]]></content:encoded></item><item><title><![CDATA[Kotlin Object Mapping - Pros & Cons]]></title><description><![CDATA[What is Object Mapping?
Multi-layered applications often have similar but different object models, where the data in two models may be similar but the structure and concerns of the models are different. 
Writing the mapping code is a tedious and erro...]]></description><link>https://krud.dev/kotlin-object-mapping-pros-cons</link><guid isPermaLink="true">https://krud.dev/kotlin-object-mapping-pros-cons</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[architecture]]></category><dc:creator><![CDATA[Aviv Mor]]></dc:creator><pubDate>Wed, 10 Aug 2022 12:59:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660136276869/7Zbc6bzB2.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-what-is-object-mapping">What is Object Mapping?</h1>
<p>Multi-layered applications often have similar but different object models, where the data in two models may be similar but the structure and concerns of the models are different. 
Writing the mapping code is a tedious and error-prone task. Object mapping makes it easy to convert one model to another.</p>
<h1 id="heading-simple-example">Simple Example</h1>
<p>Let's say we have a REST API application with two models. One for the server and one client facing:</p>
<p>User (Server):</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span></span>(
    <span class="hljs-keyword">val</span> id: String,
    <span class="hljs-keyword">val</span> name: String,
    <span class="hljs-keyword">val</span> email: String,
    <span class="hljs-comment">// isBlocked is server side only</span>
    <span class="hljs-keyword">val</span> isBlocked: <span class="hljs-built_in">Boolean</span>
)
</code></pre>
<p>UserDTO (Client):</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span></span>(
    <span class="hljs-keyword">val</span> id: String,
    <span class="hljs-keyword">val</span> name: String,
    <span class="hljs-keyword">val</span> email: String
)
</code></pre>
<h2 id="heading-conversion">Conversion</h2>
<p>We have a couple of options:</p>
<h3 id="heading-extension-methods">Extension Methods</h3>
<p>We can use simple extension methods.</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> User.<span class="hljs-title">toUserDTO</span><span class="hljs-params">()</span></span>: UserDTO {
    <span class="hljs-keyword">return</span> UserDTO(id, name, email)
}
</code></pre>
<p>Simple and easy, but requires additional boiler-plate code we need to maintain every time we change the model.</p>
<h3 id="heading-object-mapping">Object Mapping</h3>
<p>We will use the open source object mapping library <a target="_blank" href="https://github.com/krud-dev/shapeshift">ShapeShift</a> for the examples.</p>
<h4 id="heading-annotations">Annotations</h4>
<p>The first step is to add the annotations to the fields we want to map.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@DefaultMappingTarget(UserDTO::class)</span>
<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span></span>(
    <span class="hljs-meta">@MappedField</span>
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>,
    <span class="hljs-meta">@MappedField</span>
    <span class="hljs-keyword">var</span> name: String = <span class="hljs-string">""</span>,
    <span class="hljs-meta">@MappedField</span>
    <span class="hljs-keyword">var</span> email: String = <span class="hljs-string">""</span>,
    <span class="hljs-comment">// isBlocked is server side only and not mapped to client DTO</span>
    <span class="hljs-keyword">var</span> isBlocked: <span class="hljs-built_in">Boolean</span> = <span class="hljs-literal">false</span>
)
</code></pre>
<p>All that's left is to convert.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> shapeShift = ShapeShiftBuilder().build()
<span class="hljs-keyword">val</span> user = User(<span class="hljs-string">"xyz"</span>, <span class="hljs-string">"john doe"</span>, <span class="hljs-string">"john@email.com"</span>, <span class="hljs-literal">false</span>)
<span class="hljs-keyword">val</span> userDTO = shapeShift.map&lt;UserDTO&gt;(user)
</code></pre>
<h4 id="heading-dsl">DSL</h4>
<p>In some cases we can't change the data classes code (or don't want to). For these use cases we create a standalone mapper between the two classes using Kotlin DSL.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mapper = mapper&lt;User, UserDTO&gt; {
    User::id mappedTo UserDTO::id
    User::name mappedTo UserDTO::name
    User::email mappedTo UserDTO::email
}
</code></pre>
<p>And now the conversion. Note that we are registering the mapper to the ShapeShift instance.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> shapeShift = ShapeShiftBuilder().withMapping(mapper).build()
<span class="hljs-keyword">val</span> user = User(<span class="hljs-string">"xyz"</span>, <span class="hljs-string">"john doe"</span>, <span class="hljs-string">"john@email.com"</span>, <span class="hljs-literal">false</span>)
<span class="hljs-keyword">val</span> userDTO = shapeShift.map&lt;UserDTO&gt;(user)
</code></pre>
<p>Seems like a lot of work for a simple conversion, right? Maybe... Let's continue to the next example.</p>
<h1 id="heading-auto-mapping">Auto Mapping</h1>
<p>What if I told you there is a way to remove almost if not all the mapping boiler-plate code? In many use cases we have similar classes we need to map between. This is where automatic mapping comes to the rescue.</p>
<p>Let's continue with the same classes.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span></span>(
    <span class="hljs-keyword">val</span> id: String,
    <span class="hljs-keyword">val</span> name: String,
    <span class="hljs-keyword">val</span> email: String,
    <span class="hljs-keyword">val</span> isBlocked: <span class="hljs-built_in">Boolean</span>
)

<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span></span>(
    <span class="hljs-keyword">val</span> id: String,
    <span class="hljs-keyword">val</span> name: String,
    <span class="hljs-keyword">val</span> email: String
)
</code></pre>
<p>Using automatic mapping our mapper will be the following.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mapper = mapper&lt;User, UserDTO&gt; {
    autoMap(AutoMappingStrategy.BY_NAME_AND_TYPE)
}
</code></pre>
<p>Voila! No boiler-plate code to configure fields manually. <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/auto-mapping">Auto mapping</a> also comes with advanced features for more complex use cases.</p>
<h1 id="heading-generic-example">Generic Example</h1>
<p>When our projects start to scale, we want to add generic functionality to improve productivity and decrease maintenance. For example:</p>
<ul>
<li>Generic CRUD controller for entities.</li>
<li>Generic export to excel/pdf/...</li>
</ul>
<p>In order for us to be able to implement these generic functionality we need to be able to convert our objects back and forth between classes.</p>
<p>We can use the <a target="_blank" href="https://en.wikipedia.org/wiki/Factory_method_pattern">factory method pattern</a> to do it, simple and straightforward, but agin requires more boiler-plate code we need to maintain when we add new models.</p>
<p>Another option is (surprise surprise) to use object mapping.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;<span class="hljs-keyword">reified</span> ExportModel : Any&gt;</span> <span class="hljs-title">export</span><span class="hljs-params">(model: <span class="hljs-type">Any</span>)</span></span> {
    <span class="hljs-keyword">val</span> shapeShift = ShapeShiftBuilder().build()
    <span class="hljs-keyword">val</span> exportModel = shapeShift.map&lt;ExportModel&gt;(model)
    <span class="hljs-comment">// export logic...</span>
}

<span class="hljs-keyword">val</span> user = User(<span class="hljs-comment">/*...*/</span>)
export&lt;UserExport&gt;(user)
</code></pre>
<p>That's it. Zero boiler-plate code and we got ourselves the generic functionality we know and love.</p>
<h2 id="heading-type-safety">Type Safety</h2>
<p>Let's take it further and add type safety to the export method. For that we will add two interfaces:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ExportModel</span> </span>{
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">BaseModel</span>&lt;<span class="hljs-type">EM: ExportModel</span>&gt; </span>{
}
</code></pre>
<p>Now we will update our classes to implement the interfaces.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserExport</span>: <span class="hljs-type">ExportModel {</span></span>
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>: <span class="hljs-type">BaseModel</span>&lt;<span class="hljs-type">UserExport</span>&gt; </span>{
    <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>And change our generic method respectively.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;<span class="hljs-keyword">reified</span> EM : ExportModel&gt;</span> <span class="hljs-title">export</span><span class="hljs-params">(model: <span class="hljs-type">BaseModel</span>&lt;<span class="hljs-type">EM</span>&gt;)</span></span> {
    <span class="hljs-keyword">val</span> shapeShift = ShapeShiftBuilder().build()
    <span class="hljs-keyword">val</span> exportModel = shapeShift.map&lt;EM&gt;(model)
    <span class="hljs-comment">// export logic...</span>
}
</code></pre>
<p>That's it. We got ourselves type safe generic export method.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> user = User(<span class="hljs-comment">/*...*/</span>)
export(user)
</code></pre>
<h1 id="heading-spring-example">Spring Example</h1>
<p>Taking it up a notch to the next level. We have three models.</p>
<ul>
<li>Job - DB entity.</li>
<li>User - DB entity.</li>
<li>UserDTO - Client model.</li>
</ul>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Entity</span>
<span class="hljs-meta">@Table(name = <span class="hljs-meta-string">"jobs"</span>)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Job</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> name: String = <span class="hljs-string">""</span>
}

<span class="hljs-meta">@Entity</span>
<span class="hljs-meta">@Table(name = <span class="hljs-meta-string">"users"</span>)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> jobId: String? = <span class="hljs-literal">null</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> jobName: String? = <span class="hljs-literal">null</span>
}
</code></pre>
<p>We need to convert the <code>jobId</code> on User to <code>jobName</code> on UserDTO by querying the job from the DB and setting it on the DTO.</p>
<p>In Spring's case, you generally avoid interaction with the application context from static functions or functions on domain objects and because of that they cannot be invoked from extensions.</p>
<p>Object mapping to the rescue (surprise!). Let's create a custom transformer to do the heavy lifting for us.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Component</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">JobIdToNameTransformer</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> jobDao: JobDao
) : MappingTransformer&lt;String, String&gt;() {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">transform</span><span class="hljs-params">(context: <span class="hljs-type">MappingTransformerContext</span>&lt;<span class="hljs-type">out</span> <span class="hljs-type">String</span>&gt;)</span></span>: String? {
        context.originalValue ?: <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
        <span class="hljs-keyword">val</span> job = jobDao.findJobById(context.originalValue!!)
        <span class="hljs-keyword">return</span> job.name 
    }
}
</code></pre>
<p>The complicated part is over. Now we just need to add the annotations to the User model.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Entity</span>
<span class="hljs-meta">@Table(name = <span class="hljs-meta-string">"users"</span>)</span>
<span class="hljs-meta">@DefaultMappingTarget(UserDTO::class)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-meta">@MappedField</span>
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-meta">@MappedField(transformer = JobIdToNameTransformer::class, mapTo = <span class="hljs-meta-string">"jobName"</span>)</span>
    <span class="hljs-keyword">var</span> jobId: String? = <span class="hljs-literal">null</span>
}
</code></pre>
<p>That's all. The great part is that we can use the same transformer every time we need to convert a job id to job name on any model.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> shapeShift = ShapeShiftBuilder().build()
<span class="hljs-keyword">val</span> user = User(<span class="hljs-comment">/*...*/</span>)
<span class="hljs-keyword">val</span> userDTO = shapeShift.map&lt;UserDTO&gt;(user)
</code></pre>
<p>A full spring example code is available <a target="_blank" href="https://github.com/krud-dev/shapeshift/tree/master/example/kotlin/spring-mapping">here</a>.</p>
<h1 id="heading-pros-andamp-cons">Pros &amp; Cons</h1>
<p>Each conversion method has its own pros &amp; cons.</p>
<h2 id="heading-extension-methods">Extension Methods</h2>
<h3 id="heading-pros">Pros</h3>
<ul>
<li>Simple implementation.</li>
<li>Clear code - no annotations "magic".</li>
</ul>
<h3 id="heading-cons">Cons</h3>
<ul>
<li>Lots of boiler plate code.</li>
<li>Limited functionality.</li>
<li>Does not scale well.</li>
</ul>
<h2 id="heading-object-mapper">Object Mapper</h2>
<h3 id="heading-pros">Pros</h3>
<ul>
<li>Little to none boiler-plate code.</li>
<li>Auto mapping.</li>
<li>Generic code.</li>
<li><a target="_blank" href="https://dev.to/krud/object-mapping-advanced-features-qol-with-kotlin-5dgn">Advanced features</a>.</li>
<li>Code reuse.</li>
</ul>
<h3 id="heading-cons">Cons</h3>
<ul>
<li>Requires to learn new library.</li>
<li>Annotations "magic".</li>
</ul>
<h1 id="heading-summary">Summary</h1>
<p>Like most things in development, there is no right answer here. The answer is that it depends on the project. For small simple projects extension methods are more than enough to convert classes, but for large enterprise projects using an object mapper can give the freedom to achieve better architecture and more generic code that can keep moving forward with large codebase and lots of models.</p>
]]></content:encoded></item><item><title><![CDATA[So the journey begins]]></title><description><![CDATA[The stack — VB6, C
The Experience — 2 Years
The Job — High school

Isn’t learning fun?
To set the scene, it was early 2000s in a small farming village. Yes we had internet, but it was dial up, and no stack overflow or anything close yet, the best you...]]></description><link>https://krud.dev/so-the-journey-begins</link><guid isPermaLink="true">https://krud.dev/so-the-journey-begins</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Career]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[TheWizKid]]></dc:creator><pubDate>Wed, 10 Aug 2022 12:57:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660135324779/eainv1Zrc.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The stack — VB6, C</p>
<p>The Experience — 2 Years</p>
<p>The Job — High school</p>
<hr />
<h2 id="heading-isnt-learning-fun">Isn’t learning fun?</h2>
<p>To set the scene, it was early 2000s in a small farming village. Yes we had internet, but it was dial up, and no stack overflow or anything close yet, the best you could hope for is a forum post.</p>
<p>So how did we learn? TL;DR — Books and lots of them…</p>
<p>I remember going to the library looking for books, swapping with friends. If you got the expensive ones you even got a CD (you know the round thing with a hole in it) with them with code examples and lesson projects, not that the CD ever worked (or was even there) from the library. No searching the book for your problem or an example, no copy paste, nothing. Just read and hope you remember later where you saw something about that problem you are having.</p>
<p>Yes the internet existed, but there wasn’t much in the way or programming guides, tutorials, or even examples. One of the most useful tools was IRC channels (for you kids out there, a really old chat). Tell you the truth, I don’t even remember how I found what channel to write to, but I remember talking to people from around the world about the most silly things, things that today you will find the solution to as the top search result on google.</p>
<h2 id="heading-i-know-this-is-weird-but-you-can-learn-at-school">I know this is weird, but you can learn at school</h2>
<p>When I reached the last year of high school, I took a tech class. In this class we learned things from electrical engineering basics, mechanical design, and of course programming. The main problem was, I had taught myself more than what the teacher reached in class. Nonetheless I gained a great resource, my teacher could answer questions, point me in the right direction.</p>
<p>First of all, I would like to say, not all teachers are bad (yes many are, but not all). Luckily for me our high school tech teacher saw my potential (especially after I broke the school’s network). I used to get bored in class, everyone was learning C and VB6 at a level I passed a long time ago on my own. That is when my teacher came to my rescue.</p>
<h2 id="heading-my-first-real-project">My first real project</h2>
<p>Computer vision, you know when computers look at an image and try to understand what is there. Well for that time it was no AI models or anything, it was purely algorithmic. My mission should I choose to accept it (over being thrown out of class) was to take this “new” library that allowed me to capture an image from a webcam in VB6 and process it (pixel by pixel), and try and make out a shape in an image, simple geometric shapes (circle, square, triangle).</p>
<p>So my best friend and I set out to this task, it was soooo interesting we would have all nighters trying to solve it. Let me take you through the basics.</p>
<p>Go over the image one pixel at a time to try and find a place with a big change in color (black shape on white paper).
When I reach it, go in a pattern to find its neighbor that is also a border pixel.
Do this in a loop till I can’t find any more border pixels.
This worked (in theory). There is always a “but”… It all went to hell when we would hit these edge cases of a few pixels out of place.</p>
<p>That’s when it hit me, the solution may be obvious to you, but to me it wasn’t. Well, it turns out there is a use for the data structure “stack” we’ve been taught. We put all pixels in the stack, and each time we would hit a brick wall, we would pop a pixel and try again. This would continue till we popped them all out and got back to our starting pixel.</p>
<p>This turned out to be very effective, and solved our biggest problem.</p>
<p>We actually found a few solutions for understanding what shape it was.</p>
<p>From the trivial, see how many “straight” lines made up the shape, which worked pretty well for simple shapes. To the most advanced solution, that I am still proud of till this day, calculate the area of the shape, and the perimeter of the shape, and see what constant best defines the relation.</p>
<h2 id="heading-the-moral-of-the-story">The moral of the story</h2>
<p>I told you this whole story to come to a small point, one that shaped the next few years of my development life. Data structures &amp; design patterns are there for a reason, and even though it might not be obvious, you ask yourself “why would I ever need that”. At some point you will, and it’s good to keep them handy.</p>
<hr />
<p>If you would like to check out our <a target="_blank" href="https://github.com/krud-dev/shapeshift/">open source library</a> and leave feedback we would appreciate it greatly.</p>
]]></content:encoded></item><item><title><![CDATA[Object Mapping advanced features & QoL with Kotlin]]></title><description><![CDATA[When working with multi-layered applications, external libraries, a legacy code base or external APIs, we are often required to map between different objects or data structures.
In this tutorial, we will check out some Object Mapping libraries advanc...]]></description><link>https://krud.dev/object-mapping-advanced-features-qol-with-kotlin</link><guid isPermaLink="true">https://krud.dev/object-mapping-advanced-features-qol-with-kotlin</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[architecture]]></category><category><![CDATA[Object Oriented Programming]]></category><dc:creator><![CDATA[Aviv Mor]]></dc:creator><pubDate>Wed, 10 Aug 2022 12:46:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660135415481/JhCo3c-AQ.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When working with multi-layered applications, external libraries, a legacy code base or external APIs, we are often required to map between different objects or data structures.</p>
<p>In this tutorial, we will check out some Object Mapping libraries advanced features to simplify this task while saving development and maintenance time.</p>
<p>In our examples we will use the library <a target="_blank" href="https://github.com/krud-dev/shapeshift/">ShapeShift</a>. It's a light-weight object mapping library for Kotlin/Java with lots of cool features.</p>
<h1 id="heading-auto-mapping">Auto Mapping</h1>
<p>We will start with a bang. Auto mapping can and will save you lots of time and boiler-plate code. Some applications require manual mapping between objects, but most applications will save tons of time working on boring boiler-plate by just using this one feature. And it gets even better, with ShapeShift's default transformers we can even use automatic mapping between different data types.</p>
<h2 id="heading-simple-mapping">Simple Mapping</h2>
<p>Let's start with a simple example for auto mapping. We have our two objects, imagine they could also have tens, hundreds, or even thousands (for the crazy people here) of fields.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> name: String? = <span class="hljs-literal">null</span>
    <span class="hljs-keyword">var</span> email: String? = <span class="hljs-literal">null</span>
    <span class="hljs-keyword">var</span> phone: String? = <span class="hljs-literal">null</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> name: String? = <span class="hljs-literal">null</span>
    <span class="hljs-keyword">var</span> email: String? = <span class="hljs-literal">null</span>
    <span class="hljs-keyword">var</span> phone: String? = <span class="hljs-literal">null</span>
}
</code></pre>
<p>We want to map all the field from <code>User</code> to <code>UserDTO</code>. Using auto mapping we don't need to write any boiler-plate code. The mapper will be defined as follow:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mapper = mapper&lt;User, UserDTO&gt; {
    autoMap(AutoMappingStrategy.BY_NAME_AND_TYPE)
}
</code></pre>
<p>Voila! All the fields will be mapped automatically without any manual boiler-plate code.</p>
<h2 id="heading-advanced-mapping">Advanced Mapping</h2>
<p>In this example we will use the power of <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/transformers#default-transformers">default transformers</a> to take auto mapping even further.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> name: String? = <span class="hljs-literal">null</span>
    <span class="hljs-keyword">var</span> birthDate: Date? = <span class="hljs-literal">null</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> fullName: String? = <span class="hljs-literal">null</span>
    <span class="hljs-keyword">var</span> birthDate: <span class="hljs-built_in">Long</span>? = <span class="hljs-literal">null</span>
}
</code></pre>
<p>Note that the types of the <code>birthDate</code> field are different in the source and destination classes. But using the power of default transformers we can still use auto mapping here.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mapper = mapper&lt;User, UserDTO&gt; {
    autoMap(AutoMappingStrategy.BY_NAME)
}
</code></pre>
<p>We changed the auto mapping strategy to <code>BY_NAME</code> so it will map fields also with different types. Now we need to register a default transformer to the <code>ShapeShift</code> instance in order for it to know how to transform <code>Date</code> to <code>Long</code>.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> shapeShift = ShapeShiftBuilder()
    .withTransformer(DateToLongMappingTransformer(), <span class="hljs-literal">true</span>)
    .build()
</code></pre>
<p>We can also add manual mapping on top of the auto mapping in order to add/change behavior. The source and destination classes have different names for the <code>name</code> field so we will add manual mapping for it.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mapper = mapper&lt;User, UserDTO&gt; {
    autoMap(AutoMappingStrategy.BY_NAME)
    User::name mappedTo UserDTO::fullName
}
</code></pre>
<p>Auto mapping is great for use cases that does not require specific mapping. It helps reduce the amount manual boiler-plate code needed to configure mapping and also helps you keep your sanity.</p>
<h1 id="heading-transformers">Transformers</h1>
<p>Transformers are very useful feature that allows you to transform the type/value of a field to a different type/value when mapping a field.</p>
<p>Some use cases we have been using widely:</p>
<ul>
<li>Transform date to long and vice versa between server and client objects.</li>
<li>Transform JSON string to it's actual type and vice versa between server and client objects.</li>
<li>Transform comma separated string to list of enums.</li>
<li>Transform another object id to its object or one of its fields from the DB using Spring transformers.</li>
</ul>
<h2 id="heading-basic-transformers">Basic Transformers</h2>
<p>We will start with a simple transformer example. Date-to-Long  and Long-to-Date transformers:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DateToLongMappingTransformer</span> : <span class="hljs-type">MappingTransformer</span>&lt;<span class="hljs-type">Date, Long</span>&gt; </span>{
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">transform</span><span class="hljs-params">(context: <span class="hljs-type">MappingTransformerContext</span>&lt;<span class="hljs-type">out</span> <span class="hljs-type">Date</span>&gt;)</span></span>: <span class="hljs-built_in">Long</span>? {
        <span class="hljs-keyword">return</span> context.originalValue?.time
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LongToDateMappingTransformer</span> : <span class="hljs-type">MappingTransformer</span>&lt;<span class="hljs-type">Long, Date</span>&gt; </span>{
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">transform</span><span class="hljs-params">(context: <span class="hljs-type">MappingTransformerContext</span>&lt;<span class="hljs-type">out</span> <span class="hljs-type">Long</span>&gt;)</span></span>: Date? {
        context.originalValue ?: <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
        <span class="hljs-keyword">return</span> Date(context.originalValue)
    }
}
</code></pre>
<p>All we need to do now is to <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/transformers#registering-transformers">register</a> them.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> shapeShift = ShapeShiftBuilder()
    .withTransformer(DateToLongMappingTransformer(), <span class="hljs-literal">true</span>) <span class="hljs-comment">// "true" is optional, we are registering the transformers as default transformers, more on that later.</span>
    .withTransformer(LongToDateMappingTransformer(), <span class="hljs-literal">true</span>)
    .build()
</code></pre>
<p>That's it! We can now use the transformers when mapping objects.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> name: String? = <span class="hljs-literal">null</span>
    <span class="hljs-keyword">var</span> birthDate: Date? = <span class="hljs-literal">null</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> name: String? = <span class="hljs-literal">null</span>
    <span class="hljs-keyword">var</span> birthDate: <span class="hljs-built_in">Long</span>? = <span class="hljs-literal">null</span>
}

<span class="hljs-keyword">val</span> mapper = mapper&lt;User, UserDTO&gt; {
    User::id mappedTo UserDTO::id
    User::name mappedTo UserDTO::name
    User::birthDate mappedTo UserDTO::birthDate withTransformer DateToLongMappingTransformer::<span class="hljs-class"><span class="hljs-keyword">class</span> // <span class="hljs-title">We</span> <span class="hljs-title">don</span>'<span class="hljs-title">t</span> <span class="hljs-title">have</span> <span class="hljs-title">to</span> <span class="hljs-title">state</span> <span class="hljs-title">the</span> <span class="hljs-title">transformer</span> <span class="hljs-title">here</span> <span class="hljs-title">because</span> <span class="hljs-title">it</span> <span class="hljs-title">is</span> <span class="hljs-title">a</span> <span class="hljs-title">default</span> <span class="hljs-title">transformer</span></span>
}
</code></pre>
<h2 id="heading-inline-transformers">Inline Transformers</h2>
<p>In some use cases we want to transform the value but we don't need a reusable transformer and we don't want to create a class just for a one time use.</p>
<p>Inline transformers for the rescue! Inline transformers allow to transform the value without the need to create and register and transformer.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> shapeShift = ShapeShiftBuilder()
        .withMapping&lt;Source, Target&gt; {
            <span class="hljs-comment">// Map birthDate to birthYear with a transformation function</span>
            Source::birthDate mappedTo Target::birthYear withTransformer { (originalValue) -&gt;
                originalValue?.year
            }
        }
        .build()
</code></pre>
<h2 id="heading-advanced-transformers">Advanced Transformers</h2>
<p>Transformers also allow us to do transformations with the DB or other data sources.</p>
<p>In this example we will use the power of the <a target="_blank" href="https://shapeshift.krud.dev/guides/spring-usage">Spring Boot integration</a> to create transformers with DB access.</p>
<p>We have three models:</p>
<ul>
<li>Job - DB entity.</li>
<li>User - DB entity.</li>
<li>UserDTO - Client model.</li>
</ul>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Job</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> name: String = <span class="hljs-string">""</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> jobId: String? = <span class="hljs-literal">null</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">var</span> id: String = <span class="hljs-string">""</span>
    <span class="hljs-keyword">var</span> jobName: String? = <span class="hljs-literal">null</span>
}
</code></pre>
<p>We want to convert the <code>jobId</code> on <code>User</code> to <code>jobName</code> on <code>UserDTO</code> by querying the job from the DB and setting it on the DTO.</p>
<p>In Spring's case, you generally avoid interaction with the application context from static functions or functions on domain objects.</p>
<p>We will use a ShapeShift's <a target="_blank" href="https://shapeshift.krud.dev/guides/spring-usage">Spring integration</a> to create a component as a transformer to access our DAO bean.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Component</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">JobIdToNameTransformer</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> jobDao: JobDao
) : MappingTransformer&lt;String, String&gt;() {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">transform</span><span class="hljs-params">(context: <span class="hljs-type">MappingTransformerContext</span>&lt;<span class="hljs-type">out</span> <span class="hljs-type">String</span>&gt;)</span></span>: String? {
        context.originalValue ?: <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
        <span class="hljs-keyword">val</span> job = jobDao.findJobById(context.originalValue!!)
        <span class="hljs-keyword">return</span> job.name 
    }
}
</code></pre>
<p>All that's left to do is to use this transformer in our mapping.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mapper = mapper&lt;User, UserDTO&gt; {
    User::id mappedTo UserDTO::id
    User::jobId mappedTo UserDTO::jobName withTransformer JobIdToNameTransformer::<span class="hljs-class"><span class="hljs-keyword">class</span></span>
}
</code></pre>
<p>Another bonus of using transformers is their reusability. In some use cases, We could create more generic transformers that will have application-wide usage.</p>
<h2 id="heading-default-transformers">Default Transformers</h2>
<p>When registering transformers you can indicate wether a transformer is a <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/transformers#default-transformers">default transformer</a>. A default transformer of types \ is used when you map a field of type \ to field of type \ without specifying a transformer to be used.</p>
<p>As we already seen, default transformers are useful for recurring transformations and especially for automatic mapping.</p>
<h1 id="heading-deep-mapping">Deep Mapping</h1>
<p>What if we want to map from/to fields that available inside a field which is an object? We can even do that, easily.</p>
<p>In order to access child classes we can use the <code>..</code> operator. Let's look at the following example.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">From</span> </span>{
    <span class="hljs-keyword">var</span> child: Child = Child()

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> </span>{
        <span class="hljs-keyword">var</span> value: String?
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">To</span> </span>{
    <span class="hljs-keyword">var</span> childValue: String?
}
</code></pre>
<p>We want to map the <code>value</code> field in <code>Child</code> class inside the <code>From</code> class to the <code>childValue</code> field in the <code>To</code> class. We will create a mapper with the <code>..</code> operator.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mapper = mapper&lt;From, To&gt; {
    From::child..From.Child::value mappedTo To::childValue
}
</code></pre>
<p>Let's take it one step further with multi level depth.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">From</span> </span>{
    <span class="hljs-keyword">var</span> grandChildValue: String?
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">To</span> </span>{
    <span class="hljs-keyword">var</span> child: Child = Child()

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> </span>{
        <span class="hljs-keyword">var</span> grandChild: GrandChild = GrandChild()
    }

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GrandChild</span> </span>{
        <span class="hljs-keyword">var</span> value: String?
    }
}
</code></pre>
<p>To access the grand child field we just use the <code>..</code> operator twice.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mapper = mapper&lt;From, To&gt; {
    From::grandChildValue mappedTo To::child..To.Child::grandChild..To.GrandChild::value
}
</code></pre>
<h1 id="heading-conditional-mapping">Conditional Mapping</h1>
<p>Conditions allow us to add a predicate to a specific field mapping to determine whether this field should be mapped.</p>
<p>Using this feature is as easy as creating a condition.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NotBlankStringCondition</span> : <span class="hljs-type">MappingCondition</span>&lt;<span class="hljs-type">String</span>&gt; </span>{
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">isValid</span><span class="hljs-params">(context: <span class="hljs-type">MappingConditionContext</span>&lt;<span class="hljs-type">String</span>&gt;)</span></span>: <span class="hljs-built_in">Boolean</span> {
        <span class="hljs-keyword">return</span> !context.originalValue.isNullOrBlank()
    }
}
</code></pre>
<p>And adding the condition to the desired field mapping.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SimpleEntity</span></span>(
    <span class="hljs-keyword">val</span> name: String
)

<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SimpleEntityDisplay</span></span>(
    <span class="hljs-keyword">val</span> name: String = <span class="hljs-string">""</span>
)

<span class="hljs-keyword">val</span> mapper = mapper&lt;SimpleEntity, SimpleEntityDisplay&gt; {
    SimpleEntity::name mappedTo SimpleEntityDisplay::name withCondition NotBlankStringCondition::<span class="hljs-class"><span class="hljs-keyword">class</span></span>
}
</code></pre>
<h2 id="heading-inline-conditions">Inline Conditions</h2>
<p>Like transformers, conditions can also be added inline using a function.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mapper = mapper&lt;SimpleEntity, SimpleEntityDisplay&gt; {
    SimpleEntity::name mappedTo SimpleEntityDisplay::name withCondition {
        !it.originalValue.isNullOrBlank()
    }
}
</code></pre>
<h1 id="heading-annotations-mapping">Annotations Mapping</h1>
<p>This specific feature receives lots of hate because it breaks the separation of concerns principle. Agreed, this could be an issue in some applications, but in some use cases where all objects are part of the same application it can also be very useful to configure the mapping logic on top of the object. Check out the <a target="_blank" href="https://shapeshift.krud.dev/api-documentation/annotations">documentation</a> and decide for yourself.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Object mapping libraries are not the solution for every application. For small, simple applications using boiler-plate mapping functions are more than enough. But, when developing larger, more complex applications, object mapping libraries can take your code to the next level, saving you development and maintenance time. All of these while reducing the amount of boiler-plate code and overall improving the development experience.</p>
<p>On a personal note, I used to work with manual mapping functions and was ok with it. It was "just" some simple lines of code. After upgrading our applications to use object mapping as part of our "boiler-plate free" framework (We will discuss that framework at a later time), I can't go back. Now we spend more time on what's important and interesting and almost no time on boring boiler-plate code.</p>
]]></content:encoded></item><item><title><![CDATA[Open source, philosophy, hate & other random words]]></title><description><![CDATA[Some time ago our team has released our first open source library to the wild. We finished our first production ready version, posted it on Reddit and waited for the open source community to welcome us with open arms. After all, we are investing our ...]]></description><link>https://krud.dev/open-source-philosophy-hate-and-other-random-words</link><guid isPermaLink="true">https://krud.dev/open-source-philosophy-hate-and-other-random-words</guid><category><![CDATA[Open Source]]></category><category><![CDATA[community]]></category><category><![CDATA[developer relations]]></category><dc:creator><![CDATA[Aviv Mor]]></dc:creator><pubDate>Thu, 04 Aug 2022 15:09:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659625671765/BV3xbly18.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Some time ago our team has released our first <a target="_blank" href="https://github.com/krud-dev/shapeshift/">open source library</a> to the wild. We finished our first production ready version, posted it on Reddit and waited for the open source community to welcome us with open arms. After all, we are investing our own free time to create a great product to help others, and it's all for FREE.</p>
<p>Oh how naive we were... Of course some truly appreciated our contribution, yet others didn't understand what we are doing, and the crème de la crème just wanted to hate.</p>
<p>I think that in today's world it's hard to put your work out there. When you post your code you feel very vulnerable, a bit naked. It's like your soul is out there for everyone to see and criticize. And don't get me wrong, I think criticism is very important and it's one of the best ways to learn and grow.</p>
<p>On the other hand, it's very easy to completely dismiss someone else's work. It takes almost no time and costs nothing. Also I'm pretty sure some people enjoy it very much.</p>
<p>So when you meet someone like that, how should you react? The first instinct is to ignore or "yell" back, dismiss all criticism completely and move forward. I decided to do otherwise, breathe and count from 1 to 10, slowly, like my mom used to say, read it again, and think where it is coming from.</p>
<p>For example, in one of these scenarios a comment ended with "I would stay away from it" because of a disagreement with the project's coding style. Spoiler: after a few back and forths the conversation ended with "Good luck though!". How about that?</p>
<p>What is crazy and beautiful about programming. We think it is objective, that it is exact science and there is right and wrong. But the truth is, it is also art, and there is a huge subjective component to it.</p>
<p>What I realized is just that my coding philosophy is different. Even though we are still in a disagreement, it was fascinating to learn that there are completely different points of view for doing the exact same thing, and I learned a thing or two in the process.</p>
<p>What is the point of all of this? I think open source is amazing. For some reason we have crazy drive to develop stuff for free just to share it with the world and help others. Nonetheless, I think there is a lot of room for improvement in our discussions and critique. Maybe I'm naive again, however I still believe the community, our community can do better and hope for better communication between us all (and hopefully over a beer).</p>
<p>If you would like to check out our <a target="_blank" href="https://github.com/krud-dev/shapeshift/">open source library</a> and leave feedback we would appreciate it greatly.</p>
]]></content:encoded></item><item><title><![CDATA[My journey to defeat the evil boiler-plate code]]></title><description><![CDATA[A long time ago when I was about to finish university and just above junior level programmer, I joined a new company and received their organized, fresh out of the oven, MVP code.
The code was written by an Ukrainian developer I have never met, but l...]]></description><link>https://krud.dev/my-journey-to-defeat-the-evil-boiler-plate-code</link><guid isPermaLink="true">https://krud.dev/my-journey-to-defeat-the-evil-boiler-plate-code</guid><category><![CDATA[Open Source]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[crud]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[Aviv Mor]]></dc:creator><pubDate>Thu, 04 Aug 2022 15:06:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659625354872/szHOIcdQG.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A long time ago when I was about to finish university and just above junior level programmer, I joined a new company and received their organized, fresh out of the oven, MVP code.</p>
<p>The code was written by an Ukrainian developer I have never met, but loved in my heart. It wasn't the first time I saw a layered application, but it was the best of times.
She put everything there, clean controllers layer for the API, service layer to handle process logic, handlers layer to tackle fine grained actions, and of course DAO layer to handle all the DB stuff. From then on, all my future projects followed her beautiful layering and everything was better.</p>
<p>Fast forward a couple of years, my partner and I are now managing the R&amp;D team somewhere (not interesting &amp; not important). Like most teams, we are being swamped with feature requests, and other bullshit the management finds "CRITICAL". Our code-base is still quite organized with the layering we know and love but we start noticing some issues (Add dramatic sound...).</p>
<p>Every time we need to add a new CRUD entity to the system, even the most basic entity for some kind of configuration, we need to add A LOT of boiler plate code. We start by copying an existing entity code, then:</p>
<ul>
<li>Update the controller with the new entity. Clean not relevant code.</li>
<li>Update the service with the new entity, again. Clean not relevant code.</li>
<li>Update the handler with the new entity, again... Clean not relevant code.</li>
<li>Update the DAO with the new entity, again....... Clean not relevant code.</li>
</ul>
<p>The next image is not for the faint of heart. It contains the boiler-plate code required for one the SIMPLEST use cases. The horror!</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ftweaa5aldwdl18cajxa.png" alt="Boiler-plate code horror" /></p>
<p>Just writing it and remembering the old times made me tired. And more important, adding the new entity is the easy part, now we have more code we need to maintain. Our code base is growing and doing system wide changes becomes impossible.</p>
<p>Then one day, we are on a flight to some conference, disconnected from the world and connected to our inner thoughts (no wifi...). My partner, comes to me and say, "What if we develop a generic CRUD framework without boiler-plate, just add an entity and everything else is available in seconds". At first I was skeptical, but he is the smart one between us so I give it another thought and decides to roll with it.</p>
<p>Fast forward again, my partner and his trusted sidekick have kept their promise and delivered their boiler-plate free CRUD framework, after countless of fights and iterations (to this day). I don't want to bore you with too much code, but I just have to show a simple example to honor everything we lost along the way.</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Entity</span>
<span class="hljs-meta">@Table(name = <span class="hljs-meta-string">"example"</span>)</span>
<span class="hljs-meta">@DefaultMappingTarget(ExampleDisplay::class)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Example</span></span>(
    <span class="hljs-meta">@MappedField</span>
    <span class="hljs-meta">@Column</span>
    <span class="hljs-keyword">var</span> exampleString: String?,

    <span class="hljs-meta">@MappedField</span>
    <span class="hljs-meta">@Column</span>
    <span class="hljs-keyword">var</span> exampleBoolean: <span class="hljs-built_in">Boolean</span>?,

    <span class="hljs-comment">// ...</span>

) : AbstractJpaEntity()
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-meta">@DefaultMappingTarget(Example::class)</span>
<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExampleDisplay</span></span>(
    <span class="hljs-meta">@MappedField</span>
    <span class="hljs-keyword">var</span> exampleString: String? = <span class="hljs-literal">null</span>,

    <span class="hljs-meta">@MappedField</span>
    <span class="hljs-keyword">var</span> exampleBoolean: <span class="hljs-built_in">Boolean</span>? = <span class="hljs-literal">null</span>,

    <span class="hljs-comment">// ...</span>

) : AbstractJpaDisplay()
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping(<span class="hljs-meta-string">"example"</span>)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExampleController</span> : <span class="hljs-type">BaseCRUDController</span>&lt;<span class="hljs-type">Example, ExampleDisplay</span>&gt;</span>() {
}
</code></pre>
<p>That's it! Now I know what you are going to tell me. Where are your layers that you couldn't shut up about?! The beautiful thing is, they are all here. Behind the scenes the framework has all the layers and it allows you to use hooks and other mechanisms to add additional logic/frameworks/...
Since then, the smart guys have added permissions, security and more on top of the CRUD framework, according to the requirements of each project.</p>
<p>So your next thought is probably "Where do I sign?". Hold your horses for a moment, I know your honest current thought is that I'm stupid and I know nothing, fair. Also I would be happy to give you the CRUD framework but it's not truly open source ready. If you want to take a look anyway it's available <a target="_blank" href="https://github.com/crud-studio/crud-framework">here</a>.</p>
<p>Because it's a large framework and it will take time to bring it to the level that we want for an open source release, we decided to start small and separate our object mapping capabilities into a separate library. Of course the hardest part was to find a name for this library but in the end we settled for <a target="_blank" href="https://github.com/krud-dev/shapeshift">ShapeShift</a>.</p>
<p>If you are not sure what is object mapping or why you need it you can read more about it <a target="_blank" href="https://dev.to/avivm/object-mapping-pros-cons-30ln">here</a>.</p>
<p>If you have any thoughts/comments/disses you would like to throw at me I would be more than happy to connect.</p>
]]></content:encoded></item><item><title><![CDATA[The story of a Noob]]></title><description><![CDATA[The stack — VB6, Macros, MS Access
The Experience — 0 Years
The Job — Start of High school

Where do I even begin?
Like I stated in the prologue, I was fascinated with tech from a very young age. What I failed to mention before is that thanks to my l...]]></description><link>https://krud.dev/the-story-of-a-noob</link><guid isPermaLink="true">https://krud.dev/the-story-of-a-noob</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Career]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[TheWizKid]]></dc:creator><pubDate>Thu, 04 Aug 2022 08:04:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659600201974/7ewqHNBWw.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The stack — VB6, Macros, MS Access</p>
<p>The Experience — 0 Years</p>
<p>The Job — Start of High school</p>
<hr />
<h2 id="heading-where-do-i-even-begin">Where do I even begin?</h2>
<p>Like I stated in the prologue, I was fascinated with tech from a very young age. What I failed to mention before is that thanks to my loving and understanding parents, my curiosity was not killed in school. That’s mostly thanks to the fact that in my house I could always take any “junk” home to take apart and learn how it ticks.</p>
<h2 id="heading-my-first-steps">My first steps</h2>
<p>At the age of 13, I was already pretty good on a PC, but haven’t really dived into programming yet. My first real time was when I went to a few VB6 classes and convinced my parents to buy me a book.</p>
<p>For me it was like magic, I could tell the computer what to do and it would do it, as long as I didn’t fuck it up somehow (which happened a lot at that time). I wrote small dumb things, what most would call a “Hello World”.</p>
<h2 id="heading-ive-been-a-bad-boy">I’ve been a bad boy</h2>
<p>It was around the my second year of High school when I noticed how bad the computer system at school was, how weak the security was, and of course I had to find out if I could beat it. But being the goodie two shoes I was, I was scared to do it, and if it wasn’t for the fact that the guy in charge of said system told me I was wrong (he thought it was secure), I wouldn’t have even tried.</p>
<p>So I did what had to be done, I got hold of *.pwl files (win 98 password files, and yes I am a dinosaur), and found out how to crack them. I wrote my first brute force script and made all the PCs in class run it at night. Luckily for me the password was short and within a few weeks it was cracked.</p>
<h2 id="heading-you-have-got-to-start-somewhere">You have got to start somewhere</h2>
<p>Yes I know what you are going to say, what a geek, nerd, … Yes, I spent my free time teaching myself programming. No, I wouldn’t change that. I’m not much of a reader (till this day I can’t read for fun), but somehow going through a programming book was not a chore and I learned a ton. I think the most important part was that it interested me and I was passionate about it.</p>
<p>Today is different, but I highly recommend to anyone to just give it a try, go take a course online, or use YouTube, or even just go though GitHub. Today it’s sooo much easier and more accessible. Who knows you may just find that programming is your dream job.</p>
<hr />
<p>If you would like to check out our <a target="_blank" href="https://github.com/krud-dev/shapeshift/">open source library</a> and leave feedback we would appreciate it greatly.</p>
]]></content:encoded></item><item><title><![CDATA[Prologue — One devs journey]]></title><description><![CDATA[A brief history
It’s rude not to introduce myself, so I’ll start with a little background, just to get us started. I can call myself a developer for over 15 years now, and a tinkerer for a few more. I started playing with technology from the very you...]]></description><link>https://krud.dev/prologue-one-devs-journey</link><guid isPermaLink="true">https://krud.dev/prologue-one-devs-journey</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Career]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[TheWizKid]]></dc:creator><pubDate>Thu, 04 Aug 2022 08:02:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659601159642/56EGoHcRKV.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-a-brief-history">A brief history</h2>
<p>It’s rude not to introduce myself, so I’ll start with a little background, just to get us started. I can call myself a developer for over 15 years now, and a tinkerer for a few more. I started playing with technology from the very young age of 7, when I entered and won a race event where I built a toy solar car. Till today, as a system architect and having some successes (and failures) at tech startups, and running my own dev &amp; consulting business.</p>
<h2 id="heading-whats-the-point-of-all-this">What’s the point of all this</h2>
<p>As of late, my team and I have released the first of our libraries as <a target="_blank" href="https://github.com/krud-dev/shapeshift/">open source</a>, this has made me look back at the path that led me here. My main goal is to share that story, the ups and downs (and sometimes sideways) and hopefully it will help someone on their path. I can’t promise it will be interesting all the time (or even pretty), but I hope you will join me for the journey.</p>
<h2 id="heading-ill-try-and-keep-it-brief">I’ll try and keep it brief</h2>
<p>I will be writing this as a few different posts, each one not much longer than this one, as I want it to be a quick and fun read. So this is the plan:</p>
<ol>
<li><strong>The story of a Noob</strong> — My somewhat humble beginnings</li>
<li><strong>The journey begins</strong> — Teaching myself in the age before google</li>
<li><strong>They don’t call it intelligence for nothing</strong> — My military career</li>
<li><strong>School can’t teach you everything</strong> — My time at Uni and my first freelance work</li>
<li><strong>It’s time to settle down</strong> — My first real job</li>
<li><strong>Good code is like an onion, it has layers</strong> — The right way to write code</li>
<li><strong>My eureka moment</strong> — After writing the same code over and over, something had to change</li>
<li><strong>It’s ALIVE</strong> — My solution to CRUD boilerplate, and the evolution of the layers</li>
<li><strong>Shit just got real</strong> — Using what I learned to land a big contract</li>
<li><strong>Time to give back</strong> — The birth of my first open source</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Creating an automatic Helm Repository with GitHub Actions]]></title><description><![CDATA[I needed a Helm repository to house my private charts, but at the same time I didn't want to have to deal with and maintain a server for it.
In my research I discovered that it is possible and quite easy to use a git repository for this purpose. Grea...]]></description><link>https://krud.dev/creating-an-automatic-helm-repository-with-github-actions</link><guid isPermaLink="true">https://krud.dev/creating-an-automatic-helm-repository-with-github-actions</guid><category><![CDATA[Helm]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Devops]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[github-actions]]></category><dc:creator><![CDATA[Idan Elhalwani]]></dc:creator><pubDate>Wed, 10 Feb 2021 08:23:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659607094825/W5hWNhytu.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I needed a Helm repository to house my private charts, but at the same time I didn't want to have to deal with and maintain a server for it.</p>
<p>In my research I discovered that it is possible and quite easy to use a git repository for this purpose. Great! However, I feel that did not go far enough for my use. For once, I did not want to have to manually package and index the repository on every chart change and so I decided to expand on it. </p>
<h2 id="heading-the-end-result">The end result</h2>
<p>At the end, we should have a Helm repository that updates itself on every change to the git repository structured as follows:</p>
<pre><code>├── master
│   ├── charts<span class="hljs-operator">/</span>
│   │   └── example<span class="hljs-operator">/</span>
│   └── sync_repo.sh
└── repo
    ├── example<span class="hljs-number">-0</span><span class="hljs-number">.1</span><span class="hljs-number">.0</span>.tgz
    └── index.yaml
</code></pre><p>The full example is available at my <a target="_blank" href="https://github.com/Idane/helm-repo-example">GitHub</a></p>
<h2 id="heading-the-setup">The setup</h2>
<p>For this, create a new git repository, clone it locally and create a new chart in the <code>charts</code> directory;</p>
<pre><code class="lang-bash">mkdir charts
<span class="hljs-built_in">cd</span> charts
helm create example
</code></pre>
<p>Once that's done and committed, we will create an <strong>orphan branch</strong> to store the actual Helm repository. Why an orphan branch? On every commit to the repository, CircleCI will do its own commit to update the Helm repository. </p>
<p>While this step is optional, it prevents developers from having to pull-rebase every time they make a change to the repo, and has the added benefit of keeping the history of the master branch clean.
Create an orphan branch called <code>repo</code> as follows:</p>
<pre><code class="lang-bash">git checkout --orphan repo
git rm -rf . 
touch index.yaml
git add index.yaml
git commit -m <span class="hljs-string">'Initial Commit'</span>
git push -u origin repo
</code></pre>
<p>Now let's return to the <code>master</code> branch. Our next step is to create a script which our CI will use on every commit. The script will package all charts, and re-generate the <code>index.yaml</code> file.</p>
<p>Use your text editor of choice to create <code>sync_repo.sh</code> and add the following to it:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/sh</span>
mkdir -p repo
<span class="hljs-built_in">cd</span> repo
helm package ../charts/*
helm repo index .
</code></pre>
<p>At last, we add the last piece of this puzzle and integrate GitHub Actions into this process. </p>
<p>Our action will pick off where our shell script left us off; It will clone the separate <code>repo</code> branch and copy the generated files to it, finally committing and pushing back the changes to origin.</p>
<p>For this, we'll create the following action at <code>.github/workflows/sync_repo.yml</code>.</p>
<pre><code class="lang-yml"><span class="hljs-attr">name:</span> <span class="hljs-string">Sync</span> <span class="hljs-string">Helm</span> <span class="hljs-string">Repo</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">master</span> ]
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">ref:</span> <span class="hljs-string">'master'</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">'master'</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v2</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">ref:</span> <span class="hljs-string">'repo'</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">'repo'</span>   
      <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">azure/setup-helm@v1</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Sync</span> <span class="hljs-string">Helm</span> <span class="hljs-string">Repo</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">cd</span> <span class="hljs-string">master</span> <span class="hljs-string">&amp;&amp;</span> <span class="hljs-string">sh</span> <span class="hljs-string">sync_repo.sh</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Move</span> <span class="hljs-string">repo</span> <span class="hljs-string">folder</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          mv master/repo/* repo/
          cd repo
          git config user.email "idan@elhalwani.com"
          git config user.name "Idan Elhalwani"
          git add -A
          git diff --quiet &amp;&amp; git diff --staged --quiet || git commit -m "Update repo [SKIP CI]" -m "${{ github.event.head_commit.message }}"
          git push</span>
</code></pre>
<p>Let's break down the action;</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Move our generated files from the master branch folder to the repo branch folder</span>
mv master/repo/* repo/
<span class="hljs-built_in">cd</span> repo
<span class="hljs-comment"># Configure git for when we're ready to commit</span>
git config user.email <span class="hljs-string">"idan@elhalwani.com"</span>
git config user.name <span class="hljs-string">"Idan Elhalwani"</span>
<span class="hljs-comment"># Add all new files and attempt to commit. If there is nothing new, the commit won't go through and nothing will be pushed</span>
git add -A
git diff --quiet &amp;&amp; git diff --staged --quiet || git commit -m <span class="hljs-string">"Update repo [SKIP CI]"</span> -m <span class="hljs-string">"<span class="hljs-variable">${{ github.event.head_commit.message }</span>}"</span>
git push
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>At this point, we have a fully functional and automatically updating Helm repository. To use it, get the raw URL for the <code>repo</code> branch. </p>
<p>In our case, we will add the repository as follows:</p>
<pre><code class="lang-bash">helm repo add example https://raw.githubusercontent.com/idane/helm-repo-example/repo
</code></pre>
]]></content:encoded></item></channel></rss>