●●● 장비 제어 개발 및 코딩에 대한 조언 몇가지 ●●●


장비 제어 SW 개발과 관련된 특수한 환경이 있기 때문에 , 일반적인 소프트웨어 개발과는 다른 점이 있을 수 있습니다.



◆  디버거의 사용은 최소화 하고 로그를 적극 활용하라 . 장비가 동작중일때는 디버거를 사용할 수 없고 문제 생길때마다 디버거에 의존하다 보면 소스 코드 분석 능력이 떨어지게 된다.


◆  구조를 잡거나 조건을 생각할때는 나무를 보지 말고 숲을 보라. 코딩을 할때는 숲을 보지 말고 나무를 보라.



◆  고객사 담당자가 원하는것을 얘기하면 원하는대로 해주려고 하지 말고, 그 기능을 원하는 진짜 이유를 먼저 생각해 보고 근본적인 원인을 찾으려고 노력하라


◆  고객사 담당자가 원하는 조건을 얘기하면 그 조건만 생각하지 말고 기존의 조건과 그것을 포함하면서  핵심을 관통할 수 있는 가장 단순하고 공통된 조건을 찾아서 적용하라


◆  한가지를 수정하면 10가지의 문제가 생긴다. 한가지 기능을 추가하면 기존의 10가지 기능에서 문제가 발생할 수 있다.  CheckBox 옵션 한가지는 모든 경우의 수를 2배로 늘어나게하고 버그의 가능성을 2배로 늘린다.


◆  같은 장비의 실행파일이 고객사 요구에 따라  2개로 분리되고 소스 코드를 개별 관리하기 시작하면 코딩 업무량은 1.5배로 늘고, 유지보수비와 버그는 2배로 늘어난다.


◆  신규 드라이버는 처음 설치 후 바로 양산 장비에 적용하지 말고 , 1대에서 충분한 테스트를 하라.


◆  프로그램을 배포할때는 실행파일만 배포하지 말고 , 버전 업 되면서 필요한 파일이 추가 되었는지 한번 더 생각하고 배포 하라.  고객사 담당자가 프로그램을 받아서 장비PC에 복사까지 했는데.. 실행조차 안되는 문제가 발생하는것은 가장 짜증나는 일 중에 하나이다.


◆  핵심적인 조건, 시퀀스, 데이터는 반드시 로그를 남길수 있도록한다. 특히 예외 상황으로 빠지는 조건에서는 무조건 로그가 남아 있게 한다. 동시에 로그 데이터는 최대한 적게 남도록 쓸데 없는 로그는 항상 정리하는 습관를 들이자


◆  UX 디자인의 기본은 사용자에 대한 배려심이다.


◆ 조건문을 만들때는 조건의 내용을 읽어가면서 이해가기 쉬운 어순으로 배열하라.



◆ 조건문은 조건들 중에서 가장 큰 대전제가 되는 조건을 우선 배열하고, 비슷한 레벨이면 가장 참(true) 이 되기 어려운 조건을 먼저 배열하라.



◆  전체 부정 !을 사용하는 조건문은 만들지 않는다.

GOOD : if( A==false && B==false && C==false)

BAD : if( ! (A || B || C ) )  : 코드는 짧지만 읽기가 어렵다.



◆  조건문의 비교식에서는 앞쪽에서 가변값(비교항목)을 넣고 뒷쪽에 상수(또는 기준값)을 넣는다.

GOOD : if ( A > 2 )

BAD  : if ( 2 < A ) :   조건문 읽기가 부자연스럽다.



◆  포인터를 리턴하는 함수에서 에러의 경우에는 NULL을 리턴하지 말고 , Dummy 데이터의 포인터를 리턴하라 . 프로그램 죽는것을 방지할수 있다. 대신 로그 기록은 필수 !  (Dummy데이터는 글로벌 더미 데이터 )


◆ XEdit를 추가할때는 항상 적당한 기본값(Default Value) 을 설정한다.


◆ 저장 하지 않고 화면을 빠져 나올때는 항상 데이터가 원상복귀 하도록 한다.


◆  고객사 담당자의 요구를 너무 쉽게 들어주다 보면 , 그것을 당연한 것으로 생각하게 된다.



◆  중복 코드가 만들어지는 순간 바로 함수로 만들어라! ( CTRL+C , CTRL+V를 하기 전에 함수로 모듈화 할수는  없는지 다시한번 생각하라 )



◆  Include Path 옵션은  C++빌더 전체 옵션에 넣지 말고 개별 프로젝트 옵션으로 넣어라


◆  모든 개발 프로젝트는 중반 이후에는 출구 전략을 생각하라 . 언제까지나 한 프로젝트에만 매달리면 그 프로젝트는 완벽해질지 모르지만 회사는 망한다.



◆  로그 내용  자체에 함수이름을 쓸때는 괄호()를 사용하지 말자.

코드중에서 함수를 검색하고 싶을때 로그 내용까지 너무 많이 검색되서 불편한 경우가 있다

GOOD  : LOG_PRINTF(“”, “DoFunc함수 실행 ")

BAD: LOG_PRINTF(“”, “DoFunc() 실행 ")



◆ 기능을 추가할때는 항상 기존의 데이터와 호환이 가능한지를 먼저 생각해보고, 이미 납품되어 양산중인 장비에 적용했을때 문제가 없을지를 항상 생각하라



◆ 시퀀스 동작에 문제가 발생했을때는 그 문제가 발생할수 있는 명확한 타이밍과 시나리오를 찾을때까지는 만족하지 마라






  1. 양승민 2014.10.27 15:39

    좋은 내용이네요.. 장비 개발해오면서 고민하던 중요한 내용들은 다 있어요 ^^
    심지어 저는 주석도 통일화하도록 합니다. 예를 들어 임시로 수정했거나 나중에 재확인이 필요한 부분에는
    //@@ 로 시작하는 주석을 달도록 하는 형태입니다. 나중에 저것으로만 검색해도 굉장히 빠르게 접근이 가능하더군요.
    근데 사실 딜레마는 저런 좋은 내용을 아래 직원들에게 가르쳐도 잘 따르지 않는다는 점 ㅜ.ㅜ;; 인거 같습니다.

  2. 솔희 2017.02.17 17:09

    안녕하세요~ 현재 장비제어 소프트웨어 개발 유지보수 업체에서 근무하고 있는 사람입니다.
    입사한지 이제 1년 되었는데요. 질문하나만 할게용~
    1. 현 직장에선 장비를 따라 인원이 출장을 가서 3~6개월을 지내다 와야 하는 상황인대요.. 혹시 이쪽 분야에서 출장을 잘 안가는 직장을 얻고싶은데. 경력은 얼마가 적당하며. 어떤 종류의 장비가 출장이 많지 않고 적당할까요? 어려운 질문이지만 많은 분들의 답변 부탁드립니다 ㅠ.ㅠ

    • 이성열 2017.02.24 01:16

      사실 장비 제어 소프트웨어 개발이라는 이 분야에서 출장을 잘 안가는 직장은 별로 없습니다. 다만 LCD 장비등 디스플레이 장비쪽은 최소 수개월씩(6개월정도?) 출장을 가게 되고요. 장비 종류에 따라서 1~2주 출장을 가는 분야는 있습니다.


  

bool SetDeviceData( bool get, int iPkIdx)
{

    if( iPkIdx > NUM_OF_PICKER )
    {
        LOG_PRINTFW("INSP",L"Set Device Index[%d] Over Check", iPkIdx );
        return false;
    }

    //---------------------------------------------------------------------------
    // ���� ����
    if( get )  // ������ ���
    {

        XEdit *apE[]=
        {
            F_SS->E_Dv1,
            F_SS->E_Dv2,
            F_SS->E_Dv3,
            F_SS->E_Dv4,
            F_SS->E_Dv5,
            F_SS->E_Dv6,
            F_SS->E_Dv7,
            F_SS->E_Dv8,
            F_SS->E_Dv9,
            F_SS->E_Dv10,
            F_SS->E_Dv11,
            F_SS->E_Dv12,
            F_SS->E_Dv13,
            F_SS->E_Dv14,
            F_SS->E_Dv15,
            F_SS->E_Dv16,
        };

        for ( int i=; i<NUM_OF_PICKER ; i++)
        {
            Dev[i].DeviceType = (DEVICE_STATUS)apE[i]->GetInt();
            DM_X->m_iLoadingCount++;
            if( F_SS->CB_Idle->XChecked )
                Dev[i].HaveDevice=true;
        }
    }
    else  // �ٶ�
    {
        if( iPkIdx < 0 )
        {
            for ( int i=; i<NUM_OF_PICKER ; i++)
                SORT::Dev[i] = Dev[i];
        }
        else
        {
            SORT::Dev[iPkIdx] = Dev[iPkIdx];
        }
    }

    return true;
}
     


어느 프로젝트의 시퀀스 소스에서 사용하는 함수이다.

이 함수 이름만 봤을때 SetDeviceData라는  함수가 무슨 기능을 하는것인지 잘 이해가 되는가?


사소하지만 함수 이름때문에 소스 분석하는 사람이 힘들어진다.
함수 이름이 SetDeviceData()이고  파라메터 이름에 get이란것이 있으니..  함수 정의 자체에 Set과 get이라는 반대 개념의 단어가  동시에 들어가 있는 상태이다.
이런 경우 함수의 이름만 봤을때는 이 함수가 뭘하려는건지 의도가 혼란 스럽기 때문에
아예 함수를 별도로 분리하거나 함수 이름을 변경하는것이 났지 않을까 한다.

기능을 봤을때는 MoveDeviceData()나 CopyDeviceData() 정도의 함수 이름이 더 어울리지 않을까?



이 블로그는 소스 코드를 분석하다가 떠오른 생각, 느낌, 의견 등을 올린것입니다. - 이성열 - 2012.10.11









어떤 옵션의  체크 상태나 현재 상태를 표시할때 2가지 종류를 어떤 색깔로 하는것이 좋을까?


옵션이 켜졌을때를 Lime(밝은녹색)으로 하고 꺼져 있을때 Red(적색)으로 하는것을 생각해 볼수 있는데 

이 경우에는 적색이 표시될때 옵션이나 상태가 켜져 있다고 생각하는 사용자도 있을 수 있다.  

일반적인 예로 Motor Alarm 표시의 경우 적색이 켜지면 Alarm이 발생한 상태이기 때문이다.


그렇다면 적색이 Alarm ON상태이고 off 상태는 Gray(회색)으로 하는것은 어떨까?

이런 방식이면 모든 옵션의 표시할때 다음과 같은 규칙으로 일관성을 유지할 수 있다.

상태가 ON이면 Lime(밝은녹색)또는 Red(적색) 으로 표시를 하고 상태가 OFF 이면 Gray(회색)으로  표시를 하는것이다.



하지만 이 경우에도 생각해볼만한 부적한 경우가 발생한다.


CheckBox를 만들고 의미(Caption)를   "Skip Align Vision" 이라는 용도로 사용한다고 하자

메인 화면에 위 체크 박스의 상태를 표시할때.. 체크 상태를 Lime(밝은녹색)으로 표시하고 , 체크 안된 상태를 회색으로 표시한다면 얼핏  문제가 없어보일것 같지만

사용자 관점에서 Lime(밝은녹색)은 정상적인 상태를 나타낸다.

하지만 이 체크 박스는 Align Vision을 Skip하겠다는 비정상적인 상태를 선택하는 옵션이고 이것은 장비가 정상적으로 동작하는 상황이라고 볼수 없다. 

그렇기 때문에 이런 용도의 의미에서는 Checked 상태나 ON 상태일때 Red(적색) 으로 표시를 하고 OFF 상태일때 Lime(밝은녹색)   으로 표시하는것이 사용자 입장에서는 적절하다.


메인화면에 적색이 표시되고있다면 무엇인가 잘못된 상황, 비정상적인 상황이라고 인식시켜주는  것이 장비 UI 에 있어서는 올바른 방식이라고 보기 때문이다.


정리를 하면 옵션이나 현재 상태를 표시하는것은 다음과 같은 기준으로 하는게 어떨까한다.


 상태 내용

 ON 상태 표시

 OFF 상태 표시

 긍정적인 옵션

 Lime(밝은녹색)

 Gray(회색)

 부정적인 Alarm ( 모터 Alarm등 )

  Red(적색) 

 Gray(회색)

 부정적(테스트) 옵션 (ex) skip , test

 Red(적색) 

  Lime(밝은녹색)

 추가 기능 사용 여부

  Lime(밝은녹색)

 Gray(회색)


아주 단순한 Color 선택임에도 불구하고 UI를 만드는 개발자들이 일관성이 없이 색깔을 표시하기 때문에 화면 전체 옵션 상태가  사용자 관점에서 봤을때 모호하게 표시되고 쉽게 판단할 수 없는 경우가 종종 보인다.


ON/OFF 상태 표시 뿐 아니라 각각의 UI 콤포넌트를 사용함에 있어 사용자 관점에서 일관성을 유지하는 것은 설비 UI를 개발하는 사람의 기본적인  책임 중에 하나라고 할 수있다. 


최고의 개발자는 제대로 만들고 일관성을 유지하는 사람이고

최악의 개발자는 제대로 만들지도 못하면서 일관성도 없는 사람이다.


단순한 UI 하나를 만들더라도 그 UI, 기능의 존재의 이유, 동작 방법, 사용자의 입장에 대해서 한번이라도 더 생각하고 구현하는 자세가 필요하다.




이 글은 Doxygen을 처음 사용하면서 첫번째 프로젝트에 대한 결과가 제대로 나오기 까지  바꾼 설정들을 정리해 놓은 것입니다.
Doxygen 사용  경험이 없기 때문에 현재 설정 값이 제대로가 아닐 가능성도 있습니다. 그래도 한글로 주석(Comment)를 추가하고  Doxygen 포맷에 맞는 설명을 추가하여 한글 문서가 제대로 생성되는것을 확인했으니까 처음  Doxygen 을 사용하는 사람은 아래 화면 캡쳐를 참고 하면 도움이 될것입니다.

설치 파일은 2개입니다.
doxygen-1.7.4-setup.exe
graphviz-2.26.3.msi

직원들은 회사 FTP서버에서 "ICT 프로그램 설치" 폴더에 들어있는 doxygen.zip 파일을 받아서 압축을 풀면 위 파일 2개가 나옵니다. 다른 파일도 있지만 일단 무시합니다.


파일이 없거나 최신 doxygen 설치 파일은 아래 링크에서 다운로드 하면됩니다.
doxygen 다운로드페이지
 2012.3.17일 현재 1.8.0 버전까지 나와 있습니다.

call, caller그래프를 위한 설치 파일을 아래에서 다운 받을 수 있습니다.
graphviz 다운로드










[한글 문제 때문에 설정]


[한글 문제 때문에 설정] 



[SOURCE_BROWSER] 옵션을 체크해야 doxygen문서에서 소스파일(*.cpp)  보기가 가능하다.
체크 안하면 헤더파일(*.h)은 볼수 있는데 소스 파일은 포함하지 않는다.





[ Call, caller 그래프 그리는 프로그램 연결 설정]



[Run doxygen] 버튼을 클릭하면 문서화를 시작합니다.
작은 프로젝트 일때는 1분 이내이지만.. 좀 복잡하거나 클래스 상속관계가 복잡한 소스일 경우에는 전체 빌드 시간이 길어집니다.. 프로젝트와 PC성능에 따라서는 30분 이상 걸리기도 합니다.





doxygen 문서 생성 결과
아래 그림을 보면..클래스 상속도와 관계도가 깔끔하게 정리되어 표시됩니다.
각각의 멤버함수들도 caller , call 그래프가 정리되어서 나옵니다.
굳이 doxygen 전용 주석을 이용한 설명이 없어도 소스 분석하고 함께 리뷰할때  많은 도움이 될것 같습니다.



 
사용자 삽입 이미지

본 글은 선임자로서 지시 내리는 사람 입장에서 작성한것입니다. 읽을때 참고하세요

어떤 개발자 중에 일은 그런대로 하지만..

업 무 공유와 소통 능력이 부족해서 항상 업무 능력에 대해 좋지 않은 평가를 받는 사람이 있다.

고 객사에서 SW 문제점이 접수되어
담당 개발자에게 급한 사항이니 처리해서 보내라고 하였다.

그 렇게 어려운 내용도 아니라 당연히 당일 중에 처리 해서 보낼거라고 기대를 하였지만
하 루가 지나고 이틀째가 되어도 어떻게 되었는지 전혀 정보 공유가 없었다.
그 개발자가 다음날 몸이 아프다고 일찍 들어가서
다음날 다른 개발자에게 처리해서 보내라고 이슈 내용에서 담당자를 수정하였다.
그런데..
그 다음날 고객사에서 테스트 해서 확인하였다고. 메일이 날라왔다 물론 추가 요청 사항은 있었다.

나 중에 확인해 본  결과, 원래 담당 개발자는 내가 지시한 날 처리해서 메일로 보내 놓고서
나 에게 정보 공유(이메일)를 하지도 않았고, SVN 서버에 소스를 올리지도 않았으며,  이슈 관리 시스템에서 상태를 바꿔 놓지도 않았다. 3~4가지의 공식적인  업무 공유 및 소통 수단 중에서 단 한 가지도 제대로 처리하지 않은 것이다.
내가 그 진행 내용을 파악할 수 있는 방법은 전혀 없었다.

메일 보낼때 [참조] 란에  회사 전직원에게 보내도록 하는 습관만 있더라도 이런 문제는 없었는데 말이다.

그 개발자의 업무 소통 부재로 인해서 다음과 같은 문제점이 발생 했거나 가능성이 있다.

1. 고 객사 담당자가 나에게 진행 여부를 물어 봤을때 대답을 할 수가 없다.

2. 업무 지시 내용을 제대로 처리하지 않고 있다고 생각하기 때문에 그 개발자에 대해 불신이 생긴다.

3. 일 을 지시하는 입장에서 그 사람에게 시킨 일이 마무리 됐는지 알 수 있는 방법이 없으므로 답답하다.

4. 처 리가 안될 줄 알고 [이슈관리시스템]에서 다른 사람에게 담당자를 재할당하는 번거로운 문제가 생긴다.

5. 나 중에 진행 사실을 알게되어, 그 이슈는 이미 처리 된 것이므로  또 다시 이슈 담당자를 원래 개발자로 바꿔주어야 한다.

6. 만 약 재할당한 개발자가 소스 수정을 시작했다면.  똑같은 업무를 두 사람이 중복해서 한 것이기 때문에 회사 차원의 인력 낭비가 발생한다.

7. 재할당한 사람이 수정하고 SVN 서버에 까지 소스를 올려버렸다면. 나중에 원래 담당자가 소스를 올리려고 할 때  충돌이 발생한다. (물론  100% 원래 담당자의 책임이다  )

8. 위 의 모든 문제점이 발생하지 않아도 되는 것인데 생기게 되므로,  지시하는 사람은 엄청난 짜증이 몰려온다.

위 의 내용은 업무 공유에 대한 단편적인 예를 들었지만.. 회사에서 프로젝트를 진행하면서 업무 공유 부족으로 인해 발생하는 문제는 셀 수 없을 만큼 많을 것이다.
다만  정확히 지적하고 넘어가자니 쪼잔한거 같고, 계속 같이 일하자니 답답하고 이런 상황은 수도 없이 발생한다.

아주 간단한 업무 공유 방법을 제대로 지키지 않아서 위와 같은 수많은 문제점이 발생하여 회사 전체의 개발 효율을 좀 먹고 있는데도 불구하고 , 이것을 신경 쓰지 않고 별로 중요하지 않은 것으로 인식하고 있는 개발자가 있다면.. 하루 빨리 업무 공유의 중요성에 대해서 심각하게 고민해보고 실행하던가 , 그것을 못하겠다면 SW 개발이라는 직업을 떠나야 할 것이다. 그것이 더 이상 다른  동료와 회사에 피해를 주지 않는 유일한 방법일 것이다.

+ Recent posts