3

I am trying to get my head around the open closed principle:

Modules should be open for extension and closed for modification

In terms of java is the extension specifically inheritance or does it include inheritance as well as the addition of new methods or properties?

I am also struggling to get my head around closed for modification, it seems to be implying to me that once a method is written that it cannot change.

This seems at odds with real work where I will pick up tasks from jira which will require me to change at least one method in the codebase.

I have read lots of posts and articles in the last 24 hours and I am still not entirely sure what this principle is trying to get across.

Any simple explanation would be very helpful.

berimbolo
  • 3,319
  • 8
  • 43
  • 78
  • Closed to modification means thay to change the behavior, you should not have to change the code inside the class/method. And open to extension means that you can pass different parameters to change the behavior. – litelite Jul 11 '17 at 17:08
  • It ensure that you do not have to modify a method to add logic every time you want to add a use case to your system. Because if you had to, you might end up with a monster method that does all the logic of the system. And such a method is unmaintanable (I know from experience) – litelite Jul 11 '17 at 17:11
  • How do you change behaviour by not changing code but passing 'different parameters to change behaviour'? I understand you could extend the class but is using multiple layers of inheritance to achieve this what it's implying? In effective java it's recommended to prefer composition over inheritance. – berimbolo Jul 11 '17 at 17:16
  • @berimblo you pass a class that have different implementations. You do not need multiple layer of inheritence, just 1 like an interface that have a lot of different implementaions. And what i said is composition – litelite Jul 11 '17 at 17:27
  • Right ok so programming to interfaces helps to achieve this closing off. – berimbolo Jul 11 '17 at 17:29
  • Yes, because all the logic that could have change is neatly encapsulated in a class that do not have to change. And if you need to add a functionnality, you can just create a new class that implements your interface. – litelite Jul 11 '17 at 17:30

2 Answers2

2

you should write your code well enough to not have to modify existing code. Ever. If you need functionality of an existing method, you should be able to call that method because it should be highly cohesive have extremely low coupling.

Think of it this way, once you build a house, is it better to try to double the size of your bathroom (moving toilet and show back re-flooring, new walls... etc) or is it easier to build a sunroom off of the front of the house with a new entryway?

You should be closed to modifying the bedroom, while it is not impossible, making a sun room will create the new space much easier.

Jason V
  • 623
  • 1
  • 10
  • 30
  • Ok and so on systems you work/have worked on you never needed to change a methods behaviour except to address a bug? – berimbolo Jul 11 '17 at 17:22
  • correct, you should not have to alter any of the existing methods. you would accept that they are working, bug free, methods that you are using and any new bug would happen due to either your new code (type mismatch), or a runtime error. – Jason V Jul 11 '17 at 17:24
  • Ok I still don't understand as requirements change all the time as does the code. Maybe it's just the systems I have worked on. The current system I'm working on has over 100 developers and 100,000 users so many changing requirements and methods are changing frequently. – berimbolo Jul 11 '17 at 17:27
  • so the open/close principle is a goal for your engineers to take into consideration. The legacy code oyu're referring to isn't intuitively designed. Thats the whole point to making this goal clear for new code- open/close is a LONG term goal. – Jason V Jul 11 '17 at 17:29
  • Ok and these principles hold true for spring based web applications as much as any other? – berimbolo Jul 11 '17 at 17:30
  • my team also has to deal with highly coupled code- it makes it very difficult for new features, but legacy code is everywhere. – Jason V Jul 11 '17 at 17:31
  • absolutely. while i have very little experience with spring, even web apps should be well designed enough to only add. Of course you might have to add attributes to existing classes, there's no going around that (like adding a new enum type) – Jason V Jul 11 '17 at 17:32
  • Ok thanks I kind of see it more clearly now and it seems a lot of it is related to keeping methods very small. Whilst we do have small discrete methods ultimately some method needs to wrap up many of these calls and I think developers have a habit of allowing methods to grow too big in places instead of spending the time to refactor. – berimbolo Jul 11 '17 at 17:35
  • that is absolutely the problem. and knowing the problem creates the solution. dedication to writing highly cohesive/lightly coupled code! In time, the ability to generate new features will be much easier. – Jason V Jul 11 '17 at 17:38
1

Open for extension

Reasonable extensions of the module should be possible. If they are not, the potential user will instead write their own implementation, causing duplication.

What's reasonable extension is usually the hardest part of the design - the designer must anticipate what extensions the eventual users will need.

Closed for modification

The extensions to the module must not be able to break the inner workings of the module / the declared functionality. If the module fails to guard its inner workings from being modified, it will be far more difficult to ensure (or even consider) the module's correctness. Basically, by allowing the users to modify your module you're adding to the contract of your module an requirement that the extensions do not modify your module in a way that would break it - a requirement that is often undocumented and impossible to fulfill without detailed knowledge of the module by its users.

Jiri Tousek
  • 12,211
  • 5
  • 29
  • 43
  • This is understandable. I was thinking more about the principle of never changing code once it's written. Take for instance a database mapper, it takes properties from db resultset, a new column is added so it has to change. Equally the mapper utilises a builder which builds a dto they all have to change to reflect the requirement of the new database field. Is this extension? It seems to be. Now with the scenario this new property will require changes to a validator for incoming requests, a logic change in the validate() method. Multiple code changes that seem to break never change code.. – berimbolo Jul 11 '17 at 18:02
  • And in the scenario above obviously all unit and integration tests would be changed to reflect these changes. – berimbolo Jul 11 '17 at 18:04
  • This principle is important for modules that have an ambition / possibility of being reused. If you expect to support both versions in your example (with and without new column), that is reuse as well. Otherwise these might be too minor, single-purpose modules to try to apply the principle and doing so might result in over-complicated design. – Jiri Tousek Jul 11 '17 at 19:23
  • By reused do you mean as a module that would be used in multiple projects? All the systems I have worked on we dont own the software the customer does so we dont tend to write libraries in this way so maybe thats why there hasnt been as much emphasis on this principle? We do use design patterns and code to interfaces as we use spring. – berimbolo Jul 12 '17 at 07:35
  • The principle intentionally speaks about "module", not "framework", "library", "class", etc. It can be applied at any scale - if you have a single class that's reused on multiple places within your (single) project, it's good to consider this principle. If you're writing a library that someone else will be using, it becomes even more important. – Jiri Tousek Jul 12 '17 at 07:44
  • Ok your replies were actually really helpful, appreciate the time you took to respond. – berimbolo Jul 12 '17 at 09:44