레이블이 book인 게시물을 표시합니다. 모든 게시물 표시
레이블이 book인 게시물을 표시합니다. 모든 게시물 표시

2020년 3월 18일 수요일

나는 LINE 개발자입니다 : 라인의 개발 고수 12인의 도전과 기회, 성장의 개발 라이프

나는 LINE 개발자입니다 : 라인의 개발 고수 12인의 도전과 기회, 성장의 개발 라이프
강윤신,김영환,김재석,김정엽,김택주 저 외 7명 | 한빛미디어




궁금해서 읽어 봤는데 결국 LINE 홍보 도서 같다.
참고로 머리말에서 이렇게 언급하고 있다. 
"이 책은 흔한 자기개발서가 아니다. 기술 서적은 더더욱 아니다. IT기업에 합격이 잘되기 위한 절대 무공비급이 들어 있는 것도 아니다
...
라인에서 동료들과 함께 개발자로서 또 한던계 성장하고 도전하면서 느끼도 배운 경험담을 통해 개발자를 꿈꾸는 이 땅의 청년들에게 비전을 보여주고 꿈과 희망을 전달하고 싶었다."

저자의 경력과 분야가 다양하여 개발자를 꿈꾸거나 개발자인 사람들이 읽고 여러 분야를 간접 체험할 수 있을 것으로 생각된다.

하지만 읽고 나면 라인 뽐뿌가 상당하니 조심해야 할 듯 ㅎ

2018년 5월 7일 월요일

모던 C++ 입문, 1장-2장

모던 C++ 입문 엔지니어, 프로그래머를 위한 C++11/14 입문
피터 고츠슐링 저/옥찬호 역 | 길벗

http://www.yes24.com/24/goods/57615943


C++을 안쓴지 오래되서 그런지 C++11, C++14 문법들이 너무 생소하다. 옛날 생각하고 Effective Modern C++을 읽기 시작했는데 너무 어려워서 기본 문법책을 고르는 중 이책을 보게 됨.
설명이 친절하진 않지만 C++11, C++14 내용을 한글로 설명하고 있어 빠르게 읽고 다시 Effective Modern C++을 읽어야 할 것 같음.

책을 보다가 기억해야 할 것들을 정리함.
더 자세한 내용은 책에 있으니 책을 읽어 보는것이 가장 좋겠음.


1장 C++ 기초

- C++14는 2진수를 0b, 0B 접두사로 표현함.
int b1 = 0b11111010;

가독성을 위해 ' 도 사용함.

long d = 61'234'567'890;
int x = 1010'0011'0000;

- 데이터가 손실되지 않는 uniform initialization, braced initalization을 사용함.
long l = {1231234567890};
int pi = 3.14;  // 데이터 손실, 컴파일 가능
int pi = {3.14}; // 에러


* 값의 종류
Lvalue, Rvalue
Lvalue = 역사적으로, 대입 표현식의 왼쪽에 나타날 수 있기 때문에 붙여진 이름으로 함수나 개체를 말함.
Rvalue = 역사적으로, 대입 표현식의 오른쪽에 나타날 수 있기 때문에 붙여진 이름으로 만료된 값, 임시 개첸 그 하위 개체, 개ㅔ와 관련이 없는 값을 말함.

좀 말이 어려운데 아래 MSDN예시를 참조하면 더 이해하기 쉬움

https://msdn.microsoft.com/ko-kr/library/f90831hc.aspx

모든 C++ 식은 lvalue 또는 rvalue입니다. 
lvalue는 단일 식을 넘어 지속되는 개체를 참조합니다. lvalue를 이름이 있는 개체로 생각할 수 있습니다. 수정할 수 없는(const) 변수를 비롯한 모든 변수가 lvalue입니다. 
rvalue는 rvalue를 사용하는 식 외에서는 유지되지 않는 임시 값입니다. 

// lvalues_and_rvalues1.cpp  
// compile with: /EHsc  
#include <iostream>  
using namespace std;  
int main()  
{  
   int x = 3 + 4;  
   cout << x << endl;  
}  

이 예제에서 x는 이를 정의하는 식 외에도 지속되기 때문에 lvalue입니다. 3 + 4 식은 이 식을 정의하는 식 외에서는 유지되지 않는 임시 값으로 계산되기 때문에 rvalue입니다.

아래 링크도 참고.
http://jeremyko.blogspot.kr/2012/08/lvalue-rvalue.html


- 곱셈과 나눗셈은 덧셈과 뺄셈보다 먼저 계산하고, 연산은 왼쪽에서 오른쪽 순서로 결합한다. ... 여러분이 정말로 중요하게 기억해야 할 것은 인수들의 계산 순서는 정의되지 않았다는 점이다. 예를 들어

int i = 3, j = 7, k;
k = f(++i) + g(++i) +j;

이 예제는 첫번째 덧셈이 두번째 덧셈보다 먼저 수행됨을 보장한다.
그러나 f(++i)와 g(++i)중 어느 표현식이 먼저 계산될 것인지는 컴파일러 구현에 따라 달라진다.


- 범위 기반 for 문

int odd_nums[] = {1,3,5,7,9,11};
for( int i : odd_nums)
   std::cout << i << " ";


- 암수 오버로드는 signature가 서로 달라야 한다.
 : 함수 이름
 : 항(Arity)이라고 하는 인자의 개수
 : (해당 순서대로) 인자의 타입


- 배열의 바이트 크기를 단일 항목의 바이트 크기로 나누면 배열의 크기를 알 수 있다.
 : sizeof x / sizeof x[0]


- 포인터 초기화
 : int* num1 = nullptr;
 : int* num2{};
 : int* bad1 = 0;
 : int* bad2 = NULL:


- unique_ptr, shared_ptr, weak_ptr
https://msdn.microsoft.com/ko-kr/library/hh279674.aspx
  • unique_ptr
    기본 포인터로 한 명의 소유자만 허용합니다. shared_ptr이 필요하다는 점을 확실히 알 경우 POCO의 기본 선택으로 사용합니다. 새 소유자로 이동할 수 있지만 복사하거나 공유할 수 없습니다. 사용하지 않는 auto_ptr을 대체합니다. boost::scoped_ptr과 비교합니다. unique_ptr은 작고 효율적이며, 크기는 1 포인터이고 STL 컬렉션에서 빠른 삽입 및 검색을 위해 rvalue 참조를 지원합니다. 헤더 파일: <memory>. 자세한 내용은 방법: unique_ptr 인스턴스 만들기 및 사용 및 unique_ptr 클래스를 참조하십시오.
  • shared_ptr
    참조 횟수가 계산되는 스마트 포인터입니다. 원시 포인터 하나를 여러 소유자에게 할당하려고 할 경우 사용합니다(예: 컨테이너에서 포인터 복사본을 반환할 때 원본을 유지하고 싶을 경우). 원시 포인터는 모든 shared_ptr 소유자가 범위를 벗어나거나 소유권을 포기할 때까지 삭제되지 않습니다. 크기는 2개의 포인터입니다. 하나는 개체용이고, 다른 하나는 참조 횟수가 포함된 공유 제어 블록용입니다. 헤더 파일: <memory>. 자세한 내용은 방법: shared_ptr 인스턴스 만들기 및 사용 및 shared_ptr 클래스를 참조하십시오.
  • weak_ptr
    shared_ptr과 함께 사용할 수 있는 특별한 경우의 스마트 포인터입니다. weak_ptr은 하나 이상의 shared_ptr 인스턴스가 소유하는 개체에 대한 액세스를 제공하지만, 참조 수 계산에 참가하지 않습니다. 개체를 관찰하는 동시에 해당 개체를 활성 상태로 유지하지 않으려는 경우 사용합니다. shared_ptr 인스턴스 사이의 순환 참조를 차단하기 위해 필요한 경우도 있습니다. 헤더 파일: <memory>. 자세한 내용은 방법: weak_ptr 인스턴스 만들기 및 사용 및 weak_ptr 클래스를 참조하십시오.


2장 클래스

위임 생성자

: https://msdn.microsoft.com/ko-kr/library/dn387583.aspx

class class_c {  
public:  
    int max;  
    int min;  
    int middle;  
  
    class_c(int my_max) {   
        max = my_max > 0 ? my_max : 10;   
    }  
    class_c(int my_max, int my_min) : class_c(my_max) {   
        min = my_min > 0 && my_min < max ? my_min : 1;  
    }  
    class_c(int my_max, int my_min, int my_middle) : class_c (my_max, my_min){  
        middle = my_middle < max && my_middle > min ? my_middle : 5;  
}  
};  
int main() {  
  
    class_c c1{ 1, 3, 2 };  
}  
  


위 예제를 단계별로 수행했다면, class_c(int, int, int) 생성자가 class_c(int)을 다시 호출하는 class_c(int, int) 생성자를 호출하는 것을 주목합니다. 각 생성자는 다른 생성자에서 수행되지 않는 작업만을 수행합니다.
호출하는 첫번째 생성자는 해당 지점에서 해당 멤버 모두가 초기화되도록 개체를 초기화합니다. 다음과 같이 다른 생성자에 위임하는 생성자의 멤버를 초기화할 수 없습니다.
class class_a {  
public:  
    class_a() {}  
    // member initialization here, no delegate  
    class_a(string str) : m_string{ str } {}  
  
    //can’t do member initialization here  
    // error C3511: a call to a delegating constructor shall be the only member-initializer  
    class_a(string str, double dbl) : class_a(str) , m_double{ dbl } {}  
  
    // only member assignment  
    class_a(string str, double dbl) : class_a(str) { m_double = dbl; }  
    double m_double{ 1.0 };  
    string m_string;  
};  
  

멤버의 기본 값

class에서 멤버 변수의 기본값을 설정할 수 있음.

class complex
{
public:
   complex(double r, double i) : r{r}, i{i} { }
   complex(double r) : r{r} { }
   complex() { }

private:
   double r = 0.0, i = 0.0
}



유니폼 초기화, 중괄호 초기화
https://msdn.microsoft.com/ko-kr/library/dn387583.aspx

#include <string>  
using namespace std;  
  
class class_a {  
public:  
    class_a() {}  
    class_a(string str) : m_string{ str } {}  
    class_a(string str, double dbl) : m_string{ str }, m_double{ dbl } {}  
double m_double;  
string m_string;  
};  
  
int main()  
{  
    class_a c1{};  
    class_a c1_1;  
  
    class_a c2{ "ww" };  
    class_a c2_1("xx");  
  
    // order of parameters is the same as the constructor  
    class_a c3{ "yy", 4.4 };  
    class_a c3_1("zz", 5.5);  
}  
  

클래스에 기본이 아닌 생성자를 가질 경우, 중괄호 이니셜라이저에 클래스 멤버가 나타나는 순서는 멤버는 선언된 순서가 아니라 ( class_a 이전 예제에서와 마찬가지로 ) 생성자에서 해당 매개 변수가 나타나는 순서입니다. 그렇지 않고 해당 형식이 선언 된 생성자를 가지지 않을 경우, 중괄호 이니셜라이저에서 멤버가 나타나는 순서는 선언되어 있는 순서와 동일합니다; 이 경우, 대부분의 공용 멤버를 초기화할 수 있지만 모든 멤버를 건너뛸 수는 없습니다. 다음 예제에서는 선언 된 생성자가 없을 때 중괄호 초기화에서 사용되는 순서를 보여줍니다.
class class_d {  
public:  
    float m_float;  
    string m_string;  
    wchar_t m_char;  
};  
  
int main()  
{  
    class_d d1{};  
    class_d d1{ 4.5 };  
    class_d d2{ 4.5, "string" };  
    class_d d3{ 4.5, "string", 'c' };  
  
    class_d d4{ "string", 'c' }; // compiler error  
    class_d d5("string", 'c', 2.0 }; // compiler error  
}   

이동 문법

이동 생성자, 이동 할당 생성자
https://msdn.microsoft.com/ko-kr/library/dd293665.aspx


// Move constructor.  
MemoryBlock(MemoryBlock&& other)  
   : _data(nullptr)  
   , _length(0)  
{  
   std::cout << "In MemoryBlock(MemoryBlock&&). length = "   
             << other._length << ". Moving resource." << std::endl;  
  
   // Copy the data pointer and its length from the   
   // source object.  
   _data = other._data;  
   _length = other._length;  
  
   // Release the data pointer from the source object so that  
   // the destructor does not free the memory multiple times.  
   other._data = nullptr;  
   other._length = 0;  
}  
  
// Move assignment operator.  
MemoryBlock& operator=(MemoryBlock&& other)  
{  
   std::cout << "In operator=(MemoryBlock&&). length = "   
             << other._length << "." << std::endl;  
  
   if (this != &other)  
   {  
      // Free the existing resource.  
      delete[] _data;  
  
      // Copy the data pointer and its length from the   
      // source object.  
      _data = other._data;  
      _length = other._length;  
  
      // Release the data pointer from the source object so that  
      // the destructor does not free the memory multiple times.  
      other._data = nullptr;  
      other._length = 0;  
   }  
   return *this;  
}  






2017년 12월 18일 월요일

JAVA API 디자인, 7-8장

http://charlie0301.blogspot.kr/2017/12/java-api.html
http://charlie0301.blogspot.kr/2017/12/java-api-5-6.html

책이 API 디자인 외에 한번쯤 library, framework을 고민한다면 읽어 볼 만함.
일부만 추려서 적었지만 책에는 더 좋은 내용이 자~알 설명 되어 있음.

------------------------------------------------------------------------------------
Chapter 7 :  모듈화 아키텍처를 사용하라

1. 모듈화 설계의 유형

라이브러리
모듈화 라이브러리들을 사용 시 구현이 중복일 수 있고 이 때 최신 API JAR만 로드 되어 링크 될 수 있도록 해야 함.
모듈화 라이브러리의 경우 각 모듈의 구현체를 접근할 수 있는 생성자, 정적 팩터리 메서드가 주로 사용되고 다른 방법으로는 프로퍼티 기반 방법도 가능하다.
모듈화 라이브러리의 "명세"는 인터페이스나 한두 개의 팩터리가 포함된 일부 패키지를 노출하는 모듈이며 해당 명세에서 허용되는 행위를 설명하는 문서도 동반한다.
"구현"은 단순히 명세 모듈에 의존하고 팩터리 구현체를 서비스 등록 시스템이 등록하는 노출된 패키지가 없는 모듈에 해당 됨.
"클라이언트"는 명세 모듈에 의존하고 팩터리 메서드를 호출하는 모듈에 해당되는

2. 상호컴포넌트 룩업과 통신

모듈화 설계의 유일한 목적은 애플리케이션의 개별 부분들을 다른 부분과 분리하는 데 있음.
두개의 모듈을 서로 독립적으로 만들고 싶다면 서로에 관해 알아서는 안되고 인터페이스를 이용해 상호작용해야 한다.

모듈 사용 시 환경 설정을 해야할 필요가 있는데 이 때 대부분의 프레임워크에서 하는 일은 의존성 주입(dependency injection)을 하며 주로 설정파일을 사용할 때가 많다.

- 의존성 주입

*** launcher 예제

모듈화 라이브러리에서는 적절한 초기화를 위해 registerXYZ를 수행하는 팩터리 클래스가 필요하다.
단 코딩 스타일의 미적 측면을 약화시킬 수 있고 절차적 등록으로 인해 (모듈갯수, 로드, 링크, 실행시간) 구동속도를 느리게 할 수 있다.

- 호출 이 필요없는(call-less) 연동 (프로퍼티기반)

*** system.getproperty 예제

연동코드를 실행할 필요가 없고 등록을 좀 더 선언적인 방식으로 수행
주로 System.getProperty()를 호출하는 방법임.
JDK에서 흔희 사용하는 괜찮은 방법이고 호출이 필요없는 등록을 허용하고 지연연동(late binding)도 가능하다.

app 개발자가 registerXYZ 호출 코드는 필요 없지만 일종의 설정을 제공해야 한다.
이는 앱 개발자에게 코드 작성 & 컴파일 & 실행 보다는 낫지만 그래도 클래스의 이름이나 시스템 동작에 대한 지식은 필요하다.
프로퍼티 기반 설정 중 널리 알려진 형식 중 하나는 스프링 프레임워크에서 제공하는 것으로 XML 설정 파일이다.

XML 설정 파일 예제

- 어노테이션 지정

스프링 2.5에서는 구현 클래스에 어노테이션을 지정하는 옵션을 제공함.

*** 어노테이션 예제

어노테이션으로 노출한 빈과 해당 빈의 이름, 다른 API에 대한 잠재적인 의존성까지 지정함.
app 개발자는 더 이상 모든 구현체 클래스의 이름을 참조하는 설정 파일을 작성할 필요가 없음.

*** 빈 설정 예제

이전 방식보다 알아야 할 지식의 양은 적어 졌지만 그럼에도 모든 구현체가 담긴 패키지의 이름은 알아야 함.

- Look Up

*** look up 예제

Lookup.getDefault()의 기본 구현은 JDK의 확장 메커니즘을 기반으로 하기 때문에 아무런 설정파일이 필요 없고 클래스패스만 올바르게 구성하면 된다.
org.apidesign.anagram.api.WordLibrary 와 같은 서비스를 찾을 경우

Lookup.getDefault().lookupAll(org.apidesign.anagram.api.WordLibrary.class) 를 실행하게 되고 이후
구현체에서는 현재 클래스패스를 발견하고 META-INF/services/org.apidesign.anagram.api.WordLibrary에 위치한 모든 리소스를 읽어 클래스명을 알아내기 위해 분석하고
클래스를 인스턴스화 한 후 해당 인스턴스들을 반환한다.

JDK6부터는 등록된 서비스 구현체의 전체목록을 조회하는 공개 API가 존재한다.

*** 예제

3. 확장점 작성하기

왓???

4. 순환 의존성의 필요성

순환 의존성은 레거시 코드를 다룰 때 꽤나 유용하다. 반면 이러한 기능을 새로 작성한 코드에 사용하는 것은 클래스와 모듈 간의 참조로 구성된 하나의 커다란 스파게티 접시를 만드는 것과 같다.

상호 참조는 Lookup을 사용하여 의존성을 제거할 수 있다.
또한 각각 독립적으로 실행되지 않으므로 필요로하는 의존성은 manifest에 명시를 하여 적절히 처리되도록 하는게 필요하다.

5. Lookup은 어디에나 있다.

JDK의 ServiceLoader와 달리 넷빈즈의 Lookup은 다수의 인스턴스를 가질 수 있고 각각은 개별 풀의 역할을 수행한다.
예를 들어 아이콘이 java.awt.Image로 변환되어야 할 필요성이 있는 경우 아이콘이 해당 class를 이미 가지고 있다면 loader에서 찾아 제공하고 아니면 이미지를 만들어 처리하면 된다.

*** 아이콘 예제

Lookup을 이벤트 버스 (event bus)로 생각할 수 있다. 객체가 들어오고 나오고 하는 곳 같이..

*** Modifiable 예제

다른 유용한 것으로는 질의 패턴(query pattern)이다. Lookup의 두가지 측면을 혼합한 것인데 적응형 패턴(adaptable pattern)에 대한 API가 될 수 있다는 것과 Lookup이 컴포넌트 주입에 대한 파사드가 될 수 있다는 것을 의미한다.

6. Lookup의 남용

Lookup의 동적인 특성은 대단히 흥미롭고 감동적이어서 불필요하게 사용할 때가 있다.
Lookup이 흥미로운 객체로 가득 찬 "마법 가방"의 역할을 하게 되는 것이고 API 사용자는 가방안에 손을 집어 넣어 아무것도 안 보이는 채로 특정 인터페이스를 찾는다.
인터페이스가 있다면 제대로 동작할 것이고 없다면 완전히 망가질 것이다.


------------------------------------------------------------------------------------
Chapter 8 : 클라이언트와 제공자를 위한 API를 분리하라.

클라이언트를 위한 API와 플러그인을 위한 서비스 제공자 인터페이스(SPI)는 다르다.

API 진화는 SPI 진화와 다르다.

클라이언트에게 메서드를 제공하는 API의 경우 추가와 관련된 문제는 없다.
새로운 메서드를 추가한다고 해서 바이너리 호환성이 깨지는 것은 아니고 클라이언트 입장에서는 더 많은 가능성과 선택권을 갖게 된다.

. SPI의 경우 정확히 그 반대다.
다른사람들이 반드시 제공해야만 하는 인터페이스에 새로운 메서드를 추가하면 사실상 기존의 모든 구현체가 망가진다.

. API를 적절히 나눠라.
API와 SPI를 분리하는 이유는 진화 문제 때문이었다.
다른 접근 법은 가독성이다.

모든 API(특히 자바로 작성된 API)는 지역성(locality)을 보이며 관련성 있는 것들은 서로 가까운 곳에 정의된다.
사용자에 관해 생각해 보고 사용자가 API에 기대할 만한 지역성을 사용자에게 제공하라.
- 관련 메서드는 같은 클래스에 배치한다.
- 관련이 없는 메서드를 어디에 둬야 할지 생각해낼 수 없다는 이유로 그것들이 이어써야 할 자리가 아닌 곳에 놓아서는 안 된다.
- 관련 클래스는 한 패키지 안에 넣어라.
- 특별한 상황에 유용한 추가적인 클래스는 다른 곳으로 옮긴다.

위 규칙들을 따르면 API의 지역성이 증가하고 결과적으로 API 내에서의 사용자 지향성이 대폭 증가할 것이다.

여러분이 만든 라이브러리의 인터페이스를 훨씬 더 많은 부분으로 나누는 것이 타당하다.
다음은 API를 네가지 서로 다른 범주로 정의한 넷빈즈 모듈의 예다.

- 핵심 API : 이 핵심 API를 사용하지 않고는 불가능한 일부 핵심적인 연산을 수행하고자 하는 평범한 관심사를 가진 사용자 그룹
- 지원 API : API 사용을 용이하게 하는 유틸리티 메서드 집합. 이러한 유틸리티 메서드는 반드시 사용해야 하는 것은 아니지만 API 사용자에게 편의성을 제공한다.
- 핵심 SPI : 라이브러리에 연결(plug in)하고자 하는 다양한 그룹의 사용자를 위한 인터페이스 집합.
- 지원 SPI : 이따금 연결할 인터페이스를 구현하는 것이 다소 복잡할 때가 있다. 다시금 도우미 인터페이스를 제공할 수 있다.

위는 넷빈즈의 특정 모듈에 어떤 것이 효과적인지만 보여주는 것이고
다만 넷빈즈 프로젝트를 진행하면서 저지른 실수로부터 얻은 교훈 중 하나는 바로 API가 사용의 지역성을 따른 다면 API 사용자의 삶이 향상된다는 것이다.

2017년 12월 11일 월요일

JAVA API 디자인, 5-6장

http://charlie0301.blogspot.kr/2017/12/java-api.html

책이 API 디자인 외에 한번쯤 library, framework을 고민한다면 읽어 볼 만함.
일부만 추려서 적었지만 책에는 더 좋은 내용이 자~알 설명 되어 있음.

------------------------------------------------------------------------------------
5장 : 필요 이상으로 노출하지 마라.

무언가를 API로 만들것이냐 만들지 말 것이냐를 결정하는데 유스케이스를 만들어 보라
특정 메서드나 클래스에 대한 유스 케이스가 없거나 미심쩍다면 API에 해당 요소를 빼는 편이 낫다.
API를 처음 릴리스하기 앞서 제거할 수 있는 것은 모조리 제거하라는 것이다.


1. 필드를 감춰라, 직접 노출하기 보다는 필드에 접근하는 메서드(getter, setter)를 사용하는 편이 낫다.
읽기, 쓰기만 가능한 필드 보다 추가작업을 할 수 있다.

2. 생성자보다 팩터리가 낫다.
생성자 대신 팩터리 메서드를 노출할 경우 나중에 API를 진화시키기 수월해진다.

 1. 팩터리의 반환 클래스 타입을 유연(다형성)하게 제공할 수 있다.
 2. 인스턴스를 캐싱할 수 있다.
 3. 동기화가 가능하다.

3. 모든 것을 final로 만들어라
서브 클래싱을 허용하는데는 생각치 못한 결과가 발생할 수 있으므로 class를 final로 만들어라.

4. 어울리지 않는 곳에 설정자 메서드를 넣지 마라.
설정자(setXXXX)는 구현 세부사항을 API 사용자가 아는 상황에서 사용 가능하다.
API의 기능을 풍부하게 만들기 위한 방법으로 주로 사용되는데 역효과(유지보수, API 시맨틱 파악 어려움)가 발생한다.

5. 프랜드 코드에서만 접근하는 것을 허용하라.
API에서 너무 많은 것들을 호출하지 않으려고 할 때 또 한가지 유용한 기법은 특정 기능에 대한 접근 권한을 "프랜드(friend)" 코드에만 부여하는 것이다.

- "Only for internal use", "Do not call me" 이딴 설명을 API에 적지 말고 접근권한 변경으로 사용자에게서 숨겨라.

6. 객체를 만든 이에게 더 많은 권한을 부여하라.
(TBD)

7. 깊은 계층구조를 노출하지 마라.
(TBD)


------------------------------------------------------------------------------------
6장 : 구현이 아닌 인터페이스를 대상으로 코드를 작성하라.

1. 메서드나 필드 제거하기

일단 공개된 인터페이스나 클래스에서 메서드나 필드를 제거하는 것은
기존 API 사용 코드들에서 컴파일 에러를 발생 시키고 나아가서 바이너리 호환성도 보장하지 않는다.

private, package private, protected abstract(설계 실수)는 제거 가능
public, protected(설계 실수) 는 제거 불가


2. 클래스나 인터페이스를 제거하거나 추가하기

제거는 소스및 바이너리 차원에서 문제를 일으킴, 공개된 것들은 계속 유지하는 것을 권고
추가는 문제 없음. 다만 와일드카드 임포트를 이용할 경우 소스 호환성이 깨질 수 있음.


3. 기존 계층 구조에 인터페이스나 클래스 집어 넣기

가능, 제약 조건은 원본 및 새로운 타입에서 접근할 수 있었던 메서드 전체가 동일하게 유지되거나 최소한 줄어들지 않아야함.


4. 메서드나 필드 추가하기

필드의 경우 앞서 말한 것과 같이 바이너리 호환성을 지원할 수 있는 static final이 아닌 이상 API에 추가해서는 안된다.

정적 메서드를 추가하는 것은 바이너리 관점에서 수용할만하지만 클래스에서만 사용해야 한다.
정적 메서드와 중복 정의된 비슷한 메서드의 변종들로 비호환성을 야기하거나 컴파일 오류를 만들 수 있다.

서브클래싱이 가능한 클래스에 추상 메서드를 추가하는 것은 호환성을 깨뜨리는 변경사항에 해당됨. 이는 인터페이스를 사용하는 구현에서 런타임 예외를 발생 시킬 수 있다.
즉 추상메서드를 서브클래싱이 가능한 클래스와 인터페이스에 추가하는 것을 최소화 해야 하던가 클래스와 인터페이스를 서브클래싱 할 수 없게끔 만들어야 한다.

5. 자바 인터페이스와 클래스 비교

자바 인터페이스의 가장 큰 기능은 다중 상속이지만 실제로 성능, 점유 메모리의 양을 최소화 하기 위함이다.
다중 상속이면 하나의 객체로 API 인터페이스를 무제한 상속 가능하지만 클래스의 경우 API 클래스 마다 하나의 하위 클래스를 생성해야 하고 다른 클래스와 연관된 경우 위임을 통해서 인스턴시를 연결해야 한다.
단 한 두개 보다 상당한 객체들을 생성하는 경우에만 상당한 효과가 있다.


6. 외유내강

인터페이스 관점에서 기존 인터페이스에 메서드를 추가하는 것이 다소 어렵다.
하지만 이를 인터페이스의 강점으로 대처할 수 있는데
각기 버전마다 인터페이스를 만들어 제공하는 것이 방법이 될 수 있다.
Language13, Language14, Lauguage15 와 같이 인터페이스르 만들어 제공하면 사용자는 필요한 것을 선택해 사용함.
단 너무 인터페이스가 급격히 늘어나면 클라이언트 코드가 복잡해 질 수 있다.


7. 메서드를 추가하길 좋아하는 사람들의 천국

메서드가 완전히 바이너리 호환성을 보장하도록 하게 위해서는 final 클래스 형태로 표현한다.
이는 서브클래싱도 막을 수 있고 인터페이스나 추상 클래스에 메서드가 추가됐을 때도 문제는 없지만
추가된 메서드를 호출되는 경우에는 문제가 된다
클래스 파일에서 메서드의 이름과 매개변수, 반환형을 기준으로 호출된 메서드를 완전히 구분하므로
이름과 인자수가 같은 메서드를 추가하지 않아야 문제를 방지할 수 있다.

8. 추상 클래스는 유용한다.
지금까지 불변적인 계약을 정의하고 싶을 때 자바 인터페이스를 사용하고
메서드를 추가할 능력을 갖추고 싶을 때 자바 final 클래스를 사용해야 한다고 주장
반면에 추상 클래스를 사용할 이유는 실제로 없다.

자바 인터페이스와 비교 시 자바 추상 클래스의 한가지 이점은 정적 메서드를 포함할 수 있어 추상 클래스에 정적 팩터리 메서드를 만들 필요성이 있다면 사용 가능하다.

자바 인터페이스에 비해 자바 클래스의 유용한 특징은 접근 권한을 제한할 수 있다.
추상클래스를 만들어 제공할 경우 구현할 수 있는 클래스 제한은 런타임 시 클래스 타입을 보고 제한할 수 있다.

9. 매개변수 증가를 위한 대비
response/reply 패턴?

10. 인터페이스 대 클래스
구현이 아닌 인터페이스(자바 인터페이스가 아니라 추상적인 정의)를 대상으로 코드를 작성하라.
자바 인터페이스를 사용해서 불변적인 타입을 명시하고 메서드를 안전하게 추가할 수 있는 곳에서는 final 클래스를 타입으로 사용한다.
목표가 완전한 바이너리 호환성을 보장하는 것이라면 다른 누군가가 구현할 수 있는 클래스나 인터페이스에 절대 메서드를 추가해서는 안된다.

2017년 12월 4일 월요일

Java API 디자인 책, ~4장

필요에 의해 이 책을 보게 되었는데..

책에 써 있는대로 3일만에 뚝딱 읽을 수 있는 책이 아님.
너무 말이 많다. 하지만 내용은 좋아서 두고 보고 싶지만 대출기간이 짧아서 좀..

http://www.yes24.com/24/goods/17713587?scode=032

독자분들께,
서점에서 이 책을 손에 들고 “이 책을 사야 할까?”라고 자문하고 계신다면 저는 이렇게 답하겠습니다. 만약 여러분이 작성한 코드가 다른 사람들이 작성한 코드를 컴파일하는 데 필요하다면 여러분은 API의 세계에 들어갈 준비가 된 것입니다. 그리고 이 책은 여러분이 API의 세계를 탐험하도록 도와줄 것입니다.
하지만 이 책은 “5번의 손쉬운 강의로 API 설계를 가르쳐 드리지” 않습니다. 이 책은 “단 3일만에” 읽을 수 있는 책이 아닙니다! 빠르게 읽을 수 있는 지침서를 찾고 계신다면 아마 이 책은 아닐 것입니다. 한편으로 API 설계에 관한 깊이 있는 지식, 즉 API 설계에 대한 “어떻게”뿐만 아니라 “왜”에도 관심이 있다면 이 책을 책장에 다시 내려놓으시기 전에 저를 잠깐 소개해 드리겠습니다.

일단 읽은 부분 까지만 간략히 정리를 하려고 했는데
도저히 1-3장은 요약을 못하겠음. 대신 목차만 보자면..


[1부] 이론과 정당성

애플리케이션 프로그래밍 인터페이스(API; Application Programming Interface)를 만들고 설계하고 작성하는 과정은
예술적인 탐구이자 과학적인 탐구로 볼 수 있음.
관점에 따라 API 아키텍트는 세상을 바꾸려는 예술가이거나 여러 세계를 잇는 다리를 만들려는 기술자에 해당한다.

나머지는 요약 불가...

1장: 현대 소프트웨어 구축의 예술
  합리주의, 경험주의, 무지
  지금까지의 소프트웨어의 진화
  거대한 기반 요소
  아름다움, 진리, 우아함
  더 무지해져라!

2장: API를 만드는 이유
  분산 개발
  애플리케이션 모듈화
  비선형적인 버전 관리
  중요한 것은 의사소통이다
  경험적 프로그래밍
  첫 번째 버전은 늘 쉽다

3장: 훌륭한 API를 결정하는 요소
  메서드와 필드 시그너처
  파일과 파일의 내용
  환경변수와 명령줄 옵션
  API로서의 텍스트 메시지
  프로토콜
  동작 방식
  I18N 지원과 L10N 메시지
  넓은 의미의 API
  API의 품질을 검사하는 법


4장: 시시각각 변하는 표적


1. 첫 번째 버전은 결코 완벽하지 않다.
 API 개선 시 API 사용자에게 문제를 일으키지 않도록 설계해야 한다.

2. 하위 호환성

. 소스 호환성
 = API가 변경되어도 컴파일 될 수 있는가?

클래스에 새 메서드를 추가하는 것도 소스 호환성을 깰 수 있다.
필요 없는 class들을 import하는 wildcard import 로 호환성이 깨질 수 있다.

. 바이너리 호환성
 = 이전 버전의 라이브러리를 가지고 컴파일된 프로그램이 다시 컴파일하지 않고도 새로운 버전의 API와 링크 될 수 있는가?
이로 인해
1. 애플리케이션을 작성한 다음 그것을 한 버전의 라이브러리와 컴파일하는 동시에 사람들이 다른 버전으로도 사용하게 만들 수 있고
   애플리케이션의 유지보수와 패키징, 배포가 대폭 간소화 된다.
2. 이전 버전의 라이브러리를 대상으로 빌드 된 바이너리만 가지고 있는 사용자가 애플리케이션이 재 컴파일될 때까지 기다리지 않고도
    새로운 버전의 라이브러리로 마이그레이션 할 수 있다.

가상머신이 메서드를 찾을 때는 모든 가능한 상위 클래스까지 찾는데 비해 필드를 찾을 때는 지정된 클래스에서만 필드를 찾는다.
결과적으로 필드대신 메서드를 노출하는 편이 추후를 위해서 낫다.

객체 지향 언어에서 메서드를 선언한는 것과 재정의하는 것과 관련해서 가상 메서드 테이블(virtual methods table)를 알아야 한다.
final 키워드를 지정하지 않은 메서드가 여러개 포함된 클래스를 정의할 경우 사실상 테이블을 하나 만들게 된다.
이 테이블에는 메서드의 이름들(프로토타입 포함)이 해당 메세드를 호출 했을 때 실제로 실행되는 코드와 매핑되어 있다.
하위 클래스를 만들면 앞에서 말한 테이블이 만들어지고 이 테이블은 특정 메서드가 호출됐을 때 실행되는 새로운 코드를 가리키는 다른 포인터들로 채워진다.
이후 메서드를 호출하는 코드에서는 항상 테이블을 검사해서 시그너처를 기준으로 올바를 메서드를 찾아 테이블에 등록된 실제코드를 호출한다.

API 클래스에 public static final 문자열이나 정수 상수를 정의한다면 평범한 object나 다른 타입의 경우처럼 참조되지 않고 대신 그것을 참조하는 클래스로 복사된다. 이는 새 버전의 API에서 원시 상수 같은 것들의 값을 변경하더라도 해당 API의 클라이언트(이미 사용중인)가 보는 값은 변경되지 않는 다는 것을 의미한다.

. 기능적 호환성
 = 어떤 App을 새 버전의 라이브러리를 대상으로 실행했을 때와 이전 버전의 라이브러리를 대상으로 실행했을 때 동일한 결과를 보이는가?
이를 위해서는 API가 어떤 일을 해야 할지 명확하게 이해하고 그것을 실제 프로그래밍 언어로 표현하는 기술이 탁월해야 하며, API 사용자가 API를 어떻게 사용할 지 예상할 수 있어야 한다.

. 유스 케이스 지향의 중요성
API를 통해 무슨일을 할 수 있고 왜 해야 하고 어떻게 할 수 있는지를 파악하기 위해 API 사용자에 대해 생각해볼 필요가 있다.

유스 케이스는 인공적인 것에 불과하고 현실과 거리가 멀 수도 있고 API 실제 사용자의 요구사항과 다를 수 있다.

유스 케이스는 API에서 의도하는 사용법을 설명한 것으로 잠재 사용자가 겪을 수 있는 문제를 구체적인 해결책 없이 보여준다.
잠재적인 문제를 사람들이 겪을 가능성이 높은 실제 문제와 최대한 가깝게 만드는 것은 진짜 유용한 해결책(API)을 만들어 내기 위한 훌륭한 첫걸음이다.

시나리오는 추상적인 유스 케이스를 API에서 실제로 실현된 내용과 연결된다. 시나리오에서는 어떤 클래스나 인터페이스를 구현해야 하고.
그것들을 등록하려면 선언적인 파일을 어디에 어떻게 넣어야 할지 기술한다.

. API 검토
API 변경 요청을 제출 시 다음의 "성공적인 API 설계를 위한 규칙"을 충족하는 지 검사한다.
-  유스 케이스 기반 API 설계
 : API 설계 동기가 추상적이고 일반적인 수준으로 기술돼 있으며, 이를 통해 실제 시나리오에 대한 일반적인 설계 결정과 API가 최종적으로 실현된(javadoc) 결과물이 연결된다.
- 일관성 있는 API 설계
 : 개별 개발자가 만든 API는 반드시 팀 전체에서 공유하는 일반적인 "모범 사례"와 부합해야 한다.
- 단순하고 깔끔한 API 설계
 : 간단하고 공통적인 작업은 쉬워야 한다. 중요 유스케이스가 구현하기 쉬운 시나리오를 통해 충족되는지 확인할 수 있다.
- 더 적은 것이 더 많다.
 : 유스 케이스에 기술된 대로 딱 필요한 기능만 노출돼야 한다. 이렇게 하면 API 사용 범위의 예상과 현실간 차이를 방지할 수 있다.
- 진화 대비
 : 라이브러리는 반드시 나중에 유지 보수할 수 있어야 한다. 새로운 요구사항이 나타나거나 기존에 유지 보수하던 사람이 떠나더라도 API가 위태로워져서는 안 된다.

. API 생명주기
넷빈즈의 API 범주
- 비공개(Private) : 접근 가능하나 모듈과 라이브러리 외부에서 사용할 용도로 만들어진 것은 아닌 기능에 부여하는 범주
- 프렌드(Friend) : API는 시스템의 다른 부분(한정된 영역)에서 사용하기 위해 고안 된 범주
- 개발 중(Under development) : 안정적인 API 될 것으로 예상되는 불완전한 계약
- 안정(Stable) : 제품 품질에 도달했고 공개적으로 사용할 준비가 된 인터페이스에 사용됨.
- 공식(Official) : API는 안정적이면서 제품에 패키징 된 상태
- 서드파티(Third-party) : 인터페이스는 내부 규칙을 따르지 않는 측에서 제공된 범주, 이러한 인터페이스를 노출해서는 안된다.
- 표준(Standard) : 서드파티 분류와 비슷하다.
- 지원중단(Deprecated) : 어느정도 시간이 흐른 후 거의 모든 API는 현재 상태와 상관없이 쓸모가 없어지거나 새로운 API로 대체된 경우 해당되는 범주

. 점진적 향상
점진적 변경 vs 빅뱅 방식
점진적 변경 : 라이브러리 기능은 보전하면서 새로운 메서드나 클래스를 추가하거나 새로운 엘리먼트를 추가하는 것
빅뱅 방식 : 보통 기존 API를 완전히 개조해서 새로운 버전을 만들어내는 행위

"사소"한 점진적 변경이라도 API 사용에 심각한 악영향을 줄 수 있다.
빅뱅은 하위 호환성에 대해 현실적이지만 사용자들이 새로운 API를 사용하고 적응하는데 시간과 비용이 필요하고 사용자들은 뭔가 새로운 장점이 있을 것이라고 기대할 수 있다.

결론적으로는 빅뱅방식에 비해 피해가 적은 점진적 변경을 준비해야 한다. 하지만 API가 형편 없어 점진적 변경이 불가하다면 빅뱅방식의 변경이 정당화 될 수 는 있다. 단 API 사용자들의 고통을 수반한다는 것을 염두해야 한다.


나머지는 나중에..




2017년 7월 11일 화요일

고성능 .NET 프로그래밍 책을 읽고 필요한 것만 대충 정리

책을 읽다가 좀 정리함.
책의 내용은 좋은데... 이해가...

http://www.yes24.com/24/goods/24020688






성능에 대한 부분에 대해서 고민을 하고 있거나
C#, .NET 프로그래밍 시 이유나 원인을 잘 모르고 있던 것들에 대해서 설명을 잘해주고 있다.
게다가 어셈블리까지 직접 보여주며 설명하고 있는 센스 :) (난 이해 못함)

내용이 어렵거나 번역상 몇 번을 읽어도 이해되지 않는 부분이나
다소 불필요할 정도로 자세한 내용도 있는 듯하다.

보고 대체로 나에게 필요한 부분만 정리함.
자세하고 중요한 내용은 다 책에 있으니 나중에 계속 읽어 보련다.

비동기 프로그래밍

멀티 스레드를 사용하는 3가지 근본적인 이유 - UI main thread를 차단?하지 않기 위해 - I/O를 완료할 때까지 기다리지 않고 다른 작업을 함께 처리 - 처리하는 작업에 모든 프로세스를 동원 Thead context switching 비용을 위해서 .NET에서는 각 관리되는 프로세스에 대한 스레드 풀을 관리함.

Task 사용

.NET 4.0에서는 TPL(Task Paralle Library)라는 스레드의 추상화를 소개함. 내부적으로 TPL은 .NET thread pool을 사용하지만 해당 thread를 pool에 다시 반환하기 전에 동일한 thread에서 순차적으로 여러 tasks를 실행하므로 더 효율적으로 수행한다. - 연속 Task가 빠르고 짧은 코드 부분이면 task들이 동일 스레드에서 실행되도록 지정하는 것도 방법 : context switching, queue에서 대기 시간을 줄일 수 있음. : https://msdn.microsoft.com/ko-kr/library/dd321576(v=vs.110).aspx public Task ContinueWith( Action<Task> continuationAction, TaskContinuationOptions continuationOptions )
public class TaskCounter
{
   private volatile int _count;

   public void Track(Task t)
   {
      if (t == null) throw new ArgumentNullException("t");
      Interlocked.Increment(ref _count);
      t.ContinueWith(ct => Interlocked.Decrement(ref _count), TaskContinuationOptions.ExecuteSynchronously);
   }

   public int NumberOfActiveTasks { get { return _count; } }
}
: 단 I/O thread와 관련되어 있다면 확인 필요. - 오랫동안 동작하는 Task의 경우 TaskCreationOptions.LongRunning flag를 사용 : https://msdn.microsoft.com/ko-kr/library/system.threading.tasks.taskcreationoptions(v=vs.110).aspx - Task 다중 연속 : ContinueWith()를 사용해서 연속해서 사용할 수도 있음. : https://msdn.microsoft.com/ko-kr/library/dd270696(v=vs.110).aspx task.ContinueWith(OnTaskEnd1); task.ContinueWith(OnTaskEnd2); => OnTaskEnd1, OnTaskEnd2 가 독립적이고 병렬적으로 실행됨. task.ContinueWith(OnTaskEnd1).ContinueWith(OnTaskEnd2); => OnTaskEnd1이 실행되고 OnTaskEnd2가 실행됨. : Task 종료 조건에 따라 실행되게 할 수도 있음. . https://msdn.microsoft.com/ko-kr/library/dd321576(v=vs.110).aspx . https://msdn.microsoft.com/ko-kr/library/system.threading.tasks.taskcontinuationoptions(v=vs.110).aspx : 다중 Task handling을 위해서는 Task.Factory.ContinueWhenAll, Task.Factory.ContinueWhenAny - Task를 강제로 취소하는 것 보다 Task 내에서 취소 여부를 확인해서 종료하는 방법 추천 - Task.Wait()을 사용하는 것은 Task를 강제로 기다리게 하므로 비추임. : 해당 thread가 대기 상태로 차단되고 언제 다시 시작할 지 몰라서 다른 스레드를 실행 시킴. : 스레드에서 신호를 기다리면서 몇 밀리초 동안 회전하는 동기화 개체를 적중 시킴. 실패 시 차단되고 기다림.

Async와 Await

.NET 4.5에서 async, awit가 소개됨. TPL 코드를 쉬운 선형 동기화 코드로 전환 시킴. : https://docs.microsoft.com/ko-kr/dotnet/csharp/async private readonly HttpClient _httpClient = new HttpClient(); downloadButton.Clicked += async (o, e) => { // This line will yield control to the UI as the request // from the web service is happening. // // The UI thread is now free to perform other work. var stringData = await _httpClient.GetStringAsync(URL); DoSomethingWithData(stringData); };

올바른 Timer 사용

- 과도하게 많은 Timer 를 만들지 않도록 하자. : 모든 Timer는 스레드 풀의 단일 스레드에서 제공됨. : 너무 많은 Timer 는 Timer Callback 실행에 지연을 일으킨다. - 운영 체제의 tick counter(15밀리초)보다 정밀할 수 없음.

스레드를 중단하지 않는다.

스레드 우선순위를 변경하지 않는다.

스레드 동기화와 잠금

- 스레드들 간 동기화/잠금은 CPU를 낭비하며 context switching 시간을 높힌다. - 다음 기본 원칙들을 고려하자. : 잠금이 필요한가? . 스레드 동기화에 대한 필요성을 완전히 제거할 수 있다면 성능향상에 있어 궁극적인 방법임. . 단지 변수를 읽기만하거나 불변일 경우 동기화는 필요하지 않다. . 쓰기를 할 경우 임시사본을 사용해서 쓴 다음 한번에 동기화하여 쓰는 것도 방법이다. : 동기화 우선 순위 . 동기화에도 여러 수준이 있으므로 판단해서 사용 성능에 미치는 순서 : 동기화 안함 < Interlocked method < lock/moitor class < 비동기 잠금 < 기타 : 메모리 모델 . 메모리 모델 : 시스템(HW/SW)에서 규칙의 집합으로 컴파일러나 프로세서에서 다중 스레드에 다시 순서를 매기는 읽기와 쓰기 작업이 얼마나 되는지를 통제한다. 순서 재정렬에서 컴파일러와 하드웨어가 많은 최적화를 수행하지 못하게 하는 절대적인 제약 사항이 있는 경우 strong 모델로 기술한다. weak 모델에서는 컴파일러와 프로세서가 더 많은 자유를 허용 받으므로 잠재적으로 더 나은 성능을 얻기 위해 읽기와 쓰기 명령들의 순서를 바꿀 수 있다. . x86/x64은 strong 모델이며 ARM은 weak 모델을 가진다. => 즉 CLR의 호환성을 위해 해당 코드가 약한 메모리 모델이 맞는지 보장하는 것이 좋은 방법이다. 스레드 간의 공유되는 상태에서 volatile을 올바로 사용하여 JIT 컴파일러로 하여금 문제를 정리하도록 하는 것도 방법임. 공유 상태의 적절한 순서를 보장하는 다른 방법은 Interlocked를 사용해서 잠금 내에서 모든 액세스를 유지하는 것도 방법임. * 나머지는 책에서 자세히 다루고 있음 꼭 책을 구입해서 보세요!!!

일반 코딩 및 클래스 설계

- 클래스의 인스턴스는 항상 힙에 할당,일부 개체는 고정 오버헤드를 가짐 (32bit - 8bytes, 64bit - 16bytes) - 구조체는 전혀 오버헤드를 가지지 않음. (메모리 사용 = 구조체의 모든 필드의 크기 합) : 구조체가 메서드의 지역변수로 선언 => 스택 할당 : 구조체가 한 클래스의 일부분이면 => 힙에 존재 - 구조체 배열에서는 데이터의 동일한 크기가 메모리 양을 작게 차지한다. (오버헤드 없음) - 구조체 배열은 순차적으로 메모리에 존재하므로 CPU 캐시에 존재 시 더 빠른 순서로 참조 될 수 있음. - 메서드를 가상화 하는 것은 JIT 컴파일러가 메서드를 인라인 시키는 특정 최적화를 막는다. : 파생 클래스가 없다면 sealed를 표시하라. - foreach보다 for가 빠르다. (당연하겠지만..) : IEnumerable<int>보다 단순 배열이 더 많은 비용이 소요된다. (당연하겠지만..) - 캐스팅도 비용이다. : if (a is foo) { Foo f = (Foo)a; } => Foo f = a as Foo; if (f != null) { } - 예외가 발생된 메서드는 단순 빈 메서드보다 수천 배 느리다

.NET 프레임워크 사용

- Generic Collection은 boxing이나 변환 비용을 발생시키지 않고 더 좋은 메모리 집약성을 가짐. : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/generics/ : Dictionary => hash table로 구현되고 O(1) 삽입, 조회 시간을 가짐 : SortedDictionary => binary search tree로 구현되고 O(log n) 삽입과 조회 시간을 가짐 : SortedList => 정렬된 배열로 구현 O(log n) 조회시간, worst case로 O(n) 삽입 시간을 가짐, 단 최소 메모리 사용. : HashSet => hast table을 사용, O(1) 삽입 및 제거 시간 가짐 : SortedSet => binary search tree를 사용하고 O(long n) 삽입, 제거 시간을 가짐 - 문자열 비교 시 option에 따라서 속도 차이 고려 필요 : String.Compare(a,b, option), StringComparison.OrdinalIgnoreCase < StringComparison.Ordinal < StringComparison.CurrentCulture : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/strings/how-to-compare-strings - ToLower, ToUppper는 왠만하면 피하라. - String 생성 시 단순 '+' 연산자나 String.Concat 메서드를 사용하라. : StringBuilder를 사용하는 것 보다 효과적이고 StringBuilder는 문자열이 아주 가변적이고 크기가 클 때 고려하라. - 문자열 서식 (String.Format()) 메서드는 비용이 크므로 간단한 문자열이면 단순 연결 '+'을 사용하라. - 정상적인 상황에서 예외 발생 API를 회피하라. - 느슨한 초기화를 사용하자 (Lazy<T>) - 정규 표현식은 빠르지 않고 어셈블리 생성, JIT 비용, 평가 시간을 위한 비용 및 시간이 필요하다. : Regex 성능 개선을 위해서는 Regex 인스턴스 변수 생성, RegexOptions.Compiled 플래그 사용, 반복 생성하지 않고 재사용 하는 것이 방법 - LINQ는 편리하고 성능 기준에 만족하지만 코드 숨김의 가능성이 있어 조심해서 사용하라.

2016년 11월 2일 수요일

소프트웨어 장인 : 프로페셔널리즘, 실용주의, 자부심

http://m.yes24.com/Goods/Detail/20461940

소프트웨어 장인 : 프로페셔널리즘, 실용주의, 자부심
산드로 만쿠소 저/권오인 역 | 길벗



서점가서 처음에 표지보고 이게 뭥미 하고 무시했었는데 지인이 추천해서 보게 되었음.
책 저자가 너무 말이 많은듯해서 읽기가 지지부진했었는데 다른 사람들도 읽는 거 보고 궁금해서 완독함.

읽다 보면 뭐 이건 당연한 것 아닌가 했던 내용이 있어 읽으며 동의하며 줄줄 읽었음. 다만 저자의 다양하고 오랫동안 경험들이 책의 내용이라 아주 알차다. 너무 알차서 읽다가 질릴 정도로 아주 자세하고 유익하다.

솔직히 읽는 중에 장인이라는 용어가 좀 거슬렸었다. 사실 소프트웨어 엔지니어, 개발자, 코더 등등 같은 용어를 써도 별 상관이 없이 맡은 일에 대한 열정과 자부심을 가지고 대하면 된다는 생각을 하는 터라 왠지 모를 의도가 있을 것 같은 장인이라는 호칭이 좀 부자연스러웠었다. 하지만 책의 appendix를 보면 저자의 의도와 관련된 오해를 풀 수 있었다. 책을 읽을 때 장인이라는 단어에 집착하기보다 그 호칭을 부르기 위한 조건, 태도, 의도에 집중하는 것이 좋을 것 같다.

저자가 영국 컨설팅회사에서 근무하는 것 같아 국내와 좀 다른 환경에서 근무하지 않을까 생각했었는데 생각외로 국내의 환경이 열악한 쪽으로 더했으면 더했지 덜하지는 않을 것 같다.
그리고 저자가 제시하는 방법들 가령 애자일방법론, 오픈소스활동, 스터디 등도 관심만 있다면 국내에서 충분히 가능한 것 같다.

공감된 부분들이 상당히 많지만 몇 가지 발췌하자면 다음과 같다. 단 책의 일부이므로 온전하게 읽어보는 것을 추천

“네 커리어와 프로페셔널로서의 미래는 누구의 책임인가?” 그날의 대화가 있은 지 몇 년이 흘렀지만 아직도 그의 당혹스런 눈빛을 기억한다.
: 맞는 말이다. 회사에서 최선으로 일해야하지만 환경과 여건을 핑계로 자기개발을 게을리하면 안된다. 결국 자기 손해인 것 같다.

"보통 어떤 개념이나 행동양식을 다룬 책들이 혁명적인 책이 될 때가 대부분이다. 『실용주의 프로그래머』, 『The Mythical Man-Month』, 『디자인 패턴(GoF)』, 『테스트 주도 개발』, 『익스트림 프로그래밍』, 『클린 코더』, 『소프트웨어 장인정신』, 『리펙토링』과 같은 책들이 있다. 이러한 종류의 책들을 완전히 이해하려면 몇 년 이상이 걸리기도 한다."
: 이 책들은 기본 필독서다.

"차드 파울러Chad Fowler는 저서 『열정적인 프로그래머』에서 그저 실망시키지 않기 위해 말하는 ‘네’는 거짓말에 지나지 않는다고 했다. 그냥 거짓말이 아니라 중독적이고 파괴적인 습관이다. 양의 탈을 쓴 나쁜 습관이다."

"관리자는 팀의 한 부분이다. 관리자도 팀과 동고동락해야 한다. 팀원 모두가 야근을 한다면 관리자도 야근을 해야 한다. .... 그렇게 하면 팀원 모두가 같은 배를 탔다는 공동체 의식이 강화되고 프로젝트의 고통과 희열을 함께 느낄 수 있다. 무엇이 되었든 성과를 낼 수 있는 것에 몰입하는 분위기가 조성된다. 좋은 관리자는 외부의 압력으로부터 개발자를 보호하고 팀이 가진 장애요소들을 제거한다."

아무도 참여하려 하지 않는다면
  무언가에 관심을 갖도록 사람들의 행동을 변화시키기는 어려운 일이다. 불가능하다고 말하는 사람들도 있다. 당신의 열정과 책에서 얻은 지식으로 조직 전체를 바꿀 생각이라면 그냥 잊는 게 좋다. 그런 일은 일어나지 않는다. 몇몇 사람들로 하여금 개발자로서의 자부심과 즐거움, 열정을 되찾도록 돕는 것은 가능하다.

모범을 보여 사람들을 이끌라
  기술적 변화를 추진할 때, 특히 TDD 처럼 태도에 대한 변화까지 필요로 하다면, 직접 보여 주면서 따라하게 하는 것이 가장 좋은 방법이다. "


대략적인 목차는 다음과 같다.

1부 이념과 태도

1장 21세기의 소프트웨어 개발
2장 애자일
3장 소프트웨어 장인정신
4장 소프트웨어 장인의 태도
5장 영웅, 선의 그리고 프로페셔널리즘
6장 동작하는 소프트웨어
7장 기술적 실행 관례
8장 길고 긴 여정


2부 완전한 전환

9장 인재 채용
10장 소프트웨어 장인 면접하기
11장 잘못된 면접 방식
12장 낮은 사기의 대가
13장 배움의 문화
14장 기술적 변화의 실행
15장 실용주의 장인정신
16장 소프트웨어 장인으로서의 커리어

부록 소프트웨어 장인정신에 대한 오해와 설명


리디북스에서 자세히 보기 : http://ridibooks.com/v2/Detail?id=754016528

2015년 2월 5일 목요일

도와주세요 팀장이 됐어요 : 소설로 배우는 프로젝트 관리

도와주세요 팀장이 됐어요 : 소설로 배우는 프로젝트 관리
신승환 저 | 위키북스
http://www.yes24.com/24/Goods/2999953?Acode=101



제목이 좀 별로라 안보다가 도서관 둘러보다 있어서 보게 되었는데 생각보다 괜찮다.

책의 구성이 크게 두챕터로 나눠져 있다.
첫 챕터가 한 프로젝트 팀의 이야기를 담고 있는데 각 상황별로 프로젝트 관리 기법을 풀어서 보여준다. 그리고 다음 챕터에서는 소설에서 나온 프로젝트 관리 기법을 좀더 풀어서 저자의 견해와 다른 참고 자료들로 설명을 하고 있다.

쉽게 읽히고 공감이 가는 부분이 많아서 퇴근할 때 보자마자 바로 다 읽어버린 책이고 책의 양이라 부담이 가지 않고 내용도 괜찮다. 또한 이 책을 보며 톰 드마르코의 '데드라인'이 떠오르기도 했다. 톰 드마르코의 책은 소설을 보여주며 인사이트를 주는 것에 비해 이 책은 실제 상황에서 관리 기법을 콕콕 찍어주고 나중에 정리해주기 때문에 적용하는데 더 도움이 되는 것 같다.

나오는 내용 중에 "관리는 일종의 기술(art)입니다."라는게 가장 인상 깊었고
아래는 책보면서 인상 깊은 내용들을 메모한 것임.

- 양날의 검 '왜?'
 : 도요다에는 왜라는 질문을 다섯번 반복하는 습관이 있다. 이는 근본원인을 찾을 때 사용하는 강력한 방법이다. 대증요법에 머무르지 않고 근본원인을 찾을 수 있다.
하지만 '왜?'에는 비난의 뜻이 쉽게 포함될 수 있으므로 도요다식 문화가 자리잡지 않은 팀이라면 가급적 관계를 악화시키는 '왜'라는 질문은 삼가하는 것이 좋다.

- 시너지 효과와 책임감 나눔이 존재하는 팀
 : 팀은
. 일반적으로 작다. 즉, 다섯 명에서 열 명의 구성원으로 이뤄진다.
. 공동의 목적이나 목표가 있다.
. 일 처리 시 서로 합의 접근 방식이 있다.
. 서로 보완하는 능력이 있다.
. 상호 관련되거나 서로 독립적인 임시 목표가 있다.
. 서로에게 넘겨줄 작업을 약속한다.
 "실천가를 위한 실용주의 프로젝트 관리" 에서

팀원들의 공통의 목표를 향해 나아가기 위해 서로의 능력을 최대한 끌어내는 것이 '시너지 효과'이고 '책임감 나눔'은 팀원들이 가진 역량에 맞도록 전체 일을 작은 조각으로 나누어 팀원에게 책임감을 분배해주는 것임.

- 팀장의 리더십
 : 팀장의 한 약속이 한두 번 지켜져서 두터운 신뢰가 쌓이면 이 팀에는 열정과 신뢰가 넘침. 반면 팀장이 내뱉는 공허한 약속은 팀원들의 사기를 저하시키고 얼마 안되는 똑똑한 팀원을 멀리 떠나 보냄.

- 3 Sight (Foresight, Insight, Hindsight)
 : 예지력, 통창력, 회고력.
  계획이 틀어지더라도 그것은 배움의 시작임. 실패의 원인을 발견하고 새롭게 배우고 계획을 수정하고 이런 경험을 정리하는 것이 필요.

- 정보방 열기
 : 팀원들과 상사에게 항상 정보를 공유할 수 있는 정보방?상황판?이 필요함.
   스크럼 방법론을 사용하면서 느낀건데 직접 손으로 쓰고 붙이고 하는 것이 프로그램을 사용해서 관리하는 것 보다 효과가 더 좋다. 팀원에게나 상사에게나

- 0.5 MM의 문제점
 : 프로젝트 계획에서 쉽게 0.5MM을 계획 수행할 수 있을 것이라고 생각하지만 1. 소프트웨어 일의 범위(작업량)가 정확하기 않다는 것과 2. context switching의 비용이 비싸다는 측면에서 손해다.

- 팀장이 바쁘면 망한다.
 : 일손이 모자랄 때 팀장이 프로그램을 짜야할까? 라는 물음에 정답은 상황마다 다름. 어쩔 수 없이 일손이 모자라 팀장이 프로그램을 작성할 때는 프로그래머로서 임하기 전에 관리자 역할에 충실했는지 스스로에게 물어봐야 함.

- 팀장과 팀원이 충돌할 때
 : 상황에 따라 다르지만
   팀장이 강압적으로 시키면 팀원은 지시를 따르지만 속으로는 자신이 맞다라는 생각과 팀장에 대한 불신이 생길 수 있음. 반대로 팀장이 팀원에게 양보하면 자발적이고 생명력이 넘치는 팀을 위하는 것이고 팀원이 틀려서 실패하더라도 서로가 배우는 상황이 되는 것이고 성공하면 팀원을 지지한 팀장이 되는 것임. 단 실패 시 비난하지 말자.

- 멜빈 콘웨이(Melvin Conway)의 법칙
 : 시스템을 설계하는 조직들은 자신들의 조직 사이에 의사소통 구조(communication structure)를 모방한 형태의 설계를 만들곤 한다.

2014년 11월 23일 일요일

답을 내는 조직, 방법이 없는 것이 아니라 생각이 없는 것이다


답을 내는 조직 : 방법이 없는 것이 아니라 생각이 없는 것이다
김성호 저 | 쌤앤파커스 (읽고 보니 쌤앤파커스
http://news.khan.co.kr/kh_news/khan_art_view.html?artid=201409172149355&code=940202 )

http://www.yes24.com/24/goods/7960047?scode=029



도서관에 있길래 빌려 봤음.
서점 순위에 스테디셀러로 올라와 있기도 했었고.. 일본전산 이야기의 저자 이기도 해서 이다.
사실 일본전산 이야기는 보진 못했다. 몇몇 사람들이 특이한 회사라고 말하며 이야기를 했었지만 그냥 좀 색다른 회사의 이야기로만 들렸었다.

암튼, 제목에서 보다시피 좀 과격한 문구("너가 생각이 없는거야" 라고 들리는)가 눈길을 끈다.
나이가 조금씩 들며 조직에서 뭔가 정체되어 가고 발전이 더뎌지는 잉여 취급이라 더욱 저 문구가 대여를 하게 만든 이유가 아닌가 생각 되기도 한다.


책에서는 내내 뛰어남 보다는 근성을 가지고 끝장을 보라는 얘기를 자주 한다. 조직 내에서도 4가지 분류의 특성을 가진 사람들이 존재 하는데 그 중에서 해결사형의 타입이 성공을 하게 된다는 이야기다.

"내가 분명히 지시했는데도 대충 해놓고 다 했다고 손 놓는 부하 직원이 있다. 일을 할수록 오히려 방해만 된다."
"시키지 않으면 꼼짝도 안 하는 삼류직원 때문에 골치 아프다."

예로 책에서 후지 필름 이야기가 나온다.
난 후지필름이 워낙 잘 나가는 것 처럼 보여 문제가 없었던 것 같았는데 책에서는 주력인 필름 산업이 급격히 축소되어 이를 해결하고자 구조조정, 비용 절감을 바탕으로 하여 끊임없는 노력을 통해 화장품과 의약품 쪽으로 신규산업을 확장해서 위기를 벗어났다는 이야기를 해준다. 그리고 책에서는 성공에 안주해 늦게 대응했던 코닥에 비해 악착같이 달려 들어서 발전하려는 몸부림이 후지필름에 있었다는 것을 강조하며 근성의 필요성을 말해 주었다.


책에서는 조직 구성원의 4가지 유형을 '평론가형', '무기력형', '막무가내형', '해결사형'을 언급하고 있다. 이 유형들을 보며 좀 반성한 것이 배우겠다는 의지가 없고 소통할 기회를 만들지 않고 무슨일에든지 겁부터 내고 자기 생각이 아니라 '안 된다'는 남들 이야기에 의존하는 것이 무기력형인데.. 꼭 나를 말하는 것 같았다.

또한 책 중반부에서 "진정한 답을 나올 때 까지 고민하고 남들과 싸워라"라고 하는데 실제 얼굴 붉히며 싸우라는 것이 아니라 남들과 논쟁을 해서 제대로 된 해법을 찾으라는 것을 강조하고 있다. 실제 나의 경우 책에서 말하는 bad case 직원인 '좋은 게 좋은 거지'라고 생각하며 싸움을 피하는 경향이 있는데 '제대로 논쟁을 즐길 줄 아는 직원'이 되고자 노력해야 겠다는 생각을 곰곰히 하게 되었다.


교육의 중요성을 말하며 두산그룹의 "사람이 성장하고 사업이 성장한다.", 조선시대 거상 임상옥의 "장사는 이문을 남기는 것이 아니라 사람을 남기는 것" 언급 하는데 진정으로 맞는 말인것 같다. 회사나 조직 입장에서 인력들의 성장을 위한 방법, 시간을 제공하는 것이 필수 인것 같다.


책 후반부에서 답을 찾는 5단계를 말하고 있다.
1. 일을 제대로 이해하기
2. 문제가 보이도록 자신을 두기
3. 답을 생각하는 시간 갖기
4. 답을 찾아 시행착오 건너기
5. 논쟁으로 답을 완성하기

각 단계에 동의 하며 그중 내가 생각하기에 가장 못하는 것은 5번인데 책에서는 나같이 "동료들끼리 목소리 높이느니 내가 조금 양보하겠다"며 논쟁에서 물러서는 사람을 '문제적 직원'으로 말하고 있다. 논쟁을 통해서 최고의 대안을 찾을 기회를 아예 차단해 버린다는 이유를 들고 있다.


조직에서 좀 정체된 상태에서 매사에 한걸음 물러나 방관자적인 시점에서 일을 하고 최선의 답을 찾기보다 쉽고 간단히 처리할수 있는 방법을 찾아하는 나에게는 도전을 주고 다시금 성장할 수 있도록 해주는 책같아서 개인적으로는 두고 보고 싶은 책이다.



2014년 10월 22일 수요일

폴리글랏 프로그래밍(POLYGLOT PROGRAMMING)

폴리글랏 프로그래밍 : 새로운 자바 언어를 기다리는 히치하이커를 위한 안내서
임백준 저 | 한빛미디어

http://www.yes24.com/24/Goods/12204890?Acode=101


처음엔 책의 부제 "새로운 자바 언어를 기다리는 히치하이커를 위한 안내서"에서 보다시피
자바 얘기만 나오는 책이라 전혀 자바 쟁이가 아닌 나에겐 별 의미 없는 책이라고 생각했었음.

하지만 저자가 임백준님이시고 기존 책들도 재미있게 봤던 지라 서점에서 읽다가 구매하게 되었고 그리고 스칼라에 대한 얘기도 나와서 무엇인지 궁금하기도 했었다.

읽다 보니 폴리글랏 프로그래밍(polyglot programming)의 개념과 시작점, 자바 언어의 역사, 이를 기반으로 한 새로운 언어들의 탄생, 언어별 비교 및 고찰, 앞으로 발전될 방향에 대해서 말하고 있어 한번에 쭉 읽어 버렸었다.
아마도 책이 읽기 쉬운 역사의 흐름이나 간략한 예시를 통한 언어 소개로 구성이 되어 있고 책의 챕터도 1. 자바, 2. C#, 3. 스칼라 딱 세개인것도 이유이지 않을까 생각한다.

읽다가 인상 깊었던 부분은 기존 언어들이 새로운 feature를 추가해가며 좀더 편한 언어 사용을 돕는 모습에서도 역시 언어라는 것은 언제나 변화해 가야 하는 것이고 개발 용이성? 측면도 무시 못할 것이구나 라는 점이었다.

또한 책을 읽으면서 공감이 되는게 프로그래머라면 기본으로 자료구조와 알고리즘의 이해를 바탕으로 여러 언어에 능숙해야 하겠다라는 생각과 또한 여러 언어를 배우고 사용하다보면 자연스럽게 개발하기 편한 언어를 바라보게 된다는 점이다.

실제 컴파일러 기반 언어를 주로 사용하여 실제 스크립트언어를 쉽게 봤다가 실제 개발 용이성과 퍼포먼스 측면에서 깜놀했던 적이 있어 지금은 생각을 많이 바꾸게 되었고 함께 되도록이면 스크립트 언어를 더 배우고 깊게 알고자 하고 있기도 하다.

.... 공부할 것은 언제나 산더미구나...

2014년 5월 12일 월요일

애자일 회고 : 최고의 팀을 만드는 애자일 기법

애자일 회고 : 최고의 팀을 만드는 애자일 기법
에스더 더비,다이애나 라센 공저/김경수 역 | 인사이트(insight) | 원제 : Agile Retrospectives :Making Good Teams Great
: http://www.yes24.com/24/goods/2813260?scode=032&OzSrank=1


애자일의 '애'자도 모르는 상태에서 이것저것 방법만 하다보니 회고에 대해서 많이 궁금했었음.
단지 스프린트 회고나 릴리즈, 프로젝트 회고에서는 그냥 별 느낌없이 시간만 보낸 듯 했고 관련 참고 글도 없었기에 도서관에서 인사이트의 애자일시리즈를 보자마자 골라서 보게 되었다.

김창준 님의 글(http://agile.egloos.com/4122099)에서도 나와 있듯이 회고의 다양한 방법에 대해서 소개하고 있고 개인적으로도 회고의 목적, 절차 방법들이 잘 정리되어 있어 좋았다.

개인적으로 소장하며 두고 보면 좋을 것 같은 정도로 괜찮은 방법들이 많았음.
아래는 책 보면서 동감하거나 느낀 점에 대해서 대충 적음.

- 다나가 진행한 회고의 구조는 다음과 같다.
1. 사전 준비를 한다.
2. 자료를 모은다.
3. 통찰을 이끌어 낸다.
4. 무엇을 할 지 결정한다.
5. 회고를 마무리한다.


... 그러니 절대로 사전 준비 단계를 건너뀌거나 시간을 줄이지 않기 바란다.

=> 사전 준비를 소흘히 했던것 같다. 단지 현황 정도만 있었고 Feeling, Finding에 대해서는 거의 생각하지 않았던 것 같다..


- 두 시간짜리 회고를 어떤 식을 진행하는지 알아보자.

. 사전 준비를 한다. 5%  6분
. 자료를 모은다. 30-50% 40분
. 통찰을 이끌어낸다. 20-30% 25분
. 무엇을 할지 결정한다. 15-20% 20분
. 회고를 끝낸다. 10% 12분
. 여유 시간 10-15% 17분

=> 일반적으로 한나절을 할 때가 많았던것 같다. 회고에서 다음 스프린트 백로그 도출까지 했으니..

- 활동은 다음과 같은 장점이 있다.
. 동등한 참여를 독려한다.
. 대화에 집중한다.
. 새로운 괌점을 장려한다.
 > 회고에서 유용하게 사용하는 활동으로는 브레인스토밍(Brainstorming), 점 투표(Voting with Dots), 체크인(Check-Ins), 짝 인터뷰(Pair Interviews)등이 있다.
=> 점 투표와 짝 인터뷰.. 팀원이 적당하면 재미있을 것 같다.

- 회고 진행자인 여러분이 가장 큰 책임을 느껴야 할 부분은 내용이 아니라 프로세스다. 프로세스라고 해서 뭔가 어려운 방법론을 이야기하는 것은 아니다. 여기서 말하는 프로세스는 수행할 활동을 꾸리고 집단역학(group dynamics)과 시간을 관리하는 것을 의미한다.
=> 아하! 집단역학 공부해야지..

(TODO) 집단역학 찾아보기..

- 그후 나도 회고를 진행할 때 체크인 활동을 수행했는데 크게 두가지 이점이 있었다. 분위기가 부드러워지는 것과 현재 사람들이 느끼는 감정을 알게 되어 회고를 어떻게 진행해야 할지 감을 잡을 수 있다는 점이다.
=> 나같은 진지남에게는.. 회의 진행 시 꼭 필요할 듯. 1. 질문 제시, 각자 대답, 2. 평가 덧붙이지 않기

- 브레인 스토밍 지침
. 많은 양을 얻으려 노력하라. 최고의 아이디어가 처음부터 나오는 경우는 거의 없다.
. 바보 같은지 아닌지 재단하지 말고 모든 아이디어를 내라.
. 터무니없고, 웃기고, 거칠고, 창의적이 되어라.
. 다른 사람들의 아이디어에 살을 붙여라.
. 판단하거나, 평가하거나, 비판하지 않는다. 거르는 것은 나중에 한다.
. 아이디어를 눈에 보이도록 기록하자.
=> 다아는 것 같으면서도 항상 잊어버리는...

나머지 괜찮은 방법들은 꽤 많아서.. 책 사서 두고 두고 볼것임...

2014년 4월 1일 화요일

프로그래머 그 다음 이야기

프로그래머 그 다음 이야기
임백준, 오병곤, 이춘식, 이주연, 박재성, 신재용 | 로드북

http://www.yes24.com/24/goods/5354328?scode=032&OzSrank=1



회사 도서관에서 책을 둘러보다 보게 눈에 띄어 된 책이다.
이 출판사 책 중 프로그래머 관련 책을 읽다가 이 책이 언급된 기억과
저자로 나오는 분들이 꽤나 유명하신 분들이시라 궁금해서 선택함.

책 뒷 표지에 나와 있듯이 "프로그래머 평균 정년 35세 당신은 무엇을 하고 계십니까?"
프로그래머라면 누구나 30-40대 사이에 고민을 할 때 이고 나 또한 마찬가지인 상황에서 갈길이 보이지 않고 되돌아본 나의 경력이 보잘 것 없는지라 남다른 의미로 다가온다.

글 중 이춘식님의 글이 와 닫는 내용이 많고 나 같은 경우 신앙을 가지고 있는지라 더욱 좋았음.
그외 재미 있는 것은 프로그래머로서 실무에서 멀어지고 나이가 들어 관리 보직을 맡게 될 경우 일반적인 목표가 자격증(기술사, 퍼실리테이터 등) 인가 라는 생각이 든다.. 저자중 3분이 기술사 합격 하신 지라..

암튼... 일단 보면서 나에게 중요하다고 생각한 것들을 대충 정리함.


임백준 - 시니어 프로그래머, 행복한 프로그래밍

나는 후배 프로그래머들에게 생존과 기술에 대해서 고민하기 이전에 우선 "프로그래밍을 진심으로 사랑할 것"을 당부하고 싶다. 지금까지 나를 여기까지 밀어온 것은 다른 무엇이 아니라 바로 프로그래밍을 통해서 얻게 되는 행복과 성취감이었기 때문이다.
=> 동감하며 나에게 다시 되묻는다.. 입사 초기의 그 열정은 어디로 갔는지?

새로운 장소에서 만나게 된 프로그래머 중에는 솔직히 말해서 내가 따라가기 어려울 정도로 높은 실력을 갖춘 프로그래머가 몇 명 있었다. 그것은 나에게 건강한 의미에서의 도전이었지만, ... 그런 깊은 충격을 나에게 전해주기도 했다.
=> 사실 나도 동일 조직에서 한가지 업무를 오랫동안 해왔던 터라 우물안 개구리 같았다.. 지금에서야 밖으로 기어나오려고 하지만 너무 늦은 듯한 생각에 후회 막급이다.


오병곤 - 제2의 인생, 컨설턴트의 길

개발자에게 요구되는 역량이 논리력과 창의적 사고라면 PM은 종합적인 관리 능력과 함께 리더십 역량이 요구되는 직무다. 그래서 어느 정도 연수가 차면 누구나 PM이 되는 것은 위험하다.
: 그래 PM는 개나 소나 되는 게 아니다..


이춘식 - 데이터아키텍트의 마스터로 살련다.

보고서 작성 방법
: 일반적인 처음 도입으로 시작해서 '승'-'전' 에서 peak를 두는 것 보다.
처음 문제점을 강렬하게 제시하여 '기', '승'-'전' 에서 peak를 두고 '결'에서 살짝 impact를 주는 것이 보고서를 보는 사람들의 흥미를 끌게 된다.

수확체증의 법칙 (Increasing Returns of Scale)
: 수확체증의 법칙이란 투입된 생산요소가 늘어나면 늘어날수록 산출량이 기하급수적으로 증가하는 현상을 말한다.
사람이기 때문에 잠재력이 있고 또한 다양한 경험을 통해 수집된 정보가 집약되어 일정한 수준을 넘어서면 이전에 증가하였던 상태보다 엄청난 속도로 그 성과 등이 나타난다는 것이다.
=> 학습에 대한 메모를 보여주며 이를 설명하고 있고 동감하는 부분이다. 공부나 경험이라는 것을 통해서 효과가 바로 나오는 것이 아니라 어느정도 밑받침이 되어야 효과가 나오는 것이라..

능력있는 리더
: 비전이 있으며 긍적적인 사고로 즐겁게 일하면서 강한 실행력을 발휘할 수 있으면 능력있는 리더

1. Goal - 일의 목표는 분명한가?
2. Value & Performance - 일에 가치가 부여되고 있고 일의 성과를 내고 있는가?
3. Communication - 다양한 성격의 사람과 대화를 잘할 수 있는가? 협상의 기술이 있는가?
4. Presentation Skill - 프리젠테이션 스킬이 우수한가?
5. Document Skill - 기획 문서를 쉽고 빠르게 작성할 수 있는가?
6. Time Management - 시간 관리를 하고 있는가?
7. Insight - 변화와 개선점을 파악할 수 있고 제시할 수 있는가?


진정한 일의 측정은 성과와 품질로 가능하다. 그 사람이 얼마나 많은 일을 했느냐에 초점을 맞추지 말고 그 사람이 무슨 일을 성취했느냐? 그리고 그 일이 가치 있는지 품질은 우수한지를 보아야 할 것이다.


대화의 기술도 여러 가지 전문적인 방법이 많이 있지만, 상대방의 이야기를 경청하고 핵심을 파악한 다음 다시 나의 의견을 논리적으로 이야기하는 것이 핵심이다.
... 효율적인 대화를 이끌기 위해서는 상황에 적합한 적절한 유머 감각이 아주 중요한 것 같다. 보통 회사에서 여러 사람이 대화하는 자리는 주제에 대해서만 집중 하다 보니 사람들의 표정도 쉽게 굳어지고 사무적인 대화만 오가면서 가벼운 내용도 심각하게 이야기되고 따라서 의사결정도 어려워지며 시간이 많이 소요되곤한다.
=> 나도 배워야할 것 중 하나.... 하지만 유머를 책으로 배울 수는 없으니..

직장 생활의 라이프 사이클
1기 - 시작/성장기 - Low Performer, Low Cost - 0~4년차, 사원
2기 - 발전기          - High Performer, Low Cost - 5-10년차, 대리, 과장
                                  . 인건비 대비 효과 좋은 시기
3기 - 유지기          - High Performer, High Cost - 11-16년차, 과장, 차장
                                  . 일은 잘하나 몸값이 올라가 서서히 기피함.
4기 - 준비기          - Middle performer, High Cost - 17년차 ~ 퇴임
                                  . 일에 대한 관록은 우수하나 노골적인 기피 대상


2014년 2월 21일 금요일

코딩 호러가 들려주는 진짜 소프트웨어 개발 이야기


코딩 호러가 들려주는 진짜 소프트웨어 개발 이야기 : 엉터리 개발자에서 벗어나 진정한 개발자로 거듭나라! 제프 앳우드 저/임백준 역 | 위키북스 | 원제 : How to Stop Sucking and Be Awesome Instead (Hyperink)

이전 코딩 호러의 이펙티브 프로그래밍(http://imhallower.blog.me/90178246899)을 읽고
재미있는 충고들이 많아서 다음 책도 보게 되었음.
비록 오래된 블로그글들을 모아서 책으로 정리한 것이겠지만 나같이 귀찮은 사람들에게는 한꺼번에 몰아서 보기에 도움이 된다.

주요 chapter는 다음과 같다. 
1부 쓸데없는 일을 줄이는 법
2부 프로그래밍
3부 웹 디자인의 원칙
4부 테스트
5부 당신의 사용자를 알라

6부 우리가 관심을 둬야 할 것들
7부 게이밍

8불 읽어볼 만한 내용

보시다시피 책의 부제는 "엉터리 개발자에서 벗어나 진정한 개발자로 거듭나라" 이고 관련된 내용을 정리하였지만
전 책에 비해 각 챕터별 주제와 글들이 좀 탄탄하지 못하고 걸러낸 글들을 모아서 주제를 이래저래 맞춘것 같다.
내용면에서는 좀 실망이다. 3,4,5 챕터는 그냥 감흥없이 읽어 버렸다. 다만 마지막 챕터는 흥미를 끌었음.
아래에서 관심 글들을 정리하니 reference하는 책들이나 article이 어마어마하다....

아래는 읽으면서 개인적으로 해당되거나 동감이 가는 충고들을 정리한 내용과 개인 의견이다.

1부 쓸데없는 일을 줄이는 법

당신이 매일 아침 일어날 때, 신이 제작한 완벽하게 독창적인 장치인 유기적인 두뇌를 이용해 그날 해야 할 가장 중요한 일 세 가지를 떠올릴 수 없다면 그 상황을 진지하게 개선할 필요가 있다.
당신에게 중요한 일이 무엇이고, 무엇이 당신에게 동기를 부여하는지 알아내야 한다는 말이다.
=> 회사에서 뭘 할지 몰라 그냥 무의미하게 흘려 버리는 시간이 있다. 나도 회사도 손해이다....

나는 해마다 '버밍험 감옥으로부터의 편지(Letter from a Birmingham Jail)를 다시 읽는다. 그것이 가장 설득력 있는 에세이라고 생각하기 때문이다.... 당장 읽어보라.
(TODO) => 한번 읽어보자.
때로는 프로젝트 자체가 성공을 거두더라도 당신은 실패하게 되는 경우가 있다. ... 여기에 참여했던 엔지니어들이 모두 궁극적으로 실패를 넘어 생존했을뿐더러 이후에 더 엄청난 성공을 향해 나아가기도 했다는 점이다.... 실패는 놀라운 선생님이다.

당신보다 재능이 있는 개발자가 수천 명 있다는 사실에 기죽지 말라. 당신에게 열정이 있는 데 재능이 무슨 필요란 말인가?
=> 감사하게도 희망을 주는 말이다. 하지만 열정이 그냥 열심은 아니겠지..

- 연습하라, 연습하라, 연습하라!
- 경험과 전문성을 혼동하지 말라.
- 민간풍습을 믿지 말라. 하지만 그것을 배우기는 해라.
- 아무것도 절대적으로 믿지 말라. 자신만의 방법론을 세워야 한다.
- 자가 학습을 주도하라. 아무도 대신 해주지 않는다.
- 명성 = 돈. 스스로의 명성을 구축하고 보호하라.
- 자원, 자료, 도구를 끊임없이 확보하라.
- 자신민의 기준과 도덕률을 확립하라.
- 장인적 기술을 사소한 것으로 만드는 자격증을 피하라.
- 항상 노력하는 동료를 곁에 둬라.
- 쓰고, 말하고, 항상 자신이 보기에 진실인 것만을 발언하라.

(TODO) => 꼭 기억하자.
(TODO) => 읽어보자. 자격증 관련

"실천가를 위한 실용주의 프로젝트 관리: 위대한 관리의 비밀(Behind Closed Doors: Secrets of Great Management)"
(TODO) => 읽어보기, 현재 절판임.

이 소프트웨어 개발자는 자기가 해야 하는 일의 전체 목록을 가지고 있지 않다. 즉, 당당하게 99퍼센트의 일이 완성됐다고 주장하고 있기는 하지만 앞으로 남은 일에 얼마나 더 많은 시간을 쏟아 부어야 할지에 대해서는 전혀 모르고 있다!

=> 저자는 할일을 자세히 나열해 보라라고 말하고 있음.. 하긴 나도 개발 결과를 말할때 대충 다 끝나다고 말을 하지만 이것저것 손볼게 남아 있는게 사실이다. 대략적으로 생각해서 결과를 말하곤 하는데 정량적인 방법을 쓰던 다른 방법을 쓰던 자세히 따져 볼 수 있는 방법을 터득하는게 맞겠다.

Roger Session의 "엔터프라이즈 아키텍처를 향한 더 나은 길(A Better Path to Enterprise Architecture)"




2부 프로그래밍
프로그래밍: 사랑하지 않으면 떠나라.
지난 20여 년 동안 나는 돈을 받으면서 프로그래밍할 자격이 없는 것처럼 보이는 사람들과 일한 경험이 아주 많다. 나는 평균적인 수준의 프로그래머를 말하고 있는 것이다. 우리는 모두 인간이고, 그래서 많은 실수를 범한다.
=> 연차가 좀 되니 자존심을 내려 놓고 끊임없이 배우는 자세가 필요하다..... 하지만 자존심을 내려 놓는 것은 어려운 건 사실이다.

많은 사람들이 자기가 쓴 글에 '낙타는 혹이 두개다 The camel has two humps"라는 학술 논문에 대한 링크를 달고 있다.
(TODO) => 읽어 보자.

최근에 스티븐 예그 Steve Yegge의 방대한 글들을 뒤적이다가, 2005년에 작성된 프로그래밍 훈련하기 Practicing programming라는 글을 읽게 됐다.
(TODO) => 읽어 보자.

코드카타(노력이 담긴 학습을 실천하고 프로그래밍 기술을 연마하는 방법에 해당되는)의 예를 보고 싶다면 스티브가 쓴 글은 탁월한 출발점을 제공한다. 스티브는 그것을 실전 훈련 practice drills 이라고 불렀다.
(TODO) => 위 링크에서 항목들을 반복 읽기

칼 위거스 Karl Wiegers가 쓴 탁월한 책인 "소프트웨어에서의 동료 간 검토: 실전가이드 Peer Review in Software: A Practical Guide"는 2002년 이래로 훌륭한 가이드 역할을 수행해 왔다.
(TODO) => 읽고 정리하기


3부 웹 디자인의 원칙
소프트웨어 프로젝트의 사용성과 관련해서 입문자들을 위한 '물을 끓이는 방법' 수준의 쉬운 글을 읽고 싶다면 이 책을 읽는 것을 중단하고 지금 당장 "스티브 크룩의 사용성 평가, 이렇게 하라! Rocket Surgery Made Easy: The Do-It-Yourself Guide to Finding and Fixing Usability Proglems"를 구입해서 읽어보기 바란다.
(TODO) => 빌려서 읽어라.

조엘 스폴스키는 자신의 탁월한 책인 "프로그래머를 위한 사용자 인터페이스 디자인 User Interface Design from Programming"에서 사용성과 학습용이성의 차이를 설명했다.
(TODO) => 읽기

. 그냥 '아니오'라고 말하라.
이런 식의 경험을 하고 나서 많은 소프트웨어 개발자들이 그냥 '아니오'라고 말하라는 원칙을 내면화하게 된다는 생각을 하게 됐다. 양극단의 생각은 모두 위험하다. 하지만 나는 모든 것에 '예'라고 말하라는 원칙이 프로젝트 전체를 실패하게 하는 데 더 큰 위험성을 안고 있다고 생각한다. 둘중에서 어느 한 쪽을 선택해야 한다면 단순함을 추구하는 쪽에 서는 것이 좋다.

5부 사용자를 이해하라

. 개발자에게 UI를 만들게 했을 때 일어나는 일
모든 소프트웨어 개발자의 내면 깊숙한 곳에는 커밍아웃을 기다리는 그래픽 디자이너가 한 명씩 살고 있다. 그 디자이너가 바깥세상으로 나오게 한다면 심각한 문제가 발생한다.
=> 동감이다.. ㅜㅜ , UX, UI, GUI는 디자이너들에게..

게임화 gamification라고도 할 수 있는 이런 방법, 즉 동료를 통한 자극은 정말로 효과가 있다. 하지만 이러한 시스템은 총기류와 같다. 너무나 강력한 힘을 지니고 있어서 그것을 다루는 사람이 방법을 제대로 알고 있지 않으면 위험할 수 있는 것이다.
=> Gamification은 부가적인 기능으로는 매력적이다. 이 책 참고 (http://charlie0301.blogspot.kr/2014/02/gamification.html)

. 반사회적인 사람들을 위한 사회적 소프트웨어 만들기
열 개의 '무시무시한 아이디어', 우리는 이러한 아이디어를 스택 오버플로우를 만들 때 기본요소로 활용했다.
1. 참여를 가로막는 잣대의 수준을 혁신적으로 낮춰라.
2. 사용자들을 (적어도 일부는) 신뢰하라.
3. 우리의 인생 자체가 세계에서 가장 규모가 큰 MMORPG 게임이다.
4. 나쁜 일들은 일어나기 마련이다.
5. 사랑은 금전적 동기보다 우선한다.
6. 규칙은 재미있고 사회적일 수 있다.
7. 현대의 웹사이트 디자인은 모두 게임 디자인이다.
8. 사려 깊은 게임 디자인은 지속 가능한 커뮤니티를 형성한다.
9. 커뮤니티가 항상 옳은 것은 아니다.
10. 약간의 중재는 필요하다.
=> 재미있는 아이디어들 조직에 적용하면 유연하게 만들 수 있지 않을까?


6부 우리가 관심을 둬야 할 것들

.망중립성의 중요성
망중립성은 파일 공유보다 훨씬 더 많은 것을 의미한다. 그런 면에서 팀 우 Tim Wu의 책인 "마스터 스위치: 정보 제국의 흥망과 성쇠 The Master Switch: The Rise and Fall of Information Empires"는 천재적이다.
(TODO) => 읽어 보자.


7부 게이밍

게임 프로그래밍이 이러한 초창기 시절로부터 얼마나 많이 변화했는지에 알고 싶다면 제임스 헤이그의 1997년판 전자책인 "할키온 시절: 고전 컴퓨터와 비디오 게임 프로그래머와의 인터뷰 "Halcyon Days: Interviews with Classic Computer and Video Game Programmers"를 읽어보길 바란다.
(TODO) => 읽어 보자.


8불 읽어볼 만한 내용

. 프로그래머는 책을 읽지 않지만 당신은 읽어야 한다.
=> 몹쓸 기술 서적으로 인해 책을 읽는 것을 피하게 되었지만 좋은 책들을 읽을 때는 경험이 되고 더 깊은 통찰력을 준다고 말함.. 나도 동의하는 바이다. 다만 최신 기술을 습득하기에는 부적합 하지만 단시간에 자신의 경험으로 만들고 다른 방법을 배우는 것에는 효과적이라고 생각한다. 오픈 소스 공부가 최고지만..
(TODO) => 아래 책 읽기
. 코드 컴플리트 2 
. 상식이 통하는 웹 사이트가 성공한다. Don't Make Me Think
. 피플웨어 Peopleware http://charlie0301.blogspot.kr/2014/02/blog-post.html
. 실용주의 프로그래머 Pragmatic Programmer
. 소프트웨어 공학의 사실과 오해 Facts and Fallacies of Software Engineering

앞에서 인용했던 그 사람도 자기계발서 가운데 놀랍게도 5퍼센트에 해당하는 책은 쓰레기가 아니라는 결론을 내릴 수 있었다.
권장하는 책은 "59초: 순식간에 원하는 결과를 끌어 내는 결정적 행동의 비밀"59 Seconds: Think a Little, Change a Lot"
(TODO) => 읽자.

.컴퓨터 범죄, 그 과거와 현재
개과천선한 해커 중 한 명인 케빈 폴슨 Kevin Poulson이 쓴 '킹핀'은 대단히 흥미진진한 독서 경험을 제공한다.
(TODO) => 읽자.

. 사람에게 말을 하는 방법
내가 단지 10페이지 정도만 읽고도 충격을 받을 정도로 도움되는 책이 있음을 깨닫게 된 책이 있다. 당신이 나이가 2세에서 99세 사이에 있는 아이를 다뤄야 하는 입장이라면 지금 당장 가서 "어떤 아이라도 부모의 말 한마디로 훌륭하게 키울 수 있다. How to Talk So kids Will Listen So Kids Will Talk"를 구입하기 바란다. 우리는 이미 이 책을 세 권 가지고 있다. 당신도 읽어야 한다.
(TODO) => 읽자.


. 기본기 다지기: 새루운 튜링 승합차
우리의 CEO인 스콧 스탠필드 Scott Standfield는 고전적인 컴퓨터 공학 퍼즐을 연구하다가 나를 "새로운 튜링 승합차: 66일간의 컴퓨터 공학 여행 The New Turing Omnibus: 66 Excursions in Computer Science"으로 인도 했다. 정말로 믿을 수 없을 정도로 흥미로운 책이다.
(TODO) => 재미 있겠지, 읽자.