[개체지향] 소수설에서 태어난 다양한 주장들
소수설에서 태어난 다양한 주장들
지금까지 우리가 배운 것
- 주류 oo
- 이런저런 소수설
- 다양한 소수설 같지만 사실 한두 손안에 꼽을 수 있는 사람들이 주장해온 것
소수설까지 알아야 하는 이유
- 고집불통 소수설 신봉자들이 있기 때문
- 일하다 보면 잘못된 곳에 소수설을 주장하며 일을 그르치는 사람들
- 소수설이 틀리단 말이 아님
- 말도 안되는 주장을 하는 사람에 대처하는 자세를 익히기 위해서
복습 OOP 토론시 피해야 할 사람
- 처음듣는 주장을 하며 그건 올바른 OOP가 아니야 라는 사람
- 이건 순수 OOP언어가 아니야 라는 사람
- 모든 프로그램은 OOP로 만들어야 해 라는 사람
- 어쩌고 한 누구가 이리 말했으니 너는 틀려 라는 사람
- 이 방법만 따르면 문제가 해결돼 라는 사람
ADT PDA
- OOP 초창기에 OOP를 바라보던 두 가지 관점
- Object Oriented Programming Versus Abstract Data Type
- 이를 가장 잘 정리해둔 논문 (William R. Cook)
- 현재 OOP는 둘다 섞여 있음
- ADT(Abstract Data Types)
- PDA(Procedural Data Abstraction)
- 다수설의 입장과 마찬가지로 ADT가 좀 더 많이 들어있음
소수설은 기본적으로 PDA의 입장
- 초창기 소수설 주창자 중 가장 영향력 있는 사람 : Alan Kay
- 특히 OOP라는 용어를 처음 만든 사람으로 유명
- Alan Kay의 OOP정의 OO의 핵심은 메시지
- 본인의 주장을 Smalltalk란 언어로까지 만든 훈륭한 사람
-
생물학 수학 전공
- 극단적 주장을 하는 사람들도 주로 PDA에 기반을 두고 있음
- 자기들의 주장에 대한 근거를 Alan Kay도 그랬다는 식으로 대곤 함
- 확인해 보면 Alan Kay는 보통 그런적이 없음
- 근거가 빈약한 사람들이 권위에 호소하려고 Alan Kay를 이용할 뿐
- Alan Kay의 명예 회복을 위해 다음의 인터뷰를 소개
- Dr. Alan Kay on the Meaning of Object Oriented Programming
Alan Kay가 개체를 바라보는 입장
- 그에게 개체란 생물학에서의 세포 같은 존재
- 즉 자기 결정권을 가진 어떤 생명체
- 자신이 생물학을 전공했기에 그렇게 본다고 말함
- 굳이 컴퓨터 환경에서 비슷한 것을 찾으면 네트워크에 존재하는 컴퓨터
- 우리가 생각하는 단순한 개체보다는 어느 정도의 자기 결정권을 가진 존재
- 개체로부터 데이터란 존재를 지워버리고 싶었음
- 데이터가 없으니 개체 간의 상호작용은 메시지를 통해서만
- 확실한 PDA 진영
- 그가 개발한 스몰토크도 개체들로 구성된 살아 숨 쉬는 환경
- 별도의 프로그램을 만들어 배포한단 개념이 없음
- 모든 개체들이 존재하는 하나의 시뮬레이션 환경
- 스몰토크 코드 편집기까지도 개체를 고치면 곧바로 변경됨
Alan Kay가 이용당하는 경우들
내 주장은 Alan kay의 주장에 기초하고 있기 때문에 옳은 방법이다.
- Alan Kay가 처음 OO를 창시한 사람이다
- ~는 정적 타입언어에 반대한다
- ~는 이른 바인딩에 반대한다
Alan Kay는 자기가 OO창시자라고 하지 않음
- 이미 ADT를 기반으로 개체지향 비슷한 움직임은 진행되고 있었다고 함
- 거기에 자기만의 주장을 했다고 함
- 하지만 소프트웨어 공학자들은 이 의견을 받아들이지 않았음
- 그 대신 ADT를 기반으로 오늘날의 개체지향을 완성시킴
- 자기 주장에 기반을 둔 소수설이 아직까지 있는게 신기하다 생각
개체지향이란 용어를 처음 말한 건 맞다
- 지금 하고 있는 게 뭡니까? 라는 물음에 답하면서 나온 용어
- 그러나 지금 생각해보면 그 용어는 잘못된 거였다고 인정
- 오히려 메시지 지향(message oriented)이라고 했어야 한다고 함
- 개체를 구성하는 데이터는 중요하지 않고 메시지 전달만 중요하기 때문
- Alan Kay의 메시지는 요즘 OO언어의 함수 시그내처와 좀 다름
- 이런 생각을 프로그래밍 언어로 만든 것이 스몰토크
- 즉 현재 개체 지향이라 불리는 것은 Alan Kay의 주장과 많이 다름
우리가 흔히 생각하는 메서드 호출
public class Calculator{
public int add(int a, int b){
return a + b;
}
}
int val = add(1,2);
스몰토크의 메서드 호출
- 스몰토크에는 이미 존재하는 메서드를 호출한단 개념이 없음
- 컴파일 중에 올바를 메서드 시그내처를 호출하는지 검사도 불가
- 그 보다는 다른 개체에게 이거해줘 라고 메시지만 보내는 시스템
- 그 개체는 그걸 해주는 메서드를 가지고 있을 수도 아닐 수도 있음
- 아니더라도 요청자는 여전히 메시지를 보낼 수 있음
public Object execute(String methodName, Object[] args){
switch(methodName){
case "addd":
//args[0] + args[1] 반환
case "mad"
// args[0] * args[1] + args[2] 반환
}
//...
}
- 인자 수 모자라면, 인자가 다르면, Name이 없는거라면 예외를 던질 수 밖에없음
스몰토크의 다형성
- 어떤 메서드 시그내처를 미리 정의하고 따르는 개념이 아님
- 따라서 다형성이 부모 클래스의 공통 시그내처에 의존하지 않음
- methodName에 들어오는 문자열만 처리할 수 있다면 그게 다형성
- 업계에서 일반적으로 말하는 다형성이 아님
스몰토크는 예외를 많이 던질수 밖에 없음
- 주류 OO언어에서 컴파일러가 검사해주는 것도 스몰토크는 예외로
- 매개변수 수가 틀려도
- 메서드 이름이 잘못되어도
- 매개변수 형이 틀려도 예외
- 굉장히 많은 것을 예외에 의존하니 예외 처리가 중요해짐
- 안그러면 제대로 도는 제품을 만들기 어려움
- 예외 발생 시 회복해서 프로그램을 잘 돌게 만들어야 하는 일이 더욱 빈번
동적 타입을 선호할수록 예외로부터 안전한 프로그래밍을 중시(단, Alan Kay의 주장은 아님)
스몰토크의 모든 것은 늦은 바인딩
- 모든게 동적 == 늦은 바인딩
- 특히 Alan Kay는 모든것에 극도로 늦은 바인딩을 원했음
- Alan Kay의 이런 자세를 다음과 같이 주장을 하는 사람이 악용
- 정적타입보다 동적 타임이 옳습니다.
Alan Kay는 정적 타입에 반대했나?
- 인터뷰에서 전혀 안 그렇다고 말함
- 오히려 자기는 정적 타입 언어를 사용할때 힘들었다고 말함
- 그래서 자기가 설계하는 언어는 동적 타입을 사용했다고
- 즉 Alan kay는 컴퓨터 데이터를 보는 훈련을 거치지 않은 사람
Alan Kay는 겸손하고 훌륭한 과학자
- 자기가 뭘 알고 뭘 모르는지 확실히 인지하고 있음
- 자기의 주장이 소수설임을 확실히 인지하고 있음
- 자기의 주장이 널리 안 받아들여져도 그에대해 분개하지 않음
- 오히려 자기의 소수설을 실제 작동하는 언어로 완성시킴
고로 Alan Kay를 동적 타입이 옳다는 주장에 대한 권위자로 들 수 없음
동적타입은 실수를 유발한다.
- 동적 타입 시스템에서는 컴파일러가 프로그래머 실수를 많이 못 잡아줌
- 공짜 혜택을 제 발로 걷어차지 말자
다른 분야에서도 극단적 주장을 함
- 프로젝트 관리
- 품질보증 QA
극단적인 사람들의 예
- 모든것에 interface를 사용해야한다고 주장한 사람
- SOLID 설계정신을 정리한 사람
- 클래스 하나에 넣을 수 있는 최대 메서드 수는 4개라는 사람
- setter를 절대 사용하지 말아야 한다는 사람
- 오류 상황은 예외로만 처리해야 한다는 사람
익스트림 프로그래밍
- eXtreme Programming (XP)
- 애자일 소프트웨어 개발론 중의 일부
- 코드를 어떻게 작성해야 하는가를 고민하는 게 아닌
- 90년대부터 다양한 소프트웨어 개발 방법을 주장
- 어떤 주장이든 간에 소프트웨어 품질을 높이는 게 목적이라고 말했었음
- 많은 주장들은 아예 받아들여지지도 않았음
- 일부는 실제로 흥했지만 대부분 짧게 흥했다 시들해지는 패턴 반복
pair programming
- 짝 프로그래밍
- 90대 말 2000년 대 초에 꽤 흥했던 유행어
- 프로그래밍 관련 잡지에서도 여러 번 소개
- 실제로 도입한 회사들도 제법 있었음
주장 둘은 하나보다 낫다
- 두명이 같이 일하니 실수를 서로 잡아줘 버그가 줄어듦
- 따라서 품질이 높아짐
- 당연한 이야기
잠시 흥하고 사라진 이유
- 실제 효과를 측정해보니 가성비가 안 맞음
- 한 리서치에 따르면 페어 프로그래밍 후 문제가 약 15%줄음
- 버그 15%감소가 인건비 2배보다 중요한 회사는 할 것임
- 하지만 그렇지 않은 회사가 대부분
- 이제 이런 헛소리 믿는 사람은 거의 없음
- 하지만 코드 리뷰 프로세스는 남아서 업계에 도움을 줌
지속적 통합 (CI cContinuous Integration)
- 원래는 Grady Booch(UML 창시자)가 주창한 방법
- 이런 문제를 해결하려고 함
예시
- A브랜치에서 A팀 진행중
- B브랜치에서 B팀 진행중
- A,B 브랜치 병합 : merge 충돌
- A팀 팀장이 어떻게든 충돌 난 코드를 다 고침
- 그러나 실수해서 버그 몇 개가 나옴 그것도 다 고침
- A팀에서 기존의 어떤 로직에 기초해서 개발을 했는데 B팀이 그 로직 작동법을 바꿈
- 두 팀이 같은 코드를 고친 건 아니지만 가정이 달라지면서 A팀의 일이 도루묵이 됨
지속적 통합 (CI cContinuous Integration)
- 서로 각자의 브랜치에서 오랫동안 작업을 진행하지 말자
- 종종 한 브랜치로 합쳐서 최대한 최신 코드에서 작업하게 하자
- 실제 이 방법은 요즘 많이 쓰임
- 가장 큰 이유 : 브랜치 관리가 쉬운 버전 관리 시스템이 등장
- 정말 좋은 방법
- 허나 이건 XP가 주장한 CI가 아님
XP의 CI는 극단적인 규칙을 만듦
- 합치는 횟수는 반드시 하루에 여러 번이어야 한다
- 그것도 모든 프로그래머의 작업물을 합쳐야 함
- 이유 : 언제나 최신 버전에서 작업하니 시간 낭비를 막을 수 있다
하루에 브랜치를 몇 번씩 합치려면
- 한 프로그래머가 하루에 완성하는기능이 여러 개라는 이야기
- 매우 간단한 기능을 구현할 때나 가능
- 설사 그렇더라도 테스트하는 시간도 필요
- 원칙 : 개발자는 반드시 자기가 개발한 기능을 테스트한 뒤 커밋해야 함
- 버그 있는 코드를 마스터에 합치면 다른 프로그래머가 일을 못하기 때문
- 아주 간단한 기능만 만들어도 테스트하는 시간이 필요
XP의 CI가 특히 문제인 부분 : 테스팅
- 어떤 기능을 가장 먼저 테스트하는 사람은 그 기능을 구현한 프로그래머
- 하지만 구현자가 잡을 수 있는 버그에는 한계가 있음
- 버그가 발생하는 가장 큰 이유 : 구현자가 요구사항을 잘못 이해해서
- 이런 이유로 구현을 잘못한 사람은 그 문제를 스스로 알아채기 어려움
그래서 전문 테스터가 존재
- 전문 테스터로 이 모든 걸 테스트하려면 인건비가 엄청나게 듦
- 단순히 새로 구현된 기능만 테스트하는 것이 아님
- 그로 인해 다른 것들이 망가질 수 있으니 전체적인 테스트를 해야함
- 그러면 프로그래머 수 이상의 테스터가 필요하다는 이야기?
따라서 하루에 여러번은 좀 무리수
- 프로그래머가 만드는 기능의 크기에 따라 하루 한 번도 어려울 수 있음
- 어떤 경우에도 하루 여러 번 합쳐야 한다는 사람은 경험이 부족한 사람
- 다행히도 업계가 이 꼬임에 빠지지는 않았음
- Grady Booch 아저씨의 CI개념이 이미 훌륭했기 때문
- 업계에서 CI라고 하면 XP의 CI가 아님
하지만 포기하지 않았다…
- XP는 이 문제를 굳이 프로그래밍으로 해결하겠다며다른 방법론을 주장
- TDD: 테스트 주도 개발(Test Driven Development)
- 이 방법론은 최근에 흥했다가 다시 수그러들고 있는 중
- 아직도 근본적인 문제를 직시 못하는 해결법
테스트 주도 개발
- 개발 과정을 테스트 우선으로 바꿈
- 기능을 구현하기 전에 반 드 시 테스트하는 코드부터 만들어야 함
- 기능부터 만들던 기존의 방법과 반대
- 테스트코드를 작성하는 사람 == 기능을 구현하는 사람
- 매우 큰 문제
TDD 하에서 프로그래머의 개발 과정
- 어떤 기능을 만들어야 하는지 숙지함
- 제품 책임자(product owner)등이 제공한 사용자 스토리나 명세 등을 통해
- 당연히 회의 등을 소집해서 토론할 수 있음
- 그 기능이 제대로 동작하는지 테스트할 코드를 만듦
- 아직 기능은 구현하지 않았음
- 주로 단위테스트(unit test, 메서드를 하니씩 테스트)를 이용
- 보통 메서드 호출 뒤 그 결과가 예측한 결과와 일치하는지 비교
- POCU의 과제, 실습에서 제공하는 테스트 코드와 비슷
- 기능을 구현
- 2에서 만든 테스트를 실행
- 실패하면 잘못 구현한 것 : 3으로 돌아감
- 통과하면 제대로 구현한 것
- 이미 소스코드 저장소에 있는 다른 단위 테스트들을 모두 실행
- 실패하면 내가 남의 코드를 고장 낸 것 : 3번으로 돌아감
- 통과하면 아무 문제 없는 것
- 구현 코드와 테스트 코드를 모두 소스코드 저장소에 추가
XP진영의 주장
- TDD를 사용하면 극단적인 CI를 해도 문제 없음
- 하루 여러 번씩 브랜치를 합쳐도 코드를 통해 자동으로 테스트
- 단 구현되어 있는 모든 함수에 대해 단위 테스트를 만들어야 함
- 코드 커버리지 100%
- 언제나 모든 코드를 테스트하니 품질이 높아짐
TDD를 하면 정말 품질이 높아지지만…
- 당연히 모든 코드에 단위 테스트를 실행하면 품질이 높아짐
- 다른 조건이 다 동일할 경우의 이야기
- 그러나 다시 근본적인 문제에 대해 생각해야 함
- 품질이 얼마나 높아지는가?
- 그러려면 드는 비용(ex: 테스트 코드 작성하느라 생산성 저하)은 얼마인가?
- 업계가 페어 프로그래밍을 포기했다는 사실을 잊지 말자
- 과연 제대로 된 테크트 코드를 작성할 수 있는가 라는 문제도 있음
TDD는 설계능력을 향상시켜 준다는 주장
- TDD는 함수 별로 단위 테스트를 돌려야 함
- 따라서 프로그래머는 기능 하나하나를 작은 함수로 분리해야 함
- 모듈화, 유연성 향상
경제논리와 안전
- 버그가 없는 프로그램을 만들고 싶어 하는 장인정신은 존경
- 하지만 실상은 경제논리에 따라 좌우된다
- 종종 제품 개발비를 아끼려 최종 사용자에게 테스트를 미룸
- 이상적인 세계에서는 모든 버그를 다 잡고 출시하는 게 맞음
- 하지만 약간 불안정한 제품을 사용하면서 할인을 받으려는 사용자도 충분
- 단 인간의 생명을 위태롭게 할 수 있는 버그라면 경제논리는 후순위
현존하는 테스트 중 단위 테스트는 가장 비효과적인 테스트 중에 하나임
효과적인 테스트 : 최종 테스트 vs 부품 테스트
- 최종 제품 테스트와 부품 테스트 중 하나만 해야 한다면
- 최종 제품이 제대로 작동하는 게 제일 중요하기에 최종 제품 테스트
- 부품에 문제가 없어도 최종 제품에 문제가 있을 수 있음
- 최종 제품 테스트도 UI 자동화를 통해 자동 테스트 가능
- 물론 제품 규모가 커지면 최종 제품만 테스트만 할 수는 없다
- 적당한 크기로 분리한 각 부분의 동작을 테스트하는 게 더 효과적
- 하지만 과연 적절한 크기가 함수 하나일까?
효과적인 테스트 : 테스트의 주체
- 같은 사람이 구현과 테스트를 모두 하는 건 효과적이지 못함
- 이미 실수르르 하고 있는 사람이 자신의 실수를 알아채기는 힘듦
- 자동차 업계에서도 제조자와 안전성 테스트 하는 사람이 다름
- 즉 테스트 전문가가 있음
- 테스트 프로세스도 보통 인증 받은 정형화된 프로세스
테스트는 전문가에게 맡겨라
- 소프트웨어 개발 업계에서도 테스트 전문가(QA)가 있음
- 제품을 오작동하게 만드는 상황을 찾는 데 특화된 인력
- 프로그래머가 방패라면 QA는 창
- 안전을 중요시하는 곳에서는 표준화된 QA프로세스를 따라 테스트 함
POCU 학생들의 습관을 봐도 이게 보임
- 내가 작성한 테스트 코드를 다 통과해도 점수는 100점이 안 됨
- 빌드봇이 틀렸다고 잡아줌
- 남이 만든 테스트 코드에서 잡힘
- 위에서 내가 작성한 테스트 코드가 바로 TDD
- 그러면 내 테스트 코드를 더 꼼꼼히 작성 안 하는 이유는?
- 가성비
- 남의 테스트가 더 효율적/효과적이란 사실을 이미 잘 알고 있음
코드 커버리지 100%를 위해
- 아주 간단한 더하기 함수 같은 건 단위 테스트를 작성하기 쉬움
- 그보다 훨씬 복잡한 예는? (예: DB속 데이터가 필요한 기능)
- DB 접속이 안 되어 있으면 테스트 불가능
- 테스트 실패 시 DB 문제이지 내 코드 문제인지 모름
- 따라서 TDD에서는 이런 경우 DB에 직접 연결하지 말라 한다
- 그 대신 DB의 동작을 그대로 흉내내는 mock개체를 만들라고 함
- 이 개체는 실제 데이터가 아니라 테스트 데이터를 반환
단위 테스트와 mock 개체의 비용
- 단위 테스트를 하는 메서드 범위 밖의 많은 테스트용 개체를 만들어야 함
- 그 후 실체를 바꿀 때마다 테스트 개체도 바꿔야 함
- 그와 반대로 1주에 한 번 정도씩 코드를 다 합쳐 전체 테스트를 하면?
- 전문 QA들이 테스트
- 혹은 UI 자동화 프로그램을 이용한 자동 테스트
- 테스트용 개체 제작에 시간을 낭비할 필요가 없음
단위테스트의 용도
안전이 매우 중요하다면 고려할만하다
- 단 이미 최종 테스트도 하고 전문 테스터도 있는 경우
- 안전이 매우 중요하다면 가성비가 안 좋은 TDD까지 추가할 수 있음
- 타 업계도 안전이 중요하면 부품까지 꼼꼼히 테스트하는 것과 마찬가지
전문 테스트 인력이 없어도 고려해볼 만하다
- 테스터 대신 프로그래머에게 TDD를 시키는 건 이상한 이야기
- 일반적으로 테스터의 연봉보다 프로그래머 연봉이 높음
- 하지만 아예 테스터가 없는 경우도 있음
- 예 개인이 진행하는 오픈소스 프로젝트
- 전문 QA를 하나라도 둘 만큼 프로그래머의 아웃풋이 많지 않음
- 이럴 때는 테스트를 아예 안 하는 것보다 단위 테스트라도 있는 게 나음
- 하지만 여전히 UI자동화를 통한 최종 제품 테스트가 더 효과적
단위테스트가 무조건 나쁘다는 게 아니다
- POCU 아카데미 내부 기술에서도 사용하는 곳이 있음
- 특히 비지니스 로직과 먼 알고리듬 관련 기능일 때 쉽게 사용 가능
- 매개변수만으로 어떤 함수에 필요한 데이터를 모두 전달 가능
- 이미 정형화된 알고리듬이라 바뀔 일이 적음
- 원래 제대로 작동하던 데이터가 기능 수정 후에도 멀쩡한지 확인하는 용도
다른 테스트 방법이 더 효과적인 기능들
- 자주 변하는 기능
- 다른 서브 시스템에 의존하는 기능
- 기술적이기보다 비즈니스 로직을 구현한 기능
단위 테스트를 위한 다형성
모든걸 인터페이스로 만들어야 한다
- 왜냐면 이제 구현이 두 개
- 실제 개체 클래스 하나, mock 개체 클래스 하나
- 따라서 모든 메서드를 인터페이스로 표현해야 함
- 테스트할 땐 mock 클래스
- 실제 프로그램 실행할 때는 실체 클래스
- 즉 단위테스트를 위한 다형성을 주장
역사는 흘러 심판의 시간 : Python
- Python은 Guido van Rossum가 만든 대표적인 동적 타입 언어
- 이 분이 은퇴 전에 일했던 마지막 회사 DropBox
- 마지막까지 정적 타입이 없어 생기는 문제를 해결하려고 엄청 노력
- 프로그래머 수가 무지 많음
- 코드그ㅏ 400만 줄이나 됨
- 따라서 동적 타입 때문에 라이브 환경에서 생기는 문제들이 너무 심각했음
- 동적 타입 언어 때문에 라이브에서 문제 생긴 다른 제품도 많음
- 궁금하면 검색해볼 것
역사는 흘러 심판의 시간2 : JavaScrpt
- 대표적인 동적 타입 언어
- 웹 프론트엔드에서 주로 사용해옴
- 최근에 프론트엔드 기술 발전과 더불어 동적 타입이 문제 됨
- 그걸 고치려고 나온 프로그래밍 언어 중 가장 대표적인 게 TypeScrpt
- 처음엔 동적 타입이 최고라며 이건 실패할 거라 하는 사람이 많았음
- 몇 년 지나보니 주류 프론트엔드 프레임워크가 TypeScrpt를 기본으로 지원