<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: LUCIANO DE CASTRO MARTINS</title>
    <description>The latest articles on DEV Community by LUCIANO DE CASTRO MARTINS (@lcmartins).</description>
    <link>https://dev.to/lcmartins</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F334588%2F727266b7-594f-4b26-9f25-eb0ed399c334.jpeg</url>
      <title>DEV Community: LUCIANO DE CASTRO MARTINS</title>
      <link>https://dev.to/lcmartins</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lcmartins"/>
    <language>en</language>
    <item>
      <title>Design Patterns - Observer</title>
      <dc:creator>LUCIANO DE CASTRO MARTINS</dc:creator>
      <pubDate>Wed, 09 Apr 2025 17:33:16 +0000</pubDate>
      <link>https://dev.to/lcmartins/design-patterns-observer-4b7o</link>
      <guid>https://dev.to/lcmartins/design-patterns-observer-4b7o</guid>
      <description>&lt;h2&gt;
  
  
  Use cases
&lt;/h2&gt;

&lt;p&gt;Imagine a scenario where you have a platform where users can create posts (like this one), and you received a new requirement so when a post is liked or disliked depending on how many likes it reiceived the post has to be monetized. The inicial solution is go where the post is liked/disliked and place an if like this:&lt;br&gt;
&lt;code&gt;if(post.likeCount &amp;gt; X){ callMonetization(post);}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Simple, now imagine that another requirement comes to you, saying that when any post is liked or disliked it should have an addtional log for compliance. So there you go place another if or inject another dependency on client code just to log the interesting part, this way you can end up with multiple if statement anytime you need to handle a new requirement, or having your code with multiple responsabilities/dependencies for each new requirement you have. Both scenarios are not good and observer design pattern can help us handle that.&lt;/p&gt;

&lt;p&gt;Just for note the pattern is also known by other names like 'pub/sub'.&lt;/p&gt;

&lt;p&gt;So let's create some code that implements the observer pattern.&lt;br&gt;
This pattern uses an interface(observer) with methods that will be called on the observers (concrete implementation). First let's look at the arquitecture for a solution where we implemented a log requirement, a database save requirement, a notification requirement and a message queeu requirement(to focus on the pattern the specifics of those implementations were abstracted).&lt;/p&gt;

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

&lt;p&gt;On that arquitecture we have a post entity, that have an author(person), an id, etc..&lt;br&gt;
the observer interface and some pseudo concrete implementation, the post manager that will act as a proxy to our post like or dislike events calling the concret observers, the usecases that call manager's appropriate methods when invoked in client code, and offcourse there is the client code.&lt;/p&gt;

&lt;p&gt;That said lets implement it in java:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;the post entity&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;the observer interface&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndcbdh3n78ruqk6yd4nz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndcbdh3n78ruqk6yd4nz.png" alt="Image description" width="787" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;the post manager&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;the observer's implementation&lt;/strong&gt;&lt;/p&gt;

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

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

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

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

&lt;p&gt;&lt;strong&gt;and finally our client code&lt;/strong&gt;:&lt;/p&gt;

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

&lt;p&gt;so in client code we have a post manager used to add the observers (addObserver method), 2 usecases (like and dislike), people (one that create a post, and others that interact with it) and a method to create a fake id.&lt;/p&gt;

&lt;p&gt;Executing the main method we'll see the following print statements (simplicity):&lt;/p&gt;

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

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

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

&lt;p&gt;so that's it, whenever you want to react over some entity event like a post like/dislike, customer's transactions like withdraw, reimbursement, deposit, ect all you need to do is create another implementation of the observer interface, add it to the observers list in the manager and wait so your new observer will get called whenever an event occurs and you can use that call to handle your requirements.&lt;/p&gt;

&lt;p&gt;Much better than inject not related code anywhere, don't you agreee?&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>java</category>
    </item>
    <item>
      <title>Design Patterns - Pipeline</title>
      <dc:creator>LUCIANO DE CASTRO MARTINS</dc:creator>
      <pubDate>Mon, 07 Apr 2025 16:49:12 +0000</pubDate>
      <link>https://dev.to/lcmartins/design-patterns-pipeline-3ink</link>
      <guid>https://dev.to/lcmartins/design-patterns-pipeline-3ink</guid>
      <description>&lt;p&gt;Pipeline design pattern comes in handy when we need to execute sequences of steps over an input (request), were each step must be handled by differente software logic. &lt;/p&gt;

&lt;p&gt;For instance, imagine a sequence of steps needed to approve a credit, a sequence of tests scores checking before decide if an student go up a year, medical exams results, etc...&lt;/p&gt;

&lt;p&gt;Let's dive into a simple credit approval imaginary flow using typescript. You can define your own logic but for the sake of simplicity i'll keep it simple.&lt;/p&gt;

&lt;p&gt;For this we'll need the following domain:&lt;br&gt;
a card issuer represented by the enum CardIssuer, a person (Person Interface) and a Credit domain class (credit interface), see bellow:&lt;/p&gt;

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

&lt;p&gt;So with the basic model created let's define our Pipeline implementation, but before that i'll need a CreditCardEvaluation class simply to wrap our domain so handling all related information becomes easier.&lt;/p&gt;

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

&lt;p&gt;Finally an interface that defines our handlers contract (the contract to handle a request), and the pipeline class.&lt;/p&gt;

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

&lt;p&gt;Now we must define what we want to validate/check. For that i defined a basic credit validator (BasicCreditProcessor), a guarantee validator and a credit card message processor, classes are as follow:&lt;/p&gt;

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

&lt;p&gt;Now that we have our structure, let's test it:&lt;/p&gt;

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

&lt;p&gt;and the result is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5k7gl972toqfm5dcqu4d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5k7gl972toqfm5dcqu4d.png" alt="Image description" width="640" height="59"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;a second test:&lt;/p&gt;

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

&lt;p&gt;with the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvgmyhy8my43jy6qz0hzn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvgmyhy8my43jy6qz0hzn.png" alt="Image description" width="684" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;by using the &lt;strong&gt;pipeline&lt;/strong&gt; design pattern we avoid having a single class with multiple responsabilities and adding more processors "step/executors" are as easy as writing them and placing them inside the pipeline. that is it.&lt;/p&gt;

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