00. Kick-Off¶
스터디 소개¶
[내용]cd
스터디 모토
스터디 미션
스터디 규칙
멤버 소개
스터디 모토¶
무엇을 얻을것인지 생각
자랑하고 인정받고 칭찬받는 놀이터
~라는 최신 정보가 있어요 - 엄지척
스터디 미션¶
메인 미션: 책 완독, 관심 내용 발표 1회이상
그 이외에는 자유
다양한 도전과제와 즐길거리 제공
서브 퀘스트: MSA 토이 프로젝트 만들어서 호스팅하기
사이드 퀘: AWS/Azure에서 MSA 서비스 호스팅, 다른 모던 언어 배워보기, DevOps 배우기, AWS 자격증, 라즈베리파이로 개인 클러스터 만들기, 모바일 앱 만들어 플레이스토에 배포하기 등
겁먹지 마세요¶
책 내용이 어렵지만 다 이해할 필요 없어요.
책을 “완독” 하는게 목적이지 “완성”하는게 목적이 아닙니다.
메인 퀘스트가 어려우면 난이도를 낮추세요.
챕터에서 알고싶은 범위를 한정하거나, 이해할 챕터 분량을 한정하기
메인 퀘스트가 어려우면 서브/사이드 퀘스트에서 재미를 찾으세요!
이해 안가는 내용은 슬랙 / 컨플루언스에 언제든 물어보세요.
추천 미션 예:¶
다음중 하나를 해보고 스샷을 공유해주세요, 추천 수에 따라서 스벅 쿠폰을 보내드립니다(?)
마음에 드는 언어 하나 골라서 도메인 모델링 예제 구현 해보기
파이썬 도커 개발 환경에 JupyterLab 셋팅해보기
클라우드 플랫폼 (AWS, Azure, 또는 GCP) 가입해서 가상머신에 앱 하나 띄워보기
책에서 감명깊게 본 부분 캡쳐해서 감상평 올리기~
교재 선정 이유¶
https://github.com/cosmicpython/book
거의 유일 무이한 파이썬 기반 아키텍처 북
실천적인 접근 방법: 이론만큼 구현에도 중점
최신 교재 / 최신 파이썬 기술 포함
MSA를 맹신하지 않음.
엄청난 아마존 평점
스터디 규칙¶
공휴일 / 연휴 제외 매주 모이는 것을 원칙으로 합니다.
매주 내드리는 메인 미션은 반드시 완수하셔야 합니다.
메인 미션은. 정해진 분량의 교재 범위를 읽어오시고
지난번 모임에서 읽은 챕터의 테스트 코드를 완성시켜오시는 것입니다.
스터디를 마치기 전까지 최소 1번 이상 발표를 하셔야 합니다
토론¶
[내용]
왜 마이크로서비스가 대세일까요?
왜 파이썬으로 하나요?
스터디 운영방법?
왜 마이크로서비스가 대세일까요?¶
마이크로서비스가 소프트웨어 복잡성을 해결하는 현재까지 가장 진보된 방법이기 때문에
거대한 모놀리식 서비스를 세부레벨로 찢어서 부서간의 사일로 해결
그럼에도 개별 서비스들의 영향의 컨테이너 레벨로 안전하게 격리하고 서비스 메시를 통해 스케일 아웃 가능
SOA처럼 헤비한 프레임워크를필요로 하지 않아 간단하게 시작해볼 수 있음
마이크로서비스 운영 기술을 통해 엔터프라이즈 레벨로 확장이 용이
왜 파이썬으로 하나요?¶
가장 인기있는 언어
가장 빨리 발전하고 있는 언어 중 하나
오너십과 파이썬 커뮤니티니의 건전성
리눅스와 비슷? PEP 읽어보면 귀도 반 로섬이 거의 항상 참여
효과적인 스터디 운영방법은?¶
무엇을 공부하게 되나요?
너무 어렵지는 않을까요?
재미있게 열심히 할 수 있을까요?
회비 기반으로 동기부여하기
총무가 필요합니다. (매 주 5000원씩 회비를 걷습니다)
엄지척을 많이 받은 발표자에게 상품 쿠폰을 제공합니다.
책 둘러보기¶
Whenever we introduce an architectural pattern in this book, we’ll always ask,
“What do we get for this? And what does it cost us?”
Introduction¶
Why Do Our Designs Go Wrong?
Encapsulation and Abstractions
Layering
The Dependency Inversion Principle
A Place for All Our Business Logic: The Domain Model
I. Building an Architecture to Support Domain Modeling¶
1. Domain Modeling¶
What Is a Domain Model?
Exploring the Domain Language
Unit Testing Domain Models
Not Everything Has to Be an Object: A Domain Service Function
2. Repository Pattern¶
Persisting Our Domain Model
Some Pseudocode: What Are We Going to Need?
Applying the DIP to Data Access
Reminder: Our Model
Introducing the Repository Pattern
Building a Fake Repository for Tests Is Now Trivial!
What Is a Port and What Is an Adapter, in Python?
3. A Brief Interlude: On Coupling and Abstractions¶
Abstracting State Aids Testability
Choosing the Right Abstraction(s)
Implementing Our Chosen Abstractions
4. Our First Use Case: Flask API and Service Layer¶
Connecting Our Application to the Real World
A First End-to-End Test
The Straightforward Implementation
Error Conditions That Require Database Checks
Introducing a Service Layer, and Using FakeRepository to Unit Test It
Why Is Everything Called a Service?
Putting Things in Folders to See Where It All Belongs
5. TDD in High Gear and Low Gear¶
How Is Our Test Pyramid Looking?
Should Domain Layer Tests Move to the Service Layer?
On Deciding What Kind of Tests to Write
High and Low Gear
Fully Decoupling the Service-Layer Tests from the Domain
Carrying the Improvement Through to the E2E Tests
6. Unit of Work Pattern¶
The Unit of Work Collaborates with the Repository
Test-Driving a UoW with Integration Tests
Unit of Work and Its Context Manager
Using the UoW in the Service Layer
Explicit Tests for Commit/Rollback Behavior
Explicit Versus Implicit Commits
Examples: Using UoW to Group Multiple Operations into an Atomic Unit
Tidying Up the Integration Tests
7. Aggregates and Consistency Boundaries¶
Why Not Just Run Everything in a Spreadsheet?
Invariants, Constraints, and Consistency
What Is an Aggregate?
Choosing an Aggregate
One Aggregate = One Repository
What About Performance?
Optimistic Concurrency with Version Numbers
Testing for Our Data Integrity Rules
II. Event-Driven Architecture¶
8. Events and the Message Bus¶
Avoiding Making a Mess
Single Responsibility Principle
All Aboard the Message Bus!
Option 1: The Service Layer Takes Events from the Model and Puts Them on the Message Bus
Option 2: The Service Layer Raises Its Own Events
Option 3: The UoW Publishes Events to the Message Bus
9. Going to Town on the Message Bus¶
A New Requirement Leads Us to a New Architecture
Refactoring Service Functions to Message Handlers
Implementing Our New Requirement
Test-Driving a New Handler
Optionally: Unit Testing Event Handlers in Isolation with a Fake Message Bus
10. Commands and Command Handler¶
Commands and Events
Differences in Exception Handling
Discussion: Events, Commands, and Error Handling
Recovering from Errors Synchronously
11. Event-Driven Architecture: Using Events to Integrate Microservices¶
Distributed Ball of Mud, and Thinking in Nouns
Error Handling in Distributed Systems
The Alternative: Temporal Decoupling Using Asynchronous Messaging
Using a Redis Pub/Sub Channel for Integration
Test-Driving It All Using an End-to-End Test
Internal Versus External Events
12. Command-Query Responsibility Segregation (CQRS)¶
Domain Models Are for Writing
Most Users Aren’t Going to Buy Your Furniture
Post/Redirect/Get and CQS
Hold On to Your Lunch, Folks
Testing CQRS Views
“Obvious” Alternative 1: Using the Existing Repository
Your Domain Model Is Not Optimized for Read Operations
“Obvious” Alternative 2: Using the ORM
SELECT N+1 and Other Performance Considerations
Time to Completely Jump the Shark
Changing Our Read Model Implementation Is Easy
13. Dependency Injection (and Bootstrapping)¶
Implicit Versus Explicit Dependencies
Aren’t Explicit Dependencies Totally Weird and Java-y?
Preparing Handlers: Manual DI with Closures and Partials
An Alternative Using Classes
A Bootstrap Script
Message Bus Is Given Handlers at Runtime
Using Bootstrap in Our Entrypoints
Initializing DI in Our Tests
Building an Adapter “Properly”: A Worked Example
Epilogue¶
What Now?
How Do I Get There from Here?
Separating Entangled Responsibilities
Identifying Aggregates and Bounded Contexts
An Event-Driven Approach to Go to Microservices via Strangler Pattern
Convincing Your Stakeholders to Try Something New
Questions Our Tech Reviewers Asked That We Couldn’t Work into Prose
Footguns
More Required Reading
Appendicies¶
Summary Diagram and Table
A Template Project Structure
Swapping Out the Infrastructure: Do Everything with CSVs
Repository and Unit of Work Patterns with Django
Validation
참고: 프로그래밍 언어 랭킹¶
PYPL 2020¶
Python (30.34% / +1.2%) – 더 할말이?
Java (17.23% / -1.7%)
JavaScript (8.65% / +0.6%) – [TypeScript]: 왕위를 계승중입니다…
C# (6.44% / -0.8%) – .NET Framwork의 최강자
C/C++ / 6.11% / +0.1%)
PHP (5.88% / -0.3%)
R (3.84% / +0.1%) – 한때 유일하게 쓸만한 통계/데이터 과학 언어,Jupyter의 3대장
Objective-C (3.75% / +1.2%)
Swift (2.17% / -0.3%)
Matlab (1.77% / -0.0%)
TypeScript (1.62% / -0.2%)
Go (1.52% / +0.3%) – 마이크로서비스 트렌드의 대세
Kotlin (1.44% / -0.2%) – JVM 기반 언어중 최고 대세
Ruby (1.28% / -0.1%)
Rust (1.12% / +0.5%) – 마이크로서비스 트렌드의 또다른 대세언어, 함수형 언어의 적자
VBA (1.05% / -0.3%)
Scala (0.97% / -0.1%) – Kotlin에게 인기 빼앗기는 중…
Visual Basic (0.67% / -0.3%)
Ada (0.61% / +0.3%)
Dart (0.58% / +0.2%) – Flutter 프레임웍으로 인기 급상승
Lua (0.55% / +0.2%)
Perl (0.46% / -0.1%)
Groovy (0.43% / -0.0%) – 최고 Cool한 JVM 언어였지만.. Kotlin/Scala에 인기 다뺏김 Gradle로 연명중
Abap (0.41% / -0.1%)
Julia (0.33% / +0.1%) – Data Scientist 들에게 사랑받는 언어,Jupyter의 3대장
Haskell (0.27% / -0.0%)
Cobol (0.26% / -0.1%)
Delphi (0.26% / +0.0%)
3분 DDD¶
도메인 모델링이란¶
Domain modeling¶
The part of your code that is closest to the business.
The most likely to change, and the place where you deliver the most value to the business.
Need to make it easy to understand and modify.
Distinguish entities from value objects¶
Value Objects - Defined by its attributes. - Usually best implemented as an immutable type. - If you change an attribute on a Value Object, it represents a different object.
Entities - Even though an entity has attributes that may vary over time, it will still be the same entity. - Important to define what does uniquely identify an entity - usually some sort of name or reference field).
Not everything has to be an object¶
The “verbs” in your code be functions.
e.g)
FooManager, BarBuilder, BazFactory
vs.
manage_foo(), build_bar(), get_baz()
This is the time to apply your best OO design principles¶
Revisit the SOLID principles
All the other good heuristics like “has a versus is-a,” “prefer composition over inheritance,” and so on.
You’ll also want to think about consistency boundaries and aggregates¶
But that’s a topic for [chapter_07_aggregate].
Value Object in Python¶
[10]:
from dataclasses import dataclass
@dataclass(frozen=True)
class User:
name: str
age: int
user1 = User('John', 16)
user2 = User(age=16, name='John')
user1 == user2 # True
[10]:
True
참고: 모던 프로그래밍 언어에서 Value Object 구현 방법¶
public record User(String Name, int Age);
var user1 = new User("John", 16);
var user2 = new User("John", 16);
user1 == user2
public record User2 {
public String Name { get; init; }
public int Age { get; init; }
};
var user1 = new User2 { Name="Love", Age=17 };
var user2 = new User2 { Age=17, Name="Love" };
user1 == user2
// `ValueObject` 구현 방법은 별도 노트북을 참조하세요.
interface UserProps {
name: String
age: number
}
class User extends ValueObject<UserProps> {
constructor(props) { super(props) }
}
const user1 = new User({name: 'John', age: 16})
const user2 = new User({age: 16, name: 'John'})
user1 === user2 // false
user1.equals(user2) // true
type User struct {
name string
age int
}
user1 := User { "John", 16 }
user2 := User { "John", 16 }
user1 == user2 // true
// 당황: Go는 Immuable 속성을 지원하지 않아서 동적으로 속성을 변경 가능.
user1.name = "Test"
user1 == user2 // false
data class User(val name: String, val age: Int)
val user1 = User("John", 10)
val user2 = User("John", 10)
user1 == user2 // true
##[derive(PartialEq, Eq)]
struct User { name: String, age: u16 }
let user1 = User { name: String::from("John"), age: 16 };
let user2 = User { name: String::from("John"), age: 16 };
user1 == user2 // true
import groovy.transform.Immutable
@Immutable class User {
String name
int age
}
final user1 = new User('John', 16)
final user2 = new User([age: 16, name: 'John'])
user1 == user2 // true
import Base.@kwdef
@kwdef struct User
name::String
age::UInt8
end
user1 = User("John", 16)
user2 = User(age=16, name="John")
user1 == user2 # true
data User = User
{ name :: String,
age :: Int
} deriving (Eq, Show)
user1 = User { name = "John", age = 16 }
user2 = User { age = 16, name = "John" }
user1 == user2 -- True
결론¶
3개월 안에 책을 다 읽을 겁니다
3개월 동안 MSA 토이 프로젝트를 완성하고 발표를 하게 될 거에요.
스터디는 정말 재밌게 할 수 있을 겁니다!
특별한 일 없으면 매 주 오프라인/온라인 교대로 만날거에요.
다음주에 또 만나요 :D