SUBTYPES MUST BE SUBSTITUTABLE FOR THEIR BASE TYPES.

하위타입의 객체가 상위 객체를 대체할 수 있어야 한다.

Have you ever seen code that has lots of instanceof expressions in the clauses of if
statements. Though there are some legitimate uses for expressions like this, they are few
and far between. Usually they are a result of violating the LSP, and are themselves a violation
of the OCP.

The LSP says that the users of base classes should not have to do anything special in
order to use derivatives. Specifically, they should not have to use instanceof, or downcasts.
Indeed, they should know nothing about the derivatives at all. Not even that they
exist.

Consider the payroll application shown in Figure 6-8. The Employee class is abstract
and has an abstract method named calcPay. It’s pretty clear that SalariedEmployee
will implement this to return the employee’s salary. It’s also pretty clear that Hourly-
Employee will implement it to return the hourly rate times the sum of the hours on this
week’s time cards.
SOFTWARE ENTITIES (CLASSES, MODULES, FUNCTIONS, ETC.)
SHOULD BE OPEN FOR EXTENSION, BUT CLOSED FOR MODIFICATION.

S/W의 요소(클래스, 모듈, function)은 확장에는 열려있고, 
수정에는 닫혀있어야 한다.

This principle has a high-falutin’ definition, but a simple meaning: You should be able to
change the environment surrounding a module without changing the module itself.

이 원리의 핵심은 어떤 특정 기능을 시스템 자체의 모듈을 변화시키지 않고도, 
기능상의 변화를 줄 수 있다는 것이다.

Consider, for example, Figure 6-4. It shows a simple application that deals with
Employee objects through a database facade named EmployeeDB. The facade deals
directly with API of the database. This violates the OCP because a change to the implementation
of the EmployeeDB class can force a rebuild of the Employee class.
The Employee is transitively bound to the database API. Any system that contains the
Employee class must also contain TheDatabase API.

EmployeeDB는 DAO 역할을 하는 class이며, DB의 API를 직접적으로 Access하는데,
이것은 OCP 위반에 해당된다. 왜냐하면 EmployeeDB의 변경이 client, 즉 Employee의 
변화까지 동반하기 때문이다.

결국 coupling으로 인해 기능상 확장성이 떨어지는 구조라 하겠다.


Unit tests are often the places where we want to make controlled changes to the environment.
Consider, for example, how we would test Employee. Employee objects make
changes to the database. In a test environment we don’t want the real database to change.
We also don’t want to create dummy databases just for the purposes of unit testing.
Instead, we’d like to change the environment so that the test catches all the calls that
Employee makes to the database, and verifies that those calls are made correctly.

Employee를 Unit 테스트할 경우 Real DB에 영향을 주는 것은 문제가 될 수 있으며,
Test를 위한 Dummy Object를 생성하는 것도 코드의 수정을 동반하기 때문에 좋지 못하다.
결국 Employee의 호출을 검증할 수 있는 테스트 환경의 제공이 최적의 조건이라 할 수 있다.


We can do this by converting EmployeeDB to an interface as in Figure 6-5. Then we
can create derivatives that either invoke the true database API, or that support our tests.
The interface separates Employee from the database API, and allows us the change the
database environment that surrounds Employee without affecting Employee at all.

이러한 문제는 DAO 자체를 Interface로 변경해서 해결할 수 있다.
테스트용 DB 환경과 Real DB 환경을 유연하게 사용할 수 있다.
Empoyee에 어떠한 영향을 주지 않고 자유롭게 DB 환경을 제어할 수 있다는것 이점.




A CLASS SHOULD HAVE ONLY ONE REASON TO CHANGE.
하나의 클래스는 변화에 오직 하나의 이유만 있어야 한다.

You’ve probably read the nonsense about objects needing to know how to draw themselves
in a GUI, or save themselves to disk, or convert themselves to XML, right? Beginning
OO texts like to say things like that. Ridiculous! Classes should know about only one
thing. They should have a single responsibility. More to the point, there should only be
one reason for a class to change.

 Consider Figure 6-1. This class knows way too much. It knows how to calculate pay
and taxes, how to read and write itself on disk, how to convert itself to XML and back, and
how to print itself on various reports. Can you smell the Fragility? Change from SAX to
JDOM and you have to change Employee. Change from Access to Oracle, and you have t
change Employee. Change the format of the tax report and you have to change
Employee. This design is badly coupled.


하나의 클래스가 너무나 많은 역할(responsibility)를 가지고 있어 coupling이 극도로 증가한 상태


In reality we want to separate all these concepts into their own classes so that each
class has one, and only one, reason to change. We’d like the Employee class to deal with
pay and taxes, an XML related class to deal with converting Employee instances to and
from XML, an EmployeeDatabase class to deal with reading and writing Employee
instances to and from the database, and individual classes for each of the various reports.
In short, we want a separation of concerns. A potential structure is shown in Figure 6-2

위의 복잡한 것을 각자의 역할을 가지는, 변화에 대해 단 한가지 이유를 가지는 개별의 class로 나누어야 한다.



Violation of this principle is pretty easy to spot in a UML diagram. Look for classes
that have dependencies on more than one topic area. A dead give-away is a class that
implements one or more interfaces that endow it with certain properties. Careless use of an
interface that endows an object with the ability to be stored on disk, for example, can lead
to classes that couple business rules with issues of persistence.

잘못된 interface의 상속구조의 사용한 향후 coupling의 문제를 야기시킨다.


Consider the two diagrams in Figure 6-3. The one on the left couples Persistable
tighly into Employee. All users of Employee will transitively depend upon
Persistable. This dependence may not be great, but it will be there. Changes to the
Persistable interface will have the potential of affecting all users of Employee.

좌측의 구조는 Employee와 Persistable interface가 강하게 coupling된 상태로,
Persistable의 변화가 모든 Employee 클래스에 영향을 줄 수 있다.


The diagram on the right side of Figure 6-3 leaves Employee independen of Persistable,
and yet allows for persistence just the same. Instances of PersistableEmployee
can be passed around the system as Employees, without the rest of the
system knowing about the coupling. The coupling exists, but is hidden to most of the system.

우측의 구조는 Employee가 Persistable에 독립된 구조로,
시스템 상에서 coupling이 없는 상태로 Employee의 형태로만 사용될 수 있다.
coupling은 존재하지만, hidden으로서의 이점이 있다.


Many of these smells are a result of mismanaged dependencies. Mismanaged dependencies
conjure the view of code that is a tangled mass of couplings. Indeed, it is this view of
entanglement that was the origin of the term “spaghetti code”.

Object oriented languages provide tools that aid in managing dependencies. Interfaces
can be created that break or invert the direction of certain dependencies. Polymorphism
allows modules to invoke functions without depending upon the modules that contain
them. Indeed, an OOPL gives us lots of power to shape the dependencies the way we
want.


잘못된 코드는 객체의 의존관계 관리를 잘못한 결과물이라 할 수 있다. 
잘못된 의존관계는 복잡하게 꼬여서 coupling을 가지는 코드의 관점을 만들어 내고,
실제로 이것은 '스파게티 코드'라는 말의 어원이 되었다.

객체지향언어는 관계 관리에 도움을 주는 툴을 제공해준다.
인터페이스는 어떤 직접적인 관계를 방지해주도록 사용될 수 있다.
다형성(Polymorphism)은 모듈이 어떤 모듈에 대해 의존성 없이 기능을 사용할 수 있게 해준다
객체지향 어언는 우리가 원하는 형태의 의존 구조를 만드는데 도움을 준다.


Design Quality

What does it mean to be well designed? A system that is well designed is easy to understand,
easy to change, and easy to reuse. It presents no particular development difficulties,
is simple, terse, and economical.

잘 디자인(설계)된 프로그램은 위와 같은 특징들이 있음


Design Smells.

You know when a programmer is working with a poor design by the state of his eyes
and nose while he’s looking at the code. If his or her facial expression reminds you of the
detectives who have just opened a body bag containing a 12 day old corpse, then the
design is probably pretty ripe. The smells of a poor design have many different components.

1. Rigidity: The system is hard to change because every time you change one thing,
you have to change something else in a never ending succession of changes.

- 강직, 경직됨 : 시스템을 바꾸기 어려운 경우, 매번 바꾸었기 때문(스파게티 코드), 지속적인 변경이 필연적인 상황

2. Fragility: A change to one part of the system causes it to break in many other,
completely unrelated, parts.

- 단편, 깨지기 쉬움 : 하나의 변화 전체 시스템에 치명적 영향을 줌, Strongly Coupled~

3. Immobility: It is hard to disentangle the system into components that can be
reused in other systems.

- 부동성 : 시스템을 콤포넌트(다른 시스템에서 사용될 수 있는) 조합으로 분리해 내기 힘든 상황

4. Viscosity: The development environment is held together with scotch tape and
toothpaste. It takes forever to go around the edit, compile, test loop.

- 점착성 : 개발 환경에 지나친 의존성을 가지는 상황

5. Needless Complexity: There are lots of very clever code structures that aren’t
acutally necessary right now, but could be very useful one day.

- 불필요한 복잡성 : 당장 필요하지도 코드 구조가 존재하는 상황, 그러나 언젠가는 유용할 지도 모르는 코드임

6. Needless Repetition: The code looks like it was written by two programmers
named Cut and Paste.

- 불필요한 반복 : Ctrl C, V로 생산된 코드가 혼재하는 상황

7. Opacity: Elucidation of the originator’s intent presents certain difficulties
related to convolution of expression.

- 투명성 : 작성자의 의도에 대한 설명이 난해한 표현으로 어려움을 내포하고 있음
The primary mechanisms behind the Open-Closed principle are abstraction and polymorphism.
In statically typed languages like C++, one of the key mechanisms that supports
abstraction and polymorphism is inheritance. It is by using inheritance that we can
create derived classes that conform to the abstract polymorphic interfaces defined by pure
virtual functions in abstract base classes.

 inheritance를 이용하여 객체지향의 특성(polymorphism, abstraction)을 활용한다.

What are the design rules that govern this particular use of inheritance? What are the
characteristics of the best inheritance hierarchies? What are the traps that will cause us to
create hierarchies that do not conform to the Open-Closed principle? These are the questions
that this article will address.

상속의 사용에 있어 설계의 원칙이 있는가?
상속을 이용한 디자인의 특성은 무엇인가?

FUNCTIONS THAT USE POINTERS OR REFERENCES TO BASE
CLASSES MUST BE ABLE TO USE OBJECTS OF DERIVED CLASSES
WITHOUT KNOWING IT.

Reference 형을를 쓰는 기능은 상속되는 클래스는 실제 Object의 구조를 알 필요없이,
상위 레벨의 클래스의 Object로 사용될 수 있어야 한다.

The above is a paraphrase of the Liskov Substitution Principle (LSP). Barbara Liskov first
wrote it as follows nearly 8 years ago1:

위의 문장은 LSP 정의의 의역이고 바바라 리스코프는 처음에 다음과 같이 섰다.(8년전)

What is wanted here is something like the following substitution property: If
for each object o1 of type S there is an object o2 of type T such that for all
programs P defined in terms of T, the behavior of P is unchanged when o1 is
substituted for o2 then S is a subtype of T.

복잡하다.. -_-;


The Open-Closed principle is at the heart of many of the claims made for OOD. It is when
this principle is in effect that applications are more maintainable, reusable and robust. The
Liskov Substitution Principle (A.K.A Design by Contract) is an important feature of all
programs that conform to the Open-Closed principle. It is only when derived types are
completely substitutable for their base types that functions which use those base types can
be reused with impunity, and the derived types can be changed with impunity.

상위 class의 객체를 상속구조상의 하위 class의 객체로 대체할수 있어야 된다..
OCP 를 더욱 견고히 하기위한 원칙..



+ Recent posts