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

Viewers also liked

Pair programming
Pair programmingPair programming
Pair programming
Kevin Rutherford
 
OCP String Calculator kata
OCP String Calculator kataOCP String Calculator kata
OCP String Calculator kataKevin Rutherford
 
Don't forget the developers!
Don't forget the developers!Don't forget the developers!
Don't forget the developers!
Kevin Rutherford
 
Love and death
Love and deathLove and death
Love and death
Kevin Rutherford
 

Viewers also liked (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
 

Similar to 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-ins
Andrew Dupont
 
Slides python elixir
Slides python elixirSlides python elixir
Slides python elixirAdel Totott
 
Lecture 6: Client Side Programming 2
Lecture 6: Client Side Programming 2Lecture 6: Client Side Programming 2
Lecture 6: Client Side Programming 2
Artificial Intelligence Institute at UofSC
 
Secrets of JavaScript Libraries
Secrets of JavaScript LibrariesSecrets of JavaScript Libraries
Secrets of JavaScript Libraries
jeresig
 
Why Our Code Smells
Why Our Code SmellsWhy Our Code Smells
Why Our Code Smells
TiNguyn863920
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
Andrew Dupont
 
JavaScript Abstraction
JavaScript AbstractionJavaScript Abstraction
JavaScript Abstraction
☆ Milan Adamovsky ☆
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
Leonid Maslov
 
Mockito para tus pruebas unitarias
Mockito para tus pruebas unitariasMockito para tus pruebas unitarias
Mockito para tus pruebas unitarias
Antonio 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 Dive
Manish Jangir
 
Scala coated JVM
Scala coated JVMScala coated JVM
Scala coated JVM
Stuart Roebuck
 
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 2012
Nicholas Zakas
 
Reversing JavaScript
Reversing JavaScriptReversing JavaScript
Reversing JavaScript
Roberto Suggi Liverani
 
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
 
Opensocial
OpensocialOpensocial
Opensocial
Julian Doherty
 
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
James Johnson
 

Similar to 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
 

More from Kevin Rutherford

Making the most of autism
Making the most of autismMaking the most of autism
Making the most of autism
Kevin Rutherford
 
Evolving the Kanban Board
Evolving the Kanban BoardEvolving the Kanban Board
Evolving the Kanban Board
Kevin Rutherford
 

More from 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
 

Recently uploaded

Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
RTTS
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
DianaGray10
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
g2nightmarescribd
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Tobias Schneck
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
Product School
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 

Recently uploaded (20)

Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 

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