Skip to content

Latest commit

 

History

History
182 lines (138 loc) · 8.67 KB

OOP(object-oriented_programming)_1.md

File metadata and controls

182 lines (138 loc) · 8.67 KB

OOP

Object-Oriented Programming


개요

프로그램 설계 방법론의 일종, 명령형 프로그래밍에 속한다.
프로그램을 단순히 데이터와 처리 방법으로 나누는 것이 아닌,
프로그램을 수많은 객체_object라는 기본 단위로 나누고, 이들을 상호작용하는 방식이다.
객체란 하나의 역할을 수행하는 "메소드와 변수(data)"의 묶음으로 봐야한다.

편의상 class나 public 같은 Java에서 사용하는 용어를 사용하지만,
이들 외에 다른 표현 방식을 사용하는 언어 또한 존재한다.
객체 지향은 특정 언어가 아니라 개념이다.

접근 제한자

class, libary 등 객체를 만들어내는 명령어의 집합들은 이를 만든 개발자의 의도대로만 움직여야 한다. 클린코딩/시큐어코딩
그러한 이유로 객체가 동작하는 내부에는 접근을 못하게 하는데,
이를 "접근 제한자"를 이용해서 조절하고 있다.

  • 만약 이를 이용하는 개발자가 다른 의도로 이 객체를 바꾸고 싶다면, 상속해서 이용해야 한다.
  • encapsulation
  1. Python : 접근 제한자를 가지고 있지 않다. (유명무실 하다.)
  2. C++, Java : public, private, protected (, Java에서 default 추가)
  3. JavaScript : prototype

명령형 프로그래밍

Imperative Programming
프로그램의 상태에 대한 문장들을 작성하는 스타일.
상대적인 개념으로 선언형 프로그래밍(declarative programming)이 존재한다.




역사

OOP 출현의 이유


1. 초기의 프로그래밍 방식은 절차적 프로그래밍 방식이었다.


입력을 받으면, 명시된 순서대로 처리한 다음, 결과를 낸다.
프로그램을 명령어의 모음으로 인식한 방법이고,
"어떤 논리를 어떤 순서대로 써나가는 것인가"라는 단순한 기술이었다.
이는 데이터를 어떻게 취급할 것인가에 대해서는 깊게 생각치 않는 방법이다.

여기서 말하는 절차적 프로그래밍은 C가 아니다.

말그대로 한줄씩 읽어 나가는 절차적 프로그래밍이고, "언어"라는 개념이 나오기 전이다.
"C 언어"는 절차 지향 "언어"이다.
여기서 말하는 절차적 프로그래밍의 대표적인 예는 "어셈블리어"이다.
우리가 사용하는 "언어"는 인터프리터나 컴파일러를 통해
자동으로 메모리와 레지스터 관리 등을 해주는 고급언어이고,
어셈블리어는 직접 메모리의 관리와 상태 변환을 시켜줘야하는 언어이다.

이러한 절차적 프로그래밍의 한계 때문에 "언어"가 개발되게 되었다.



2. 절차적 프로그래밍 방식의 한계


"어떤 논리를 어떤 순서대로". 프로그래밍은 순서도로 나타낼 수 있다.

프로그래밍 전반에 걸쳐 기획 및 개발 단계에서 순서도를 이용해서 논리를 표현한다.
절차적 프로그래밍 방식은 프로그래밍을 설계하는 단계에서
복잡한 알고리즘의 경우 순서도로 표현하는 것이 불가능할 정도로 꼬인
소위 "스파게티 코드"를 만들게 된다.

꼬여버린 코드는 다른 사람이 보고 이해하는 것(협업)이 거의 불가능 하고,
작성한 본인조차도 유지보수에 어려움을 겪게 된다.

  1. 명령어의 양이 많아진다.
  2. 코드의 연결성을 파악하기 힘들다.
  3. 중복 코드에 대한 대처도 어려워진다.

순서도 (flowchart)

어떠한 일을 처리하는 과정을 순서대로 간단한 기호와 도형으로 도식화한 것으로,
여러 분야에서 프로세스나 문제의 분석, 기획, 디자인, 설계나 관리 등 폭넓게 쓰인다.



3. OOP의 전신의 등장


상술한 문제를 해결하기 위해, 에르허츠 다익스트라(Edsger Wybe Dijkstra)가
GOTO문의_해로움 이라는 논문을 저술하게 된다.

이 논문은 프로그램을 procedure(프로시저) 단위로 나누고, procedure 끼리 호출하는
"구조적 프로그래밍" 이라는 방식을 제안하며 절차적 프로그래밍의 한계를 넘게 된다.

큰 문제(program)를 작은 문제들(procedures)로 쪼개서 해결하는 방식인
하향식(Top-down) 방식이 쓰이는 프로그래밍 방식이다.

procedure

프로그램을 작은 단위로 나눈 것으로, 후에 함수로 발전하게 된다.
Python이나 Java는 method 라 하고, c++은 procedure 라고 부른다.
대개는 함수라는 표현이 통용되며,
메서드의 경우 클래스 혹은 라이브러리 내 함수를 지칭하는 용어로서 쓰는 경우가 많다.

GOTO 문

우리가 사용하는 언어에서 콜러(caller)가 함수를 호출하면,
콜리(callee)가 호출에 응답(response)하여 연산을 진행하고 다시 제 위치로 반환된다.

하지만 초기의 언어에는 "함수"가 존재하지 않았고, GOTO문을 이용해서 콜러와 콜리를 구분해 주었다.
이러다 보니 코드 길이가 길어진 상태에서, 코드스페이스 메모리 영역밖으로 GOTO가 보내버리면
이상한 곳으로 가게되어 코드 자체가 이유도 모른체 꼬일 수 있다.
(찐 맞왜틀)

(참고) 코드스페이스가 그렇게 길어??

개발자는 항상 연산 시간과 저장공간을 신경써야 하는데,
우리가 사용하는 언어 수준에서 우리가 신경써야 할 부분은
알고리즘의 효율성과 code영역, heap영역, stack영역 정도이다.

register에 변수를 mapping해서 보낸다든가, 잠시 안쓸때는 heap에 얼마나 저장한다던가, 언제 다시 꺼낸다던가 전혀 신경 쓸 필요가 없는 것이다.

그런데 어셈블리어는 레지스터에서 변수를 사용하다가도

  1. "이거 일단은 사용할 필요 없으니까 heap에 보내놓고~"
  2. "이제는 사용하지 않는 register 영역에 새로 할당할(or 데이터 갱신한) 변수 넣고~"
  3. "연산 이렇게 해줘서 나온 값을 다음 register 영역에서 갱신하고~"

이런식으로 다 명령어(instruction용 명령어)로 적어줘야 하는 것이다.
코드 길이가 길어지면서 생기는 여러 문제들이 발생할 수 밖에 없었고,
복잡한 알고리즘을 코드로 짜는 것은 불가능에 가까웠다.

  • (프로그래밍 언어의 출현에 관한 야사)
    계산을 더 효율적으로, 더 구조적으로 하면
    어떠한 복잡한 알고리즘도 어셈블리어로 구현 가능하다는 주장을 하며
    programming language의 출현을 반대하는 이가 있었다.
    근데 그 사람이 리처드 파인만이라 너만 되는거 아니냐면서 결국 언어가 만들어지게 되었다 "카더라".



4. 구조적 프로그래밍의 한계

"구조적 프로그래밍"의 함수는 데이터 처리 방법을 구조화 했을 뿐, 데이터 자체는 구조화하지 못했다.
이는 전역 name space 포화 문제(변수 이름을 다 써서 이름을 짓지 못하는 상황..)를 야기하였다.

엉뚱한 데이터가 엉뚱한 함수에 전달돼서 데이터를 오염시키는 문제가 발생할 수 있고,
그런 가능성 때문에 프로그래머가 한 함수의 작동에 영향을 받는 변수를 조사하기 위해
모든 변수를 다 조사해야 하는 상황이 벌어지게 되었다.

이게 변수의 개수가 수백 개 이하인 코드에서야 사람의 힘으로(ㄷㄷ..) 가능했지,
코드의 덩치가 커지면서 함수가 접근할 수 있는 데이터의 범위에
명시적인 제한을 걸어야하는 상황이 도래했다.

이를 해결하기 위해 나온것이 객체 지향 프로그래밍 개념이다.




OOP

큰 문제를 작게 쪼개는 것(Top-down)이 아닌
작은 문제들을 해결할 수 있는 객체(object)들을 만든 뒤
이 객체들을 조합해서 큰 문제(program)를 해결하는 방식(Bottom-up)



(다음 이 시간에...)




reference

나무위키

flowchart