3

Encapsulation is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. Client code is expected to inherit from system-supplied classes and then substituted for the system's classes in its algorithms.

Inheritance is when an object or class is based on another object or class, using the same implementation or specifying a new implementation to maintain the same behavior.

I like inheritance. For numerous reasons. That's the way of not writing everything again. I like that. Encapsulation... well, that's the thing that I don't like so much because of logic around it. To encapsulate something I need to know much bigger scheme of it all. But, eventually it's the same "scheme" as if I'm looking for inheritance.

But what do you do to avoid coupling when there's a bunch of inheritance? Is coupling a good thing or bad thing when I'm developing standalone modules on framework? Is it better to go with inheritance or is it better to go with encapsulation?

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
Josip Ivic
  • 1,617
  • 5
  • 28
  • 46
  • 1
    Possible duplicate of [Are there any OO-principles that are practically applicable for Javascript?](http://softwareengineering.stackexchange.com/questions/180585/are-there-any-oo-principles-that-are-practically-applicable-for-javascript) – gnat Oct 26 '16 at 14:55
  • 1
    did you actually read my question and read that question? – Josip Ivic Oct 26 '16 at 14:55
  • sure I did. [Answer in duplicate target](http://softwareengineering.stackexchange.com/a/180588/31260) is a definitive guiding reference on how to address concerns like you expressed in your question – gnat Oct 26 '16 at 14:58
  • 1
    Maybe it's my relative unfamiliarity with Javasript, but I'm having a hard time seeing how encapsulation and inheritance would be mutually exclusive? (Also, curious as to if and why you eschew composition?) – LindaJeanne Oct 26 '16 at 15:00
  • @gnat, Cool. Because, I'm only seeing https://www.bennadel.com/blog/recent-blog-entries.htm this link that is talking about encapsulation. – Josip Ivic Oct 26 '16 at 15:00
  • @LindaJeanne, don't know, that's why I asked, because there's a bunch of experts on this SE. :) – Josip Ivic Oct 26 '16 at 15:01
  • 2
    Also, the problem isn't with "coupling" generally, it's with "tight coupling". Obviously the parts of the program are all connected together somehow, it's just a matter of how easy any individual part is to change or maintain without breaking the rest. – LindaJeanne Oct 26 '16 at 15:04
  • Maybe the conflict between "inheritance" and "encapsulation" that you are asking about is specific to Javascript? Because otherwise, I got nothin'. – LindaJeanne Oct 26 '16 at 15:05
  • How is inheritance opposed to encapsulation in a way that you have to decide to go with one or the other? – Tulains Córdova Oct 26 '16 at 15:39
  • Encapsulation does not require inheritance or imply class hierarchy. Whereas inheritance involves class hierarchy, and implies encapsulation. – Erik Eidt Oct 26 '16 at 15:47
  • 2
    @gnat: Strictly speaking, answers don't make a post a duplicate target... *Questions do.* – Robert Harvey Oct 26 '16 at 16:38
  • @RobertHarvey per my reading [this answer at MSE you accepted a while ago](http://meta.stackexchange.com/a/217406/165773) suggests otherwise – gnat Oct 26 '16 at 16:59
  • @gnat: The general principle is "but only for canonical questions," and that Javascript question seems too specific to act as a canonical here (this question mentions Javascript, but only in passing). – Robert Harvey Oct 26 '16 at 17:01
  • @RobertHarvey if the one I referred isn't canonical ([answer](http://softwareengineering.stackexchange.com/a/180588/31260) / [meta](http://meta.softwareengineering.stackexchange.com/q/5496/31260)) then I don't know what is – gnat Oct 26 '16 at 17:05
  • 1
    @gnat: This question appears to be specifically about *coupling,* not general OO principles; we can't ask folks to wade through a mountain of information to find a nugget that you happen to know exists in some other post, unless that post happens to be *the same question.* – Robert Harvey Oct 26 '16 at 17:08
  • @RobertHarvey you got to read it differently than I then, what I see here is far beyond just coupling, there's inheritance and encapsulation. To me that makes it about general OO principles – gnat Oct 26 '16 at 17:10
  • This question would be much improved if you deleted everything but the last paragraph. I'm sure the first 85% deals with some sort of concerns that you have, but it has little to do with the question you're asking and it just muddies the water. – Caleb Oct 26 '16 at 17:34
  • 5
    Yes, the actual question is in the last paragraph: *"what do you do to avoid coupling when there's a bunch of inheritance?"* Incidentally, the de facto answer is probably some combination of "use composition instead," "inherit from interfaces instead," or "use composition with dependency injection." – Robert Harvey Oct 26 '16 at 17:55
  • @RobertHarvey good point, I've tried to deal with that a little better. – candied_orange Oct 26 '16 at 19:08

2 Answers2

8

Is coupling a good thing or bad thing when I'm developing standalone modules on framework?

Coupling is an unavoidable thing if you want things to work together. What you work towards is loose or low coupling so that you can make changes in one place without being forced to make them in other places as well to keep things working.

Is it better to go with inheritance or is it better to go with encapsulation?

This is a false choice. Choosing between inheritance and encapsulation is like choosing between cats and democrats. Sure there is an important choice here but it's not between these two things.

The alternative to inheritance is composition with delegation. Both are ways of doing polymorphism.

The alternative to encapsulation is public state. Both let you hold information.

Encapsulation is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. Client code is expected to inherit from system-supplied classes and then substituted for the system's classes in its algorithms.

No.

A mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit is called an object.

Encapsulation is information hiding, even if I only do it by naming variables with underscores to signal that you should keep your grubby mitts off of them. It's me separating what parts of my object are for public consumption and what aren't.

By the way, encapsulation has nothing to do with remembering to use getters and setters. That's a lie that's been told many times but it still isn't true. Getters and setters started as debugging code, a manual way to do Aspect-Oriented Programming before we knew what that was. Me getting a chance to fiddle with my private stuff before you read my private stuff isn't encapsulating it. It just gives me a chance to know what's causing bugs with it because I can set a breakpoint and look at the call stack.

Inheritance is when an object or class is based on another object or class, using the same implementation or specifying a new implementation to maintain the same behavior.

No.

More correctly, Inheritance is when an object or class is based on another object or class, using the same implementation or specifying a new implementation to maintain the same interface or type.

Inheritance is a way of implementing polymorphism. It's not the only way. Composition and delegation can do this as well and more flexibly. It just requires that you type out more code.

I like inheritance. For numerous reasons. That's the way of not writing everything again.

I hate inheritance. For numerous reasons. Mostly over use of the template method pattern and the sickening yo yo problem. This emerges because lazy SOB's create a system with a few generic classes that barely do things you need them to do and design the system to only accept them. Rather than design a proper API for people to use they say, "Oh just inherit from the Foo class". Doing that, especially when you're not the only one or the only layer, without getting hideously coupled to Foo, is a nightmare.

I greatly prefer composition and delegation. Sure it's more typing of code but it means I control what I care about.

...the way of not writing everything again.

Don't repeat yourself is an excelent principle. Inheritance has no monopoly on following it. The strategy pattern discorages solving this with hierarchys in favor of optional implementations. And it isn't the only way to delegate. I can go as far as doing composition and delegation with Single Method Interfaces so I'm never repeating code. Here's an example.

To encapsulate something I need to know much bigger scheme of it all.

Encapsulation doesn't mean you need to know the bigger scheme. Encapsulation means never you mind what my private stuff is doing. The best encapsulated objects don't offer any getters at all. They ask you to follow Tell, Don't Ask. They are not designed to give up their secrets when asked. They sit around waiting for you to tell them to do something, then they go do it. What they do may depend on that private stuff but you don't need to worry about that, that's their job.

When you work this way you can tell an animal to speak without testing if it's a duck. You say speak and it quacks. Unless it's a dog. But since you just need it to speak you don't care. You don't even know it's a duck. You don't want to know. Whatever you are, just go speak already.

Build your classes and API's with that kind of thinking and avoiding coupling is much easier. You can't be coupled to what you don't know about. Be very careful of what you let your classes know about.

But what do you do to avoid coupling when there's a bunch of inheritance?

If you must use inheritance at least design a child class that puts a stop to it. The real cause of the yo-yo problem is when you inherit, add what you need, and let the next poor guy inherit from you. If you can't get rid of the inheritance at least design the child class so that anyone coming after can pass in (inject) what they need without being weighed down by everything that went before. Doing that injection in a loosely coupled way is what dependency injection is all about.

Frameworks have come a long way. They are very powerful and useful. But all too often they want to take over your language space to the point that you're not a Javascript programmer anymore your a Javascript/Angular.js programmer. If you have to mention a framework when you advertise for a programming job, don't tell me you're not coupled to it.

You can fight this by treating your framework like a library, telling it to do what you need in controlled ways, not letting it visibly spread into all of your code. But doing that is fighting against the will of the framework author. They want you coupled. It's in their business plan. Don't expect doing that to be easy.

One of the best presentations I've seen to demonstrate that you can use a framework without it taking over you're life is this. It's about ruby and rails but hopefully you can get some use out of it.

candied_orange
  • 102,279
  • 24
  • 197
  • 315
  • This is largely correct (+1). But I'd like to point out why getters and setters are important: A setter allows me to constrain the values of a field without creating a custom type. It also lets me trigger actions when the value is changed. A getter allows me to switch the representation of a field without affecting the public interface, e.g. switching from a plain field to an ad-hoc calculated value. – amon Oct 26 '16 at 17:42
  • 2
    A constructor allows me to constrain the values of a field without creating a custom type as well (this is called validation). Unlike a setter, a constructor doesn't force me to be mutable. Triggering actions is the manual Aspect Oriented part. As for getters having the ability to switch things around doesn't correct the fact that you've destroyed encapsulation. I'm not saying there isn't a place for that. There is a place. It's data structures, containers, data transfer objects, entities. All fancy terms for state being shared. You can pass around state but don't call it encapsulated. – candied_orange Oct 26 '16 at 18:32
  • "This is a false choice. Choosing between inheritance and encapsulation is like choosing between cats and democrats" I disagree and think that @josip-ivic is spot on here. If a type is designed around inheritance, then it is forced to expose its inner workings to potential sub-types, through `protected` members. That weakens encapsulation. – David Arno Oct 26 '16 at 22:25
  • @DavidArno You're apparently talking about java. Using protected rather than private is a choice to weaken encapsulation. Nothing was forced. Even if that was the issue it doesn't matter thanks to reflection. The point is to SIGNAL to other coders what is for public consumption and what is not. Underscores in python do the same thing without any enforcement. A subtype is free to override everything public and not care at all what the parent thinks. The only weakness comes from you thinking you're entitled to go poking around inside the parent. If you think that there really is no stopping you. – candied_orange Oct 26 '16 at 22:56
2

Favor composition over inheritance. Inheritance is falling out of favor in many use cases. It is essentially a form of tight coupling between components that tend to diverge over time. Tight coupling is to be avoided between separate areas of concern. Better to have a wide array of narrowly focused components, essentially tightly coupled internally via encapsulation, each following carefully the Single Responsibility Principle, yet very loosely coupled to everything else. Eg. with dependency injection.

Bradley Thomas
  • 5,090
  • 6
  • 17
  • 26