Here are the key points about GRASP patterns:
1. GRASP stands for General Responsibility Assignment Software Patterns. It is a set of 9 patterns used to assign responsibilities to classes in object-oriented design.
2. Properly assigning responsibilities and distributing them among classes is a core part of object-oriented design. Developers and designers should be familiar with these patterns.
3. The 9 GRASP patterns are: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Indirection, Polymorphism, Pure Fabrication, and Protected Variations. Each pattern provides guidance on distributing responsibilities in a certain context.
4. When designing a system, analyzing which classes should have which responsibilities based
10. rpc: remove size limit on RPC server message freelist.
Servers like FizzBuzz have very large messages and would benefit
from reuse. Make the freelist larger, and add a goroutine that
frees the freelist entries slowly over time, so that idle servers
eventually release all freelist entries.
Construct a Task with a TimeKeeper to use its TimeStr and Now methods.
Add a Now method to Task, so the borglet() getter method can be removed
(which was only used by OOMCandidate to call borglet’s Now method). This
replaces the methods on Borglet that delegate to a TimeKeeper.
Allowing Tasks to supply Now is a step toward eliminating the dependency
on Borglet. Eventually, collaborators that depend on getting Now from
the Task should be changed to use a TimeKeeper directly, but this has
been an accommodation to refactoring in small steps.
Continuing the long-range goal of refactoring the Borglet Hierarchy.
40. GRASP 9
9가지 General Responsibility Assignment Software Patterns 집합
객체 책임을 할당하는 것은 OOD(객체 지향 설계) 핵심 설계 방법 중에 하나
개발자와 설계자라면 이런 패턴에 익숙해져야 함
1.정보 담당자 Information Expert
2.소유권한 Creator
3.컨트롤러 Controller
4.낮은 연결 Low Coupling
5.높은 응집도 High Cohesion
6.간접 참조 Indirection
7.다형성 Polymorphism
8.순수 조립 Pure Fabrication
9.변화 보호 Protected Variations
https://medium.com/@codesquad_yoda/ -grasp- -d5e37a1bb5dc
55. HL1
ML1
+ Foo()
<<Protocol>>
AM
+ Foo()
호출을 하는 모듈과 호출 받는 모듈 모두 소스 코드 의존성을 원하는 방향으로 설정할 수 있다.
소스 코드 의존성을 원하는 방향으로 관리할 수 있기 때문에
모듈, 컴포넌트 또는 배포가능한 단위로 서로 의존하지 않도록 컴파일할 수 있다.
결국 서로 독립적으로 배포를 할 수 있다. (배포 독립성)
71. Classes Are Awesome
• Encapsulation
• Access Control
• Abstraction
• Namespace
• Expressive Syntax
• Extensibility
ClassesClassesClassesTypes
I can do all
that with structs
and enums.
WWDC 2015 : POP
84. class Screening {
func reserve(with customer: Customer, audienceCount: Int) -> Reservation {
}
}
class Screening {
private var movie : Movie
private var sequence : Int
private var whenScreened : DateTime
func reserve(with customer: Customer, audienceCount: Int) -> Reservation {
}
}
class Screening {
private var movie : Movie
private var sequence : Int
private var whenScreened : DateTime
func reserve(with customer: Customer, audienceCount: Int) -> Reservation {
return Reservation(with: customer, screening: self, fee:calculateFee(audienceCount), audienceCount)
}
func calculateFee(int audienceCount) -> Money {
return movie.calculateMovieFee(self).times(audienceCount)
}
}
Screening
85. class Movie {
func calculateMovieFee(screening: Screening) -> Money {
}
}
class Movie {
private let title : String
private let runningTime : TimeInterval
private let fee : Money
private var discountConditions = Array<DiscountCondition>()
private let movieType : MovieType
private let discountAmount : Money
private let discountPercent : Double
func calculateMovieFee(screening: Screening) -> Money {
}
}
Movie
86. class Movie {
enum MovieType {
case AmountDiscount
case PercentDiscount
case NoneDiscount
}
private let title : String
private let runningTime : TimeInterval
private let fee : Money
private var discountConditions = Array<DiscountCondition>()
private let movieType : MovieType
private let discountAmount : Money
private let discountPercent : Double
func calculateMovieFee(screening: Screening) -> Money {
if isDiscountable(for: screening) {
return fee.minus(calculateDiscountAmount())
}
return fee
}
private func isDiscountable(for: Screening) -> Bool {
return discountConditions.filter{ $0.isSatisfied(by: screening) }.count > 0
}
}
Movie
87. class DiscountCondition {
func isSatisfied(by screening: Screening) -> Bool {
}
}
class DiscountCondition {
private let type : DiscountConditionType
private let sequence : Int
private let dayOfWeek : DayOfWeek
private let startTime : Date
private let endTime : Date
func isSatisfied(by screening: Screening) -> Bool {
if type == .period {
return isSatisfiedByPeriod(screening)
}
return isSatisfiedBySequence(screening)
}
private func isSatisfiedByPeriod(_ screening: Screening) -> Bool {
return dayOfWeek.equals(screening.whenScreened.dayOfWeek) &&
startTime.compare(to: screening.whenScreended.toLocalTime() <= 0) &&
endTime.isAfter(to: screening.whenScreended.toLocalTime() >= 0)
}
private func isSatisfiedBySequence(_ screening: Screening) -> Bool {
return sequence == screening.sequence
}
}
DiscountCondition
88. class Screening {
private var movie : Movie
private(set) var sequence : Int
private(set) var whenScreened : DateTime
func reserve(with customer: Customer, audienceCount: Int) -> Reservation {
return Reservation(with: customer, screening: self, fee:calculateFee(audienceCount), audienceCount)
}
func calculateFee(int audienceCount) -> Money {
return movie.calculateMovieFee(self).times(audienceCount)
}
}
Screening & DiscountCondition
class DiscountCondition {
enum DiscountConditionType {
case Sequence, Period
}
private let type : DiscountConditionType
private let sequence : Int
private let dayOfWeek : DayOfWeek
private let startTime : DateTime
private let endTime : DateTime
//…