SlideShare a Scribd company logo
Don’t Settle for
Poor Names
Alistair McKinnell
@amckinnell
Naming
is deeply

connected to
Designing
Designing
is deeply

connected to
Naming
Example from

QCloud
QCloud has forms,

sheets, and inspections
QCloud has forms,

sheets, and inspections
A sheet is composed of a
reviewed and a submitted
{ something or other }
class Sheet < ActiveRecord::Base
composed_of :submitted_attribution_event,
class_name: ’AttributionEvent',
allow_nil: true,
mapping: [
['submitted_by_name', 'name'],
['submitted_by_email', 'email'],
['submitted_by_id', 'user_id'],
['submitted_at', 'event_at']
]
composed_of :reviewed_attribution_event,
class_name: 'AttributionEvent',
allow_nil: true,
mapping: [
['reviewed_by_name', 'name'],
['reviewed_by_email', 'email'],
['reviewed_by_id', 'user_id'],
['reviewed_at', 'event_at']
]
#
# Represents the information required to attribute
# an event to a user.
#
class AttributionEvent
attr_reader :name, :email, :user_id, :event_at
def initialize(name, email, user_id, at)
@name = name
@email = email
@user_id = user_id
@event_at = at
end
end
composed_of :submitted_attribution_event,
class_name: ’AttributionEvent',
allow_nil: true,
mapping: [
['submitted_by_name', 'name'],
['submitted_by_email', 'email'],
['submitted_by_id', 'user_id'],
['submitted_at', 'event_at']
]
A sheet is composed of a
reviewed and a submitted
attribution event
An attribution event
identifies a user and

has a timestamp
An attribution event
identifies a user and

has a timestamp
An attribution event
identifies a user and

has a timestamp
#
# Represents the information required to attribute
# an event to a user.
#
class AttributionEvent
attr_reader :name, :email, :user_id, :event_at
def initialize(name, email, user_id, at)
@name = name
@email = email
@user_id = user_id
@event_at = at
end
end
An attribution event
identifies a user and

has a timestamp
sheet.submitted_attribution_event =
AttributionEvent.new(
inspector.name, inspector.email,
inspector.id, Time.zone.now
)
sheet.submitted_by_name = inspector.name
sheet.submitted_by_email = inspector.email
sheet.submitted_by_id = inspector.id
sheet.submitted_at = Time.zone.now
Before
After
sheet.submitted_attribution_event =
AttributionEvent.new(
inspector.name, inspector.email,
inspector.id, Time.zone.now
)
sheet.submitted_by_name = inspector.name
sheet.submitted_by_email = inspector.email
sheet.submitted_by_id = inspector.id
sheet.submitted_at = Time.zone.now
Before
After
#
# Represents the information required to attribute
# an event to a user.
#
class AttributionEvent
attr_reader :name, :email, :user_id, :event_at
def initialize(name, email, user_id, at)
@name = name
@email = email
@user_id = user_id
@event_at = at
end
end
An attribution event
identifies a user and

has a timestamp
#
# Represents the information required to attribute
# an event to a user.
#
class AttributionEvent
attr_reader :name, :email, :user_id, :event_at
def self.build(user, at: Time.zone.now)
new(user.name, user.email, user.id, at)
end
def initialize(name, email, user_id, at)
@name = name
@email = email
@user_id = user_id
@event_at = at
end
end
An attribution event
identifies a user and

has a timestamp
sheet.submitted_attribution_event =
AttributionEvent.build(inspector)
sheet.submitted_by_name = inspector.name
sheet.submitted_by_email = inspector.email
sheet.submitted_by_id = inspector.id
sheet.submitted_at = Time.zone.now
Before
After
sheet.submitted_attribution_event =
AttributionEvent.build(inspector)
sheet.submitted_by_name = inspector.name
sheet.submitted_by_id = inspector.id
sheet.submitted_at = Time.zone.now
Before
After
!
sheet.submitted_attribution_event =
AttributionEvent.build(inspector)
sheet.submitted_by_name = inspector.name
sheet.submitted_by_email = inspector.email
sheet.submitted_by_id = inspector.id
sheet.submitted_at = Time.zone.now
Before
After
sheet.submitted_attribution_event =
AttributionEvent.build(inspector)
sheet.submitted_by_name = inspector.name
sheet.submitted_by_email = reviewer.email
sheet.submitted_by_id = inspector.id
sheet.submitted_at = Time.zone.now
Before
After
!
sheet.submitted_attribution_event =
AttributionEvent.build(inspector)
sheet.submitted_by_name = inspector.name
sheet.submitted_by_email = reviewer.email
sheet.submitted_by_id = inspector.id
sheet.submitted_at = Time.zone.now
Before
After
#
# Represents the information required to attribute
# an event to a user.
#
class AttributionEvent
attr_reader :name, :email, :user_id, :event_at
def self.build(user, at: Time.zone.now)
new(user.name, user.email, user.id, at)
end
def initialize(name, email, user_id, at)
@name = name
@email = email
@user_id = user_id
@event_at = at
end
end
class Sheet < ActiveRecord::Base
composed_of :reviewed_attribution_event,
class_name: 'AttributionEvent',
allow_nil: true,
mapping: [
['reviewed_by_name', 'name'],
['reviewed_by_email', 'email'],
['reviewed_by_id', 'user_id'],
['reviewed_at', 'event_at']
]
composed_of :submitted_attribution_event,
class_name: ’AttributionEvent',
allow_nil: true,
mapping: [
['submitted_by_name', 'name'],
['submitted_by_email', 'email'],
['submitted_by_id', 'user_id'],
['submitted_at', 'event_at']
]
class Sheet < ActiveRecord::Base
composed_of :reviewed_attribution_event,
class_name: ’AttributionEvent',
allow_nil: true,
mapping: [
[‘reviewed_by_name’, 'name'],
[‘reviewed_by_email', 'email'],
[‘reviewed_by_id', 'user_id'],
[‘reviewed_at', 'event_at']
]
composed_of :submitted_attribution_event,
class_name: ’AttributionEvent',
allow_nil: true,
mapping: [
[‘submitted_by_name', 'name'],
[‘submitted_by_email’, 'email'],
[‘submitted_by_id', 'user_id'],
[‘submitted_at’, 'event_at']
]
class Sheet < ActiveRecord::Base
attribution_event :reviewed
attribution_event :submitted
attribution_event :discarded
module Models
module AttributionEvents
extend ActiveSupport::Concern
module ClassMethods
def attribution_event(type, allow_nil: true)
attribution_event = <<-ATTRIBUTION_EVENT
composed_of :#{type}_attribution_event,
class_name: 'AttributionEvent',
allow_nil: #{allow_nil},
mapping: [
['#{type}_by_name', 'name'],
['#{type}_by_email', 'email'],
['#{type}_by_id', 'user_id'],
['#{type}_at', 'event_at']
]
ATTRIBUTION_EVENT
class_eval(attribution_event)
end
end
end
end
module Models
module AttributionEvents
extend ActiveSupport::Concern
module ClassMethods
def attribution_event(type, allow_nil: true)
attribution_event = <<-ATTRIBUTION_EVENT
composed_of :#{type}_attribution_event,
class_name: 'AttributionEvent',
allow_nil: #{allow_nil},
mapping: [
['#{type}_by_name', 'name'],
['#{type}_by_email', 'email'],
['#{type}_by_id', 'user_id'],
['#{type}_at', 'event_at']
]
ATTRIBUTION_EVENT
class_eval(attribution_event)
end
end
end
end
module Models
module AttributionEvents
extend ActiveSupport::Concern
module ClassMethods
def attribution_event(type, allow_nil: true)
attribution_event = <<-ATTRIBUTION_EVENT
composed_of :#{type}_attribution_event,
class_name: 'AttributionEvent',
allow_nil: #{allow_nil},
mapping: [
['#{type}_by_name', 'name'],
['#{type}_by_email', 'email'],
['#{type}_by_id', 'user_id'],
['#{type}_at', 'event_at']
]
ATTRIBUTION_EVENT
class_eval(attribution_event)
end
end
end
end
module Models
module AttributionEvents
extend ActiveSupport::Concern
module ClassMethods
def attribution_event(type, allow_nil: true)
attribution_event = <<-ATTRIBUTION_EVENT
composed_of :#{type}_attribution_event,
class_name: 'AttributionEvent',
allow_nil: #{allow_nil},
mapping: [
['#{type}_by_name', 'name'],
['#{type}_by_email', 'email'],
['#{type}_by_id', 'user_id'],
['#{type}_at', 'event_at']
]
ATTRIBUTION_EVENT
class_eval(attribution_event)
end
end
end
end
module Models
module AttributionEvents
extend ActiveSupport::Concern
module ClassMethods
def attribution_event(type, allow_nil: true)
attribution_event = <<-ATTRIBUTION_EVENT
composed_of :#{type}_attribution_event,
class_name: 'AttributionEvent',
allow_nil: #{allow_nil},
mapping: [
['#{type}_by_name', 'name'],
['#{type}_by_email', 'email'],
['#{type}_by_id', 'user_id'],
['#{type}_at', 'event_at']
]
ATTRIBUTION_EVENT
class_eval(attribution_event)
end
end
end
end
include Models::AttributionEvents
attribution_event :reviewed
composed_of :reviewed_attribution_event,
class_name :'AttributionEvent',
allow_nil: true,
mapping: [
['reviewed_by_name', 'name'],
['reviewed_by_email', 'email'],
['reviewed_by_id', 'user_id'],
['reviewed_at', 'event_at']
]
Before
After
An attribution event
identifies a user and

has a timestamp
And there are different 

types of attribution events
sheet.submitted_attribution_event =
AttributionEvent.build(inspector)
sheet.reviewed_attribution_event =
AttributionEvent.build(supervisor)
class Sheet < ActiveRecord::Base
include Models::AttributionEvents
attribution_event :reviewed
attribution_event :submitted
...
end
How do we { log, capture,
assign, save, or record }
an attribution event ?
sheet.log_attribution_event(
type: :reviewed, user: inspector, at: reviewed_at
)
sheet.capture_attribution_event(
type: :submitted, user: inspector, at: submitted_at
)
header.assign_attribution_event(
type: :reviewed, user: inspector, at: reviewed_at
)
inspection.save_attribution_event(
type: :submitted, user: inspector, at: reviewed_at
)
inspection.record_attribution_event(
type: :reviewed, user: inspector, at: reviewed_at
)
sheet.log_attribution_event(
type: :reviewed, user: inspector, at: reviewed_at
)
sheet.capture_attribution_event(
type: :submitted, user: inspector, at: submitted_at
)
header.assign_attribution_event(
type: :reviewed, user: inspector, at: reviewed_at
)
inspection.save_attribution_event(
type: :submitted, user: inspector, at: reviewed_at
)
inspection.record_attribution_event(
type: :reviewed, user: inspector, at: reviewed_at
)
sheet.log_attribution_event(
type: :reviewed, user: inspector, at: reviewed_at
)
sheet.capture_attribution_event(
type: :submitted, user: inspector, at: submitted_at
)
sheet.assign_attribution_event(
type: :reviewed, user: inspector, at: reviewed_at
)
inspection.save_attribution_event(
type: :submitted, user: inspector, at: reviewed_at
)
sheet.record_attribution_event(
type: :reviewed, user: inspector, at: reviewed_at
)
module Models
module AttributionEvents
extend ActiveSupport::Concern
included do
def capture_attribution_event(type:, user:,
at: Time.zone.now)
send("#{type}_attribution_event=",
AttributionEvent.build(user, at: at))
end
end
module ClassMethods
...
end
end
end
module Models
module AttributionEvents
extend ActiveSupport::Concern
included do
def capture_attribution_event(type:, user:,
at: Time.zone.now)
send("#{type}_attribution_event=",
AttributionEvent.build(user, at: at))
end
end
module ClassMethods
...
end
end
end
module Models
module AttributionEvents
extend ActiveSupport::Concern
included do
def capture_attribution_event(type:, user:,
at: Time.zone.now)
send("#{type}_attribution_event=",
AttributionEvent.build(user, at: at))
end
end
module ClassMethods
...
end
end
end
sheet.capture_attribution_event(
type: :submitted, user: inspector
)
Before
After
sheet.submitted_by_name = inspector.name
sheet.submitted_by_email = inspector.email
sheet.submitted_by_id = inspector.id
sheet.submitted_at = Time.zone.now
Example from

QCloud
composed_of Concern
An attribution event
identifies a user and

has a timestamp
And we capture different 

types of attribution events
class Sheet < ActiveRecord::Base
include Models::AttributionEvents
attribution_event :reviewed
attribution_event :submitted
sheet.capture_attribution_event(
type: :submitted, user: inspector
)
An attribution event
identifies a user and

has a timestamp
And we capture different 

types of attribution events
class Sheet < ActiveRecord::Base
include Models::AttributionEvents
attribution_event :reviewed
attribution_event :submitted
sheet.capture_attribution_event(
type: :submitted, user: inspector
)
Naming
is deeply

connected to
Designing
Ubiquitous 

Language
The language used by everyone on the team
to describe the domain model when speaking,
writing user stories, and in the source code.
• Passes the tests
• Reveals intention
Simple 

Design
• No duplication
• Fewest elements
• Passes the tests
• Reveals intention
Simple 

Design
• No duplication
• Fewest elements
• Passes the tests
• Reveals intention
Simple 

Design
• No duplication
• Fewest elements
• Passes the tests
• Improves names
Simple 

Design
• No duplication
• Fewest elements
• Improves names
Simple 

Design
• Removes duplication
• Improves names
Simple 

Design
• Removes duplication
The Simple Design Dynamo™
Example from

QCloud
class Sheet < ActiveRecord::Base
composed_of :reviewed_attribution_event,
class_name: 'AttributionEvent',
allow_nil: true,
mapping: [
['reviewed_by_name', 'name'],
['reviewed_by_email', 'email'],
['reviewed_by_id', 'user_id'],
['reviewed_at', 'event_at']
]
composed_of :submitted_attribution_event,
class_name: ’AttributionEvent',
allow_nil: true,
mapping: [
['submitted_by_name', 'name'],
['submitted_by_email', 'email'],
['submitted_by_id', 'user_id'],
['submitted_at', 'event_at']
]
#
# Represents the information required to attribute
# an event to a user.
#
class AttributionEvent
attr_reader :name, :email, :user_id, :event_at
def initialize(name, email, user_id, at)
@name = name
@email = email
@user_id = user_id
@event_at = at
end
end
sheet.submitted_attribution_event =
AttributionEvent.new(
inspector.name, inspector.email,
inspector.id, Time.zone.now
)
#
# Represents the information required to attribute
# an event to a user.
#
class AttributionEvent
attr_reader :name, :email, :user_id, :event_at
def self.build(user, at: Time.zone.now)
new(user.name, user.email, user.id, at)
end
def initialize(name, email, user_id, at)
@name = name
@email = email
@user_id = user_id
@event_at = at
end
end
An attribution event
identifies a user and

has a timestamp
class Sheet < ActiveRecord::Base
composed_of :reviewed_attribution_event,
class_name: ’AttributionEvent',
allow_nil: true,
mapping: [
[‘reviewed_by_name’, 'name'],
[‘reviewed_by_email', 'email'],
[‘reviewed_by_id', 'user_id'],
[‘reviewed_at', 'event_at']
]
composed_of :submitted_attribution_event,
class_name: ’AttributionEvent',
allow_nil: true,
mapping: [
[‘submitted_by_name', 'name'],
[‘submitted_by_email’, 'email'],
[‘submitted_by_id', 'user_id'],
[‘submitted_at’, 'event_at']
]
module Models
module AttributionEvents
extend ActiveSupport::Concern
module ClassMethods
def attribution_event(type, allow_nil: true)
attribution_event = <<-ATTRIBUTION_EVENT
composed_of :#{type}_attribution_event,
class_name: 'AttributionEvent',
allow_nil: #{allow_nil},
mapping: [
['#{type}_by_name', 'name'],
['#{type}_by_email', 'email'],
['#{type}_by_id', 'user_id'],
['#{type}_at', 'event_at']
]
ATTRIBUTION_EVENT
class_eval(attribution_event)
end
end
end
end
class Sheet < ActiveRecord::Base
include Models::AttributionEvents
attribution_event :reviewed
attribution_event :submitted
sheet.capture_attribution_event(
type: :submitted, user: inspector
)
sheet.capture_attribution_event(
type: :reviewed, user: supervisor
)
The Simple Design Dynamo™
Don’t Settle for
Poor Names
Don’t Settle for
Poor Names
Pretty Please
The Simple Design Dynamo™
Resources
http://blog.jbrains.ca/permalink/the-four-elements-of-simple-design
http://blog.thecodewhisperer.com/permalink/putting-an-age-old-battle-to-rest
One of the best thinkers around on effective
software development: J. B. Rainsberger.

More Related Content

What's hot

Eden Hackathon Benilde (Mysql & SMTP)
Eden Hackathon Benilde (Mysql & SMTP)Eden Hackathon Benilde (Mysql & SMTP)
Eden Hackathon Benilde (Mysql & SMTP)
Dan Michael Molina
 
Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine PerformanceCatalin Dumitru
 
Web 5 | JavaScript Events
Web 5 | JavaScript EventsWeb 5 | JavaScript Events
Web 5 | JavaScript Events
Mohammad Imam Hossain
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Alessandro Nadalin
 
Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to ask
Andrea Giuliano
 
Sending Email with Rails
Sending Email with RailsSending Email with Rails
Sending Email with Rails
James Gray
 
Active record(1)
Active record(1)Active record(1)
Active record(1)
Ananta Lamichhane
 
Ajax nested form and ajax upload in rails
Ajax nested form and ajax upload in railsAjax nested form and ajax upload in rails
Ajax nested form and ajax upload in rails
Tse-Ching Ho
 
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate ModuleDigital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Erich Beyrent
 
Technology and Science News - ABC News
Technology and Science News - ABC NewsTechnology and Science News - ABC News
Technology and Science News - ABC News
numberlesspasto93
 
Design Summit - Navigating the ManageIQ Object Model - Brad Ascar
Design Summit - Navigating the ManageIQ Object Model - Brad AscarDesign Summit - Navigating the ManageIQ Object Model - Brad Ascar
Design Summit - Navigating the ManageIQ Object Model - Brad Ascar
ManageIQ
 

What's hot (12)

Metaworks3
Metaworks3Metaworks3
Metaworks3
 
Eden Hackathon Benilde (Mysql & SMTP)
Eden Hackathon Benilde (Mysql & SMTP)Eden Hackathon Benilde (Mysql & SMTP)
Eden Hackathon Benilde (Mysql & SMTP)
 
Modern JavaScript Engine Performance
Modern JavaScript Engine PerformanceModern JavaScript Engine Performance
Modern JavaScript Engine Performance
 
Web 5 | JavaScript Events
Web 5 | JavaScript EventsWeb 5 | JavaScript Events
Web 5 | JavaScript Events
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 
Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to ask
 
Sending Email with Rails
Sending Email with RailsSending Email with Rails
Sending Email with Rails
 
Active record(1)
Active record(1)Active record(1)
Active record(1)
 
Ajax nested form and ajax upload in rails
Ajax nested form and ajax upload in railsAjax nested form and ajax upload in rails
Ajax nested form and ajax upload in rails
 
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate ModuleDigital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
 
Technology and Science News - ABC News
Technology and Science News - ABC NewsTechnology and Science News - ABC News
Technology and Science News - ABC News
 
Design Summit - Navigating the ManageIQ Object Model - Brad Ascar
Design Summit - Navigating the ManageIQ Object Model - Brad AscarDesign Summit - Navigating the ManageIQ Object Model - Brad Ascar
Design Summit - Navigating the ManageIQ Object Model - Brad Ascar
 

Similar to Don't Settle for Poor Names

Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelpauldix
 
Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelpauldix
 
Do You Need That Validation? Let Me Call You Back About It
Do You Need That Validation? Let Me Call You Back About ItDo You Need That Validation? Let Me Call You Back About It
Do You Need That Validation? Let Me Call You Back About It
Tobias Pfeiffer
 
Empower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo MixinsEmpower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo Mixins
Odoo
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
Jorn Oomen
 
Implementation of EAV pattern for ActiveRecord models
Implementation of EAV pattern for ActiveRecord modelsImplementation of EAV pattern for ActiveRecord models
Implementation of EAV pattern for ActiveRecord models
Kostyantyn Stepanyuk
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutes
Barang CK
 
Web technology javascript
Web technology   javascriptWeb technology   javascript
Web technology javascript
Uma mohan
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
Samuel ROZE
 
Deep-dive into Django #1
Deep-dive into Django #1Deep-dive into Django #1
Deep-dive into Django #1Avik Das
 
Django - sql alchemy - jquery
Django - sql alchemy - jqueryDjango - sql alchemy - jquery
Django - sql alchemy - jquery
Mohammed El Rafie Tarabay
 
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024  - Need for Speed: Removing speed bumps in API ProjectsConFoo 2024  - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
Łukasz Chruściel
 
Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with React
GreeceJS
 
CakePHP workshop
CakePHP workshopCakePHP workshop
CakePHP workshop
Walther Lalk
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful Security
Ryan Weaver
 
Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Luka Zakrajšek
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
Marcus Ramberg
 
Better Together: Building Scalable Real Time Collaborative Apps with Node.js
Better Together: Building Scalable Real Time Collaborative Apps with Node.js  Better Together: Building Scalable Real Time Collaborative Apps with Node.js
Better Together: Building Scalable Real Time Collaborative Apps with Node.js
Kav Latiolais
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
Samuel ROZE
 

Similar to Don't Settle for Poor Names (20)

Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModel
 
Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModel
 
Do You Need That Validation? Let Me Call You Back About It
Do You Need That Validation? Let Me Call You Back About ItDo You Need That Validation? Let Me Call You Back About It
Do You Need That Validation? Let Me Call You Back About It
 
Empower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo MixinsEmpower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo Mixins
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Implementation of EAV pattern for ActiveRecord models
Implementation of EAV pattern for ActiveRecord modelsImplementation of EAV pattern for ActiveRecord models
Implementation of EAV pattern for ActiveRecord models
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutes
 
Web technology javascript
Web technology   javascriptWeb technology   javascript
Web technology javascript
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
Deep-dive into Django #1
Deep-dive into Django #1Deep-dive into Django #1
Deep-dive into Django #1
 
Django - sql alchemy - jquery
Django - sql alchemy - jqueryDjango - sql alchemy - jquery
Django - sql alchemy - jquery
 
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024  - Need for Speed: Removing speed bumps in API ProjectsConFoo 2024  - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
 
Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with React
 
CakePHP workshop
CakePHP workshopCakePHP workshop
CakePHP workshop
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful Security
 
Django (Web Konferencia 2009)
Django (Web Konferencia 2009)Django (Web Konferencia 2009)
Django (Web Konferencia 2009)
 
Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Django Class-based views (Slovenian)
Django Class-based views (Slovenian)
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
Better Together: Building Scalable Real Time Collaborative Apps with Node.js
Better Together: Building Scalable Real Time Collaborative Apps with Node.js  Better Together: Building Scalable Real Time Collaborative Apps with Node.js
Better Together: Building Scalable Real Time Collaborative Apps with Node.js
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 

More from Alistair McKinnell

Succeeding with Specification by Example
Succeeding with Specification by ExampleSucceeding with Specification by Example
Succeeding with Specification by Example
Alistair McKinnell
 
The Boy Scout Rule
The Boy Scout RuleThe Boy Scout Rule
The Boy Scout Rule
Alistair McKinnell
 
Advanced Developer Testing
Advanced Developer TestingAdvanced Developer Testing
Advanced Developer Testing
Alistair McKinnell
 
What Can Journalists Teach Developers About Writing Source Code?
What Can Journalists Teach Developers About Writing Source Code?What Can Journalists Teach Developers About Writing Source Code?
What Can Journalists Teach Developers About Writing Source Code?
Alistair McKinnell
 
Ubiquitous Testing
Ubiquitous TestingUbiquitous Testing
Ubiquitous Testing
Alistair McKinnell
 
Commonality and Variability Analysis: Avoiding Duplicate Code
Commonality and Variability Analysis: Avoiding Duplicate CodeCommonality and Variability Analysis: Avoiding Duplicate Code
Commonality and Variability Analysis: Avoiding Duplicate Code
Alistair McKinnell
 
Simple Design
Simple DesignSimple Design
Simple Design
Alistair McKinnell
 
Agile Tour Shanghai December 2011
Agile Tour Shanghai December 2011Agile Tour Shanghai December 2011
Agile Tour Shanghai December 2011Alistair McKinnell
 
Pair Programming
Pair ProgrammingPair Programming
Pair Programming
Alistair McKinnell
 
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic Tool
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic ToolAgile Transition in Trouble? Using the Kotter Change Model as a Diagnostic Tool
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic Tool
Alistair McKinnell
 
The Story of a Story
The Story of a StoryThe Story of a Story
The Story of a Story
Alistair McKinnell
 
The Testing Landscape
The Testing LandscapeThe Testing Landscape
The Testing Landscape
Alistair McKinnell
 
Struggling to Create Maintainable Unit Tests?
Struggling to Create Maintainable Unit Tests?Struggling to Create Maintainable Unit Tests?
Struggling to Create Maintainable Unit Tests?
Alistair McKinnell
 

More from Alistair McKinnell (13)

Succeeding with Specification by Example
Succeeding with Specification by ExampleSucceeding with Specification by Example
Succeeding with Specification by Example
 
The Boy Scout Rule
The Boy Scout RuleThe Boy Scout Rule
The Boy Scout Rule
 
Advanced Developer Testing
Advanced Developer TestingAdvanced Developer Testing
Advanced Developer Testing
 
What Can Journalists Teach Developers About Writing Source Code?
What Can Journalists Teach Developers About Writing Source Code?What Can Journalists Teach Developers About Writing Source Code?
What Can Journalists Teach Developers About Writing Source Code?
 
Ubiquitous Testing
Ubiquitous TestingUbiquitous Testing
Ubiquitous Testing
 
Commonality and Variability Analysis: Avoiding Duplicate Code
Commonality and Variability Analysis: Avoiding Duplicate CodeCommonality and Variability Analysis: Avoiding Duplicate Code
Commonality and Variability Analysis: Avoiding Duplicate Code
 
Simple Design
Simple DesignSimple Design
Simple Design
 
Agile Tour Shanghai December 2011
Agile Tour Shanghai December 2011Agile Tour Shanghai December 2011
Agile Tour Shanghai December 2011
 
Pair Programming
Pair ProgrammingPair Programming
Pair Programming
 
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic Tool
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic ToolAgile Transition in Trouble? Using the Kotter Change Model as a Diagnostic Tool
Agile Transition in Trouble? Using the Kotter Change Model as a Diagnostic Tool
 
The Story of a Story
The Story of a StoryThe Story of a Story
The Story of a Story
 
The Testing Landscape
The Testing LandscapeThe Testing Landscape
The Testing Landscape
 
Struggling to Create Maintainable Unit Tests?
Struggling to Create Maintainable Unit Tests?Struggling to Create Maintainable Unit Tests?
Struggling to Create Maintainable Unit Tests?
 

Recently uploaded

Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
Rohit Gautam
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
Matthew Sinclair
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
Alex Pruden
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
Neo4j
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
Kumud Singh
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
ThomasParaiso2
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
Neo4j
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 

Recently uploaded (20)

Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 

Don't Settle for Poor Names

  • 1. Don’t Settle for Poor Names Alistair McKinnell @amckinnell
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13. A sheet is composed of a reviewed and a submitted { something or other }
  • 14.
  • 15. class Sheet < ActiveRecord::Base composed_of :submitted_attribution_event, class_name: ’AttributionEvent', allow_nil: true, mapping: [ ['submitted_by_name', 'name'], ['submitted_by_email', 'email'], ['submitted_by_id', 'user_id'], ['submitted_at', 'event_at'] ] composed_of :reviewed_attribution_event, class_name: 'AttributionEvent', allow_nil: true, mapping: [ ['reviewed_by_name', 'name'], ['reviewed_by_email', 'email'], ['reviewed_by_id', 'user_id'], ['reviewed_at', 'event_at'] ]
  • 16. # # Represents the information required to attribute # an event to a user. # class AttributionEvent attr_reader :name, :email, :user_id, :event_at def initialize(name, email, user_id, at) @name = name @email = email @user_id = user_id @event_at = at end end composed_of :submitted_attribution_event, class_name: ’AttributionEvent', allow_nil: true, mapping: [ ['submitted_by_name', 'name'], ['submitted_by_email', 'email'], ['submitted_by_id', 'user_id'], ['submitted_at', 'event_at'] ]
  • 17. A sheet is composed of a reviewed and a submitted attribution event
  • 18. An attribution event identifies a user and
 has a timestamp
  • 19. An attribution event identifies a user and
 has a timestamp
  • 20. An attribution event identifies a user and
 has a timestamp
  • 21. # # Represents the information required to attribute # an event to a user. # class AttributionEvent attr_reader :name, :email, :user_id, :event_at def initialize(name, email, user_id, at) @name = name @email = email @user_id = user_id @event_at = at end end An attribution event identifies a user and
 has a timestamp
  • 22. sheet.submitted_attribution_event = AttributionEvent.new( inspector.name, inspector.email, inspector.id, Time.zone.now ) sheet.submitted_by_name = inspector.name sheet.submitted_by_email = inspector.email sheet.submitted_by_id = inspector.id sheet.submitted_at = Time.zone.now Before After
  • 23. sheet.submitted_attribution_event = AttributionEvent.new( inspector.name, inspector.email, inspector.id, Time.zone.now ) sheet.submitted_by_name = inspector.name sheet.submitted_by_email = inspector.email sheet.submitted_by_id = inspector.id sheet.submitted_at = Time.zone.now Before After
  • 24. # # Represents the information required to attribute # an event to a user. # class AttributionEvent attr_reader :name, :email, :user_id, :event_at def initialize(name, email, user_id, at) @name = name @email = email @user_id = user_id @event_at = at end end An attribution event identifies a user and
 has a timestamp
  • 25. # # Represents the information required to attribute # an event to a user. # class AttributionEvent attr_reader :name, :email, :user_id, :event_at def self.build(user, at: Time.zone.now) new(user.name, user.email, user.id, at) end def initialize(name, email, user_id, at) @name = name @email = email @user_id = user_id @event_at = at end end An attribution event identifies a user and
 has a timestamp
  • 26. sheet.submitted_attribution_event = AttributionEvent.build(inspector) sheet.submitted_by_name = inspector.name sheet.submitted_by_email = inspector.email sheet.submitted_by_id = inspector.id sheet.submitted_at = Time.zone.now Before After
  • 27. sheet.submitted_attribution_event = AttributionEvent.build(inspector) sheet.submitted_by_name = inspector.name sheet.submitted_by_id = inspector.id sheet.submitted_at = Time.zone.now Before After !
  • 28. sheet.submitted_attribution_event = AttributionEvent.build(inspector) sheet.submitted_by_name = inspector.name sheet.submitted_by_email = inspector.email sheet.submitted_by_id = inspector.id sheet.submitted_at = Time.zone.now Before After
  • 29. sheet.submitted_attribution_event = AttributionEvent.build(inspector) sheet.submitted_by_name = inspector.name sheet.submitted_by_email = reviewer.email sheet.submitted_by_id = inspector.id sheet.submitted_at = Time.zone.now Before After !
  • 30. sheet.submitted_attribution_event = AttributionEvent.build(inspector) sheet.submitted_by_name = inspector.name sheet.submitted_by_email = reviewer.email sheet.submitted_by_id = inspector.id sheet.submitted_at = Time.zone.now Before After
  • 31. # # Represents the information required to attribute # an event to a user. # class AttributionEvent attr_reader :name, :email, :user_id, :event_at def self.build(user, at: Time.zone.now) new(user.name, user.email, user.id, at) end def initialize(name, email, user_id, at) @name = name @email = email @user_id = user_id @event_at = at end end
  • 32. class Sheet < ActiveRecord::Base composed_of :reviewed_attribution_event, class_name: 'AttributionEvent', allow_nil: true, mapping: [ ['reviewed_by_name', 'name'], ['reviewed_by_email', 'email'], ['reviewed_by_id', 'user_id'], ['reviewed_at', 'event_at'] ] composed_of :submitted_attribution_event, class_name: ’AttributionEvent', allow_nil: true, mapping: [ ['submitted_by_name', 'name'], ['submitted_by_email', 'email'], ['submitted_by_id', 'user_id'], ['submitted_at', 'event_at'] ]
  • 33. class Sheet < ActiveRecord::Base composed_of :reviewed_attribution_event, class_name: ’AttributionEvent', allow_nil: true, mapping: [ [‘reviewed_by_name’, 'name'], [‘reviewed_by_email', 'email'], [‘reviewed_by_id', 'user_id'], [‘reviewed_at', 'event_at'] ] composed_of :submitted_attribution_event, class_name: ’AttributionEvent', allow_nil: true, mapping: [ [‘submitted_by_name', 'name'], [‘submitted_by_email’, 'email'], [‘submitted_by_id', 'user_id'], [‘submitted_at’, 'event_at'] ]
  • 34. class Sheet < ActiveRecord::Base attribution_event :reviewed attribution_event :submitted attribution_event :discarded
  • 35.
  • 36. module Models module AttributionEvents extend ActiveSupport::Concern module ClassMethods def attribution_event(type, allow_nil: true) attribution_event = <<-ATTRIBUTION_EVENT composed_of :#{type}_attribution_event, class_name: 'AttributionEvent', allow_nil: #{allow_nil}, mapping: [ ['#{type}_by_name', 'name'], ['#{type}_by_email', 'email'], ['#{type}_by_id', 'user_id'], ['#{type}_at', 'event_at'] ] ATTRIBUTION_EVENT class_eval(attribution_event) end end end end
  • 37. module Models module AttributionEvents extend ActiveSupport::Concern module ClassMethods def attribution_event(type, allow_nil: true) attribution_event = <<-ATTRIBUTION_EVENT composed_of :#{type}_attribution_event, class_name: 'AttributionEvent', allow_nil: #{allow_nil}, mapping: [ ['#{type}_by_name', 'name'], ['#{type}_by_email', 'email'], ['#{type}_by_id', 'user_id'], ['#{type}_at', 'event_at'] ] ATTRIBUTION_EVENT class_eval(attribution_event) end end end end
  • 38. module Models module AttributionEvents extend ActiveSupport::Concern module ClassMethods def attribution_event(type, allow_nil: true) attribution_event = <<-ATTRIBUTION_EVENT composed_of :#{type}_attribution_event, class_name: 'AttributionEvent', allow_nil: #{allow_nil}, mapping: [ ['#{type}_by_name', 'name'], ['#{type}_by_email', 'email'], ['#{type}_by_id', 'user_id'], ['#{type}_at', 'event_at'] ] ATTRIBUTION_EVENT class_eval(attribution_event) end end end end
  • 39. module Models module AttributionEvents extend ActiveSupport::Concern module ClassMethods def attribution_event(type, allow_nil: true) attribution_event = <<-ATTRIBUTION_EVENT composed_of :#{type}_attribution_event, class_name: 'AttributionEvent', allow_nil: #{allow_nil}, mapping: [ ['#{type}_by_name', 'name'], ['#{type}_by_email', 'email'], ['#{type}_by_id', 'user_id'], ['#{type}_at', 'event_at'] ] ATTRIBUTION_EVENT class_eval(attribution_event) end end end end
  • 40. module Models module AttributionEvents extend ActiveSupport::Concern module ClassMethods def attribution_event(type, allow_nil: true) attribution_event = <<-ATTRIBUTION_EVENT composed_of :#{type}_attribution_event, class_name: 'AttributionEvent', allow_nil: #{allow_nil}, mapping: [ ['#{type}_by_name', 'name'], ['#{type}_by_email', 'email'], ['#{type}_by_id', 'user_id'], ['#{type}_at', 'event_at'] ] ATTRIBUTION_EVENT class_eval(attribution_event) end end end end
  • 41. include Models::AttributionEvents attribution_event :reviewed composed_of :reviewed_attribution_event, class_name :'AttributionEvent', allow_nil: true, mapping: [ ['reviewed_by_name', 'name'], ['reviewed_by_email', 'email'], ['reviewed_by_id', 'user_id'], ['reviewed_at', 'event_at'] ] Before After
  • 42. An attribution event identifies a user and
 has a timestamp And there are different 
 types of attribution events
  • 43. sheet.submitted_attribution_event = AttributionEvent.build(inspector) sheet.reviewed_attribution_event = AttributionEvent.build(supervisor) class Sheet < ActiveRecord::Base include Models::AttributionEvents attribution_event :reviewed attribution_event :submitted ... end
  • 44. How do we { log, capture, assign, save, or record } an attribution event ?
  • 45. sheet.log_attribution_event( type: :reviewed, user: inspector, at: reviewed_at ) sheet.capture_attribution_event( type: :submitted, user: inspector, at: submitted_at ) header.assign_attribution_event( type: :reviewed, user: inspector, at: reviewed_at ) inspection.save_attribution_event( type: :submitted, user: inspector, at: reviewed_at ) inspection.record_attribution_event( type: :reviewed, user: inspector, at: reviewed_at )
  • 46. sheet.log_attribution_event( type: :reviewed, user: inspector, at: reviewed_at ) sheet.capture_attribution_event( type: :submitted, user: inspector, at: submitted_at ) header.assign_attribution_event( type: :reviewed, user: inspector, at: reviewed_at ) inspection.save_attribution_event( type: :submitted, user: inspector, at: reviewed_at ) inspection.record_attribution_event( type: :reviewed, user: inspector, at: reviewed_at )
  • 47. sheet.log_attribution_event( type: :reviewed, user: inspector, at: reviewed_at ) sheet.capture_attribution_event( type: :submitted, user: inspector, at: submitted_at ) sheet.assign_attribution_event( type: :reviewed, user: inspector, at: reviewed_at ) inspection.save_attribution_event( type: :submitted, user: inspector, at: reviewed_at ) sheet.record_attribution_event( type: :reviewed, user: inspector, at: reviewed_at )
  • 48. module Models module AttributionEvents extend ActiveSupport::Concern included do def capture_attribution_event(type:, user:, at: Time.zone.now) send("#{type}_attribution_event=", AttributionEvent.build(user, at: at)) end end module ClassMethods ... end end end
  • 49. module Models module AttributionEvents extend ActiveSupport::Concern included do def capture_attribution_event(type:, user:, at: Time.zone.now) send("#{type}_attribution_event=", AttributionEvent.build(user, at: at)) end end module ClassMethods ... end end end
  • 50. module Models module AttributionEvents extend ActiveSupport::Concern included do def capture_attribution_event(type:, user:, at: Time.zone.now) send("#{type}_attribution_event=", AttributionEvent.build(user, at: at)) end end module ClassMethods ... end end end
  • 51. sheet.capture_attribution_event( type: :submitted, user: inspector ) Before After sheet.submitted_by_name = inspector.name sheet.submitted_by_email = inspector.email sheet.submitted_by_id = inspector.id sheet.submitted_at = Time.zone.now
  • 53. An attribution event identifies a user and
 has a timestamp And we capture different 
 types of attribution events
  • 54. class Sheet < ActiveRecord::Base include Models::AttributionEvents attribution_event :reviewed attribution_event :submitted sheet.capture_attribution_event( type: :submitted, user: inspector ) An attribution event identifies a user and
 has a timestamp And we capture different 
 types of attribution events
  • 55. class Sheet < ActiveRecord::Base include Models::AttributionEvents attribution_event :reviewed attribution_event :submitted sheet.capture_attribution_event( type: :submitted, user: inspector )
  • 57.
  • 58. Ubiquitous 
 Language The language used by everyone on the team to describe the domain model when speaking, writing user stories, and in the source code.
  • 59. • Passes the tests • Reveals intention Simple 
 Design • No duplication • Fewest elements
  • 60. • Passes the tests • Reveals intention Simple 
 Design • No duplication • Fewest elements
  • 61. • Passes the tests • Reveals intention Simple 
 Design • No duplication • Fewest elements
  • 62. • Passes the tests • Improves names Simple 
 Design • No duplication • Fewest elements
  • 63. • Improves names Simple 
 Design • Removes duplication
  • 64. • Improves names Simple 
 Design • Removes duplication
  • 65. The Simple Design Dynamo™
  • 67.
  • 68. class Sheet < ActiveRecord::Base composed_of :reviewed_attribution_event, class_name: 'AttributionEvent', allow_nil: true, mapping: [ ['reviewed_by_name', 'name'], ['reviewed_by_email', 'email'], ['reviewed_by_id', 'user_id'], ['reviewed_at', 'event_at'] ] composed_of :submitted_attribution_event, class_name: ’AttributionEvent', allow_nil: true, mapping: [ ['submitted_by_name', 'name'], ['submitted_by_email', 'email'], ['submitted_by_id', 'user_id'], ['submitted_at', 'event_at'] ]
  • 69. # # Represents the information required to attribute # an event to a user. # class AttributionEvent attr_reader :name, :email, :user_id, :event_at def initialize(name, email, user_id, at) @name = name @email = email @user_id = user_id @event_at = at end end sheet.submitted_attribution_event = AttributionEvent.new( inspector.name, inspector.email, inspector.id, Time.zone.now )
  • 70. # # Represents the information required to attribute # an event to a user. # class AttributionEvent attr_reader :name, :email, :user_id, :event_at def self.build(user, at: Time.zone.now) new(user.name, user.email, user.id, at) end def initialize(name, email, user_id, at) @name = name @email = email @user_id = user_id @event_at = at end end An attribution event identifies a user and
 has a timestamp
  • 71. class Sheet < ActiveRecord::Base composed_of :reviewed_attribution_event, class_name: ’AttributionEvent', allow_nil: true, mapping: [ [‘reviewed_by_name’, 'name'], [‘reviewed_by_email', 'email'], [‘reviewed_by_id', 'user_id'], [‘reviewed_at', 'event_at'] ] composed_of :submitted_attribution_event, class_name: ’AttributionEvent', allow_nil: true, mapping: [ [‘submitted_by_name', 'name'], [‘submitted_by_email’, 'email'], [‘submitted_by_id', 'user_id'], [‘submitted_at’, 'event_at'] ]
  • 72. module Models module AttributionEvents extend ActiveSupport::Concern module ClassMethods def attribution_event(type, allow_nil: true) attribution_event = <<-ATTRIBUTION_EVENT composed_of :#{type}_attribution_event, class_name: 'AttributionEvent', allow_nil: #{allow_nil}, mapping: [ ['#{type}_by_name', 'name'], ['#{type}_by_email', 'email'], ['#{type}_by_id', 'user_id'], ['#{type}_at', 'event_at'] ] ATTRIBUTION_EVENT class_eval(attribution_event) end end end end
  • 73.
  • 74. class Sheet < ActiveRecord::Base include Models::AttributionEvents attribution_event :reviewed attribution_event :submitted sheet.capture_attribution_event( type: :submitted, user: inspector ) sheet.capture_attribution_event( type: :reviewed, user: supervisor )
  • 75. The Simple Design Dynamo™
  • 77. Don’t Settle for Poor Names Pretty Please
  • 78.
  • 79. The Simple Design Dynamo™
  • 80.