{"id":1031,"date":"2018-06-26T19:16:29","date_gmt":"2018-06-27T00:16:29","guid":{"rendered":"http:\/\/blog.gwadej.org\/programmer_musings\/?p=1031"},"modified":"2018-06-26T19:16:29","modified_gmt":"2018-06-27T00:16:29","slug":"bpgb-single-responsibility-preoccupation","status":"publish","type":"post","link":"https:\/\/blog.gwadej.org\/programmer-musings\/2018\/06\/bpgb-single-responsibility-preoccupation\/","title":{"rendered":"BPGB: Single Responsibility Preoccupation"},"content":{"rendered":"<p>It&#8217;s time for another post in my intermittent series of Best Practices Gone Bad (BPGB). This time we&#8217;ll cover the dark side of the Single Responsibility Principle (SRP). According to Robert Martin:<\/p>\n<blockquote><p>A class should have one, and only one, reason to change.<\/p><\/blockquote>\n<p>The basic concept is easy. Every object or method should be responsible for only one thing. This makes a lot of sense because combining two separate pieces of functionality in a single class or method usually makes that item harder to maintain, understand, or troubleshoot. It seems obvious that you can improve any design by ruthlessly breaking any class with more than one responsibility into two of more classes. Likewise, any method that does more than one thing should be separated into two or more methods. The logic here seems pretty obvious.<\/p>\n<p>If you notice, the third word in the name is actually important. This is a <em>principle<\/em> that should help you think about how to organize your objects and methods. It is not a law that mandates how all code is written. The problem begins when you take the principle too far. You could argue that almost anything can be divided into separate responsibilities. Smaller classes and methods must be easier to understand, right? Unfortunately, if you divide a concept inappropriately, you might need to add a class to pull the concept back together.<\/p>\n<h2>An Example<\/h2>\n<p>For example, let&#8217;s say you have a circle class. To define a circle, you need a center point (let&#8217;s say just <code>x<\/code> and <code>y<\/code>), and a radius. For the sake of the argument, let&#8217;s say you want the circle to be able to return a circumference and a bounding box. (Let&#8217;s use Ruby for this example.)<\/p>\n<pre><code>\nclass Circle\n  attr_reader :x, :y, :radius\n\n  def initialize x: x, y: y, radius: radius\n    @x = x\n    @y = y\n    @radius = radius\n  end\n\n  def diameter\n    radius * 2.0\n  end\n\n  def circumference\n    diameter * Math::PI\n  end\n\n  def bounding_box\n    [ x - radius, y - radius, diameter, diameter ]\n  end\nend\n<\/code><\/pre>\n<p>You can see that I factored out a <code>diameter<\/code> method to <abbr title=\"Don't Repeat Yourself\">DRY<\/abbr> the code, which also moved a responsibility into a separate method.<\/p>\n<h2>A Step Too Far<\/h2>\n<p>Now, someone in the throes of <em>Single Responsibility Preoccupation<\/em> might reason that the <code>Circle<\/code> class should just contain the attributes of the circle, it should not also be responsible for calculating synthetic attributes, like <code>circumference<\/code>, and <code>bounding_box<\/code>. Maybe we should separate those out. After all, other classes might need a <code>circumference<\/code> or a <code>bounding_box<\/code>. So, let&#8217;s create a Circumference class, that returns the correct length when supplied with a <code>Circle<\/code> object. And, we can create a <code>BoundingBox<\/code> class that calculates the upper, left corner and width and height, given a <code>Circle<\/code> object.<\/p>\n<p>The problem is that it almost makes sense. But, I would argue that the knowledge of how to calculate the circumference, or make the appropriate bounding box is actually part of the concept of a Circle. Separating those methods out splits the concept of a Circle, moving some if its responsibility elsewhere. This leaves the concept of a <code>Circle<\/code> in three classes.<\/p>\n<p>Now, some of you will think that this is a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Straw_man\" target=\"_blank\" rel=\"noopener\">Straw Man<\/a> argument. That&#8217;s not the case. I was working on a system recently with a set of classes that supplied 4 public methods as an interface. Some people suggested that we should separate each of these classes into 4 classes, one for each original method. It did take a bit of argument to show how the 4 methods together made a single concept, that would be harder to work with if it were broken down.<\/p>\n<h2>Conclusion<\/h2>\n<p>The Single Responsibility Principle is an effective mental tool to avoid classes that do too much. But, becoming preoccupied with the principle can lead to hard-to-understand code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s time for another post in my intermittent series of Best Practices Gone Bad (BPGB). This time we&#8217;ll cover the dark side of the Single Responsibility Principle (SRP). According to Robert Martin: A class should have one, and only one, reason to change. The basic concept is easy. Every object or method should be responsible\u2026 <span class=\"read-more\"><a href=\"https:\/\/blog.gwadej.org\/programmer-musings\/2018\/06\/bpgb-single-responsibility-preoccupation\/\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[52,106,229,293,342],"_links":{"self":[{"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/posts\/1031"}],"collection":[{"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/comments?post=1031"}],"version-history":[{"count":0,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/posts\/1031\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/media?parent=1031"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/categories?post=1031"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.gwadej.org\/programmer-musings\/wp-json\/wp\/v2\/tags?post=1031"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}