2. Agenda
• Design Patterns – still valuable?
• The world without spam – chain of responsibility
• Level designer - builder
• Watch out for walls – object pool
4. The world without spam
• Have you ever consider how filtering in mailboxes works?
• What happens when you receive a new mail?
[
{
"title": "Test message",
"body": "Lorem ipsum",
"date": "2018-07-20 09:38:12",
"from": "example@example.com",
"to": "my_mail@example.com"
},
{
"title": "Test message with Spam title",
"body": "Lorem ipsum",
"date": "2018-07-20 09:18:12",
"from": "example@example.com",
"to": "my_mail@example.com"
},
{
"title": "Test message with weird body",
"body": "Lorem ipsum spam and another",
"date": "2018-07-20 09:38:12",
"from": "example@example.com",
"to": "my_mail@example.com"
}
]
7. Filtering
• There is a “spam” word in a message title?
• There is a “spam” word in a message body?
• There is a message for me?
• There is a sender on a blacklist?
type Validator interface {
IsSpam(message.Message) bool
}
type Filter struct {
validator Validator
next *Filter
}
func NewFilter(filter Validator) *Filter {
return &Filter{validator: filter, next: nil}
}
8. Filtering in goroutines
func (f Filter) ValidateAllMessages(messages []message.Message) {
var wg sync.WaitGroup
for index := range messages {
wg.Add(1)
go f.validateMessage(&messages[index], &wg)
}
wg.Wait()
if f.isNextHandler() {
f.next.ValidateAllMessages(messages)
}
}
func (f Filter) isNextHandler() bool {
return f.next != nil
}
func (f Filter) validateMessage(msg *message.Message, wg *sync.WaitGroup) {
defer wg.Done()
if f.validator.IsSpam(*msg) {
msg.Spam = true
}
}
9. Title filtering
type TitleFilter struct {
Validator
}
func (TitleFilter) IsSpam(msg message.Message) bool {
return strings.Contains(strings.ToLower(msg.Title), "spam")
}
14. Map generator
• Let’s build a game level.
• A simple survive game needs generated maps (e.g. height maps).
• Blueprints of different kind of buildings:
• Heating building
• Smith building
• Shop building
• All buildings contains rooms
18. IBuilding
type IBuilding interface {
Build() (Building, error)
getOwner() player.Player
buildRooms() ([]Room, error)
}
type HeatingBuilding struct {
IBuilding
Owner player.Player
X int
Y int
}
type ShopBuilding struct {
IBuilding
Owner player.Player
X int
Y int
}
type SmithBuilding struct {
IBuilding
Owner player.Player
X int
Y int
}
func (_ ________) getOwner() player.Player {
return hb.Owner
}
type Room struct {
Map []Point
RoomLetter rune
}
26. Level
type Level struct {
Board [][]rune
XSize, YSize uint
wallPool *object_pool.WallPool
actors []interfaces.Actor
nextWallWidth uint
}
func NewLevel(XSize, YSize uint, wallPool *object_pool.WallPool) Level {
board := make([][]rune, XSize)
for i := range board {
board[i] = make([]rune, YSize)
}
level := Level{Board: board, XSize: XSize, YSize: YSize, wallPool: wallPool}
level.clear()
return level
}
func (l *Level) clear() {
for x := range l.Board {
for y := range l.Board[x] {
l.Board[x][y] = ' '
}
}
}
func (l *Level) printRenderedBoardOnConsole() {
for x := range l.Board {
for y := range l.Board[x] {
fmt.Printf("%c", l.Board[x][y])
}
fmt.Printf("n")
}
}
func (l *Level) RenderOnConsole() {
l.clear()
l.addWall()
l.renderActors()
l.printWallStatsSummary()
l.printRenderedBoardOnConsole()
}
27. Player and actors
type Actor interface {
Render(ILevel)
}
type Player struct {
interfaces.Actor
X, Y uint
currentLevel interfaces.ILevel
}
type Wall struct {
interfaces.Actor
X, Y uint
Width uint
}
28. Walls
func NewWall(x, y, width uint) Wall {
return Wall{X: x, Y: y, Width: width}
}
func GenerateRandomWidthWall(xLevelSize, yLevelSize uint) Wall {
time.Sleep(time.Second * 2)
randomX := uint(rand.Int31n(int32(xLevelSize - MAXSIZE)))
randomY := uint(rand.Int31n(int32(yLevelSize)))
randomWidth := uint(rand.Int31n(MAXSIZE + 1))
return NewWall(randomX, randomY, randomWidth)
}
func (w Wall) Render(level interfaces.ILevel) {
for i := uint(0); i < w.Width; i++ {
level.SetObjectOnBoard(w.X + i, w.Y, '-')
}
}
Czy design patterny dalej żyją czy sa to już dinozaury?
Zaprezentuje i polecę apki do napisania dla 3 design patternów
C++, Java bez sprzecznie wzorce sa uzyteczne
W Pythonie i GoLang – do rozwagi
Minuta na zastanowienie się jak filtrują wiadomości w klientach mailowych
Struktura przechowująca maile
Mamy do odpalenia kilka elementow ktore przetwarzaja obiekt
Zrobmy z nich liste
Struktura wzorca.
Client przechowuje liste przetwarzajacych
Client pozwala dodawac nowych przetwarzajacych (dbajac o zaleznosc listy)
Przetwarzajacy obiekt
Przetwarza
Dodaje nastepny element do siebie
Workflow
Tworzymy 3 handlery
Dodajemy je do listy
Wrzucamy obj do przetwarzania dla clienta
Filtr tytulu maila
Filtr tresci maila
Filtr czy napewno do mnie (moze sprawdzac imie I nazwisko np.)
Filtr czy uzytkownik nie jest na czarnej liscie
Interfejs filtrow:
Handle -> sprawdza wiadomosc
AddNext -> dodaje kolejny filtr
1. Pamietaj o breakpointach w filtrach
2. Tytuly takie jak Rust, Minecraft, Ark, Don’t Starve
Po co err? Przekonamy sie przy budowie
Konstuktor, moze randomowo tworzyc mapy albo miec zafixowane.
Wykorzystujemy mechanism uproszczajacy obsluge bledow (md.err)