coding convention, which is more important than design patterns

부제 : More practical design pattern (보다 현실적인 디자인 패턴)
( 창기님의 CCV 방법론 – 중복의 해악에 덧대어.. )
 
    디자인 패턴은 참으로 뜨거운 감자이다. 미국에서 인터뷰를 보다보면 꼭 나오는 이야기가 디자인 패턴이다. 디자인 패턴을 내 나름대로 정의를 해 보자면, “어떤 문제를 해결하기 위해 마련한 코드인데, 잘 설계가 되어서 다른 사람들도 따라서 써주길 바라는 패턴의 코드”이다. Cocoa를 하는 사람은 MVC에 익숙할테고, singleton이나, Factory, Constructor, Container등의 패턴은 알게 모르게 쓰게 된다.

    Design pattern is a hot potato. The issue is quite popular and asked often when you are interviewed in the U.S. Let me define what the design pattern is : “Certain lines of codes to solve problems. And it is supposed to be used by many others because it is designed so well.” If you are a Cocoa programmer, you will use factory, contructor, container and singletone pattern without recognizing that you use them. Also most of the code in Cocoa will follow the MVC, i.e. Model-View-Controller, design pattern.

    그런데, 미국에서 직장생활을 하다보니 느끼는 점이 있다. 막상 말들은 “디자인 패턴”을 연신 외치면서도, 기본적인 코드 패턴은 갖추어져 있지 않다는 것이다.

    However, there is something I found out by working for companies in the US. Although they keep mentioning “Design Patterns”, they even don’t follow the most basic pattern or coding convention.

몇가지 예를 들어보자.

Let’s take a look at a few examples.

1. Declaration of global variables

    코드가 길어지게 되다보면, 일일히 각 파일의 앞으로 커서를 옮기는게 무척이나 불편해진다. 그리고 그렇게 왔다 갔다 하는게 별로 생산성 면에서도 좋지 않다. 그런데 왜 변수의 이름을 확실히 “이건 전역변수이다”라고 알 수있도록 해 놓지 않는가? Objective-C가 namespace가 없다고 C++ 프로그래머들이 불평하면서도 막상 그들의 소스 코드를 보면, 이런 기초적인 것조차 지키지 않는 경우가 많다. 굳이 namespace가 필요한가? 변수 이름등을 잘만 정해도 굳이 namespace가 그다지 필요해지지 않는다.

    If the lines of codes become long, it is inconvenient to move around the cursor. It is also not good for productivity. Then why don’t people declare global variables such that they look like global variables? Although mny C++ programmers complain that the Objective-C doesn’t have “namespace”, but when I took a look at their code, I often found out that they even don’t keep this kind of simple coding convention. Do we really need a namespace? If you set the variable names well, you will not need the namespace as much as you think.

다시 생각해 보자. 

Let’s think about it again.

int gNumberOfElement

앞에 g를 넣어 그것이 global variable을 의미했다. 혹은 더 좋은 나름의 방법을 만들어도 좋겠다.

By prepending “g”, I made the variable mean a global variable. Or you can invent your own way to mean global variables.

또한 global variable을 너무 남용하는 것도 좋지 않다. 많은 코드를 보니, class의 member variable로 하는게 더 낳은 경우를 봤다.

Additionally, it is not good to use global variables too much. I found out that many global variable could be replaced by member variables of classes.

2. Separation of class definition and its declaration

Java 때문일까? header 파일, 즉 class를 선언하는데서 실지로 class를 define하는 경우를 굉장히 많이 봤다.

Is it due to the Java? I noticed a lot that a class was defined in a header file, in which a class was declared.

class MyClass
{
	int age;
	...

	void doSomething( void );	

};

void MyClass::doSomething( void )
{

}

이상과 같은 코드가 header 파일 자체에 들어간 경우가 많았다. 이렇게 되면 무슨 문제가 생길까?
만약 다른 파일들에서 위의 내용이 있는 header file을 include했다고 하자. multiple definition이 되버린다.

I saw a lot that codes like above were put into a header file. What kind of problems it can cause? Let’s assume that the header file is included by a few .c/.cpp files. Then a compiler will raise error saying “… are defined multiply.”

3. Implementation of methods in a class definition

이 문제는 앞에서 언급한 것의 다른 측면이 되겠다. 이 세번째 문제가 진짜 Java로 부터 영향을 받은 것으로 보인다.

This is different aspect of the issue #2 explained above. Actually this seems to be highly affected by Java.

class MyClass
{
	int age;
	...

	void doSomething( void )
	{
		...
	}
}

아무리 요새 에디터들이 좋아지고 IDE가 좋아져서, 자동으로 정의된 method들의 리스트들을 에디터의 pop-down 컨트롤에서 보여준다곤 하지만, 그건 한번 클릭을 해서 봐야만 한다. 더군다나 클래스 자체내에 그 메소드의 정의가 길어지면, 한눈에 전체를 볼 수가 없다. 즉 헤더만 봐도 전체를 파악할 수있어야 하는데, 그게 되지 않는다고 한다. 원래 C++의 소개서에도 가능하면 class의 선언에 들어가는 메소드는 짧은 경우에 한해서만 직접 그 안에서 정의를 하라고 되어 있다. 근데 이렇게 긴 메소드의 정의가 헤더 파일안에 그냥 있는 경우를 굉장히 많이 본다. 

Even though editors and IDEs have evolved so much that IDE/editors display methods in list automatically, they should be clicked to be displayed. Also, when method definition become long, it is hard to take a glance at sourc codes and figure out the whole codes. In other word, you can’t figure out what classes do by reading their header files. When the C++ was introduced, only short method definition was recommended if they are defined in the class header file, or the class declaration. However, I have seen lots of class declaration with long method definition.

또한 이런 코드는 에러를 유발하기가 쉽다. 왜냐? 어디에 뭐가 있는지 일목요연하지 않으니까, 뭐가 어디에 있는지 파악하기가 힘들어서이다. 놓치는 경우가 많은 것이다.

Also codes like above can cause errors easily. Why? It is because it is pretty hard to figure out what is where. You can easily skip them.

4. 이해하기 힘든 소스 코드 (Source code which is difficult to understand.)

– 쓴 사람만 이해하는 약어등을 절대 쓰지 말라. 헝가리안 코드도 나는 사실 좋아하지 않는다. 왜냐하면 일단 이게 뭔가 생각을 하게 만들기 때문이다. Apple이 쓰는 스타일로 보통의 영어로 쓰는게 좋다. 단 그런 방식은 길어지기 쉬운 면이 있다. 하지만 이해하기 어려운 코드보다는 긴 코드가 낫다. 어차피 컴파일되면 짧은 것으로 바뀐다.

Don’t use abbrebiation which only the writer understands. I don’t like Hungarian codes also. Hungarian notation make you think to figure out what it means. I prefere plain English style, which is used by the Apple Inc. One negative side of plain English style is that it can be lengthy. However, I prefer long codes to cryptic codes.

아무튼 혼자만 아는 스타일로 약어를 만들어서 붙이지 말라.
Anyway, don’t use abbreviation only you know.

– 또 하나의 잘못된 코딩은, 해당 환경을 쓰는 사람들의 convention에 어긋나는 것이다. 다음의 예를 보자.
Another wrong coding is to be against convention used by the interested environment. Let’s take a look at an example below.

 MTLINK SHARED *pShared;

위의 코드가 무엇을 의미할까? 다음을 볼까?
What does that mean? Let’s take a look at the following.

#define MTLINK __declspec(dllimport)

이제 이해가 된다. 왜 이런 식으로 Macro를 만들어 내었을까? MS는 이미 자체적으로 dllimport에 대한 매크로를 준비해두고 있다. 
A-ha! Now you can understand it. Why on earth did the original writer make that kind of macro? MS already provides a good and understandable macro for DllImport.

그런데 왜 굳이 코드의 의미와 일치하지 않는 매크로를 만들어 내는가? 또한 readability면에서도 안좋지 않은가?

Why invent macros which are not consistent with the original meaning? It is not also good as far as readability is concerned.

또 하나의 예가 있다.

Here is another example.

THREADDATA std[MAX_CHANNELS];

눈에 들어오지 않는다. Thread_Data 혹은 ThreadData는 어떨까? 훨씬 눈에 잘 들어 오지 않는가?
더군다나 모두다 대문자로 되어 있으면 꼭 Macro같이 느껴진다.

It is pretty hard to catch what it means. Wouldn’t it be better if Thread_Data or ThreadData is used? They are more visible and easy to read. Also, it looks like a macro when every characters are in capital letters.

Macro는 대문자로 정의하는 것은 C/C++ 프로그래밍에서의 오래된 관습이다. 꼭 이렇게 관습을 파괴해야 할까?

It is very old convention among C/C++ programmers to declare macros in capital letters. Wouldn’t it be easier to figure out if certain terms are macro or not if people follows the coding convention?

5. Pointer variables and plain general variables

C/C++에서 포인터 변수와 일반 변수를 같은 식으로 선언하면, 코드 길이가 길어질때 굉장히 헷갈려진다. 특히 structure나 class instance에 대한 것에 대해선 더욱 그러하다. 

It is pretty hard to figure out if a variable is a pointer variable or a plain variable in long source codes, when they are declared in the same way. Especially structures and class instances are.

values = data;

위와 같이 되어 있으면 저게 일반 변수의 assign일까 아니면 일련의 데이터에 포인팅하는 data를 values라는 pointer 변수에 assign하는 것일까?
흡사 일반 변수의 내용을 일반 변수에 할당하는 것처럼 보이지 않는가?

How does the above code look like? Are they general variable? Or is it assigning a pointer variable, data, which points to a series of data, to another pointer variable, values? Doesn’t it look like plain variable assignment?

즉 pointer 변수라면 이렇게 하면 어땠을까?

How they look, if they are revised this way?

pValues = pData;

혹은 다음은 어떨까?

Or how about this?

valuePtr = dataPtr;

첫째번의 방법에 비해서 훨씬 낫지 않은가? 여기까지는 C/C++에서이다. Objective-C는 어떨까?

Aren’t they a lot more clearer to figure out? Those are for C/C++. How about Objective-C?

여기서 Objective-C의 class instance가 문제가 될 수있다.

Class instances, or objects, can be an issue for the Objective-C.

NSString *myString;

이 경우는 myString이라고 해서, 확실하게 어떤 object같은 느낌이 난다. 이것을 다음과 비교해 보자.

The term, “myString”, looks like an object. Let’s compare it with this.

int numberOfElement;

이건 확실히 일반 변수같다.

It looks like a general variable clearly.

즉 Objective-C에선 pointer냐 아니냐로 구분이 된다기 보다는 객체냐 아니냐로 구분하는 식으로 coding convention이 되어 있다.

In other words, it is determined by whether they are objects or not, instead of pointer or not, in the case of the Objective-C.

이 점은 상당히 흥미있는 점이다. 오히려 OOP가 되기 위한 확장은 C++이 Objective-C보다 더 많은데, coding에 있어서는 확실히 Objective-C가 더 OOP적이라는 점이다. 장치를 얼마나 준비해 두었느냐보다, 운영의 묘미가 더 빛을 발한다고 할까?

It is very interesting point. Although C++ has more keywords and facilities than Objective-C, but the Objective-C actually look more like OOP. How to utilize them seems to be more important and effective than how many more features it has.

6. 메모리 할당과 해제 ( Memory allocation and release )

메모리 관리 문제는 코드의 안전한 수행에 있어서 상당히 민감한 문제이다. 그러므로 상당히 잘 관리해야 하는데, 이것또한 제대로 안되고 있는 것중의 단골 메뉴다.

How to manage memory is very crutial for safe operation of codes. So, it should be done carefully but also is not done properly often.

– Class의 instance가 있는 동안 존재하는 것들은 그 클래스의 constructor에서  memory를 allocation하고, destructor에서 free시키라.

For memory blocks which is alive during the lifespan of its subordinating object, allocate the memory space in the constructor of the class and free in its destructor.

어중간하게 그것들을 사용하기 시작하는데서 할당하고, 사용이 다 끝났을때 free를 하면 코드가 길어질때 관리가 무척 힘들어진다. 그렇게 하는 것은 확실하게 그렇게 할 필요가 있을때 하는게 좋다. 

If they are allocated in the middle of something and freed right after it is used, it becomes very hard to manage code. Only when it is clear to do so, do so.

– 어떤 함수 A 내에서 메모리를 alloc하고 사용한다면, 비록 그 함수가 부르는 다른 함수 B내에서 그 할당된 메모리에 대한 사용을 다 끝내더라도, 함수 A에서 해당 메모리를 free하는게 좋다. 그렇게 함으로써, 어디서 메모리가 할당되고 free되는지 그 책임 소재를 명확하게 알 수있고, 혹 free가 안된 것이 있는지 일일이 찾아 다니지 않아도 된다.

When memory is allocated and used in a function A, although something finishes using it in a function called in the function A, it is better to free it in the function A, not B. By doig so, it is easier to track where the memroy is allocated and freed. And it is also easier to check which memory space is not freed.

다른 것들도 많은데, 당장 지금 생각나는 정도는 이 정도이다.

2 responses to this post.

  1. I do agree with you 100%, totally!

    I have once wished that I could convince a “Martian” programmer I knew that he should not, ever, use abbreviations that he just made up himself. He doesn’t even leave a comment that explains what it stands for.

    Anyway, an excellent essay!

    Reply

  2. […] about coding style 28 01 2009 In a previous post, coding convention, which is more important than design patterns, I pointed out some bad […]

    Reply

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: