|
괜히 딴지 및 비판하는 글로 비춰지겠지만 어찌되었던 한 말씀 드립니다. 이제 막 C/C++을 배운 사람이면 트랙백 건 글은 읽으면 많이 도움 되는 내용임에 틀림 없다. 그러나 사람들은 너무나 절차식~, 객체지향~, C는 절차지향~, C++은 객체지향~ 이라는 선입관을 크게 가지고 있는 것 같다. 원글에서 써니님은 아래 C 코드를 절차지향의 관점에서 이야기 하고 있다.
그러나 나는 이 코드가 매우 “객체지향”적으로 보인다.
똑같은 코드라도 “C는 절차지향”이라는 선입관에 빠져 있으면 코드를 절차지향적으로 읽을 수 밖에 없다. 객체 지향은 언어를 가리지 않는다. C++/C#/Java는 객체 지향을 보다 인간이 이해하기 쉽도록 직관적으로 ‘표현’ 해주는 것에 지나지 않는다. 객체 지향은 언어와는 거의 무관하다. 그 사고 방식은 C 언어에도 얼마든지 적용할 수 있다. 최초의 C++ 컴파일러가 C++ 소스를 C로 변환했던 것을 생각하면 객체 지향이라는 개념은 언어와 큰 상관없다.
하나 더 생각해 보자. 아래 printf 코드가 어떻게 보이는가? 컴퓨터에게 문자를 찍으라고 명령을 내리는 것? printf(“Hello, World!”); 객체 지향적으로 본다면 stdout ‘객체’에 printf라는 ‘메소드’를 실행시키는 것이다. 우리가 쓰는 C 라이브러리도 위에서 언급한 불투명한 타입을 이용하여 매우 객체 지향적으로 만들어져있다. C++ 캡슐화처럼 완벽하지는 않지만 불투명한 타입으로 얼마든지 구현이 가능하다. 예를 들어, Win32 API는 C로 제공된다. 그러나 한번 API를 보면 역시 매우 객체 지향적이다. HWND hWnd = CreateWindow(...); CreateWindow는 윈도우 객체를 만드는 함수고 SetParent는 부모 윈도우라는 ‘속성’을 바꾸는 메소드다.
“에이, 그래도 virtual 함수는 어떡해요?” 라고 물으신다면 역시 이건 virtual 함수의 본질을 모르는 데서 기인한 오해일 뿐이다. C++이 순수 가상 함수로 ‘인터페이스’를 만들 수 있다. C언어는 불가능할까? 가능하다. 왜냐면 가상 함수는 그냥 “함수에 대한 포인터”를 추상화 시킨 것에 불과하다. C언어에서도 얼마든지 C++의 인터페이스를 흉내 낼 수 있다. C struct에 수 많은 함수에 대한 포인터를 선언하면 그게 바로 ‘인터페이스’가 되는 것이다. 실제로 리눅스 커널의 구조체 하나를 보면: struct block_device_operations {이게 뭥미? 바로 ‘인터페이스’다. C++로 표현하면: class block_device_operations {이것과 완전히 동일하다. (물론 overriding 이런 건 안 되겠죠) “에이 그래도 이벤트 핸들러 이런건 힘들자나요~” 라고 물으시면 역시 이벤트 핸들러가 어떻게 구현 되는지 잘 몰라서 벌어지는 사태다. 이벤트 핸들러도 그냥 함수에 대한 포인터, 콜백 함수다. 이걸 가다듬고 추상화한 것이 C#의 delegate과 event이다. Win32 API로 윈도우 프로그래밍을 하면 “event driven”으로 프로그램을 짜야 한다. 메세지 핸들러라는 것이 단순히 WNDPROC이라는 윈도우 프로시저 콜백 함수로 표현되어 있을 뿐이다. 마지막으로 "상속은 안되겠죠?" 상속받을 struct를 멤버 변수로 넣으면 어느 정도 가능하지만 그럴거면 C++을 쓰세요 ㅎ
두 줄 요약:
(솔직히 프로그래밍 언어론적으로 분류를 한다면 C언어는 절차지향으로 분류가 되기는 됩니다.)
p.s. 굳이 딴지 거는 것 같아 말을 하지 않고 있었지만 써니님의 이 글을 보면 큰 오류가 두 개 있다.:
이것은 사실이 아니다. 아주 명백한 예를 하나 들면 난수를 만들어 주는 srand, rand는 ‘전역 변수’를 참조하고 있고 이 두 함수들은 C 기본 라이브러리에 매우 잘 포함되어 있다. 좀 더 정확하게 말하면 멀티스레드 환경을 고려해 재진입 가능하게 만들어야 하므로 이제는 ‘전역 변수’, static 변수가 아니라 스레드 로컬 변수로 구현을 하고 있지만 DLL과 정적 라이브러리에 데이터를 export하는 것은 아무런 문제가 없다. (참고 글)
C언어가 전역 변수로 문제를 많이 일으킨다고 말씀하셨는데 이것도 너무 비약된 말씀이다. C++, 자바에서도 얼마든지 남발된 클래스 멤버 변수나 static 변수로 똑같은 문제를 겪을 수 있다. 이건 언어의 문제가 아니라 디자인의 문제일 뿐이다. 클래스 멤버 변수도 누가 변경할지를 명확하지 않으면 개판되기 일쑤다. 함수와 프로시저를 엄격히 구분하는 함수형 언어에서도 어쩔 수 없이 프로시저가 있을 수 밖에 없고, 그럴 경우 전역 변수로 인한 문제는 일어날 수 밖에 없다. C/C++/Java 같은 imperative 언어들은 함수(function)과 프로시저(procedure)를 구분하지 않는다. 프로그래밍 언어 관점에서 함수는 전혀 side-effect가 없어야 한다. 즉, 함수는 주어진 매개 변수만을 조작하여 외부 상태를 전혀 건들이지 않고 값을 반환해야 한다. ‘전역 변수’에 의한 문제점을 없애려면 순수한 함수로, 프로시저 없이 프로그램을 짜야만 할 것이다. 그리고 C언어는 전혀 몰락하지 않았습니다. 앞으로도 몰락하지 않습니다.
최근 등록된 덧글
개발자 입장에서의 수많은 ..
by Jiyoon at 02/04 저도 아들 돌잔치때 돌잡이 .. by 박상욱 at 01/18 미국 대학원 원서 작성중에 p.. by 태클사이야 at 01/13 TO: 박PD 로그인 하지 않아.. by 박응용 at 01/10 http://gigglehd.com/zbx.. by dhunter at 12/28 우와.. 좋네요. 태반이 .. by 윤광배 at 12/17 항상 좋은 글 잘 보고 있습니.. by y2k at 11/23 글이 좋아서 제 블로그에 담.. by 쏭섭 at 11/23 최근 등록된 트랙백
메뉴릿
이글루 파인더
|