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

Using "integer type" has lots of merits against using "float type"
So, in some cases - especially in embedded system that uses ARM as their main MCU - we want to change float-operation into integer-operation by multiplying or shifting it.
Yes! It's a good method in point of performance!
But we should take our careful attention to OVER/UNDERFLOW of integer-operation!!!
(In case of float-operation, in general, we are free from over/under flow!)

Keep in mind this.

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

Output files should be separated from input files. Usually, 'clean' option is supported to delete auto-generated-output-files. But, separating outputs at directory level is better - for example, 'out' directory is root directory for output.
This is very basic and fundamental. But, this also easily ignored.

Supporting 'clean' option is good. But, cleaning output files those are scattered over several different places, is difficult to maintain. And, in this case, to find some necessary output files is also difficult.
On the environment that output files are separated at directory level, programmer can tell easily that which is input and which is output. This means, he/she can know which are necessary files to build software without further efforts - easy to read software.

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

조직의 최고 책임자가 조직 전체를 세세히 알 수 있는 작은 조직에서는 밥그릇 싸움이 일어나기 힘들다. 밥그릇 싸움은 조직의 크기가 어느 정도 이상 커졌을 때 주로 발생한다.

다음의 시나리오를 생각해 보자.

처음에 10명으로 시작한 회사가 있다. 이 회사의 일이 처음에는 10명이 열심히 하면 되었다. 그런데 차츰 회사가 성장하면서 10명으로는 도저히 감당할 수 없을 정도로 일의 양이 늘어났다. 그래서 회사는 사람을 더 뽑았고, 이런 과정이 몇번 발생하면서, 회사의 인원은 100명으로 늘어났다.

그런데 회사가 계속 일이 늘어나기만 할 수는 없다. 어느 날 부터, 100명 분의 일이 80명 분의 일로 줄어들었다. 그럼 20명은 놀아야 정상인데, 놀고 있다는 사실이 위쪽에 알려지면 놀고 있는 부서는 그 규모가 축소되어지게 되므로, 80명 분의 일을 100명분의 일로 늘리게 된다. 즉, 실무자들은 이 일이 80명 분의 일이라는 것을 알고 있으나, 관리자는 추가적이고, 비생산적인 20명분의 일을 만들어서 자기 부서의 규모를 유지하고자 하게 된다. 구체적인 예를 들어보자.

프로젝트 A, B가 있다. B는 50명 A는 10명의 인원이 배정되었으며, A는 B의 결과물을 받아서, 약간의 수정/개선 을 통해서 제품화되어 지게 된다. 프로젝트 납기일은 A는 B보다 2달 늦다. 이 상황에서 A는 B에서 어떤 base line이 되는 결과물이 나오기 전에는 Project에 관한한, Project가 진행되고 있음을 위쪽에 보여줄 어떠한 결과물도 만들어낼 수 없는 상황이다.

이때, 보통의 회사, 그리고 보통의 관리자라면, A 프로젝트의 10명의 인원에게, 무언가 생산적이고, 장기적인 일을 시키기 보다는(이런 일은 보통, Project진행상황을 진척시키는 것처럼 보이게하는데 별 도움이 되지 못한다.) 프로젝트가 진행되고 있다는 사실을 윗사람에게 보이기 위해, B의 결과물을 받기 이전에, A의 10명에게 B에서 하는 것과 똑같은 일을 시키게 된다. (A 프로젝트도 뭔가 진행되고 있다는 것을 보이기 위해...) 이 일은 명백히 B에서의 일과 중복된다. 그리고, B에서 어느정도 결과물이 나오게 되면, A는 자신이 했던 거의 모든 일은 다 버리고, B의 결과물을 받아와서 새로 A 프로젝트를 시작한다. 그리고 보통, 이 상태는 그 동안 A에서 "보여주기 위한 일"을 했던 그 상태보다 더 진보된 상태가 된다. (왜냐하면 50명의 산출물을 가져 왔으므로...). 이렇게 해서, A의 관리자는 프로젝트 A가 뭔가 진행되고 있는 것처럼 위에 보고 한다. 더 한심한 일은, 대부분의 윗쪽 상급관리자는 A 프로젝트의 관리자가 일을 잘 하고 있다고 생각하고, 여기에 무엇이 잘못되었는지 전혀 알지 못한다는 것이다.

이런 일은 특히 Software Project에서 많이 일어난다. 왜냐하면, Software 산업에서, 의사결정권을 가진 위쪽 사람들은 Software를 전혀 모를 사람이 대부분이기 때문이다. 이런 비효율은 계속해서 발생하고, 회사가 심각하게 어려워지기 전까지는 항상 사람이 부족한 것처럼 아래에서는 보고가 올라오고, 위헤서는 그렇게 보일것이다. 내가 너무 비약해서 글을 썼을 수도 있으나, 실제로 이런 과정을 몇차례 겪어보았으니... 쩝...

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

Sometimes, so-called 'context' data structure is used to handling set of related information. And this context data tends to be required as parameter by various functions. Here is pros and cons.

Pros:
- It is easy to handle lots of related data - data allocation and free etc.
- We can save costs of parameter passing; Passing context is enough.

Cons:
- It is difficult to know which one is input and which one is output, because whole context is passed as parameter. This decrease readability very much.
- Usually, context is passed as parameter to lots of functions. So, just like 'global' data, it is very difficult to trace the value-change-history. That is, debugging/maintaining becomes difficult.

One good way to using context structure; Only very few modules can change/modify context data. And others only can read this one. Than, lot's of issues in "Cons" can be overcome.

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

There are two different API implementation to get data.

  // (*1) return, length of data remained.
  get_data(char* buffer /*in/out*/, int buffer_size/*in*/);

  // (*2) caller should free memory of (*data).
  get_data(char** data/*out*/, int* len/*out*/);

(*1) :
  This is very clear and safe, but inefficient in performance point of view and difficult to implement.
  And, the one who allocates memory, frees it too. (very reasonable. So, there is less risk of memory leak.)
(*2) : contrary to (*1)

Which one is better? In general, (*1) is recommended.

In terms of memory allocation/free, if possible, the one who allocates should free it. In case of this is not reasonable, at least, allocation-free-pair should be easy to track!

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

C++ doesn't support the 'interface' explicitly unlike Java. So, combination of abstract class and virtual function, is used.

Let's think of following case.

ModuleA
  A : pure abstract class (interface class).
  AImpl : implementation(concrete) class inherited from A.

External module that want to use ModuleA need to know interface, but don't need to know it's implementation. So, Knowing class A should be enough to use ModuleA. And this is tightly coupled with the way of instantiation.
Let's see below

A* instance = new AImpl(argument);

This is easy way. But, in this case, definition of 'AImpl' should be included in external code. This is not good in terms of 'Information Hiding'. We want to hide implementation details (even if it's header). See following example to do this.

----- A.h
class A // interface class
{
public:
    virtual ~A(){};
    static A* Create_instance(Arguments);
    int Interface_function_A(void) = 0;
    int Interface_function_B(void) = 0;
};

---- AImpl.h
#include "A.h"
class AImpl : private A
{
    friend class A;
    ...
}
...

---- A.cpp
#include "AImpl.h"
A::Create_instance(Arguments)
{
    AImpl* instance = new AImpl(Arguments);
    return static_cast(instance);
}

Now, knowing definition of class A is enough to use this module. Therefore, implementation details are completely hidden. Besides, inheriting as 'private', can prevent module from unexpected usage (AImpl can be used only through A). Here is sample usage.

#include "A.h"
...
A* instance = A::Create_instance(Arguments);
...
delete instance;

We made function for create instance. But, we should make destroying instance be possible by 'delete' keyword. Because, in many cases, knowing instance's concrete class at the moment of deleting it, is not necessary. And unifying interfaces to destroy instance (into using 'delete') is also good to read.

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

In general, there is a table to help estimate schedule and this table usually categorize software according to software type(system product, business product and so on) and size(line of code - 10,000/20,000/.../500,000/... ). It is definitely very useful.
Now it's time to make table for me, my team and our company for more accurate estimation!! (We can use more customized categorization.)

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

아래는 모두 개인적인 의견임을 밝힌다.

전제 : 어떤 결정을 하기 전에, 최선의 결정이 무엇인지 아는 것은 불가능하다.

가능하다면, 의사결정을 민주적으로 하는 것이 좋다는데는 이견이 없다. 그런데, 회사에서는 '민주적'이라는 단어가 존재할 수 없다. 조직 자체가, 서열화 되어 있고, 의사결정권한은 한 사람에게 집중되어 있다. 따라서, 회사에서 말하는 '민주적'이란, 의사 결정권자가, 다른 사람들의 의견을 수렴해서, 최대한 여러사람이 공감할 수 있는 결정을 내리는 것을 말하리라.

그러나, 다음의 경우를 생각해 보자.

A와 B 라는 두가지 선택을 할 수 있는데, 의사결정권자의 마음이 이미 A로 기운 상황을 생각해보자. 이 의사 결정권자는 민주적인 결정을 하고 싶어한다 (누가나 그렇다.) 그래서 사람들을 불러 모아 놓고, 의견을 듣는다. 그런데 사람들은 B를 주장한다. 그렇지만 의사 결정권자의 마음은 바뀌지 않는다. 그래서 사람들을 설득하고자 한다. 동의를 얻어내기 위함이다. 그러나 설득이 되지 않는다. 따라서, 다시 사람들에게 시간을 준다. "A와 B 진정으로 어느 쪽이 옳은지 다시 한 번 생각해 보고, 다시 회의 하자." 그리고 다음 회의에서도 이전 회의와 똑같은 현상이 되풀이 된다. ("1+1=2" 와 같이 논리적인 답이 있는 것이 아니라면, 사람들은 자신의 뜻을 쉽게 바꾸지 않는다.)

위의 상황에서도 계속해서 소위 말하는 '민주적'인 의사결정을 고집해야 하는가? 물론, A와 B가 어떤 문제에 대한 의사 결정인지에 따라 다르겠지만, 만약, 이 결정이 부서 업무의 방향을 결정짓는 것이라면, 사람들은 이 결정이 내려지기 전까지는 아무일도 할 수 없고 시간만 보내는 상황이 될 것이다. 만약 이 문제가 시간을 다투는 것이라면, 차라리 어느 쪽이든 빨리 결정해서 밀고 나가는 것이 더 나을 수 있다. 이런 때는 의사 결정권자가 자신의 뜻을 독단적으로 관철시키는 것이 오히려 더 낫다고 생각한다.

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

In case that several branches are maintained at the same time, 'change list'(ex. bug fix) tends to be patched to several different code branches. General way to apply 'change list' is code-merge. In this case, the guy who merges 'change list' may not know enough about change. So, there should be information about checking patch result - to verify that patching is successful or not - as a comments of 'change list'.

One of good example is something like this.
* before patch : title string is "xxxx" in screen A.
* after patch : title stringis "yyyy" in screen B.

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

다른 사람과 같이 일하다 보면, 서로가 일하는 style, 가치관 등이 맞지 않아서 갈등이 발생하는 경우가 많다. 그리고, 이 갈등 때문에 사람을 관리하는 노력이 들게 된다. 그렇기 때문에, "Good to Great"에서 "관리해야하는 사람이라면, 쓰지 않는 것이 낫다."라는 논조로 이야기 하고 있는지도 모르겠다. 반면, "Good to Great"에서는 이렇게 이야기 하기도 한다. "적합한 사람이 아니라고 판단하기 전에, 그 사람이 적합하지 않는 자리에 있는 것은 아닌지 생각해 보아야 한다.". 절대적으로 동의한다.

난, 한 번 같이 일해보고, 잘 맞지 않은 것 같아서 바로, 그 사람과 같이 일할 여지를 뿌리채 뽑아 버린 경험이 있다. ("같이 일하고 싶지 않다."고 단도 직입적으로 이야기 했다.) 지금 돌이켜 생각해 보면, 얼마나 성급한 결론이였던가? 그런 결론을 내릴만큼 난 충분히 상황을 고려했었는가? 정말 그 사람과는 같이 일하기 힘든 사람이였던가? 지금 다시 생각해봐도 성급한 결론이였던 것 같다. 그리고 설사, 적합한 사람이 아니라고 생각되더라도, "같이 일하고 싶지 않다" 라는 식의 단도 직입적인 말은 피하는게 당연한 도리일진데, 난 그리하지 못했다. (한국말은 '아' 다르고 '어' 다르다.)

이러한 일이 반복되지 않도록... 반성의 시간을 가져 본다.

+ Recent posts