Life/Software Engineer

James Long "나는 어떻게 더 나은 프로그래머가 되었는가"의 인상 깊은 문장들

엄청나보이는 사람도 실제로 일하는 모습을 보면 우리가 일하는 모습과 그리 다르지 않습니다.
모든 수단과 방법을 가리지 않고 작동하는 코드를 쓰려 합니다(Hacks everywhere).


매일 등장하는 대부분의 새로운 라이브러리 등은 그저 기존에 있던 같은 아이디어의 재탕입니다.
진정 혁명적인 물건은 몇 년에 한번씩 나타납니다.


해결하고자 하는 문제 및 추상화 계층에 많은 시간과 노력을 들이는게 더 낫습니다.
모든 문제가 정리되었다면 약간의 시간을 들여서 코드를 정리하는 작업을 하면 됩니다.


특정 주제를 며칠 정도 조사해보는 버릇은 언제나 문제를 해결하는 방법을 송두리째 바꿔줍니다.

논문을 읽는 방법을 배우는 것도 좋습니다.


[번역] 나는 어떻게 더 나은 프로그래머가 되었는가

Practice/GTK+, Linux

'ps aux'와 'ps -ef'의 차이

ps -eps ax를 모든 프로세스를 보여준다는 의미에서 같다.


ps -fps u는 보여주는 필드를 정하는데 아래와 같은 소소한 차이가 있다.

ps -f
프로세스의 식별 정보를 더 잘 보여준다.

  • PPID : 부모 PID

ps u
프로세스의 상태 정보를 더 잘 보여준다.

  • %CPU : CPU 사용율
  • %MEM : 메모리 사용율
  • VSZ : 가상 메모리 크기
  • RSS : 실제 메모리 크기
  • STAT : 프로세스 상태


부모 프로세스와 자식 프로세스의 관계를 보려면 ps -ef
프로세스 상태를 보는 용도로는 ps aux가 더 적당하다.

Practice/Python, Perl

Ubuntu 16.04에서 Python 3.6 사용하기

Python 3.6 설치하기

Ubuntu 16.04에는 써드파티 PPA를 추가해야 python 3.6을 설치할 수 있다.

sudo add-apt-repository ppa:jonathonf/python-3.6

Python 3.6을 설치한다.

sudo apt-get update
sudo apt-get install python3.6


Python 3.6 설치 후 gnome-terminal 외 다수 프로그램이 동작하지 않는 문제 해결하기

Ubuntu 16.04의 몇몇 프로그램은 python 2.7, python 3.5 이외의 버전에서 동작을 보장하지 않는다.
이런 이유로 python 3.6 설치 이후로 문제가 발생하는 프로그램이 나타날 수 있다.(대표적으로 gnome-terminal)
시스템이 사용하는 python 버전을 2.7이나 3.5로 지정해야 한다.

간단한 방법

사용할 python을 등록한다.

sudo rm /usr/bin/python
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.5 2
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.6 3

아래 명령으로 python2.7을 선택한다.

sudo update-alternatives --config python
There are 2 choices for the alternative python (providing /usr/bin/python).

  Selection    Path                Priority   Status
------------------------------------------------------------
  0            /usr/bin/python2.7   1         auto mode
* 1            /usr/bin/python2.7   1         manual mode
  2            /usr/bin/python3.5   2         manual mode
  3            /usr/bin/python3.6   3         manual mode

Press <enter> to keep the current choice[*], or type selection number:

python 버전 2, 3을 분리하여 해결하는 방법

python2와 python3을 각각 등록한다.

python2를 등록은 아래 명령어면 충분하다.

sudo rm /usr/bin/python2
sudo update-alternatives --install /usr/bin/python2 python2 /usr/bin/python2.7 1

python3를 등록은 아래 명령어로 등록하고 사용할 버전을 고르면 된다.

sudo rm /usr/bin/python3
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.5 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 2

아래 명령으로 원하는 버전을 선택한다.

sudo update-alternatives --config python3

python3는 목록 중에 원하는 것을 아무거나 선택해도 무방하다.

There are 2 choices for the alternative python3 (providing /usr/bin/python3).

  Selection    Path                Priority   Status
------------------------------------------------------------
  0            /usr/bin/python3.5   1         auto mode
* 1            /usr/bin/python3.5   1         manual mode
  2            /usr/bin/python3.6   2         manual mode

Press <enter> to keep the current choice[*], or type selection number:

이제 시스템의 기본 python의 환경을 구성한다.
과정은 python3 선택 과정과 유사하다.

sudo rm /usr/bin/python
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 2

시스템의 기본으로 python2를 선택한다.

sudo update-alternatives --config python
There are 2 choices for the alternative python3 (providing /usr/bin/python).

  Selection    Path                Priority   Status
------------------------------------------------------------
  0            /usr/bin/python2     1         auto mode
* 1            /usr/bin/python2     1         manual mode
  2            /usr/bin/python3     2         manual mode

Press <enter> to keep the current choice[*], or type selection number:

이렇게 시스템의 python 환경을 완료했다.


개발에 사용할 버전 선택하기

개발은 사용할 python 버젼은 virtualenv로 환경을 구축한다.

예를 들어 python 3.6을 사용한다면

python3.6 -m venv .venv

로 가상 환경을 구성한다.

가상 환경은 아래 명령으로 활성화 한다.

. .venv/bin/activate


Practice/Python, Perl

파이썬 프러퍼티 사용하여 일관되게 속성에 접근하라

파이썬의 프러퍼티(property)를 설명한 책과 글은 많음으로 필요성만 살짝 언급하고 지나가겠다.

파이썬에서는 공개 애트리뷰트(public attribute)을 직접 접근(access)하는 것이 관례이다.

class A:
    def __init__(self):
        self.x = 0

a = A()
a.x = 1
print('{}'.format(a.x))

그런데, 비공개(private) 애트리뷰트[각주:1]가 필요한 경우가 있다.
이들을 외부에서 접근하기 위해서는 엑세스 함수-즉 get_xxx(), set_xxx()와 같은 것-을 사용해야 한다.
접근 형식이 관례와 달아서 표현의 일관성이 깨지는 것이 문제이다.[각주:2]
이럴 때, 프러퍼티를 사용하면 동일한 표현 형식으로 접근이 가능하다.

class A:
    def __init__(self):
        self.x = 0
        self.__y = 0

    @property
    def y(self):
        return self.__y

    @y.setter
    def y(self, value):
        self.__y = value


a = A()
# attribute access
a.x = 1
print('{}'.format(a.x))
# property access
a.y = 2
print('{}'.format(a.y))

아래 코드처럼 엑세스 함수를 사용하면, 즉, a.x와 a.set_y()를 섞어쓰면, 더럽지 아니한가?

class A:
    def __init__(self):
        self.x = 0
        self.__y = 0

    def get_y(self):
        return self.__y

    def set_y(self, value):
        self.__y = value


a = A()
# attribute access
a.x = 1
print('{}'.format(a.x))
# getter/setter access
a.set_y(2)
print('{}'.format(a.get_y()))

매우 드물기는 하지만, 엑세스 함수의 오버라이딩(overriding)이 필요할 때가 있다.
그러한 경우, 아래 예제 코드를 참고하여 작성하도록 한다.[각주:3]

class A:
    def __init__(self):
        pass

    @property
    def x(self):
        return self.__x

    @x.setter
    def x(self, value):
        self.__x = value


class B(A):
    def __init__(self):
        super().__init__()

    @A.x.setter
    def x(self, value):
        if value < 0:
            raise ValueError('x below 0 is not possible')
        super(B, B).x.__set__(self, value)


class C(B):
    def __init__(self):
        super().__init__()

    @B.x.setter
    def x(self, value):
        if value > 100:
            raise ValueError('x above 100 is not possible')
        super(C, C).x.__set__(self, value)

데코레이션 패턴(decoration pattern)이 상속보다 더 유용할 수 있다.
예를 들면, getter에 캐싱 기능을 추가하는 경우가 그러하다.
데코레이션 패턴으로 구현하는 것은 본 글의 취지와 맞지 않아서 생략한다.


참고 링크:

  1. 관례적으로 '__'로 시작하면 비공개 애트리뷰트이다. [본문으로]
  2. 코드가 더러워진다. [본문으로]
  3. 그 동안의 실무 경험에서 깨달은 한가지 교훈. "때때로 백번의 설명보다 한번의 예제가 낫다." [본문으로]
Practice/Coding, Debugging

기본 값(default value)을 언제 사용할까?

얼마 전, 기본 매개변수(default parameter) 때문에 문제를 겪었다.
큰 규모의 리펙토링 후에 문제가 발생했다.
이 함수를 호출할 때 문제의 매개변수를 누락한 것이 원인이다.
그러나, 기본 값이 있어서 오류가 드러나지 않았고,
테스트에 사용한 값이 오류를 보여주지 못하는 값이었다.[각주:1]

위 사건 이후로 기본 값에 대해서 고민하게 되었다.

매번 값을 특정하는 것은 꽤 귀찮은 일이다.
가령, ssh 접속할 때 포트 번호 22를 항상 입력하는 것은 불편하다.
기본 값[각주:2]은 이런 불편함을 덜어준다.
이는 곧 개발의 생산성과 사용의 편의성으로 이어진다.
한편으로는, 이것이 나중에 문제가 되기도 한다.

기본 값을 사용하는 원칙을 하나 정하자.
명백하고 합리적으로 그 값을 대부분 사용하면 기본 값이 될 수 있다.

예를 들면, 일반적인 HTTP 클라이언트를 개발한다면,
HTTP 프로토콜의 기본 포트인 80을 기본 값으로 사용할 수 있다.

한편으로는, 사내 HTTP API 서버들의 포트가 다양하다면,
또는 개발 서버와 테스트 서버, 실 서버 간에 포트가 다르다면,
포트에 기본 값을 지정할 지 고민이 필요하다.

데이터베이스 테이블과 클래스 이름 간에 생성 규칙[각주:3]이 있다면,
테이블의 이름을 생략할 수 있다.
멤버 변수나 함수의 인자의 기본 값으로 클래스 명에서 도출된 테이블 이름을 사용한다.

'일단 이 값을 기본으로 하자.'와 같은 위험천만한 기본 값은 조심해야 한다.[각주:4]
당장은 개발의 생산성으로는 이어진다.
하지만, 이것은 기술 부채가 되어 자신의 발목을 잡을 것이다.
기본 값은 명백하고 합리적인 접근으로 판단해야 한다.

  1. 이 매개변수는 함수의 로직에서 중요한 것이 아니었기 때문에 크게 신경쓰지 않았다. [본문으로]
  2. 하드 코딩, 기본 매개변수 등 [본문으로]
  3. Convention over Configuration [본문으로]
  4. 문제의 탐색에서의 기본값은 괜찮다. [본문으로]

알림

이 블로그는 구글에서 제공한 크롬에 최적화 되어있고, 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

카운터

Today : 35
Yesterday : 164
Total : 218,584