SlideShare a Scribd company logo
Telling, not asking
@kevinrutherford
“Tell, don't ask”
… means WHAT, exactly … ?
“Tell, don't ask”
"Procedural code gets information
then makes decisions. Object-oriented
code tells objects to do things."
— Alec Sharp, Smalltalk by Example
How can I do that?
How can I do that?
… without violating the SRP?
How can I do that?
… without violating the SRP?
… without having DoubleDispatch everywhere?
controllers,
views
A simple to-do list app
rake tasks,
test scripts
etc
use case
objects
A use case object
class CreateAction
def initialize(user)
@user = user
end
def execute(options)
project = @user.open_project(options[:project_id])
action = project.create_action(options[:attrs])
unless action.errors.any?
event = Event.create!(summary: "##{action.id} created", project_id: project.id)
msg = "#{@user.name} created #{action.title}"
project.campfire_room.speak(msg)
PushMessage.instance.publish("action-do.#{action.project.id}.action_item",
{:action_item_id => action})
action.project.users.reject {|u| u == @user}.each do |u|
ActionItemMailer.action_item_created(action, u).deliver
end
end
action
end
end
A use case object
class CreateAction
def initialize(user)
@user = user
end
def execute(options)
project = @user.open_project(options[:project_id])
action = project.create_action(options[:attrs])
unless action.errors.any?
event = Event.create!(summary: "##{action.id} created", project_id: project.id)
msg = "#{@user.name} created #{action.title}"
project.campfire_room.speak(msg)
PushMessage.instance.publish("action-do.#{action.project.id}.action_item",
{:action_item_id => action})
action.project.users.reject {|u| u == @user}.each do |u|
ActionItemMailer.action_item_created(action, u).deliver
end
end
action
end
end
A use case object
class CreateAction
def initialize(user)
@user = user
end
def execute(options)
project = @user.open_project(options[:project_id])
action = project.create_action(options[:attrs])
unless action.errors.any?
event = Event.create!(summary: "##{action.id} created", project_id: project.id)
msg = "#{@user.name} created #{action.title}"
project.campfire_room.speak(msg)
PushMessage.instance.publish("action-do.#{action.project.id}.action_item",
{:action_item_id => action})
action.project.users.reject {|u| u == @user}.each do |u|
ActionItemMailer.action_item_created(action, u).deliver
end
end
action
end
end
A use case object
class CreateAction
def initialize(user)
@user = user
end
def execute(options)
project = @user.open_project(options[:project_id])
action = project.create_action(options[:attrs])
unless action.errors.any?
event = Event.create!(summary: "##{action.id} created", project_id: project.id)
msg = "#{@user.name} created #{action.title}"
project.campfire_room.speak(msg)
PushMessage.instance.publish("action-do.#{action.project.id}.action_item",
{:action_item_id => action})
action.project.users.reject {|u| u == @user}.each do |u|
ActionItemMailer.action_item_created(action, u).deliver
end
end
action
end
end
A use case object
class CreateAction
def initialize(user)
@user = user
end
def execute(options)
project = @user.open_project(options[:project_id])
action = project.create_action(options[:attrs])
unless action.errors.any?
event = Event.create!(summary: "##{action.id} created", project_id: project.id)
msg = "#{@user.name} created #{action.title}"
project.campfire_room.speak(msg)
PushMessage.instance.publish("action-do.#{action.project.id}.action_item",
{:action_item_id => action})
action.project.users.reject {|u| u == @user}.each do |u|
ActionItemMailer.action_item_created(action, u).deliver
end
end
action
end
end
A simple to-do list app
“Tell, don't ask”
"Procedural code gets information
then makes decisions. Object-oriented
code tells objects to do things."
— Alec Sharp, Smalltalk by Example
“Tell, don't ask”
"Procedural code gets information
then makes decisions. Object-oriented
code tells objects to do things."
— Alec Sharp, Smalltalk by Example
“Tell, don't ask”
"Sometimes an object will change
its state, and on those occasions
it might be expected to report
that change to others."
— David West, Object Thinking
A use case object
class CreateAction
def initialize(user)
@user = user
end
def execute(options)
project = @user.open_project(options[:project_id])
action = project.create_action(options[:attrs])
unless action.errors.any?
event = Event.create!(summary: "##{action.id} created", project_id: project.id)
msg = "#{@user.name} created #{action.title}"
project.campfire_room.speak(msg)
PushMessage.instance.publish("action-do.#{action.project.id}.action_item",
{:action_item_id => action})
action.project.users.reject {|u| u == @user}.each do |u|
ActionItemMailer.action_item_created(action, u).deliver
end
end
action
end
end
A use case object
class CreateAction
def initialize(user)
@user = user
end
def execute(options)
project = @user.open_project(options[:project_id])
action = project.create_action(options[:attrs])
unless action.errors.any?
event = Event.create!(summary: "##{action.id} created", project_id: project.id)
msg = "#{@user.name} created #{action.title}"
project.campfire_room.speak(msg)
PushMessage.instance.publish("action-do.#{action.project.id}.action_item",
{:action_item_id => action})
action.project.users.reject {|u| u == @user}.each do |u|
ActionItemMailer.action_item_created(action, u).deliver
end
end
action
end
end
A use case object : after
class CreateAction
def initialize(user)
@user = user
end
def execute(options)
project = @user.open_project(options[:project_id])
action = project.create_action(options[:attrs])
unless action.errors.any?
EventBus.announce('action-created', action: action, actor: @user, publisher: self)
end
action
end
end
https://rubygems.org/gems/event_bus
The Campfire listener
class CampfireAnnouncer
def action_created(payload)
actor = payload[:actor]
action = payload[:action]
project = action.project
msg = "#{actor.name} created #{action.title}"
project.campfire_room.speak(msg)
end
def action_deleted(payload)
#...
end
#...
end
Listener registration
class ApplicationController < ActionController::Base
before_filter do
EventBus.clear
EventBus.register(CampfireAnnouncer.new)
EventBus.register(EventLogger.new)
EventBus.register(EmailNotifier.new)
EventBus.register(PushNotifier.new)
end
#...
end
A simple to-do list app
A simple to-do list app
listeners
event bus
“Tell, don't ask”
Tell, don't ...
“Tell, don't ask”
Tell, don't wait to be asked
“Tell, don't ask”
Tell, don't wait to be asked
@kevinrutherford
http://silkandspinach.net
http://refactoringinruby.info
https://rubygems.org/gems/event_bus

More Related Content

PDF
Scalable CSS You and Your Back-End Coders Can Love - @CSSConf Asia 2014
PDF
Javascript spaghetti stirtrek_5_17
PDF
Tools For jQuery Application Architecture (Extended Slides)
PDF
Tdd is dead
ODP
Red, green, ... what now?!
ODP
The 5-day challenge
ODP
Connascence hunting
Scalable CSS You and Your Back-End Coders Can Love - @CSSConf Asia 2014
Javascript spaghetti stirtrek_5_17
Tools For jQuery Application Architecture (Extended Slides)
Tdd is dead
Red, green, ... what now?!
The 5-day challenge
Connascence hunting

Viewers also liked (11)

ODP
OCP Checkout kata
ODP
Object discovery
ODP
OCP kata overview
ODP
OCP bowling kata
ODP
Pair programming
PDF
Shepherding antipatterns
ODP
OCP String Calculator kata
ODP
Don't forget the developers!
ODP
Connascence
ODP
Love and death
ODP
Agile principles
OCP Checkout kata
Object discovery
OCP kata overview
OCP bowling kata
Pair programming
Shepherding antipatterns
OCP String Calculator kata
Don't forget the developers!
Connascence
Love and death
Agile principles
Ad

Similar to Telling not-asking (20)

KEY
Programming SOLID
PDF
Document Your Development Code
PDF
iOS development best practices
PDF
OOP vs COP
PDF
Ruby on-rails-101-presentation-slides-for-a-five-day-introductory-course-1194...
ODP
Design Patterns
KEY
Objective c
PPTX
Intro to iOS: Object Oriented Programming and Objective-C
PDF
War between Tools and Design 2016
KEY
Ruby On Rails Overview
PPT
Rapid Application Development using Ruby on Rails
PDF
Method Swizzling with Objective-C
PPT
AOP-IOC made by Vi Quoc Hanh and Vu Cong Thanh in SC Team
PDF
Refactoring
PDF
AOP in NET Practical Aspect Oriented Programming Matthew D. Groves
PDF
Programming with Objective-C
PDF
Say Goodbye to Procedural Programming - Nick Sutterer
PDF
Ruby On Rails
PPTX
Cocoa and MVC in ios, iOS Training Ahmedbad , iOS classes Ahmedabad
PPTX
Software Development: Beyond Training wheels
Programming SOLID
Document Your Development Code
iOS development best practices
OOP vs COP
Ruby on-rails-101-presentation-slides-for-a-five-day-introductory-course-1194...
Design Patterns
Objective c
Intro to iOS: Object Oriented Programming and Objective-C
War between Tools and Design 2016
Ruby On Rails Overview
Rapid Application Development using Ruby on Rails
Method Swizzling with Objective-C
AOP-IOC made by Vi Quoc Hanh and Vu Cong Thanh in SC Team
Refactoring
AOP in NET Practical Aspect Oriented Programming Matthew D. Groves
Programming with Objective-C
Say Goodbye to Procedural Programming - Nick Sutterer
Ruby On Rails
Cocoa and MVC in ios, iOS Training Ahmedbad , iOS classes Ahmedabad
Software Development: Beyond Training wheels
Ad

More from Kevin Rutherford (6)

PDF
Making the most of autism
ODP
Evolving the Kanban Board
PDF
ODP
Kata rules
ODP
Movie app kata
Making the most of autism
Evolving the Kanban Board
Kata rules
Movie app kata

Recently uploaded (20)

PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
PPT
What is a Computer? Input Devices /output devices
PDF
Enhancing emotion recognition model for a student engagement use case through...
PDF
Hybrid model detection and classification of lung cancer
PDF
2021 HotChips TSMC Packaging Technologies for Chiplets and 3D_0819 publish_pu...
PDF
project resource management chapter-09.pdf
PDF
Developing a website for English-speaking practice to English as a foreign la...
PDF
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
PDF
STKI Israel Market Study 2025 version august
PDF
A comparative study of natural language inference in Swahili using monolingua...
PDF
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
PDF
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
PDF
1 - Historical Antecedents, Social Consideration.pdf
PDF
A contest of sentiment analysis: k-nearest neighbor versus neural network
PPTX
cloud_computing_Infrastucture_as_cloud_p
PDF
Zenith AI: Advanced Artificial Intelligence
PPTX
Chapter 5: Probability Theory and Statistics
PPTX
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
PDF
Web App vs Mobile App What Should You Build First.pdf
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
What is a Computer? Input Devices /output devices
Enhancing emotion recognition model for a student engagement use case through...
Hybrid model detection and classification of lung cancer
2021 HotChips TSMC Packaging Technologies for Chiplets and 3D_0819 publish_pu...
project resource management chapter-09.pdf
Developing a website for English-speaking practice to English as a foreign la...
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
STKI Israel Market Study 2025 version august
A comparative study of natural language inference in Swahili using monolingua...
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
1 - Historical Antecedents, Social Consideration.pdf
A contest of sentiment analysis: k-nearest neighbor versus neural network
cloud_computing_Infrastucture_as_cloud_p
Zenith AI: Advanced Artificial Intelligence
Chapter 5: Probability Theory and Statistics
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
Web App vs Mobile App What Should You Build First.pdf

Telling not-asking

  • 2. “Tell, don't ask” … means WHAT, exactly … ?
  • 3. “Tell, don't ask” "Procedural code gets information then makes decisions. Object-oriented code tells objects to do things." — Alec Sharp, Smalltalk by Example
  • 4. How can I do that?
  • 5. How can I do that? … without violating the SRP?
  • 6. How can I do that? … without violating the SRP? … without having DoubleDispatch everywhere?
  • 7. controllers, views A simple to-do list app rake tasks, test scripts etc use case objects
  • 8. A use case object class CreateAction def initialize(user) @user = user end def execute(options) project = @user.open_project(options[:project_id]) action = project.create_action(options[:attrs]) unless action.errors.any? event = Event.create!(summary: "##{action.id} created", project_id: project.id) msg = "#{@user.name} created #{action.title}" project.campfire_room.speak(msg) PushMessage.instance.publish("action-do.#{action.project.id}.action_item", {:action_item_id => action}) action.project.users.reject {|u| u == @user}.each do |u| ActionItemMailer.action_item_created(action, u).deliver end end action end end
  • 9. A use case object class CreateAction def initialize(user) @user = user end def execute(options) project = @user.open_project(options[:project_id]) action = project.create_action(options[:attrs]) unless action.errors.any? event = Event.create!(summary: "##{action.id} created", project_id: project.id) msg = "#{@user.name} created #{action.title}" project.campfire_room.speak(msg) PushMessage.instance.publish("action-do.#{action.project.id}.action_item", {:action_item_id => action}) action.project.users.reject {|u| u == @user}.each do |u| ActionItemMailer.action_item_created(action, u).deliver end end action end end
  • 10. A use case object class CreateAction def initialize(user) @user = user end def execute(options) project = @user.open_project(options[:project_id]) action = project.create_action(options[:attrs]) unless action.errors.any? event = Event.create!(summary: "##{action.id} created", project_id: project.id) msg = "#{@user.name} created #{action.title}" project.campfire_room.speak(msg) PushMessage.instance.publish("action-do.#{action.project.id}.action_item", {:action_item_id => action}) action.project.users.reject {|u| u == @user}.each do |u| ActionItemMailer.action_item_created(action, u).deliver end end action end end
  • 11. A use case object class CreateAction def initialize(user) @user = user end def execute(options) project = @user.open_project(options[:project_id]) action = project.create_action(options[:attrs]) unless action.errors.any? event = Event.create!(summary: "##{action.id} created", project_id: project.id) msg = "#{@user.name} created #{action.title}" project.campfire_room.speak(msg) PushMessage.instance.publish("action-do.#{action.project.id}.action_item", {:action_item_id => action}) action.project.users.reject {|u| u == @user}.each do |u| ActionItemMailer.action_item_created(action, u).deliver end end action end end
  • 12. A use case object class CreateAction def initialize(user) @user = user end def execute(options) project = @user.open_project(options[:project_id]) action = project.create_action(options[:attrs]) unless action.errors.any? event = Event.create!(summary: "##{action.id} created", project_id: project.id) msg = "#{@user.name} created #{action.title}" project.campfire_room.speak(msg) PushMessage.instance.publish("action-do.#{action.project.id}.action_item", {:action_item_id => action}) action.project.users.reject {|u| u == @user}.each do |u| ActionItemMailer.action_item_created(action, u).deliver end end action end end
  • 13. A simple to-do list app
  • 14. “Tell, don't ask” "Procedural code gets information then makes decisions. Object-oriented code tells objects to do things." — Alec Sharp, Smalltalk by Example
  • 15. “Tell, don't ask” "Procedural code gets information then makes decisions. Object-oriented code tells objects to do things." — Alec Sharp, Smalltalk by Example
  • 16. “Tell, don't ask” "Sometimes an object will change its state, and on those occasions it might be expected to report that change to others." — David West, Object Thinking
  • 17. A use case object class CreateAction def initialize(user) @user = user end def execute(options) project = @user.open_project(options[:project_id]) action = project.create_action(options[:attrs]) unless action.errors.any? event = Event.create!(summary: "##{action.id} created", project_id: project.id) msg = "#{@user.name} created #{action.title}" project.campfire_room.speak(msg) PushMessage.instance.publish("action-do.#{action.project.id}.action_item", {:action_item_id => action}) action.project.users.reject {|u| u == @user}.each do |u| ActionItemMailer.action_item_created(action, u).deliver end end action end end
  • 18. A use case object class CreateAction def initialize(user) @user = user end def execute(options) project = @user.open_project(options[:project_id]) action = project.create_action(options[:attrs]) unless action.errors.any? event = Event.create!(summary: "##{action.id} created", project_id: project.id) msg = "#{@user.name} created #{action.title}" project.campfire_room.speak(msg) PushMessage.instance.publish("action-do.#{action.project.id}.action_item", {:action_item_id => action}) action.project.users.reject {|u| u == @user}.each do |u| ActionItemMailer.action_item_created(action, u).deliver end end action end end
  • 19. A use case object : after class CreateAction def initialize(user) @user = user end def execute(options) project = @user.open_project(options[:project_id]) action = project.create_action(options[:attrs]) unless action.errors.any? EventBus.announce('action-created', action: action, actor: @user, publisher: self) end action end end https://rubygems.org/gems/event_bus
  • 20. The Campfire listener class CampfireAnnouncer def action_created(payload) actor = payload[:actor] action = payload[:action] project = action.project msg = "#{actor.name} created #{action.title}" project.campfire_room.speak(msg) end def action_deleted(payload) #... end #... end
  • 21. Listener registration class ApplicationController < ActionController::Base before_filter do EventBus.clear EventBus.register(CampfireAnnouncer.new) EventBus.register(EventLogger.new) EventBus.register(EmailNotifier.new) EventBus.register(PushNotifier.new) end #... end
  • 22. A simple to-do list app
  • 23. A simple to-do list app listeners event bus
  • 25. “Tell, don't ask” Tell, don't wait to be asked
  • 26. “Tell, don't ask” Tell, don't wait to be asked @kevinrutherford http://silkandspinach.net http://refactoringinruby.info https://rubygems.org/gems/event_bus