8 ms·
Law of Demeter
- dang 7y agoA thread from 2016: https://news.ycombinator.com/item?id=12611651 https://news.ycombinator.com/item?id=12611651 C2 page: http://wiki.c2.com/?LawOfDemeter http://wiki.c2.com/?LawOfDemeter
- utopian3 7y agoI wonder why it’s both a “law” and a “principle”? Did someone else change it?
- regularfry 7y agoThe definition of "principle" includes "law" - at least, according to the dictionary. I'm not sure I can identify a useful distinction in common use.
- gowld 7y agoA principle is a personal choice to take or leave, to me. Law is imposed by the external world that doesn't defer to your opinion (but you can break it). I violate my principles, but I violate your laws.
- inopinatus 7y agoJim Weirich once called it the “Very Good Suggestion of Demeter”.
- HelloNurse 7y agoUnusually, it's the kind of "law" that you are supposed to follow, not an observed law of nature.
- hyperpape 7y agoIn the article linked above, Martin Fowler is quoted with an even weaker formulation: the "Occasionally Useful Suggestion of Demeter".
- inopinatus 7y agoThey were very likely aware of each other. Jim Weirich said it in his talk The Grand Unified Theory of Software Development at Acts as Conference 2009, just a few weeks prior to the Fowler tweet.
- mannykannot 7y agoIt's mostly just a matter of usage, though in my personal (unwritten) style guide, 'law' would be reserved for constraints that, if not strictly true all the time, you generally cannot avoid (e.g. Moore's law), while a principle is a good idea that you would generally be well advised to try to conform to.
- deleted 7y ago[deleted]
- Lapsa 7y agohaack once wrote a nice article on this: https://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx/ https://haacked.com/archive/2009/07/14/law-of-demeter-dot-co...
- nabla9 7y agoHeh. I didn't know this was called the Law of Demeter. I learned this principle as a joke: Good object should be like like stereotypical reserved introvert Finn: respect the privacy of others, don't talk to strangers, keep only few close friends.
- jonny_eh 7y ago> stereotypical reserved introvert Finn Who? Huck Finn? or a cartoon character?
- dredmorbius 7y agoNationality.
- stcredzero 7y agoThe cartoon Finn is very extroverted.
- pontifier 7y agoThat's not the way I think, so that's not the way I program. When I'm thinking about an algorithm for solving a problem I sometimes need extra info from many other places. I sometimes need to use globals to get around all this message passing nonsense that would otherwise clutter my function calls with 50 parameters. I'd use GoTos if they were better supported. I don't usually program for others, and I don't call myself a good programmer though. I usually just need to solve my own problems, then move on to the next.
- bluGill 7y agoWhen doing a tiny program of just a few thousand lines of code all by yourself you can get away with that. I do it myself at times because for a tiny program who cares - if I don't understand it I'll re-write it again. When you move t very large programs with millions of lines of code you cannot get by with that. You need strict rules of communication so all the humans can understand what is going on.
- inlined 7y agoSome tips: If your function call needs 50 parameters (I assume this is hyperbole) then you need some encapsulation. Many codebases with complex functions actually create a struct for the function call, which actually adds forwards compatibility if new struct members are optional. If you use globals to pass state then you’re probably not thread safe and you’re certainly going to have problems testing because you’ll need to “prep” global state before every test.
- stcredzero 7y agoIf your function call needs 50 parameters There's an object asking to be born!
- wongarsu 7y agoIn my opinion this is a corollary of Conway's law [1]: "organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations". Code that demands more communication then what people are comfortable with is bound to fail (become unmaintainable and produce many bugs), so the law of demeter codifies communication structures as a law about code dependencies and architecture. It follows that for small teams and personal projects the law of Demeter might not be worth following since they don't suffer from these communication problems. Also microservices an application of the law of Demeter to larger chunks of code instead of just classes. https://en.wikipedia.org/wiki/Conway%27s_law https://en.wikipedia.org/wiki/Conway%27s_law
- hyperpape 7y agoI think your comment is really about rejecting the law. You're describing a kind of encapsulation between different modules, or packages (or some other name for large collections of code). The Law of Demeter is really supposed to apply at the class level, which is much more fine-grained than any kind of organizational boundary.
- wongarsu 7y agoI think in a monolithic Java or C++ application the organisational boundaries often do flow along class boundaries (and actually the boundaries between two programmers can be nearly as high as those between two teams). In object oriented programming classes are basically black boxes of code with well defined interfaces. In that sense modules, packages and microservices are just new types of "classes" we invented since the law of Demeter was formulated in '87. The purpose of all of those constructs is just to give a clear interface to a black box of code, just that those black boxes get successively larger.
- hyperpape 7y agoThe Law of Demeter is more fine-grained, though. If I write classes A, B and C, I'm not supposed to call A.getB().getC().doThings(), even if I'm the author of A, B and C. So the Law of Demeter is potentially more fine-grained than anything you might infer based on organizational structure.
- ralusek 7y agoRoughly analogous to programming concepts of "encapsulation" and "decoupling." An exercise I often use is to pretend like whatever I'm writing needs to be usable on multiple projects, so it should be able to be a package that anybody could find useful. Then you work backwards from the interface you'd like a tool like this to have, and obfuscate anything other than the interface. Obviously you're not doing this for most business/controller logic, but for most other things it goes a long way towards avoiding the kind of spaghetti code the Law of Demeter seeks to weed out.
- inlined 7y agoThe law of Demeter is sometimes a pain to work with but it makes your codebases easier to refactor and test when there’s no calls to foo.bar.qux.makeWidget() inside a WidgetFactory class. WidgetFactory instead is constructed with multiple single-purpose objects that are easily mocked or refactored. This however adds complication to constructors in OOP and is what I assume has always been the reason for the rise of Dependency Injection.
- gowld 7y agoPlease don't mock objects if possible. Prefer real, then fake, then mock for testing error conditions that "cannot happen" during normal operation that you can't force of fake in tests. https://medium.com/@CDehning/when-to-use-fakes-instead-of-mocks-c80188b9a3f1 https://medium.com/@CDehning/when-to-use-fakes-instead-of-mo...
- iteriteratedone 7y agoDI is a higher order idea of encapsulation Demeter is not about your current inplementation but about always being ready for refactoring. With the demeter law respected you never have to hunt down dependencies. They are obvious and restricted to signatures. Not internal function logic.
- johnsimer 7y agoDependency injection plus LoD has made designing new modules for me a breeze, and has drastically reduced my number of bugs
- dwheeler 7y agoThis is a weird deja vu. I created that page on Wikipedia back in 2003 so that people could find out what it was. At the time there were a huge host of things that Wikipedia didn't cover at all; it's remarkable how much Wikipedia has grown since then. As noted elsewhere, this is not really a "law" - it's a design guideline that many find (usually) helpful. However, it was named a "law" and the name has stuck.
- dragonwriter 7y ago> As noted elsewhere, this is not really a "law" It is a law in the regulatory rather than scientific sense, in that it was adopted as a coding rule in the Demeter project.
- octosphere 7y agoAlso similar: https://en.wikipedia.org/wiki/Principle_of_least_privilege https://en.wikipedia.org/wiki/Principle_of_least_privilege
- robbrit 7y agoI've never found that sticking strictly to the Law of Demeter makes your life that much easier for the reasons under "Disadvantages" in the article. I prefer a more relaxed form of the law: you can do something like a.b().c(), where b is a method that returns an interface. I think of it as a "composite interface". You can repeat the nesting as much as you like, however it gets a little hard to read after a while.
- johnsimer 7y agoIf you're trying to do b.c() you should inject b directly into your constructor
- hellofunk 7y agoWhenever I see things like this "law," or the ridiculous "DRY" principle, I'm glad I don't program deep in the OO paradigm. There have been so many code sins committed in the name of DRY that I think it is a good interview question to ask why it is useful to not follow some of these guidelines.
- twh270 7y agoI'm curious, what code sins do you see committed in the name of DRY? I ask because in my org there's rarely even an attempt made to DRY anything, so I'm not really aware of how people screw it up.
- jrochkind1 7y agoBasically, over-engineering. One example, sometimes DRY'ing up things that just happen to use the same logic now, but don't existentially/necessarily use the same logic. When they stop using the same logic, you add extra 'magic flags', or you've got to undo the architecture. Sandi Metz says "prefer duplication over the wrong abstraction ". https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstracti... She also writes about how devs are reluctant to change existing abstractions (for both rational and irrational reasons), making the wrong abstraction even more expensive. Which isn't to say that lots of duplication all over the place is a good sign either, obviously not.
- hn23 7y agoI think that a good abstraction is not always obvious. For example, in our old code base from 2008, which is still in production and extended, the main idea was inheritance can solve DRY. Many developers still stick to abstract class just to save a few lines where they could go with a strategy or just split up. I wouldn't call this over engineering. I call it laziness to learn and refactor.
- jrochkind1 7y agoI agree that a good abstraction is not always obvious, which is why we should try to avoid unneccesary abstractions (we probably won't get them right, at first, and they can be expensive to fix when we don't), which is why sometimes DRY can lead you wrong. Exactly my point. :)
- rthomas6 7y agoThis is as good a thread as any to say that I don't like object oriented programming. When I have had the occasion to use some open source library to do something (mostly in Python, occasionally in Javascript), it's been rare that I haven't dug into objects to figure out what the hell they were actually doing, and the assumptions the creator made (that they didn't realize they made) about how the object was supposed to be used. I get the point of OO and see how it's supposed to be used, and how handy it would be in large systems, but in my world the information hiding has been more of a hindrance than a help. Maybe what I really want to say is that it's harder than people think to do OO well, and when it's not done well, it just make everything more buggy and complicated.
- Animats 7y agoThat way lies "objects".
- galaxyLogic 7y agoThink about it this way. Your code says a.b().c().d(). But then you discover that 'a' actually has method d() whose implementation is "return this.b().c().d()". In other words a.d() <=> a.b().c().d() Which call should you make? Obviously a.d(), not only because it is shorter but because it makes your code independent of the fact whether a.b() returns something that understands c() which returns d() whose result is what you want. a.d() is better code then than a.b().c().d() because it makes fewer assumptions about the rest of the system. Now assume such a.d() does NOT exist. Would it make sense to create it? Yes because THEN you will be able to write better code by more simply writing a.d() . Now there is a cost to writing a new method a.d(). But typically that cost is not much because its implementation is simple "return this.b().c().d()" . But then you realize b().c().d() should be replaced by b.d() to follow the Law of Demeter again. So you actually must pay the price of writing two new methods if you want to follow Demeter. Is it worth it? It depends on how much you value maintainablity vs. having to write less code right now. My guess is that following Demeter is almost always better.