Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Don't Settle for Poor Names (Or Poor Design)

134 views

Published on

Have you ever been frustrated with code that is sprinkled with poorly named classes, methods, and variables?

One of the most valuable things you can do as a developer is to choose good names and to sensitize your teammates to the benefits of improving names.

It turns out that improving names is deeply connected to improving design. And vice-versa. You will see and experience this deep connection as we explore a real world example.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Don't Settle for Poor Names (Or Poor Design)

  1. 1. Don’t Settle for Poor Names Alistair McKinnell @amckinnell
  2. 2. 1974
  3. 3. Naming is deeply
 connected to Designing
  4. 4. Designing is deeply
 connected to Naming
  5. 5. Example from
 QCloud
  6. 6. QCloud has forms,
 sheets, and inspections
  7. 7. QCloud has forms,
 sheets, and inspections
  8. 8. A sheet is composed of a reviewed and a submitted { something or other }
  9. 9. class Sheet < ActiveRecord::Base
  10. 10. 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'] ]
  11. 11. 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'] ]
  12. 12. 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'] ]
  13. 13. 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'] ]
  14. 14. # # 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'] ]
  15. 15. A sheet is composed of a reviewed and a submitted { something or other }
  16. 16. A sheet is composed of a reviewed and a submitted attribution event
  17. 17. An attribution event identifies a user and
 has a timestamp
  18. 18. An attribution event identifies a user and
 has a timestamp
  19. 19. An attribution event identifies a user and
 has a timestamp
  20. 20. # # 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
  21. 21. 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
  22. 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. 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. 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. 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. 26. 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
  27. 27. 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
  28. 28. 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 !
  29. 29. 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
  30. 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. 31. 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
  32. 32. # # 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
  33. 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. 34. 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'] ]
  35. 35. class Sheet < ActiveRecord::Base attribution_event :reviewed attribution_event :submitted
  36. 36. class Sheet < ActiveRecord::Base attribution_event :reviewed attribution_event :submitted attribution_event :discarded
  37. 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. 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. 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. 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. 41. 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
  42. 42. 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
  43. 43. 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
  44. 44. 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
  45. 45. An attribution event identifies a user and
 has a timestamp And there are different 
 types of attribution events
  46. 46. 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
  47. 47. 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
  48. 48. How do we { log, capture, assign, save, or record } an attribution event ?
  49. 49. 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 )
  50. 50. 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 )
  51. 51. 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 )
  52. 52. 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
  53. 53. 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
  54. 54. 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
  55. 55. 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
  56. 56. 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
  57. 57. Example from
 QCloud composed_of Concern
  58. 58. An attribution event identifies a user and
 has a timestamp And we capture different 
 types of attribution events
  59. 59. 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
  60. 60. class Sheet < ActiveRecord::Base include Models::AttributionEvents attribution_event :reviewed attribution_event :submitted sheet.capture_attribution_event( type: :submitted, user: inspector )
  61. 61. Naming is deeply
 connected to Designing
  62. 62. Designing is deeply
 connected to Naming
  63. 63. 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.
  64. 64. • Passes the tests • Reveals intention Simple 
 Design • No duplication • Fewest elements
  65. 65. Simple 
 Design • Removes duplication • Improves names
  66. 66. The Simple Design Dynamo™
  67. 67. Example from
 QCloud
  68. 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. 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. 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. 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. 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. 73. 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 )
  74. 74. The Simple Design Dynamo™
  75. 75. Don’t Settle for Poor Names
  76. 76. Don’t Settle for Poor Names Pretty Please

×