<?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[Yonatan Karp-Rudin | kotlin for backend developer skills | java for backend developer skills | SpringBoot | Tutorials]]></title><description><![CDATA[A blog with tutorials around spring boot, kotlin  &amp; java languages, and code samples. The blog focuses on, but is not limited to, backend topics in the JVM world]]></description><link>https://yonatankarp.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 10 Apr 2026 15:41:39 GMT</lastBuildDate><atom:link href="https://yonatankarp.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Design Patterns - Prototype]]></title><description><![CDATA[TL;DR: The Prototype design pattern creates new objects by cloning a prototypical instance, allowing you to modify the copy without creating an object from scratch. This pattern is useful when object creation is expensive or when classes to instantia...]]></description><link>https://yonatankarp.com/design-patterns-prototype</link><guid isPermaLink="true">https://yonatankarp.com/design-patterns-prototype</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[clean code]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Mon, 20 Nov 2023 09:49:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/tZc3vjPCk-Q/upload/a1419155b315c0db6704d2eb6a94aed0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR:</strong> The Prototype design pattern creates new objects by cloning a prototypical instance, allowing you to modify the copy without creating an object from scratch. This pattern is useful when object creation is expensive or when classes to instantiate are specified at runtime.</p>
</blockquote>
<h2 id="heading-intent">Intent</h2>
<p>Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.</p>
<h2 id="heading-explanation">Explanation</h2>
<p>First, it should be noted that the Prototype pattern is not used to gain performance benefits. It's only used for creating new objects from prototype instances.</p>
<p>Real-world example</p>
<blockquote>
<p>Remember Dolly? The sheep that was cloned! Let's not get into the details but the key point here is that it is all about cloning.</p>
</blockquote>
<p>In plain words</p>
<blockquote>
<p>Create an object based on an existing object through cloning.</p>
</blockquote>
<p>Wikipedia says</p>
<blockquote>
<p>The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects.</p>
</blockquote>
<p>In short, it allows you to create a copy of an existing object and modify it to your needs, instead of going through the trouble of creating an object from scratch and setting it up.</p>
<p><strong>Programmatic Example</strong></p>
<p>In Kotlin, the prototype pattern is recommended to be implemented as follows. First, create an interface with a method for cloning objects. In this example, <code>Prototype</code> interface accomplishes this with its <code>clone</code> method. We will then use the <code>copy()</code> function of data class to create a clone of our class where we can override specific fields of the class if needed.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Prototype</span>&lt;<span class="hljs-type">T</span>&gt; </span>{
  <span class="hljs-keyword">abstract</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">clone</span><span class="hljs-params">()</span></span>: T
}
</code></pre>
<p>Our example contains a hierarchy of different creatures. For example, let's look at <code>Beast</code> and <code>OrcBeast</code> classes.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Beast</span> : <span class="hljs-type">Prototype</span>&lt;<span class="hljs-type">Beast</span>&gt;</span>()

<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrcBeast</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> weapon: String) : Beast() {

  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">clone</span><span class="hljs-params">()</span></span> = copy()

  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">toString</span><span class="hljs-params">()</span></span> = <span class="hljs-string">"Orcish wolf attacks with <span class="hljs-variable">$weapon</span>"</span>
}
</code></pre>
<p>We don't want to go into too many details, but the full example contains also base classes <code>Mage</code> and <code>Warlord</code> and there are specialized implementations for those for elves in addition to orcs.</p>
<p>To take full advantage of the prototype pattern, we create <code>HeroFactory</code> class to produce different kinds of creatures from prototypes.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HeroFactory</span></span>(
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> mage: Mage,
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> warlord: Warlord,
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> beast: Beast,
) {
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createMage</span><span class="hljs-params">()</span></span> = mage.clone()

  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createWarlord</span><span class="hljs-params">()</span></span> = warlord.clone()

  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createBeast</span><span class="hljs-params">()</span></span> = beast.clone()
}
</code></pre>
<p>Now, we are able to show the full prototype pattern in action producing new creatures by cloning existing instances.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">var</span> factory = HeroFactory(
  ElfMage(<span class="hljs-string">"cooking"</span>),
  ElfWarlord(<span class="hljs-string">"cleaning"</span>),
  ElfBeast(<span class="hljs-string">"protecting"</span>)
)

<span class="hljs-keyword">var</span> mage = factory.createMage()
<span class="hljs-keyword">var</span> warlord = factory.createWarlord()
<span class="hljs-keyword">var</span> beast = factory.createBeast()

logger.info(mage.toString())
logger.info(warlord.toString())
logger.info(beast.toString())

factory = HeroFactory(
  OrcMage(<span class="hljs-string">"axe"</span>),
  OrcWarlord(<span class="hljs-string">"sword"</span>),
  OrcBeast(<span class="hljs-string">"laser"</span>)
)

mage = factory.createMage()
warlord = factory.createWarlord()
beast = factory.createBeast()

logger.info(mage.toString())
logger.info(warlord.toString())
logger.info(beast.toString())
</code></pre>
<p>Here's the console output from running the example.</p>
<pre><code class="lang-kotlin">Elven mage helps <span class="hljs-keyword">in</span> cooking
Elven warlord helps <span class="hljs-keyword">in</span> cleaning
Elven eagle helps <span class="hljs-keyword">in</span> protecting
Orcish mage attacks with axe
Orcish warlord attacks with sword
Orcish wolf attacks with laser
</code></pre>
<h2 id="heading-class-diagram">Class diagram</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700473254933/1d7d62ab-cbb3-4d17-8efb-b52d017e44f0.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-applicability">Applicability</h2>
<p>Use the Prototype pattern when a system should be independent of how its products are created, composed, represented and</p>
<ul>
<li><p>When the classes to instantiate are specified at run-time, for example, by dynamic loading.</p>
</li>
<li><p>To avoid building a class hierarchy of factories that parallels the class hierarchy of products.</p>
</li>
<li><p>When instances of a class can have one of only a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually, each time with the appropriate state.</p>
</li>
<li><p>When object creation is expensive compared to cloning.</p>
</li>
</ul>
<div class="hn-embed-widget" id="contact-me"></div><p> </p>
<h2 id="heading-code-examples"><strong>Code Examples</strong></h2>
<p>All code examples and tests can be found in the <a target="_blank" href="https://github.com/yonatankarp/kotlin-design-patterns/tree/main/prototype"><strong>Kotlin Design Patterns repository</strong></a></p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><p><a target="_blank" href="https://github.com/iluwatar/java-design-patterns">Java Design Patterns</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0201633612&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=675d49790ce11db99d90bde47f1aeb59">Design Patterns: Elements of Reusable Object-Oriented Software</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0596007124&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=6b8b6eea86021af6c8e3cd3fc382cb5b">Head First Design Patterns: A Brain-Friendly Guide</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Design Patterns - Builder]]></title><description><![CDATA[TL;DR: Separate the construction of a complex object from its representation so that the same construction process can create different representations.

Intent
Separate the construction of a complex object from its representation so that the same co...]]></description><link>https://yonatankarp.com/design-patterns-builder</link><guid isPermaLink="true">https://yonatankarp.com/design-patterns-builder</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[clean code]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Fri, 03 Nov 2023 08:01:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/lAqSzwr5eQc/upload/2a1d9e5bb38a28acf273c36a60756c59.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR:</strong> Separate the construction of a complex object from its representation so that the same construction process can create different representations.</p>
</blockquote>
<h2 id="heading-intent">Intent</h2>
<p>Separate the construction of a complex object from its representation so that the same construction process can create different representations.</p>
<h2 id="heading-explanation">Explanation</h2>
<p>Real-world example</p>
<blockquote>
<p>Imagine a character generator for a role-playing game. The easiest option is to let the computer create the character for you. If you want to manually select the character details like profession, gender, hair color, etc. the character generation becomes a step-by-step process that completes when all the selections are ready.</p>
</blockquote>
<p>In plain words</p>
<blockquote>
<p>Allows you to create different flavors of an object while avoiding constructor pollution. Useful when there are several flavours of an object. Or when there are a lot of steps involved in the creation of an object.</p>
</blockquote>
<p>Wikipedia says</p>
<blockquote>
<p>The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor anti-pattern.</p>
</blockquote>
<p>Having said that let me add a bit about what telescoping constructor anti-pattern is. At one point or the other, we have all seen a constructor like below:</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">Hero</span></span>(
  <span class="hljs-keyword">val</span> profession: Profession,
  <span class="hljs-keyword">val</span> name: String,
  <span class="hljs-keyword">val</span> hairType: HairType?,
  <span class="hljs-keyword">val</span> hairColor: HairColor?,
  <span class="hljs-keyword">val</span> armor: Armor?,
  <span class="hljs-keyword">val</span> weapon: Weapon?
)
</code></pre>
<p>As you can see the number of constructor parameters can quickly get out of hand, and it may become difficult to understand the arrangement of parameters. Plus this parameter list could keep on growing if you would want to add more options in the future. This is called a telescoping constructor anti-pattern.</p>
<p><strong>Programmatic Example</strong></p>
<p>The sane alternative is to use the Builder pattern. First of all, we have our hero that we want to create:</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">Hero</span></span>(
  <span class="hljs-keyword">val</span> profession: Profession,
  <span class="hljs-keyword">val</span> name: String,
  <span class="hljs-keyword">val</span> hairType: HairType?,
  <span class="hljs-keyword">val</span> hairColor: HairColor?,
  <span class="hljs-keyword">val</span> armor: Armor?,
  <span class="hljs-keyword">val</span> weapon: Weapon?
) {
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">constructor</span>(builder: Builder) : <span class="hljs-keyword">this</span>(
    builder.profession,
    builder.name,
    builder.hairType,
    builder.hairColor,
    builder.armor,
    builder.weapon
  )
}
</code></pre>
<p>Then we have the builder:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Builder</span></span>(profession: Profession?, name: String?) {
  <span class="hljs-keyword">val</span> profession: Profession
  <span class="hljs-keyword">val</span> name: String
  <span class="hljs-keyword">var</span> hairType: HairType? = <span class="hljs-literal">null</span>
  <span class="hljs-keyword">var</span> hairColor: HairColor? = <span class="hljs-literal">null</span>
  <span class="hljs-keyword">var</span> armor: Armor? = <span class="hljs-literal">null</span>
  <span class="hljs-keyword">var</span> weapon: Weapon? = <span class="hljs-literal">null</span>

  <span class="hljs-keyword">init</span> {
    require(!(profession == <span class="hljs-literal">null</span> || name == <span class="hljs-literal">null</span>)) { <span class="hljs-string">"profession and name can not be null"</span> }
    <span class="hljs-keyword">this</span>.profession = profession
    <span class="hljs-keyword">this</span>.name = name
  }

  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">withHairType</span><span class="hljs-params">(hairType: <span class="hljs-type">HairType</span>?)</span></span>: Builder = apply {
    <span class="hljs-keyword">this</span>.hairType = hairType
  }

  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">withHairColor</span><span class="hljs-params">(hairColor: <span class="hljs-type">HairColor</span>?)</span></span>: Builder = apply {
    <span class="hljs-keyword">this</span>.hairColor = hairColor
  }

  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">withArmor</span><span class="hljs-params">(armor: <span class="hljs-type">Armor</span>?)</span></span>: Builder = apply {
    <span class="hljs-keyword">this</span>.armor = armor
  }

  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">withWeapon</span><span class="hljs-params">(weapon: <span class="hljs-type">Weapon</span>?)</span></span>: Builder = apply {
    <span class="hljs-keyword">this</span>.weapon = weapon
  }

  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">build</span><span class="hljs-params">()</span></span> = Hero(<span class="hljs-keyword">this</span>)
}
</code></pre>
<p>Then it can be used as:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mage = Hero.Builder(Profession.MAGE, <span class="hljs-string">"Riobard"</span>)
  .withHairColor(HairColor.BLACK)
  .withWeapon(Weapon.DAGGER)
  .build()
</code></pre>
<p>However, Kotlin provides an alternative to the Builder pattern with named arguments and default parameter values:</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">Hero</span></span>(
    <span class="hljs-keyword">val</span> profession: Profession,
    <span class="hljs-keyword">val</span> name: String,
    <span class="hljs-keyword">val</span> hairType: HairType? = <span class="hljs-literal">null</span>,
    <span class="hljs-keyword">val</span> hairColor: HairColor? = <span class="hljs-literal">null</span>,
    <span class="hljs-keyword">val</span> armor: Armor? = <span class="hljs-literal">null</span>,
    <span class="hljs-keyword">val</span> weapon: Weapon? = <span class="hljs-literal">null</span>
)
</code></pre>
<p>Then it can be used as:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> mage = Hero(
    profession = Profession.MAGE,
    name = <span class="hljs-string">"Riobard"</span>,
    hairColor = HairColor.BLACK,
    weapon = Weapon.DAGGER
)
</code></pre>
<p>Not only that the code simpler, but we are also enforcing the required parameters at compile time.</p>
<h2 id="heading-class-diagram">Class diagram</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698998254082/18ebd81d-fc31-403e-87a2-948361720a75.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-applicability">Applicability</h2>
<p>Use the Builder pattern when</p>
<ul>
<li><p>The algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled</p>
</li>
<li><p>The construction process must allow different representations for the object that's constructed</p>
</li>
</ul>
<h2 id="heading-tutorials">Tutorials</h2>
<ul>
<li><p><a target="_blank" href="https://refactoring.guru/design-patterns/builder">Refactoring Guru</a></p>
</li>
<li><p><a target="_blank" href="https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java">Oracle Blog</a></p>
</li>
<li><p><a target="_blank" href="https://www.journaldev.com/1425/builder-design-pattern-in-java">Journal Dev</a></p>
</li>
</ul>
<div class="hn-embed-widget" id="contact-me"></div><p> </p>
<h2 id="heading-code-examples"><strong>Code Examples</strong></h2>
<p>All code examples and tests can be found in the <a target="_blank" href="https://github.com/yonatankarp/kotlin-design-patterns/tree/main/builder"><strong>Kotlin Design Patterns repository</strong></a></p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><p><a target="_blank" href="https://github.com/iluwatar/java-design-patterns">Java Design Patterns</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0201633612&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=675d49790ce11db99d90bde47f1aeb59">Design Patterns: Elements of Reusable Object-Oriented Software</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0134685997&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=4e349f4b3ff8c50123f8147c828e53eb">Effective Java</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0596007124&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=6b8b6eea86021af6c8e3cd3fc382cb5b">Head First Design Patterns: A Brain-Friendly Guide</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0321213351&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=2a76fcb387234bc71b1c61150b3cc3a7">Refactoring to Patterns</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.de/Kotlin-Design-Patterns-Best-Practices/dp/1801815720/ref=sr_1_1?keywords=kotlin+design+patterns+and+best+practices&amp;qid=1694244553&amp;sprefix=kotlin+design%2Caps%2C101&amp;sr=8-1">Kotlin Design Patterns and Best Practices</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Design Patterns - Abstract Factory]]></title><description><![CDATA[TL;DR: Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. This pattern is useful when the system needs to be independent of how its products are created, com...]]></description><link>https://yonatankarp.com/design-patterns-abstract-factory</link><guid isPermaLink="true">https://yonatankarp.com/design-patterns-abstract-factory</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[clean code]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Thu, 26 Oct 2023 07:29:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/wQLAGv4_OYs/upload/dcd00d4c6babbb3fd051826ff1aaec00.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>TL;DR: Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. This pattern is useful when the system needs to be independent of how its products are created, composed, and represented, and when there are multiple families of products that need to be used together.</p>
</blockquote>
<h2 id="heading-also-known-as">Also known as</h2>
<ul>
<li>Kit</li>
</ul>
<h2 id="heading-intent">Intent</h2>
<p>Provide an interface for creating families of related or dependent objects without specifying their concrete classes.</p>
<h2 id="heading-explanation">Explanation</h2>
<p>Real-world example</p>
<blockquote>
<p>To create a kingdom we need objects with a common theme. The elven kingdom needs an elven king, elven castle, and elven army whereas the orcish kingdom needs an orcish king, orcish castle, and orcish army. There is a dependency between the objects in the kingdom.</p>
</blockquote>
<p>In plain words</p>
<blockquote>
<p>A factory of factories; is a factory that groups the individual but related/dependent factories together without specifying their concrete classes.</p>
</blockquote>
<p>Wikipedia says</p>
<blockquote>
<p>The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes</p>
</blockquote>
<p><strong>Programmatic Example</strong></p>
<p>Translating the kingdom example above. First of all, we have some interfaces and implementations for the objects in the kingdom.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Castle</span> </span>{
  <span class="hljs-keyword">val</span> description: String
}

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">King</span> </span>{
  <span class="hljs-keyword">val</span> description: String
}

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Army</span> </span>{
  <span class="hljs-keyword">val</span> description: String
}

<span class="hljs-comment">// Elven implementations -&gt;</span>

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ElfCastle</span> : <span class="hljs-type">Castle {</span></span>
  <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> description = <span class="hljs-string">"This is the elven castle!"</span>
}

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ElfKing</span> : <span class="hljs-type">King {</span></span>
  <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> description = <span class="hljs-string">"This is the elven king!"</span>
}

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ElfArmy</span> : <span class="hljs-type">Army {</span></span>
  <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> description = <span class="hljs-string">"This is the elven army!"</span>
}

<span class="hljs-comment">// Orcish implementations similarly -&gt; ...</span>
</code></pre>
<p>Then we have the abstraction and implementations for the kingdom factory.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">KingdomFactory</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createCastle</span><span class="hljs-params">()</span></span>: Castle
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createKing</span><span class="hljs-params">()</span></span>: King
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createArmy</span><span class="hljs-params">()</span></span>: Army
}

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ElfKingdomFactory</span> : <span class="hljs-type">KingdomFactory {</span></span>
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createCastle</span><span class="hljs-params">()</span></span> = ElfCastle()
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createKing</span><span class="hljs-params">()</span></span> = ElfKing()
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createArmy</span><span class="hljs-params">()</span></span> = ElfArmy()
}

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrcKingdomFactory</span> : <span class="hljs-type">KingdomFactory {</span></span>
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createCastle</span><span class="hljs-params">()</span></span> = OrcCastle()
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createKing</span><span class="hljs-params">()</span></span> = OrcKing()
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createArmy</span><span class="hljs-params">()</span></span> = OrcArmy()
}
</code></pre>
<p>Now we have the abstract factory that lets us make a family of related objects i.e. elven kingdom factory creates an elven castle, king and army, etc.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> factory = ElfKingdomFactory()
<span class="hljs-keyword">val</span> castle = factory.createCastle()
<span class="hljs-keyword">val</span> king = factory.createKing()
<span class="hljs-keyword">val</span> army = factory.createArmy()

castle.description
king.description
army.description
</code></pre>
<p>Program output:</p>
<pre><code class="lang-shell">This is the elven castle!
This is the elven king!
This is the elven Army!
</code></pre>
<p>Now, we can design a factory for our different kingdom factories. In this example, we created <code>FactoryMaker</code>, responsible for returning an instance of either <code>ElfKingdomFactory</code> or <code>OrcKingdomFactory</code>.<br />The client can use <code>FactoryMaker</code> to create the desired concrete factory which, in turn, will produce different concrete objects (derived from <code>Army</code>, <code>King</code>, <code>Castle</code>).<br />In this example, we also used an enum to parameterize which type of kingdom factory the client will ask for.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Kingdom</span></span>(
  <span class="hljs-keyword">val</span> king: King,
  <span class="hljs-keyword">val</span> castle: Castle,
  <span class="hljs-keyword">val</span> army: Army,
) {
  <span class="hljs-keyword">object</span> FactoryMaker {
    <span class="hljs-keyword">enum</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">KingdomType</span> </span>{
      ELF,
      ORC
    }

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">makeFactory</span><span class="hljs-params">(type: <span class="hljs-type">KingdomType</span>)</span></span>: KingdomFactory {
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">when</span> (type) {
        KingdomType.ELF -&gt; ElfKingdomFactory()
        KingdomType.ORC -&gt; OrcKingdomFactory()
      }
    }
  }
}
</code></pre>
<p>Now we can use the abstract factory to create the kingdoms</p>
<pre><code class="lang-kotlin">logger.info(<span class="hljs-string">"elf kingdom"</span>)
<span class="hljs-keyword">val</span> elfKingdom = createKingdom(KingdomType.ELF)
logger.info(elfKingdom.army.description)
logger.info(elfKingdom.castle.description)
logger.info(elfKingdom.king.description)

logger.info(<span class="hljs-string">"orc kingdom"</span>)
<span class="hljs-keyword">val</span> orcKingdom = createKingdom(KingdomType.ORC)
logger.info(orcKingdom.army.description)
logger.info(orcKingdom.castle.description)
logger.info(orcKingdom.king.description)
</code></pre>
<p>Program output:</p>
<pre><code class="lang-shell">elf kingdom
This is the elven castle!
This is the elven king!
This is the elven Army!
orc kingdom
This is the orc castle!
This is the orc king!
This is the orc Army!
</code></pre>
<h2 id="heading-class-diagram">Class diagram</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698305107773/18697199-20cf-49fc-af8c-4530569e902f.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-applicability">Applicability</h2>
<p>Use the Abstract Factory pattern when</p>
<ul>
<li><p>The system should be independent of how its products are created, composed, and represented</p>
</li>
<li><p>The system should be configured with one of the multiple families of products</p>
</li>
<li><p>The family of related product objects is designed to be used together, and you need to enforce this constraint</p>
</li>
<li><p>You want to provide a class library of products, and you want to reveal just their interfaces, not their implementations</p>
</li>
<li><p>The lifetime of the dependency is conceptually shorter than the lifetime of the consumer.</p>
</li>
<li><p>You need a run-time value to construct a particular dependency</p>
</li>
<li><p>You want to decide which product to call from a family at runtime.</p>
</li>
<li><p>You need to supply one or more parameters only known at run-time before you can resolve a dependency.</p>
</li>
<li><p>When you need consistency among products</p>
</li>
<li><p>You don’t want to change existing code when adding new products or families of products to the program.</p>
</li>
</ul>
<p>Example use cases</p>
<ul>
<li><p>Selecting to call to the appropriate implementation of FileSystemAcmeService or DatabaseAcmeService or NetworkAcmeService at runtime.</p>
</li>
<li><p>Unit test case writing becomes much easier</p>
</li>
<li><p>UI tools for different OS</p>
</li>
</ul>
<h2 id="heading-consequences">Consequences</h2>
<ul>
<li><p>Dependency injection in Java hides the service class dependencies that can lead to runtime errors that would have been caught at compile time.</p>
</li>
<li><p>While the pattern is great when creating predefined objects, adding new ones might be challenging.</p>
</li>
<li><p>The code becomes more complicated than it should be since many new interfaces and classes are introduced along with the pattern.</p>
</li>
</ul>
<h2 id="heading-tutorials">Tutorials</h2>
<ul>
<li><a target="_blank" href="https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java">Abstract Factory Pattern Tutorial</a></li>
</ul>
<div class="hn-embed-widget" id="contact-me"></div><p> </p>
<h2 id="heading-code-examples"><strong>Code Examples</strong></h2>
<p>All code examples and tests can be found in the <a target="_blank" href="https://github.com/yonatankarp/kotlin-design-patterns/tree/main/abstract-factory"><strong>Kotlin Design Patterns repository</strong></a></p>
<h2 id="heading-related-patterns">Related patterns</h2>
<ul>
<li><p><a target="_blank" href="../factory-method/README.md">Factory Method</a></p>
</li>
<li><p>Factory Kit</p>
</li>
</ul>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><p><a target="_blank" href="https://github.com/iluwatar/java-design-patterns">Java Design Patterns</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0201633612&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=675d49790ce11db99d90bde47f1aeb59">Design Patterns: Elements of Reusable Object-Oriented Software</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0596007124&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=6b8b6eea86021af6c8e3cd3fc382cb5b">Head First Design Patterns: A Brain-Friendly Guide</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Design Patterns - Factory]]></title><description><![CDATA[TL;DR: Factory pattern provides a static method encapsulated in a class to hide implementation logic, allowing client code to focus on usage rather than object initialization. It simplifies object creation, promotes loose coupling, and supports easy ...]]></description><link>https://yonatankarp.com/design-patterns-factory</link><guid isPermaLink="true">https://yonatankarp.com/design-patterns-factory</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[clean code]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Tue, 24 Oct 2023 15:53:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ppN1zRQrCEg/upload/8ca67e12452532fc6cfa8a8fb34087c1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR:</strong> Factory pattern provides a static method encapsulated in a class to hide implementation logic, allowing client code to focus on usage rather than object initialization. It simplifies object creation, promotes loose coupling, and supports easy switching between object types without modifying existing code.</p>
</blockquote>
<h2 id="heading-also-known-as">Also known as</h2>
<ul>
<li><p>Factory</p>
</li>
<li><p>Simple Factory</p>
</li>
</ul>
<h2 id="heading-intent">Intent</h2>
<p>Providing a static method encapsulated in a class called the factory, to hide the implementation logic and make client code focus on usage rather than initializing new objects.</p>
<h2 id="heading-explanation">Explanation</h2>
<p>Real-world example</p>
<blockquote>
<p>Imagine an alchemist who is about to manufacture coins. The alchemist must be able to create both gold and copper coins and switching between them must be possible without modifying the existing source code. The factory pattern makes it possible by providing a static construction method which can be called with relevant parameters.</p>
</blockquote>
<p>Wikipedia says</p>
<blockquote>
<p>A factory is an object for creating other objects – formally a factory is a function or method that returns objects of a varying prototype or class.</p>
</blockquote>
<p><strong>Programmatic Example</strong></p>
<p>We have an interface <code>Coin</code> and two implementations <code>GoldCoin</code> and <code>CopperCoin</code>.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Coin</span> </span>{
    <span class="hljs-keyword">val</span> description: String
}

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GoldCoin</span> : <span class="hljs-type">Coin {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> description = <span class="hljs-string">"This is a gold coin."</span>
}

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CopperCoin</span> : <span class="hljs-type">Coin {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">val</span> description = <span class="hljs-string">"This is a copper coin."</span>
}
</code></pre>
<p>The enumeration above represents the types of coins that we support (<code>GoldCoin</code> and <code>CopperCoin</code>).</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">enum</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CoinType</span></span>(<span class="hljs-keyword">val</span> <span class="hljs-keyword">constructor</span>: () -&gt; Coin) {
    COPPER({ CopperCoin() }),
    GOLD({ GoldCoin() }),
}
</code></pre>
<p>Then we have the static method <code>getCoin</code> to create coin objects encapsulated in the factory class <code>CoinFactory</code>.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">object</span> CoinFactory {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getCoin</span><span class="hljs-params">(type: <span class="hljs-type">CoinType</span>)</span></span>: Coin = type.<span class="hljs-keyword">constructor</span>()
}
</code></pre>
<p>Now on the client code, we can create different types of coins using the factory class.</p>
<pre><code class="lang-kotlin">logger.info(<span class="hljs-string">"The alchemist begins his work."</span>)
<span class="hljs-keyword">val</span> copper = CoinFactory.getCoin(CoinType.COPPER)
<span class="hljs-keyword">val</span> gold = CoinFactory.getCoin(CoinType.GOLD)
logger.info(copper.description)
logger.info(gold.description)
</code></pre>
<p>Program output:</p>
<pre><code class="lang-shell">The alchemist begins his work.
This is a copper coin.
This is a gold coin.
</code></pre>
<h2 id="heading-class-diagram">Class Diagram</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698162320093/2cf7b127-a3c0-4118-9753-906cd62b8061.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-applicability">Applicability</h2>
<p>Use the factory pattern when you only care about the creation of an object, not how to create and manage it.</p>
<p>Pros</p>
<ul>
<li><p>Allows keeping all objects created in one place.</p>
</li>
<li><p>Allows to write loosely coupled code. Some of its main advantages include better testability, easy-to-understand code, swappable components, scalability, and isolated features.</p>
</li>
</ul>
<p>Cons</p>
<ul>
<li>The code becomes more complicated than it should be.</li>
</ul>
<div class="hn-embed-widget" id="contact-me"></div><p> </p>
<h2 id="heading-code-examples"><strong>Code Examples</strong></h2>
<p>All code examples and tests can be found in the <a target="_blank" href="https://github.com/yonatankarp/kotlin-design-patterns/tree/main/factory"><strong>Kotlin Design Patterns repository</strong></a></p>
<h2 id="heading-related-patterns">Related patterns</h2>
<ul>
<li><p><a target="_blank" href="../factory-method/README.md">Factory Method</a></p>
</li>
<li><p><a target="_blank" href="../abstract-factory/README.md">Abstract Factory</a></p>
</li>
<li><p>Factory Kit</p>
</li>
</ul>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://github.com/iluwatar/java-design-patterns">Java Design Patterns</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Our Errors, Your Gain: A System Design Cautionary Tale]]></title><description><![CDATA[TL;DR: This article shares my experience with a temporary solution that turned into a long-term issue. I discuss the evolution of a service and how it improved its performance by over 450% in a few hours. The story highlights the importance of addres...]]></description><link>https://yonatankarp.com/our-errors-your-gain-a-system-design-cautionary-tale</link><guid isPermaLink="true">https://yonatankarp.com/our-errors-your-gain-a-system-design-cautionary-tale</guid><category><![CDATA[System Design]]></category><category><![CDATA[System Architecture]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Case Study]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Mon, 23 Oct 2023 06:28:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/21DP3hytVHw/upload/5542ee49a269773069cecd00d94f67da.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR:</strong> This article shares my experience with a temporary solution that turned into a long-term issue. I discuss the evolution of a service and how it improved its performance by over 450% in a few hours. The story highlights the importance of addressing temporary solutions and constantly evaluating system design to optimize performance.</p>
</blockquote>
<h2 id="heading-introduction">Introduction</h2>
<p>About four years ago, around the time I joined my previous employer, my manager at the time introduced me to one of the services my team owned. He opened the explanation with the sentence, "As the saying goes, nothing is more permanent than a temporary solution". More than five years have passed since this service was initially introduced, and it's still running in production.</p>
<p>In this article, I share a specific use case of the service and how we improved its performance by over 450% in just a few hours.</p>
<h2 id="heading-the-original-system-design">The Original System Design</h2>
<p>Let's start by briefly looking at the system's original design. The system included a database that serves as the source of the data, a poller service that checks for changes in the source database every five seconds, and in case a change is found, it aggregates the data and stores it in a different database. Lastly, a Reader service is responsible for reading the aggregated data from the database and serving it to our clients.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697120445320/7890ecff-2488-46af-97b3-f9dc1fc4ff7b.jpeg" alt class="image--center mx-auto" /></p>
<p>As you might already imagine, integration via a database is almost always a bad idea. It can lead to data inconsistency, lack of real-time updates, difficulty in making changes in the database schema, and more. But as we just said, temporary solution - right? Our system specifically suffered mainly from data inconsistency. The main root cause for the issues was been that the entities in the database might not yet be finalized by the time they were polled. In such a case, the poller would ignore the data and would never return to fix it later.</p>
<p><img src="https://media2.giphy.com/media/XvQXEi09zfmcE/giphy.gif?cid=ecf05e47iv1j50rr89r8aftkerydv41umrzwwh3jekd2lsaa&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" alt="Kill It With Fire GIF" class="image--center mx-auto" /></p>
<h2 id="heading-addressing-data-inconsistency">Addressing Data Inconsistency</h2>
<p>Eventually, the data-owning team began publishing events indicating that the data was finalized and ready for use. We amended our poller service, so it would start to listen to those events and store the IDs of the entities that are ready to be picked in a table that it would later poll. This ensures no data is missed. With the new change, our system now looks as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697120458791/1a39e48f-2f9f-4ab3-bd2c-5baf50c870b2.jpeg" alt class="image--center mx-auto" /></p>
<p>You might ask: "<strong><em>Why didn't you change the implementation to rely completely on the events?</em></strong>". Well... First, the events lacked the required information. The only reason the data exists in the database, to begin with, is because of domain mixing. The mix in domains has been so deep that multiple teams worked very hard for a very long time to split those domains.</p>
<h2 id="heading-the-human-error">The Human Error</h2>
<p>At this point, it's worth stopping and discussing the human aspect behind the existence of this solution. The poller service was introduced as a technical solution for a technical problem. We needed access to data that we didn't have, and with the help of this service, we had that access (even if it caused a violation of multiple domain boundaries).</p>
<p>However, as we made the poller stable it fell lower and lower in the priority list of the company to replace this design with a proper solution. Not only that, but the maintenance of the service moved between teams in the company like a hot potato. In my time in the company, I actually had the pleasure of working on this system in 3 different contexts and teams.</p>
<p>The lack of real ownership of the system, higher company priorities, and management's general agreement that the solution wasn't great but worked, led to the repeated de-prioritization of refactoring this part of the system.</p>
<h2 id="heading-introducing-new-features-and-challenges">Introducing New Features and Challenges</h2>
<p>The system functioned and was left unchanged for some time. Until one day, we had to introduce another new feature. The feature required to generate information for our clients about the previous day. The data should be available every day at 5 a.m. (client's local time).</p>
<p>To solve this problem, we first introduced a new service responsible for managing day opening/closing. Next, the poller service made a REST call to the new service for each entity in the database and assigned the ID of the current day. Lastly, the Read service aggregated the data from the database and used it to generate the required information.</p>
<p>Our system now looked like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697120469964/8a31b4da-5c88-467d-8ad9-7f5c469c29ba.jpeg" alt class="image--center mx-auto" /></p>
<p>As you can imagine, using REST calls between the poller and the new service created a strong coupling. Every time we had to maintain the database of the day management service, our poller service received an internal error response from the REST call and did not assign an ID to the entity. We could resolve this situation by using asynchronous communication between the services. In such a case, the Day management service would notify all consumers whenever a new day is opened/closed and let them do as they wish with the information. Such a solution would allow scalability of the system, resiliency, and avoid coupling between the services (or as my favorite phrase says, building a distributed monolith).</p>
<p>Yet another issue, when the clients activated the feature, we did not assign the ID of the day to already existing entities. The impact of that was that the data from the first day was incomplete at best, or completely wrong at worst. This caused many calls to our support agents and wasted quite a significant amount of the team's time debugging the issue.</p>
<p><img src="https://i.imgflip.com/81wb1k.jpg" alt class="image--center mx-auto" /></p>
<h2 id="heading-performance-issues-and-materialized-views">Performance Issues and Materialized Views</h2>
<p>We rolled out the feature to 1000 clients. After about two weeks, we discovered that we had severe performance issues with our new feature. The issue was related to the SQL query we used to build the required information, which included multiple JOINs.</p>
<p>Since the data doesn't have to be updated during the day but only in the morning, we decided to come up with a new approach. We introduced a materialized view that was holding all the required information for the feature pre-calculated and refreshed the view every morning.</p>
<p>If you're unfamiliar with the <a target="_blank" href="https://www.postgresql.org/docs/current/rules-materializedviews.html">materialized view</a> in SQL, it is a database object that contains the results of a query, stored in a table-like structure. It is used to cache the results of complex queries for faster access and improved performance. Materialized views are periodically updated by refreshing the stored data, either manually or automatically, to keep the view in sync with the underlying data.</p>
<p>That means that from that point on, our poller started to refresh the materialized view every day. That was supposed to be a temporary solution until we find a more suitable database for our needs (where did I hear this before?)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697120482000/ec222028-cf2f-4fa6-aab5-6b16397c8174.jpeg" alt class="image--center mx-auto" /></p>
<p>At this point, I would like to stop and point out a few flaws in the above design with the requirements we had:</p>
<ul>
<li><p>Since we rolled out in multiple time zones, and we had only one view, we could not serve the information for our client at 5 a.m. anymore; the refresh had to happen when the client with the latest timezone hit this time.</p>
</li>
<li><p>Materialized view does not support partial refresh, which means that every day we had to refresh all the data that was included in the feature, for all of our clients.</p>
</li>
</ul>
<p><img src="https://media3.giphy.com/media/QMHoU66sBXqqLqYvGO/giphy.gif?cid=ecf05e47h33684kr9hfkivnh4hm93eu3y9768fgmeg9tl7hu&amp;ep=v1_gifs_search&amp;rid=giphy.gif&amp;ct=g" alt="This Is Fine GIF" class="image--center mx-auto" /></p>
<p>The solution kind of worked for a while. However, as the number of clients using the feature grew, and the amount of data we collected for each of them also grew, the refresh of the materialized view started to become heavy. It became so heavy that at some point it took almost 5 hours to refresh the view.</p>
<p>Not only did our API not match its target, but it also consumed a lot of resources from our database, which caused a lot of headaches for our database admins.</p>
<h2 id="heading-the-efficient-solution-and-its-benefits">The Efficient Solution and its Benefits</h2>
<p>Some time passed by, and a colleague of mine reached out to me and told me, "<em>I think that I know how to fix the issue!</em>". Instead of refreshing all the data every day, let's create a new table that would hold the pre-calculated data, we will run a job that would be executed periodically, and calculate only the delta since the previous calculation. The idea was genius by its simplicity!</p>
<p>We decided to make a POC for the above suggestion and check if it can be implemented. In six hours, we deployed a working POC in our staging environment, tested it, and with an additional day of work we went all the way to production.</p>
<p><img src="https://i.imgflip.com/81id0p.jpg" alt="Success Meme" class="image--center mx-auto" /></p>
<p>After some testing, we set our refresh period to 1 minute and noticed that the query takes now around 1.4 seconds to be executed. With that, our saga came to an end.</p>
<p>As you can see in the graph below, our CPU usage for the database dropped dramatically after the changes!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696538938506/523fb6fa-46d8-49d5-9cf1-c24b99c8a7d6.jpeg" alt class="image--center mx-auto" /></p>
<p>With those changes, we regained:</p>
<ul>
<li><p>Minimal resource consumption by the database.</p>
</li>
<li><p>Near-real-time information availability for clients instead of a 5-hour delay</p>
</li>
<li><p>Simpler, easier-to-understand codebase.</p>
</li>
</ul>
<h2 id="heading-to-be-continue">To Be Continue?</h2>
<p>While the story of the poller does not end here, my story in the company does. After almost 4.5 years I contacted my first manager in the company and told him that I had failed to sunset the poller. However, there is good news on the horizon. A new dedicated team starting to work now on re-writing the entire system from the ground, basing it on the right data sources, and hopefully soon enough the poller story will come to an end! 🤞</p>
<div class="hn-embed-widget" id="contact-me"></div><p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This cautionary tale demonstrates the importance of addressing temporary solutions and constantly evaluating system design to optimize performance. By implementing a more efficient approach to handling growing data and client needs, the team significantly improved their system's performance, resource consumption, and overall simplicity.</p>
<p>Remember, temporary solutions are never temporary!</p>
<p>Every tech debt decision you make will come back and hunt you if you are not going to come back and fix it later.</p>
]]></content:encoded></item><item><title><![CDATA[Observability in Action Part 3: Enhancing Your Codebase with OpenTelemetry]]></title><description><![CDATA[This blog post was moved to [This blog post was moved to This blog post was moved to https://kotlinbackend.com/observability-in-action-how-to-use-opentelemetry/.]]></description><link>https://yonatankarp.com/observability-in-action-part-3-enhancing-your-codebase-with-opentelemetry</link><guid isPermaLink="true">https://yonatankarp.com/observability-in-action-part-3-enhancing-your-codebase-with-opentelemetry</guid><category><![CDATA[Devops]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[observability]]></category><category><![CDATA[OpenTelemetry]]></category><category><![CDATA[Springboot]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Tue, 17 Oct 2023 07:43:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/z9z6u1rn7sY/upload/64059cfb860d42a549748c2756ca7a5a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post was moved to [This blog post was moved to This blog post was moved to https://kotlinbackend.com/observability-in-action-how-to-use-opentelemetry/.</p>
]]></content:encoded></item><item><title><![CDATA[Observability in Action Part 2: Enhancing Your Codebase with OpenTelemetry]]></title><description><![CDATA[This blog post was moved to [This blog post was moved to This blog post was moved to https://kotlinbackend.com/observability-in-action-how-to-use-opentelemetry/.]]></description><link>https://yonatankarp.com/observability-in-action-part-2-enhancing-your-codebase-with-opentelemetry</link><guid isPermaLink="true">https://yonatankarp.com/observability-in-action-part-2-enhancing-your-codebase-with-opentelemetry</guid><category><![CDATA[Devops]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[observability]]></category><category><![CDATA[OpenTelemetry]]></category><category><![CDATA[Springboot]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Thu, 05 Oct 2023 12:23:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/1MwB2BXuUMI/upload/b17c33f58c51320d329cb4820eaabf80.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post was moved to [This blog post was moved to This blog post was moved to https://kotlinbackend.com/observability-in-action-how-to-use-opentelemetry/.</p>
]]></content:encoded></item><item><title><![CDATA[Observability in Action Part 1: Enhancing Your Codebase with OpenTelemetry]]></title><description><![CDATA[This blog post was moved to [This blog post was moved to This blog post was moved to https://kotlinbackend.com/observability-in-action-how-to-use-opentelemetry/.]]></description><link>https://yonatankarp.com/observability-in-action-part-1-enhancing-your-codebase-with-opentelemetry</link><guid isPermaLink="true">https://yonatankarp.com/observability-in-action-part-1-enhancing-your-codebase-with-opentelemetry</guid><category><![CDATA[Devops]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[observability]]></category><category><![CDATA[OpenTelemetry]]></category><category><![CDATA[Springboot]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Thu, 05 Oct 2023 10:25:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/oQbTpK4rXr0/upload/f7dc126791503f3947688e6810e40231.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post was moved to [This blog post was moved to This blog post was moved to https://kotlinbackend.com/observability-in-action-how-to-use-opentelemetry/.</p>
]]></content:encoded></item><item><title><![CDATA[Design Patterns - Factory Method]]></title><description><![CDATA[TL;DR: Factory Method is a design pattern that defines an interface for creating objects, allowing subclasses to decide which class to instantiate, thus delegating instantiation logic to child classes.

Also known as

Virtual Constructor

Intent
Defi...]]></description><link>https://yonatankarp.com/design-patterns-factory-method</link><guid isPermaLink="true">https://yonatankarp.com/design-patterns-factory-method</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[clean code]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Fri, 29 Sep 2023 08:30:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/6xeDIZgoPaw/upload/dd9e740579a0e08639315c1d99817bcf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR</strong>: Factory Method is a design pattern that defines an interface for creating objects, allowing subclasses to decide which class to instantiate, thus delegating instantiation logic to child classes.</p>
</blockquote>
<h2 id="heading-also-known-as">Also known as</h2>
<ul>
<li>Virtual Constructor</li>
</ul>
<h2 id="heading-intent">Intent</h2>
<p>Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.</p>
<h2 id="heading-explanation">Explanation</h2>
<p>Real-world example</p>
<blockquote>
<p>Blacksmith manufactures weapons. Elves require Elvish weapons and orcs require Orcish weapons. Depending on the customer at hand the right type of blacksmith is summoned.</p>
</blockquote>
<p>In plain words</p>
<blockquote>
<p>It provides a way to delegate the instantiation logic to child classes.</p>
</blockquote>
<p>Wikipedia says</p>
<blockquote>
<p>In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method — either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.</p>
</blockquote>
<p><strong>Programmatic Example</strong></p>
<p>Take our blacksmith example above. First of all, we have a <code>Blacksmith</code> interface and some implementations for it:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Blacksmith</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">manufactureWeapon</span><span class="hljs-params">(weaponType: <span class="hljs-type">WeaponType</span>)</span></span>: Weapon
}

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ElfBlacksmith</span> : <span class="hljs-type">Blacksmith {</span></span>
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">manufactureWeapon</span><span class="hljs-params">(weaponType: <span class="hljs-type">WeaponType</span>)</span></span>: Weapon =
    ELF_ARSENAL.getOrElse(weaponType) {
      <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"Weapon type <span class="hljs-variable">$weaponType</span> is not supported by elf blacksmith."</span>)
    }
}

<span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrcBlacksmith</span> : <span class="hljs-type">Blacksmith {</span></span>
  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">manufactureWeapon</span><span class="hljs-params">(weaponType: <span class="hljs-type">WeaponType</span>)</span></span>: Weapon =
    ORC_ARSENAL.getOrElse(weaponType) {
      <span class="hljs-keyword">throw</span> IllegalArgumentException(<span class="hljs-string">"Weapon type <span class="hljs-variable">$weaponType</span> is not supported by the orc blacksmith."</span>)
    }
}
</code></pre>
<p>When the customers come, the correct type of blacksmith is summoned and the requested weapons are manufactured:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">// Orc</span>
<span class="hljs-keyword">var</span> blacksmith: Blacksmith = OrcBlacksmith()

<span class="hljs-keyword">var</span> weapon: Weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR)
logger.info(<span class="hljs-string">"<span class="hljs-variable">$blacksmith</span> manufactured <span class="hljs-subst">${weapon.weaponType.title}</span>"</span>)

weapon = blacksmith.manufactureWeapon(WeaponType.AXE)
logger.info(<span class="hljs-string">"<span class="hljs-variable">$blacksmith</span> manufactured <span class="hljs-subst">${weapon.weaponType.title}</span>"</span>)

<span class="hljs-comment">// Elf</span>
blacksmith = ElfBlacksmith()

weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR)
logger.info(<span class="hljs-string">"<span class="hljs-variable">$blacksmith</span> manufactured <span class="hljs-subst">${weapon.weaponType.title}</span>"</span>)

weapon = blacksmith.manufactureWeapon(WeaponType.AXE)
logger.info(<span class="hljs-string">"<span class="hljs-variable">$blacksmith</span> manufactured <span class="hljs-subst">${weapon.weaponType.title}</span>"</span>)
</code></pre>
<p>Program output:</p>
<pre><code class="lang-plaintext">The orc blacksmith manufactured spear
The orc blacksmith manufactured axe
The elf blacksmith manufactured spear
The elf blacksmith manufactured axe
</code></pre>
<h2 id="heading-class-diagram">Class diagram</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695931268294/bb81f1d5-ec79-4150-8182-93c9d83ca6e9.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-applicability">Applicability</h2>
<p>Use the Factory Method pattern when:</p>
<ul>
<li><p>The class cannot anticipate the class of objects it must create.</p>
</li>
<li><p>The class wants its subclasses to specify the objects it creates.</p>
</li>
<li><p>Classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate.</p>
</li>
</ul>
<div class="hn-embed-widget" id="contact-me"></div><p> </p>
<h2 id="heading-code-examples"><strong>Code Examples</strong></h2>
<p>All code examples and tests can be found in the <a target="_blank" href="https://github.com/yonatankarp/kotlin-design-patterns/tree/main/factory-method"><strong>Kotlin Design Patterns repository</strong></a></p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><p><a target="_blank" href="https://github.com/iluwatar/java-design-patterns">Java Design Patterns</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0201633612&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=675d49790ce11db99d90bde47f1aeb59">Design Patterns: Elements of Reusable Object-Oriented Software</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0596007124&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=6b8b6eea86021af6c8e3cd3fc382cb5b">Head First Design Patterns: A Brain-Friendly Guide</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0321213351&amp;linkCode=as2&amp;tag=javadesignpat-20&amp;linkId=2a76fcb387234bc71b1c61150b3cc3a7">Refactoring to Patterns</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Design Patterns - Singleton]]></title><description><![CDATA[TL;DR: Ensure a class has only one instance and provide a global access point to it with the Singleton pattern, which is useful for coordinating actions across a system.

Intent
Ensure a class only has one instance, and provide a global point of acce...]]></description><link>https://yonatankarp.com/design-patterns-singleton</link><guid isPermaLink="true">https://yonatankarp.com/design-patterns-singleton</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Tue, 26 Sep 2023 07:58:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/4H6FXd0ld38/upload/9afbdb9132a842484ae39858cf23f73f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>TL;DR: Ensure a class has only one instance and provide a global access point to it with the Singleton pattern, which is useful for coordinating actions across a system.</p>
</blockquote>
<h2 id="heading-intent">Intent</h2>
<p>Ensure a class only has one instance, and provide a global point of access to it.</p>
<h2 id="heading-explanation">Explanation</h2>
<p>Real-world example</p>
<blockquote>
<p>There can only be one ivory tower where the wizards study their magic. The same enchanted ivory tower is always used by the wizards. The ivory tower here is a singleton.</p>
</blockquote>
<p>In plain words</p>
<blockquote>
<p>Ensures that only one object of a particular class is ever created.</p>
</blockquote>
<p>Wikipedia says</p>
<blockquote>
<p>In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.</p>
</blockquote>
<p><strong>Programmatic Example</strong></p>
<p>Kotlin makes it externally easy to create singletons by introducing the language keyword <code>object</code>. By using this keyword, we will get an implementation of the Singleton pattern from the compiler that contains all of our requirements.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">data</span> <span class="hljs-keyword">object</span> IvoryTower
</code></pre>
<p>One of the key differences between a <code>class</code> and a <code>object</code> is that the latter does not allow constructor arguments. If your implementation needs initialization for your Singleton (e.g. to load data) you can use an <code>init</code> block.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">data</span> <span class="hljs-keyword">object</span> IvoryTower {
  <span class="hljs-keyword">init</span> {
    logger.info(<span class="hljs-string">"Initializing Ivory Tower..."</span>)
  }
}
</code></pre>
<p>Note that if the Singleton object is never invoked, it won't run its initialization block at all. This is called lazy initialization.</p>
<p>Then in order to use:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> ivoryTower1 = IvoryTower
<span class="hljs-keyword">val</span> ivoryTower2 = IvoryTower
logger.info(<span class="hljs-string">"ivoryTower1={}"</span>, ivoryTower1)
logger.info(<span class="hljs-string">"ivoryTower2={}"</span>, ivoryTower2)
</code></pre>
<p>The output on the console:</p>
<pre><code class="lang-console">09:21:31.107 [main] INFO Singlton -- Initializing Ivory Tower...
09:21:31.109 [main] INFO Singlton -- ivoryTower1=com.yonatankarp.singleton.IvoryTower@1207938418
09:21:31.111 [main] INFO Singlton -- ivoryTower2=com.yonatankarp.singleton.IvoryTower@1207938418
</code></pre>
<h2 id="heading-class-diagram">Class diagram</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695714225028/86b98902-dfe6-4d48-bdb8-8641a868ea18.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-applicability">Applicability</h2>
<p>Use the Singleton pattern when</p>
<ul>
<li><p>There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point</p>
</li>
<li><p>When the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code</p>
</li>
</ul>
<p>Some typical use cases for the Singleton</p>
<ul>
<li><p>The logging class</p>
</li>
<li><p>Managing a connection to a database</p>
</li>
<li><p>File manager</p>
</li>
</ul>
<h2 id="heading-consequences">Consequences</h2>
<ul>
<li><p>Violates the <em>Single Responsibility Principle</em> (SRP) by controlling their creation and lifecycle.</p>
</li>
<li><p>Encourages using a globally shared instance which prevents an object and resources used by this object from being deallocated.</p>
</li>
<li><p>Creates tightly coupled code. The clients of the Singleton become difficult to test.</p>
</li>
<li><p>It makes it almost impossible to subclass a Singleton.</p>
</li>
</ul>
<div class="hn-embed-widget" id="contact-me"></div><p> </p>
<h2 id="heading-code-examples">Code Examples</h2>
<p>All code examples and tests can be found in the <a target="_blank" href="https://github.com/yonatankarp/kotlin-design-patterns/tree/main/singleton">Kotlin Design Patterns repository</a></p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><p><a target="_blank" href="https://github.com/iluwatar/java-design-patterns">Java Design Patterns</a></p>
</li>
<li><p><a target="_blank" href="https://www.amazon.de/Kotlin-Design-Patterns-Best-Practices/dp/1801815720/ref=sr_1_1?keywords=kotlin+design+patterns+and+best+practices&amp;qid=1694244553&amp;sprefix=kotlin+design%2Caps%2C101&amp;sr=8-1">Kotlin Design Patterns and Best Practices</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Kotlin Code Smell 36 - Object Coupling]]></title><description><![CDATA[TL;DR: Respect object boundaries: avoid coupling to data and prioritize interfaces and behavior.


When you view your objects merely as data holders, you risk violating their encapsulation.

Problem

Information Hiding Violation

Encapsulation Violat...]]></description><link>https://yonatankarp.com/kotlin-code-smell-36-object-coupling</link><guid isPermaLink="true">https://yonatankarp.com/kotlin-code-smell-36-object-coupling</guid><category><![CDATA[clean code]]></category><category><![CDATA[code smell ]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Mon, 04 Sep 2023 13:41:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/yB2TGLr-rVo/upload/e62a1c9cd1c1ac241af55927059db55a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR:</strong> Respect object boundaries: avoid coupling to data and prioritize interfaces and behavior.</p>
</blockquote>
<ul>
<li>When you view your objects merely as data holders, you risk violating their encapsulation.</li>
</ul>
<h2 id="heading-problem">Problem</h2>
<ul>
<li><p>Information Hiding Violation</p>
</li>
<li><p>Encapsulation Violation</p>
</li>
<li><p>Coupling</p>
</li>
</ul>
<h2 id="heading-solution">Solution</h2>
<ul>
<li>Always couple to interfaces and behavior, not data.</li>
</ul>
<h2 id="heading-sample-code">Sample Code</h2>
<h3 id="heading-wrong">Wrong</h3>
<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">Point</span></span>(<span class="hljs-keyword">var</span> x: <span class="hljs-built_in">Double</span>, <span class="hljs-keyword">var</span> y: <span class="hljs-built_in">Double</span>)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DistanceCalculator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">distanceBetween</span><span class="hljs-params">(origin: <span class="hljs-type">Point</span>, destination: <span class="hljs-type">Point</span>)</span></span>: <span class="hljs-built_in">Double</span> {
        <span class="hljs-keyword">return</span> sqrt(
            (destination.x - origin.x).pow(<span class="hljs-number">2</span>) +
                    (destination.y - origin.y).pow(<span class="hljs-number">2</span>)
        )
    }
}
</code></pre>
<h3 id="heading-right">Right</h3>
<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">Point</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> radius: <span class="hljs-built_in">Double</span>,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> theta: <span class="hljs-built_in">Double</span>
) {
    <span class="hljs-keyword">val</span> x: <span class="hljs-built_in">Double</span> <span class="hljs-keyword">get</span>() = radius * cos(theta)
    <span class="hljs-keyword">val</span> y: <span class="hljs-built_in">Double</span> <span class="hljs-keyword">get</span>() =  radius * sin(theta)
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DistanceCalculator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">distanceBetween</span><span class="hljs-params">(origin: <span class="hljs-type">Point</span>, destination: <span class="hljs-type">Point</span>)</span></span>: <span class="hljs-built_in">Double</span> {
        <span class="hljs-keyword">return</span> sqrt(
            (destination.x - origin.x).pow(<span class="hljs-number">2</span>) +
                    (destination.y - origin.y).pow(<span class="hljs-number">2</span>)
        )
    }
}
</code></pre>
<div class="hn-embed-widget" id="contact-me"></div><h2 id="heading-conclusion">Conclusion</h2>
<p>If your classes are polluted with setters, getters and public methods you will certainly have ways to couple to their accidental implementation.</p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-55-object-orgy">Code Smell 55 - Object Orgy</a> by <a class="user-mention" href="https://hashnode.com/@mcsee">Maximiliano Contieri</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Kotlin Code Smell 35 - Explicit Iteration]]></title><description><![CDATA[TL;DR: Avoid index-based iteration. Embrace higher-order collection functions.

Problem

Violation of encapsulation

Lack of declarativeness


Solution

Opt for forEach() or high-order iterators.

Concealing implementation details opens up possibilit...]]></description><link>https://yonatankarp.com/kotlin-code-smell-35-explicit-iteration</link><guid isPermaLink="true">https://yonatankarp.com/kotlin-code-smell-35-explicit-iteration</guid><category><![CDATA[clean code]]></category><category><![CDATA[code smell ]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Wed, 30 Aug 2023 09:38:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/FOsina4f7qM/upload/c37139d31191c8b8ab90c24697abff6e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong><em>TL;DR:</em></strong> Avoid index-based iteration. Embrace higher-order collection functions.</p>
</blockquote>
<h2 id="heading-problem">Problem</h2>
<ul>
<li><p>Violation of encapsulation</p>
</li>
<li><p>Lack of declarativeness</p>
</li>
</ul>
<h2 id="heading-solution">Solution</h2>
<ul>
<li><p>Opt for <code>forEach()</code> or high-order iterators.</p>
</li>
<li><p>Concealing implementation details opens up possibilities like caching, proxies, lazy loading, and more.</p>
</li>
</ul>
<h2 id="heading-sample-code">Sample Code</h2>
<h3 id="heading-wrong">Wrong</h3>
<pre><code class="lang-kotlin"><span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> until colors.count()) {
    print(colors[i])
}

<span class="hljs-comment">// For Kotlin 1.9 and above, the 'until' can (and should) be</span>
<span class="hljs-comment">// substituted with '..&lt;' to denote a range from 0 to </span>
<span class="hljs-comment">// colors.count(), excluding the end.</span>
</code></pre>
<h3 id="heading-right">Right</h3>
<pre><code class="lang-kotlin"><span class="hljs-keyword">for</span>(color <span class="hljs-keyword">in</span> colors) {
    println(color)
}

<span class="hljs-comment">// Utilizing closures and arrow functions</span>
colors.forEach { println(it) }
</code></pre>
<h2 id="heading-exceptions">Exceptions</h2>
<p>Should the problem domain necessitate elements being mapped to natural numbers like indices, then the initial method may suffice.</p>
<p>Always strive to draw parallels with real-world scenarios.</p>
<div class="hn-embed-widget" id="contact-me"></div><h2 id="heading-conclusion">Conclusion</h2>
<p>Many developers overlook this kind of code smell, dismissing it as a minor detail.</p>
<p>Yet, it's the accumulation of such declarative nuances that truly elevates code quality.</p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-53-explicit-iteration">Code Smell 53 - Explicit Iteration</a> by <a class="user-mention" href="https://hashnode.com/@mcsee">Maximiliano Contieri</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Kotlin Code Smell 34 - Fragile Tests]]></title><description><![CDATA[TL;DR: Steer clear of non-deterministic tests..

Problem

Lack of determinism

Eroding confidence

Time squandered


Solution

Ensure that the test is fully deterministic. Eradicate any potential for unpredictable behavior.

Eliminate test coupling.
...]]></description><link>https://yonatankarp.com/kotlin-code-smell-34-fragile-tests</link><guid isPermaLink="true">https://yonatankarp.com/kotlin-code-smell-34-fragile-tests</guid><category><![CDATA[clean code]]></category><category><![CDATA[code smell ]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Mon, 28 Aug 2023 10:06:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/5X5-iyx1SP0/upload/72295aca8e728b619e89241949ff9e19.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR:</strong> Steer clear of non-deterministic tests..</p>
</blockquote>
<h2 id="heading-problem">Problem</h2>
<ul>
<li><p>Lack of determinism</p>
</li>
<li><p>Eroding confidence</p>
</li>
<li><p>Time squandered</p>
</li>
</ul>
<h2 id="heading-solution">Solution</h2>
<ol>
<li><p>Ensure that the test is fully deterministic. Eradicate any potential for unpredictable behavior.</p>
</li>
<li><p>Eliminate test coupling.</p>
</li>
</ol>
<h2 id="heading-examples">Examples</h2>
<p>The terms "Fragile," "Intermittent," "Sporadic," and "Erratic" are often used interchangeably when discussing problematic tests in many development environments.</p>
<p>However, such tests erode the trust developers place in their test suites.</p>
<p>Such tests are best avoided.</p>
<h2 id="heading-sample-code">Sample Code</h2>
<h3 id="heading-wrong">Wrong</h3>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> org.junit.jupiter.api.Assertions.assertEquals
<span class="hljs-keyword">import</span> org.junit.jupiter.api.Test

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SetTest</span> </span>{

    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">abstract</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">constructor</span><span class="hljs-params">()</span></span>: MutableSet&lt;String&gt;

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> `test add empty`<span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">val</span> <span class="hljs-keyword">set</span> = <span class="hljs-keyword">constructor</span>()
        <span class="hljs-keyword">set</span>.add(<span class="hljs-string">"green"</span>)
        <span class="hljs-keyword">set</span>.add(<span class="hljs-string">"blue"</span>)
        assertEquals(<span class="hljs-string">"[green, blue]"</span>, <span class="hljs-keyword">set</span>.toString())
        <span class="hljs-comment">// This is fragile since the outcome hinges on the set's</span>
        <span class="hljs-comment">// ordering, which isn't predefined and can vary based on</span>
        <span class="hljs-comment">// the set's implementation.</span>
    }
}
</code></pre>
<h3 id="heading-right">Right</h3>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> org.junit.jupiter.api.Test
<span class="hljs-keyword">import</span> kotlin.test.assertEquals
<span class="hljs-keyword">import</span> kotlin.test.assertTrue

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SetTest</span> </span>{

    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">abstract</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">constructor</span><span class="hljs-params">()</span></span>: MutableSet&lt;String&gt;

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> `test add empty`<span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">val</span> <span class="hljs-keyword">set</span> = <span class="hljs-keyword">constructor</span>()
        <span class="hljs-keyword">set</span>.add(<span class="hljs-string">"green"</span>)
        assertEquals(<span class="hljs-string">"[green]"</span>, <span class="hljs-keyword">set</span>.toString())
    }

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> `test entry at single entry`<span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">val</span> <span class="hljs-keyword">set</span> = createFromArgs(<span class="hljs-string">"red"</span>)
        <span class="hljs-keyword">val</span> result = <span class="hljs-keyword">set</span>.contains(<span class="hljs-string">"red"</span>)
        assertTrue(result)
    }
}
</code></pre>
<div class="hn-embed-widget" id="contact-me"></div><h2 id="heading-conclusion">Conclusion</h2>
<p>Fragile tests often indicate system coupling and manifest as non-deterministic or unpredictable behaviors.</p>
<p>Addressing and resolving these erratic tests can drain considerable developer time and energy.</p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-52-fragile-tests">Code Smell 51 - Fragile Tests</a> by <a class="user-mention" href="https://hashnode.com/@mcsee">Maximiliano Contieri</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Kotlin Code Smell 33 - Caches]]></title><description><![CDATA[TL;DR - Caches discusses the problems with caching, such as coupling and maintainability, and proposes solutions like using an object mediator, testing invalidation scenarios, and modeling real-world cache metaphors. It concludes that caches should b...]]></description><link>https://yonatankarp.com/kotlin-code-smell-33-caches</link><guid isPermaLink="true">https://yonatankarp.com/kotlin-code-smell-33-caches</guid><category><![CDATA[clean code]]></category><category><![CDATA[code smell ]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Fri, 25 Aug 2023 08:30:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/gRujUd2CtTk/upload/e222cdbad8f7b3fb3b7d41e6e5083c29.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>TL;DR - Caches discusses the problems with caching, such as coupling and maintainability, and proposes solutions like using an object mediator, testing invalidation scenarios, and modeling real-world cache metaphors. It concludes that caches should be functional, and intelligent, and domain objects shouldn't be cached.</p>
</blockquote>
<h2 id="heading-problem">Problem</h2>
<ul>
<li><p>Coupling</p>
</li>
<li><p>Testability</p>
</li>
<li><p>Cache Invalidation</p>
</li>
<li><p>Maintainability</p>
</li>
<li><p>Premature Optimization</p>
</li>
<li><p>Erratic Behavior</p>
</li>
<li><p>Lack of Transparency</p>
</li>
<li><p>Non-Deterministic Behavior</p>
</li>
</ul>
<h2 id="heading-solution">Solution</h2>
<ol>
<li><p>If you have a conclusive benchmark and are willing to accept some coupling, put an object in the middle.</p>
</li>
<li><p>Unit test all your invalidation scenarios. Experience shows that we face them in an incremental way.</p>
</li>
<li><p>Look for a real-world cache metaphor and model it.</p>
</li>
</ol>
<h2 id="heading-sample-code">Sample Code</h2>
<h3 id="heading-wrong">Wrong</h3>
<pre><code class="lang-kotlin"><span class="hljs-keyword">typealias</span> Cache&lt;T&gt; = MutableMap&lt;String, List&lt;T&gt;&gt;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> cachedBooks: Cache&lt;Book&gt; = mutableMapOf()
) {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getBooks</span><span class="hljs-params">(title: <span class="hljs-type">String</span>)</span></span>: List&lt;Book&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> (cachedBooks.containsKey(title)) {
            cachedBooks[title]!!
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">val</span> booksFromDatabase = getBooksFromDatabase(title)
            cachedBooks[title] = booksFromDatabase
            booksFromDatabase
        }
    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getBooksFromDatabase</span><span class="hljs-params">(title: <span class="hljs-type">String</span>)</span></span>: List&lt;Book&gt; =
        globalDatabase().selectFrom(<span class="hljs-string">"Books"</span>, <span class="hljs-string">"WHERE TITLE = <span class="hljs-variable">$title</span>"</span>)
}
</code></pre>
<h3 id="heading-right">Right</h3>
<pre><code class="lang-kotlin"><span class="hljs-keyword">typealias</span> Cache&lt;T&gt; = MutableMap&lt;String, T&gt;

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">BookRetriever</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">bookByTitle</span><span class="hljs-params">(title: <span class="hljs-type">String</span>)</span></span>: Book?
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> </span>{
    <span class="hljs-comment">// Just Book-related Stuff</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DatabaseLibrarian</span> : <span class="hljs-type">BookRetriever {</span></span>
    <span class="hljs-comment">// Go to the database (not global hopefully)</span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">bookByTitle</span><span class="hljs-params">(title: <span class="hljs-type">String</span>)</span></span>: Book? { ... }
}

<span class="hljs-comment">// We always look for real-life metaphors</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HotSpotLibrarian</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> inbox: Inbox,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> realRetriever: BookRetriever
) : BookRetriever {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">bookByTitle</span><span class="hljs-params">(title: <span class="hljs-type">String</span>)</span></span>: Book? {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> (inbox.includesTitle(title)) {
            <span class="hljs-comment">// We are lucky. Someone has just returned the book copy.</span>
            inbox.retrieveAndRemove(title)
        } <span class="hljs-keyword">else</span> {
            realRetriever.bookByTitle(title)
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Inbox</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> books: Cache&lt;Book&gt; = mutableMapOf()) {   
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">includesTitle</span><span class="hljs-params">(title: <span class="hljs-type">String</span>)</span></span> { ... }
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">retrieveAndRemove</span><span class="hljs-params">(title: <span class="hljs-type">String</span>)</span></span>: Book? { ... }
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">addBook</span><span class="hljs-params">(title: <span class="hljs-type">String</span>, book: <span class="hljs-type">Book</span>)</span></span> { ... }
}
</code></pre>
<div class="hn-embed-widget" id="contact-me"></div><h2 id="heading-conclusion">Conclusion</h2>
<p>Caches should be functional and intelligent, allowing for effective management of invalidation. General-purpose caches are best suited for low-level objects like operating systems, files, and streams, while domain objects should not be cached.</p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-49-caches">Code Smell 49 - Caches</a> by <a class="user-mention" href="https://hashnode.com/@mcsee">Maximiliano Contieri</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Kotlin Code Smell 32 - Repeated Code]]></title><description><![CDATA[Problem

Code Duplication

Maintainability

Don't Repeat Yourself


Solution

Find repeated patterns (not repeated code).

Create an abstraction.

Parametrize abstraction calls.

Use composition and avoid inheritance.

Unit test the new abstraction.
...]]></description><link>https://yonatankarp.com/kotlin-code-smell-32-repeated-code</link><guid isPermaLink="true">https://yonatankarp.com/kotlin-code-smell-32-repeated-code</guid><category><![CDATA[clean code]]></category><category><![CDATA[code smell ]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Wed, 23 Aug 2023 08:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zAZYuch7deE/upload/105e5b048e80b9419b301810cc15e656.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-problem">Problem</h2>
<ul>
<li><p>Code Duplication</p>
</li>
<li><p>Maintainability</p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"><strong>Don't Repeat Yourself</strong></a></p>
</li>
</ul>
<h2 id="heading-solution">Solution</h2>
<ol>
<li><p>Find repeated patterns (not repeated code).</p>
</li>
<li><p>Create an abstraction.</p>
</li>
<li><p>Parametrize abstraction calls.</p>
</li>
<li><p>Use composition and avoid inheritance.</p>
</li>
<li><p>Unit test the new abstraction.</p>
</li>
</ol>
<h2 id="heading-sample-code">Sample Code</h2>
<h3 id="heading-wrong">Wrong</h3>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WordProcessor</span></span>(<span class="hljs-keyword">var</span> text: String = <span class="hljs-string">""</span>) {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">replaceText</span><span class="hljs-params">(patternToFind: <span class="hljs-type">String</span>, textToReplace: <span class="hljs-type">String</span>)</span></span> {
        text = <span class="hljs-string">"&lt;&lt;&lt; <span class="hljs-subst">${text.replace(patternToFind, textToReplace}</span> &gt;&gt;&gt;"</span>
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Obfuscator</span></span>(<span class="hljs-keyword">var</span> text: String = <span class="hljs-string">""</span>) {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">obfuscate</span><span class="hljs-params">(patternToFind: <span class="hljs-type">String</span>, textToReplace: <span class="hljs-type">String</span>)</span></span> {
        text = text.lowercase().replace(patternToFind, textToReplace)
    }
}
</code></pre>
<h3 id="heading-right">Right</h3>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TextReplacer</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">replace</span><span class="hljs-params">(
        patternToFind: <span class="hljs-type">String</span>,
        textToReplace: <span class="hljs-type">String</span>,
        subject: <span class="hljs-type">String</span>,
        replaceFunction: (<span class="hljs-type">String</span>, <span class="hljs-type">String</span>, <span class="hljs-type">String</span>) -&gt; <span class="hljs-type">String</span>,
        postProcessClosure: (<span class="hljs-type">String</span>) -&gt; <span class="hljs-type">String</span>
    )</span></span>: String =
        replaceFunction(patternToFind, textToReplace, subject)
            .let(postProcessClosure)
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WordProcessor</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> text: String = <span class="hljs-string">""</span>) {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">replaceText</span><span class="hljs-params">(patternToFind: <span class="hljs-type">String</span>, textToReplace: <span class="hljs-type">String</span>)</span></span> {
        text = TextReplacer()
            .replace(
                patternToFind,
                textToReplace,
                text,
                replaceFunction = { pattern, replace, subject -&gt;
                    subject.replace(pattern, replace)
                },
                postProcessClosure = { <span class="hljs-string">"&lt;&lt;&lt; <span class="hljs-variable">$it</span> &gt;&gt;&gt;"</span> }
            )
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Obfuscator</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> text: String = <span class="hljs-string">""</span>) {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">obfuscate</span><span class="hljs-params">(patternToFind: <span class="hljs-type">String</span>, textToReplace: <span class="hljs-type">String</span>)</span></span> {
        text = TextReplacer()
            .replace(
                patternToFind,
                textToReplace,
                text,
                replaceFunction = { pattern, replace, subject -&gt;
                    subject.replace(pattern, replace, ignoreCase = <span class="hljs-literal">true</span>)
                },
                postProcessClosure = { it.lowercase() }
            )
    }
}
</code></pre>
<div class="hn-embed-widget" id="contact-me"></div><h2 id="heading-conclusion">Conclusion</h2>
<p>Repeated code is always a smell. Copying and pasting code is always a shame. With our refactoring tools, we need to accept the challenge of removing duplication and trust our tests as a safety net.</p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-46-repeated-code">Code Smell 46 - Repeated Code</a> by <a class="user-mention" href="https://hashnode.com/@mcsee">Maximiliano Contieri</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Kotlin Code Smell 31 - Not Polymorphic]]></title><description><![CDATA[Problems

Missed Polymorphism
Coupling
IFs / Type check Polluting.
Names are coupled to types.

Solutions

Rename methods after what they do.
Favor polymorphism.

Sample Code
Wrong
class Array {
    fun arraySort() { ... }
}

class List {
    fun lis...]]></description><link>https://yonatankarp.com/kotlin-code-smell-31-not-polymorphic</link><guid isPermaLink="true">https://yonatankarp.com/kotlin-code-smell-31-not-polymorphic</guid><category><![CDATA[clean code]]></category><category><![CDATA[code smell ]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Mon, 21 Aug 2023 08:34:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1691137175613/31685090-0c41-47c5-915c-102997e11f33.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-problems">Problems</h2>
<ul>
<li>Missed Polymorphism</li>
<li>Coupling</li>
<li>IFs / Type check Polluting.</li>
<li>Names are coupled to types.</li>
</ul>
<h2 id="heading-solutions">Solutions</h2>
<ol>
<li>Rename methods after what they do.</li>
<li>Favor polymorphism.</li>
</ol>
<h2 id="heading-sample-code">Sample Code</h2>
<h3 id="heading-wrong">Wrong</h3>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Array</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">arraySort</span><span class="hljs-params">()</span></span> { ... }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">List</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">listSort</span><span class="hljs-params">()</span></span> { ... }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Set</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">setSort</span><span class="hljs-params">()</span></span> { ... }
}
</code></pre>
<h3 id="heading-right">Right</h3>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Sortable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sort</span><span class="hljs-params">()</span></span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Array</span> : <span class="hljs-type">Sortable {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sort</span><span class="hljs-params">()</span></span> { ... }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">List</span> : <span class="hljs-type">Sortable {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sort</span><span class="hljs-params">()</span></span> { ... }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Set</span> : <span class="hljs-type">Sortable {</span></span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sort</span><span class="hljs-params">()</span></span> { ... }
}
</code></pre>
<div class="hn-embed-widget" id="contact-me"></div><h2 id="heading-conclusion">Conclusion</h2>
<p>Naming is very important. We need to name concepts after what they do, not after accidental types.</p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-45-not-polymorphic">Code Smell 45 - Not Polymorphic</a> by <a class="user-mention" href="https://hashnode.com/@mcsee">Maximiliano Contieri</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Kotlin Code Smell 30 - Concrete Classes Subclassified]]></title><description><![CDATA[Problem

Bad Models
Coupling
Liskov Substitution Violation
Method overriding
Mapper fault

Solution

Subclasses should be specializations.
Refactor Hierarchies.
Favor Composition.
Leaf classes should be concrete.
Not-leaf classes should be abstract.
...]]></description><link>https://yonatankarp.com/kotlin-code-smell-30-concrete-classes-subclassified</link><guid isPermaLink="true">https://yonatankarp.com/kotlin-code-smell-30-concrete-classes-subclassified</guid><category><![CDATA[clean code]]></category><category><![CDATA[code smell ]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Fri, 18 Aug 2023 08:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/GqQ1Jnl0TWQ/upload/a140e90b91e3367277d3cda82a0c44e9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-problem">Problem</h2>
<ul>
<li>Bad Models</li>
<li>Coupling</li>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Liskov_substitution_principle"><strong>Liskov Substitution</strong></a> Violation</li>
<li>Method overriding</li>
<li><a target="_blank" href="https://maximilianocontieri.com/what-is-wrong-with-software"><strong>Mapper</strong></a> fault</li>
</ul>
<h2 id="heading-solution">Solution</h2>
<ol>
<li>Subclasses should be specializations.</li>
<li>Refactor Hierarchies.</li>
<li>Favor Composition.</li>
<li>Leaf classes should be concrete.</li>
<li>Not-leaf classes should be abstract.</li>
</ol>
<h2 id="heading-sample-code">Sample Code</h2>
<h3 id="heading-wrong">Wrong</h3>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Stack</span>&lt;<span class="hljs-type">T</span>&gt; : <span class="hljs-type">ArrayList</span>&lt;<span class="hljs-type">T</span>&gt;</span>() {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">push</span><span class="hljs-params">(value: <span class="hljs-type">T</span>)</span></span> { … }
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">pop</span><span class="hljs-params">()</span></span>: T { … }
}
<span class="hljs-comment">// Stack does not behave Like an ArrayList</span>
<span class="hljs-comment">// besides pop, push, top it also implements (or overrides) get, set,</span>
<span class="hljs-comment">// add, remove and clear stack elements can be arbitrary accessed</span>

<span class="hljs-comment">// both classes are concrete</span>
</code></pre>
<h3 id="heading-right">Right</h3>
<pre><code class="lang-kotlin"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Collection</span> </span>{
    <span class="hljs-keyword">abstract</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">size</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Int</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Stack</span>&lt;<span class="hljs-type">out T</span>&gt; : <span class="hljs-type">Collection</span></span>() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> contents = ArrayList&lt;T&gt;()

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">push</span><span class="hljs-params">(value: <span class="hljs-type">Any</span>)</span></span> { ... }

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">pop</span><span class="hljs-params">()</span></span>: Any? { ... }

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">size</span><span class="hljs-params">()</span></span> = contents.size
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayList</span> : <span class="hljs-type">Collection</span></span>() {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">size</span><span class="hljs-params">()</span></span>: <span class="hljs-built_in">Int</span> { ... }
}
</code></pre>
<div class="hn-embed-widget" id="contact-me"></div><h2 id="heading-conclusion">Conclusion</h2>
<p>Accidental sub-classification is the first obvious advantage for junior developers.</p>
<p>More mature ones find composition opportunities instead.</p>
<p>Composition is dynamic, multiple, pluggable, more testable, more maintainable, and less coupled than inheritance.</p>
<p>Only subclassify an entity if it follows the relationship <em>behaves like</em>.</p>
<p>After subclassing, the parent class should be abstract.</p>
<p>Java made this mistake, and they're regretting it until now. Let's do better than Java 😁</p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-43-concrete-classes-subclassified">Code Smell 43 - Concrete Classes Subclassified</a> by <a class="user-mention" href="https://hashnode.com/@mcsee">Maximiliano Contieri</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Kotlin Code Smell 29 - Regular Expression Abusers]]></title><description><![CDATA[RegEx is a wonderful tool, we should use them carefully and not look smart.
Problem

Readability

Maintainability

Testability

Intention Revealing


Solution

Use regular expressions just for string validation.

If you need to manipulate objects, do...]]></description><link>https://yonatankarp.com/kotlin-code-smell-29-regular-expression-abusers</link><guid isPermaLink="true">https://yonatankarp.com/kotlin-code-smell-29-regular-expression-abusers</guid><category><![CDATA[clean code]]></category><category><![CDATA[code smell ]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Wed, 16 Aug 2023 08:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Kl4LNdg6on4/upload/e2b025e94f4ae29d131bd6081cad013d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>RegEx is a wonderful tool, we should use them carefully and not look smart.</em></p>
<h2 id="heading-problem">Problem</h2>
<ul>
<li><p>Readability</p>
</li>
<li><p>Maintainability</p>
</li>
<li><p>Testability</p>
</li>
<li><p>Intention Revealing</p>
</li>
</ul>
<h2 id="heading-solution">Solution</h2>
<ol>
<li><p>Use regular expressions just for string validation.</p>
</li>
<li><p>If you need to manipulate objects, don't make them strings.</p>
</li>
</ol>
<h2 id="heading-sample-code">Sample Code</h2>
<h3 id="heading-wrong">Wrong</h3>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> regex = <span class="hljs-string">"^\\+(?:[0-9a-zA-Z][– -]?){6,14}[0-9a-zA-Z]$"</span>.toRegex()
</code></pre>
<h3 id="heading-right">Right</h3>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> prefix = <span class="hljs-string">"""\+"""</span>
<span class="hljs-keyword">val</span> digit = <span class="hljs-string">"[0-9a-zA-Z]"</span>
<span class="hljs-keyword">val</span> space = <span class="hljs-string">"[– -]"</span>
<span class="hljs-keyword">val</span> phoneRegex = <span class="hljs-string">"^<span class="hljs-variable">$prefix</span>(?:<span class="hljs-variable">$digit</span><span class="hljs-variable">$space</span>?){6,14}<span class="hljs-variable">$digit</span>$"</span>.toRegex()
</code></pre>
<div class="hn-embed-widget" id="contact-me"></div><h2 id="heading-conclusion">Conclusion</h2>
<p>Regular expressions are a great tool for string validation. We must use them in a declarative way and just for strings.</p>
<p>Names are very important to understand pattern meanings.</p>
<p>If we need to manipulate objects or hierarchies, we should do it in an <em>object way</em>.</p>
<p>Unless we have a conclusive benchmark of <strong>impressive</strong> performance improvement.</p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-41-regular-expression-abusers">Code Smell 41 - Regular Expression Abusers</a> by <a class="user-mention" href="https://hashnode.com/@mcsee">Maximiliano Contieri</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Kotlin Code Smell 28 - Abstract Names]]></title><description><![CDATA[Problem

Implemental Naming
Meaningless names
Broken MAPPER and Bijection to real-world entities.

Solution

Choose meaningful names.
Find metaphors.
Avoid words like abstract, base, generic, helper, data, info, etc.
Use rules for naming.

Sample Cod...]]></description><link>https://yonatankarp.com/kotlin-code-smell-28-abstract-names</link><guid isPermaLink="true">https://yonatankarp.com/kotlin-code-smell-28-abstract-names</guid><category><![CDATA[clean code]]></category><category><![CDATA[code smell ]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Mon, 14 Aug 2023 08:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/wQLAGv4_OYs/upload/0da07320cfbf4e807972d868892c17a3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-problem">Problem</h2>
<ul>
<li>Implemental Naming</li>
<li>Meaningless names</li>
<li>Broken <a target="_blank" href="https://maximilianocontieri.com/what-is-wrong-with-software"><strong>MAPPER</strong></a> and <a target="_blank" href="https://maximilianocontieri.com/the-one-and-only-software-design-principle"><strong>Bijection</strong></a> to real-world entities.</li>
</ul>
<h2 id="heading-solution">Solution</h2>
<ol>
<li>Choose meaningful names.</li>
<li>Find metaphors.</li>
<li>Avoid words like <em>abstract</em>, <em>base</em>, <em>generic</em>, <em>helper</em>, <em>data</em>, <em>info</em>, etc.</li>
<li>Use <a target="_blank" href="https://maximilianocontieri.com/what-exactly-is-a-name-part-ii-rehab"><strong>rules</strong></a> for naming.</li>
</ol>
<h2 id="heading-sample-code">Sample Code</h2>
<h3 id="heading-wrong">Wrong</h3>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Repository</span> </span>{
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MeetingCollection</span> </span>{
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AccountsComposite</span> </span>{
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NoteArray</span> </span>{
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LogCollector</span> </span>{
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SearcherBase</span> </span>{
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractTransportation</span> </span>{
    <span class="hljs-comment">// ...</span>
}
</code></pre>
<h3 id="heading-right">Right</h3>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Schedule</span> </span>{
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Portfolio</span> </span>{
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NoteBook</span> </span>{
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Journal</span> </span>{
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Vehicle</span> </span>{
    <span class="hljs-comment">// ...</span>
}
</code></pre>
<div class="hn-embed-widget" id="contact-me"></div><h2 id="heading-conclusion">Conclusion</h2>
<p>Finding names is the last thing we should do in our designs. Unless we have a clear business understanding, good names emerge at the end after defining behavior and protocol boundaries.</p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-38-abstract-names">Code Smell 38 - Abstract Names</a> by <a class="user-mention" href="https://hashnode.com/@mcsee">Maximiliano Contieri</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Kotlin Code Smell 27 - Protected Attributes]]></title><description><![CDATA[Problem

Sub-classification for code reuse purposes.
Liskov substitution violation (SOLID principle).
Possible subclass overrides.

Solution

Favor composition
Avoid subclassifying attributes.
Extract behavior to separate objects.

Sample Code
Wrong
...]]></description><link>https://yonatankarp.com/kotlin-code-smell-27-protected-attributes</link><guid isPermaLink="true">https://yonatankarp.com/kotlin-code-smell-27-protected-attributes</guid><category><![CDATA[clean code]]></category><category><![CDATA[code smell ]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[kotlin beginner]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Yonatan Karp-Rudin]]></dc:creator><pubDate>Thu, 10 Aug 2023 08:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Uf-c4u1usFQ/upload/e5894315f656ab2940d08f90a8558c1c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-problem">Problem</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-11-subclassification-for-code-reuse"><strong>Sub-classification</strong></a> for code reuse purposes.</li>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Liskov_substitution_principle"><strong>Liskov substitution</strong></a> violation (<a target="_blank" href="https://en.wikipedia.org/wiki/SOLID"><strong>SOLID</strong></a> principle).</li>
<li>Possible subclass overrides.</li>
</ul>
<h2 id="heading-solution">Solution</h2>
<ol>
<li>Favor composition</li>
<li>Avoid subclassifying attributes.</li>
<li>Extract behavior to separate objects.</li>
</ol>
<h2 id="heading-sample-code">Sample Code</h2>
<h3 id="heading-wrong">Wrong</h3>
<pre><code class="lang-kotlin"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ElectronicDevice</span></span>(<span class="hljs-keyword">protected</span> <span class="hljs-keyword">val</span> battery: Battery)

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IDevice</span></span>(
    battery: Battery,
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">val</span> operatingSystem: OperatingSystem
) : ElectronicDevice(battery)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IPad</span></span>(
    battery: Battery,
    ios: OperatingSystem
) : IDevice(battery, ios)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IPhone</span></span>(
    battery: Battery,
    ios: OperatingSystem,
    <span class="hljs-keyword">val</span> phoneModule: PhoneModule
) : IDevice(battery, ios)
</code></pre>
<h3 id="heading-right">Right</h3>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ElectronicDevice</span> </span>{
    <span class="hljs-comment">//...</span>
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PhoneCommunication</span> </span>{
    <span class="hljs-comment">//...</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IPad</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> battery: Battery,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> operatingSystem: OperatingSystem
) : ElectronicDevice {
    <span class="hljs-comment">// Implement iPad-specific functionality here</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IPhone</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> battery: Battery,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> operatingSystem: OperatingSystem,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> phoneModule: PhoneModule
) : ElectronicDevice, PhoneCommunication {
    <span class="hljs-comment">// Implement iPhone-specific functionality here</span>
}
</code></pre>
<div class="hn-embed-widget" id="contact-me"></div><h2 id="heading-conclusion">Conclusion</h2>
<p>Protected attributes are yet another tool we should use carefully. Every decision is a smell, and we should be very cautious with attributes and inheritance.</p>
<h2 id="heading-credits">Credits</h2>
<ul>
<li><a target="_blank" href="https://maximilianocontieri.com/code-smell-37-protected-attributes">Code Smell 37 - Protected Attributes</a> by <a class="user-mention" href="https://hashnode.com/@mcsee">Maximiliano Contieri</a></li>
</ul>
]]></content:encoded></item></channel></rss>