본문 바로가기
Language/python

[python] Clean Code in Python 1. 코드 포매팅과 도구

by _YUJIN_ 2024. 5. 1.

1. 프로그래밍 언어

  • 프로그래밍 언어를 컴파일하고 실행시키는 주체는 컴퓨터이나, 프로그램은 단 한번 실행하고 멈추는 것이 아니라 지속적으로 유지보수하고 발전해나가는 존재이다. 
  • 즉, 프로그래밍 언어는 인간의 아이디어를 다른 개발자에게 전달하는 것이다. 
  • 컴파일 (compile)? 사람이 이해하는 언어를 컴퓨터가 이해할 수 있는 언어로 바꿔주는 과정

2. 클린코드

  • 좋은 코드와 나쁜 코드를 구분할 수 있어야한다. 
  • 코드 포매팅 != 클린코드
    PEP-8과 같은 지침에 따라 코드를 포매팅하고 구조화하는 것은 클린코드의 최소요건이다.
  • 일관성 
    → PEP-8과 같은 코딩 가이드를 준수하는 것은 SW 일관성을 유지하는 것에 도움을 준다. 
    →일관성 있는 코드는 오류를 감지하기 쉬우며, 신속하게 패턴을 파악하여 개발자의 이해를 높일 수 있다. 
    → 아래의 코드 예시처럼 가이드를 지키지 않아도 얼마든지 깔끔하게 코드를 적을 수 있다. 
# PEP-8 가이드에 어긋나는 변수 선언 
# "변수 선언 시, 할당 연산자 앞/뒤에는 공백문자가 하나씩만 포함되어야 한다."
my_first_name = "lee"
my_age        = 26

따라서, 코드 포매팅은 코드를 깔끔하게 보기 위한 최소요건이지 클린코드로 볼 수는 없다. 

3. 클린코드의 중요성

  • 유지 보수 향상 
  • 기술부채 감소 
    → 기술 부채 ? 나쁜 결정이나 적당한 타협의 결과로 생긴 소프트웨어적 결함을 말한다. 
  • 애자일 개발을 통한 효과적인 작업 진행 
    → 아무런 계획이 없는 방법과 계획이 지나치게 많은 개발 방법들 사이에서 타협점을 찾고자 하는 방법론 

4. 코드 설명 방법 

  • 설명이 필요 없는 코드가 좋은 코드이지만, 본인이 사용한 코드를 이해할 때나 다른 사람이 썼던 코드를 이해해야할 때 주석이 있으면 조금 더 편리하다. 

(1) Comment 

"주석은 코드로 아이디어를 제대로 표현하지 못했음을 나타낸다." (p.24)

 

  • 주석을 업데이트하는 것을 잊는 경우가 많아서, 현재와 일치하지 않을 경우 다른 위험을 초래한다. 
  • 주석을 허용하는 경우 : 외부 라이브러리에 오류가 있을 경우 

(2) 함수와 파라미터 이름

  • 함수의 이름과 파라미터의 이름에서 충분히 설명이 가능하면 매우 좋지만, 생각보다 쉽지 않다. 

(3) Docstring (good~!)

  • docstring은 각 함수나 클래스에 추가할 수 있는 설명 문서이다. 
  • docstring은 간편하게 함수, 모듈, 클래스의 선언부 아래에 멀티라인 주석(""" """)을 붙음으로써 추가할 수 있다. 
  • Python이 동적 타이핑을 하기 때문에 파라미터 타입이나 반환 타입 체크를 강요하지 않는다. 그래서 함수명이나 파라미터명에 충분히 설명되어 있다면 이를 보완할 수는 있지만, 파이썬의 대화형 인터프리터를 통해 바로 실행하여 쉽게 알 수 있도록 docstring을 사용하는 것이 가장 번거롭지 않은 방법이다. 
  • 가장 좋은 방법은 개발자가, 프로젝트 팀원끼리 자신의 프로젝트에 맞는 dostring 가이드를 선택하는 것이다. (docstring 가이드)

< 함수 docstring 구현 >

def some_func():
    """Hello Fuction Docstring"""

 

< 클래스 docstring 구현 >

class SomeClass():
    """Hello Class Docstring"""

 

docstring에 적용되어 있는 값을 호출하고 싶다면 `.__doc__` 를 통해 호출할 수 있다. 

some_function.__doc__
SomeClass.__doc__

 

Ex. 

def sum_list(lst):
    """
    Descriotion : 
    	리스트에 있는 모든 요소를 더하는 함수 
    Param : 
    	lst 숫자로 이루어진 리스트 
    Return : 
    	리스트의 모든 요소의 합    	
    """
    total = 0
    for num in lst:
    	total += num 
    return total

 

# 방법 1
>>> help(sum_list)
Descriotion : 
    리스트에 있는 모든 요소를 더하는 함수 
Param : 
    lst 숫자로 이루어진 리스트 
Return : 
    리스트의 모든 요소의 합    	
(END)

# 방법 2
>>> print(sum_list.__doc__)
Descriotion :
    리스트에 있는 모든 요소를 더하는 함수
Param :
    lst 숫자로 이루어진 리스트
Return :
    리스트의 모든 요소의 합

 

( 4 ) Annotation (good~!)

  • 어노테이션 ? 타입! 
    어노테이션은 힌트를 활성화시켜주는 역할을 수행한다. 
  • 타입힌트를 명시하면 실행시키는 타입과 다를 경우 에러가 날까?
    → 아니다. PEP-484에서는 "타입 힌트를 필수로 하자거나 심지어 관습으로 하자는 것은 아니다"라고 명시되어있다. 
    타입힌트 등을 지키기 위해서는 개발자들 사이에서 먼저 타입힌트가 필요한 코드인지 확인하고, 컨벤션을 우선적으로 정의할 필요가 있다. 
def sum_list(lst: list) -> int:
    """
    Descriotion : 
    	리스트에 있는 모든 요소를 더하는 함수 
    Param : 
    	lst 숫자로 이루어진 리스트 
    Return : 
    	리스트의 모든 요소의 합    	
    """
    total = 0
    for num in lst:
    	total += num 
    return total

 

어노테이션을 명시한다면 어떤 타입을 파라미터로 받는지, 어떤 타입을 리턴하는지 쉽게 알 수 있다.

어노테이션은 인터프리터나 코드에서 타입 힌트를 명시한 함수에 아래 `.__annotations__` 으로 확인할 수 있다.  

>>> sum_list.__annotations__
{'lst': <class 'list'>, 'return': <class 'int'>}
반응형