<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Rafael Rutsatz on Medium]]></title>
        <description><![CDATA[Stories by Rafael Rutsatz on Medium]]></description>
        <link>https://medium.com/@rafael.rutsatz?source=rss-1e31801975d5------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*5lQXwnaYIRM8-C4f</url>
            <title>Stories by Rafael Rutsatz on Medium</title>
            <link>https://medium.com/@rafael.rutsatz?source=rss-1e31801975d5------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 08 Jun 2026 17:46:54 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@rafael.rutsatz/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[SOLID Principles — Why Bother]]></title>
            <link>https://medium.com/@rafael.rutsatz/solid-principles-why-bother-78adccc66519?source=rss-1e31801975d5------2</link>
            <guid isPermaLink="false">https://medium.com/p/78adccc66519</guid>
            <category><![CDATA[solid]]></category>
            <dc:creator><![CDATA[Rafael Rutsatz]]></dc:creator>
            <pubDate>Tue, 14 Feb 2023 14:01:43 GMT</pubDate>
            <atom:updated>2023-02-16T19:53:54.276Z</atom:updated>
            <content:encoded><![CDATA[<h3>SOLID Principles — Why Bother</h3><p>This article will briefly review the importance of applying good practices in projects and then give a quick overview of the SOLID principles.</p><h3>Why Bother</h3><p>Have you ever wondered why you should care about good practices? Or what could happen if you don’t apply them to the project? And how can you ensure your code is good enough? So let’s try to explore these subjects.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pKhn9a0SvF3EUFUi6zWR7g.jpeg" /></figure><p>I want to start with this phrase: “The ritual lasts long after the reasons have been forgotten”. This means that it is common for humans to do many things without understanding the reasons behind them. As Jordan Peterson once said: &quot;It’s like waking up one day and noting that you don’t know why you put a Christmas tree up, but you have been doing it for a long time, and that is what people do, and you know there are reasons that the Christmas tree came about.&quot; We do this in our lives, and we also do this in our projects. How many times have you copied code from someone else’s project? Or from the internet? We’ve all probably done it. So this is the first point: Ask yourself why something is done the way it is.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IeYAX6oqz1igFSSmAt9-Pg.jpeg" /></figure><p>And now let’s talk a little about money. Developers often don’t think about this subject, but it’s essential to have a view from all angles, including the perspective of the company that hired you to develop the project.</p><p>Let me tell you a little story. I started working on our team’s biggest project when I joined a company. And they said it was the sales champion, the most profitable project. But today, I see that the project failed. The developers of that project failed. And you might think: But what do you mean? Isn’t it the team’s biggest, most profitable, and best seller? And yes, that is correct, but now let me explain this further. It turns out that the project was complicated to maintain. Any adjustments we had to make sometimes took hours or days. In other words, the project was very costly to maintain. And the proof of this is that we started to develop a new project, to do the same thing this other project was already doing. So this is a consequence of a project that did not follow good practices.</p><p>So we have to consider that developing software is expensive. And I can’t finish it and never touch it again. It needs constant maintenance, as it needs to keep up with the evolution of the business. And for the software to be profitable, it needs to stay in the running for as long as possible because the longer this running time is, the more return it generates. And to achieve all of this, the project needs a well-architected solution.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*U_yCuOpRSB6nQZ9dE_ox2A.jpeg" /></figure><p>Another thing we do is: make mistakes. And this is no different with new projects. And we must make many mistakes before we can create a solution that will meet all the points we’ve already discussed. And those mistakes can be costly, and they often are. No wonder most projects fail because of high maintenance costs. So how can we ensure we don’t make the same mistakes? Well, there is a shortcut that we can use, which allows us to reach the results we want quickly, that is, making good software. So let’s delve deeper into this subject.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qGIfu9nAyiDNuxMAuMyauQ.jpeg" /></figure><p>We often sink in the mud, but there is already a path that will help us, but we are not seeing it. And this path has been shown to us by people who have already made many mistakes in the past. So what we can do is: learn from the mistakes of others. This is our shortcut. So if you look at design patterns, you’ll see that they’re the solution to many of the problems other people have had. And we must use them, so we don’t make the same mistakes.</p><p>In fact, the book Clean Code, written by Robert C. Martin, aka Uncle Bob, is an example of this. The first edition began to be written in the 90s and was published a little later. And as Uncle Bob himself said, he didn’t create all the rules. At that time, it was common to use forums to exchange ideas and talk with others. Using the forums a lot, he realized that several people had some problems and that, in the end, everyone came to similar solutions. So what he started to do was to group these problems and solutions in one place. So many of the patterns that we have today are years of experience of people making mistakes and coming to the same conclusions. So we don’t have to make the same mistakes. We can identify our problem and apply a solution, that is, some design pattern. And SOLID is a good start.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*o-iyXnXZJumbAqhZ4HNAiw.jpeg" /></figure><p>So keep in mind that If the software doesn’t think about being sustainable from day zero, it can generate a nightmare for the company and, in the end, could be loss-making.</p><p>This was an introduction to show the importance of good practices, how design patterns can help us, and what can happen if we don’t use them. So, now that you know this, let’s start talking about SOLID.</p><h3>SOLID</h3><p>When we are talking about software architecture, we are talking about several pillars, and one of these pillars is: how you code. And we have different ways of programming, and one of those ways is using object orientation. And because of that, we have several good programming practices. SOLID is an acronym that consolidates five items that are considered good practices in the world of object-oriented development. So let’s see each of them, why to use them, and what problems each one solves, and give some practical examples.</p><h3><strong>S — Single Responsibility Principle</strong></h3><p>A class should have only one responsibility. It can’t do more things than it was created to do. When you put too much to do inside the class, you are hurting this principle and complicating the way you work with object orientation. We can also apply this to methods, so each method needs to do only one thing.</p><p>Let’s take a look at the example below. We have a <em>Movie</em> class with <em>name</em> and <em>category</em> attributes and <em>connection</em> and <em>createCategory</em> methods. However, in this example, this is a Model class, that is, a class that contains our attributes and should probably be an anemic class (without any methods). So the <em>connection</em> method, which connects to the database, and the <em>createCategory</em> method, which saves the <em>category</em> in the database, are not respecting this principle, as they are doing things that the class was not created to do. Therefore, connecting to the database and saving the category is not the responsibility of this class.</p><pre>class Movie {<br>    private String name;<br>    private Category category;<br><br>    public Connection connection() {<br>        return new Connection();<br>    }<br><br>    public void createCategory() {<br>        this.connection().insert(this.category);<br>    }<br><br>    // getters and setters<br>}</pre><p>So we have to move to other classes the methods that don’t fit. We will have two new classes if we use the MVC (Model-View-Controller) pattern to refactor this class. First, we create the <em>Service</em> class, responsible for our logic to create the <em>category</em>, which will receive the <em>createCategory</em> method. Then, we create the <em>Repository</em> class, which is responsible for connecting to the database, and which will receive the <em>connection</em> method.</p><pre>class Movie {<br>    private String name;<br>    private Category category;<br><br>    // getters and setters<br>}<br><br>class Service {<br>    private Repository repository;<br><br>    // The createCategory method is now inside the Service.<br>    public void createCategory(Category category) {<br>        repository.createCategory(category);<br>    }<br>}<br><br>class Repository {<br>    public void createCategory(Category category) {<br>        this.connection().insert(category);<br>    }<br><br>    // The connection method is now inside the Repository.<br>    public Connection connection() {<br>        return new Connection();<br>    }<br>}</pre><h3>O — Open Closed Principle</h3><p>Every class has to be open for extension and closed for modification. Every time you need to add a new behavior, you increase the class size by adding new conditions. When you apply this principle, instead of creating a class and every time you change some requirement, you have to keep changing and incrementing this class, you make a base of this class, and every time you need to modify or add something new, you extend the behavior. Instead of putting everything inside the same class, you create different objects and make the system more extensible, taking better advantage of object-oriented resources. You work with objects and make them talk with each other.</p><p>In the example below, we have the <em>Movie</em> class with a <em>category</em> and a <em>price</em>. We have the <em>calculatePrice</em> method, which has a simple logic to calculate the price depending on the movie category. I know this might not make sense, and we should avoid using constants in our code, but the idea here is to use a simple example to demonstrate this principle in practice. So if the category is Action, we double the movie price. If the category is Drama, we increase the price by 50%. Now, what if we need to add one more category? What if now we also have Comedy? We have to add one more if statement. Every time I need to add a new category, I must remember to adjust the <em>calculatePrice</em> method. And it gets worse and worse because this method only tends to grow in size. This class is plastered because I always need to modify it. But the idea is that the class is closed for modification, but at the same time, we can open this class for extension.</p><pre>class Movie {<br>    private Category category;<br>    private double price;<br><br>    public double calculatePrice() {<br>        if (category.getName().equals(&quot;Action&quot;)) {<br>            return price * 2;<br>        } else if (category.getName().equals(&quot;Drama&quot;)) {<br>            return price * 1.5;<br>        }<br>        return price;<br>    }<br><br>    // getters and setters<br>}</pre><p>The abstract class cannot be instanciated. It ends up becoming a model. I create <em>Action</em> and <em>Drama</em> classes, which extend from <em>Movie</em> and which have the <em>calculatePrice</em> method implementation. Every time I need to calculate the price of a <em>Movie</em>, I instantiate an <em>Action</em> or <em>Drama</em> class and call the <em>calculatePrice</em> method. I don’t need to modify the <em>Movie</em> class all the time. Instead, I extended the class and added the behavior. It is much simpler to change the code and more organized. Every time I need to add a new category, I extend the class.</p><pre>abstract class Movie {<br>    Category category;<br>    double price;<br><br>    public abstract double calculatePrice();<br><br>    // getters and setters<br>}<br><br>class Action extends Movie {<br>    public double calculatePrice() {<br>        return price * 2;<br>    }<br>}<br><br>class Drama extends Movie {<br>    public double calculatePrice() {<br>        return price * 1.5;<br>    }<br>}</pre><h3>L — Liskov Substitution Principle</h3><p>Liskov comes from the name Barbara Liskov, who was the woman who created this idea. What is it for? The idea is that subclasses can be replaced by their parent classes. Every time a class extends from another class, you must be able to replace the child class with the parent class. This parent class can be used at any time in place of the child class. If it cannot be used, you are violating this principle.</p><p>In this example, we have our Movie class again, with <em>play</em> and <em>increaseVolume</em> methods. And we created two movies: <em>TheLionKing</em> and <em>ModernTimes</em>. The first is a very famous movie, surely you know it. The second film is an old Charlie Chaplin film from the year 1936. This was a time when films were usually silent, so this film had no sound. So maybe you already realized what the problem is: How are we going to increase the volume of a movie that has no sound? That is, how will the <em>ModernTimes</em> class implement the <em>increaseVolume</em> method? In these cases, developers usually leave the method blank, add a comment or throw an exception, which is what I did.</p><pre>class Movie {<br>    public void play() {}<br>    public void increaseVolume() {}<br>}<br><br>class TheLionKing extends Movie {}<br><br>class ModernTimes extends Movie {<br>    @Override<br>    public void increaseVolume() {<br>        throw new UnsupportedOperationException(&quot;This movie is silent&quot;);<br>    }<br>}</pre><p>Although <em>TheLionKing</em> and <em>ModernTimes</em> are movies, they both implement the <em>increaseVolume</em> method, but only <em>TheLionKing</em> can use it. This is because <em>ModernTimes</em> looks like a movie, has images like a movie, and shows scenes like a movie, but in the current context, all movies have volume. But <em>ModernTimes</em> is silent and cannot extend from the <em>Movie</em> class because the <em>increaseVolume</em> method will not work. This error is difficult to detect because, as we see in the image below, we can replace both child classes with the parent class without generating any compilation errors since both classes follow the Object-Oriented polymorphism rule, which is to extend from the same class. However, when trying to execute the method <em>increaseVolume</em> of the <em>ModernTimes</em> class, we will have an error at runtime or, in cases where the method is blank, a logic problem, as we expect something to happen, but nothing happens. The next principle will help us solve this problem.</p><pre>public void watchMovies() {<br>    Movie movie;<br><br>    movie = new TheLionKing();<br>    playMovie(movie);<br><br>    movie = new ModernTimes();<br>    playMovie(movie); // It will not work<br>}<br><br>public void playMovie(Movie movie) {<br>    movie.play();<br>    movie.increaseVolume();<br>}</pre><h3>I — Interface Segregation Principle</h3><p>A class is not required to implement interfaces that it will not use. For example, we often have a class that implements an interface with several methods my class will need to implement. Now imagine that I need to implement only two of the three interface methods. In the other method, you will put a comment, leave it blank, or throw an exception. And that’s the problem. So, you should only implement interfaces that your class will use. So if you have an interface with a method you’re not going to use, you create a new one with just that method. That is, you segregate this interface.</p><p>In the example below, we can see an example very similar to the previous principle. The <em>ModernTimes</em> class needs to implement the <em>increaseVolume</em> method, even if the method is not used. However, the <em>ModernTimes</em> class shouldn’t be forced to implement a method that it won’t use just to be able to implement the interface. So to solve this problem, let’s segregate the interface by moving the <em>increaseVolume</em> method somewhere else.</p><pre>interface Movie {<br>    void play();<br>    void increaseVolume();<br>}<br><br>class TheLionKing implements Movie {<br>    @Override public void play() {}<br>    @Override public void increaseVolume() {}<br>}<br><br>class ModernTimes implements Movie {<br>    @Override public void play() {}<br>    @Override public void increaseVolume() {<br>        // method not used<br>    }<br>}</pre><p>The <em>Movie</em> interface was divided into two interfaces, creating a new <em>AudioControl</em> interface with only the <em>increaseVolume</em> method. Now <em>TheLionKing</em> class can extend from both <em>Movie</em> and <em>AudioControl</em> interfaces and implement <em>play</em> and <em>increaseVolume</em> methods. And the <em>ModernTimes</em> class only extends from the <em>Movie</em> interface and implements only the <em>play</em> method. That is, now it is no longer required to implement the <em>increaseVolume</em> method. Now classes only implement the methods they are going to use.</p><pre>interface Movie {<br>    void play();<br>}<br><br>interface AudioControl {<br>    void increaseVolume();<br>}<br><br>class TheLionKing implements Movie, AudioControl {<br>    @Override public void play() {}<br>    @Override public void increaseVolume() {}<br>}<br><br>class ModernTimes implements Movie {<br>    @Override public void play() {}<br>}</pre><h3><strong>Dependency Inversion Principle</strong></h3><p>This principle says that we should depend on abstractions and not on implementations. When we talk about implementation, we are talking about a concrete class when you use the new word to create an object from the class. The abstraction is a model of our class. So, we must depend on a model, which can be an interface or an abstract class that cannot be instantiated.</p><p>Looking at the code below, it seems nothing is wrong at first glance. I have the <em>Movie</em> class, and it has the <em>DramaCategory</em> class. The problem is that the <em>DramaCategory</em> class specifically implements a drama-type category. So the <em>Movie</em> class can only have drama types. So if I create another category like Action or Comedy, it won’t work. This creates a tight coupling, and it’s right for the <em>Movie</em> class to use the <em>Category</em> class, not the other way around. So we must invert how this dependency works and remove this specific <em>DramaCategory</em> implementation.</p><pre>class DramaCategory {}<br><br>class Movie {<br>    String name;<br>    DramaCategory category;<br><br>    public DramaCategory getCategory() {<br>        return category;<br>    }<br><br>    public void setCategory(DramaCategory category) {<br>        this.category = category;<br>    }<br><br>    // getters and setters<br>}</pre><p>So what we did was create a <em>Category</em> interface, and I have the <em>DramaCategory</em> class implement that interface. Now I add this to my constructor, signaling the calling method that I depend on a category type and that it needs to provide me with an implementation. Now the calling method is responsible for providing that dependency, and I can work with any category that implements the interface. If I want to add the <em>ActionCategory</em>, I implement the <em>Category</em> interface and provide this class when I’m instantiating the <em>Movie</em> class. So now the control is inverted because I need to pass my dependency when creating my object.</p><pre>public void watchMovies() {<br>    Movie dramaMovie = new Movie(&quot;The Godfather&quot;, new DramaCategory());<br>    Movie actionMovie = new Movie(&quot;The Rock&quot;, new ActionCategory());<br>}<br><br>interface Category {}<br>class DramaCategory implements Category {}<br>class ActionCategory implements Category {}<br><br>class Movie {<br>    String name;<br>    Category category;<br><br>    public Movie(String name, Category category) {<br>        this.name = name;<br>        this.category = category;<br>    }<br><br>    // getters and setters<br>}</pre><h3><strong>Summary</strong></h3><p>See the summary below on each of the principles:</p><p><strong>Single Responsibility Principle</strong></p><p>Problem: A class should have only one responsibility.</p><p>Solution: Move to other classes the methods that don’t fit.</p><p><strong>Open Closed Principle</strong></p><p>Problem: Every class has to be open for extension and closed for modification.</p><p>Solution: Extend the behavior without changing the parent class.</p><p><strong>Liskov Substitution Principle</strong></p><p>Problem: Subclasses must be replaceable by their parent classes.</p><p>Solution: Don’t implement methods you’re not going to use.</p><p><strong>Interface Segregation Principle</strong></p><p>Problem: A class should not implement methods that will not be used.</p><p>Solution: Move unused methods to a new interface.</p><p><strong>Dependency Inversion Principle</strong></p><p>Problem: Rely on abstractions, not implementations.</p><p>Solution: Invert dependencies, receiving an abstraction in the constructor</p><h3>Conclusion</h3><p>Developing software is expensive, and if we are not careful, it can become a nightmare for the company, even causing money losses. And indeed, most projects fail because of the high maintenance cost. So to reduce this cost and have maintainable software, we need to think about a good software architecture. SOLID is a good start to having a well-defined architecture. By applying its principles, you will have software that is easy to maintain and will allow it to keep up with the evolution of the business.</p><h3>References</h3><p>Free images. <a href="https://www.pexels.com/">https://www.pexels.com</a>. Accessed February 2023.</p><p>The S.O.L.I.D Principles in Pictures. <a href="https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898">https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898</a>. Accessed February 2023.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=78adccc66519" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>