[Dev] Sometimes, code duplication may need to be allowed.

Essay/Software 2006.12.14 20:42

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

Ideally, duplicated code leads to maintenance nightmare. So, Not-allowing-duplicated-code always seems to be better. But, in this article, I want to say that in some cases, code-duplication needs to be allowed.

In practice, lots of people who has different ability work together in one source code branch. In this case, if code duplication is not allowed, all developer should search all sources to find the reusable module. Let's image that there are thousands modules. Finding appropriate module is not easy. And lots of people try to customize(modify) the module for easy-reuse. If all engineers are enough good at programming and enough time to consider code quality then we don't need to worry about "customization". But, it cannot be in some cases - especially, product development. Skill level of engineers are always various and they are always pushed by project schedule. So, the shared module tends to become worse and worse in terms of its quality. (It's normal in large-size-project).

Here is merits of allowing code duplication.(There are lots of well-known-disadvantage of allowing code duplication. So, let's talk about only "Merits".)
  * There is no dependency among people. So, it's very easy to work in parallel.
  * Merging is easy, because of no-dependency and no-conflicts.
  * Bug from mistake affects only limited area. So, detecting issued part is easy.

So, practically, we need to consider what should be reused(shared) and what shouldn't.

Here is my opinion about this.
Codes that should not be duplicated.
  - codes for interface with external modules.(In App. point of view, OS, filesystem and so on can be external modules)
  - codes that are used very frequently. (ex. code for getting lengh of string. - strlen)
  - stable codes.
  - ... (anything else???)

Codes that can be duplicated.
  - parts that should be done in parallel with tight schedule and enough human resources.
  - codes that are customized very often.
  - ... (anything else???)

Hmm... I need further study...

tags : development
Trackback 0 : Comment 0

[C/C++][Tip] Using long and important 'enum'..

Language/C&C++ 2006.12.03 23:48
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

This is tip to define 'enum' that has quite lots of items and important information - ex thread id, event id, etc...

(*1)

// File : "main"

enum
{
    enum01,
    enum02,
    ...
}
...

This is not recommended.
How about using following way?

(*2)

// File : "enum.h "

DEF_ENUM(enum01)
DEF_ENUM(enum02)
...

------------------

// File : "main

#define DEF_ENUM(x)   x,
enum
{
    #include "enum.h"
}
#undef DEF_ENUM

Why this way is better? Let's assume that you want to print 'enum' values.
In (*1) case, only number value can be printed. But in (*2) case, even enum name - string - can be easily printed by following way.

// File : "Enum_str.c"

#define DEF_ENUM(x)   #x,
static const char* enum_str[] =
{
    #include "enum.h"
};
...

printf("%s", enum_str[enum_id]);

It is good, isn't it?
Except for this, you can find other lots of useful ways by using macro.

tags : C/C++, Enum
Trackback 0 : Comment 0

[C/C++][Tip] Macro...

Language/C&C++ 2006.11.17 23:45
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

====================================================

// From MSDN

#define paster( n ) printf( "token" #n " = %d", token##n )
int token9 = 9;

If a macro is called with a numeric argument like

paster( 9 );

the macro yields

printf( "token" "9" " = %d", token9 );

which becomes

printf( "token9 = %d", token9 );

====================================================

',' is used as parameter separator in C/C++. So, function which uses variable number of parameter - like "logger(const char* format, ...)" - is difficult to present by using macro. (Some compilers support variable number of parameter in macro too. But, most are not.)
In this case, we can make those be on parameter by groupping all parameters with "()".
For example,

#ifdef _DEBUG_
#   define LOGGER(X) logger X
#else // _DEBUG_
// we don't need to run log function in release build!
#   define LOGGER(X)
#endif // _DEBUG_
...
LOGGER((”print :%d, %d”, a, b)); // == logger(“print:%d, %d”, a, b);
...

=====================================================

To track a function, following way is very common.

// foo_fnc. h :
#ifdef CODE_DEBUG
#   define REAL_fnc(a, b) real_fnc(a, b, __FILE__, __LINE__)
#else
#   define REAL_fnc(a,b) real_fnc(a,b)
#endif

But, In following cases, some compiler raises error.

#ifdef 1
REAL_fnc(a,
#else
NEW_REAL_fnc(a,
#endif
    b);

Yes. It's a kind of porting issue.
In this case, we can use following walk-around.

// foo_fnc. h :
#ifdef CODE_DEBUG
    typedef int (* RealType_Fnc)(int, int)
#   define REAL_fnc real_fnc_wrap(__FILE__, __LINE__)
    extern RealType_Fnc real_fnc_wrap(char*, int);
#else
#   define REAL_fnc(a,b) real_fnc(a,b)
#endif

---------

// foo_fnc.c
...(omitted)
RealType_Fnc real_fnc_wrap(char* fileName, int line)
{
    printf(“%s : %d”, fileName, line);
    return real_fnc;
}
tags : C/C++, Macro
Trackback 0 : Comment 0