Coder Social home page Coder Social logo

styleguide's Introduction

styleguide

뱅크샐러드 엔지니어링 팀이 지향하는 코드의 형태를 함께 논의하고 이를 문서로 정리해둔 스타일 가이드 코드 저장소입니다.

정적인 문서 파일이 아닌 코드 저장소 형태로 스타일 가이드를 운영하는 것은 이를 논의의 공간으로 삼고자 하는데 가장 큰 뜻이 있습니다. 누구든 제안(issue 혹은 pull request)할 수 있으며 이에 대한 의견을 공유할 수 있도록 하기 위함입니다.

다음은 저희 뱅크샐러드 엔지니어링 팀에서 작성한 언어별 스타일 가이드 목록입니다. 늘 저희 팀 최신의 생각을 반영하기 위해 노력 중이며, 작성된 스타일 가이드는 언제든 더 나은 형태로 변경될 수 있습니다.

철학

저희 뱅크샐러드는 작성에 편리한 코드보다는 읽기에 더 쉬운 코드를 더 가치 있게 생각하며 이를 스타일 가이드에 충분히 반영하고자 합니다. 물론 저희 팀은 코드 작성의 편리함 또한 중요한 가치라 여기며 이를 위한 노력 역시 해나가고 있습니다.

다음의 내용은 저희 팀이 스타일 가이드에 대한 철학을 정립하며 도움을 받았던 스타일 가이드이며 일부를 발췌하여 공유합니다.

Use common sense and BE CONSISTENT.

If you are editing code, take a few minutes to look at the code around you and determine its style. If they use spaces around their if clauses, you should, too. If their comments have little boxes of stars around them, make your comments have little boxes of stars around them too.

The point of having style guidelines is to have a common vocabulary of coding so people can concentrate on what you are saying, rather than on how you are saying it. We present global style rules here so people know the vocabulary. But local style is also important. If code you add to a file looks drastically different from the existing code around it, the discontinuity throws readers out of their rhythm when they go to read it. Try to avoid this.

OK, enough writing about writing code; the code itself is much more interesting. Have fun!

Google C++ Style Guide

참고 자료

styleguide's People

Contributors

0xd669 avatar astroplex avatar devholic avatar doong-jo avatar eastroots92 avatar grap3fruit avatar jy7123943 avatar kanziw avatar kimhecan avatar maryang710 avatar p-iknow avatar pjhjohn avatar winterjung avatar wisdommy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

styleguide's Issues

Python Style Guide 제안

Python Style Guide 제안

목적

Rainist 구성원이 파이썬 코드를 작성할 때 참고할 스타일 가이드를 작성하려는데 모두가 동의할 스타일가이드를 작성하기 위해 이슈로서 이견이 있을 수 있는 사항을 먼저 짚어보고자 합니다.

스타일 가이드 제안은 리뷰어 모두의 만장일치를 전제로합니다. 더불어 의견 수렴의 효율성을 높이기 위해 각 주제마다 제 개인적인 기호를 먼저 주장하고 있으며 당연히 이견이 있을 수 있음을 인지하고 있습니다. 각 주제에 대해 구성원 분들의 의견을 가감없이 말씀해 주길 바라며 일단 제일 이견이 있을만한 순서로 주제를 나열했습니다.

Trailing comma

제 주장: 트레일링 콤마를 사용합니다.

트레일링 콤마를 사용하면 git diff를 볼 때 실질적으로 바뀐 부분에만 집중할 수 있으며 에디터에서 한 줄을 복제하거나 제거할 때 성가심을 줄여주고 실수를 방지합니다. 전사적으로 지금까지 트레일링 콤마를 사용하지 않았음을 알고 있지만 이로인해 불필요한 추가 커밋과 실수가 지속적으로 발생하고 있으며 이는 구성원이 합의한 방식을 린트 도구에 반영해 줄여나가는게 맞다고 생각합니다.

 # non trailing comma
 def func(
-    hint: Optional[Dict[str, Any]] = None,
-    sort: Optional[Dict[str, Any]] = None
+    hint: Optional[Dict[str, Any]] = None
 )
 # with trailing comma
 def func(
     hint: Optional[Dict[str, Any]] = None,
-    sort: Optional[Dict[str, Any]] = None,
 )
labels = [
    'apple',
    'crumble',
]
# a few moment later
labels = [
    'apple',
    'banana'  # <- New element with missing comma
    'crumble',
]

Single quote, double quote

제 주장: double quote만 사용합니다.

사실 개인적으로는 모든 문자열을 single quote로, docstring만 double quote로 사용해왔습니다. 다만 이럴경우 린트 도구를 사용할 때 quote 검사를 예외사항으로 추가시켜주어야 하는데 이는 스타일 가이드를 따르는데 어려움만 높여주므로 하나로 통일해 사용해야한다고 생각했습니다. 그래서 docstring이 double quote인 김에 모두 double quote를 사용하도록 통일하는게 나을 것 같습니다.

  • double quote를 사용할 땐 shift키를 눌러야 하므로 입력에 불편함이 있습니다.
  • PEP257은 "always use """triple double quotes""" around docstrings"으로 명시합니다.
  • double quote를 사용하면 문자열 내 single quote로 apostrophe를 입력하기 쉽습니다.
  • single quote를 사용하면 문자열 내 double quote로 대화를 인용하기 쉽습니다.
  • google styleguide 에서는 single이든 double이든 일관성있게 사용하도록 권장하며 \\ 이스케이프를 피하기 위해 둘을 잠시 혼용하는걸 허용합니다.
  • black 포매터는 double quote를 강제합니다.

Line length

제 주장: 1줄은 80자까지 작성합니다.

코드를 작성하다보면 종종 80자를 넘어가곤 합니다. 그렇지만 1줄에 80자가 넘어가는 상황은 무언가 좋지 않다는 신호이며 max line length를 100자, 120자로 늘리는건 이런 코드 냄새에 관대해지게 만든다고 생각합니다. 깊은 indent, 긴 변수와 함수 이름, 깊숙한 곳에서의 import 때문에 80자를 넘기곤 하지만 이는 indent를 깊게 가져가지 말고 함수로 쪼개기, 여러 줄에 걸쳐 import 작성하기 등으로 리팩토링할 부분이지 관대함을 적용할 부분이 아니라 생각합니다. 더불어 80자 규칙은 린트 도구 도입으로 자동화할 수 있습니다.
PEP8의 언급에 따르면 파이썬 표준 라이브러리는 코드에 79자, 주석과 docstring에 72자를 사용하고 있지만 너무 보수적이라 생각하고 널리 받아들여질 수 있는 80자를 사용하는게 낫지 않을까 생각합니다.

네이밍

제 주장: PEP8을 따르고 클래스 이름은 온전하게, 함수 이름은 부분적으로 작성합니다.

entities/fruits.py내부의 클래스 이름으로 불필요한 중복으로 보여도 Common대신 CommonFruit을 사용합니다. 여러 저장소를 봤을 때 상위 모듈을 임포트해 네임스페이스와 같이 사용되기 보단 클래스 그 자체를 임포트해 사용하는 경향이 있으므로 클래스 그 자체로 스스로 설명가능한 이름이어야 한다고 생각합니다.

다만 함수명에 있어선 부분적인 이름이어도 괜찮다고 생각합니다. common_fruit.py 내부에선 컨텍스트를 공유하고 있으므로 common_fruit.update_banana_common_fruit보단 common_fruit.update_banana 혹은 더 분리해서 common_fruit.banana.update만으로도 충분하다고 생각합니다. 또 클래스와는 반대로 함수를 사용할 땐 함수를 임포트해 사용하기 보단 상위 모듈을 임포트해 네임스페이스와 같이 사용되는 경향을 보였습니다.

# in common_fruits.py

# bad
def get_user_common_fruits():
    pass

# good
def get():
    pass

def update():
    pass
# ...

Assert와 If 문

제 주장: assert는 오로지 test 용으로만 사용합니다.

assert statement는 문서에서 언급되었다시피 디버깅용 검사구문으로 의도되었습니다. __debug__과 함께 사용되는 if 문의 shortcut이며 이는 python을 실행할 때 -O(Optimize) 플래그와 함께 사용하면 모든 assert 구문을 무시하는 동작에서도 짐작할 수 있습니다. 그렇기 때문에 assert는 test 검증용으로 사용해야하며 유저가 어드민인지, 값이 제대로 들어 있는지 등 비즈니스 로직 상 검사하는 용도로 사용하지 않아야 한다고 생각합니다.

line break

제 주장: \보단 ()를 사용합니다.

긴 줄을 래핑하는 가장 좋은 방법은 괄호, 대괄호 및 중괄호를 사용하는 것입니다. 긴 줄은 괄호로 묶어서 여러 줄로 나눠질 수 있습니다. 이 괄호들은 백 슬래시보다 우선적으로 사용되어야합니다. - PEP8

append와 +=, list comprehension

제 주장: array += [other]보단 array.append(other)를, append보단 list comprehension 사용합니다.

언어적 차원에서 보다 편한 문법을 제공하므로 마땅히 이를 사용해야 한다고 생각합니다.

In [1]: %%timeit
   ...: a = []
   ...: for i in range(1_000_000):
   ...:     a += [str(i)]
   ...:
268 ms ± 8.88 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [2]: %%timeit
   ...: a = []
   ...: for i in range(1_000_000):
   ...:     a.append(str(i))
   ...:
252 ms ± 2.55 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [3]: %%timeit
   ...: a = [str(i) for i in range(1_000_000)]
   ...:
212 ms ± 4.01 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

indent style

제 주장: 함수 선언 줄이 80자가 넘어간다면 1줄에 1인자씩 적어주고 마지막 인자 뒤 트레일링 콤마를 붙이고 Parentheses를 다음 줄에서 닫아줍니다.

auto formatter중 하나인 black의 기본 동작이기도 합니다.

def func(
    if_some_variables: Optional[List[str]],
    over_the_80_width: Optional[int],
    separate_lines: bool = True,
) -> int:
    return 42

def foo(short: int) -> None:
    pass

Lint tool

  • pylint: eslint처럼 작성된 파이썬 코드에 잘못된 부분은 없는지, 더 개선시킬 부분은 없는지 자동으로 검사해주는 린트 도구입니다. .pylintrc 파일을 통해 세부적인 옵션을 조정할 수 있습니다.
  • isort: import order를 자동으로 정렬해주는 도구입니다. .editorconfig 혹은 .isort.cfg로 세부적인 옵션을 조정할 수 있습니다.
  • black: auto formatter 중 하나입니다. medium 아티클를 참고하시면 다른 포매터도 있지만 black을 제안하는 이유는 따로 설정해줘야할 부분이 적으며 위에서 주장한 스타일에 가장 근접하게 동작하는 도구이기 때문입니다. 다만 포매터라는 것이 기호가 있을 수 있는 부분이며 없어도 충분히 Rainist의 스타일 가이드에 맞는 코드를 작성할 수 있기에 이는 개인에 판단에 맡겨 사용하는 도구로 제안하고자합니다.
  • mypy: 파이썬 스태틱 타입 검사 도구입니다. TypeScript처럼 변수, 함수 등에 타입 힌트를 부여할 수 있으며 이를 기반으로 잘못된 코드가 없나 검사합니다. 참고로 파이썬의 타입 힌트는 런타임에 영향을 끼치지 않습니다. 기존 몇몇 레포에서 mypy를 적극적으로 사용해보고자 하는 시도가 있었으나 경험 부족으로 타입으로 커버하기 힘들어지는 케이스들이 발생하였고 결국 Any로 처리하거나 mypy를 제거하는 사례가 있었습니다. 그래서 이는 개인의 판단에 맡겨 사용하는게 좋을 것 같습니다.

Pre commit hook

위에서 결정된 lint 도구들을 커밋 작성 전에 실행되는 git pre commit hook에 설정하여 완전히는 아니더라도 잦은 스타일 코드 리뷰, 실수 등을 줄이고자 합니다. 최근 진행된 프로젝트 중 하나에서 시범적으로 도입했었고 lint에러나 스타일 지적이 줄어드는 효과를 보였습니다.

테스트 코드

기본적인 테스트 코드를 pytest를 이용해 작성하길 제안합니다. TDD와 integration test까지는 아니어도 각 함수의 동작을 테스트하는 unit test만이라도 작성한다면 좀 더 명세에 맞게 검증된 코드를 짤 수 있다고 생각합니다.

pytest는 파이썬 기본 내장 unittest에 비해 간결하고 깔끔한 테스트 코드를 작성할 수 있으며 더 읽기 쉬운 에러 리포트를 출력하며 fixture기능을 적극적으로 활용할 수 있고 여러 플러그인 또한 지원됩니다.

참고: unittest와 pytest를 비교해보는 글

Abbreviation and Acronym, 축약어와 두문자어

  • PascalCase 혹은 camelCase 사용시에 다음의 규칙을 적용합니다.
  • 축약어는 모두 첫 글자만 대문자
    • 예) simpleApp (application), currentMax (maximum)
    • 단 2글자 축약어는 모두 대문자
      • 예) userID (identity)
  • 두문자어는 모두 대문자
    • 예) HTTP, HTML, URL, DB, UUID, JSON, IO
    • 예) URLBuilder, IOStream, HTTPClient
  • 다양한 케이스 바이 케이스 규칙을 적용하기 보단 간결한 규칙을 적용해버리는게 낫다고 생각합니다.

버저닝

  • 시맨틱 버저닝: 3.6.5, 1.10.24
  • 캘린더 버저닝: 18.10.01, 16.04
  • 기존 레포들은 시맨틱 버저닝을 기준으로 작성되어 왔습니다. 라이브러리를 작성한다면 각 버전 업데이트가 어떤 의미를 가지고있는지 파악하기 쉬운 시맨틱 버저닝이 어울린다 생각하지만 웹 서버에 캘린더 버저닝을 사용하면 어떨까 생각해봤습니다.
  • 캘린더 버저닝은 주로 정기적인 릴리즈 프로세스를 갖는 프로젝트에 쓰이고 있으나 또 릴리즈 날짜가 유의미한 프로젝트(pytz, certifi)에도 사용되고 있습니다.
  • 클라이언트와의 협업에 있어 시맨틱 버저닝이 어울린다라는 생각과 동시에 outdated된 서버를 파악하고 주시하기엔 캘린더 버저닝이 유용하지 않을까라는 생각을 갖고 있습니다.
  • 이 부분은 따로 주장하는 부분은 없습니다.

기타사항

  • PEP8을 준수합니다.
  • Google Python Style Guide를 참고합니다.
  • 매직 밸류는 상수로 선언합닌다.
  • 전역 변수를 사용하지 않습니다.
    • app, db, config등의 변수들을 실행시켜줘야 할 때는 main()함수를 선언한 뒤 그 안에서 사용합니다.
  • 상수에 __contains__할 땐 상수를 set으로 사용합니다.
    • e.g. value in {1, 2, 3}

버전

  • Python 3.6 이상을 사용합니다.
  • 마이너 업데이트가 있을 시 첫 패치 업데이트 이후 사용합니다.
    • 예) 3.7 버전은 3.7.1 이후로 사용

문서화

  • 최소한 Repo의 Description과 간단한 README를 작성합니다.
  • 굳이 한 곳(Backend wiki, Confluence 등)에 모으기 보단 일단 해두기라도 하자 라는데 공감합니다

긴 제안 읽어주셔서 감사하며 본 이슈는 PR과 분리되어 진행됩니다. 이 이슈에서 구성원들의 합의가 이루어진 뒤 세부적인 파일작성, config 파일이 포함된 내용 등이 PR에 올라갑니다.

Python Sanic 컨벤션 내용 추가

서버에서 HTTPStatus만 응답하고 싶을 때 아래 3개의 방식 중 두번째 방식을 이용한다.

  1. response.raw(b’’, status=HTTPStatus.NO_CONTENT)
  2. response.json(None, status=HTTPStatus.NO_CONTENT)
  3. response.json({}, status=HTTPStatus.NO_CONTENT)

레퍼런스

불필요한 Python 관련 파일 제거

  • https://github.com/rainist/python 레포 공개로 styleguide의 파이썬 관련 파일 중 몇몇 개를 삭제할 수 있게되었습니다.
  • bin 폴더, Makefile, mypy.ini 를 삭제해도 될 듯 합니다.
  • .editorconfig 는 스타일에 관련된 내용이므로 남겨놔도 될 듯 합니다.
  • @sunghyunzz .pylintrc 는 남겨놔야할까요?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.