C와 C++ 경계선에 대한 궁금증요....
글쓴이: kknd345 / 작성시간: 월, 2005/05/02 - 1:22오전
요즘에 한창 C++ 배우고 있는 학생입니다.
그런데 보통 제 친구들 경우 C와 C++ 의 경계선을 두고 있는 것 같습니다. 전 실무 경험 있는 선배한테 듣기로 C와 C++ 을 구지 구분 할 필요가 없다고 들었는데요.
친구들 이야기 하는 거 들어보면 조금 갑갑하기도 합니다. 클래스에서 printf 썻다고 C++탈을 쓴 C라면서 머라고 하는데.....
여러분 의견은 어떤가요?
그리고 정컴에서 모든걸 클래스화 하려는 경향이 강한데... 학년이 낮아서 그런지는 몰라도 실제로 모든 걸 클래스화 하는 버릇이 좋은건가요?
Forums:
[quote]주어진 코드를 개념적으로 가장 깔끔하게 유지하는 방법중 하나
음. 구현을 몰라도 되는 것과 이것과는 좀 다른 이야기인 듯 합니다. 사실 리팩토링에서는 이와 정반대로 이야기하고 있습니다. 처음부터 완전한 컴포넌트란 있을 수 없죠. 개발을 진행하면서 변경이 일어나는 것을 피할 수 있는 경우는 존재하지 않습니다. 하지만 리팩토링은 이러한 변경이 계속되어도 코드가 지저분해지기는 커녕 더 깔끔해지게 만들죠. 그리고 이런 리팩토링이 잘 되려면 다른 사람의 코드를 볼 수 없는 것이 아니라 오히려 [url]http://c2.com/cgi/wiki?CollectiveCodeOwnership CollectiveCodeOwnership[/url]이 요구됩니다. 누구의 코드든 자유롭게 수정할 수 있는 것이죠. 전 확실한 역할 분담은 오히려 싫어하는 편이죠.
그러면 이럴 때 레이어가 깊어지면 장애가 되지 않느냐..고 할 수 있겠지만 현실은 그렇지 않습니다. 필요한 만큼만 내려가면 되거든요. 이를테면, A가 B를 쓰고 B가 C를 쓰는데 A를 쓰다가 문제가 생겨 A를 고치고 싶으면 A까지만 내려가서 일단 고쳐봅니다. 그래서 되면 B, C는 볼 필요 없죠. 만약 이게 A,B,C가 묶여 있다면 한 레이어만 내려가면 되지만 그 레이어에서는 A,B,C를 모두 검토해야합니다. 한 번에 검토해야할 코드량이 늘어나는 것이죠. 하지만 이게 레이어가 깊어지면 불투명해지는 대신 한 번에 검토해야할 코드가 줄어들어 그 코드의 신뢰성이 높아집니다. 하나하나의 코드의 신뢰성을 높이면 전체의 신뢰성이 높아진다..이것이 리팩토링의 가치 중 하나이기도 하죠. 제가 항상 OOP의 장점으로 리팩토링 파워가 높다는 것을 꼽는데 그것도 바로 이런 이유입니다.
자바가 좋은 점 중 하나는 엔터프라이즈 애플리케이션을 위한 컴포넌트들이 오픈소스로 상당히 많이 나와 있다는 것입니다. 자카르타, 오픈심포니, 코드하우스 등 많은 공동체가 있고 여기서 나온 컴포넌트들을 자바 프로그래머라면 다 한 번씩은 써보게 됩니다. 그런데 이런 것들을 쓸 때 프로그래머들이 소스를 뒤져가면서 쓰느냐..하면 결코 그렇지가 않습니다. 다 그냥 API만 보고 가져다 씁니다. 심지어 자카르타의 commons에 있는 것들은 javadoc에 내용 하나도 없는 class도 많습니다. 그래도 클래스 이름이랑 메쏘드 이름만 보고 잘 가져다 씁니다. 딱히 그 오픈소스 공동체가 뛰어난 사람들이 모여서 그런 것도 아니고 프로그래머들이 그걸 그냥 신뢰해서 그런 것도 아닙니다. 그냥 그렇게 하는 게 쉽고 자연스럽기 때문입니다. 왜 여기서 가능한 것이 다른 곳이라고 가능하지 않겠습니까.
자바로 SI하는 업체에서 공통모듈 개발해본 사람은 알 겁니다. 사람들은 공통모듈팀 절대 신뢰안합니다. 그래도 막상 사용할 때 소스는 절대 안 봅니다. javadoc만 보고 개발하죠. 사실은 아무리 OOP라도 쓰다가 문제 생기면 소스 들여다봐야하는 건데 그렇게도 안합니다. 이게 오히려 우리 나라 SI 업계의 현실에 가까울 겁니다.
물론 refactoring 이 훌륭한 도구임에는 당연합니다.하지만,
물론 refactoring 이 훌륭한 도구임에는 당연합니다.
하지만, (예전에도 언급한 적이 있습니다만..) refactoring이 적용되기 힘든 부분또한 많습니다.
실례로 project갯수만 100개가 넘습니다. 하나의 dsw에 묶인 dsp만요...
각 dsp내에 class만 60개가 넘는것들이 매우 많습니다.
그중 core라 할 수 있는 dsp가 약 10개 내외 됩니다만, 그 core들의 tree(라기 보다는 hierarchal dependency죠..) dependency를 곁가지로 나머지 90여개의 dsp가 또한 서로간의 그리고 core와의 dependency를 가집니다. 물론 resource만을 전담하는 dsp도 있습니다.
90여개의 dsp에 해당하는 것은 toolkit이라 부르고 있습니다만.
toolkit을 개발하는 인원이 core에 해당하는 부분을 손대야할 경우가 적지 않습니다.
새로운 기능을 추가하기 위해서요...
전체 개발인력이 10~15명 정도 되지만, 각자 자신의 일이 할당되어 있겠죠...
이쯤되면 각자 모든 개발인력이, 자신의 일을 처리하기 위해서, core에 필요한경우 소소의 추가&수정을 해야만 하는 경우가 빈번하게 발생합니다.
operation 추가의 경우에는 별 고민이 없겠지만, operation 수정에는 고민이 많게 됩니다.
(operation수정을 function의 수정과 function들간의 동작의 수정을 포함하여 말하겠습니다.)
core 의 base 에 해당하는 하나의 함수를 고쳐야 할 경우, (주로 기능확장을 위해서입니다만...)
기능확장을 위해서 그 함수의 definition이 바뀌게 됩니다. 그로인해 그 class를 상속받고있는 다른 class들의 동작을 보장하기 위해서 모든 다른 class의 그 확장된 function의 definition을 모두 바꿔줘야 하고, 그들간의 동작에 대한 확인또한 필요하게 됩니다. 이럴경우 전체에 대한 안전성을 검사하기 위해서 전체를 컴파일 해야만 하게되는데, 소스의 모든부분을 전체 컴파일 하게 되는경우 10시간이 넘는 시간이 소요되게 됩니다. 물론 dependency가 적은곳은 부담이 적을수도 있겠습니다만, 고민이 된다면 dependency가 큰 곳이라는 것쯤은 쉽게 짐작하실 수 있을 것입니다.
즉 기능확장을 위해, 그 확장된 부분을 확인사살 하는데 걸리는 시간이 너무 심각하다는 점입니다. (compile 오류를 수정하는데만요..)
또한, 그러한 function들이 변경되는 것에대해, 매번 다른 팀원들에게 전달하여 숙지시키는것 또한 어려운 일입니다.
각자의 일정이 있기 때문이기도 하구요, 어찌보면, 필요한 사람이 알아서 보면 되기 때문입니다. 그래서 핵심적인/근본적인 변화 외에는 각자 알아서 보게 됩니다.
이쯤에서 다른사람이 그 수정된 것에 대한 부분을 보게 됩니다. 자신이 알던 포멧과는 다른형식으로 바뀌어 있기 때문에...
그 변경에 대해서 알아야만 작업의 진행이 가능합니다. (물론 document가 충분하다면, 그러한 고민이 적을수 있습니다만,
이정도 분량의 프로젝트라면, 하나하나 만들어나가고, 변경시켜 나가는데에 따른 document의 생성과 수정이 도리어 budden some 한 작업이 되기 시작합니다.) 이럴경우 일반적으로 자신이 알던 것에 대한 부분을 기초로 넘어가는것이 대부분입니다만, 그러한 일로인해 문제가 될 경우, 자신이 제대로 동작을 이해하고 넘어가지 않은것이 문제가 되기때문에, 책임(이라고 할 것 까지는 없지만...)은 나중에 사용한 사람에게 있게 됩니다.
또한, 저정도의 project라면, refactoring 도구가 알아서 처리하기에는 좀 버거운 량이라고 보여집니다.
물론 C++로 작성되었기에 적절한 refactoring 도구가 없는것 또한 문제입니다만... 그리고, 각자 자신이 알고있는 기존의 내용을 기반으로, base class의 내용을 확장해 나가기 때문에, refactoring 등을 통한 class/function 의 definition의 잦은 변경이 다른 작업자에게 부담을 안겨주게 됩니다. (머 실제로 적용시켜 볼 수 없었다는게, 가장 큰 결점이겠지만, 실제로 적용시키기도 힘듭니다. 하위 dependency들을 모두 찾아서 정리해줘야 하기때문에, 쉽사리 손댈수가 없는거죠.. definition이나 use나...)
"이쯤되면 누구나 자유롭게 수정" 이란 수식어는, 그 많은 분량의 내용을 기억하고 있는데, 어느부분의 내용이 변경되었는지 나도 모른다. 즉 "바뀐부분의 소스분석이 새로운 작업을 하기 이전에 항상 확인을 해야 한다"는 점으로 이어지게 됩니다.
또한 refactoring과 TDD의 경우에는 내용 변경시마다 testing에 의한 확인사살을 기정사실화 하고 있습니다만.
기존의 프로젝트가 testing을 위한 기반하에 개발되지 않았고, 또한 event deriven system에 있어서 testing을 할 수 있는 시점은 function level에 한해서 입니다. (머 UI를 테스트 할 수 있는 테스트 도구가 있는것으로 알고 있습니다만 (최근에 알았습니다..) 윈도우의 버튼을 클릭하는것이 아니라, view의 클릭위치에 따라 다른동작을 하는 시스템이라면, 이러한 테스팅 도구마저 적용이 불가능합니다.) function level 에서의 test 또한 function의 definition 혹은 추상화된 전반적인 operation 의 정의가 바뀌게 되면, 소용없게 됩니다. (머 충분한 test code가 이미 있지 않으니 이에대한 언급도 필요없군요...)
이밖에 많은 문제점이 있습니다만...
지금 생각나는건 이정도 이군요...
하나의 프로그램을 키워나가면서 현재의 확장버전만 3년 이상 manage하고 있습니다.
프로그램의 dependency와 규모는 계속적으로 커져나가면서요...
이런상황에서 refactoring이라는 훌륭한 도구는 "그림의 떡"에 지나지 않는군요.. "TDD"도 말이죠...
또한, 팀원 각자의 언어 혹은 개발 방법론에 대한 이해의 깊이의 차이 또한, 디자인과 개발효율성의 측면에서 어느정도 blockage역활을 하는것도 있구요...
이쯤되면, 호출된 함수에 대해서, 어느정도 신뢰를 할 수 도 있지만, 그렇지 않은경우도 많게됩니다. 즉 그 함수의 소스를 뒤져봐야 하는것이죠...
또한 리펙토링을 통해 신뢰성이 높아진다고 할 수 없게 됩니다. 리펙토링 자체가 버겁고, 버그를 유발할 수 있는 작업이 되기 때문이죠..
결국 현실적으로 불가능한 "주어진 코드를 개념적으로 가장 깔끔하게 유지하는 방법중 하나는, 처음 설계되었을때 그대로 이후로 계속 가져가는 것" 이란 얘기가 나오게 되었네요...
refactoring, TDD 매우 좋은툴 입니다만, 적용가능해야 하다는 전제가 필요한 듯 합니다...
PS:
예전에 다른 주제에 올렸던것과 같은 내용을 다시 올리게 되는구요..
좋은모습 아닌데.. ㅡ.ㅜ
이런글 좀 자제해야 할 듯 하네요. ^^;;;
PS:
refactoring, TDD 지금의 현실로는 적용 가능하지 않습니다.
하지만, 좀 방법을 생각해 봐야 할 듯 한데.. 쉽지가 않네요..
너무 긴 글을 작성했군요. 죄송합니다..
^^;
PS:
refectoring 이라고 된 것을 refactoring 으로 고쳤습니다.
WOW Wow!!!
Computer Science is no more about computers than astronomy is about telescopes.
-- E. W. Dijkstra
저 또한...Refectoring과 TDD를 할 수 있는 작업환경에서
저 또한...
Refectoring과 TDD를 할 수 있는 작업환경에서 일을 하고 싶은 생각이 간절하군요...
아. Refectoring도 좋지만, Refectoring 할 필요가 없게 구조를 깔끔히 잡는것도 중요하지 않나요 ???
머 당연한 말이겠지만요 ^^
WOW Wow!!!
Computer Science is no more about computers than astronomy is about telescopes.
-- E. W. Dijkstra
[quote="htna"]...또한, 저정도의 project라면, r
이 부분을 읽기 전에도 "C++을 쓰겠구나" 라고 짐작이 되더군요.
때로는 전체를 다른 언어로 뒤집기도 한답니다. :wink: 그러면, 설계가 깔끔하게 되기도 하지요. (말 뜻은 refactoring이 문제가 아니라 design에 문제가 있다는 거죠.)
----
I paint objects as I think them, not as I see them.
atie's minipage
[quote="htna"]물론 Refectoring 이 훌륭한 도구임
Refectoring 이 아니라 Refactoring 이겠지요.
이런거 꼬리잡는게 좋은건 아니겠지만
한두군데 쓰신것도 아니고
그냥 리팩토링이라고 하든가
함 찾아보시든가 하시지,
보기가 영...
개념없는 초딩들은 좋은 말로 할때 DC나 웃대가서 놀아라. 응?
[quote="girneter"]Refectoring 이 아니라 Refa
하하. 그렇군요..
음... 이문제는.. 걍 원 소스를 수정하는게 낫겠군요.
refectoring => refactoring 으로..
오타가 좀 많이 나와서 죄송합니다.
지적 감사드립니다.
^^;;;
물론 그렇기는 합니다만... 현실적으로 그럴 수가 없는경우이지 않나 생각합니다.
다른언어로 뒤집으려면, 개발자 전체에 걸쳐 언어교육이 우선적으로 들어가야 하죠...
언어적 특성을 이해하고, 그에 맞게 사용할 수 있도록....
또한 전체 언어를 다른언어로 뒤집기 위해, 기존에 사용하던 외부모듈(외부 라이브러리)가 역시 무리없이 사용될 수 있는지 확인해야 합니다.
또한, 전체를 바꾸는 과정에서 디자인의 재설계 과정이 필수이고, conversion시 들어가는 시간도 무시못할양이 됩니다...
머, 하긴 팀에서 다음버전을 위해 새로이 디자인하고 있기는 하군요...
디자인 문제는 팀장의 재량에 따라 좌우되는듯 생각됩니다.
댜략 1~2년 개발기간이 예상되는 편입니다만...
COM으로...
직접 상황을 보지 못하면..
그 상황에 대해서 이해하지 못하는것이 대부분입니다.
다른분들께서 여러가지 지적을 해 주시지만, 다들 자기가 봐온 환경과 개념의 기준으로 문제를 판단하기 쉬운건 당연합니다.
이러한 문제들에 대해서 혼자만의 노력으로 고쳐지는게 아니기때문에,
여러가지 좋은 의견과 방법이 있지만서도 직접적인 적용이 가능한 경우와, 가능하지 않은 경우도 있습니다.
Design이 문제라는것을 이미 알고 있었지만, Design을 바꿀수가 없는것과,
Refactoring/TDD가 좋은 방법임에도 불구하고, 적용시킬수 없는 것 등....이 그러한 경우라고 생각합니다. 만...
WOW Wow!!!
Computer Science is no more about computers than astronomy is about telescopes.
-- E. W. Dijkstra
C++이 그런 면에서 구린 것은 사실입니다. 유닛 테스팅 프레임웍도 서너
C++이 그런 면에서 구린 것은 사실입니다. 유닛 테스팅 프레임웍도 서너 개 있지만 다 좀 구리고 리팩토링 툴도 부실하고 무지막지한 빌드 타임도 변화에 저항하게 만드는 주요한 요인이죠. 그래서 사실 전 C++가 OOP하기에 적합한 언어가 아니라고 생각합니다. 언어 자체의 문법은 OOP를 소화하기에 부족함이 없지만 좋은 OOP로 가기 위해서는 무언가 바꾸기가 쉬워야하는데 C++에서는 그게 잘 안되니까요.
그래서 저도 이 문제로 고민을 많이 하는 중인데 현재까지의 결론은 두 가지입니다. 하나, 그래도 C++ 쓸 때는 OOP로 가는 게 안 가는 거보단 낫다는 것. 그리고 VM 기반 언어만큼은 아니라도 C++도 어느 정도 변화에 유연하게 할 수 있는 방법들이 있다는 것. Large Scale C++ Software Design이 꽤 도움이 많이 되었습니다. XP에서도 C++을 하는 사람들은 도대체 C++에서 XP가 가능한가..하는 질문을 많이 던집니다. 그런데 거기에 대한 대답은 그래도 하는 게 낫다..가 주류를 이루죠. 실제 TDD 같은 경우는 제한된 범위만 컴파일할 수 있기 때문에 VM 기반 언어에 꽤 근접하는 속도로 개발해나갈 수 있습니다. 제 경우는 C++에서 TDD를 하면서 개발 속도가 상당히 빨라지는 것을 느낄 수 있었습니다. 다만 리팩토링을 자유롭게 할 수 없어서 수동으로 해야한다는 것은 상당히 스트레스로 남더군요.
그리고 또 하나의 문제, 공표된 interface를 변경하는 것. 이것은 리팩토링을 적극적으로 하는 팀이라 해도 그렇게 쉽게 하지 않습니다. 대부분의 리팩토링은 외부에 보이는 동작을 변경하지 않는 선에서 내부 구조를 개선하는 방향으로 이루어지죠. 공표된 interface의 변경에 신중을 기하는 것은 어차피 다 마찬가지입니다. 이런 한계는 소규모 파일럿 프로젝트가 아닌 이상 어디에나 존재하는 것으로 보아야할 것입니다.
어쨋든, C++이 분명 유연성이 떨어지고 다른 OOP 언어에 비해 OOP로 가는 길이 험난한 것은 사실이지만 어차피 SP로 가도 길은 험난한 것이고 그나마 OOP로 갈 ㅤㄸㅒㅤ의 생산성이 더 높을 것이라고 봅니다.
MFC
그럼 M$의 수만 개발자들이 쓴 MFC도 API를 Wrapping 했으므로 대략 무효~!
Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.
이 주제 ... 처음에 좀 얘기 동참하다 중간에 잘 발을 뺀거 같은데..
이 주제 ... 처음에 좀 얘기 동참하다 중간에 잘 발을 뺀거 같은데...
아직도 얘기가 결론은 내지 못하고 순환을 하고 있네요.
이러다 OOP적인 언어와 C의 모든 특성 특징들이 다 꺼집어 내지고...
이 사이트가 닫기 전에 얘기의 끝이 날까 의심스럽군요... ㅡㅡㅋ
근데... 솔직히 C와 C++는 완전히 다른 언어인데...
경계를 정할려는 잘못된 명제에 의해서 불랙홀에 빠진건 아닌지 모르겠군요.
명제가 틀렸는데...
나오는 주장들에는 무언가 논리를 실으려고 하니 끝이 없군요.
<어떠한 역경에도 굴하지 않는 '하양 지훈'>
#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);
저도 동감입니다.C++ 에서 무언가 부족한 2%를 느끼는 경우가 많습
저도 동감입니다.
C++ 에서 무언가 부족한 2%를 느끼는 경우가 많습니다.
TDD야 특별한 툴에 크게 의존적인것이 아니지만 (있음 더욱 좋겠죠),
Refactoring의 경우에는 툴 없이 하는것과 환경적인 문제로 많은 불편함을 느끼기에,
그냥 필요한 경우에만 간단히 적용할 수 있고, 가능한 부분에 조금씩 테스트 없이 하고 있습니다만
너무많은 제약에 답답함이 좀 크게 남네요..
저 또한 VM을 이용하는 것이 아닌 이상 C보다 C++, SP 보다 OOP가 낫다라고 생각하고 있습니다.
제가 알기로는 (틀릴수도 있습니다만...)
C++에서 Refactoring, static analysis(용어가 이게 맞는지는 모르겠군요) 를 해주지 못하는 가장 큰 이유중에 하나가,
static type casting에 있다고 알고 있습니다. (맞나요?)
그렇다면, 차라리 C++의 그러한 몇가지 불안전한 부분을 없애고 (C와의 완벽한 호환이 좀 떨어더라도),
Refactoring 등과 같은 것을 처리할 수 었으면 하는 바램이 있지만... 희망사항 뿐이겠죠 ? ^^
WOW Wow!!!
Computer Science is no more about computers than astronomy is about telescopes.
-- E. W. Dijkstra
[quote="creativeidler"][code:1]순수 객체지향적인
Dijkstra가 (논리적으로는 필요없는) 반복문이 없는 프로그래밍을 원했던 것처럼 OOP에서도 속성을 사용하지 않는 게 가능한 줄 알았습니다. 논리적으로 본다면 꼭 필요하지 않는 것 처럼 보였기 때문입니다. 다만 현실적인 이유로 속성들을 사람들이 쓴다고 생각했기 ㅤㄸㅒㅤ문에 속성을 쓰지 않는 것이 순수한 OOP가 아닌가 지례짐작으로 글을 적었습니다.
속성이 필수적인 것이라면 약간은 실망스럽기도 합니다. 변수라는 low level 특성을 사용하지 않는다면 OOP는 디버깅 면에서 SP보다 확실히 앞서는 부분이 있다고 생각했기 ㅤㄸㅒㅤ문입니다. 전에 말씀하신 객체만으로 표현하는 언어들은 어떤 언어들이 있습니까?
strcpy의 내부구조를 몰라도 되지만 strcpy가 할 수 있는 범위를 넘었을때 다시 만들어야 합니다. 유닉스의 역사나 게임 산업의 역사를 보면 아예 처음 부터 엎어버리고 만든 경우를 많이 볼 수 있습니다. 객체지향으로 프로그래밍을 한다고 해서 위 층의 레이어에서만 작업하는 일은 없을 것이라고 생각됩니다. 아래 층의 레이어까지 모두 바꾸어야 할때 여전히 투명성은 중요한 요소가 되지 않을까요?
- 죠커's blog / HanIRC:#CN
[quote]속성이 필수적인 것이라면 약간은 실망스럽기도 합니다. 변수라
우선 한 가지.
object should not be based on class.
이를테면 자바에서 배열은 class에 기반하지 않지만 객체로 취급됩니다. 파이썬에서는 함수나 메쏘드도 객체로 취급되죠.
모든 것이 객체인 언어는 구성 요소가 모두 객체로 취급될 수 있는 것을 말합니다. 이를테면 순수 객체지향 언어라고 할 수 있는 smalltalk 같은 언어는 문자열은 물론이고 숫자, boolean 등도 모두 객체입니다. 파이썬도 마찬가지죠.
위에 제가 제시한 A,B,C의 비유를 생각해봐주시기 바랍니다. 레이어가 두꺼워지는 것이 오히려 아래 레이어를 이해하는 것을 더 쉽게 만들어줄 수 있습니다. 사실 아무리 투명성이 좋다해도 C 프로그래밍하면서 이 코드들이 어떤 instruction set으로 구성되고 이 변수들이 몇 개의 레지스터에 들어가고 예상 캐시 히트율은 얼마고 microprocessor 파이프라인 활용도는 얼마나 되는지를 알고 싶지는 않을 것입니다. 프로그래머가 원하는 투명성에는 분명 한계가 있다는 것이죠. 두꺼운 레이어는 프로그래머가 알고 싶은 레이어까지만 내려갈 수 있게 해 줍니다. 이것은 OOP가 아니라 SP에서도 마찬가지입니다. 함수 하나가 100라인씩 되는 것보다 10라인 짜리 10개로 쪼개져서 레이어를 이루고 있는 것이 한 번에 봐야하는 코드량을 줄여 각각의 신뢰도를 높여줍니다. 레이어링은 원래 인간의 이해력의 한계를 인정하는데서 출발하는 것입니다.
마지막으로, 디버깅이 gdb 같은 툴을 이용한 디버깅을 말하는 것이라면 이 점에서는 OOP가 SP보다 유리한 점은 제로입니다. 기본적으로 디버깅은 "따라가면서 버그를 찾는 방법"이므로 디버깅할 때는 레이어가 많고 개입하는 객체가 많을수록 따라가기는 어려워지는 것이 사실입니다. 그래서 OOP에서는 디버깅보다 테스트로 버그를 찾습니다. 실제로 TDD의 주창자 Kent Beck은 모든 디버깅은 테스트로 대체할 수 있다고 합니다. 디버깅 vs 테스트에 대한 논의도 많았는데 대체적으로 디버깅이나 테스트나 문제를 해결할 수 있다는 점은 같지만 테스트는 그 고민의 결과가 코드로 남는다는 점이 장점이 된다는 이야기가 많더군요. xper.org에서도 이런 논의가 있었는데 아쉽게도 오늘 이 사이트가 접속이 안되서 링크를 못 걸겠네요.
에구. 한동안 KLDP 에 접속이 안되었네요...음. 쓸데없는 얘기를
에구. 한동안 KLDP 에 접속이 안되었네요...
음. 쓸데없는 얘기를 하게 되는게 아닌가 생각이 들지만...
그렇게 본다면 C/C++의 함수또한 객체라고 정의할 수 있겠군요...
.NET 에서 각 class의 function 또한 reflection을 통해서 이 function이 함수인지, 무엇인지를 알 수있는 방법을 제공하는 것으로 알 고 있습니다. (음. 아닌가..??)
즉 reflection을 통해서 class의 function을 객체로 바라볼 수 있다는말이죠. 하지만, 이에 앞서서 CLS라고 해야하나 IDL/MD 라고 해야하나.. 암튼 그 부분에서 조차 이러한것을 지원하죠..
개념을 좀 확장하면 C/C++ 에서 function 또한 그 function의 address를 통해 identify 할 수 있습니다.
다만, 그 주어진 address가 function 의 address인지, 변수의 address인지, class라고 구체화된 변수의 address인지 알 수 없다는게 단점이죠...
이렇게 본다면, C/C++ 또한 모든것을 객체라 볼 수 있을것으로 생각됩니다. 다만, 언어적인 차원에서 이것들의 속성을 알 수 있는 방법을 제공해주지 못한다는게 흠이지만요.. 머 블랙박스인가요...
하지만 OOP는 이런 관점과는 좀 다르다는 생각이 드네요.
주어진 문제를 "객체 중심적으로 문제를 해결" 하고자 하는것이 OOP이지, 어디까지를 객체라 정의할 것인가와는 다르다는 생각이 드네요..
object라는 것을 property을 지닌것으로 정의하는게 일반적이지만, creativeidler님의 말 처럼 behavior를 지는것을 object라고 정의한다고 해도 OOP의 관점에서는 크게 벗어나지 않는다는데 동의 합니다.
하지만, 이때 이러한 behavior object가 얼마나 효율적이며, 어느부분에서 이득을 볼 수 있는가가 관건이 될 듯 싶습니다.
머... 그때그때 달라지겠죠. ?
두분이 얘기하시는 부분이 서로 다르네요. creativeidler님은 개념적인 부분에 있어서, CN님은 현실적인 부분에 있어서...
일단 상위/하위 에 대해서 제가 생각하던것과 좀 반대인지라, 글을 분석하는데 혼동을 했었습니다.
( 저는 아래를 derived, 위에를 base/super로 생각하고 있었거든요. ^^; )
저희 회사에서도 그렇지만, 서로 다른 주장을 할때, 동일선상에 놓여있지 않은 부분에 대해서 같은 이름으로 서로의 주장을 하는 경우가 대부분 입니다. 만...
creativeidler님께서 얘기하시는 것은, (경우에 따라 다르겠지만...) 일반적으로 base class는 추상적으로 정의되어 있으며, 이 추상적인 base class를 상속받아 derived class에서 개념을 구체화 하기 때문에, derived layer ( 상위레이어 하위레이어, 어느게 상위고 하위죠. ? @.@, base / derived 로 말을 풀어나가겠습니다. ) 로 갈 수록, 그 객체를 사용하는 코드를 이해가 더욱 쉽게 만든다는 얘기를 하시는 듯 합니다만.. 당연한 얘기죠.
CN님께서는 객체란것이 사람이 구현하는, 만큼 완벽하게 구현할 수 없을 뿐더러, 초기에 정의된 객체의 한정된 가용분야를 넘어설 경우, 갸용분야를 넘어서는 부분을 새로운 객체를 만들어 보충을 하거나 (이미 객체가 충분히 큰 경우에는 이러기가 어렵습니다.), 기존의 base class / layer를 수정/재구성 해야만 하는 경우가 발생하는데... 이렇게 base class / layer를 수정/재구성하는 경우, layer가 깊어질수록, case에 대한 정확한 이해가 어려워지는 경우가 많기때문에 (저는 이렇게 생각합니다...실제로 이련경우를 많이 봐 왔구요...), layer에 있어서의 투명성이 중요해진다.
그리고, class가 버그를 가지고 있는경우 이러한 버그가 있는 코드를 분석하는데 있어서도 layer가 깊어지는 경우 역시 같은 결과가 나오죠.
여기서 투명성이 "class 혹은 class cluster의 layer가 얇게 하도록 하는것"을 의미할 수도 있고, "객체에 대한 명확한 정의"를 얘기하는 것일수도 있겠습니다만, 제가보기에는 layer에 대한 얘기가 아닌가 생각이 듭니다 만..
어쨋든 이 또한 당연한 얘기입니다. 만...
그리고, 제가 다르게 설명했을수도 있습니다만. 그렇다면 지적해 주세요...
윗쪽을 모두 다 다시 읽어보는것이 도움이 되겠지만.. 귀차니즘의 압박이.. ^^;;;
장단점이 있을것 같군요.
디버깅의 방법과 테스트의 방법 사이에.
디버깅은 '세부적인 부분에서 조차', 구현자의 의도에 맞게 돌아가는지 확인할 수 있는 방법이지만,
테스트에 의한 방법은, 고민의 결과가 코드로 남는다는 장점이 있겠군요. (새로운 것을 알았네요. 테스트의 장점 중에서..)
하지만 그 function/class가 이후로 바뀌지 않을것이라는 (않아야 한다는) 점에서, 프로그램이 진화하는것에 대한 허용범위가 좁아진다는 점에서, 좀 유동성이 떨어지는 면도 있군요...
WOW Wow!!!
Computer Science is no more about computers than astronomy is about telescopes.
-- E. W. Dijkstra
RTTI는 C++에서도 지원되고 C/C++에 function pointe
RTTI는 C++에서도 지원되고 C/C++에 function pointer도 있지만 그렇다고 C/C++에서의 function을 객체라고 하긴 좀 곤란하죠. 파이썬의 function object는 객체처럼 파라미터로 전달될 수도 있고 대입될 수도 있고 속성도 가지고 있죠. 단순한 behavior object가 아닙니다.
그리고, 다음에 쓰신 부분들을 보니 OOP의 레이어가 상속에 의해서만 생긴다고 생각하시는 듯 합니다. CN님도 아마 그런 생각을 하고 있으신 것 같구요. 그리고 실제로 이 상속이야말로 OOP의 오용이 나타나는 결정적인 이유이기 때문에 그렇게 생각하시는 것 같습니다. 실제로 상속은 OOP에서 그리 권장되는 방법이 아니며 출판된지 10년이 되어가는 GoF의 디자인 패턴에서도 상속은 좋은 방법이 아니며 웬만하면 합성을 통해 문제를 해결하라고 하고 있습니다. 실제로 OOP에서의 레이어가 나타나는 형태는 SP에서 나타나는 형태와 크게 다르지 않습니다. function 안에서 다른 function을 호출함으로써 SP의 레이어가 생기듯, object의 method 안에서 다른 object의 method를 호출함으로써 OOP의 레이어가 생기는 것이죠.
움. TDD나 리팩토링에 대해 "좋은 방법"이라고 말씀하시는 것을 보고 TDD와 리팩토링에 대해 잘 아시는 줄 알았는데 그게 아닌 것 같군요. 건방진 말로 들릴지 모르겠지만 이 부분에 대해서 조금 공부를 해보시는 것이 도움이 될 것입니다. Martin Fowler의 Refactoring이나 Kent Beck의 Test Driven Development by Example을 한 번 읽어보시길 권합니다. 둘다 번역서가 있고 번역이 꽤 잘 되어 있습니다. 테스트나 리팩토링에 관한 책들은 모두 공통적으로 테스트야말로 과감한 리팩토링을 할 수 있는 원천이라고 말하고 있습니다.
그리고 이와는 별개로, 이제 xper이 복구되었기 때문에 지난 번에 링크하려했던 주소를 적어둡니다.
http://xper.org/wiki/xp/AreDebuggersWasteful?action=highlight&value=%B5%F0%B9%F6%B1%EB
[b]개념을 확장해 본 것입니다.단지, 고정관념을 탈피해서 객체의 관
개념을 확장해 본 것입니다.
단지, 고정관념을 탈피해서 객체의 관점으로 바라봐도 되지 않을까 하는 생각이었습니다.
물론 파이썬 등에서 제공하는 function object (파이썬을 알고있지는 않습니다만..) 처럼 여러가시 속성을 query 할 수 있는 정도는 아닙니다. C/C++의 함수포인터를 function object와 같이 객체라 엄밀하게 말할 수는 없죠..
하지만, C/C++에서도 함수의 주소를 넘김으로써(함수포인터), 파라메터로 전달될 수 있고, typedef에 의해 어느정도 변수처럼 사용할 수 있기에, 객체라 봐도 될 듯 하다 생각한 것입니다... 물론 이경우 (다른 언어에서도 마찬가지라 생각됩니다만) call back이 주요 목적일 것으로 알 고 있습니다.
제가 바라본 layer는 다른쪽 이었습니다만.
layer에 대해서 function 안에서 다른 function을 호출함으로써 생기는 layer에 대해서도 생각할 수가 있군요..
저는 함수의 virtual로든 (혹은 virtual이 아니든) overriding을 통한(함수의 재정의) layer에 대해서 생각하였었습니다.
어떤면에서는 derived class에서 새로운 함수의 정의는, layer를 깊게 만들면서 complexity를 증가시키는 영향보다는, 객체의 기능확장쪽에 무게가 실리는게 아닌가 생각합니다.
하지만, derived class에서 virtual function의 overriding은 derived class의 개념을 명확하게 해주는 장점이 있지만, 구현 세부적으로 봐서는 complexity를 증가시키는 면이 없잖아 있기 때문이죠..
함수의 기능을 확장하게 되면서, 함수의 정의가 바뀌게 될 경우, 이때에 이미 만들어진 test code또한 손을 봐야 한다는 의미로, 유동성이 떨어진다고 생각했습니다
함수의 기능을 확장하면서 함수로 넘기는 파라메터를 추가하게 되는경우, (다들 아시겠지만) 일반적으로 함수의 뒷부분에 default parameter를 주면서 추가합니다만,
int function(int original_parameter, int additional_parameter=0);
함수의 리턴타입을 변경하거나, 이미 default parameter가 있는 상황에서, 그 parameter sequence중간에 새로운 default parameter를 추가하거나, 그러한 default parameter들을 정리하면서 함수의 정의를 바꾸게 되는경우...
이전에 만들어 놓은 test code는 적용되기 힘들게 됩니다.
즉 제대로 하기 위해서는 test code또한 바꾸어야 하는것이죠..
실제 하나의 제품을 3년 이상 관리하면서 확장을 하게 되는경우에 이런일이 가끔 발생하게 됩니다. (overriding에의한 dependency가 적거나, 없거나, (기능이 아니라) 개념확장을 하면서 이렇게 해결해야 문제해결이 쉽게 되는 경우에는, 이런 방법을 사용하는 경우가 있죠..)
물론 현재에 test code가 있는것은 아니지만, 이러한 경우에 test code마저 확인을 하면서 고쳐야 한다는 점에서.
"프로그램이 진화하는것에 대한 허용범위가 좁아진다" 고 얘기한 것입니다. 음.. 하지만, 허용범위가 좁아지게 하는것보다 할 일이 많아지게 하는 것이군요...
TDD에 대해서는 creativeidler님께서 말씀하신 책의 1~3 부 중에서 1,2 부의 내용은 정독으로, 충분히 이해했다고 생각하고 있습니다.
Refectoring에 있어서는 (이책은 원서로 보지는 못했지만.. 개인적으로 충분히) 이해하고 알고 있다고 생각합니다.
여담입니다만, TDD에서 언급한 작업관리방식이 상당히 맘에 들어서, coding쪽이 아니라 assign된 작업을 관리하는 측면에서, 지금 현재 사용하고있구요...
3부에 대해서는 미처 보지는 못했지만, 만약 그쪽에 좀 더 중요한 내용이 있다면, 다시 시간을 내서라도 봐야할듯 하군요..
TDD의 모든부분에 대해서 이해를 하지 않은상태에서 토론에 참여한 점에 대해서는, 혹시 맘 상하셨다면 죄송합니다.
WOW Wow!!!
Computer Science is no more about computers than astronomy is about telescopes.
-- E. W. Dijkstra
제가 하나 착각한 것이 있군요. TDD by Example은 why te
제가 하나 착각한 것이 있군요. TDD by Example은 why test보다는 how to test에 대한 설명 중심이라 제가 말한 그런 내용이 명시적으로 나오진 않는군요. JUnit for pragmatic programmer랑 착각한 것 같습니다. 리팩토링에는 명시적으로 잘 설명이 되어 있습니다.
사실상 코드를 수정할 때 테스트도 수정해야하므로 유동성이 떨어진다는 논리는 TDD에 대한 주요한 반론인 코드를 만들 때 테스트도 만들어야하므로 추가 비용이 발생한다는 것과 같은 논리죠. TDD는 테스트를 먼저 작성하고 코드를 작성하는 것이므로 수정할 때도 테스트를 먼저 수정하는 것이 당연한 것이고 이게 추가 부담으로 느껴진다면 TDD 자체가 성립할 수 없는 것이죠. 그래서 TDD를 좋은 방법이라고 말씀하시면서 위와 같은 말씀을 하시는 게 좀 이상했습니다. 그리고, 실제로 변경이 잦은 프로젝트를 할 때 TDD로 해보면 테스트가 있기에 변경을 자유롭게 할 수 있다는 말이 참 와닿게 되기에 htna님이 아직 TDD를 별로 해보지 않은 것 같다고 생각한 것이죠.
코드를 수정할 때 제일 골치아픈 부분이 뭘까요? 여러 가지가 있겠지만 정작 골치아픈 것은 수정한 그 부분보다 자신이 수정한 코드 때문에 다른 잘 되던 곳에서 문제가 발생하는 것일 겁니다. 큰 시스템일수록 이런 게 더 심각한 문제가 되죠. 테스트는 이런 점을 효과적으로 발견할 수 있게 해 줍니다. 수정한 코드 때문에 다른 곳에서 문제가 생기면 바로 전체 테스트에서 빨간 불이 떠서 금방 찾아서 고칠 수 있거든요. 테스트의 장점은 문제를 빨리 드러내준다는 것이고 그래서 내가 고친 코드가 맞는가, 다른 코드에 영향을 주진 않을까 고민할 필요 없이 과감하게 수정을 할 수 있는 것입니다.
TDD와 리팩토링에 대해 좀더 알아보시길 권하는 것은 굳이 이런 토론을 하기 위해 그런 것들을 다 알아야한다고 말하고 싶은 것이 아니라 그것이 OOP에 이르는 방법으로 현재까지 발견된 것 중 가장 좋다고 생각하기 때문입니다. 그래서 그것들이 습관이 되면 OOP는 자연스럽게 스며듭니다. 마침 TDD by Example을 읽고 있으시다면 실무에 전면적인 적용을 한 번 해보시길 강력히 권합니다. 아마 생각이 많이 바뀔 것입니다.
TDD를 실제 적용시켜 본 적이 적은것은 사실입니다.아무래도 업무에서
TDD를 실제 적용시켜 본 적이 적은것은 사실입니다.
아무래도 업무에서의 적용 가능할때야, 실제로 적용해가며 익혀나갈 수 있기 때문에, 충분히 경험을 가지고 있지는 않습니다.
하지만, 다른사람들과 소스를 공유하는 부분이 아닌, 제가 만들고, 다른사람들이 관여할 수 없는 부분에 있어서는, test를 합니다. Debug mode에서는 프로그램이 실행되기 이전에 항상 테스트 코드가 먼저 돌지요...
아무래도 critical한 부분이기도 하고, 이 부분들이 제대로 돌아가야만, 다른사람들이 믿고 사용할 수 있는 부분이라서요...
TDD, Refactoring을 알기전에 작성한 부분이긴 합니다만, 그래서 Test Driven 한 개발이 아니라, Test에 의해 동작을 확인하는 Test가 뒤따르는 프로그램을 하게 되었습니다만.. 이경우에 다른사람들이 건들 수 없다는 점이 아무래도 특징이지요. (다른사람들이 손을 못대는 이유가 귀찮아서와, 이미 충분히 필요한 동작을 cover 하기 때문에, 그리고 오동작에 대한 부담감 때문에가 주 이유겠지만요..)
이부분에 수정이 가해지게되면, 문제가 없다는것이 보장되어야만 하기 때문에, 아무래도 (의도하는것은 아닙니다만) Refactoring의 방식으로 진행이 됩니다..
하지만, 역시나, 이외의 부분에서는 TDD과 Refactoring을 적용시킬 수가 없군요...
개인적인 습관의 문제인지.. 구조적인 문제인지...
WOW Wow!!!
Computer Science is no more about computers than astronomy is about telescopes.
-- E. W. Dijkstra
개발자 입장에서보면 편리하고 쉽게 구현하고 성능좋은게 우선이라고보봅니다.
개발자 입장에서보면 편리하고 쉽게 구현하고 성능좋은게 우선이라고보봅니다.
그러면 oop 과연 얼마나 편리하며 쉽게될지 구체적으로 따져봐야죠..
oop로 하면 코딩량이 더적을까...
속도가 더빠를까..?
설계가 더쉬울까? 개념자체가 증가하는만큼 고려할것도 많겠죠.
그리고 배우기도 쉬워야하는데 아무래도 배울것도 증가하니.
그또한 단점이군요..
C++이 C보다 우수하다고 말하는사람이 있다면
최고의 언어는 C++에다 java 에다 php, basic, 코볼,파스칼,C#
등등등.. 컴파일러들 다묶어놓고 최고언어라고 하면되겠네요..^^
----------------------------------------------------------------------------
차라리...
마징가Z 와 그랜다이져가 싸우면 헬박사는 누굴 응원하냐 물어보는게 훨씬 현명할지두...
페이지
댓글 달기