Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
Tags
- 실전알고리즘
- 이것이 코딩테스트다 with 파이썬
- cs
- docker
- 프로그래머스
- 백준
- 전산기초
- 코드수행
- test-helper
- 자료구조 및 실습
- 머신러닝
- 파이썬
- 그리디
- C++
- 딥러닝
- 구현
- 3단계
- 2단계
- ssd
- MySQL
- 모두를 위한 딥러닝 강좌 시즌1
- CS231n
- pytorch
- SWEA
- Python
- AWS
- STL
- Object detection
- ubuntu
- 1단계
Archives
- Today
- Total
곰퓨타의 SW 이야기
CH1. 코드 포매팅과 도구 본문
1. 서론
- 클린 코드의 의미
- 프로그래밍 언어의 의미
- 인간의 아이디어를 컴퓨터에 전달하기 위해 사용하는 언어 (X)
- 아이디어를 다른 개발자에게 전달하는 것
- 따라서, 클린 코드는 다른 엔지니어가 코드를 읽고 유지 관리할 수 있는지 여부에 따라 달려있다.
- 클린 코드의 중요성
- 유지보수성 향상
- 일정하게 예측 가능한 속도로 민첩한 개발과 지속적인 배포 가능
- 기술 부채의 감소
- 기술 부채 : 나쁜 결정이나 적당한 타협의 결과로 생긴 소프트웨어적 결함
- 1. 현재 -> 과거의 방향 : 직면한 문제가 과거의 잘못된 코드로 생긴 건 아닐지
- 2. 현재 -> 미래 : 현재의 문제를 적절하게 해결하기 위해 시간을 투자하지 않아서 미래에 문제가 발생하는 건 아닐지
- 이자가 발생하는 부채처럼, 코드를 미래에 변경하는 것이 더 어렵다.
- 기술 부채 有 -> 애자일 방식 개발 X
- 코드 스멜이 있다면 잘못된 코드를 암시하는 신호로 명시적인 오류는 아니지만 장기적으로 코드에 나쁜 영향을 줄 수 있다.
- EX ) 함수의 파라미터로 변경 가능한 기본 값을 사용한다고 해보자.
- 결함 발견 전까지는 상당히 오랫동안 정상적으로 동작, 하지만 실제로는 프로그램을 비정상적으로 종료시키는 시한 폭탄이 될 수 있다.
- -> 철저한 코드 리뷰 & 자동화된 테스트
- 애자일 개발을 통한 효과적인 작업 진행
- 성공적인 프로젝트 관리
- 수정 가능한 코드를 만들기 위한 절대적인 요구사항
- 기술 부채 : 나쁜 결정이나 적당한 타협의 결과로 생긴 소프트웨어적 결함
- 예외 상황
- 해커톤 참여
- 일회성 작업을 위한 간단한 스크립트 작성
- 프로그래밍 경진 대회 참여
- 기존에 없던 개념을 검증하기 위해 개발하는 경우
- 나중에 버려질 것이라고 확신하는 프로토타입 개발 등
2. 클린 코드에서 코드 포매팅의 역할
PEP-8(Python Enhancement Proposal) : 가장 잘 알려진 표준이며, 띄어쓰기, 네이밍 컨벤션, 줄 길이 제한 등의 가이드 랑니 제공
하지만, 클린 코드는 PEP-8 이나 코딩 스타일 그 이상의 유지 보수성이나 소프트웨어 품질에 관한 것을 말한다.
- 프로젝트 코딩 스타일 가이드 준수
- 코딩 가이드 라인 : 품질 표준을 지키기 위해 프로젝트에서 따라야 하는 최소한의 요구사항
- 코드가 일관되게 구조화되어 있으면 가독성이 높아지고 이해하기 쉬워진다.
- PEP-8 표준
- 검색 효율성 (Searchability)
- 코드에서 원하는 부분을 빠르게 검색할 수 있도록 한다.
- 변수에 값을 할당하는 경우, 함수의 키워드 파라미터에 값을 할당하는 경우 구분 가능
- 일관성
- 더 나은 오류 처리
- try~except 블록 내부의 코드를 최소화
- 코드 품질
- 한 눈에 코드를 이해하고 버그와 실수를 쉽게 찾을 수 있다.
- 검색 효율성 (Searchability)
- PEP-8 표준 검색 효율성 예시
$ grep -nr "location="
./core.py:13:location=current_location, # keyword argument에 값을 할당하는 경우 띄어쓰기 X
$ grep -nr "location ="
./core.py:10:current_location = get_location(), # 변수에 값을 할당하는 경우 띄어쓰기 권고
포매팅은 문서화 방식이나 코드 품질 자동화 도구를 결정하는 데 영향을 많이 미친다.
3. 문서화 (Documentation)
훌륭한 코드는 그 자체로 분명하지만 문서화 또한 잘 되어 있다!
파이썬 코드를 문서화하는 방법으로는 Docstring, annotation이 있다.
파이썬은 변수의 타입이 동적이어서 변수나 객체의 값이 무엇인지 잃어버리기 쉬우므로, 타입 정보를 명시해두는 것이 좋다.
cf ) 어노테이션은 mypy, pytype과 같은 도구를 통해 변수 타입 힌트와 같은 자동화에 좋다.
코드 주석 (code comments) (a.k.a. 악마)
- 주석은 적어야 한다.
- 주석을 작성하기 전에 새로운 함수를 추가하거나 보다 나은 변수명을 사용하는 것 등의 방법을 고려해보자
- 외부 함수의 문제를 피하기 위해 특정한 파라미터를 넘겨야 하는 경우는 허용된다.
- (이름이 지정되어 있는 경우, 설명이 필요할 때를 이야기하는건가?)
- 주석 처리된 코드는 없어야 한다.
Docstring
- 소스 코드에 포함된 문서 (Documentation)
- Docstring은 리터럴 문자열이며, 로직의 일부분을 문서화하기 위해 코드 어딘가에 배치된다.
- 모듈, 클래스, 메서드 또는 함수에 대해 문서를 제공하기 위한 것
- 동작 방식과 입출력 정보 등을 확인할 수 있다.
- 프로그램 디자인과 아키텍처에 대해 문서화 유용
- EX)
- dict.update에 대해 알고 싶은 경우
Help on method_descriptor:
update(...)
D.update([E,]**F)->None. Update D from dict/iterable E and F.
If E is present and has a.keys() method, then does: for k in E : D[k] = E[k]
If E is present and lacks a.keys() method, then does: for k, v in E : D[k] = v
In either case, this is followed by: for k in F : D[k] = F[k]
(END)
-> 새로운 함수가 어떻게 동작하는지, 어떻게 활용될 수 있는지 이해하는데 중요한 역할을 할 것이다.
-
- 객체에 docstring이 정의되어 있으면 __doc__속성 (property, attribute)로 접근이 가능하다
>>> def my_function():
... """임의의 연산 수행"""
... return None
...
>>> my_function.__doc__
'임의의 연산 수행'
>>> help(my_function)
- 도구
- Sphinx: 프로젝트 문서화를 위한 골격 만들어준다.
- Autodoc 익스텐션 (sphinx.ext.autodoc)을 사용하면 코드에서 docstring을 가져와서 문서화된 페이지를 만들어준다.
- 도구 오픈을 위해 "read the docs" 와 같은 도구를 사용할 수 있다. (오픈 소스의 경우)
- Sphinx: 프로젝트 문서화를 위한 골격 만들어준다.
- 단점 : 지속적으로 수작업을 해야 한다.
어노테이션
- 코드 사용자에게 함수 인자로 어떤 값이 와야하는지 힌트를 준다
- Type hinting을 활성화한다.
- 변수의 예쌍 타입을 지정할 수 있다.
- 변수의 의도를 설명하는 문자열, 콜백이나 유효성 검사 함수로 사용할 수 있는 callable 이 있다.
- 함수.__annotations__로 활용 가능
- 유의미한 이름을 사용하거나 적절한 데이터 타입 추상화를 할 수 있도록 도와줄 수 있다.
ex ) Docstring과 어노테이션의 활용
def data_from_response(response:dict) -> dict:
"""response의 HTTP status가 200이라면 response의 payload를 반환
- response 사전의 예제::
{
"status":200, # <int>
"timestamp": ..., # 현재 시간의 ISO 포맷 문자열
"payload" : {...] # 반환하려는 사전 데이터
}
- 반환 사전 값의 예제::
{"data":{...}}
- 발생 가능한 예외:
- HTTP Status가 200이 아닌 경우 ValueError 발생
"""
if response["status"] != 200:
raise ValueError
return {"data" : response["payload"]}
4. 도구 설정
- 이 코드를 동료 개발자가 쉽게 이해하고 따라갈 수 있을까?
- 업무 도메인에 대해서 말하고 있는가?
- 팀에 새로 합류하는 사람도 쉽게 이해하고 효과적으로 작업할 수 있을까?
- 이 검사는 모두 자동화로 해야 한다. 테스트와 체크리스트가 지속적으로 통합 빌드 (Continuous Integration Build)와 하나가 되도록 해야 한다.
데이터 타입 일관성 검사
- mypy, pytype
- mypy {파일명} : 의심되는 오류 보고
- mypy와 pytype의 가장 큰 차이 : 오류를 확인하는 시점
- pytype은 일시적으로 지정된 데이터 타입과 다른 타입을 사용하여도 최종 결과가 선언된 유형을 준수하는 한 문제로 간주되지 않는다.
- 런타임 시에는 문제되지 않는 코드
from typing import List
def get_list() -> List[str]:
lst = ["PyCon"]
lst.append(2022) #mypy에서는 오류지만 pytype에서는 허용
return [str(x) for x in lst]
일반적인 코드 검증
- pycodestyle, flake8 : PEP-8 표준을 위반한 모든 라인과 에러 유형 출력
- cf ) PEP-8은 일반적인 코드의 스타일이나 구조에 관한 것을 검사할 뿐, 모든 메서드, 클래스, 모듈에 docstring을 넣도록 강제하지는 않는다. 그리고 너무 많은 파라미터를 사용하는 함수에 대해서도 아무런 불평을 하지 않는다.)
- pylint : 가장 엄격한 수준의 검증
- pylintrc 설정 파일로 개별적인 규칙에 대해 활성/비활성 여부 결정 가능
- Coala : 파이썬 뿐만 아니라 다른 언어도 지원
- 설정 파일 有, 커맨드 라인 도구 有, 에러 발생 가능성이 있는 경우 수정 가능한 코드 형식 지정
자동 포매팅
- flake8: PEP-8 준수 여부 + 코드 변환
- black : 라인 길이 제외와 같은 옵션을 허용하지 않으면서 고유하고 결정적인 방식으로 코드 형식 지정
- Ex ) 따옴표는 항상 큰 따옴표, 파라미터 순서는 항상 동일한 구조
- PEP-8 보다 엄격한 하위 집합 관리
- --check를 통해 검사 가능
- All or nothing formatting
- yapf : 사용자 정의 가능하면서 코드의 일부분만 포매팅 가능 (적용할 줄도 지정 가능)
자동 검사 설정
- 리눅스 개발 환경에서 빌드 자동화 : Makefile 사용
- Makefile : 프로젝트를 컴파일 하고 실행하기 위한 설정을 도와주는 강력한 도구
- 빌드 외에도 포매팅 검사나 코딩 컨벤션 검사를 자동화하기 위해 사용 가능
- 명령어 있을 때에는 공백이 아닌 탭으로 들여쓰기를 해야 한다.
- 테스트를 위한 각각의 target을 만들고, 이것들을 모두 실행하는 또다른 target 만들어야 한다.
.PHONY: typehint
typehint:
mypt --ignore-missing-imports src/
.PHONY: test
test:
pytest test/
.PHONY: lint
lint:
pylint src/
.PHONY: checklist
checklist: lint typehint test
.PHONY: black
black:
black -l 79 *.py
.PHONY: clean
clean:
find . -type -f -name "*.pyc" | xargs rm -fr
find . -type -d __pycache__ | xargs rm -fr
- 개발 머신과 CI 빌드에서의 실행할 커맨드
- $ make checklist
- 1. 먼저 PEP-8 이나 black의 --check 파라미터를 사용해 코딩 가이드라인을 잘 지키고 있는지 확인
- 2. 올바른 타입을 사용했는지 검사
- 3. 최종적으로 테스트 실행
--> 이 중 하나라도 실패하면 전체 프로세스 실패
- 장점
- 1. 가장 많이 사용하는 반복적인 작업을 간단하게 표준화 가능
- 2. Makefile은 프로젝트의 여러 작업을 한꺼번에 실행하는 표준화된 방법을 제공한다.
Reference
'TIL > 클린코드' 카테고리의 다른 글
CH 6. 디스크립터로 더 멋진 객체 만들기 (0) | 2023.06.26 |
---|---|
CH 5. 데코레이터를 사용한 코드 개선 (0) | 2023.05.16 |
CH 4. SOLID 원칙 (0) | 2023.05.15 |
CH 3. 좋은 코드의 일반적인 특징 (0) | 2023.05.07 |
CH 2. 파이썬스러운 코드 (0) | 2023.05.02 |