{"id":676,"date":"2025-07-23T09:00:00","date_gmt":"2025-07-22T23:00:00","guid":{"rendered":"https:\/\/jm.armijo.au\/dev\/?p=676"},"modified":"2025-07-22T17:16:45","modified_gmt":"2025-07-22T07:16:45","slug":"decoupling-code-with-the-law-of-demeter","status":"publish","type":"post","link":"https:\/\/jm.armijo.au\/dev\/blog\/2025\/07\/23\/decoupling-code-with-the-law-of-demeter\/","title":{"rendered":"Decoupling Code With The Law Of Demeter"},"content":{"rendered":"\n<p>It is usually well understood that decoupled software helps us easily change, test, reuse, understand, and extend our code. For this reason, many of us will either advocate or hear someone promoting decoupled code when we build our systems.<\/p>\n\n\n\n<p>There are a number of techniques that we can use to do this, and today I&#8217;ll write about one in particular: the Law of Demeter.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Law Of Demeter<\/h3>\n\n\n\n<p>I first stumbled upon the Law of Demeter while reading the Clean Code book by Robert C. Martin (a must read in my opinion). It was discovered in 1987 by Ian Holland while working on a project called Demeter, thus the name of the Law.<\/p>\n\n\n\n<p>The Law of Demeter says that class methods should only access variables they directly know about. Or, as the motto says: &#8220;<em>Only talk to your friends<\/em>&#8220;. Despite the simplicity, I find that the words get in the way, so instead, let me start by showing some code that breaks this law.<\/p>\n\n\n\n<p>Let&#8217;s consider some classes <code>House<\/code>, <code>Room<\/code> and <code>SmartLight<\/code>:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/documents.lucid.app\/documents\/28c38ec7-4de5-44a5-b38e-47b25b6b7828\/pages\/0_0?a=809&amp;x=1553&amp;y=-49&amp;w=1014&amp;h=184&amp;store=1&amp;accept=image%2F*&amp;auth=LCA%202639946127ce500c5cd8e8357c7c9afdbbbfc9bb9286b0577bbda31974ef47d9-ts%3D1752889824\" alt=\"\" \/><\/figure>\n\n\n\n<p><code>House<\/code> implements the <code>illuminate_rooms<\/code> method to turn on the lights in every room. When called, it finds the light object on a specific room, and calls the <code>turn_on<\/code> method.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nclass House\n  ...\n  def illuminate_rooms\n    @kitchen.light.turn_on\n  end\nend\n<\/pre><\/div>\n\n\n<p>Although this works, this implementation of the <code>illuminate_rooms<\/code> method breaks the Law of Demeter because class <code>House<\/code> is sending a message (<code>turn_on<\/code>) on an object (<code>light<\/code>) that it&#8217;s not directly associated with.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter is-resized\"><img decoding=\"async\" src=\"https:\/\/documents.lucid.app\/documents\/28c38ec7-4de5-44a5-b38e-47b25b6b7828\/pages\/0_0?a=756&amp;x=1683&amp;y=287&amp;w=794&amp;h=274&amp;store=1&amp;accept=image%2F*&amp;auth=LCA%20301991af62b659b0d9aa1e61bd4f0af81e36c1d980015621500c7f5c8494c449-ts%3D1752889824\" alt=\"\" style=\"width:538px;height:auto\" \/><\/figure>\n\n\n\n<p>We can easily fix this by adding a method in class <code>Room<\/code> to hide its implementation details, and call it from class <code>House<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nclass Room\n  ...\n  def illuminate\n    @light.turn_on\n  end\nend\n\nclass House\n  ...\n  def illuminate_rooms\n    @kitchen.illuminate\n  end\nend\n<\/pre><\/div>\n\n\n<p>Now, class <code>House<\/code> emits a message to <code>kitchen<\/code>, one of its member variables, and so does class <code>Room<\/code> when it calls <code>@light.turn_on<\/code>. The Law of Demeter is then satisfied, as we are only making function calls on direct dependencies of the classes.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/documents.lucid.app\/documents\/28c38ec7-4de5-44a5-b38e-47b25b6b7828\/pages\/0_0?a=952&amp;x=2617&amp;y=293&amp;w=926&amp;h=141&amp;store=1&amp;accept=image%2F*&amp;auth=LCA%203883d0dca3c26a5b0ab647a6384c94ca990dcded13b8aa837c814cc5630950c2-ts%3D1752889824\" alt=\"\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Formal Definition<\/h3>\n\n\n\n<p>The Law of Demeter is formally defined in a paper published in 1989 [1]. It provides two definitions of the rule: the official, which is a bit cryptic and you can find in the reference, and another that even the authors believe is &#8220;<em>the most natural way to state the Law&#8221;<\/em>, that goes like this:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>For all classes C, and for all methods M attached to C, all objects to which M sends a message must be:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>M&#8217;s argument objects, including the self object, or<\/li>\n\n\n\n<li>The instance variable objects of C.<\/li>\n<\/ul>\n\n\n\n<p>(Objects created by M, or by functions or methods which M calls, and objects in global variables are considered as arguments of M.)<\/p>\n<\/blockquote>\n\n\n\n<p>I will complement this with some examples of function calls that adhere to the Law of Demeter:<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">M&#8217;s arguments<\/h5>\n\n\n\n<p>If a method M receives an object as argument, the Law of Demeter allows calling methods on this object.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nclass Class_C\n  ...\n  def method_M(argument_object)\n    argument_object.message()\n  end\nend\n<\/pre><\/div>\n\n\n<h5 class=\"wp-block-heading\">M&#8217;s self argument<\/h5>\n\n\n\n<p>In some languages, like Python, methods explicitly include a <code>self<\/code> argument that corresponds to the method&#8217;s class. Other programming languages do this implicitly. Irrespective of how this is done, what this rule says is that methods in a class can call methods on the same class.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nclass ClassC\n  ...\n  def method_M\n    another_method\n  end\n\n  def another_method\n    ...\n  end\nend\n<\/pre><\/div>\n\n\n<h5 class=\"wp-block-heading\">Objects created by M<\/h5>\n\n\n\n<p>As we saw in a previous article, we should usually prefer to follow the Dependency Inversion principle and inject dependencies, instead of creating objects inside other classes.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-practical-software-development wp-block-embed-practical-software-development\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"gz3DZu4NrR\"><a href=\"https:\/\/jm.armijo.au\/dev\/blog\/2025\/07\/02\/dependency-inversion-principle\/\">Dependency Inversion Principle<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; visibility: hidden;\" title=\"&#8220;Dependency Inversion Principle&#8221; &#8212; Practical Software Development\" src=\"https:\/\/jm.armijo.au\/dev\/blog\/2025\/07\/02\/dependency-inversion-principle\/embed\/#?secret=vjK3NDXIIg#?secret=gz3DZu4NrR\" data-secret=\"gz3DZu4NrR\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>However, if we still decide to create objects inside other classes, the Law of Demeter treats them as if they were function arguments, and so sending messages to these objects is allowed.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nclass ClassC\n  ...\n  def method_M\n    created_object = AnotherClass.new\n    created_object.message()\n  end\nend\n<\/pre><\/div>\n\n\n<h5 class=\"wp-block-heading\">Objects created by functions or methods which M calls<\/h5>\n\n\n\n<p>This is very similar to the previous case, only that classes are not created directly by method M, but by a method call that also follows the Law of Demeter:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nclass ClassC\n  ...\n  def method_M(argument_object)\n    created_object = argument_object.message()\n    created_object.message()\n  end\nend\n<\/pre><\/div>\n\n\n<h5 class=\"wp-block-heading\">objects in global variables<\/h5>\n\n\n\n<p>Although global variables are usually a coding smell and should be avoided, the Law of Demeter has nothing against them, and making function calls to objects in global variables is permitted:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\n$global_variable_object = SomeClass.new\n\nclass ClassC\n  ...\n  def method_M\n    $global_variable_object.message()\n  end\nend\n<\/pre><\/div>\n\n\n<h5 class=\"wp-block-heading\">The instance variable objects of C.<\/h5>\n\n\n\n<p>Finally, the Law of Demeter establishes that a method M of class C can make function calls on any member variables of class C:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: ruby; gutter: false; title: ; notranslate\" title=\"\">\nclass ClassC\n  def initialize(some_object)\n    @some_instance_variable = some_object\n    @another_instance_variable = AnotherClass.new\n  end\n  ...\n  def method_M\n    @some_instance_variable.message()\n    @another_instance_variable.message()\n  end\nend\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Benefits<\/h3>\n\n\n\n<p>The Law of Demeter has direct consequences for everyday developers. According to the authors, it <em>&#8220;simplifies complexity of programming [as] it restricts the number of types the programmer has to be aware of when writing a method.&#8221;<\/em><\/p>\n\n\n\n<p>Even more, it <em>&#8220;has many implications regarding widely known software engineering principles<\/em>&#8220;, which I&#8217;ve taken the liberty to quote and summarise here:<\/p>\n\n\n\n<p>&#8220;<em><strong>Coupling controls<\/strong>: &#8230; The Law reduces the methods we can call inside a given method and therefore limits the coupling of methods.<\/em>&#8220;<\/p>\n\n\n\n<p><strong><em>&#8220;Information hiding&#8221;<\/em><\/strong>: The Law enforces information hiding by preventing methods from directly accessing an object deep in the hierarchy and promoting the use of intermediary methods instead.<\/p>\n\n\n\n<p><strong><em>&#8220;Information restriction&#8221;<\/em><\/strong>: The Law of Demeter restricts the use of function calls, complementing information hiding.<\/p>\n\n\n\n<p><em><strong>&#8220;Localization of information<\/strong>: &#8230; When we study a method we only have to be aware of types which are very closely related&#8230; We can effectively be ignorant (and independent) of the rest of the system.<\/em>&#8220;<\/p>\n\n\n\n<p><em><strong>&#8220;Narrow interfaces<\/strong>: &#8230; A method should have access to only as much information as it needs&#8230;&#8221;<\/em> When a method handles too much information, it will usually end up making nested function calls, <em>&#8220;which the Law of Demeter discourages&#8221;<\/em>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Applying The Law<\/h3>\n\n\n\n<p>The Law of Demeter presents a very simple and clear strategy to write decoupled systems. There are some tools available to enforce it, like Reek for Ruby. For other languages like Typescript, it is possible to create custom ESLint rules to catch any violations.<\/p>\n\n\n\n<p>Even if we don&#8217;t have a tool to automatically enforce it, we can still keep the Law in mind while writing or reviewing code. This will help us build cleaner and more decoupled systems.<\/p>\n\n\n\n<p>To get the most out of it, the authors also recommend reducing code duplication, minimising the number of arguments per method and methods per class.<\/p>\n\n\n\n<p>Cheers!<br>Jos\u00e9 Miguel<\/p>\n\n\n\n<p><em>Share if you find this content useful.<\/em><br><em>Follow me on&nbsp;<a href=\"http:\/\/www.linkedin.com\/comm\/mynetwork\/discovery-see-all?usecase=PEOPLE_FOLLOWS&amp;followMember=jmarmijo\">LinkedIn<\/a>&nbsp;to be notified of new articles.<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">References<\/h3>\n\n\n\n<p><a href=\"https:\/\/www2.ccs.neu.edu\/research\/demeter\/papers\/law-of-demeter\/oopsla88-law-of-demeter.pdf\">[1] Object Oriented Programming: An Objective Sense of Style: K. Lieberherr, I. Holland, A. Riel<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>It is usually well understood that decoupled software helps us easily change, test, reuse, understand, and extend our code. For this reason, many of us will either advocate or hear someone promoting decoupled code when we build our systems. There are a number of techniques that we can use to do this, and today I&#8217;ll [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":689,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-676","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts\/676","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/comments?post=676"}],"version-history":[{"count":13,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts\/676\/revisions"}],"predecessor-version":[{"id":690,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts\/676\/revisions\/690"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/media\/689"}],"wp:attachment":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/media?parent=676"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/categories?post=676"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/tags?post=676"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}