Object Oriented Programming

The Local Change - Local Effect Principle

August 29, 2004 19:47:49.925

There's a principle of object oriented programming that I've never seen written up formally. For me, it's one of the key reasons to have object oriented software in the first place. I don't remember whether I came up with the term myself or whether I heard it from someone else first, but since I haven't seen it written up anywhere, I thought I'd do it here.

The principle is called "Local Change / Local Effect". It states:

Any localized design change to a software system should only require changes to a small amount of code in the immediate vicinity of the change. There should be no wide-spread or system-wide changes needed.

Encapsulation helps follow this principle by allowing changes in the representation of an object's state. The methods for the object may be affected, but callers of those methods shouldn't be. The effects of the change are localized.

Polymorphism helps by allowing us to add new objects without changing existing code to know about them. You only need to add the new classes and new methods. You shouldn't need to change existing code. (This is also known as the Open/Closed Principle).

Inheritance helps by providing one place to put common code for many similar objects. Changes to this code can be isolated to the superclass and may require no changes to subclasses in order to make them work.

There are many coding practices that tend to work against the local change/local effect principle. They include:

  • Copy and paste code - by making more copies of code, you have more things that need to be changed for any change in design.
  • Public instance variables - by making instance variables public, more people can use them directly and require more changes if you need to change the representation.
  • Manifest types - the type information for variables and parameters often causes domino effect changes. When you change the type that a method accepts, you may have to change its callers and their callers and so forth.

In any software system, the one thing you can count on is change. The local change/local effect principle makes change possible. Without it, as a system gets larger, it becomes more brittle and eventually becomes unmaintainable.

Think about your design principles. If they don't support local change/local effect, you may be building a system that will become too brittle to ever change again.

Comments

written up

[keith ray] August 29, 2004 21:42:44.477

See Robert Martin's "Agile Software Development: Principles, Practices, Patterns" I may not have the P's in the right order. Also written up (using different terminology) in "What Every Programmer Should Know About Object Oriented Design" (or "Programming")...

Re: The Local Change - Local Effect Principle

[ David Buck] August 30, 2004 6:43:08.784

Comment on The Local Change - Local Effect Principle by David Buck

Pointing to an entire book doesn't help me. I was looking for a name for the concept. Robert Martin talks a lot about the Open/Closed Principle, the Dependency Inversion Principle, and others, but I haven't seen a principle that covers the concept that design changes should cause localized effects. Maybe I missed it. Is there a name he assigned to it?

terms

[keith ray] August 30, 2004 10:31:38.657

"cohesion" and "coupling". Also, Martin introduces OO by saying its sole purpose is to allow the programmer to separate the "parts that change from the parts that don't change.

Local Change/Local Effect

[David Buck] August 30, 2004 10:50:09.994

Cohesion and coupling are related to LCLE, but not the same notion. Cohesion states that a module (class) should form a meaningful unit and related behavior should be brought together into one object. Coupling is the depencency that one (class) has on another - low coupling is better than high coupling. Neither of these concepts talks about the ease of making changes. I would agree that low coupling helps achieve LCLE. You could even say that the reason that low coupling is good is because of LCLE, but the concept of coupling is still different than what I'm trying to express with LCLE.

As for separating the "parts that change from the parts that don't change", I normally attribute this to runtime changes of instance variables. Even if you apply it to the code, it says little about the ability to make a change in one spot without global impacts.

Java's throwing

[Charles Monteiro] August 30, 2004 11:03:13.689

I'm curious as to your thoughts on the effect of Java's throws clause on the concept of local change local effect.

thanks

Java Throw Clauses

[David Buck] August 30, 2004 11:29:01.212

Actually, I've already commented on Java's throw clauses. Check my article Domino changes in Static Typing. This article is where I first introduce the term "Local Change/Local Effect".

Basically, Java's throw clauses and C++'s const methods both suffer domino effect changes when you make small changes in one area. They badly break LCLE.

Java throws

[Charles Monteiro] August 30, 2004 13:22:47.897

good, one of my pet issues with Java

const functions in C++

[Thorsten Seitz] September 3, 2004 10:07:05.489

I do not agree with your example regarding const functions in C++ in your article "Domino changes in Static Typing".

As you did not introduce a side effect into the const function, you could have easily left the function a const function and declared the new cache inst var as mutable. Indeed you should have left it const, thereby indicating that it does not have side effects.

If you had really introduced a side effect then the domino effect would not just have been syntactically neccessary but semantically useful, too: a client of your method might have it called several times (because it has no side effect) where he would not want to do that if the method suddenly gained a side effect, e.g. int f() const; being used as x = f() * f();

The domino effect would have noted clients that the method has changed semantically, so that all calling sites have to be checked whether they still use the method correctly.

static typing and nil

[Thorsten Seitz] September 3, 2004 10:20:13.139

In your article "Domino changes in Static Typing" you stated that "Static typing will never eliminate divide by zero errors, arrays indexed out of bounds, nil values instead of pointers" and other errors.

I do not agree with the nil values part. Have a look at the option types of the Nice Language for example. The type system ensures that you won't get null pointer exceptions in a nice way (at least that's my opinion). Sure, you are forced to handle the nil case when crossing the boundary between option types and normal types, but you should do handle the nil case (in those places where nil is allowed) in dynamic languages, too. Otherwise you will get errors.

(People are researching dependency type systems which might catch array indexed out of bounds errors and others, as well.)