Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 20 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
- [사이드 이펙트 피하기](#사이드-이펙트-피하기)
- [**Classes**](#classes)
- [**Single Responsibility Principle (SRP)**](#single-responsibility-principle-srp)
- [**Open/Closed Principle (OCP)**](#openclosed-principle-ocp)
- [**개방/폐쇄 원칙(Open/Closed Principle (OCP))**](#개방폐쇄-원칙openclosed-principle-ocp)
Copy link
Author

@kyc3492 kyc3492 Jun 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SRP와 마찬가지로 통용된 한국어 원칙명을 적용했으며 영어 원문 명칭을 병기했습니다.
또한 통용되는 원칙명은 개방 폐쇄 원칙 이나 원문을 유지하고자 개방/폐쇄 원칙으로 작성했습니다.
너무 길어 번잡해보이진 않는지 다른 분들 의견 궁금합니다. 🤔

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SRP와 마찬가지로 바람직해보입니닷! 👍👍👍

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 좋아 보입니다!! 👍

- [**Liskov Substitution Principle (LSP)**](#liskov-substitution-principle-lsp)
- [**Interface Segregation Principle (ISP)**](#interface-segregation-principle-isp)
- [**Dependency Inversion Principle (DIP)**](#dependency-inversion-principle-dip)
Expand Down Expand Up @@ -830,28 +830,17 @@ accepts a string.

As an added bonus, the `get_version()` is now reusable elsewhere.

### **Open/Closed Principle (OCP)**
### **개방/폐쇄 원칙(Open/Closed Principle (OCP))**

> “Incorporate new features by extending the system, not by making
> modifications (to it)”,
> Uncle Bob.
> “시스템을 확장함으로써 새로운 기능을 통합하세요. (시스템을) 수정하지 말고요.”, Uncle Bob.

Objects should be open for extension, but closed to modification. It should be
possible to augment the functionality provided by an object (for example, a
class)
without changing its internal contracts. An object can enable this when it is
designed to be extended cleanly.
객체는 확장에는 개방적이어야 하지만 수정에는 폐쇄적이어야 합니다. 내부 계약의 변경 없이 객체(클래스 등)에서 제공하는 기능을 활용해 확장이 가능해야 합니다. 객체가 깔끔하게 확장될 수 있도록 디자인되어야 이와 같은 방법이 가능해집니다.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 링크를 참조하여 계약이라는 단어를 그대로 활용하는 것을 참고하였고 본문에도 해당 단어를 사용했습니다.
다른 안이 있다면 자유롭게 코멘트 남겨주세요!


In the following example, we try to implement a simple web framework that
handles HTTP requests and returns responses. The `View` class has a single
method `.get()` that will be called when the HTTP server will receive a GET
request from a client.
다음의 예시는 HTTP 요청을 처리하고 응답을 반환하는 간단한 웹 프레임워크를 구현합니다. `View` 클래스에는 HTTP 서버가 GET 요청을 클라이언트로부터 받았을 때 호출될 단일 메서드 `.get()`가 있습니다.

`View` is intentionally simple and returns `text/plain` responses. We would
also like to return HTML responses based on a template file, so we subclass it
using the `TemplateView` class.
`View`는 의도적으로 단순하고 `text/plain` 응답을 반환합니다. 또한 템플릿 기반의 HTML 응답을 반환하고자 하기에, `TemplateView`라는 하위 클래스를 사용합니다.

**Bad**
**나쁜 예**

```python
from dataclasses import dataclass
Expand Down Expand Up @@ -892,17 +881,11 @@ class TemplateView(View):

```

The `TemplateView` class has modified the internal behaviour of its parent
class in order to enable the more advanced functionality. In doing so, it now
relies on the `View` to not change the implementation of the `.get()`
method, which now needs to be frozen in time. We cannot introduce, for example,
some additional checks in all our `View`-derived classes because the behaviour
is overridden in at least one subtype and we will need to update it.
`TemplateView` 클래스는 더 많은 기능을 수행하기 위해 부모 클래스의 내부 동작을 수정했습니다. 이렇게 함으로써, 이제 일정 시간 정지해야하는 `.get()` 메서드의 구현을 변경하지 않기 위해 `View`에 의존하게 됩니다. 예를 들어, `View`의 파생 클래스들에 대한 몇 가지 추가 검사를 도입하려할 때, 적어도 하나의 하위 유형에 오버라이딩 되어있고 이를 업데이트해야 하기 때문에 불가능합니다.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수요일 회의 때 이야기 나눈 것처럼,

In doing so, it now relies on the View to not change the implementation of the .get() method, which now needs to be frozen in time.

이 부분의 내용 자체가 좀 어색해보입니다.
제 생각에는 다음과 같이 쓰여야 될 것 같습니다.

In doing so, it now doesn't rely on the `View` to change the implementation of the `.get()` method, which now needs to be frozen in time.

그리고 여기서 frozen의 의미는 부모 클래스의 메서드가 override 되지 않고, 유지되어야 한다 라는 의미로 쓰인 것 같습니다.

추후에 저자의 repo에 PR를 남겨놓는게 좋아보입니다.


Let's redesign our classes to fix this problem and let the `View` class be
extended (not modified) cleanly:
이 클래스들을 다시 디자인해서 문제를 해결하고 `View` 클래스가 (수정하지 않고) 깔끔하게 확장될 수 있도록 해봅시다.

**Good**
**좋은 예**

```python
from dataclasses import dataclass
Expand Down Expand Up @@ -948,28 +931,18 @@ class TemplateView(View):


```
body의 소스를 바꾸려면 `render_body()`에 오버라이딩해야 합니다만, 이 방식은 **'오버라이딩을 위해 서브타입을 불러온다'** 라는 단일이고 잘 정의된 책임을 가집니다. 이는 서브타입에 의해 확장될 수 있게끔 디자인되었습니다.

Note that we did need to override the `render_body()` in order to change the
source of the body, but this method has a single, well defined responsibility
that **invites subtypes to override it**. It is designed to be extended by its
subtypes.
객체 상속과 객체 구성의 장점을 둘 다 활용하는 또 다른 좋은 방법은 [Mixins](https://docs.djangoproject.com/en/4.1/topics/class-based-views/mixins/)을 사용하는 것입니다.

Another good way to use the strengths of both object inheritance and object
composition is to
use [Mixins](https://docs.djangoproject.com/en/4.1/topics/class-based-views/mixins/)
.
Mixins는 다른 관련 클래스들과 독점적으로 사용되게끔 하게 해주는 베어본 클래스입니다. 대상의 동작을 변경하기 위해 다중상속을 활용하여 '혼합' 되어있습니다.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

독자들이 bare-bones classes 라는 용어가 어떤 의미인지 잘 모를 수도 있을 것 같습니다.
참고할 만한 링크가 있으면 이해에 도움이 될 것 같습니다.


Mixins are bare-bones classes that are meant to be used exclusively with other
related classes. They are "mixed-in" with the target class using multiple
inheritance, in order to change the target's behaviour.
몇 가지 규칙들이 있습니다.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다음과 같이이를 위해 처럼 매끄럽게 이어지게 할 수 있는 추가 단어를 붙일까요? 🤔

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

원문에서 명사형으로 사용되었으니,
몇 가지 규칙: 요렇게 하는 것도 방법이라 생각해요! 🤔


A few rules:
- Mixins는 항상 `객체`로부터 상속받아야 합니다.
- Mixins는 다음과 같이 항상 대상 클래스 앞에 와야합니다. `class Foo(MixinA, MixinB, TargetClass): ...`

- Mixins should always inherit from `object`
- Mixins always come before the target class,
e.g. `class Foo(MixinA, MixinB, TargetClass): ...`

**Also good**
**다른 좋은 예**

```python
from dataclasses import dataclass, field
Expand Down Expand Up @@ -1041,17 +1014,11 @@ class TemplateView(TemplateRenderMixin, ContentLengthMixin, View):
template_file = "index.html"

```
보시다시피, Mixins는 객체를 관련 기능들을 함께 패키징하여 단일 책임을 갖고 있고 깔끔하게 분리될 수 있는 재사용 가능한 클래스로 만듭니다. 클래스 확장은 추가 클래스의 '혼합'으로 달성됩니다.

As you can see, Mixins make object composition easier by packaging together
related functionality into a highly reusable class with a single
responsibility, allowing clean decoupling. Class extension is achieved by "
mixing-in" the additional classes.

The popular Django project makes heavy use of Mixins to compose its class-based
views.
인기있는 Django 프로젝트는 Mixins을 많이 활용하여 클래스 기반의 뷰를 구성합니다.

FIXME: re-enable typechecking for the line above once it's clear how to use
`typing.Protocol` to make the type checker work with Mixins.
FIXME: Mixins에서 `typing.Protocol`를 사용해 타입 체킹하는 방법이 명확해지면 코드에서도 다시 활성화하도록 합니다.

### **Liskov Substitution Principle (LSP)**

Expand Down