SlideShare a Scribd company logo
@sandimetz Jul 2017
Go Ahead
Make a Mess
Sandi Metz
@sandimetz Jul 2017
Project Life Cycle
@sandimetz Jul 2017
Satisfaction
Timeline
Start Beta 1.0 2.0 Today
@sandimetz Jul 2017
Satisfaction
Timeline
Start Beta 1.0 2.0 Today
@sandimetz Jul 2017
Satisfaction
@sandimetz Jul 2017
Satisfaction
Those who cannot remember the past
are condemned to repeat it.
@sandimetz Jul 2017
@sandimetz Jul 2017
Satisfaction
@sandimetz Jul 2017
The Mess
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
Knowledge
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
Dependencies
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
Stability
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
Hope
@sandimetz Jul 2017
@sandimetz Jul 2017
Satisfaction
Timeline
Start Beta 1.0 2.0 Today
@sandimetz Jul 2017
Timeline
Start Beta 1.0 2.0 Today
Object-Oriented Design
@sandimetz Jul 2017
Timeline
Start Beta 1.0 2.0 Today
Stop worrying
and
learn to love the mess
Object-Oriented Design
@sandimetz Jul 2017
@sandimetz Jul 2017
Label the Knowledge
@sandimetz Jul 2017
Label the Knowledge
Complicate the Code
@sandimetz Jul 2017
Label the Knowledge
Complicate the Code
Isolate the Instability
@sandimetz Jul 2017
Label the Knowledge
Complicate the Code
Isolate the Instability
Manage the Mess
@sandimetz Jul 2017
Example #1
Label the Knowledge
@sandimetz Jul 2017
Example #1
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
				#	...	
						#	which	eventually	return	
				cost	
		end
@sandimetz Jul 2017
Example #1
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
				#	...	
						#	which	eventually	return	
				cost	
		end
@sandimetz Jul 2017
Example #1
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
				#	...	
						#	which	eventually	return	
				cost	
		end
@sandimetz Jul 2017
Example #1
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
				#	...	
						#	which	eventually	return	
				cost	
		end
@sandimetz Jul 2017
Example #1
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
				#	...	
						#	which	eventually	return	
				cost	
		end
@sandimetz Jul 2017
Example #1
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
				#	...	
						#	which	eventually	return	
				cost	
		end	
			
MESS
@sandimetz Jul 2017
Example #1
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
				#	...	
						#	which	eventually	return	
				cost	
		end	
			
Omega Mess
@sandimetz Jul 2017
@sandimetz Jul 2017
Omega Mess
@sandimetz Jul 2017
Omega Mess
End of the Line
@sandimetz Jul 2017
Omega Mess
End of the Line
No Dependencies
@sandimetz Jul 2017
Omega Mess
End of the Line
No Dependencies
No Dependents
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
Knowledge Stability
@sandimetz Jul 2017
External
Knowledge Stability
@sandimetz Jul 2017
Internal
External
Knowledge Stability
@sandimetz Jul 2017
Internal
External
Knowledge Stability
Low
High
@sandimetz Jul 2017
Internal
External
Knowledge Stability
Low
High
@sandimetz Jul 2017
Internal
External
Knowledge Stability
Low
High
@sandimetz Jul 2017
Internal
External
Knowledge Stability
Low
High
@sandimetz Jul 2017
Internal
External
Knowledge Stability
Low
High
@sandimetz Jul 2017
Internal
External
Knowledge Stability
Low
High
@sandimetz Jul 2017
Internal
External
Knowledge Stability
Low
High
@sandimetz Jul 2017
Dependencies
Shock
@sandimetz Jul 2017
Dependencies
Shock
Game
@sandimetz Jul 2017
@sandimetz Jul 2017
Omega
@sandimetz Jul 2017
Omega
@sandimetz Jul 2017
@sandimetz Jul 2017
Omega Mess
@sandimetz Jul 2017
Omega Mess
Hides behind
the message
@sandimetz Jul 2017
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
						#	...	
						#	which	eventually	return	
				cost	
		end	
			
end
Example #1
@sandimetz Jul 2017
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
						#	...	
						#	which	eventually	return	
				cost	
		end	
			
end
It’s not about
the code
Example #1
@sandimetz Jul 2017
It’s
about
the
message
@sandimetz Jul 2017
@sandimetz Jul 2017
Interlude
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Public
API
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Public
API
Expose
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Public
API
Private
Behavior
Expose
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Public
API
Private
Behavior
Expose Hide
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Public
API
Private
Behavior
Dependencies
Expose Hide
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Public
API
Private
Behavior
Dependencies
Expose Hide
Minimize
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Public
API
Private
Behavior
Dependencies
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. cost calculation
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. cost calculation
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. cost calculation
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. cost calculation
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge Plot
1
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method (expose)
2. cost calculation
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method (expose)
2. cost calculation
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method (expose)
2. cost calculation
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge Plot
1
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge Plot
1
2
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method (expose)
2. cost calculation (hide)
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method (expose)
2. cost calculation (hide)
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method (expose)
2. cost calculation (hide)
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method (expose)
2. cost calculation (hide)
Game depends on
3. cost message
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge Plot
3
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. cost calculation
Game depends on
3. cost message (minimize)
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. cost calculation
Game depends on
3. cost message (minimize)
4. Shock class name
5. cost receiver
@sandimetz Jul 2017
Knowledge Plot
3
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge Plot
4 53
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge Plot
4 53
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge Plot
?
4 53
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. cost calculation
Game depends on
3. cost message (minimize)
4. Shock class name
5. cost receiver ???
@sandimetz Jul 2017
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
						#	...	
						#	which	eventually	return	
				cost	
		end	
			
end
Example #1
@sandimetz Jul 2017
What is the
future cost
of doing
nothing now?
@sandimetz Jul 2017
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
						#	...	
						#	which	eventually	return	
				cost	
		end	
			
end
Example #1
@sandimetz Jul 2017
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
						#	...	
						#	which	eventually	return	
				cost	
		end	
			
end
I would inject this dependency
Example #1
@sandimetz Jul 2017
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
						#	...	
						#	which	eventually	return	
				cost	
		end	
			
end
I would inject this dependency
I would neaten this mess
Example #1
@sandimetz Jul 2017
class	Game	
		def	shock_cost	
				Shock.new.cost	
		end	
end	
class	Shock	
		def	cost	
						#	lines	of	messy	math	
						#	...	
						#	which	eventually	return	
				cost	
		end	
			
end
I would inject this dependency
I would neaten this mess
You might not
Example #1
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
Example #2
Complicate the code
@sandimetz Jul 2017
Example #2
Complicate the code
Shocks vary in cost
@sandimetz Jul 2017
Example #2
class	Game	
		def	shock_cost(type)	
				Shock.new(type).cost	
		end	
end
@sandimetz Jul 2017
Example #2
class	Game	
		def	shock_cost(type)	
				Shock.new(type).cost	
		end	
end
@sandimetz Jul 2017
Example #2
class	Game	
		def	shock_cost(type)	
				Shock.new(type).cost	
		end	
end
@sandimetz Jul 2017
Example #2
class	Shock	
		attr_reader	:type	
		def	initialize(type)	#	...	
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
@sandimetz Jul 2017
Example #2
class	Shock	
		attr_reader	:type	
		def	initialize(type)	#	...	
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
@sandimetz Jul 2017
Example #2
class	Shock	
		attr_reader	:type	
		def	initialize(type)	#	...	
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
@sandimetz Jul 2017
Example #2
class	Shock	
		attr_reader	:type	
		def	initialize(type)	#	...	
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
@sandimetz Jul 2017
Example #2
class	Shock	
		attr_reader	:type	
		def	initialize(type)	#	...	
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
Omega?
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. cost calculation
3.
4.
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. cost calculation
3.
4.
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
Omega
Mess?
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
Omega
Mess?
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
Meta
Knowledge
@sandimetz Jul 2017
@sandimetz Jul 2017
Meta Knowledge
@sandimetz Jul 2017
Meta Knowledge
Knowledge
about
Knowledge
@sandimetz Jul 2017
@sandimetz Jul 2017
Meta Knowledge
@sandimetz Jul 2017
Meta Knowledge
The Domain
of Design
@sandimetz Jul 2017
@sandimetz Jul 2017
Interlude
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge Plot
2
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge Plot
2
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations (move)
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations (move)
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge Plot
3
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations (move)
3. four shock types (move)
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations (move)
3. four shock types (move)
4. which type gets what calculation
@sandimetz Jul 2017
Knowledge Plot
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge Plot
4
Stable Unstable
Within My Purpose
Outside of My Purpose
Expose Hide
Minimize Move
@sandimetz Jul 2017
Knowledge
Shock knows
1. cost method
2. four shock cost calculations (move)
3. four shock types (move)
4. which type gets what calculation (min)
@sandimetz Jul 2017
Preference
@sandimetz Jul 2017
Preference
Send a message
@sandimetz Jul 2017
Preference
Send a message
rather than
implement behavior
@sandimetz Jul 2017
Move it
@sandimetz Jul 2017
Move it
Find the message
@sandimetz Jul 2017
Move it
Find the message
(Create the object)
@sandimetz Jul 2017
Move it
Find the message
(Create the object)
Send the message
@sandimetz Jul 2017
@sandimetz Jul 2017
Example #3
Composition
@sandimetz Jul 2017
#3 Composition
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
@sandimetz Jul 2017
#3 Composition
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
@sandimetz Jul 2017
#3 Composition
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
@sandimetz Jul 2017
#3 Composition
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
What’s the message?
@sandimetz Jul 2017
#3 Composition
		def	cost	
				case	type	
				when	:front	
						someObligingObj.compute	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
@sandimetz Jul 2017
#3 Composition
		def	cost	
				case	type	
				when	:front	
						someObligingObj.compute	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
???
@sandimetz Jul 2017
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
#3 Composition
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end
@sandimetz Jul 2017
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
#3 Composition
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end
@sandimetz Jul 2017
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
#3 Composition
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end
Hide the
Mess
@sandimetz Jul 2017
		def	cost	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
#3 Composition
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end
@sandimetz Jul 2017
		def	cost	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
#3 Composition
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end
Send the
Message
@sandimetz Jul 2017
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
#3 Composition
@sandimetz Jul 2017
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
#3 Composition
@sandimetz Jul 2017
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
#3 Composition
@sandimetz Jul 2017
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly	different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
#3 Composition
Hide all
of the
Messes
@sandimetz Jul 2017
#3 Composition
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end	
class	RearShockCost	
		def	compute	
				#	slightly	changed	mess	
		end	
end	
#	etc
@sandimetz Jul 2017
#3 Composition
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end	
class	RearShockCost	
		def	compute	
				#	slightly	changed	mess	
		end	
end	
#	etc
@sandimetz Jul 2017
#3 Composition
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end	
class	RearShockCost	
		def	compute	
				#	slightly	changed	mess	
		end	
end	
#	etc
@sandimetz Jul 2017
#3 Composition
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end
@sandimetz Jul 2017
#3 Composition
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
Send
the
Message
@sandimetz Jul 2017
#3 Composition
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end
@sandimetz Jul 2017
#3 Composition
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
Really?
@sandimetz Jul 2017
Meta Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Meta Knowledge
Shock knows
1. cost method
2. four shock cost calculations
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Meta Knowledge
Shock knows
1. cost method
2. four ShockCostxx classes
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Meta Knowledge
Shock knows
1. cost method
2. four ShockCostxx classes
3. four shock types
4. which type gets what calculation
@sandimetz Jul 2017
Meta Knowledge
Shock knows
1. cost method
2. four ShockCostxx classes
3. four shock types
4. which type gets what class
@sandimetz Jul 2017
Good News
Calculations are isolated
@sandimetz Jul 2017
Bad News
Still have dependencies
@sandimetz Jul 2017
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
#3 Composition
@sandimetz Jul 2017
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
#3 Composition
@sandimetz Jul 2017
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
when	:front	
#3 Composition
@sandimetz Jul 2017
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
when	:foo	
		FooShockCost.new.compute
#3 Composition
@sandimetz Jul 2017
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
when	:foo	
		FooShockCost.new.compute
#3 Composition
@sandimetz Jul 2017
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
when	:foo	
		FooShockCost.new.compute
#3 Composition
Conventionoverconfiguration
@sandimetz Jul 2017
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
when	:foo	
		FooShockCost.new.compute
class_name	=	type.to_s.capitalize	+	"ShockCost"	
#3 Composition
Conventionoverconfiguration
@sandimetz Jul 2017
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
class_name	=	type.to_s.capitalize	+	"ShockCost"	
eval(class_name).new.compute
#3 Composition
Conventionoverconfiguration
when	:foo	
		FooShockCost.new.compute
@sandimetz Jul 2017
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
class_name	=	type.to_s.capitalize	+	"ShockCost"	
eval(class_name).new.compute	
Object.const_get(class_name).new.compute
#3 Composition
Conventionoverconfiguration
when	:foo	
		FooShockCost.new.compute
@sandimetz Jul 2017
class	Shock	
		def	cost(type)	
				case	type	
				when	:front	
						FrontShockCost.new.compute	
				when	:rear	
						RearShockCost.new.compute	
				when	:lefty	
						LeftyShockCost.new.compute	
				else	
						ShockCost.new.compute	
				end	
		end	
		#	...	
end	
class_name	=	type.to_s.capitalize	+	"ShockCost"	
eval(class_name).new.compute	
Object.const_get(class_name).new.compute	
class_name.constantize.new.compute	
#3 Composition
Conventionoverconfiguration
when	:foo	
		FooShockCost.new.compute
@sandimetz Jul 2017
Example #3
class	Shock	
		def	cost(type)	
	 		class_name	=	(type.to_s.capitalize	+	"ShockCost")	
	 		Object.const_get(class_name).new.compute	
		end	
end
@sandimetz Jul 2017
Example #3
class	Shock	
		def	cost(type)	
	 		class_name	=	(type.to_s.capitalize	+	"ShockCost")	
	 		Object.const_get(class_name).new.compute	
		end	
end
@sandimetz Jul 2017
Example #3
class	Shock	
		def	cost(type)	
	 		class_name	=	(type.to_s.capitalize	+	"ShockCost")	
	 		Object.const_get(class_name).new.compute	
		end	
end	
Factory
@sandimetz Jul 2017
We
<3
Factories
@sandimetz Jul 2017
Meta Knowledge
Shock knows
1. cost method
2. four ShockCostxx classes
3. four shock types
4. which type gets what class
@sandimetz Jul 2017
Meta Knowledge
Shock knows
1. cost method
2. four ShockCostxx classes
3. four shock types
4. which type gets what class
@sandimetz Jul 2017
Meta Knowledge
Shock knows
1. cost method
2. four ShockCostxx classes
3. four shock types
4. which type gets what class
@sandimetz Jul 2017
Meta Knowledge
Shock knows
1. cost method
2. four ShockCostxx classes
3. four shock types
4. which type gets what class
@sandimetz Jul 2017
Meta Knowledge
Shock knows
1. cost method
2. the convention
Before
@sandimetz Jul 2017
#3 Composition
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly		
						#		different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
Before
@sandimetz Jul 2017
#3 Composition
		def	cost	
				case	type	
				when	:front	
						#	the	original	mess	
				when	:rear	
						#	a	slightly		
						#		different	mess	
				when	:lefty	
						#	another	variant	
				else	
						#	and	so	on.	
				end	
		end
Many changes
affect this code
After
@sandimetz Jul 2017
Example #3
class	Shock	
		def	cost(type)	
	 		class_name	=	(type.to_s.capitalize	+	"ShockCost")	
	 		Object.const_get(class_name).new.compute	
		end	
end
After
@sandimetz Jul 2017
Example #3
class	Shock	
		def	cost(type)	
	 		class_name	=	(type.to_s.capitalize	+	"ShockCost")	
	 		Object.const_get(class_name).new.compute	
		end	
end
After
@sandimetz Jul 2017
Example #3
class	Shock	
		def	cost(type)	
	 		class_name	=	(type.to_s.capitalize	+	"ShockCost")	
	 		Object.const_get(class_name).new.compute	
		end	
		def	coster(type)	
				Object.const_get(type.to_s.capitalize	+	“ShockCost").new	
		end	
end
After
@sandimetz Jul 2017
Example #3
class	Shock	
		def	cost(type)	
				coster(type).compute	
		end	
		def	coster(type)	
				Object.const_get(type.to_s.capitalize	+	“ShockCost").new	
		end	
end
After
@sandimetz Jul 2017
Example #3
class	Shock	
		def	cost(type)	
				coster(type).compute	
		end	
		def	coster(type)	
				Object.const_get(type.to_s.capitalize	+	“ShockCost").new	
		end	
end
Few changes
affect this code
After
@sandimetz Jul 2017
Example #3
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end
class	Shock	
		def	cost(type)	
				coster(type).compute	
		end	
		def	coster(type)	
				Object.const_get(type.to_s.capitalize	+	“ShockCost").new	
		end	
end
Few changes
affect this code
After
@sandimetz Jul 2017
Example #3
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end
class	Shock	
		def	cost(type)	
				coster(type).compute	
		end	
		def	coster(type)	
				Object.const_get(type.to_s.capitalize	+	“ShockCost").new	
		end	
end
class	RearShockCost	
		def	compute	
				#	slightly	changed	mess	
		end	
end
Few changes
affect this code
After
@sandimetz Jul 2017
Example #3
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end
class	Shock	
		def	cost(type)	
				coster(type).compute	
		end	
		def	coster(type)	
				Object.const_get(type.to_s.capitalize	+	“ShockCost").new	
		end	
end
class	RearShockCost	
		def	compute	
				#	slightly	changed	mess	
		end	
end
Etc...
Few changes
affect this code
After
@sandimetz Jul 2017
Example #3
class	FrontShockCost	
		def	compute	
				#	the	original	mess	
		end	
end
class	Shock	
		def	cost(type)	
				coster(type).compute	
		end	
		def	coster(type)	
				Object.const_get(type.to_s.capitalize	+	“ShockCost").new	
		end	
end
class	RearShockCost	
		def	compute	
				#	slightly	changed	mess	
		end	
end
Etc...
Few changes
affect this code
Need a new one?
Follow the
convention!
@sandimetz Jul 2017
Composition
@sandimetz Jul 2017
Shock
?
@sandimetz Jul 2017
Shock
@sandimetz Jul 2017
Shock
@sandimetz Jul 2017
Shock
@sandimetz Jul 2017
Shock
@sandimetz Jul 2017
Shock
@sandimetz Jul 2017
Shock
@sandimetz Jul 2017
Shock
@sandimetz Jul 2017
Shock
@sandimetz Jul 2017
Shock
@sandimetz Jul 2017
The Role
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
Reprise
Find the message
(Create the object)
Send the message
@sandimetz Jul 2017
Omega Mess
@sandimetz Jul 2017
Omega Mess
Hide It
@sandimetz Jul 2017
Meta Knowledge
@sandimetz Jul 2017
Meta Knowledge
Organize It
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
Depend on Stability
@sandimetz Jul 2017
Depend on Stability
Find the Message
@sandimetz Jul 2017
Isolate Uncertainty
@sandimetz Jul 2017
Isolate Uncertainty
Hide the Mess
@sandimetz Jul 2017
We stand
on the shoulders
of giants
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
@sandimetz Jul 2017
Thanks
Sandi Metz
@sandimetz Jul 2017
http://www.flickr.com/photos/slumadridcampus/5736110401/
http://www.flickr.com/photos/jennifermarquez/4441957235/
http://www.flickr.com/photos/58789412@N00/4106497024/
http://www.flickr.com/photos/27927484@N00/264072199/
http://www.flickr.com/photos/alexindigo/2572565946/in/photostream/
http://www.flickr.com/photos/moje_moje/4500967490/
http://www.flickr.com/photos/dr_nixon/4366089630/
http://www.flickr.com/photos/question_everything/4778500858/
http://www.flickr.com/photos/thegforcers/6202236364/in/photostream/
http://www.flickr.com/photos/jeffhester/2785524078/
http://www.flickr.com/photos/thegforcers/6040964794/in/photostream/
http://www.flickr.com/photos/magnus_akselvoll/4741056713/
http://www.flickr.com/photos/chiotsrun/6553699405/
http://www.flickr.com/photos/45682148@N05/7943889710/
http://www.flickr.com/photos/piper/393928412/
http://www.flickr.com/photos/thegforcers/6202237588/in/photostream/
http://www.flickr.com/photos/juju2nantes/5895167252/
Credits
@sandimetz Jul 2017
http://www.flickr.com/photos/harlequeen/3323992902/
http://www.flickr.com/photos/thegforcers/6114852991/in/photostream/
http://www.flickr.com/photos/qatarperegrine/5040119481/
http://www.flickr.com/photos/reneeanddolan/6152499201/
http://www.flickr.com/photos/tchelseat/7628965564/
http://www.flickr.com/photos/clappstar/1064543301/
http://www.flickr.com/photos/nycarthur/2482218423/
http://www.flickr.com/photos/oliverlaumann/5525877007/
http://www.websequencediagrams.com/
Credits
@sandimetz
http://poodr.com
Jul 2017
@sandimetz
http://99bottlesbook.com
Jul 2017
@sandimetz
Sandi Metz
@sandimetz
http://sandimetz.com
Jul 2017

More Related Content

PDF
hafentalks #10 - Jurgen Appelo: "Managing for Happiness"
PDF
hafentalks #9 - Jeff Gothelf: "Almost Everything I've Learned from 6 Years of...
PDF
hafentalks #5 - André Häusling: "Mythos Agilität – über Sinn und Unsinn des a...
PDF
hafentalks #4 -Kontantin Haase: Wie wir Gehaltsverhandlungen durch eine Sinat...
PDF
hafentalks #1 - Chad Fowler: Impermanence as the key to good systems thinking
PDF
2024 Trend Updates: What Really Works In SEO & Content Marketing
PDF
Storytelling For The Web: Integrate Storytelling in your Design Process
PDF
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
hafentalks #10 - Jurgen Appelo: "Managing for Happiness"
hafentalks #9 - Jeff Gothelf: "Almost Everything I've Learned from 6 Years of...
hafentalks #5 - André Häusling: "Mythos Agilität – über Sinn und Unsinn des a...
hafentalks #4 -Kontantin Haase: Wie wir Gehaltsverhandlungen durch eine Sinat...
hafentalks #1 - Chad Fowler: Impermanence as the key to good systems thinking
2024 Trend Updates: What Really Works In SEO & Content Marketing
Storytelling For The Web: Integrate Storytelling in your Design Process
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...

Recently uploaded (20)

PDF
Comprehensive Salesforce Implementation Services.pdf
PDF
ShowUs: Pharo Stream Deck (ESUG 2025, Gdansk)
DOCX
The Five Best AI Cover Tools in 2025.docx
PPTX
Presentation of Computer CLASS 2 .pptx
PPTX
Save Business Costs with CRM Software for Insurance Agents
PDF
How Creative Agencies Leverage Project Management Software.pdf
PDF
Community & News Update Q2 Meet Up 2025
PDF
How to Confidently Manage Project Budgets
PDF
Microsoft Teams Essentials; The pricing and the versions_PDF.pdf
PPTX
Safe Confined Space Entry Monitoring_ Singapore Experts.pptx
PDF
Jenkins: An open-source automation server powering CI/CD Automation
PDF
Become an Agentblazer Champion Challenge Kickoff
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PPTX
Odoo Consulting Services by CandidRoot Solutions
PDF
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
PDF
The Future of Smart Factories Why Embedded Analytics Leads the Way
PDF
Best Smart Port Software of 2025 Why Envision Leads the Market.pdf
PDF
Build Multi-agent using Agent Development Kit
PDF
Micromaid: A simple Mermaid-like chart generator for Pharo
PPTX
What to Capture When It Breaks: 16 Artifacts That Reveal Root Causes
Comprehensive Salesforce Implementation Services.pdf
ShowUs: Pharo Stream Deck (ESUG 2025, Gdansk)
The Five Best AI Cover Tools in 2025.docx
Presentation of Computer CLASS 2 .pptx
Save Business Costs with CRM Software for Insurance Agents
How Creative Agencies Leverage Project Management Software.pdf
Community & News Update Q2 Meet Up 2025
How to Confidently Manage Project Budgets
Microsoft Teams Essentials; The pricing and the versions_PDF.pdf
Safe Confined Space Entry Monitoring_ Singapore Experts.pptx
Jenkins: An open-source automation server powering CI/CD Automation
Become an Agentblazer Champion Challenge Kickoff
How to Migrate SBCGlobal Email to Yahoo Easily
Odoo Consulting Services by CandidRoot Solutions
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
The Future of Smart Factories Why Embedded Analytics Leads the Way
Best Smart Port Software of 2025 Why Envision Leads the Market.pdf
Build Multi-agent using Agent Development Kit
Micromaid: A simple Mermaid-like chart generator for Pharo
What to Capture When It Breaks: 16 Artifacts That Reveal Root Causes
Ad
Ad

hafentalks #7 - Sandi Metz: Go Ahead, Make a Mess