Skip to content

Latest commit

 

History

History
184 lines (137 loc) · 5.82 KB

04.md

File metadata and controls

184 lines (137 loc) · 5.82 KB

4. Fundamentals of Django App Design

4.1 The Golden Rule of Django App Design

"Write programs that do one thing and do it well."(하나의 기능만 잘 수행하는 프로그램을 작성하라)

Unix philosophy according to Douglas Mcllroy

해당 철학을 따라 각 app은 하나의 task만 처리해야한다. 만약 각 app을 설명할 때 한 문장으로 설명할 수 없다면 app이 나뉘어질 수 있다는 것이다.

4.1.1 A Practical Example of Apps in a Project

아이스크림 가게가 있을 때 각 app은 다음과 같이 나뉘어질 수 있다.

  • flavors: 아이스크림 맛과 그를 웹사이트에 보여주는 app
  • blog: Two Scoops blog 관련 로직
  • events: 가게의 이벤트들을 띄워주는 app
  • shop: mail 주문으로 판매할 수 있게 해주는 서비스
  • tickets: 프리미엄 아이스크림 페스티벌 티켓 판매를 관리하는 앱

하나의 앱에서 이걸 다 하는 것보다 나누는 것이 훨씬 낫다.

4.2 What to Name Your Django Apps

App을 위해 쉽고, 기억하기 쉬운 이름을 짓는 것이 좋다.

그리고 PEP 8 가이드에 맞게

  1. 모두 소문자고,
  2. 숫자, 대쉬, 마침포, 공백, 특수문자가 없는 이름을 써라
  3. 필요하다면 언더바(_)를 사용하라

4.3 When in Doubt, Keep Apps Small

완벽한 App design을 만들기 위해서 너무 최선을 다하지 마라. 그냥 이것만 기억해라.

App을 최대한 작게 만드는 것에 집중해라

4.4 What Modules Belong in an App?

4.4.1 Common App Modules

99%의 Django app들은 이런 식으로 구성되어 있다.

# Common modules

  scoops/
  ├── __init__.py
  ├── admin.py
  ├── apps.py
  ├── forms.py
  ├── management/
  ├── migrations/
  ├── models.py
  ├── templatetags/
  ├── tests/
  ├── urls.py
  ├── views.py

4.4.2 Uncommon App Modules

하지만 우리는 이런식으로 구성한다.

# uncommon modules

   scoops/
   ├── api/
   ├── behaviors.py
   ├── constants.py
   ├── context_processors.py
   ├── decorators.py
   ├── db/
   ├── exceptions.py
   ├── fields.py
   ├── factories.py
   ├── helpers.py
   ├── managers.py
   ├── middleware.py
   ├── schema.py
   ├── signals.py
   ├── utils.py
   ├── viewmixins.py
  • api/: api를 �구성할 때 필요한 다양한 모듈들을 분리해놓는다.
  • behaviours.py: Model mixin들에 대한 정보를 포함한다.
  • constants.py: app-level 설정들을 저장해두는 파일.
  • decorators.py: Decorator들을 위치시키는 파일
  • db/: custom model field나 component를 저장하는 파일
  • fields.py: form field를 위한 파일
  • factories.py: Test data factory를 위한 파일
  • utils.py: Helper function들을 ㅈ저장하는 파일. viewmodel을 가볍게 만들기 위해 사용한다.
  • managers.py: models.py가 엄청나게 커질 때 custom model manager를 이곳에다 둔다.
  • schema.py: GraphQL을 위한 파일
  • signals.py: Custom signal을 위한 파일
  • viewmixins.py: View mixin 저장 파일

4.5 Alternative: Ruby on Rails-Style Approaches

Ruby on Rails style 적용에 대한 예시

4.5.1 Service Layers

예를 들어 user를 만들고, user에게 티켓을 주는 예시를 생각해보자.

전통적인 접근법에서는

class UserManager(BaseUserManager):
  """In users/managers.py"""
  def create_user(self, email=None, password=None, avatar_url=None):
    user = self.model(
            email=email,
            is_active=True, last_login=timezone.now(), registered_at=timezone.now(), avatar_url=avatar_url
            )
    resize_avatar(avatar_url)
    Ticket.objects.create_ticket(user)
    return user

class TicketManager(models.manager):
  """In tasks/managers.py"""
  def create_ticket(self, user: User):
    ticket = self.model(user=user)
    send_ticket_to_guest_checkin(ticket)
    return ticket

user manager에서 ticket manager를 부르는 식으로 구현한다. 이는 User app과 Ticket app의 dependency를 강화한다.

Service Layer의 접근에서는 services.pyselectors.py를 통해 서비스 로직을 구현할 수 있다.

# In users/services.py
from .models import User
from tickets.models import Ticket, send_ticket_to_guest_checkin

def create_user(email: str, password: str, avatar_url: str) -> User:
  user = User(
     email=email,
     password=password,
     avatar_url=avatar_url
  )
  user.full_clean()
  user.resize_avatar()
  user.save()

  ticket = Ticket(user=user)
  send_ticket_to_guest_checkin(ticket)

  return user

이런 접근의 장점은 다음과 같다.

  • 17줄이 12줄로 줄었다.
  • user와 ticket 코드의 의존성이 줄어든다.
  • 책임감의 분리를 통해 유저를 생성하는 로직과 티켓을 부여하는 로직을 분리해줄 수 있다.
  • (Optional) type annotation을 통해서 return 되는 객체에 대해서 쉽게 알 수 있다.

단점은 다음과 같다.

  • 작은 프로젝트의 경우에는 복잡성만 더한다.
  • 복잡한 프로젝트의 서비스 레이어는 1000줄 이상으로 비대해질 것이다.
  • selectors.py는 ORM이 할 수 있는 일을 굳이 wrapping할 수 있다.
  • Django는 model에 business logic을 넣는 식으로 발전하기 때문에 그런 능력을 잃게 된다.

4.5.2 The Large Single App Project

하나의 app으로 전체 프로젝트를 관리한다.

migration에 이점이 있다. Ruby on rails나 다른 프레임워크은 이런 패턴을 따르게 돼있지만, Django는 이런 디자인으로 최적화 되지 않는다.

4.6 Summary

  • App 사이즈는 최대한 줄여라.
  • App이 하는 일을 한 문장으로 설명하지 못한다면 줄여야된다는 신호다.