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

Microservices Part 3 Service Mesh and Kafka
Microservices Part 3 Service Mesh and KafkaMicroservices Part 3 Service Mesh and Kafka
Microservices Part 3 Service Mesh and KafkaAraf Karsh Hamid
 
Grokking TechTalk #35: Efficient spellchecking
Grokking TechTalk #35: Efficient spellcheckingGrokking TechTalk #35: Efficient spellchecking
Grokking TechTalk #35: Efficient spellcheckingGrokking 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 #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
 
Scaling a Core Banking Engine Using Apache Kafka | Peter Dudbridge, Thought M...
Scaling a Core Banking Engine Using Apache Kafka | Peter Dudbridge, Thought M...Scaling a Core Banking Engine Using Apache Kafka | Peter Dudbridge, Thought M...
Scaling a Core Banking Engine Using Apache Kafka | Peter Dudbridge, Thought M...HostedbyConfluent
 
Scalability, Availability & Stability Patterns
Scalability, Availability & Stability PatternsScalability, Availability & Stability Patterns
Scalability, Availability & Stability PatternsJonas Bonér
 
Agile Scrum Presentation-Detailed
Agile Scrum Presentation-DetailedAgile Scrum Presentation-Detailed
Agile Scrum Presentation-DetailedPrashaanth T R
 
Distributed Transaction in Microservice
Distributed Transaction in MicroserviceDistributed Transaction in Microservice
Distributed Transaction in MicroserviceNghia Minh
 
How to Break the Requirements into User Stories
How to Break the Requirements into User StoriesHow to Break the Requirements into User Stories
How to Break the Requirements into User StoriesShriKant Vashishtha
 
Architecture Sustaining LINE Sticker services
Architecture Sustaining LINE Sticker servicesArchitecture Sustaining LINE Sticker services
Architecture Sustaining LINE Sticker servicesLINE Corporation
 
Networking in Java with NIO and Netty
Networking in Java with NIO and NettyNetworking in Java with NIO and Netty
Networking in Java with NIO and NettyConstantine Slisenka
 
Dual write strategies for microservices
Dual write strategies for microservicesDual write strategies for microservices
Dual write strategies for microservicesBilgin Ibryam
 
Prometheus Overview
Prometheus OverviewPrometheus Overview
Prometheus OverviewBrian Brazil
 
Prometheus design and philosophy
Prometheus design and philosophy   Prometheus design and philosophy
Prometheus design and philosophy Docker, Inc.
 
Introduction To Agile
Introduction To AgileIntroduction To Agile
Introduction To AgileKnoldus Inc.
 
Agile & SCRUM basics
Agile & SCRUM basicsAgile & SCRUM basics
Agile & SCRUM basicsArun R
 
Kafka streams windowing behind the curtain
Kafka streams windowing behind the curtain Kafka streams windowing behind the curtain
Kafka streams windowing behind the curtain confluent
 
Agile, User Stories, Domain Driven Design
Agile, User Stories, Domain Driven DesignAgile, User Stories, Domain Driven Design
Agile, User Stories, Domain Driven DesignAraf Karsh Hamid
 

What's hot (20)

Microservices Part 3 Service Mesh and Kafka
Microservices Part 3 Service Mesh and KafkaMicroservices Part 3 Service Mesh and Kafka
Microservices Part 3 Service Mesh and Kafka
 
Grokking TechTalk #35: Efficient spellchecking
Grokking TechTalk #35: Efficient spellcheckingGrokking TechTalk #35: Efficient spellchecking
Grokking TechTalk #35: Efficient spellchecking
 
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 #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
 
Scaling a Core Banking Engine Using Apache Kafka | Peter Dudbridge, Thought M...
Scaling a Core Banking Engine Using Apache Kafka | Peter Dudbridge, Thought M...Scaling a Core Banking Engine Using Apache Kafka | Peter Dudbridge, Thought M...
Scaling a Core Banking Engine Using Apache Kafka | Peter Dudbridge, Thought M...
 
Scalability, Availability & Stability Patterns
Scalability, Availability & Stability PatternsScalability, Availability & Stability Patterns
Scalability, Availability & Stability Patterns
 
Agile Release & Iteration Planning
Agile Release & Iteration Planning   Agile Release & Iteration Planning
Agile Release & Iteration Planning
 
Agile Scrum Presentation-Detailed
Agile Scrum Presentation-DetailedAgile Scrum Presentation-Detailed
Agile Scrum Presentation-Detailed
 
Distributed Transaction in Microservice
Distributed Transaction in MicroserviceDistributed Transaction in Microservice
Distributed Transaction in Microservice
 
How to Break the Requirements into User Stories
How to Break the Requirements into User StoriesHow to Break the Requirements into User Stories
How to Break the Requirements into User Stories
 
Architecture Sustaining LINE Sticker services
Architecture Sustaining LINE Sticker servicesArchitecture Sustaining LINE Sticker services
Architecture Sustaining LINE Sticker services
 
Networking in Java with NIO and Netty
Networking in Java with NIO and NettyNetworking in Java with NIO and Netty
Networking in Java with NIO and Netty
 
Dual write strategies for microservices
Dual write strategies for microservicesDual write strategies for microservices
Dual write strategies for microservices
 
Prometheus Overview
Prometheus OverviewPrometheus Overview
Prometheus Overview
 
Prometheus design and philosophy
Prometheus design and philosophy   Prometheus design and philosophy
Prometheus design and philosophy
 
Agile Methodology
Agile MethodologyAgile Methodology
Agile Methodology
 
Introduction To Agile
Introduction To AgileIntroduction To Agile
Introduction To Agile
 
Agile & SCRUM basics
Agile & SCRUM basicsAgile & SCRUM basics
Agile & SCRUM basics
 
Kafka streams windowing behind the curtain
Kafka streams windowing behind the curtain Kafka streams windowing behind the curtain
Kafka streams windowing behind the curtain
 
Agile, User Stories, Domain Driven Design
Agile, User Stories, Domain Driven DesignAgile, User Stories, Domain Driven Design
Agile, User Stories, Domain Driven Design
 

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 #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 #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 #31: Asynchronous Communications
Grokking TechTalk #31: Asynchronous CommunicationsGrokking TechTalk #31: Asynchronous Communications
Grokking TechTalk #31: Asynchronous CommunicationsGrokking 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
 
Grokking TechTalk #18B: VoIP Architecture For Telecommunications
Grokking TechTalk #18B: VoIP Architecture For TelecommunicationsGrokking TechTalk #18B: VoIP Architecture For Telecommunications
Grokking TechTalk #18B: VoIP Architecture For TelecommunicationsGrokking 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 #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 #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 #31: Asynchronous Communications
Grokking TechTalk #31: Asynchronous CommunicationsGrokking TechTalk #31: Asynchronous Communications
Grokking TechTalk #31: Asynchronous Communications
 
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
 
Grokking TechTalk #18B: VoIP Architecture For Telecommunications
Grokking TechTalk #18B: VoIP Architecture For TelecommunicationsGrokking TechTalk #18B: VoIP Architecture For Telecommunications
Grokking TechTalk #18B: VoIP Architecture For Telecommunications
 

Recently uploaded

litvinenko_Henry_Intrusion_Hong-Kong_2024.pdf
litvinenko_Henry_Intrusion_Hong-Kong_2024.pdflitvinenko_Henry_Intrusion_Hong-Kong_2024.pdf
litvinenko_Henry_Intrusion_Hong-Kong_2024.pdfAlexander Litvinenko
 
Fundamentals of Internet of Things (IoT) Part-2
Fundamentals of Internet of Things (IoT) Part-2Fundamentals of Internet of Things (IoT) Part-2
Fundamentals of Internet of Things (IoT) Part-2ChandrakantDivate1
 
5G and 6G refer to generations of mobile network technology, each representin...
5G and 6G refer to generations of mobile network technology, each representin...5G and 6G refer to generations of mobile network technology, each representin...
5G and 6G refer to generations of mobile network technology, each representin...archanaece3
 
Basics of Relay for Engineering Students
Basics of Relay for Engineering StudentsBasics of Relay for Engineering Students
Basics of Relay for Engineering Studentskannan348865
 
8th International Conference on Soft Computing, Mathematics and Control (SMC ...
8th International Conference on Soft Computing, Mathematics and Control (SMC ...8th International Conference on Soft Computing, Mathematics and Control (SMC ...
8th International Conference on Soft Computing, Mathematics and Control (SMC ...josephjonse
 
History of Indian Railways - the story of Growth & Modernization
History of Indian Railways - the story of Growth & ModernizationHistory of Indian Railways - the story of Growth & Modernization
History of Indian Railways - the story of Growth & ModernizationEmaan Sharma
 
Introduction to Artificial Intelligence ( AI)
Introduction to Artificial Intelligence ( AI)Introduction to Artificial Intelligence ( AI)
Introduction to Artificial Intelligence ( AI)ChandrakantDivate1
 
Call for Papers - Journal of Electrical Systems (JES), E-ISSN: 1112-5209, ind...
Call for Papers - Journal of Electrical Systems (JES), E-ISSN: 1112-5209, ind...Call for Papers - Journal of Electrical Systems (JES), E-ISSN: 1112-5209, ind...
Call for Papers - Journal of Electrical Systems (JES), E-ISSN: 1112-5209, ind...Christo Ananth
 
Fundamentals of Structure in C Programming
Fundamentals of Structure in C ProgrammingFundamentals of Structure in C Programming
Fundamentals of Structure in C ProgrammingChandrakantDivate1
 
Overview of Transformation in Computer Graphics
Overview of Transformation in Computer GraphicsOverview of Transformation in Computer Graphics
Overview of Transformation in Computer GraphicsChandrakantDivate1
 
Computer Graphics Introduction To Curves
Computer Graphics Introduction To CurvesComputer Graphics Introduction To Curves
Computer Graphics Introduction To CurvesChandrakantDivate1
 
Study of Computer Hardware System using Block Diagram
Study of Computer Hardware System using Block DiagramStudy of Computer Hardware System using Block Diagram
Study of Computer Hardware System using Block DiagramChandrakantDivate1
 
Involute of a circle,Square, pentagon,HexagonInvolute_Engineering Drawing.pdf
Involute of a circle,Square, pentagon,HexagonInvolute_Engineering Drawing.pdfInvolute of a circle,Square, pentagon,HexagonInvolute_Engineering Drawing.pdf
Involute of a circle,Square, pentagon,HexagonInvolute_Engineering Drawing.pdfJNTUA
 
Independent Solar-Powered Electric Vehicle Charging Station
Independent Solar-Powered Electric Vehicle Charging StationIndependent Solar-Powered Electric Vehicle Charging Station
Independent Solar-Powered Electric Vehicle Charging Stationsiddharthteach18
 
What is Coordinate Measuring Machine? CMM Types, Features, Functions
What is Coordinate Measuring Machine? CMM Types, Features, FunctionsWhat is Coordinate Measuring Machine? CMM Types, Features, Functions
What is Coordinate Measuring Machine? CMM Types, Features, FunctionsVIEW
 
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdf
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdfInstruct Nirmaana 24-Smart and Lean Construction Through Technology.pdf
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdfEr.Sonali Nasikkar
 
Convergence of Robotics and Gen AI offers excellent opportunities for Entrepr...
Convergence of Robotics and Gen AI offers excellent opportunities for Entrepr...Convergence of Robotics and Gen AI offers excellent opportunities for Entrepr...
Convergence of Robotics and Gen AI offers excellent opportunities for Entrepr...ssuserdfc773
 
01-vogelsanger-stanag-4178-ed-2-the-new-nato-standard-for-nitrocellulose-test...
01-vogelsanger-stanag-4178-ed-2-the-new-nato-standard-for-nitrocellulose-test...01-vogelsanger-stanag-4178-ed-2-the-new-nato-standard-for-nitrocellulose-test...
01-vogelsanger-stanag-4178-ed-2-the-new-nato-standard-for-nitrocellulose-test...AshwaniAnuragi1
 
Presentation on Slab, Beam, Column, and Foundation/Footing
Presentation on Slab,  Beam, Column, and Foundation/FootingPresentation on Slab,  Beam, Column, and Foundation/Footing
Presentation on Slab, Beam, Column, and Foundation/FootingEr. Suman Jyoti
 

Recently uploaded (20)

litvinenko_Henry_Intrusion_Hong-Kong_2024.pdf
litvinenko_Henry_Intrusion_Hong-Kong_2024.pdflitvinenko_Henry_Intrusion_Hong-Kong_2024.pdf
litvinenko_Henry_Intrusion_Hong-Kong_2024.pdf
 
Signal Processing and Linear System Analysis
Signal Processing and Linear System AnalysisSignal Processing and Linear System Analysis
Signal Processing and Linear System Analysis
 
Fundamentals of Internet of Things (IoT) Part-2
Fundamentals of Internet of Things (IoT) Part-2Fundamentals of Internet of Things (IoT) Part-2
Fundamentals of Internet of Things (IoT) Part-2
 
5G and 6G refer to generations of mobile network technology, each representin...
5G and 6G refer to generations of mobile network technology, each representin...5G and 6G refer to generations of mobile network technology, each representin...
5G and 6G refer to generations of mobile network technology, each representin...
 
Basics of Relay for Engineering Students
Basics of Relay for Engineering StudentsBasics of Relay for Engineering Students
Basics of Relay for Engineering Students
 
8th International Conference on Soft Computing, Mathematics and Control (SMC ...
8th International Conference on Soft Computing, Mathematics and Control (SMC ...8th International Conference on Soft Computing, Mathematics and Control (SMC ...
8th International Conference on Soft Computing, Mathematics and Control (SMC ...
 
History of Indian Railways - the story of Growth & Modernization
History of Indian Railways - the story of Growth & ModernizationHistory of Indian Railways - the story of Growth & Modernization
History of Indian Railways - the story of Growth & Modernization
 
Introduction to Artificial Intelligence ( AI)
Introduction to Artificial Intelligence ( AI)Introduction to Artificial Intelligence ( AI)
Introduction to Artificial Intelligence ( AI)
 
Call for Papers - Journal of Electrical Systems (JES), E-ISSN: 1112-5209, ind...
Call for Papers - Journal of Electrical Systems (JES), E-ISSN: 1112-5209, ind...Call for Papers - Journal of Electrical Systems (JES), E-ISSN: 1112-5209, ind...
Call for Papers - Journal of Electrical Systems (JES), E-ISSN: 1112-5209, ind...
 
Fundamentals of Structure in C Programming
Fundamentals of Structure in C ProgrammingFundamentals of Structure in C Programming
Fundamentals of Structure in C Programming
 
Overview of Transformation in Computer Graphics
Overview of Transformation in Computer GraphicsOverview of Transformation in Computer Graphics
Overview of Transformation in Computer Graphics
 
Computer Graphics Introduction To Curves
Computer Graphics Introduction To CurvesComputer Graphics Introduction To Curves
Computer Graphics Introduction To Curves
 
Study of Computer Hardware System using Block Diagram
Study of Computer Hardware System using Block DiagramStudy of Computer Hardware System using Block Diagram
Study of Computer Hardware System using Block Diagram
 
Involute of a circle,Square, pentagon,HexagonInvolute_Engineering Drawing.pdf
Involute of a circle,Square, pentagon,HexagonInvolute_Engineering Drawing.pdfInvolute of a circle,Square, pentagon,HexagonInvolute_Engineering Drawing.pdf
Involute of a circle,Square, pentagon,HexagonInvolute_Engineering Drawing.pdf
 
Independent Solar-Powered Electric Vehicle Charging Station
Independent Solar-Powered Electric Vehicle Charging StationIndependent Solar-Powered Electric Vehicle Charging Station
Independent Solar-Powered Electric Vehicle Charging Station
 
What is Coordinate Measuring Machine? CMM Types, Features, Functions
What is Coordinate Measuring Machine? CMM Types, Features, FunctionsWhat is Coordinate Measuring Machine? CMM Types, Features, Functions
What is Coordinate Measuring Machine? CMM Types, Features, Functions
 
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdf
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdfInstruct Nirmaana 24-Smart and Lean Construction Through Technology.pdf
Instruct Nirmaana 24-Smart and Lean Construction Through Technology.pdf
 
Convergence of Robotics and Gen AI offers excellent opportunities for Entrepr...
Convergence of Robotics and Gen AI offers excellent opportunities for Entrepr...Convergence of Robotics and Gen AI offers excellent opportunities for Entrepr...
Convergence of Robotics and Gen AI offers excellent opportunities for Entrepr...
 
01-vogelsanger-stanag-4178-ed-2-the-new-nato-standard-for-nitrocellulose-test...
01-vogelsanger-stanag-4178-ed-2-the-new-nato-standard-for-nitrocellulose-test...01-vogelsanger-stanag-4178-ed-2-the-new-nato-standard-for-nitrocellulose-test...
01-vogelsanger-stanag-4178-ed-2-the-new-nato-standard-for-nitrocellulose-test...
 
Presentation on Slab, Beam, Column, and Foundation/Footing
Presentation on Slab,  Beam, Column, and Foundation/FootingPresentation on Slab,  Beam, Column, and Foundation/Footing
Presentation on Slab, Beam, Column, and Foundation/Footing
 

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.