클린코드를 작성하는 방법

Sawol·2021년 6월 3일
0

I Need Python

목록 보기
10/13
post-thumbnail

❗️ 파이썬 클린코드를 읽고 정리한 글입니다.

클린 코드

프로그래밍 언어의 진정한 의미는 아이디어를 다른 개발자에게 전달하는 것.
즉, 다른 개발자가 코드를 읽고 유지보수를 할 수 있어야 클린 코드라고 말할 수 있다.
파이썬의 표준 코딩 스타일인 PEP-8을 따르는 것을 넘어 소프트웨어의 품질과 유지보수성을 의미.
기본은 일관된 코딩 스타일을 지키는 것이므로 PEP-8을 따라야함.

클린 코드의 장점

Docstring과 Annotation

좋은 코드는 문서화도 잘 되어 있어야 한다. 함수가 어떤 파라미터를 필요로 하는지 등을 기록하여야한다. 또한 파이썬은 동적 타이핑 언어이기때문에 변수나 객체의 값이 어떤 타입의 값인지 명확히 알기 힘들다. 이때 사용하는 것이 어노테이션이다.

독스트링(Dosctring)

독스트링에 대한 내용은 여기에 정리 되어있음.

어노테이션(Annotation)

코드 사용자에게 함수 인자, 함수의 반환값 등이 어떤 값이 와야하는 지 힌트를 줌.
힌트만 줄뿐이지 타입을 검사하거나 강제하지는 않음.

num: int = 1

class Point:
    lat: float
 
    def __init__(self, lat, long):
        self.lat = lat
        self.long = long
        
def locate(latitude: float, longitude: float) -> Point:
    """ 맵에서 좌표에 해당하는 객체를 검색"""

num: intnum이라는 변수는 int형을 기대한다는 것을 의미한다. 또한 locate 함수는 반환하는 값이 Point의 인스턴스라는 의미이다.
어노테이션을 생성하면 자동으로 __annotations__라는 매직 메서드가 생긴다.

>>> locate.__annotations__
{'num': int, 'latitude': float, 'longitue':float, 'return': __main__.Point}

이 정보를 통해 문서 생성이나 유효성 검증 및 타입 체크를 할 수 있다.

typing 모듈
좀 더 복잡한 어노테이션을 추가할 때 사용하는 라이브러리. 자세한 예는 여기 참고.

# 어노테이션만 사용했을 때
a: list = ['사과','딸기','바나나']
# 어노테이션과 typing 모듈을 함께 사용했을 때
import typing
a: list[str] = ['사과','딸기','바나나']

코드 품질을 향상시키는 도구

코드 포매팅, 적절한 들여쓰기 등 검사는 자동화되어야 하며 검사에 실패하면 빌드도 실패하여야 한다.

Mypy

가장 일반적으로 사용하는 정적 타입 검사 도구.
pip install mypy로 설치 가능.
mypy {파일명}을 통해 타입 검사를 한다.

num: int = 3
Success: no issues found in 1 source file

num: int = 'hi'
{파일명}:1: error: Incompatible types in assignment (expression has type "str", variable has type "int")
Found 1 error in 1 file (checked 1 source file)

가끔 잘 못 탐지를 할 수 있는데 그 경우 주석을 이용해 무시하도록 할 수 있다.
아래 예제는 잘 못 탐지한건 아니지만, 예시를 들기위해 무시하도록 함.

num: int = 'hi'		 # type: ignore
Success: no issues found in 1 source file

Pylint

코드 구조를 검사하는 도구. 코딩스타일(PEP-8) 기준으로 검사를 해줌.
pip install pylint로 설치 가능.
필요에 따라 규칙을 활성화/비활성화를 할 수 있다.
pylint {파일명}을 통해 코드 구조를 검사한다.

num: int = 'hi'     # type: ignore


class Point:
    lat: float

    def __init__(self, lat, long):
        self.lat = lat
        self.long = long
def locate(latitude: float, longitude: float) -> Point:
    """ 맵에서 좌표에 해당하는 객체를 검색"""
    pass

print(locate.__annotations__)

************* Module {파일명}
{파일명}:15:0: C0304: Final newline missing (missing-final-newline)
{파일명}:1:0: C0114: Missing module docstring (missing-module-docstring)
{파일명}:5:0: C0115: Missing class docstring (missing-class-docstring)
{파일명}:5:0: R0903: Too few public methods (0/2) (too-few-public-methods)
{파일명}:13:4: W0107: Unnecessary pass statement (unnecessary-pass)
{파일명}:11:11: W0613: Unused argument 'latitude' (unused-argument)
{파일명}:11:28: W0613: Unused argument 'longitude' (unused-argument)

-----------------------------------
Your code has been rated at 2.22/10

점수와 함께 코드 구조에 문제가 있는 줄을 알려준다. 코드를 수정하여 점수를 좀 더 올려보자.

"""
독스트링이다.
"""
num: int = 'hi'     # type: ignore


class Point:
    lat: float

    def __init__(self, lat, long):
        self.lat = lat
        self.long = long
def locate(latitude: float, longitude: float) -> Point:
    """ 맵에서 좌표에 해당하는 객체를 검색"""
    return latitude + longitude

print(locate.__annotations__)

************* Module {파일명}
{파일명}:17:0: C0304: Final newline missing (missing-final-newline)
{파일명}:7:0: C0115: Missing class docstring (missing-class-docstring)
{파일명}:7:0: R0903: Too few public methods (0/2) (too-few-public-methods)

------------------------------------------------------------------
Your code has been rated at 6.67/10 (previous run: 2.22/10, +4.44)

독스트링도 추가하고 사용하지 않던 변수도 사용을 했다. 점수가 4.44점이나 올랐다!

0개의 댓글