수업/Software Design

Object-Oriented Systems의 기본 특징

hw-ani 2022. 9. 7. 19:16

교수님께서 한번 읽어보라고 올려주신 자료인데, 내용이 괜찮아 한번 정리해볼까한다.
내가 이해한대로 예를 들어가며 작성했다.


기존에도 Smalltalk나 Simula programming language에 object-oriented라는 개념은 있었으나, 1980년대에 processor power가 증가하고 비용이 감소하기 전까지 그리 실용적인 개념은 아니었다.
현재는 다양한 programming language(C++, Java, Objective-C, Python, ...)에서 object-oriented 개념을 각각 다른 방식으로 구현한다.
여기선 object-oriented system의 기본 특성인 class, object, method, message, encapsulation, information hiding, inheritance, polymorphism, dynamic binding에 대해 알아본다.
 
여기서 설명하는 Object Oriented 개념은 특정 Programming Language에 대해 얘기하는 것이 아니라, 진짜 OO "개념"에 대해 말한다.
Information System의 SW 부분을 설계할때는 크게 두가지 방식이 있다. 익히 들어온 절차지향과 객체지향이다.
SW라는 것은 건축물처럼 눈에 보이는 것이 아니기때문에 요구사항을 언어로 제대로 명시해야한다. SW 개발이란 이 세상에 없던 무언가를 만들어내는 과정이기때문에 모든 것들이 우선 "언어"로 표현될 수 밖에 없다. 언어는 보통 명사와 동사로 나뉜다. 어떤 SW를 만들지 명시된 문장의 동사에 집중하여 설계하는 방식을 "절차지향"이라고하고, 명사에 집중하여 설계하는 방식을 "객체지향"이라고 한다. 보통 명사에 집중한 객체지향 방법론이 유지보수성이나 재사용성이 좋다.
그런면에서 OO 개념을 잘 정립해 활용(구현)만 하면 좋은 SW를 설계/제작할 수 있다. 또한 information hiding 같은 개념은 추상화를 가능하게해 더 복잡한 기능을 구현할 수 있게 해주고, 여러 사람이 쉽게 일을 나눠 작업할 수 있게 한다.
C가 assembly에 비해선 우리와 가까운 고수준 언어라고는하지만, Object 개념을 구현할 수 있는 언어는 거기서 한단계 더 발전한 것이라고 볼 수 있다.
물론 OO를 사용해 편리함이 증가하면 퍼포먼스 측면에서 손실이 있을 수 있지만, 예전에 비해 hardware가 발전한만큼 어느 정도 감수할 수 있는 수준이라고 생각한다.
C++/Java 등의 PL은 여기서 말하는 OO개념을 각각의 방식으로 구현할 수 있도록 지원한다.(물론 이런 PL들은 딱 OO만 지원하는게 아니라 다른 패러다임도 지원한다.)
 
 
주변을 보자.. 박지환, 김현수, ... 각각이 object이다. 이런 object들은 각각 attributebehavior을 갖는다.
예를들어 키, 몸무게 등이 attribute일 것이고, 걷는다, 뛴다 등이 behavior일 것이다.
이렇게 우리는 attribute와 behavior을 이용해 각 object를 정의할 수 있다.
그런데 보면 알겠지만, 박지환과 김현수는 모두 인간이다. 즉 객체마다 attribute나 behavior 값들은 다르겠지만, 공통 카테고리를 가진다. 그렇기때문에 이런 인간 object를 찍어내는 틀이 있으면 편리할 것이다.
 
그래서 이를 class라는 틀로 만들어 각 instances(objects)를 만들 수 있도록 한다.(즉, instance를 한단계 추상화한 것이 class이다. 아니면 data와 그에 대한 연산을 정의한 data type을 구현한 것이라고 볼 수도 있는데, 둘 다 맞는 말이다.)
class는 당연히 attribute와 behavior(method)를 갖는다.(OOP에선 method를 이용해 behavior을 구현한다.)
attribute는 해당 object(혹은 class)의 특성뿐만아니라 다른 object와의 관계도 나타내는데, 이를 state라고 한다.
 
object가 동작을 하기 위해 정보가 필요할 수 있다.
예를들어 박지환 object의 키가 5cm 컸다고 해보자. 키 attribute도 있고, 키가큰다는 behavior도 있다.
이런 동작을 실행시키려면 당연히 함수도 호출해야하고, 정보도 전달해야한다.
message는 method를 실행시키기위해 object로 전달되는 information이다.(본문보니 함수호출 행위 자체도 포함되는 것 같다.)
 
우리가 각 object 하나하나 다루기보단 general하게 다루고 싶을 수도 있다. 예를들어 박지환, 김현수말고 저 옆에 원숭이까지 묶어서 '유인원'이란 object로 사용하고 싶을 수 있다.
int와 float을 예시로 polymorphism을 보자. 만약 int와 float이란 class내부에 숫자를 출력하는 'print'라는 method가 있다고 해보자.
int이든 float이든 상관안쓰고 그냥 'number'로 general하게 인식해서 그냥 'print'를 하고 싶을 수 있다.
이럴때 polymorphism이란 개념을 알면 좋다.(참고)
다형성(polymorphism)이란 내부 형태는 좀 다르지만, interface가 같은 놈들을 표현할 수 있는 능력을 말한다.
이를통해 우리는 서로 다른 종류의 object들의 집합에 같은 message를 보낼 수도 있다.
즉, 위 두 예시에서 우린 저 둘을 general하게 표현한 object에 같은 message를 보냄으로써 해결한다.(이런 개념이 없다면 어떤 object인지 판단해서 알맞은 함수를 호출하는 과정을 거쳐야한다.)
참고로 polymorphism을 구현할때는 interface만 같다고 무조건 polymorphism이 될 수 있는게 아니란 걸 알아야 한다. 의미도 같아야한다.
program이라는 class에 run method를 적용하는 것과 human이라는 class에 run method를 적용하는건 확실히 의미가 다르다.
당연히 이런 경우는 우리가 원하는 결과가 나오지 않을 것이다.
OO 개념 자체가 더 편리한 설계를 위한건데, 특정 프로그래밍 언어의 규칙에서 벗어나지 않는다고 편법을 이용해 기본 OO 개념을 무시해버리면 아무 의미가 없다.
 
dynamic binding은 runtime중에 object의 종류가 무엇인지 결정하도록 하는 기술인데, 이덕에 polymorphism이 가능하다.(C++에서 기술적 측면은 간단하게 배웠어서 여기선 생략..)
 
이제 class위로 한단계 더 올라가보자.
object들의 공통된 특성을 뽑아서 class라는걸 만들었다. 그런데 class에도 공통된 특성들이 있을 수 있다.
예를들어, galaxy class와 iphone class가 있다고 해보자. 이들은 모두 phone이라는 공통 특성이 있다. 우리는 이런 공통 특성을 묶어서 다른 sub class들의 super class로 만들 수 있다.
super class의 역할만 하는 class를 abstract class라고 하고(object를 만들지 않음), inheritance hierarchy의 끝에서 다른 object를 만들어내는 class를 concrete class라고 한다.
inheritance는 redefine 때문에 이름/의미 등이 충돌할 수 있으니 이를 주의해야한다.
 
Jim Rumbaugh와 그 동료들이 Inheritance시 발생할 수 있는 이런 issues를 위한 guideline을 제시했다.
1. query operations은 redefine하지말라
2. 상속된 methods를 redefine한다면, 상속된 것의 의미만을 제한해야한다.(아마 super class의 함수의 의미를 벗어나지 말란 소리인듯)
3. 상속된 method의 기저 의미는 절대 변경돼선 안된다.
4. 상속된 method의 signature(argument list)은 절대 변경돼선 안된다.
하지만 많은 OOP에서 이 guideline을 위반한다.
 
Multiple Inheritance는 single inheritance보다 더 복잡하게 문제가 생길 수 있다.
그래서 OO의 이해를 좀 낮추더라도 MI는 사용하지 않는 편이 좋다.(애초에 지원하지 않는 언어도 있지만...)
사용하더라도 굉장히 주의해서 사용하도록...
 
EncapsulationInformation Hiding이란 용어도 있다. 둘은 서로 관련되지만, 다르다.
Information hiding이란 특정 object를 다루는데 필요한 정보만 그 object밖에서 사용할 수 있도록 나머지 정보들은 숨기는 것이다.(보통 특정 object와는 그 object의 method만을 이용해 소통한다.)
Encapsulation은 간단하게 한 object에 data와 process를 묶어(모아)두는 것이다.
이 두 특성이 잘 구현되면 (내부 동작은 가려지기때문에) reusability는 증가하고, 마치 object를 검은 박스처럼 대할 수 있게한다.(작동 원리를 자세히 알아야하는 편보단 오히려 사용하긴 편리)
 

> 알고있던 encapsulation과는 뜻이 좀 다른 것 같길래 찾아보니 링크에 자세히 답변이 돼있었다. 사람마다 조금씩 의미가 다른 것 같다. 물론 이 글에서 말한게 OO개념에서의 encapsulation의 의미인건 맞겠지만, '그냥 information hiding과 같은 개념이지만 그게 실제 구현된 걸 말할때 주로 encapsulation이라고 하기도 한다.'란 것도 알고 있으면 좋을 것 같다.