Don't Settle for Poor Names

Post on 22-Jan-2018

159 views 2 download

transcript

Don’t Settle for Poor Names

Alistair McKinnell@ amckinnell

Namingis deeply

connected to

Designing

Designingis deeply

connected to

Naming

Example fromQCloud

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 andhas 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 fromQCloud

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 )

Namingis 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 fromQCloud

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 andhas 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.