<?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: Matheus Schreiber</title>
    <description>The latest articles on DEV Community by Matheus Schreiber (@matheusschreiber).</description>
    <link>https://dev.to/matheusschreiber</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%2F1956520%2F3d6b49ef-0a90-49bb-9d4f-c70504e09cad.png</url>
      <title>DEV Community: Matheus Schreiber</title>
      <link>https://dev.to/matheusschreiber</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/matheusschreiber"/>
    <language>en</language>
    <item>
      <title>From Messy to SOLID: First Steps Towards Clean Architecture</title>
      <dc:creator>Matheus Schreiber</dc:creator>
      <pubDate>Mon, 30 Jun 2025 01:04:21 +0000</pubDate>
      <link>https://dev.to/matheusschreiber/from-messy-to-solid-first-steps-towards-clean-architecture-42d6</link>
      <guid>https://dev.to/matheusschreiber/from-messy-to-solid-first-steps-towards-clean-architecture-42d6</guid>
      <description>&lt;h2&gt;
  
  
  Quick intro
&lt;/h2&gt;

&lt;p&gt;Hi, I'm Matheus. I'm fairly new to the SOLID principles of object-oriented design (you could say I recently joined the cult of clean code after watching a video about it 🤪). This post is a short case study of how I applied some SOLID ideas to improve a messy view function in one of my personal projects.&lt;/p&gt;

&lt;p&gt;This is a short scenario study about my approach to a certain problematic involving SOLID principles, so stick until the end to judge my solution and also comment if you find a better one. &lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;To give some context, I’ll use an application I'm currently building as an example. This app is a web-based guessing game. Each level shows an image, and the user must guess the location it represents.&lt;/p&gt;

&lt;p&gt;Before I jump right into the problem, here’s a summary of the SOLID principles using (check out &lt;a href="https://www.digitalocean.com/community/conceptual-articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design#dependency-inversion-principle" rel="noopener noreferrer"&gt;this BEAUTIFUL article&lt;/a&gt; for a deeper dive).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;S&lt;/code&gt;&lt;/strong&gt; – Single Responsibility: an entity has to deal with one, and only one, responsibility, it shouldn't do multiple tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;O&lt;/code&gt;&lt;/strong&gt; – Open/Closed: you should be able to extend an entity with new stuff, without modifying what already exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;L&lt;/code&gt;&lt;/strong&gt; – Liskov Substitution: extended entities should act just like their parent when needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;I&lt;/code&gt;&lt;/strong&gt; – Interface Segregation: each entity can have its own interface, to utilize only the variables it really needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;D&lt;/code&gt;&lt;/strong&gt; – Dependency Inversion: entities depend on abstractions between them, not knowing exactly how one thing is done, just doing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was I doing wrong
&lt;/h2&gt;

&lt;p&gt;So, back to my app, I had a function-based view that was handling (already a red flag) a lot of things at the same time. It was generating a random level while checking if the user who made the request doesn't already have an open session and if not it creates a new session.&lt;/p&gt;

&lt;p&gt;Basically I had:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@api_view&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nd"&gt;@permission_classes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;IsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getRandomLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="c1"&gt;# checking if the run has been passed as a parameter
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

        &lt;span class="c1"&gt;# 1- do stuff to create a new session
&lt;/span&gt;        &lt;span class="c1"&gt;# 2- append a level to the session
&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

        &lt;span class="c1"&gt;# 1- fetch the open session
&lt;/span&gt;        &lt;span class="c1"&gt;# 2- check for a real run
&lt;/span&gt;        &lt;span class="c1"&gt;# 3- check for a valid run (not already finished)
&lt;/span&gt;        &lt;span class="c1"&gt;# 4- append a level to the session 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I will not show the entire code here for the sake of brevity, but there's a specific part I want to comment about. &lt;/p&gt;

&lt;p&gt;When the request is called with a &lt;code&gt;pk&lt;/code&gt; parameter, we need to check if thats a real &lt;code&gt;Run&lt;/code&gt;. So in this bit of code I handle the run existence check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="c1"&gt;# [...]
&lt;/span&gt;
    &lt;span class="n"&gt;current_run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;levels_left&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Run finished&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_301_MOVED_PERMANENTLY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# [...] a lot of code here
&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DoesNotExist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid run&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_400_BAD_REQUEST&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The refactor
&lt;/h2&gt;

&lt;p&gt;Now, can you identify (among other problems) which SOLID principles is this code violating? Heres a quick breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Right away you can tell that this view is handling a lot of logic (or responsibilities) that it really shouldn't. This breaks the Single Responsibility Principle, the view should only do one thing and one thing only, which is generate the next random level.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The error handling has two possibilities, one at the &lt;code&gt;try/except&lt;/code&gt; wrapper and the other in the middle of the logic. This complicates extension and violates the Open/Closed Principle when new exceptions are required in the future.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So with that in mind, we can move to the refactored bit and take a look at my choices to solve these problems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
    &lt;span class="c1"&gt;# [...]
&lt;/span&gt;
    &lt;span class="c1"&gt;# creating a processor to handle it properly
&lt;/span&gt;    &lt;span class="n"&gt;run_processor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RunProcessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

    &lt;span class="c1"&gt;# handling one exception
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;run_processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_valid_run&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; 
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid Run&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_400_BAD_REQUEST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# handling the other exception
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;run_processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_finished_run&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; 
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Run has finished&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_301_MOVED_PERMANENTLY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# [...]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key changes that I need to highlight:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Removal of try-except wrapper. This makes the code a lot &lt;strong&gt;easier&lt;/strong&gt; to read.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Delegation of the responsibility to check the run to a separate processor (Single Responsibility Principle).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Addition of separate method for each error handling allowing easy implementation of new checks in the future like run_processor.is_user_banned() (Open/Closed Principle).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The other SOLID principles like Liskov Substitution, Interface Segregation, and Dependency Inversion aren’t directly relevant here yet, since I'm only working with a single class and not a full inheritance chain or interface architecture. That said, as the app grows, these principles may become more applicable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This small refactor might seem simple, but for me it marked a shift in mindset. Instead of just getting code to work, I started thinking about how to make it clean, maintainable, and extendable. Applying the SOLID principles — even just SRP and OCP in this case — helped me break apart tangled logic and structure my code with more intention.&lt;/p&gt;

&lt;p&gt;I’m still learning, and I know there’s plenty of room for improvement. But this was a solid (pun intended) first step toward better architecture in my projects. If you’ve got feedback, questions, or even a better way to tackle the same problem, I’d love to hear from you!&lt;/p&gt;

&lt;p&gt;Let’s keep writing code that future-us won’t hate. 🚀&lt;/p&gt;

</description>
      <category>cleancoding</category>
      <category>beginners</category>
      <category>solidprinciples</category>
      <category>refactoring</category>
    </item>
  </channel>
</rss>
