SlideShare ist ein Scribd-Unternehmen logo
1 von 26
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

Weitere ähnliche Inhalte

Andere mochten auch (11)

OCP Checkout kata
OCP Checkout kataOCP Checkout kata
OCP Checkout kata
 
Object discovery
Object discoveryObject discovery
Object discovery
 
OCP kata overview
OCP kata overviewOCP kata overview
OCP kata overview
 
OCP bowling kata
OCP bowling kataOCP bowling kata
OCP bowling kata
 
Pair programming
Pair programmingPair programming
Pair programming
 
Shepherding antipatterns
Shepherding antipatternsShepherding antipatterns
Shepherding antipatterns
 
OCP String Calculator kata
OCP String Calculator kataOCP String Calculator kata
OCP String Calculator kata
 
Don't forget the developers!
Don't forget the developers!Don't forget the developers!
Don't forget the developers!
 
Connascence
ConnascenceConnascence
Connascence
 
Love and death
Love and deathLove and death
Love and death
 
Agile principles
Agile principlesAgile principles
Agile principles
 

Ähnlich wie Telling not-asking

Everything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insEverything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insAndrew Dupont
 
Slides python elixir
Slides python elixirSlides python elixir
Slides python elixirAdel Totott
 
Secrets of JavaScript Libraries
Secrets of JavaScript LibrariesSecrets of JavaScript Libraries
Secrets of JavaScript Librariesjeresig
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScriptAndrew Dupont
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2Leonid Maslov
 
Mockito para tus pruebas unitarias
Mockito para tus pruebas unitariasMockito para tus pruebas unitarias
Mockito para tus pruebas unitariasAntonio Robres Turon
 
Uses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & StubsUses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & StubsPatchSpace Ltd
 
Javascript Objects Deep Dive
Javascript Objects Deep DiveJavascript Objects Deep Dive
Javascript Objects Deep DiveManish Jangir
 
Java script object model
Java script object modelJava script object model
Java script object modelJames Hsieh
 
Week 4 - jQuery + Ajax
Week 4 - jQuery + AjaxWeek 4 - jQuery + Ajax
Week 4 - jQuery + Ajaxbaygross
 
Rapid Prototyping with Solr
Rapid Prototyping with SolrRapid Prototyping with Solr
Rapid Prototyping with SolrErik Hatcher
 
Maintainable JavaScript 2012
Maintainable JavaScript 2012Maintainable JavaScript 2012
Maintainable JavaScript 2012Nicholas Zakas
 
jQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't KnowjQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't Knowgirish82
 
A Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NETA Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NETJames Johnson
 

Ähnlich wie Telling not-asking (20)

Everything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insEverything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-ins
 
Slides python elixir
Slides python elixirSlides python elixir
Slides python elixir
 
Lecture 6: Client Side Programming 2
Lecture 6: Client Side Programming 2Lecture 6: Client Side Programming 2
Lecture 6: Client Side Programming 2
 
Secrets of JavaScript Libraries
Secrets of JavaScript LibrariesSecrets of JavaScript Libraries
Secrets of JavaScript Libraries
 
Why Our Code Smells
Why Our Code SmellsWhy Our Code Smells
Why Our Code Smells
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
JavaScript Abstraction
JavaScript AbstractionJavaScript Abstraction
JavaScript Abstraction
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
 
Mockito para tus pruebas unitarias
Mockito para tus pruebas unitariasMockito para tus pruebas unitarias
Mockito para tus pruebas unitarias
 
Uses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & StubsUses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & Stubs
 
Javascript Objects Deep Dive
Javascript Objects Deep DiveJavascript Objects Deep Dive
Javascript Objects Deep Dive
 
Scala coated JVM
Scala coated JVMScala coated JVM
Scala coated JVM
 
Java script object model
Java script object modelJava script object model
Java script object model
 
Week 4 - jQuery + Ajax
Week 4 - jQuery + AjaxWeek 4 - jQuery + Ajax
Week 4 - jQuery + Ajax
 
Rapid Prototyping with Solr
Rapid Prototyping with SolrRapid Prototyping with Solr
Rapid Prototyping with Solr
 
Maintainable JavaScript 2012
Maintainable JavaScript 2012Maintainable JavaScript 2012
Maintainable JavaScript 2012
 
Reversing JavaScript
Reversing JavaScriptReversing JavaScript
Reversing JavaScript
 
jQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't KnowjQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't Know
 
Opensocial
OpensocialOpensocial
Opensocial
 
A Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NETA Rich Web experience with jQuery, Ajax and .NET
A Rich Web experience with jQuery, Ajax and .NET
 

Mehr von Kevin Rutherford

Mehr von Kevin Rutherford (6)

Making the most of autism
Making the most of autismMaking the most of autism
Making the most of autism
 
Evolving the Kanban Board
Evolving the Kanban BoardEvolving the Kanban Board
Evolving the Kanban Board
 
Hex arch
Hex archHex arch
Hex arch
 
Kata rules
Kata rulesKata rules
Kata rules
 
Movie app kata
Movie app kataMovie app kata
Movie app kata
 
Uml
UmlUml
Uml
 

Kürzlich hochgeladen

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 

Kürzlich hochgeladen (20)

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 

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