<?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: Michael Seymour</title>
    <description>The latest articles on DEV Community by Michael Seymour (@seymour).</description>
    <link>https://dev.to/seymour</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%2F186983%2Fd2c849cd-d020-456f-805f-ee8e6bb1c6a5.jpeg</url>
      <title>DEV Community: Michael Seymour</title>
      <link>https://dev.to/seymour</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/seymour"/>
    <language>en</language>
    <item>
      <title>Why Are There So Few Women Programmers?</title>
      <dc:creator>Michael Seymour</dc:creator>
      <pubDate>Tue, 27 Sep 2022 10:48:29 +0000</pubDate>
      <link>https://dev.to/seymour/why-are-there-so-few-women-programmers-ejo</link>
      <guid>https://dev.to/seymour/why-are-there-so-few-women-programmers-ejo</guid>
      <description>&lt;p&gt;Only &lt;strong&gt;5%&lt;/strong&gt; of developers are women (source: &lt;a href="https://survey.stackoverflow.co/2022/#section-demographics-gender"&gt;StackOverflow Developer Survey 2022&lt;/a&gt;). Someone recently asked me why there's so few women in tech. "It’s not a physically demanding job so why not?" he said.&lt;/p&gt;

&lt;p&gt;I didn't really have a good answer to explain it, so I had a look around on the internet and made a summary of the top reasons I could find.&lt;/p&gt;

&lt;p&gt;I tried keeping the article succinct and easy to read so excuse the surface-level analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stereotypes
&lt;/h2&gt;

&lt;p&gt;How your parents, teachers, media etc. treat you while you’re growing up influences your career choice. Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a friend has a broken computer, a parent might tell their daughter to 'stay away and let the man do it'&lt;/li&gt;
&lt;li&gt;A parent might buy toy cars, guns, legos etc. for a boy which are much more related to programming/engineering than barbies, cooking toys, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Women Don’t Want to Join a Male-Dominated Career
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;There are so few women programmers because there are so few women programmers to begin with.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Being in a career dominated by the opposite sex can have it’s problems, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Greater chance of facing sexist comments, harassment etc.&lt;/li&gt;
&lt;li&gt;Being singled out or getting special treatment&lt;/li&gt;
&lt;li&gt;Masculine terms being used by default&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lack of Role Models
&lt;/h2&gt;

&lt;p&gt;Having role models are important. If a girl has an interest in programming but doesn’t see any other girl programmers, she might see that as a red flag and pursue another interest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Controversial Reason: Biological Differences
&lt;/h2&gt;

&lt;p&gt;This is a very controversial reason made popular by &lt;a href="https://twitter.com/jamesadamore"&gt;James Damore&lt;/a&gt; who got fired from Google for writing a memo suggesting this. &lt;/p&gt;

&lt;p&gt;I’m just mentioning it for the sake of completeness but note that none of his theories have been scientifically proven. The gist is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The brains of men and women are wired up differently which could explain some of the stereotypical differences in male and female behavior.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;I've turned this post into a TikTok video which you can view on &lt;a href="https://www.tiktok.com/@thatmichaelseymour"&gt;my account&lt;/a&gt; here if you'd like:&lt;br&gt;
&lt;a href="https://www.tiktok.com/@thatmichaelseymour/video/7148008782050692357"&gt;Why are there so few women software developers?&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Salary Progression: $4k to $150k per year</title>
      <dc:creator>Michael Seymour</dc:creator>
      <pubDate>Fri, 23 Sep 2022 09:22:59 +0000</pubDate>
      <link>https://dev.to/seymour/salary-progression-4k-to-150k-per-year-48i5</link>
      <guid>https://dev.to/seymour/salary-progression-4k-to-150k-per-year-48i5</guid>
      <description>&lt;p&gt;How a software developer went from $4k/year to $150k/year in 8 years:&lt;br&gt;
&lt;/p&gt;
&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--11eizI_A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1573239110508204033/pu/img/Ba4HDwAeZ8JQzhj_.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--QT8V6mvQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1143593357773549570/h6vqnBJs_normal.png" alt="Michael profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Michael
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @mikeseym
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      How a software developer went from $4k/year to $150k/year in 8 years 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      09:13 AM - 23 Sep 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1573239225411059712" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1573239225411059712" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1573239225411059712" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


</description>
      <category>webdev</category>
      <category>career</category>
      <category>startup</category>
    </item>
    <item>
      <title>The Ultimate Guide to Reverting Git Merges</title>
      <dc:creator>Michael Seymour</dc:creator>
      <pubDate>Sun, 08 May 2022 15:20:33 +0000</pubDate>
      <link>https://dev.to/seymour/the-ultimate-guide-to-reverting-git-merges-abi</link>
      <guid>https://dev.to/seymour/the-ultimate-guide-to-reverting-git-merges-abi</guid>
      <description>&lt;h3&gt;
  
  
  How to Undo an Unpushed Merge
&lt;/h3&gt;

&lt;p&gt;If you’ve done a merge and haven’t pushed it yet, undoing the merge is very simple.&lt;/p&gt;

&lt;p&gt;Use the &lt;code&gt;git reset&lt;/code&gt; command to return to the revision before the merge, thereby effectively undoing it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git reset --hard &amp;lt;commit-hash-before-merge&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't have the hash of the commit before the merge at hand, you can use &lt;code&gt;git log&lt;/code&gt; to find it out or you can use the following variation of the reset command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git reset --hard HEAD~1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, using &lt;code&gt;HEAD~1&lt;/code&gt;, you're telling git to go back to the commit before the current &lt;code&gt;HEAD&lt;/code&gt; revision, which should be the commit before the merge.&lt;/p&gt;

&lt;p&gt;Note: In both cases, we need to use the &lt;code&gt;--hard&lt;/code&gt; option. This means that any local uncommitted changes will be discarded - if you have valuable uncommitted changes, be sure to use git stash before.&lt;/p&gt;

&lt;p&gt;After doing the above &lt;code&gt;git reset&lt;/code&gt;, you’ll notice that any changes from the merge will be undone and you can continue working as normal.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Undo a Pushed Merge
&lt;/h3&gt;

&lt;p&gt;Undoing a pushed merge is a bit more complicated. Before getting to it, we need to learn a bit more about commits and git merges.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is a commit parent?
&lt;/h4&gt;

&lt;p&gt;Every commit has a parent commit. When you &lt;code&gt;git commit&lt;/code&gt; normally, the current commit becomes the parent commit of the new commit that you’re creating.&lt;/p&gt;

&lt;p&gt;To view the parent of a commit, use &lt;code&gt;git show --pretty=raw &amp;lt;commit-hash&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is a merge commit?
&lt;/h4&gt;

&lt;p&gt;When a branch named &lt;code&gt;feature&lt;/code&gt; is merged with &lt;code&gt;master&lt;/code&gt;, a new “merge commit” is created on the branch &lt;code&gt;master&lt;/code&gt;. A merge commit is the same as a normal commit except that it has 2 parents. In this case, the 2 parents of the merge commit will be the previous head of &lt;code&gt;master&lt;/code&gt; and the head of &lt;code&gt;feature&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fjcdbl2etdovobtcac4yu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fjcdbl2etdovobtcac4yu.png" alt="git merge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On running &lt;code&gt;git show&lt;/code&gt;, the new commit displays both the parents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git show

commit ae2058cf5cafe807af44114d15bac65fc4efd714 (HEAD -&amp;gt; master)
Merge: bf75d61d8f1 12d62bfa0e0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  How does git revert work?
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git revert &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The revert command in git takes in a commit hash and compares the changes with the parent. The delta or the diff is calculated and the negation of it is applied as a new commit.&lt;/p&gt;

&lt;p&gt;What happens if we want to revert a merge commit? The merge commit has 2 parents and git won’t know automatically which parent was the mainline, and which parent was the branch you want to unmerge.&lt;/p&gt;

&lt;h4&gt;
  
  
  Reverting a merge commit
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git revert -m 1 &amp;lt;merge-commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a closer look at what this command will do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git revert&lt;/code&gt; will make sure that a new commit is created to revert the effects of that unwanted merge. &lt;/li&gt;
&lt;li&gt;The &lt;code&gt;-m 1&lt;/code&gt; option tells git that we want to keep the parent side of the merge (which is the branch we had merged into).&lt;/li&gt;
&lt;li&gt;Finally, make sure to specify the actual merge commit's hash.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;-m&lt;/code&gt; option specifies the parent number. This is because a merge commit has more than one parent, and git does not know automatically which parent was the mainline, and which parent was the branch you want to unmerge.&lt;/p&gt;

&lt;p&gt;When you view a merge commit in the output of &lt;code&gt;git log&lt;/code&gt;, you will see its parents listed on the line that begins with &lt;code&gt;Merge:&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;commit ae2058cf5cafe807af44114d15bac65fc4efd714
Merge: bf75d61d8f1 12d62bfa0e0
Author: Michael Seymour &amp;lt;michael@example.com&amp;gt;
Date:   Sun May 08 13:52:29 2022 +0100

Merge branch 'my-branch'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this situation, &lt;code&gt;git revert ae2058cf5ca -m 1&lt;/code&gt; will get you the tree as it was in &lt;code&gt;bf75d61d8f1&lt;/code&gt;, and &lt;code&gt;git revert -m 2&lt;/code&gt; will reinstate the tree as it was in &lt;code&gt;12d62bfa0e0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fu1em9qa94qgqppjnqpu2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fu1em9qa94qgqppjnqpu2.png" alt="git revert 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fxwq00nfh4bba0pbrmvt9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fxwq00nfh4bba0pbrmvt9.png" alt="git revert 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To better understand the parent commits, you can run:&lt;br&gt;
&lt;code&gt;git log bf75d61d8f1&lt;/code&gt; or &lt;code&gt;git log 12d62bfa0e0&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Why can’t we use git reset this time?
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;git revert&lt;/code&gt; will make sure that a new commit is created to revert the effects of that unwanted merge. This is in contrast to &lt;code&gt;git reset&lt;/code&gt;, where we effectively "remove" a commit from the history. Hence, &lt;code&gt;git revert&lt;/code&gt; is a better solution in cases where you've already pushed to remote as altering the history of the remote repo can cause problems for the other developers using the repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.git-tower.com/learn/git/faq/undo-git-merge" rel="noopener noreferrer"&gt;https://www.git-tower.com/learn/git/faq/undo-git-merge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/q/7099833" rel="noopener noreferrer"&gt;https://stackoverflow.com/q/7099833&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://levelup.gitconnected.com/reverting-a-merge-commit-7de2e9114c7d" rel="noopener noreferrer"&gt;https://levelup.gitconnected.com/reverting-a-merge-commit-7de2e9114c7d&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-school.github.io/visualizing-git/#free" rel="noopener noreferrer"&gt;https://git-school.github.io/visualizing-git/#free&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>The SOLID principles of Object Oriented Design</title>
      <dc:creator>Michael Seymour</dc:creator>
      <pubDate>Tue, 10 Nov 2020 00:51:21 +0000</pubDate>
      <link>https://dev.to/seymour/the-solid-principles-of-object-oriented-design-53ho</link>
      <guid>https://dev.to/seymour/the-solid-principles-of-object-oriented-design-53ho</guid>
      <description>&lt;h3&gt;
  
  
  What is SOLID?
&lt;/h3&gt;

&lt;p&gt;SOLID helps you to write code that is easy to maintain, extend and understand.&lt;/p&gt;

&lt;p&gt;It is an acronym for the following 5 principles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S = Single-responsibility principle
O = Open-closed principle
L = Liskov substitution principle
I = Interface segregation principle
D = Dependency inversion principle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Single-responsibility principle
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A class/module should only be responsible for one thing.&lt;/li&gt;
&lt;li&gt;A class/module should have only one reason to be changed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example that violates this principle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Database&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"INSERT INTO..."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeAllText&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/var/log/error.log"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Customer&lt;/code&gt; class is responsible for both writing to the database and writing to the logfile.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If we want to change the way we log errors, &lt;code&gt;Customer&lt;/code&gt; needs to change.&lt;/li&gt;
&lt;li&gt;If we want to change the way we write to the DB, &lt;code&gt;Customer&lt;/code&gt; needs to change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This code should be refactored to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;FileLogger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileLogger&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Database&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"INSERT INTO..."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileLogger&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeAllText&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/var/log/error.log"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some other examples where you'd need separate classes are: user input validation, authentication, caching.&lt;/p&gt;

&lt;p&gt;Be careful not to over-fragment code (creating too many responsibilities). Remember the whole point of SOLID is to make your code easier to maintain.&lt;/p&gt;

&lt;p&gt;Further reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.ndepend.com/solid-design-the-single-responsibility-principle-srp"&gt;NDepend&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Open-closed principle
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Classes/modules should be open for extension but closed for modification.&lt;/li&gt;
&lt;li&gt;Rather extend functionality by adding new code instead of changing existing code.&lt;/li&gt;
&lt;li&gt;The goal is to get to a point where you can never break the core of your system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example that violates this principle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Payment&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getType&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;eq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"credit"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;payWithCreditCard&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;payWithPaypal&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;payWithCreditCard&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// logic for paying with credit card&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;payWithPaypal&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// logic for paying with paypal&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What if we wanted to add a new payment method? We would have to modify the &lt;code&gt;Payment&lt;/code&gt; class, which violates the open-closed principle.&lt;/p&gt;

&lt;p&gt;This code should be refactored to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;PaymentFactory&lt;/span&gt; &lt;span class="n"&gt;paymentFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaymentFactory&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paymentFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initialisePayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getType&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//-----------------------&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentFactory&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt; &lt;span class="nf"&gt;intialisePayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;eq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"credit"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CreditCardPayment&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="n"&gt;elseif&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;eq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"paypal"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PaypalPayment&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="n"&gt;elseif&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;eq&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wire"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WirePayment&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unsupported payment method"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//-----------------------&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreditCardPayment&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// logic for paying with credit card&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaypalPayment&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// logic for paying with paypal&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WirePayment&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// logic for paying with wire&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can add new payment methods by adding new classes, instead of modifying existing classes.&lt;/p&gt;

&lt;p&gt;Further reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.ndepend.com/solid-design-the-open-close-principle-ocp"&gt;NDepend&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Liskov substitution principle
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If a class implements an interface, it must be able to substitute any reference that implements that same interface.&lt;/li&gt;
&lt;li&gt;e.g. if a class called &lt;code&gt;MySQL&lt;/code&gt; implements &lt;code&gt;Database&lt;/code&gt;, and another class called &lt;code&gt;MongoDB&lt;/code&gt; implements &lt;code&gt;Database&lt;/code&gt;, you should be able to substitute &lt;code&gt;MySQL&lt;/code&gt; objects for &lt;code&gt;MongoDB&lt;/code&gt; objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example that violates this principle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Fly&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Parrot&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;override&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Fly&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// logic for flying&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ostrich&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;override&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Fly&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;// Can't implement as ostriches can't fly&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above is a bad design as &lt;code&gt;Bird&lt;/code&gt; assumes all birds can fly.&lt;/p&gt;

&lt;p&gt;This code could then be refactored to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlyingBird&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Fly&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Parrot&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlyingBird&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;override&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Fly&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// logic for flying&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ostrich&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gist of this principle is to be careful when using polymorphism and inheritance.&lt;/p&gt;

&lt;p&gt;Here is another, more real-world encounter of this principle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a class called &lt;code&gt;BankAccount&lt;/code&gt; with a &lt;code&gt;withdrawal()&lt;/code&gt; method. Do all bank accounts allow withdrawals? A fixed deposit account won't allow withdrawals, for example.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Further reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.ndepend.com/solid-design-the-liskov-substitution-principle"&gt;NDepend&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Interface segregation principle
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No client should be forced to depend on methods it does not use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example that violates this principle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Athlete&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;compete&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swim&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;highJump&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;longJump&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JohnDoe&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Athlete&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;compete&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John Doe started competing"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swim&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John Doe started swimming"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;highJump&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;longJump&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;JohnDoe&lt;/code&gt; is just a swimmer, but is forced to implement methods like &lt;code&gt;highJump&lt;/code&gt; and &lt;code&gt;longJump&lt;/code&gt; that he'll never use.&lt;/p&gt;

&lt;p&gt;This code could then be refactored to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Athlete&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;compete&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;SwimmingAthlete&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Athlete&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swim&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;JumpingAthlete&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Athlete&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;highJump&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;longJump&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JohnDoe&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;SwimmingAthlete&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;compete&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John Doe started competing"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;swim&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John Doe started swimming"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, &lt;code&gt;JohnDoe&lt;/code&gt; does not have to implement actions that he is not capable of performing.&lt;/p&gt;

&lt;p&gt;Further reading: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.ndepend.com/solid-design-the-interface-segregation-principle-isp"&gt;NDepend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dzone.com/articles/solid-principles-interface-segregation-principle"&gt;DZone&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dependency inversion principle
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;High-level modules should not depend on low-level modules. They should depend on abstractions.&lt;/li&gt;
&lt;li&gt;This allows you to change an implementation easily without altering the high level code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example that violates this principle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BackEndDeveloper&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;writeJava&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FrontEndDeveloper&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;writeJavascript&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Project&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;BackEndDeveloper&lt;/span&gt; &lt;span class="n"&gt;backEndDeveloper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BackEndDeveloper&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;FrontEndDeveloper&lt;/span&gt; &lt;span class="n"&gt;frontEndDeveloper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FrontEndDeveloper&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;implement&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;backEndDeveloper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeJava&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;frontEndDeveloper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeJavascript&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Project&lt;/code&gt; class is a high-level module, and it depends on low-level modules such as &lt;code&gt;BackEndDeveloper&lt;/code&gt; and &lt;code&gt;FrontEndDeveloper&lt;/code&gt;. This violates the principle.&lt;/p&gt;

&lt;p&gt;This code should be refactored to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Developer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;develop&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BackEndDeveloper&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Developer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;develop&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;writeJava&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;writeJava&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FrontEndDeveloper&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Developer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;develop&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;writeJavascript&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;writeJavascript&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//-----------------------&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Project&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Developer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Project&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Developer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;developers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;implement&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;developers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;develop&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the &lt;code&gt;Project&lt;/code&gt; class does not depend on lower level modules, but rather abstractions.&lt;/p&gt;

&lt;p&gt;Further reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.ndepend.com/solid-design-the-dependency-inversion-principle-dip"&gt;NDepend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dzone.com/articles/solid-principles-dependency-inversion-principle"&gt;DZone&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Final note: Don't be too strict with SOLID principles
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SOLID design principles are principles, not rules.&lt;/li&gt;
&lt;li&gt;Always use common sense when applying SOLID (know your trade-offs).&lt;/li&gt;
&lt;li&gt;Usually with SOLID, it requires more time writing code, so you can spend less time reading it later.&lt;/li&gt;
&lt;li&gt;Finally, remember to use SOLID as a tool, not as a goal.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>oop</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Types of NoSQL Databases</title>
      <dc:creator>Michael Seymour</dc:creator>
      <pubDate>Thu, 05 Nov 2020 22:19:09 +0000</pubDate>
      <link>https://dev.to/seymour/types-of-nosql-databases-2oin</link>
      <guid>https://dev.to/seymour/types-of-nosql-databases-2oin</guid>
      <description>&lt;h3&gt;
  
  
  Why do we need this blog post?
&lt;/h3&gt;

&lt;p&gt;Most people have only had experience with relational databases but there are many other types of databases, each with their own pros and cons, that developers should know when to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why are relational databases most popular?
&lt;/h3&gt;

&lt;p&gt;The theory behind non-relational databases has been around since the 1970's, but back then, storage was extremely expensive. Thus, database types that optimised for storage space, such as relational databases, are the ones that became popular. Relational databases store &lt;a href="https://en.wikipedia.org/wiki/Database_normalization"&gt;normalised data&lt;/a&gt;, meaning no redundant data is stored. Databases that weren't normalised were not financially viable at the time. In the 80-90s, people kept using relational databases and then in the 2000's, NoSQL databases started popping up because we were no longer constrained by storage, but rather, the main bottleneck now is compute. However, despite this rise in popularity, relational databases are still used the most today. This is most likely because people already have a lot of experience with them, it is often the type of database that developers first learn to use and also because many apps are already built with relational databases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Types of databases
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Relational
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;Stores data in one or more tables of columns and rows, with a unique key identifying each row.&lt;/li&gt;
&lt;li&gt;Supports &lt;a href="https://en.wikipedia.org/wiki/Referential_integrity"&gt;referential integrity&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Supports &lt;a href="https://en.wikipedia.org/wiki/ACID"&gt;ACID transactions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Strict schema enforcement (&lt;a href="https://www.delltechnologies.com/en-us/blog/schema-read-vs-schema-write-started/"&gt;schema-on-write&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Queried using SQL&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Examples

&lt;ul&gt;
&lt;li&gt;MySQL, MariaDB, PostgreSQL, Oracle, MSSQL&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pros

&lt;ul&gt;
&lt;li&gt;Data integrity is enforced&lt;/li&gt;
&lt;li&gt;Avoids data duplication&lt;/li&gt;
&lt;li&gt;ACID-compliant&lt;/li&gt;
&lt;li&gt;Well-documented, lots of tutorials and stackoverflow answers&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cons

&lt;ul&gt;
&lt;li&gt;Difficult to scale writes&lt;/li&gt;
&lt;li&gt;Has row locking&lt;/li&gt;
&lt;li&gt;Not designed to handle unstructured/semi-structured data&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Use cases

&lt;ul&gt;
&lt;li&gt;An ecommerce platform where you have users linked to orders linked to items etc., and many other use cases&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Key-value
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;Allows storing arbitrary data via a specific key&lt;/li&gt;
&lt;li&gt;Schemaless (values can be anything)&lt;/li&gt;
&lt;li&gt;It is effectively a dictionary/hash table stored on disk&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Examples

&lt;ul&gt;
&lt;li&gt;Amazon DynamoDB, RocksDB&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pros

&lt;ul&gt;
&lt;li&gt;Low latency reads &amp;amp; writes&lt;/li&gt;
&lt;li&gt;Scales easily and cheaply&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cons

&lt;ul&gt;
&lt;li&gt;Can only query/search by key&lt;/li&gt;
&lt;li&gt;No data integrity&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Use cases

&lt;ul&gt;
&lt;li&gt;Config data, url shortener etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  In-memory key-value
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;Same as key-value, but data is stored in memory (RAM)&lt;/li&gt;
&lt;li&gt;Can be configured to persist data, but not the primary focus&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Examples

&lt;ul&gt;
&lt;li&gt;Redis, memcached, Amazon ElastiCache&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pros

&lt;ul&gt;
&lt;li&gt;Extremely low latency&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cons

&lt;ul&gt;
&lt;li&gt;Can be hard to scale&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Use cases

&lt;ul&gt;
&lt;li&gt;Caching, leaderboards, real-time analytics, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Document (a.k.a. document-orientated)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;Similar to key-value, but value is a document&lt;/li&gt;
&lt;li&gt;MongoDB actually uses a key value store called WiredTiger as their default storage engine&lt;/li&gt;
&lt;li&gt;Documents are typically JSON, BSON, XML&lt;/li&gt;
&lt;li&gt;Schemaless&lt;/li&gt;
&lt;li&gt;Documents are stored in collections (not tables)&lt;/li&gt;
&lt;li&gt;Optimised more for speed and scalability rather than space&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Examples

&lt;ul&gt;
&lt;li&gt;MongoDB, DocumentDB, Couchbase, DynamoDB, Firebase&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pros

&lt;ul&gt;
&lt;li&gt;Fast writes&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;li&gt;Schemaless allows changing data structure without downtime&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cons

&lt;ul&gt;
&lt;li&gt;Not ACID compliant&lt;/li&gt;
&lt;li&gt;Relationships/cross references not enforced&lt;/li&gt;
&lt;li&gt;Can't join documents/collections in a single query&lt;/li&gt;
&lt;li&gt;Joins can be slow&lt;/li&gt;
&lt;li&gt;Data is usually duplicated&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Use cases

&lt;ul&gt;
&lt;li&gt;Storing user metadata, product inventory etc., and many other use cases&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Wide-column (a.k.a. column-orientated)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;Somewhere in between a document store and a relational DB&lt;/li&gt;
&lt;li&gt;Uses tables, columns, rows etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Examples

&lt;ul&gt;
&lt;li&gt;Cassandra, Keyspaces (AWS), HBase, Bigtable&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pros

&lt;ul&gt;
&lt;li&gt;Same pros as a document db&lt;/li&gt;
&lt;li&gt;Can query/update individual columns&lt;/li&gt;
&lt;li&gt;More efficient aggregation operations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cons

&lt;ul&gt;
&lt;li&gt;Same cons as a document db&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Use cases

&lt;ul&gt;
&lt;li&gt;Storing events, messages etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Graph
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;Based on graph theory&lt;/li&gt;
&lt;li&gt;Data represented as network of nodes, edges and properties&lt;/li&gt;
&lt;li&gt;Data is stored in nodes (schemaless)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Examples

&lt;ul&gt;
&lt;li&gt;Neo4j, OrientDB, TitanDB, Neptune (AWS)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pros

&lt;ul&gt;
&lt;li&gt;Optimised for querying data with complex relations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cons

&lt;ul&gt;
&lt;li&gt;Difficult for developers to learn&lt;/li&gt;
&lt;li&gt;Poor performance of aggregation operations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Use cases

&lt;ul&gt;
&lt;li&gt;Social networks, recommendation engines, gps navigation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Search
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;Stores non-relational, document-based data&lt;/li&gt;
&lt;li&gt;Built to be able to index large volumes of full text (e.g. logs)&lt;/li&gt;
&lt;li&gt;Primary focus is on full text search and fuzzy matching&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Examples

&lt;ul&gt;
&lt;li&gt;Elasticsearch, Splunk, Apache Solr&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pros

&lt;ul&gt;
&lt;li&gt;Optimised full text searching&lt;/li&gt;
&lt;li&gt;Highly scalable&lt;/li&gt;
&lt;li&gt;Schemaless&lt;/li&gt;
&lt;li&gt;Other search options such as suggestions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cons

&lt;ul&gt;
&lt;li&gt;Expensive&lt;/li&gt;
&lt;li&gt;Low durability&lt;/li&gt;
&lt;li&gt;No transaction support&lt;/li&gt;
&lt;li&gt;Not efficient for writing/reading other than searching&lt;/li&gt;
&lt;li&gt;Can be difficult to manage&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Use cases

&lt;ul&gt;
&lt;li&gt;Search results on ecommerce website, searching logs, input form autosuggest&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Time series
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;Collect, store and process data sequenced by time&lt;/li&gt;
&lt;li&gt;Heavily write oriented&lt;/li&gt;
&lt;li&gt;Designed to handle constant streams of data&lt;/li&gt;
&lt;li&gt;Typically append-only (on modification after ingestion)&lt;/li&gt;
&lt;li&gt;Aggregation/down sampling features to lower archive data footprint&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Examples

&lt;ul&gt;
&lt;li&gt;InfluxDB, Prometheus, graphite, Timestream (AWS)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pros

&lt;ul&gt;
&lt;li&gt;Can handle high ingestion rates&lt;/li&gt;
&lt;li&gt;Optimised for time-based aggregation queries (mean, std dev, max etc.)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cons

&lt;ul&gt;
&lt;li&gt;Can only deal with time-series data&lt;/li&gt;
&lt;li&gt;Reads are a lot slower than writes&lt;/li&gt;
&lt;li&gt;Does not support transactions&lt;/li&gt;
&lt;li&gt;Append-only&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Use cases

&lt;ul&gt;
&lt;li&gt;IoT sensor collection, app metrics, log monitoring, alerting&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Ledger
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Characteristics

&lt;ul&gt;
&lt;li&gt;An immutable database&lt;/li&gt;
&lt;li&gt;If you try to update a value, it creates a new entry with a diff&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Examples

&lt;ul&gt;
&lt;li&gt;Amazon Quantum Ledger Database&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pros

&lt;ul&gt;
&lt;li&gt;Complete, immutable, and verifiable history of all changes to application data&lt;/li&gt;
&lt;li&gt;Also provides cryptographic mechanism to verify integrity of data&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cons

&lt;ul&gt;
&lt;li&gt;Can grow large in size&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Use cases

&lt;ul&gt;
&lt;li&gt;Highly regulated industries e.g. banking, systems of record, supply chain, healthcare, registrations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bonus Section! (hosting options)
&lt;/h3&gt;

&lt;p&gt;There are 3 database hosting options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On-premises

&lt;ul&gt;
&lt;li&gt;Database fully maintained by organization on servers running within their data centers&lt;/li&gt;
&lt;li&gt;More control, but usually more expensive and time consuming&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cloud hosted

&lt;ul&gt;
&lt;li&gt;Servers are maintained by cloud providers&lt;/li&gt;
&lt;li&gt;Organizations maintain database software and operating system running on the machine&lt;/li&gt;
&lt;li&gt;Flexible scaling and no server upkeep, but no control over physical server and potential network limitations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Serverless (database-as-a-service)

&lt;ul&gt;
&lt;li&gt;Database maintained by service provider&lt;/li&gt;
&lt;li&gt;Organizations only charged for usage of service (storage, bandwidth etc.)&lt;/li&gt;
&lt;li&gt;Can be cost effective&lt;/li&gt;
&lt;li&gt;Zero upkeep: database maintenance, patching, infrastructure support etc. is outsourced&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>database</category>
      <category>sql</category>
    </item>
    <item>
      <title>Video Call Bingo</title>
      <dc:creator>Michael Seymour</dc:creator>
      <pubDate>Fri, 27 Mar 2020 22:03:57 +0000</pubDate>
      <link>https://dev.to/seymour/video-call-bingo-106g</link>
      <guid>https://dev.to/seymour/video-call-bingo-106g</guid>
      <description>&lt;p&gt;This is a Bingo game that you can play with fellow colleagues/friends during video calls. Click on the squares to mark them as they occur during your video call. First player to mark 5 squares in a row (horizontally, vertically or diagonally) wins.&lt;/p&gt;

&lt;p&gt;It's just something quick I made now that I'm doing a lot more video calls while working from home.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bingo.seymour.co.za/"&gt;https://bingo.seymour.co.za/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EdADCuwB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3et97ljettdgqxje4s89.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EdADCuwB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3et97ljettdgqxje4s89.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>MySQL Schema Change Without Downtime</title>
      <dc:creator>Michael Seymour</dc:creator>
      <pubDate>Wed, 22 Jan 2020 20:12:53 +0000</pubDate>
      <link>https://dev.to/seymour/mysql-schema-change-without-downtime-378e</link>
      <guid>https://dev.to/seymour/mysql-schema-change-without-downtime-378e</guid>
      <description>&lt;p&gt;When altering large MySQL tables (&amp;gt; 200MB) it can block reads or writes for a long time. In this post, I'll explain how to alter a large table without any downtime.&lt;/p&gt;

&lt;p&gt;First, let's look at how MySQL does an &lt;code&gt;ALTER TABLE&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lock the table&lt;/li&gt;
&lt;li&gt;Make a copy of the table&lt;/li&gt;
&lt;li&gt;Modify the copy (the "new table")&lt;/li&gt;
&lt;li&gt;Copy all the rows into the new table&lt;/li&gt;
&lt;li&gt;Swap the old and new tables&lt;/li&gt;
&lt;li&gt;Unlock the table&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;How can we avoid the blocking (steps 1 &amp;amp; 6)? Here are some options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do it at 2am on Sunday morning

&lt;ul&gt;
&lt;li&gt;Problem: Not fun for developers, lowers developer productivity.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Do a planned failover (aka. "rolling schema upgrade")

&lt;ul&gt;
&lt;li&gt;Start with slaves and, once the schema change is applied to the slave, promote one of the slaves to the new master, demote the old master to a slave and execute the schema change on it.&lt;/li&gt;
&lt;li&gt;Problem: Can break replication for some schema changes, requires high availability infrastructure.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Make MySQL use row versioning

&lt;ul&gt;
&lt;li&gt;Tell MySQL this table has a new version of the schema. Then, you can still read from old row versions but when writing a new row, it writes in the new row format.&lt;/li&gt;
&lt;li&gt;Problem: MySQL still doesn't support row versioning.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Handle the &lt;code&gt;ALTER&lt;/code&gt; process yourself

&lt;ul&gt;
&lt;li&gt;Manually perform the same steps the server takes (without locking).&lt;/li&gt;
&lt;li&gt;Problems: discussed below&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last option is my preferred so I'll go ahead and explain that. You perform the &lt;code&gt;ALTER&lt;/code&gt; steps manually, with the following changes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;del&gt;Lock the table&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;Make a copy of the table&lt;/li&gt;
&lt;li&gt;Modify the copy (the "new table")&lt;/li&gt;
&lt;li&gt;Copy all the rows into the new table

&lt;ol&gt;
&lt;li&gt;Add triggers to keep track of changes&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Swap the old and new tables&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Unlock the table&lt;/del&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As we're not locking the table, your application can continue to read/write to the original table. It will take some time to copy rows to the new table, so we add triggers to the old table that update or insert corresponding rows in the new table.&lt;/p&gt;

&lt;p&gt;Some notes on the above process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remember to make backups before trying this&lt;/li&gt;
&lt;li&gt;Do multiple, smaller chunks of &lt;code&gt;INSERT..SELECT&lt;/code&gt; when copying data to the new table

&lt;ul&gt;
&lt;li&gt;Helps to avoid deadlocks&lt;/li&gt;
&lt;li&gt;Try make the chunks small enough so each one takes about 0.5s&lt;/li&gt;
&lt;li&gt;Start at the low-end of the primary key&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The triggers should only copy columns that are common between the 2 tables.&lt;/li&gt;
&lt;li&gt;To swap the old and new tables, we can atomically rename the old table to something else and the new table to the old table.

&lt;ul&gt;
&lt;li&gt;Don't forget to alter the foreign keys to point to the new table&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Problems with above process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's a lot slower than just letting MySQL handle the &lt;code&gt;ALTER&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The table you're altering can't have triggers already defined&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this post has helped if you find yourself altering some large tables. If you have any questions or corrections, you can message me &lt;a href="https://twitter.com/mikeseym"&gt;@mikeseym&lt;/a&gt; on twitter.&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>database</category>
    </item>
    <item>
      <title>Solving a MySQL Deadlock</title>
      <dc:creator>Michael Seymour</dc:creator>
      <pubDate>Mon, 13 Jan 2020 20:56:15 +0000</pubDate>
      <link>https://dev.to/seymour/solving-a-mysql-deadlock-bpm</link>
      <guid>https://dev.to/seymour/solving-a-mysql-deadlock-bpm</guid>
      <description>&lt;p&gt;A deadlock occurs when you have 2 processes that are both waiting on each other to release a lock on a resource.&lt;/p&gt;

&lt;p&gt;Imagine we have 2 threads in a Java application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Thread 1 acquires a lock on resource A&lt;/li&gt;
&lt;li&gt;Thread 2 acquires a lock on resource B&lt;/li&gt;
&lt;li&gt;In order to continue execution (and release the lock on resource A), Thread 1 waits until resource B is free&lt;/li&gt;
&lt;li&gt;In order to continue execution (and release the lock on resource B), Thread 2 waits until resource A is free&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither thread will ever finish execution, and our app has reached a deadlock.&lt;/p&gt;

&lt;p&gt;You can actually try this for yourself on a MySQL table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; CREATE TABLE a (id int primary key, value int);
Query OK, 0 rows affected (0.01 sec)

mysql&amp;gt; INSERT INTO a VALUES (1, 0), (2, 0), (3, 0), (4, 0);
Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql console 1:
step 1&amp;gt; START TRANSACTION;
step 3&amp;gt; UPDATE a SET value = 1 WHERE id = 2;
step 5&amp;gt; UPDATE a SET value = 1 WHERE id = 1;

mysql console 2:
step 2&amp;gt; START TRANSACTION;
step 4&amp;gt; UPDATE a SET value = 1 WHERE id = 1;
step 6&amp;gt; UPDATE a SET value = 1 WHERE id = 2;

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recently I was working on a multi-threaded application that had this problem. It was a Java application with 16 threads. Each thread would update a batch of 10 rows in a MySQL table every 1ms. When updating a row in MySQL, an exclusive lock is set on that particular row - blocking any other transaction from updating it. It didn't happen often, but on occasion 2 threads would be waiting on each other to release a row lock, causing a deadlock.&lt;/p&gt;

&lt;p&gt;I considered a few different solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restarting the transaction if a deadlock occured.Problem: I'd be updating my rows with stale data&lt;/li&gt;
&lt;li&gt;Restarting the entire process if a deadlock occured.Problem: This could potentially make the app a lot slower.&lt;/li&gt;
&lt;li&gt;Make each thread ‘claim' a row before trying to update it. If it's already claimed, find another row to update.Problem: This adds a lot of complexity to the app and slows down performance as well&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before continuing, I took a break and thought more about the cause of a deadlock. All threads were performing 10 updates each on the same MySQL table. The only way a deadlock could occur is if the order and timing matched a very particular pattern. I couldn't control the timing, but I could control the order of updates.&lt;/p&gt;

&lt;p&gt;In fact, if I ordered all updates in the same way (e.g. by ascending order of the row id), this would eliminate the possibility of a deadlock.&lt;/p&gt;

&lt;p&gt;But why are updates occuring in a random order anyway? It turns out the application fetches 100 rows from the database and picks 10 to update. However, in order to prevent the 16 threads from always updating the same 10 rows, it would shuffle the list of 100 rows first. This means that the 10 updates would always occur in some random order.&lt;/p&gt;

&lt;p&gt;I modified the application so that before updating the 10 rows, it would order the updates in ascending order of the row id. I deployed the app and that was the end of the deadlocks.&lt;/p&gt;

&lt;p&gt;Deadlocks can occur in many different ways, but in this case, the lesson learned is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're locking resources in a multi-threaded application, make sure all threads are locking in the same order (order based on an attribute of the resource).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In simpler terms:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're updating rows in a multi-threaded application, make sure all threads are updating the rows in order of the row id (ascending or descending).&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>deadlocks</category>
      <category>mysql</category>
      <category>multithreading</category>
      <category>java</category>
    </item>
  </channel>
</rss>
