SlideShare a Scribd company logo
1 of 76
Software design and
refactoring
Cracking complexity by sending messages and building pipelines
Self introduction
Let’s start with a puzzle...
Happy company
class Employee; end
class Engineer < Employee
def do_work; end
end
class ProductAnalyst < Employee
def do_work; end
end
class Company
attr_accessor :members
end
def main
thong_ng = Engineer.new
khai = ProductAnalyst.new
company = Company.new
company.members = [thong_ng, khai, ...]
company.members.each(&:do_work)
end
How about Son?
class Engineer; def write_code; end; end
class ProductAnalyst; def design_product; end; end
company.engineers.each(&:write_code)
company.product_analysts.each(&:design_product)
# How about Son = ???
son = SometimesEngineerSometimesProductAnalyst.new
son.write_code
son.design_product
# 3 months later...
son.becomes(ProductAnalyst) # ???
Agenda
1. OOP is not about class and inheritance
2. Software design is about cracking complexity
3. Functional programming is about reducing complexity
4. Functional core, imperative shell
● Traditional way of thinking about OOP is
incomplete
OOP is not about class and inheritance
Class and inheritance are language features and
implementation details, not essential parts of object-
oriented design.
Can we use OOP without class or inheritance?
OOP without class
module Employee
def do_work; end
end
module Engineer
def write_code; end
end
module ProductAnalyst
def design_product; end
end
son = Object.new.extend(Employee)
son.extend(Engineer)
son.extend(ProductAnalyst)
OOP without inheritance
class Engineer; end
class ProductAnalyst; end
thong_ng = Employee.new(roles: [Engineer.new])
son = Employee.new(roles: [Engineer.new, ProductAnalyst.new])
“Favor composition over inheritance”
Alan Kay’s OOP
“OOP to me means only messaging, local retention and protection and hiding of state-
process, and extreme late-binding of all things.” -- Alan Kay
● Message passing -> Interface is the only dependency between objects
● Local retention, protection and hiding of state-process -> Objects don’t know
the internal details of each other
● Extreme late-binding of all things -> Object behaviors can be changed at any
point in time
No mention of class or inheritance at all!
Ruby’s messages - everything is an object
1.to_s # returns "1"
1.send(:to_s) # returns "1"
1 + 1 == 1.send(:+, 1)
# There is no Boolean class in Ruby
true.class # returns TrueCLass
if (1 == 1)
'true'
end
# There is no if/else in Smalltalk - control structures are messages
(1 == 1).ifTrue do
'true'
end
(1 == 1).send(:ifTrue, &Proc.new { 'true' })
son.send(:extend, ProductAnalyst)
Class A; end
A.is_a?(Object) # returns true - classes are objects
A whole program is just about objects sending messages to each other.
What this means for software design
When you design a program, don't confuse class with role (interface).
● Class: language feature to construct object with certain roles. An object can
be created from a single class.
● Role: Messages an object with this role can reply to. An object can have
multiple roles. An object’s roles can change during run time.
Start with roles first: Employee role, Engineer role, ProductAnalyst role,
Persistable role, Movable role, etc.
The messages
Think about the behaviors the program must support, in other words, the
messages of each role:
● do_work → WorkingRole
● write_code → EngineeringRole
● design_product → ProductAnalysisRole
And then, when we want concrete behavior, we supply them via Factory, Class or
whatever the mechanism the language supports to construct objects. In pure
OOP, class is just a type of factory.
Recap
● OOP is not about class and inheritance
● OOP is about message sending
Part II
Software Design and Refactoring
Software design is about cracking
complexity
Writing software is complex...
How complex?
Example: Slack notification flowchart
As your software grows, complexity increases
Complexity is the root of all evil
● Readability: It makes it hard to understand and
reason about a program
● Reliability: Hard to reason about the program →
hard to debug
● Reusability: Hard to turn code into reusable
component
● Scalability: Hard to separate code that can run in
parallel
● Testability: Hard to test code with too many
dependencies
Two types of complexity
● Essential complexity
○ Complexity inherent to the problem which can’t be removed e.g. Slack
notification
● Accidental complexity
○ Complexity due to the choices made from a particular software design to
solve the problem
5 aspects of complexity
● Shared mutable state
● Side-effects
● Dependencies
● Control flow
● Code size
1st aspect of complexity - mutable state
● Hard to reason about
● Implicit time
dependency
● Explosion of state
space
● Hard to parallelize
2nd aspect of complexity - side effects
● Async call
● UI render
● Network call, etc.
Main problems: asynchronous
and fallible
3rd aspect of complexity - Dependencies
● Class dependency: object creation
dependency
● Interface dependency: messages
dependency
● Temporal dependency: mutable
state/side-effect dependency
Golden rule of dependency management:
Things that change more should depend
on things that change less often
4th aspect of complexity - Control flow
Control flow: hard to understand, reason
about, more cases to test
● Branching: if/else, case/when, etc.
● Looping: for/while loop, recursion, etc.
● Error handling: try/catch
5th aspect of complexity - Code size
5 aspects of complexity
● Shared mutable state
● Side-effects
● Dependencies
● Control flow
● Code size
● Reduce complexity
● Isolate complexity
Two ways to manage complexity
OOP helps with isolating complexity
OOP isolates shared mutable state
Objects don’t mutate state of each other directly but send messages to each other
instead
OOP isolate dependencies
Objects only depend on each other’s interface, not implementation which
generally changes more often
OOP isolate control flow
Objects’ internal control flow are isolated from each other. External control flow is
just about objects sending messages to each other.
Branching can be converted to polymorphism and isolated to object creation
phase.
But OOP does not reduce complexity!
The main problem with OOP is that it does not reduce global complexity, it just packages
complexity into isolated, smaller boxes.
● Increase global complexity by adding indirection to behavior
○ Raw data is inherently less complex than objects with behavior
● Increase dependencies: Adding dependencies between objects
● Increase control flow: As the control flow now are the messages between
objects
● Increase code size
OOP may even increase complexity!
● Writing software is about fighting complexity
● 2 types of complexity
● 5 aspects of complexity
● How OOP isolates complexity but does not reduce it
Recap
Part II
Software Design and Refactoring
Seeking complexity reduction with
functional programming
● Reduce shared mutable state
● Reduce side effects
● Reduce dependencies
● Reduce control flow
Functional programming helps reduce complexity
What is functional programming?
Programming with pure, composable functions
● Pure: Data flows from inputs to outputs
○ No mutations
○ No side-effects
● Composable: Functions are first-class, which means they can be treated as
data and transformed like data.
How to make tiramisu
1. Begin by assembling four large egg yolks, 1/2 cup sweet marsala wine, 16 ounces mascarpone
cheese, 12 ounces espresso, 2 tablespoons cocoa powder, 1 cup heavy cream, 1/2 cup granulated
sugar, and enough lady fingers to layer a 12x8 inch pan twice (40).
2. Stir two tablespoons of granulated sugar into the espresso and put it in the refrigerator to chill.
3. Whisk the egg yolks
4. Pour in the sugar and wine and whisked briefly until it was well blended.
5. Pour some water into a saucepan and set it over high heat until it began to boil.
6. Lowering the heat to medium, place the heatproof bowl over the water and stirred as the mixture began
to thicken and smooth out.
7. Whip the heavy cream until soft peaks.
8. Beat the mascarpone cheese until smooth and creamy.
9. Poured the mixture onto the cheese and beat
10. Fold in the whipped cream
11. Assemble the tiramisu.
○ Give the each ladyfinger cookie a one second soak on each side and then arrange it on the
pan
○ After the first layer of ladyfingers are done, use a spatula to spread half the cream mixture
over it.
○ Cover the cream layer with another layer of soaked ladyfingers.
○ The rest of the cream is spread onto the top and cocoa powder sifted over the surface to
cover the tiramisu.
12. The tiramisu was now complete and would require a four hour chill in the refrigerator.
Imperative: mutates data
def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa)
mixture = whisk(eggs)
beat(mixture, sugar1, wine)
whisk(mixture) # over steam
whip(cream)
beat(cheese)
beat(mixture, cheese)
fold(mixture, cream)
dissolve(sugar2, espresso)
soak(fingers, espresso, seconds: 2)
assemble(mixture, fingers)
sift(mixture, cocoa)
refrigerate(mixture)
mixture # it's now a tiramisu
end
OOP: mutates data
def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa)
mixture = eggs.whisk
mixture.beat(sugar1, wine) # mutates itself
mixture.whisk(steam: true)
cream.whip
cheese.beat
mixture.beat(cheese)
mixture.fold(cream)
espresso.dissolve(sugar2)
fingers.soak(espresso, seconds: 2)
mixture.assemble(fingers)
mixture.sift(cocoa)
mixture.refrigerate
mixture # it's now a tiramisu
end
Problems
● What are the states of the input arguments after
running this function?
● If I have two people to make this tiramisu, which
parts can be done in parallel?
● The steps are too complex, how do I refactor the
steps to sub-functions?
● If we miss a step, how do we debug the wrong
mixture state?
What if we can make tiramisu without mutating data?
The core of Functional Programming is thinking
about data-flow rather than control-flow
Functional: nested functions
def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa)
refrigerate(
sift(
assemble(
fold(
beat(
whisk( # over steam
beat(beat(eggs), sugar1, wine)
),
beat(cheese)
),
whip(cream)
),
soak(fingers, dissolve(sugar2, espresso), seconds: 2)
),
cocoa
)
)
end
Which parts can be done in parallel?
Which parts must be done sequentially?
Functional: named constants
def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa)
beaten_eggs = beat(eggs)
mixture = beat(beaten_eggs, sugar1, wine)
whisked = whisk(mixture)
beaten_cheese = beat(cheese)
cheese_mixture = beat(whisked, beaten_cheese)
whipped_cream = whip(cream)
folded_mixture = fold(cheese_mixture, whipped_cream)
sweet_espresso = dissolve(sugar2, espresso)
wet_fingers = soak(fingers, sweet_espresso, seconds: 2)
assembled = assemble(folded_mixture, wet_fingers)
complete = sift(assembled, cocoa)
ready_tiramisu = refrigerate(complete)
ready_tiramisu
end
Benefits
No hidden state → explicit dependency → obvious error
Benefits (cont.)
● Each step can be tested in isolation without mocking
● Easier to debug, just put a breakpoint between 2 steps and check the input
and output of each function
● The pipeline can be parallelized and refactored easily. Any group of steps will
have a clear set of inputs and outputs.
● Reduce shared mutable state: pure functions don’t mutate state
● Reduce side effects: pure functions don’t create side effects
● Reduce dependencies: zero time dependency, explicit dependencies
between steps
● Reduce control flow: no loop, no if/else
Functional programming helps reduce complexity
Also, can functional and object oriented be mixed?
Functional: OO syntax - object returns new version of itself
def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa)
whisked = eggs
.beat(sugar1)
.beat(wine)
.whisk
cheese_mixture = cheese.beat(whisked)
folded_mixture = cream
.whip
.fold(cheese_mixture)
wet_fingers = espresso
.dissolve(sugar2)
.soak(fingers, seconds: 2)
ready_tiramisu = folded_mixture
.assemble(wet_fingers)
.sift(cocoa)
.refrigerate
ready_tiramisu
end
Part II
Software Design and RefactoringCombining the best of OOP and FP
Part IV
Functional core, object oriented shell
Refactoring is about reducing or isolating complexity
-- Thanh Dinh
Object oriented programming makes code understandable
by encapsulating (isolating) moving parts (complexity).
Functional programming makes code understandable by
minimizing (reducing) moving parts (complexity).
-- Michael Feathers
What if we can get the best of both worlds?
All code can be classified into two distinct roles: code that
does work (algorithms) and code that coordinates work
(coordinators).
-- John Sonmez
Example
We need to design a game that has
● Human has health
● Monster can attack human
● When a group of humans is near a monster, the monster will find human with
least health to attack
● When a human is attacked, its health is reduced based on monster's Attack
attribute - human’s Defense attribute
The game also needs to handle physics, input and rendering, etc.
Traditional OO design
class Monster
attr_accessor id, position, health, attributes
def attack(humans)
attacked_human = humans.min { |h| abs(h.position - monster.position) }
attacked_human.health -= min(attributes.atk - attacked_human.attributes.dfs, 0)
end
def render; end
def physics; end
end
class Human
attr_accessor id, position, health, attributes
def render; end
def physics; end
end
Problems
● Mutable states make it very hard to debug and reason about
● Tangled dependencies: Monster class now depends on Human class
○ As most real world requirements involve multiple objects, this is unavoidable
● Bloated classes: more requirements mean the classes get bigger and bigger
Functional programming deals with values; imperative
programming deals with objects
-- Alex Stepanov, Elements of Programming
Functional Core - immutable values
class PositionData < Value.new(x, y); end
class HealthData < Value.new(health); end
class AttributesData < Value.new(atk, dfs); end
class Monster < Value.new(
id: Integer,
position: PositionData,
health: HealthData,
attributes: AttributesData
)
end
class Human < Value.new(
id: Integer,
position: PositionData,
health: HealthData,
attributes: AttributesData
)
end
Functional core - pure functions for behaviors
class DamageService
def self.attack(monsters, humans)
monsters.reduce([]) do |attacked_humans, monster|
attacked_human = humans.min { |h| abs(h.position - monster.position) }
attacked_humans << attacked_human
.merge_new(health: attacked_human.health - min(monster.atk - attacked_human.dfs, 0))
attacked_humans
end
return humans.merge(attacked_humans)
end
end
OOP shell - objects
require DamageService, InputHandler, Renderer, PhysicsProcessor # etc.
class Environment # Storing states and communicate with other objects
attr_accessor humans: HumanCollection,
monsters: MonsterCollection
def process_damage
humans = DamageService.attack(monsters, humans)
end
def process_input; end # Coordinate with InputHandler
def process_physics; end # Coordinate with PhysicsProcessor
def render; end # Coordinate with Renderer
def run
loop do
process_input
process_damage
process_physics
render
end
end
end
Refactoring: reducing/isolating complexity
Mutations, side effects, dependencies, control flow can either be minimized or
isolated. We are doing both with this architecture.
● Reduce mutations by changing the core to functional. The only parts that still
have mutations are in the OO shell → Mutations are isolated
● Reduce unnecessary side effects by changing the core to functional. The
only parts that still have side effects are in the OO shell → Side effects are
isolated
● Reduce dependencies by moving to functional. Isolate dependencies to OO
shell.
● Number of control flows: Isolated inside the functional core
Benefits
● Testability: Trivial and very fast to unit test the core, minimal number of
integration tests needed for the coordinators
● Reliability: Validation can be easily added to value classes, ensure the
system is always in a valid state. Side effects and exceptions are isolated
within coordinator classes.
● Readability: Functional core has no dependency and self-contained → very
easy to read and understand in isolation
Benefits (cont.)
● Extensibility: Very easy to add new or update existing behavior without
worrying about changing the behavior since the core has no side effects and
no dependency.
● Scalability: Functional core can be put on parallel threads easily as there is
no shared data. Coordinator objects can also be moved to
distributed/microservice model easily as messaging is done through
serializable values.
● OOP is not about class and inheritance
● Software design is complex
● 2 ways to manage complexity: reduce and isolate
● OOP helps isolate complexity
● FP helps reduce complexity
● Best of both world: Functional Core Imperative Shell architecture
Takeaways
References
● The forgotten history of OOP (https://medium.com/javascript-scene/the-forgotten-history-of-oop-
88d71b9b2d9f)
● OO programming, a personal disaster (https://medium.com/@brianwill/object-
oriented-programming-a-personal-disaster-1b044c2383ab)
● What functional programming is all about
(http://www.lihaoyi.com/post/WhatsFunctionalProgrammingAllAbout.html)
● Boundaries (https://www.destroyallsoftware.com/talks/boundaries)
● Oh composable worlds (https://www.youtube.com/watch?v=SfWR3dKnFIo)
Questions?

More Related Content

What's hot

Grokking TechTalk #35: Efficient spellchecking
Grokking TechTalk #35: Efficient spellcheckingGrokking TechTalk #35: Efficient spellchecking
Grokking TechTalk #35: Efficient spellcheckingGrokking VN
 
Grokking Techtalk: Problem solving for sw engineers
Grokking Techtalk: Problem solving for sw engineersGrokking Techtalk: Problem solving for sw engineers
Grokking Techtalk: Problem solving for sw engineers9diov
 
Tiki.vn - How we scale as a tech startup
Tiki.vn - How we scale as a tech startupTiki.vn - How we scale as a tech startup
Tiki.vn - How we scale as a tech startupTung Ns
 
Thiết kế hệ thống E-Commerce yêu cầu mở rộng
Thiết kế hệ thống E-Commerce yêu cầu mở rộngThiết kế hệ thống E-Commerce yêu cầu mở rộng
Thiết kế hệ thống E-Commerce yêu cầu mở rộngNguyen Minh Quang
 
Distributed Transaction in Microservice
Distributed Transaction in MicroserviceDistributed Transaction in Microservice
Distributed Transaction in MicroserviceNghia Minh
 
Using ClickHouse for Experimentation
Using ClickHouse for ExperimentationUsing ClickHouse for Experimentation
Using ClickHouse for ExperimentationGleb Kanterov
 
Storing State Forever: Why It Can Be Good For Your Analytics
Storing State Forever: Why It Can Be Good For Your AnalyticsStoring State Forever: Why It Can Be Good For Your Analytics
Storing State Forever: Why It Can Be Good For Your AnalyticsYaroslav Tkachenko
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPSeungmo Koo
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDBMike Dirolf
 
Next-generation MMORPG service architecture
Next-generation MMORPG service architectureNext-generation MMORPG service architecture
Next-generation MMORPG service architectureJongwon Kim
 
Apache Kafka – (Pattern and) Anti-Pattern
Apache Kafka – (Pattern and) Anti-PatternApache Kafka – (Pattern and) Anti-Pattern
Apache Kafka – (Pattern and) Anti-Patternconfluent
 
MongoDB WiredTiger Internals: Journey To Transactions
MongoDB WiredTiger Internals: Journey To TransactionsMongoDB WiredTiger Internals: Journey To Transactions
MongoDB WiredTiger Internals: Journey To TransactionsMydbops
 
Reddit/Quora Software System Design
Reddit/Quora Software System DesignReddit/Quora Software System Design
Reddit/Quora Software System DesignElia Ahadi
 
실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략YEONG-CHEON YOU
 
게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCP게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCPSeungmo Koo
 
Introduction to Redis
Introduction to RedisIntroduction to Redis
Introduction to RedisArnab Mitra
 
Kafka Intro With Simple Java Producer Consumers
Kafka Intro With Simple Java Producer ConsumersKafka Intro With Simple Java Producer Consumers
Kafka Intro With Simple Java Producer ConsumersJean-Paul Azar
 
Updated: Should you be using an Event Driven Architecture
Updated: Should you be using an Event Driven ArchitectureUpdated: Should you be using an Event Driven Architecture
Updated: Should you be using an Event Driven ArchitectureJeppe Cramon
 
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델Seungmo Koo
 
Lets make a better react form
Lets make a better react formLets make a better react form
Lets make a better react formYao Nien Chung
 

What's hot (20)

Grokking TechTalk #35: Efficient spellchecking
Grokking TechTalk #35: Efficient spellcheckingGrokking TechTalk #35: Efficient spellchecking
Grokking TechTalk #35: Efficient spellchecking
 
Grokking Techtalk: Problem solving for sw engineers
Grokking Techtalk: Problem solving for sw engineersGrokking Techtalk: Problem solving for sw engineers
Grokking Techtalk: Problem solving for sw engineers
 
Tiki.vn - How we scale as a tech startup
Tiki.vn - How we scale as a tech startupTiki.vn - How we scale as a tech startup
Tiki.vn - How we scale as a tech startup
 
Thiết kế hệ thống E-Commerce yêu cầu mở rộng
Thiết kế hệ thống E-Commerce yêu cầu mở rộngThiết kế hệ thống E-Commerce yêu cầu mở rộng
Thiết kế hệ thống E-Commerce yêu cầu mở rộng
 
Distributed Transaction in Microservice
Distributed Transaction in MicroserviceDistributed Transaction in Microservice
Distributed Transaction in Microservice
 
Using ClickHouse for Experimentation
Using ClickHouse for ExperimentationUsing ClickHouse for Experimentation
Using ClickHouse for Experimentation
 
Storing State Forever: Why It Can Be Good For Your Analytics
Storing State Forever: Why It Can Be Good For Your AnalyticsStoring State Forever: Why It Can Be Good For Your Analytics
Storing State Forever: Why It Can Be Good For Your Analytics
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCP
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDB
 
Next-generation MMORPG service architecture
Next-generation MMORPG service architectureNext-generation MMORPG service architecture
Next-generation MMORPG service architecture
 
Apache Kafka – (Pattern and) Anti-Pattern
Apache Kafka – (Pattern and) Anti-PatternApache Kafka – (Pattern and) Anti-Pattern
Apache Kafka – (Pattern and) Anti-Pattern
 
MongoDB WiredTiger Internals: Journey To Transactions
MongoDB WiredTiger Internals: Journey To TransactionsMongoDB WiredTiger Internals: Journey To Transactions
MongoDB WiredTiger Internals: Journey To Transactions
 
Reddit/Quora Software System Design
Reddit/Quora Software System DesignReddit/Quora Software System Design
Reddit/Quora Software System Design
 
실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략
 
게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCP게임서버프로그래밍 #1 - IOCP
게임서버프로그래밍 #1 - IOCP
 
Introduction to Redis
Introduction to RedisIntroduction to Redis
Introduction to Redis
 
Kafka Intro With Simple Java Producer Consumers
Kafka Intro With Simple Java Producer ConsumersKafka Intro With Simple Java Producer Consumers
Kafka Intro With Simple Java Producer Consumers
 
Updated: Should you be using an Event Driven Architecture
Updated: Should you be using an Event Driven ArchitectureUpdated: Should you be using an Event Driven Architecture
Updated: Should you be using an Event Driven Architecture
 
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
 
Lets make a better react form
Lets make a better react formLets make a better react form
Lets make a better react form
 

Similar to Grokking Techtalk #37: Software design and refactoring

Structured Software Design
Structured Software DesignStructured Software Design
Structured Software DesignGiorgio Zoppi
 
Effects, Coeffects & Subscriptions: a pit of success for SPAs
Effects, Coeffects & Subscriptions: a pit of success for SPAsEffects, Coeffects & Subscriptions: a pit of success for SPAs
Effects, Coeffects & Subscriptions: a pit of success for SPAsManuel Rivero
 
Cis 1403 lab1- the process of programming
Cis 1403 lab1- the process of programmingCis 1403 lab1- the process of programming
Cis 1403 lab1- the process of programmingHamad Odhabi
 
Effects, coeffects & subscriptions: a pit of success for SPAs Socracan18
Effects, coeffects & subscriptions: a pit of success for SPAs Socracan18Effects, coeffects & subscriptions: a pit of success for SPAs Socracan18
Effects, coeffects & subscriptions: a pit of success for SPAs Socracan18Manuel Rivero
 
Writing clean scientific software Murphy cleancoding
Writing clean scientific software Murphy cleancodingWriting clean scientific software Murphy cleancoding
Writing clean scientific software Murphy cleancodingsaber tabatabaee
 
Try the monad!
Try the monad!Try the monad!
Try the monad!Luis Muniz
 
Application development with Python - Desktop application
Application development with Python - Desktop applicationApplication development with Python - Desktop application
Application development with Python - Desktop applicationBao Long Nguyen Dang
 
Share the insight of ServiceInsight
Share the insight of ServiceInsightShare the insight of ServiceInsight
Share the insight of ServiceInsightParticular Software
 
Single Responsibility Principle
Single Responsibility PrincipleSingle Responsibility Principle
Single Responsibility PrincipleBADR
 
4 coding from algorithms
4 coding from algorithms4 coding from algorithms
4 coding from algorithmshccit
 
Top Tips Every Notes Developer Needs To Know
Top Tips Every Notes Developer Needs To KnowTop Tips Every Notes Developer Needs To Know
Top Tips Every Notes Developer Needs To KnowKathy Brown
 
Gatling - Bordeaux JUG
Gatling - Bordeaux JUGGatling - Bordeaux JUG
Gatling - Bordeaux JUGslandelle
 
Basics of Programming - A Review Guide
Basics of Programming - A Review GuideBasics of Programming - A Review Guide
Basics of Programming - A Review GuideBenjamin Kissinger
 
The pragmatic programmer
The pragmatic programmerThe pragmatic programmer
The pragmatic programmerLeylimYaln
 
DevOps Days Vancouver 2014 Slides
DevOps Days Vancouver 2014 SlidesDevOps Days Vancouver 2014 Slides
DevOps Days Vancouver 2014 SlidesAlex Cruise
 

Similar to Grokking Techtalk #37: Software design and refactoring (20)

Structured Software Design
Structured Software DesignStructured Software Design
Structured Software Design
 
Algorithms overview
Algorithms overviewAlgorithms overview
Algorithms overview
 
Effects, Coeffects & Subscriptions: a pit of success for SPAs
Effects, Coeffects & Subscriptions: a pit of success for SPAsEffects, Coeffects & Subscriptions: a pit of success for SPAs
Effects, Coeffects & Subscriptions: a pit of success for SPAs
 
Cis 1403 lab1- the process of programming
Cis 1403 lab1- the process of programmingCis 1403 lab1- the process of programming
Cis 1403 lab1- the process of programming
 
Effects, coeffects & subscriptions: a pit of success for SPAs Socracan18
Effects, coeffects & subscriptions: a pit of success for SPAs Socracan18Effects, coeffects & subscriptions: a pit of success for SPAs Socracan18
Effects, coeffects & subscriptions: a pit of success for SPAs Socracan18
 
Writing clean scientific software Murphy cleancoding
Writing clean scientific software Murphy cleancodingWriting clean scientific software Murphy cleancoding
Writing clean scientific software Murphy cleancoding
 
Try the monad!
Try the monad!Try the monad!
Try the monad!
 
Application development with Python - Desktop application
Application development with Python - Desktop applicationApplication development with Python - Desktop application
Application development with Python - Desktop application
 
01 Programming Fundamentals.pptx
01 Programming Fundamentals.pptx01 Programming Fundamentals.pptx
01 Programming Fundamentals.pptx
 
Share the insight of ServiceInsight
Share the insight of ServiceInsightShare the insight of ServiceInsight
Share the insight of ServiceInsight
 
Single Responsibility Principle
Single Responsibility PrincipleSingle Responsibility Principle
Single Responsibility Principle
 
C++ good tutorial
C++ good tutorialC++ good tutorial
C++ good tutorial
 
4 coding from algorithms
4 coding from algorithms4 coding from algorithms
4 coding from algorithms
 
Top Tips Every Notes Developer Needs To Know
Top Tips Every Notes Developer Needs To KnowTop Tips Every Notes Developer Needs To Know
Top Tips Every Notes Developer Needs To Know
 
MPP-UPNVJ
MPP-UPNVJMPP-UPNVJ
MPP-UPNVJ
 
Gatling - Bordeaux JUG
Gatling - Bordeaux JUGGatling - Bordeaux JUG
Gatling - Bordeaux JUG
 
Basics of Programming - A Review Guide
Basics of Programming - A Review GuideBasics of Programming - A Review Guide
Basics of Programming - A Review Guide
 
The pragmatic programmer
The pragmatic programmerThe pragmatic programmer
The pragmatic programmer
 
Slide 01
Slide 01Slide 01
Slide 01
 
DevOps Days Vancouver 2014 Slides
DevOps Days Vancouver 2014 SlidesDevOps Days Vancouver 2014 Slides
DevOps Days Vancouver 2014 Slides
 

More from Grokking VN

Grokking Techtalk #46: Lessons from years hacking and defending Vietnamese banks
Grokking Techtalk #46: Lessons from years hacking and defending Vietnamese banksGrokking Techtalk #46: Lessons from years hacking and defending Vietnamese banks
Grokking Techtalk #46: Lessons from years hacking and defending Vietnamese banksGrokking VN
 
Grokking Techtalk #45: First Principles Thinking
Grokking Techtalk #45: First Principles ThinkingGrokking Techtalk #45: First Principles Thinking
Grokking Techtalk #45: First Principles ThinkingGrokking VN
 
Grokking Techtalk #42: Engineering challenges on building data platform for M...
Grokking Techtalk #42: Engineering challenges on building data platform for M...Grokking Techtalk #42: Engineering challenges on building data platform for M...
Grokking Techtalk #42: Engineering challenges on building data platform for M...Grokking VN
 
Grokking Techtalk #43: Payment gateway demystified
Grokking Techtalk #43: Payment gateway demystifiedGrokking Techtalk #43: Payment gateway demystified
Grokking Techtalk #43: Payment gateway demystifiedGrokking VN
 
Grokking Techtalk #40: AWS’s philosophy on designing MLOps platform
Grokking Techtalk #40: AWS’s philosophy on designing MLOps platformGrokking Techtalk #40: AWS’s philosophy on designing MLOps platform
Grokking Techtalk #40: AWS’s philosophy on designing MLOps platformGrokking VN
 
Grokking Techtalk #39: Gossip protocol and applications
Grokking Techtalk #39: Gossip protocol and applicationsGrokking Techtalk #39: Gossip protocol and applications
Grokking Techtalk #39: Gossip protocol and applicationsGrokking VN
 
Grokking Techtalk #38: Escape Analysis in Go compiler
 Grokking Techtalk #38: Escape Analysis in Go compiler Grokking Techtalk #38: Escape Analysis in Go compiler
Grokking Techtalk #38: Escape Analysis in Go compilerGrokking VN
 
Grokking Techtalk #34: K8S On-premise: Incident & Lesson Learned ZaloPay Mer...
 Grokking Techtalk #34: K8S On-premise: Incident & Lesson Learned ZaloPay Mer... Grokking Techtalk #34: K8S On-premise: Incident & Lesson Learned ZaloPay Mer...
Grokking Techtalk #34: K8S On-premise: Incident & Lesson Learned ZaloPay Mer...Grokking VN
 
Grokking TechTalk #33: Architecture of AI-First Systems - Engineering for Big...
Grokking TechTalk #33: Architecture of AI-First Systems - Engineering for Big...Grokking TechTalk #33: Architecture of AI-First Systems - Engineering for Big...
Grokking TechTalk #33: Architecture of AI-First Systems - Engineering for Big...Grokking VN
 
Grokking TechTalk #30: From App to Ecosystem: Lessons Learned at Scale
Grokking TechTalk #30: From App to Ecosystem: Lessons Learned at ScaleGrokking TechTalk #30: From App to Ecosystem: Lessons Learned at Scale
Grokking TechTalk #30: From App to Ecosystem: Lessons Learned at ScaleGrokking VN
 
Grokking TechTalk #29: Building Realtime Metrics Platform at LinkedIn
Grokking TechTalk #29: Building Realtime Metrics Platform at LinkedInGrokking TechTalk #29: Building Realtime Metrics Platform at LinkedIn
Grokking TechTalk #29: Building Realtime Metrics Platform at LinkedInGrokking VN
 
Grokking TechTalk #27: Optimal Binary Search Tree
Grokking TechTalk #27: Optimal Binary Search TreeGrokking TechTalk #27: Optimal Binary Search Tree
Grokking TechTalk #27: Optimal Binary Search TreeGrokking VN
 
Grokking TechTalk #26: Kotlin, Understand the Magic
Grokking TechTalk #26: Kotlin, Understand the MagicGrokking TechTalk #26: Kotlin, Understand the Magic
Grokking TechTalk #26: Kotlin, Understand the MagicGrokking VN
 
Grokking TechTalk #26: Compare ios and android platform
Grokking TechTalk #26: Compare ios and android platformGrokking TechTalk #26: Compare ios and android platform
Grokking TechTalk #26: Compare ios and android platformGrokking VN
 
Grokking TechTalk #24: Thiết kế hệ thống Background Job Queue bằng Ruby & Pos...
Grokking TechTalk #24: Thiết kế hệ thống Background Job Queue bằng Ruby & Pos...Grokking TechTalk #24: Thiết kế hệ thống Background Job Queue bằng Ruby & Pos...
Grokking TechTalk #24: Thiết kế hệ thống Background Job Queue bằng Ruby & Pos...Grokking VN
 
Grokking TechTalk #24: Kafka's principles and protocols
Grokking TechTalk #24: Kafka's principles and protocolsGrokking TechTalk #24: Kafka's principles and protocols
Grokking TechTalk #24: Kafka's principles and protocolsGrokking VN
 
Grokking TechTalk #21: Deep Learning in Computer Vision
Grokking TechTalk #21: Deep Learning in Computer VisionGrokking TechTalk #21: Deep Learning in Computer Vision
Grokking TechTalk #21: Deep Learning in Computer VisionGrokking VN
 
Grokking TechTalk #20: PostgreSQL Internals 101
Grokking TechTalk #20: PostgreSQL Internals 101Grokking TechTalk #20: PostgreSQL Internals 101
Grokking TechTalk #20: PostgreSQL Internals 101Grokking VN
 
Grokking TechTalk #19: Software Development Cycle In The International Moneta...
Grokking TechTalk #19: Software Development Cycle In The International Moneta...Grokking TechTalk #19: Software Development Cycle In The International Moneta...
Grokking TechTalk #19: Software Development Cycle In The International Moneta...Grokking VN
 
Grokking TechTalk #18B: Giới thiệu về Viễn thông Di động
Grokking TechTalk #18B:  Giới thiệu về Viễn thông Di độngGrokking TechTalk #18B:  Giới thiệu về Viễn thông Di động
Grokking TechTalk #18B: Giới thiệu về Viễn thông Di độngGrokking VN
 

More from Grokking VN (20)

Grokking Techtalk #46: Lessons from years hacking and defending Vietnamese banks
Grokking Techtalk #46: Lessons from years hacking and defending Vietnamese banksGrokking Techtalk #46: Lessons from years hacking and defending Vietnamese banks
Grokking Techtalk #46: Lessons from years hacking and defending Vietnamese banks
 
Grokking Techtalk #45: First Principles Thinking
Grokking Techtalk #45: First Principles ThinkingGrokking Techtalk #45: First Principles Thinking
Grokking Techtalk #45: First Principles Thinking
 
Grokking Techtalk #42: Engineering challenges on building data platform for M...
Grokking Techtalk #42: Engineering challenges on building data platform for M...Grokking Techtalk #42: Engineering challenges on building data platform for M...
Grokking Techtalk #42: Engineering challenges on building data platform for M...
 
Grokking Techtalk #43: Payment gateway demystified
Grokking Techtalk #43: Payment gateway demystifiedGrokking Techtalk #43: Payment gateway demystified
Grokking Techtalk #43: Payment gateway demystified
 
Grokking Techtalk #40: AWS’s philosophy on designing MLOps platform
Grokking Techtalk #40: AWS’s philosophy on designing MLOps platformGrokking Techtalk #40: AWS’s philosophy on designing MLOps platform
Grokking Techtalk #40: AWS’s philosophy on designing MLOps platform
 
Grokking Techtalk #39: Gossip protocol and applications
Grokking Techtalk #39: Gossip protocol and applicationsGrokking Techtalk #39: Gossip protocol and applications
Grokking Techtalk #39: Gossip protocol and applications
 
Grokking Techtalk #38: Escape Analysis in Go compiler
 Grokking Techtalk #38: Escape Analysis in Go compiler Grokking Techtalk #38: Escape Analysis in Go compiler
Grokking Techtalk #38: Escape Analysis in Go compiler
 
Grokking Techtalk #34: K8S On-premise: Incident & Lesson Learned ZaloPay Mer...
 Grokking Techtalk #34: K8S On-premise: Incident & Lesson Learned ZaloPay Mer... Grokking Techtalk #34: K8S On-premise: Incident & Lesson Learned ZaloPay Mer...
Grokking Techtalk #34: K8S On-premise: Incident & Lesson Learned ZaloPay Mer...
 
Grokking TechTalk #33: Architecture of AI-First Systems - Engineering for Big...
Grokking TechTalk #33: Architecture of AI-First Systems - Engineering for Big...Grokking TechTalk #33: Architecture of AI-First Systems - Engineering for Big...
Grokking TechTalk #33: Architecture of AI-First Systems - Engineering for Big...
 
Grokking TechTalk #30: From App to Ecosystem: Lessons Learned at Scale
Grokking TechTalk #30: From App to Ecosystem: Lessons Learned at ScaleGrokking TechTalk #30: From App to Ecosystem: Lessons Learned at Scale
Grokking TechTalk #30: From App to Ecosystem: Lessons Learned at Scale
 
Grokking TechTalk #29: Building Realtime Metrics Platform at LinkedIn
Grokking TechTalk #29: Building Realtime Metrics Platform at LinkedInGrokking TechTalk #29: Building Realtime Metrics Platform at LinkedIn
Grokking TechTalk #29: Building Realtime Metrics Platform at LinkedIn
 
Grokking TechTalk #27: Optimal Binary Search Tree
Grokking TechTalk #27: Optimal Binary Search TreeGrokking TechTalk #27: Optimal Binary Search Tree
Grokking TechTalk #27: Optimal Binary Search Tree
 
Grokking TechTalk #26: Kotlin, Understand the Magic
Grokking TechTalk #26: Kotlin, Understand the MagicGrokking TechTalk #26: Kotlin, Understand the Magic
Grokking TechTalk #26: Kotlin, Understand the Magic
 
Grokking TechTalk #26: Compare ios and android platform
Grokking TechTalk #26: Compare ios and android platformGrokking TechTalk #26: Compare ios and android platform
Grokking TechTalk #26: Compare ios and android platform
 
Grokking TechTalk #24: Thiết kế hệ thống Background Job Queue bằng Ruby & Pos...
Grokking TechTalk #24: Thiết kế hệ thống Background Job Queue bằng Ruby & Pos...Grokking TechTalk #24: Thiết kế hệ thống Background Job Queue bằng Ruby & Pos...
Grokking TechTalk #24: Thiết kế hệ thống Background Job Queue bằng Ruby & Pos...
 
Grokking TechTalk #24: Kafka's principles and protocols
Grokking TechTalk #24: Kafka's principles and protocolsGrokking TechTalk #24: Kafka's principles and protocols
Grokking TechTalk #24: Kafka's principles and protocols
 
Grokking TechTalk #21: Deep Learning in Computer Vision
Grokking TechTalk #21: Deep Learning in Computer VisionGrokking TechTalk #21: Deep Learning in Computer Vision
Grokking TechTalk #21: Deep Learning in Computer Vision
 
Grokking TechTalk #20: PostgreSQL Internals 101
Grokking TechTalk #20: PostgreSQL Internals 101Grokking TechTalk #20: PostgreSQL Internals 101
Grokking TechTalk #20: PostgreSQL Internals 101
 
Grokking TechTalk #19: Software Development Cycle In The International Moneta...
Grokking TechTalk #19: Software Development Cycle In The International Moneta...Grokking TechTalk #19: Software Development Cycle In The International Moneta...
Grokking TechTalk #19: Software Development Cycle In The International Moneta...
 
Grokking TechTalk #18B: Giới thiệu về Viễn thông Di động
Grokking TechTalk #18B:  Giới thiệu về Viễn thông Di độngGrokking TechTalk #18B:  Giới thiệu về Viễn thông Di động
Grokking TechTalk #18B: Giới thiệu về Viễn thông Di động
 

Recently uploaded

Heart Disease Prediction using machine learning.pptx
Heart Disease Prediction using machine learning.pptxHeart Disease Prediction using machine learning.pptx
Heart Disease Prediction using machine learning.pptxPoojaBan
 
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxDecoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxJoão Esperancinha
 
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube ExchangerStudy on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube ExchangerAnamika Sarkar
 
Oxy acetylene welding presentation note.
Oxy acetylene welding presentation note.Oxy acetylene welding presentation note.
Oxy acetylene welding presentation note.eptoze12
 
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)dollysharma2066
 
Application of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptxApplication of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptx959SahilShah
 
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)Dr SOUNDIRARAJ N
 
Comparative Analysis of Text Summarization Techniques
Comparative Analysis of Text Summarization TechniquesComparative Analysis of Text Summarization Techniques
Comparative Analysis of Text Summarization Techniquesugginaramesh
 
computer application and construction management
computer application and construction managementcomputer application and construction management
computer application and construction managementMariconPadriquez1
 
8251 universal synchronous asynchronous receiver transmitter
8251 universal synchronous asynchronous receiver transmitter8251 universal synchronous asynchronous receiver transmitter
8251 universal synchronous asynchronous receiver transmitterShivangiSharma879191
 
Arduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptArduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptSAURABHKUMAR892774
 
CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdf
CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdfCCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdf
CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdfAsst.prof M.Gokilavani
 
Correctly Loading Incremental Data at Scale
Correctly Loading Incremental Data at ScaleCorrectly Loading Incremental Data at Scale
Correctly Loading Incremental Data at ScaleAlluxio, Inc.
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024hassan khalil
 
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdfCCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdfAsst.prof M.Gokilavani
 
Churning of Butter, Factors affecting .
Churning of Butter, Factors affecting  .Churning of Butter, Factors affecting  .
Churning of Butter, Factors affecting .Satyam Kumar
 
Instrumentation, measurement and control of bio process parameters ( Temperat...
Instrumentation, measurement and control of bio process parameters ( Temperat...Instrumentation, measurement and control of bio process parameters ( Temperat...
Instrumentation, measurement and control of bio process parameters ( Temperat...121011101441
 

Recently uploaded (20)

Heart Disease Prediction using machine learning.pptx
Heart Disease Prediction using machine learning.pptxHeart Disease Prediction using machine learning.pptx
Heart Disease Prediction using machine learning.pptx
 
POWER SYSTEMS-1 Complete notes examples
POWER SYSTEMS-1 Complete notes  examplesPOWER SYSTEMS-1 Complete notes  examples
POWER SYSTEMS-1 Complete notes examples
 
Call Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCR
Call Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCRCall Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCR
Call Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCR
 
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxDecoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
 
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube ExchangerStudy on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
 
Oxy acetylene welding presentation note.
Oxy acetylene welding presentation note.Oxy acetylene welding presentation note.
Oxy acetylene welding presentation note.
 
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
 
Application of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptxApplication of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptx
 
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)
 
Comparative Analysis of Text Summarization Techniques
Comparative Analysis of Text Summarization TechniquesComparative Analysis of Text Summarization Techniques
Comparative Analysis of Text Summarization Techniques
 
computer application and construction management
computer application and construction managementcomputer application and construction management
computer application and construction management
 
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptxExploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
 
8251 universal synchronous asynchronous receiver transmitter
8251 universal synchronous asynchronous receiver transmitter8251 universal synchronous asynchronous receiver transmitter
8251 universal synchronous asynchronous receiver transmitter
 
Arduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptArduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.ppt
 
CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdf
CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdfCCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdf
CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdf
 
Correctly Loading Incremental Data at Scale
Correctly Loading Incremental Data at ScaleCorrectly Loading Incremental Data at Scale
Correctly Loading Incremental Data at Scale
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024
 
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdfCCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
 
Churning of Butter, Factors affecting .
Churning of Butter, Factors affecting  .Churning of Butter, Factors affecting  .
Churning of Butter, Factors affecting .
 
Instrumentation, measurement and control of bio process parameters ( Temperat...
Instrumentation, measurement and control of bio process parameters ( Temperat...Instrumentation, measurement and control of bio process parameters ( Temperat...
Instrumentation, measurement and control of bio process parameters ( Temperat...
 

Grokking Techtalk #37: Software design and refactoring

  • 1. Software design and refactoring Cracking complexity by sending messages and building pipelines
  • 3. Let’s start with a puzzle...
  • 4. Happy company class Employee; end class Engineer < Employee def do_work; end end class ProductAnalyst < Employee def do_work; end end class Company attr_accessor :members end def main thong_ng = Engineer.new khai = ProductAnalyst.new company = Company.new company.members = [thong_ng, khai, ...] company.members.each(&:do_work) end
  • 5. How about Son? class Engineer; def write_code; end; end class ProductAnalyst; def design_product; end; end company.engineers.each(&:write_code) company.product_analysts.each(&:design_product) # How about Son = ??? son = SometimesEngineerSometimesProductAnalyst.new son.write_code son.design_product # 3 months later... son.becomes(ProductAnalyst) # ???
  • 6. Agenda 1. OOP is not about class and inheritance 2. Software design is about cracking complexity 3. Functional programming is about reducing complexity 4. Functional core, imperative shell
  • 7. ● Traditional way of thinking about OOP is incomplete OOP is not about class and inheritance
  • 8. Class and inheritance are language features and implementation details, not essential parts of object- oriented design.
  • 9. Can we use OOP without class or inheritance?
  • 10. OOP without class module Employee def do_work; end end module Engineer def write_code; end end module ProductAnalyst def design_product; end end son = Object.new.extend(Employee) son.extend(Engineer) son.extend(ProductAnalyst)
  • 11. OOP without inheritance class Engineer; end class ProductAnalyst; end thong_ng = Employee.new(roles: [Engineer.new]) son = Employee.new(roles: [Engineer.new, ProductAnalyst.new]) “Favor composition over inheritance”
  • 12. Alan Kay’s OOP “OOP to me means only messaging, local retention and protection and hiding of state- process, and extreme late-binding of all things.” -- Alan Kay ● Message passing -> Interface is the only dependency between objects ● Local retention, protection and hiding of state-process -> Objects don’t know the internal details of each other ● Extreme late-binding of all things -> Object behaviors can be changed at any point in time No mention of class or inheritance at all!
  • 13. Ruby’s messages - everything is an object 1.to_s # returns "1" 1.send(:to_s) # returns "1" 1 + 1 == 1.send(:+, 1) # There is no Boolean class in Ruby true.class # returns TrueCLass if (1 == 1) 'true' end # There is no if/else in Smalltalk - control structures are messages (1 == 1).ifTrue do 'true' end (1 == 1).send(:ifTrue, &Proc.new { 'true' }) son.send(:extend, ProductAnalyst) Class A; end A.is_a?(Object) # returns true - classes are objects A whole program is just about objects sending messages to each other.
  • 14. What this means for software design When you design a program, don't confuse class with role (interface). ● Class: language feature to construct object with certain roles. An object can be created from a single class. ● Role: Messages an object with this role can reply to. An object can have multiple roles. An object’s roles can change during run time. Start with roles first: Employee role, Engineer role, ProductAnalyst role, Persistable role, Movable role, etc.
  • 15. The messages Think about the behaviors the program must support, in other words, the messages of each role: ● do_work → WorkingRole ● write_code → EngineeringRole ● design_product → ProductAnalysisRole And then, when we want concrete behavior, we supply them via Factory, Class or whatever the mechanism the language supports to construct objects. In pure OOP, class is just a type of factory.
  • 16. Recap ● OOP is not about class and inheritance ● OOP is about message sending
  • 17. Part II Software Design and Refactoring Software design is about cracking complexity
  • 18. Writing software is complex...
  • 21. As your software grows, complexity increases
  • 22. Complexity is the root of all evil ● Readability: It makes it hard to understand and reason about a program ● Reliability: Hard to reason about the program → hard to debug ● Reusability: Hard to turn code into reusable component ● Scalability: Hard to separate code that can run in parallel ● Testability: Hard to test code with too many dependencies
  • 23. Two types of complexity ● Essential complexity ○ Complexity inherent to the problem which can’t be removed e.g. Slack notification ● Accidental complexity ○ Complexity due to the choices made from a particular software design to solve the problem
  • 24. 5 aspects of complexity ● Shared mutable state ● Side-effects ● Dependencies ● Control flow ● Code size
  • 25. 1st aspect of complexity - mutable state ● Hard to reason about ● Implicit time dependency ● Explosion of state space ● Hard to parallelize
  • 26. 2nd aspect of complexity - side effects ● Async call ● UI render ● Network call, etc. Main problems: asynchronous and fallible
  • 27. 3rd aspect of complexity - Dependencies ● Class dependency: object creation dependency ● Interface dependency: messages dependency ● Temporal dependency: mutable state/side-effect dependency Golden rule of dependency management: Things that change more should depend on things that change less often
  • 28. 4th aspect of complexity - Control flow Control flow: hard to understand, reason about, more cases to test ● Branching: if/else, case/when, etc. ● Looping: for/while loop, recursion, etc. ● Error handling: try/catch
  • 29. 5th aspect of complexity - Code size
  • 30. 5 aspects of complexity ● Shared mutable state ● Side-effects ● Dependencies ● Control flow ● Code size
  • 31. ● Reduce complexity ● Isolate complexity Two ways to manage complexity
  • 32. OOP helps with isolating complexity
  • 33. OOP isolates shared mutable state Objects don’t mutate state of each other directly but send messages to each other instead
  • 34. OOP isolate dependencies Objects only depend on each other’s interface, not implementation which generally changes more often
  • 35. OOP isolate control flow Objects’ internal control flow are isolated from each other. External control flow is just about objects sending messages to each other. Branching can be converted to polymorphism and isolated to object creation phase.
  • 36. But OOP does not reduce complexity!
  • 37. The main problem with OOP is that it does not reduce global complexity, it just packages complexity into isolated, smaller boxes. ● Increase global complexity by adding indirection to behavior ○ Raw data is inherently less complex than objects with behavior ● Increase dependencies: Adding dependencies between objects ● Increase control flow: As the control flow now are the messages between objects ● Increase code size OOP may even increase complexity!
  • 38. ● Writing software is about fighting complexity ● 2 types of complexity ● 5 aspects of complexity ● How OOP isolates complexity but does not reduce it Recap
  • 39. Part II Software Design and Refactoring Seeking complexity reduction with functional programming
  • 40. ● Reduce shared mutable state ● Reduce side effects ● Reduce dependencies ● Reduce control flow Functional programming helps reduce complexity
  • 41. What is functional programming? Programming with pure, composable functions ● Pure: Data flows from inputs to outputs ○ No mutations ○ No side-effects ● Composable: Functions are first-class, which means they can be treated as data and transformed like data.
  • 42. How to make tiramisu 1. Begin by assembling four large egg yolks, 1/2 cup sweet marsala wine, 16 ounces mascarpone cheese, 12 ounces espresso, 2 tablespoons cocoa powder, 1 cup heavy cream, 1/2 cup granulated sugar, and enough lady fingers to layer a 12x8 inch pan twice (40). 2. Stir two tablespoons of granulated sugar into the espresso and put it in the refrigerator to chill. 3. Whisk the egg yolks 4. Pour in the sugar and wine and whisked briefly until it was well blended. 5. Pour some water into a saucepan and set it over high heat until it began to boil. 6. Lowering the heat to medium, place the heatproof bowl over the water and stirred as the mixture began to thicken and smooth out. 7. Whip the heavy cream until soft peaks. 8. Beat the mascarpone cheese until smooth and creamy. 9. Poured the mixture onto the cheese and beat 10. Fold in the whipped cream 11. Assemble the tiramisu. ○ Give the each ladyfinger cookie a one second soak on each side and then arrange it on the pan ○ After the first layer of ladyfingers are done, use a spatula to spread half the cream mixture over it. ○ Cover the cream layer with another layer of soaked ladyfingers. ○ The rest of the cream is spread onto the top and cocoa powder sifted over the surface to cover the tiramisu. 12. The tiramisu was now complete and would require a four hour chill in the refrigerator.
  • 43. Imperative: mutates data def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa) mixture = whisk(eggs) beat(mixture, sugar1, wine) whisk(mixture) # over steam whip(cream) beat(cheese) beat(mixture, cheese) fold(mixture, cream) dissolve(sugar2, espresso) soak(fingers, espresso, seconds: 2) assemble(mixture, fingers) sift(mixture, cocoa) refrigerate(mixture) mixture # it's now a tiramisu end
  • 44. OOP: mutates data def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa) mixture = eggs.whisk mixture.beat(sugar1, wine) # mutates itself mixture.whisk(steam: true) cream.whip cheese.beat mixture.beat(cheese) mixture.fold(cream) espresso.dissolve(sugar2) fingers.soak(espresso, seconds: 2) mixture.assemble(fingers) mixture.sift(cocoa) mixture.refrigerate mixture # it's now a tiramisu end
  • 45. Problems ● What are the states of the input arguments after running this function? ● If I have two people to make this tiramisu, which parts can be done in parallel? ● The steps are too complex, how do I refactor the steps to sub-functions? ● If we miss a step, how do we debug the wrong mixture state?
  • 46. What if we can make tiramisu without mutating data?
  • 47. The core of Functional Programming is thinking about data-flow rather than control-flow
  • 48. Functional: nested functions def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa) refrigerate( sift( assemble( fold( beat( whisk( # over steam beat(beat(eggs), sugar1, wine) ), beat(cheese) ), whip(cream) ), soak(fingers, dissolve(sugar2, espresso), seconds: 2) ), cocoa ) ) end
  • 49. Which parts can be done in parallel?
  • 50. Which parts must be done sequentially?
  • 51. Functional: named constants def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa) beaten_eggs = beat(eggs) mixture = beat(beaten_eggs, sugar1, wine) whisked = whisk(mixture) beaten_cheese = beat(cheese) cheese_mixture = beat(whisked, beaten_cheese) whipped_cream = whip(cream) folded_mixture = fold(cheese_mixture, whipped_cream) sweet_espresso = dissolve(sugar2, espresso) wet_fingers = soak(fingers, sweet_espresso, seconds: 2) assembled = assemble(folded_mixture, wet_fingers) complete = sift(assembled, cocoa) ready_tiramisu = refrigerate(complete) ready_tiramisu end
  • 52. Benefits No hidden state → explicit dependency → obvious error
  • 53. Benefits (cont.) ● Each step can be tested in isolation without mocking ● Easier to debug, just put a breakpoint between 2 steps and check the input and output of each function ● The pipeline can be parallelized and refactored easily. Any group of steps will have a clear set of inputs and outputs.
  • 54. ● Reduce shared mutable state: pure functions don’t mutate state ● Reduce side effects: pure functions don’t create side effects ● Reduce dependencies: zero time dependency, explicit dependencies between steps ● Reduce control flow: no loop, no if/else Functional programming helps reduce complexity
  • 55. Also, can functional and object oriented be mixed?
  • 56. Functional: OO syntax - object returns new version of itself def make_tiramisu(eggs, sugar1, wine, cheese, cream, fingers, espresso, sugar2, cocoa) whisked = eggs .beat(sugar1) .beat(wine) .whisk cheese_mixture = cheese.beat(whisked) folded_mixture = cream .whip .fold(cheese_mixture) wet_fingers = espresso .dissolve(sugar2) .soak(fingers, seconds: 2) ready_tiramisu = folded_mixture .assemble(wet_fingers) .sift(cocoa) .refrigerate ready_tiramisu end
  • 57. Part II Software Design and RefactoringCombining the best of OOP and FP
  • 58. Part IV Functional core, object oriented shell
  • 59.
  • 60. Refactoring is about reducing or isolating complexity -- Thanh Dinh Object oriented programming makes code understandable by encapsulating (isolating) moving parts (complexity). Functional programming makes code understandable by minimizing (reducing) moving parts (complexity). -- Michael Feathers
  • 61. What if we can get the best of both worlds?
  • 62.
  • 63. All code can be classified into two distinct roles: code that does work (algorithms) and code that coordinates work (coordinators). -- John Sonmez
  • 64. Example We need to design a game that has ● Human has health ● Monster can attack human ● When a group of humans is near a monster, the monster will find human with least health to attack ● When a human is attacked, its health is reduced based on monster's Attack attribute - human’s Defense attribute The game also needs to handle physics, input and rendering, etc.
  • 65. Traditional OO design class Monster attr_accessor id, position, health, attributes def attack(humans) attacked_human = humans.min { |h| abs(h.position - monster.position) } attacked_human.health -= min(attributes.atk - attacked_human.attributes.dfs, 0) end def render; end def physics; end end class Human attr_accessor id, position, health, attributes def render; end def physics; end end
  • 66. Problems ● Mutable states make it very hard to debug and reason about ● Tangled dependencies: Monster class now depends on Human class ○ As most real world requirements involve multiple objects, this is unavoidable ● Bloated classes: more requirements mean the classes get bigger and bigger
  • 67. Functional programming deals with values; imperative programming deals with objects -- Alex Stepanov, Elements of Programming
  • 68. Functional Core - immutable values class PositionData < Value.new(x, y); end class HealthData < Value.new(health); end class AttributesData < Value.new(atk, dfs); end class Monster < Value.new( id: Integer, position: PositionData, health: HealthData, attributes: AttributesData ) end class Human < Value.new( id: Integer, position: PositionData, health: HealthData, attributes: AttributesData ) end
  • 69. Functional core - pure functions for behaviors class DamageService def self.attack(monsters, humans) monsters.reduce([]) do |attacked_humans, monster| attacked_human = humans.min { |h| abs(h.position - monster.position) } attacked_humans << attacked_human .merge_new(health: attacked_human.health - min(monster.atk - attacked_human.dfs, 0)) attacked_humans end return humans.merge(attacked_humans) end end
  • 70. OOP shell - objects require DamageService, InputHandler, Renderer, PhysicsProcessor # etc. class Environment # Storing states and communicate with other objects attr_accessor humans: HumanCollection, monsters: MonsterCollection def process_damage humans = DamageService.attack(monsters, humans) end def process_input; end # Coordinate with InputHandler def process_physics; end # Coordinate with PhysicsProcessor def render; end # Coordinate with Renderer def run loop do process_input process_damage process_physics render end end end
  • 71. Refactoring: reducing/isolating complexity Mutations, side effects, dependencies, control flow can either be minimized or isolated. We are doing both with this architecture. ● Reduce mutations by changing the core to functional. The only parts that still have mutations are in the OO shell → Mutations are isolated ● Reduce unnecessary side effects by changing the core to functional. The only parts that still have side effects are in the OO shell → Side effects are isolated ● Reduce dependencies by moving to functional. Isolate dependencies to OO shell. ● Number of control flows: Isolated inside the functional core
  • 72. Benefits ● Testability: Trivial and very fast to unit test the core, minimal number of integration tests needed for the coordinators ● Reliability: Validation can be easily added to value classes, ensure the system is always in a valid state. Side effects and exceptions are isolated within coordinator classes. ● Readability: Functional core has no dependency and self-contained → very easy to read and understand in isolation
  • 73. Benefits (cont.) ● Extensibility: Very easy to add new or update existing behavior without worrying about changing the behavior since the core has no side effects and no dependency. ● Scalability: Functional core can be put on parallel threads easily as there is no shared data. Coordinator objects can also be moved to distributed/microservice model easily as messaging is done through serializable values.
  • 74. ● OOP is not about class and inheritance ● Software design is complex ● 2 ways to manage complexity: reduce and isolate ● OOP helps isolate complexity ● FP helps reduce complexity ● Best of both world: Functional Core Imperative Shell architecture Takeaways
  • 75. References ● The forgotten history of OOP (https://medium.com/javascript-scene/the-forgotten-history-of-oop- 88d71b9b2d9f) ● OO programming, a personal disaster (https://medium.com/@brianwill/object- oriented-programming-a-personal-disaster-1b044c2383ab) ● What functional programming is all about (http://www.lihaoyi.com/post/WhatsFunctionalProgrammingAllAbout.html) ● Boundaries (https://www.destroyallsoftware.com/talks/boundaries) ● Oh composable worlds (https://www.youtube.com/watch?v=SfWR3dKnFIo)

Editor's Notes

  1. At first, it was nice. It was really fast to build any new feature. It is easy to debug and modify. However, 4 years passed. Holistics’ code base is getting more and more complex, it is hard to change anything without breaking something. The engineers are afraid to change the code that he doesn’t understand. New features are getting slower and slower to implement. Does this story sound familiar to you?
  2. Do you think that OOP design is easy? Let’s start with an OOP puzzle...
  3. Do you think that OOP design is easy? Traditional way of thinking about OOP makes
  4. How many of you agree with this? Disagree?
  5. Cut into 2 parts
  6. In Ruby, almost everything is an object. An integer is an object. A boolean is an object. This is inspired from Smalltalk, a language created by Alan Kay. In Smalltak, object does not execute “method” but send messages to each other. Even if/else is about sending message to boolean object. Even a class is an object.
  7. OOP is just one way to think about software design. Let’s actually go deeper into software design and understand it.
  8. It is already hard with the existing solution. Each new feature adds exponentially more complexity as the new complexity multiplies existing complexity.
  9. This is why OOP makes sense. Depending on interface that generally changes less often than implementation.
  10. In Holistics, a better design is when one reduces some aspects of complexity. Also, the order is from more important to less important.
  11. There is another way that can actually reduce complexity. That’s functional programming.
  12. You can see that in each step, the data is mutated. At each step, the code implicitly produces a new program state. At the end of the function, almost all inputs are no longer the same. It is hard to know in terms of the orders between each step, which one depends on each other. In other words, is it ok to switch the order of “whip(cream)” and “beat(cheese)”?
  13. This is slightly better as this isolate the mutations inside “mixture” object.
  14. All the functions in here are pure functions, which don’t mutate the input arguments. The structure of the code makes it obvious which is needed before which.
  15. We can break this code into multiple parts, and each part will have clear inputs and outputs. Pure functions easily compose.
  16. OOP is just one way to think about software design. Let’s actually go deeper into software design and understand it.
  17. The architecture was introduced in 2012 by Gary Bernhard in his “Boundaries” talk.
  18. The code looks simple at first glance, but there are many problems with it.