728x90

파일 헤더를 제공하라
사소하지만 꽤 중요하다. 난 지금까지 제대로 지키지 않았다. 앞으로는 잘 하도록 노력해야겠다. 대부분의 회사에서는 법률적인 이유로 모든 소스 파일에 가시적인 저작권 공지를 포함시키도록 의무화하고 있단다.
/*************************************
* 파일 : FileName.java
* 목적 :
* 알림 : 저작권표시
*************************************/

에러를 적절하게핸들링하라
에러는 발생한 곳과 가까운 곳에서 처리하는 것이 좋다. 에러가 발생하면 어디서 왔는지, 에러의 이유가 무엇인지, 에러가 발생한 것은 무엇을 의미하는 것인지 알기 쉽도록 해라.(어떻게? 잘~)

의미 있는 코멘트를 작성하라
학교에서 처음 프로그래밍을 배우면서 코드를 작성하고 발표수업이 있을 때 모든 문장에 코멘트를 달도록 강요받은 기억이 있다. 코멘트가 너무 많은 코드는 오히려 보기 불편하다. 가능하면 코멘트가 필요없도록 작성하되 그러고도 남아있는 부분에 대해서는 적절한 분량의 코멘트를 추가해야 한다.
* 파일헤더, 함수의 설명, 변수에 대한 설명은 가능하면 생략하지 마라.


문서화의 여러가지 방법


문학적 프로그래밍(프로그램을 작성하지 말고, 문서를 작성하라. 소설처럼 써라.)
장점

* 문학적 프로그래밍은 문서작성에 강점을 둔다.
* 문서가 가까이 있으므로 업데이트할 때 문서도 함께 업데이트 하기 쉽다.
* 전체 코드베이스에 대해 단 하나의 문서만 존재한다는 사실이 보장된다.(코드 자체가 문서기 때문)
* 일반적으로 코멘트에 쓰이지 않는 항목도 문서화하도록 유도한다.(사용된 알고리즘에 대한 설명, 코드가 올바르다는 증명, 그렇게 설계하게 된 결정의 정당성.)
* 유지보수에서 빛이 난다.
단점
* 코드가 아니라 문서 전체를 작성해야 하므로 대부분의 프로그래머들이 힘들고 귀찮아 한다.
* 또 하나의 컴파일 단계가 필요하고, 그것이 작업 속도를 느리게 만든다.(아직 바로 컴파일해줄만한 툴은 없단다. 당연하지!)
* 정말 문서화가 필요하지 않은 부분까지도 문서화하게 될지도 모른다. 또는 일부를 문서화하지 않게 될지도 모른다. 귀찮으면 아예 하지 않는 것이 좋다. 이도저도 아니면 안된다.
* 프로그램 잘 짠다고 글도 잘쓰는 것은 아니다. 훌륭한 프로그래머라고 해서 반드시 유능한 문학적 프로그래머가 되는 것은 아니다.


문서화툴
문서화를 도와주는 툴이 많이 있다는 말이다. 책에서는 Javadoc를 예로 들었는데 이는 다음과 같은 일을 도와준다.
 * 저작권 정보를 명시한다
 * 생성일자를 기록한다
 * 정보를 상호 참조시킨다
 * 오래된 코드에 deprecated라고 표시한다.(오래됐다고 바꾸라고 권장한다는 뜻)
 * 빠른 참조용의 짤막한 개요(synopsis)를 제공한다
 * 함수 파라미터 각각에 대한 설명을 제시한다
javadoc, C#의 NDoc와 Doxygen(www.doxygen.org)등이 있단다.
장점
* 코드의 문서화와 업데이트를 촉진
* 컴파일할 수 있는 코드를 위해 별도의 단계가 필요하지 않다(문학적 프로그래밍과의 차이)
* 비교적 자연스럽게 보인다.
* 문서화 툴은 풍부한 검색, 상호 참조, 코드 아웃라인 기능을 지원
단점
* API의 문서화에만 정말로 유용하고, 내부 코드의 문서화에는 일반 코멘트를 사용해야 함
* 소스 파일을 훑어보고 개략적인 내용을 파악하기 어렵다.(이런 건 문학적 프로그래밍이 한 수 위)
주의
* public 항목에 대해서는 하나 또는 두 개의 문장으로 구성된 설명을 작성하라. 쓸데없이 주절주절 늘어놓지 말란 말이다.
* 변수나 파라미터가 어디에 사용되는지 분명하지 않으면 문서화하라. 단 이름만 보아도 확실하게 알수 있으면 문서화하지 마라.
*함수 파라미터 중 어떤 것은 입력에 사용되고 어떤 것은 출력에 사용된다면, 그런 사실을 파라미터 설명에 명확히 기술하라
* 함수의 전제조건, 후행조건, 발생할 수 있는 exception, side effect를 모두 문서화 하라.

생각해보니 2학년 때 이현아교수님이 문서화 툴에 대해 언급했었고 임은기 교수님도 권장한 적이 있다. 다만 귀찮아서 사용하지 않았다. 잠시 알아본 적도 있었지만 귀찮아서 사용하지 않았다. 문서화 툴은 형식이 일정한 것이 아니라 툴 마다 다르기 때문에 필요하다면 실무에서 사용되는 공통된 것을 이용하면 될 것 같다. 사용법이 그리 어렵지 않으니 그때그때 필요한 것을 배우면서 사용할 수 있다. 문서화 툴에 의존하기보다는 필요한 정보는 코멘트로 달아두는 습관을 기르는 것이 더 도움이 될 것 같다.

+ 파일에는 헤더를 유지 (파일명, 목적, 저작권 [, 특이사항])
+ 함수에도 헤더를 유지 (parameter, return value, 목적)
+ 변수는 이름만으로 명확한 것이 아니면 반드시 설명(객체형식이라면 이름이 확실해도 설명을 붙여두는 것이 좋다.)

728x90
728x90
외부 문서의 지원이 필요한 코드는 작성하지 마라. 그런 코드는 취약하다. 코드 자체만으로 명료하게 읽히도록 만들어야 한다.
 - 외부 문서가 필요한 코드의 경우 수정 될 때마다 외부 문서를 같이 수정해야 한다. 처음 작성되었을 때 어떻게 되었는지 알 필요가 있는 경우 이러한 문서 작업은 더욱 복잡해 질 것이다. 큰 프로젝트를 작업하는데 이렇게 진행하면 힘들어서 제대로 진행하질 못한다.
 - 그렇다고 지나치게 상세한 코멘트(주석)로 코드 자체의 내용을 가리는 것도 옳지 않다. 코드만 보고도 쉽게 알 수 있는 곳이라면 코멘트를 자제하자. 어차피 코드만 보고 이해하기 쉽도록 만드는 것이 목표이니 코멘트는 필요없는 것인가? 코멘트가 필요한 곳과 작성요령은 나중에 다시 다룬다.

코드가 명료해지면 실수할 가능성이 적어지기 때문에, 코드의 품질이 높아지고, 유지보수 비용이 줄어든다. (가독성을 높이는 것이 최대 목표라고 생각해라.)

가끔 자신이 만든 소스를 다른 사람들이 쉽게 알아보지 못하는 것에 대해 쾌감을 느끼는 변태들이 있다. 단점은 그런 변태들과 같이 일하고 싶어하는 사람이 적다는 것이다.

같은 일을 하는 함수다. 어떻게 보이는지 감상해보자.

중요한 것은 짧은 코드를 작성하는 것이 아니라 다른 프로그래머가 봤을 때 쉽게 읽을 수 있고 명확한 코드를 작성하는 것이다.

if문의 함정에 조심하라!
 - 이건 책에서 강조하는 것이 아니라 내가 강조하는 내용이다. 책에서는 if-then-else 구조를 작성할 때 "정상"인 경우가 "에러"인 경우보다 항상 앞에 나오거나 그 반대가 되도록 하라고 권한다.

내가 권하는 방법은 if문은 가능한 처음부터 사용하지 말라는 것이다. 초보 프로그래머가 쉽게 작성하는 코드는 많은 문제를 if, else문으로 처리하려고 들고 if문 내에 전체 코드를 다 넣으려고 한다. 특히나 if문으로 오류처리를 하면서 전체 코드를 다 집어넣는 경우 처리할 오류가 많아질수록 중첩수준이 깊어진다.

그래서 일단 이론적으로 올바른 입력이 있을때(아무런 오류처리도 필요없을 때)의 코드를 먼저 작성하고 오류처리는 if문으로 나중에 추가하라고 권한다. 불필요한 경우 else문도 절대 사용하지 말것을 권한다. 이것이 올바른 것인지는 모르겠지만 중첩의 깊이가 적을수록 코드를 읽을 때 생각할 것이 줄어든다는 믿음에는 변함이 없다.
728x90
728x90

예전에 선배가 시집을 선물해준 적이 있었다. 'love adagio'란 책으로 시인의 이름이 '박상순'이었는데 한동안 그분이 여성작가인줄 알았다. 이름으로 인한 오해는 확실히 알아보기 전에는 계속 작용하기 때문에 그만큼 위험하다. 이름을 잘 붙이는 것은 코딩할 때 상당히 까다롭고 중요한 일이다. 내가 이 카테고리를 만들고 책을 사서 정리하는 이유가 사실은 작명 때문이다.

이름은 다음 3가지를 나타낸다.
identity(신원) : 무엇인지 나타내는 기본적인 것으로 주로 변수(혹은 속성)
begavior(행동) : 무엇을 하는 것인지 나타내는 것으로 주로 함수(혹은 메쏘드)
recognition(인지) : 추상적인 것을 표현함(사상, 우주등 실체를 확인하기 힘든 것들)
이름만 잘 지어도 특별한 주석이나 추가 설명문 없이도 이해하기 쉬운 코드가 된다.

잘못 지어진 이름은 자칫 커다란 위험이 될 수도 있다. 책에는 이런 예를 들었다
void checkForContinue(bool weShouldContinue)
{
      if (weShouldContinue) abort();
}

argument로 넘어오는 weShouldContinue은 이름만 봐도 계속 진행할 필요가 있으면 true, 정지해야 하면 false가 들어오는 것을 예상할 수 있다. 그런데 if문에서 만약 true면 중단하라고 하고있다. 정말이지 어이가 희박한 상황이다.
그렇다면 잘못 지어진 이름 말고 대강 아무런 생각 없이 지어진 이름은 어떨까?

void fun(bool a)
{
     if( a ) b();
}
난 이 함수가 의도하는 것을 도무지 이해할 수가 없다. 처음 언어를 배우는 사람들이 실습용 코드를 작성할 때 변수명을 x,y,z,a,b,c.. 이런 식으로 이어가는 경우가 있다. 이렇게 이름을 짓는다면 무슨 기능을 하는지 하나하나 다 설명해줘야 한다. 설명이야 귀찮지만 하면 된다. 그러나 작성하는 프로그래머조자 코드를 작성하는 도중에 헷갈린다. (인간인 주제에 헷갈리지 않을 것이라고 장담하지 마라.)

* 이름을 붙이는 대상
 - 변수(속성, attribute)
 - 함수(메쏘드, method)
 - 타입: class, enum, struct, typedef
 - C++의 namespace, JAVA의 package
 - 매크로
 - source file(파일명)

기본원칙

묘사적인 이름 :
무엇을 나타내는지 정확해야 한다.

적법한 이름 :
이름도중 공백불가, 대소문자구분 허용, 특수문자불가, (언어에 따라 길이와 사용하는 문자셋(unicode,ascii등)의 차이가 있을 수 있다), 예약서 사용불가. C언어에서는 코드 중간에 선언불가, C/C++에서는 global식별자는 str로 시작하고 다음에 소문자나 밑줄불가하며, std namespace에 속하는 이름도 사용불가.

관용구 사용 :
많은 사람들의 코드를 보고 일반적으로 사용하는 이름이 무엇인지 알면 그걸 지어라. 많이 사용하는 이름 일수록 더 알아보기 쉽다.

정확한 이름 : 사전에 없는 단어를 사용하지 마라. 영어 사용에 약한 한국과 일본에서 간혹 영어대신 자국어를 발음나는대로 적어서 사용하는 경우가 있다. 주문을 나타내는 order대신 jumoon이나 joomoon, jumun(주문)이라고 적어버리는 경우가 있다는 말이다.(허접한 인터넷 사이트에서 간혹 보인다.) 심지어 위의 보기에서 jumoon과 joomoon을 같이 사용하면 다른 기능을 표현하는 경우도 있다.(미친 짓이다.) 사전에 없는 단어를 새롭게 만들어내면 나중에 본인도 무엇을 나타내는지 알아보지 못하는 수가 있다. 뭔지 몰라서 사전을 찾아도 소용 없다.

적절한 길이 : 프로그래머는 단어를 짧게 줄이고 싶어하는 충동을 가지고 있다. 하지만 그렇다고해서 함부로 줄이면 큰일난다. 가능하면 모든 이름에 있어 사전을 따라는 것이 좋다.
단, 줄일 때는 몇가지 규칙이 있다.
 - 반복문의 카운터 : 보통 i,j등으로 사용한다. 이것도 짧은 반복문일 경우에 적당하다.
 - 짧은 범위 : 짧은 범위에서는 지나치게 긴 이름대신 짧은 이름을 사용하고 주석을 달아주면 더 이해하기 쉬울수도 있다.

처음부터 잘 지어라 : 나중에 고치지 뭐..같은 건 없다. 임시로 급하게 작성하는 코드라 해도 생각보다 오래가는 경우가 많다. 나중에 창피당하지 말고 첨부터 잘해라.

-다음번엔 대상별로 이름 붙이는 방법을 알아보도록 하자...

728x90
728x90
  • Design and implement (in C++) an ADT Array that can dynamically grow and shrink as integers are data is inserted and removed. // ADT array 을 하나 맏르어줘서 엄청나게 커질수도 작아질수도 있게 만들어 주는거네요 . Access time to any item in an array (via it's index) should be constant. The cost of an insert into the middle of an array may be O(n). Indexes need not start at zero and may be negative.
  1. The ADT should include the following:
    1. -A default constructor that creates an empty array starting at index 0.
    2. -A constructor taking an intdata [] array that builds an array populated with the items in the array starting at index 0.
    3. -A constructor taking a range int low, int high that builds an empty array ranging from the low index to the high. (Pre: high >= low.)
    4. -A copy constructor array( const array& that ) .
    5. -A destructor. 
    6. -An accessor int size( ) that returns the size of (number of entries in) the array. 
    7. -An accessor int find( intdata n ) that returns the index of element n in the array.
    8. -An accessor int at( intdata n ) that returns the integer at the given index n. 
    9. -A mutator void insert( intdata n ) that inserts the element n at the end of the array.
    10. -A mutator void insert( intdata n, index i ) that inserts the element n into the array at index position i. 
    11. -Amutator void erase( int index ) that removes the element at the given index position in the array. 
    12. -A mutator void clear( ) that empties the array.
    13. Overload the [] operator
    14. Overload the assignment operator =
    15. Overload the operator == to test array equality.
    16. Overload the operator != to test array inequality.

ADT란게 자료의 type에 무관하게 사용하겠다는 겁니다. 뎃글에 자료형을 물어보신 글이 있던데 특정한 자료가 정해진 것아닙니다. C++ 문법에 template이 있는데 이 부분은 표준이 제대로 안되어 있어서 컴파일러마다 조금씩 다르기도 합니다.

배열의 크기가 동적으로 커졌다고 줄었다가 한다고 되어 있습니다. 배열로 지정하고 크기에 따라 deep copy를 통해 크기가 다른 배열로 바꿀 수도 있습니다만 문제에서 O(n)이 예상된다고 하니 링크드리스트를 원하는 것으로 보입니다.


한시간 넘게 붙잡고 있었는데 엉망이다. 귀찮아서 다 inline으로 해버렸고
A constructor taking a range int low, int high that builds an empty array ranging from the low index to the high. (Pre: high >= low.)
이부분... 생성자에서 low와 high값을 argument로 던져주고 배열사이즈를 계산해서 생성하란 것 같은데 무슨 뜻인지, 왜 필요한지 몰라서 제대로 못했다.
그리고 test결과 =연산자가 제대로 작동하지 않는다. 제대로 연산은 되는데 const &로 parameter를 맞추니까 오류나고 그냥 해버리니까 연산이 끝난 후 R-value의 링크가 사라진다. 뭐냐고..

아무튼 문제에 보면 Indexes need not start at zero and may be negative. 이렇게 되어 있는데 그러면 생성할 때 배열의 low와 high를 정하는 것이 아니라 method중에 begin을 결정하는 method가 있으면 되는거 아닌가? 문제를 만든 사람은 뭘 생각한 거지? 내 영어실력이 문젠가?
아무튼 제대로 이해한 사람 있으면 좀 알려주..
728x90

'Programming > C++은객체지향언어다' 카테고리의 다른 글

error C2220: warning treated as error - no object file generated  (0) 2011.07.29
g++ for windows  (0) 2008.11.07
집합(차집합, 교집합, 합집합) - cpp  (0) 2008.04.02
C++ (OOP개념들)  (0) 2008.02.26
C++ (객체)  (0) 2008.02.26
C++ (OOP개념)  (0) 2008.02.26
C++ (개요)  (0) 2008.02.26

+ Recent posts