We.TIL 번외 : 파이썬을 파이썬답게!, 깔끔한 코드짜기

김기욱·2020년 8월 7일
1

We.TIL

목록 보기
31/69

Wecode Python Coding Convention

파이썬 코드 스타일은 인터넷 검색하면 여러가지가 이미 존재 합니다. 그중 대표적인 것은 파이썬 공식 가이드인 PEP-8과 구글의 파이썬 코딩 스타일 입니다. 다음 내용은 >wecode의 파이썬 코딩 스타일 가이드 입니다. 기본적으로는 PEP-8과 일맥상통 하며, wecode만의 스타일과 철학을 추가한 코딩 스타일 가이드 입니다.

Wecode의 Coding Convention 철학

코드는 가독성이 중요합니다.
가독성이 높은 코드는 내가 작성한 하지 않았어도 보면 이해하기 쉬운 코드가 가독성이 높은 코드 입니다. 그렇다면 어떠한 코드가 이해하기 쉬운 코드 일까요? 이해하기 쉬운 코드는 다음 사항들이 잘 지켜진 코드가 이해하기 쉬운 코드 입니다.

  • 깔끔한 코딩 스타일
  • 간단하고 명료한 로직
  • 명확한 명수, 함수, 클래스 등의 이름

위의 사항들이 잘 지켜진 코드가 가독성이 높은 코드 입니다.
일반 글쓰기와 비교하자면 코드는 일기가 아니라 소설이나 출판 책에 가깝습니다.
일기는 개인용도 이기 때문에 가독성이 중요하지 않습니다. 나 혼자만 이해하면 됩니다.
반면에 소설은 모든 사람들이 읽고 이해하고 공감할 수 있어야 합니다.
코드도 마찬가지 입니다. 나 혼자만 이해할 수 있는 코드는 안좋은 코드 입니다.
다른 개발자들도 쉽게 이해할 수 있는 코드가 좋은 코드 입니다.

Naming

변수, 함수, 클래스, 모듈, 팩케지(package)등의 이름은 최대한 한 눈에 그 목적을 이해할 수 있는 이름을 선택하는 것이 좋습니다. 그래서 이름만 보더라도 목적이나 기능이 파악이 되는 이름이 좋습니다.

# 변수 이름 예제
user         = User()
users        = get_users()
bmw          = Car("BMW")
http_request = HttpRequest()
total_cost   = calculate_total_cost()

# Constant(상수)
DEBUG_LEVEL = 1
MAX_USERS   = 200
VIP         = 3

# 함수 이름 예제
def calculate_total_cost():
    # ...

def get_user_permission(user):
   # ...

def buy_stock(stock_name):
   # ...

# 클래스 이름 예제
class User:
    # ...

class HttpRequest:
    # ....

class Car:
    # ...

# 모듈 이름 예제
module.py
my_module.py

# 팩케지 이름 예제
package
mypackage

위의 예제 처럼 간단하면서도 명료한 이름들이 좋습니다.
또 한 가지 중요한 점:

일반적으로 변수나 클래스는 이름이 명사로 이루어지며 함수는 동사 입니다.

변수나 클래스는 특정 정보나 resource를 가지고 있는 역할을 하고 함수는 특정 기능이나 연산을 실행하는 역할 이기 때문에 변수나 클래스 이름은 명사로 되고 함수는 동사로 됩니다.
또 한가지 중요한 점은, 함수나 변수의 이름에는 _ (밑줄, underscore)이 사용되었고 클래스 이름에는 HttpRequest 와 같이 대문자로 구분 되었다는 점입니다.
파이썬에서는 클래스의 이름을 제외하고는 일반적으로 _ 을 사용해서 단어들을 구분합니다.
또한 상수(constant)는 일반적으로 전부 대문자로 이루어지고 팩케지는 _를 사용해서 구분하지 않습니다.

아래 표를 참조하세요:

Naming Anti Pattern

이름을 정할때 다음과 같은 이름들은 일반적으로 가독성이 떨어지는 이름들 입니다:

  • 특별한 의미가 없거나 목적이 불분명한 이름들:

    object = User()
    list   = [1, 2, 3, 4, 5]
  • 너무 자세하거나 긴 이름들:

    user_who_is_created_now                         = User()
    list_of_integer_numbers_that_are_less_than_five = [1, 2, 3, 4]
  • 너무 짧은 이름들

    u = User()
    l = [1, 2, 3, 4, 5]
    i = 7
  • 단어 철자를 짧게 만든 이름들:

    trd  = Trader()
    nums = [1, 2, 3, 4, 5]

Space

Space(빈 줄)을 사용하는 것에도 암묵적으로 지켜지는 convention이 있습니다.
Wecoder 분들이 처음 배우실 때 많이 실수 하시는 부분이 여러 빈 줄을 삽입하는 경우 입니다.
일반적으로 빈 줄은 하나만 삽입 합니다 (어떤 가이드들은 클래스와 클래스 사이는 2줄의 빈 줄을 삽입하라고 안내하는 가이드도 있지만 저희는 기본적으로 빈 줄은 하나만 사용합니다).
또한 빈줄은 관련이 있는 로직(login) 단위로 삽입 합니다.
예를 들어, 같은 함수라도 함수를 구성하는 로직은 여러 부분으로 나뉠 수 있습니다. 이러한 부분 사이에 빈 줄을 삽입 해주시면 됩니다.

Bad

class User:

    def __init__(self, name):
        self.name

if True:
    print("Hello World!")
    if False:
        print("False")

else:
    print("Else")
 

def create_user(user):
    new_user      = User()

    new_user.name = user["name"]
    new_user.age  = user["age"]        
    save_user(new_user)

try:

    do_something()

except Exception as e:
    print("Exception!!")

Good

class User:
    def __init__(self, name):
        self.name

if True:
    print("Hello World!")

    if False:
        print("False")
else:
    print("Else")
 
def create_user(user):
    new_user      = User()
    new_user.name = user["name"]
    new_user.age  = user["age"]       
 
    save_user(new_user)

try:
    do_something()
except Exception as e:
    print("Exception!!")

코드가 한줄에 너무 길게 있을때

일반적으로 한 줄에는 79자를 안넘어가도록 코드를 작성합니다. 한 줄에 79자를 넘어가면 다음줄로 나누어서 작성하는것이 일반적인 가이드 입니다.
하지만 저희 wecode는 79자도 너무 많다고 생각합니다.
그래서 79자가 아니더라도 한 눈에 봤을때 부담스럽다면 다음줄로 나누어서 작성하여 가독성을 높이는 것을 선호합니다:

Bad

from module1 import ClassA, ClassB, ClassC, ClassD, ClassE

new_design = DesignDescription.objects.create(category_id = 1, name = "test", description = "some long test description")

def get_something(param1, param2, param3, param4, param5):
		pass

user = { "id" : 1, "name" : "아이유", "age" : 27, "gender" : "Female", "occupation" : "Artist"}

Good

from module1 import (
		ClassA, 
		ClassB, 
		ClassC, 
		ClassD, 
		ClassE
)

new_design = DesignDescription.objects.create(
		category_id = 1, 
		name        = "test", 
		description = "some long test description"
)

def get_something(
		param1, 
		param2, 
		param3, 
		param4, 
		param5
):
		pass

user = { 
    "id"         : 1, 
		"name"       : "아이유", 
		"age"        : 27, 
		"gender"     : "Female", 
		"occupation" : "Artist"
}

Code Align
일상에서도 "줄"을 잘 맞추고 "각"을 잘 맞추면 깔끔하고 정리된 느낌을 줍니다.

코드도 마찬가지 입니다. Align, 즉 줄을 잘 맞추면 코드가 깔끔하고 정리된 느낌을 줌으로 읽는 사람이 더 편하게 읽을 수 있도록 해줍니다.

Bad

import django
from something import awesome
from math import random
import requests

new_user = User()
new_user.name = user["name"]
new_user.age = user["age"]
new_user.feature = "?"       

user = { 
    "id" : 1, 
		"name" : "아이유", 
		"age" : 27, 
		"gender" : "Female", 
		"occupation" : "Artist"
} 

Good

import django
import requests

from something import awesome
from math      import random

new_user         = User()
new_user.name    = user["name"]
new_user.age     = user["age"]
new_user.feature = "?" 

user = { 
    "id"         : 1, 
		"name"       : "아이유", 
		"age"        : 27, 
		"gender"     : "Female", 
		"occupation" : "Artist"
}
profile
어려운 것은 없다, 다만 아직 익숙치않을뿐이다.

1개의 댓글

comment-user-thumbnail
2022년 7월 2일

감사합니다

답글 달기