Bringing UX to Your Code, V2

Bringing UX to Your Code, V2

User Centered Design as a process is almost thirty years old now. The philosophy has permeated our products and the way we build our interfaces. But this philosophy is rarely extended to the code we write. We'll take a look at some principles of UX and Interface Design and relate them back to our code. By comparing code that gets it right to code that gets it desperately wrong, we'll learn some principles that we can use to write more usable code.

A9704266587836f7e784235e5073b93e?s=128

Joseph Mastey

May 05, 2017
Tweet

Transcript

  1. Bringing UX to Your Code Joe Mastey @jmmastey

  2. @jmmastey Joe Mastey @jmmastey josephmastey.com chicagoapprenticeships.com

  3. @jmmastey I help companies build awesome internal education programs

  4. @jmmastey I’ve worked in software for a million years.

  5. None
  6. @jmmastey I am not a UX designer / developer

  7. Don Norman

  8. @jmmastey

  9. None
  10. @jmmastey “Norman discussed door handles at length.” - Wikipedia

  11. None
  12. None
  13. It’s not your fault

  14. None
  15. None
  16. None
  17. @jmmastey <rant>

  18. @jmmastey Things We Ignore:

  19. @jmmastey Things We Ignore: 1. Anything invented a long time

    ago
  20. @jmmastey Things We Ignore: 1. Anything invented a long time

    ago 2. Anything invented by non-engineers
  21. None
  22. None
  23. None
  24. @jmmastey < decades of research shit I made up

  25. @jmmastey We’re missing out

  26. @jmmastey Our code is an interface

  27. @jmmastey Our users are stressed

  28. @jmmastey </rant>

  29. @jmmastey Let’s try it!

  30. @jmmastey Gulf of Execution

  31. @jmmastey Is there an action that corresponds to my intentions?

  32. @jmmastey An example: deleting an ActiveRecord object

  33. @jmmastey macguffin.methods.sort

  34. @jmmastey [:!, :!=, :!~, :<=>, :==, :===, :=~, :Pathname, :[],

    : []=, :__class__, :__extend__, :__id__, :__instance_variable_defined_p__, :__instance_variable_get__, :__instance_variable_set__, :__instance_variables__, :__marshal__, :__respond_to_p__, :__send__ , :__show__, :_commit_callbacks, :_commit_callbacks=, :_commit_callbacks?, :_create_callbacks, :_create_callbacks=, :_create_callbacks?, :_destroy, :_destroy_callbacks, :_destroy_callbacks=, :_des troy_callbacks?, :_find_callbacks, :_find_callbacks=, :_find_callbacks?, :_initialize_callbacks, :_initialize_callbacks=, :_initialize_callbacks?, :_read_attribute, :_reflections, :_reflections=, :_reflections?, :_rollback_callbacks, :_rollback_callbacks=, :_rollback_callbacks?, :_run_commit_callbacks, :_run_create_callbacks, :_run_destroy_callbacks, :_run_find_callbacks, :_run_initialize_ callbacks, :_run_rollback_callbacks, :_run_save_callbacks, :_run_touch_callbacks, :_run_update_callbacks, :_run_validate_callbacks, :_run_validation_callbacks, :_save_callbacks, :_save_callbacks=, :_save_callbacks?, :_touch_callbacks, :_touch_callbacks=, :_touch_callbacks?, :_update_callbacks, :_update_callbacks=, :_update_callbacks?, :_validate_callbacks, :_validate_callbacks=, :_validate_ callbacks?, :_validation_callbacks, :_validation_callbacks=, :_validation_callbacks?, :_validators, :_validators=, :_validators?, :`, :acts_like?, :actually_destroyed?, :add_to_transaction, :after _add_for_categories, :after_add_for_categories=, :after_add_for_categories?, :after_add_for_enrollments, :after_add_for_enrollments=, :after_add_for_enrollments?, :after_add_for_skills, :after_add _for_skills=, :after_add_for_skills?, :after_add_for_users, :after_add_for_users=, :after_add_for_users?, :after_remove_for_categories, :after_remove_for_categories=, :after_remove_for_categories? , :after_remove_for_enrollments, :after_remove_for_enrollments=, :after_remove_for_enrollments?, :after_remove_for_skills, :after_remove_for_skills=, :after_remove_for_skills?, :after_remove_for_u sers, :after_remove_for_users=, :after_remove_for_users?, :aggregate_reflections, :aggregate_reflections=, :aggregate_reflections?, :approve, :approve!, :approve_transition, :approved?, :arel_attr ibutes_with_values_for_create, :arel_attributes_with_values_for_update, :as_json, :assign_attributes, :association, :association_cache, :attribute_aliases, :attribute_aliases?, :attribute_changed? , :attribute_changed_in_place?, :attribute_for_inspect, :attribute_method?, :attribute_method_matchers, :attribute_method_matchers?, :attribute_missing, :attribute_names, :attribute_present?, :att ribute_was, :attributes, :attributes=, :attributes_before_type_cast, :attributes_changed_by_setter, :autosave_associated_records_for_categories, :autosave_associated_records_for_enrollments, :auto save_associated_records_for_skills, :autosave_associated_records_for_users, :becomes, :becomes!, :before_add_for_categories, :before_add_for_categories=, :before_add_for_categories?, :before_add_f or_enrollments, :before_add_for_enrollments=, :before_add_for_enrollments?, :before_add_for_skills, :before_add_for_skills=, :before_add_for_skills?, :before_add_for_users, :before_add_for_users=, :before_add_for_users?, :before_remove_for_categories, :before_remove_for_categories=, :before_remove_for_categories?, :before_remove_for_enrollments, :before_remove_for_enrollments=, :before_remo ve_for_enrollments?, :before_remove_for_skills, :before_remove_for_skills=, :before_remove_for_skills?, :before_remove_for_users, :before_remove_for_users=, :before_remove_for_users?, :blank?, :ca che_key, :cache_timestamp_format, :cache_timestamp_format?, :can_approve?, :can_deprecate?, :can_hide?, :can_publish?, :capture, :categories, :categories=, :category_ids, :category_ids=, :changed, :changed?, :changed_attributes, :changed_for_autosave?, :changes, :changes_applied, :class, :class_eval, :clear_aggregation_cache, :clear_association_cache, :clear_changes_information, :clear_dest roy_state, :clear_transaction_record_state, :clone, :clone_attribute_value, :column_for_attribute, :committed!, :concern, :connection_handler, :created?, :created_at, :created_at=, :created_at?, : created_at_before_type_cast, :created_at_change, :created_at_changed?, :created_at_was, :created_at_will_change!, :decrement, :decrement!, :deep_dup, :default_connection_handler, :default_connecti on_handler?, :default_scopes, :default_timezone, :define_singleton_method, :defined_enums, :defined_enums=, :defined_enums?, :delete, :deprecate, :deprecate!, :deprecate_transition, :deprecated?, :description, :description=, :description?, :description_before_type_cast, :description_change, :description_changed?, :description_was, :description_will_change!, :destroy, :destroy!, :destroyed? , :destroyed_by_association, :destroyed_by_association=, :display, :dump_schema_after_migration, :dup, :duplicable?, :enable_warnings, :encode_with, :enrollment_ids, :enrollment_ids=, :enrollments , :enrollments=, :enum_for, :eql?, :equal?, :error_on, :errors, :errors_on, :extend, :find_by_statement_cache, :find_by_statement_cache=, :find_by_statement_cache?, :fire_events, :fire_events!, :f ire_status_event, :force_clear_transaction_record_state, :freeze, :from_json, :from_xml, :frozen?, :gem, :handle, :handle=, :handle?, :handle_before_type_cast, :handle_change, :handle_changed?, :h andle_was, :handle_will_change!, :has_attribute?, :has_transactional_callbacks?, :hash, :hidden?, :hide, :hide!, :hide_transition, :html_safe?, :human_status_name, :id, :id=, :id?, :id_before_type _cast, :id_change, :id_changed?, :id_was, :id_will_change!, :in?, :include_root_in_json, :include_root_in_json=, :include_root_in_json?, :increment, :increment!, :init_with, :initialize_internals_ callback, :initialize_state_machines, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_values, :instance_variable_defined?, :instance_variable_get, :instance_variable_names, :ins tance_variable_set, :instance_variables, :invalid?, :is_a?, :is_haml?, :itself, :kind_of?, :load_dependency, :lock!, :lock_optimistically, :lock_optimistically?, :locking_enabled?, :logger, :mark_ for_destruction, :marked_for_destruction?, :method, :method_missing, :methods, :model_name, :name, :name=, :name?, :name_before_type_cast, :name_change, :name_changed?, :name_was, :name_will_chang e!, :nested_attributes_options, :nested_attributes_options?, :new_record?, :nil?, :no_touching?, :object_id, :organization, :organization=, :organization?, :organization_before_type_cast, :organiz ation_change, :organization_changed?, :organization_was, :organization_will_change!, :partial_writes, :partial_writes?, :perform_validations, :persisted?, :pluralize_table_names, :pluralize_table_ names?, :populate_with_current_scope_attributes, :presence, :presence_in, :present?, :pretty_inspect, :pretty_print, :pretty_print_cycle, :pretty_print_inspect, :pretty_print_instance_variables, : previous_changes, :primary_key_prefix_type, :private_methods, :protected_methods, :public_method, :public_methods, :public_send, :publish, :publish!, :publish_transition, :published?, :query_attri bute, :quietly, :quietly_with_deprecation_silenced, :quietly_without_deprecation_silenced, :quoted_id, :raise_in_transactional_callbacks, :raise_record_invalid, :read_attribute, :read_attribute_be fore_type_cast, :read_attribute_for_serialization, :read_attribute_for_validation, :read_store_attribute, :readonly!, :readonly?, :record_timestamps, :record_timestamps=, :record_timestamps?, :rel oad, :remember_transaction_record_state, :remove_instance_variable, :require_dependency, :require_or_load, :reset_created_at!, :reset_description!, :reset_handle!, :reset_id!, :reset_name!, :reset _organization!, :reset_status!, :reset_updated_at!, :respond_to?, :respond_to_without_attributes?, :restore_attributes, :restore_created_at!, :restore_description!, :restore_handle!, :restore_id!, :restore_name!, :restore_organization!, :restore_status!, :restore_transaction_record_state, :restore_updated_at!, :rollback_active_record_state!, :rolledback!, :run_callbacks, :run_validations!, :sanitize_for_mass_assignment, :sanitize_forbidden_attributes, :save, :save!, :schema_format, :send, :serializable_hash, :set_transaction_state, :should, :should_not, :silence, :silence_stderr, :s ilence_stream, :silence_warnings, :singleton_class, :singleton_class?, :singleton_methods, :skill_ids, :skill_ids=, :skills, :skills=, :skip_time_zone_conversion_for_attributes, :skip_time_zone_co nversion_for_attributes?, :slice, :status, :status=, :status?, :status_before_type_cast, :status_change, :status_changed?, :status_event, :status_event=, :status_event_transition, :status_event_tr ansition=, :status_events, :status_name, :status_paths, :status_transitions, :status_was, :status_will_change!, :store_full_sti_class, :store_full_sti_class?, :suppress, :suppress_warnings, :syck_ to_yaml, :table_name_prefix, :table_name_prefix?, :table_name_suffix, :table_name_suffix?, :taguri, :taguri=, :taint, :tainted?, :tap, :time_zone_aware_attributes, :timestamped_migrations, :to_enu m, :to_gid, :to_global_id, :to_json, :to_json_with_active_support_encoder, :to_json_without_active_support_encoder, :to_key, :to_model, :to_param, :to_partial_path, :to_query, :to_s, :to_sgid, :to _signed_global_id, :to_xml, :to_yaml, :to_yaml_properties, :to_yaml_style, :toggle, :toggle!, :touch, :transaction, :transaction_include_any_action?, :transaction_record_state, :trust, :try, :try! , :type_for_attribute, :unloadable, :untaint, :untrust, :untrusted?, :update, :update!, :update_attribute, :update_attributes, :update_attributes!, :update_column, :update_columns, :updated_at, :u pdated_at=, :updated_at?, :updated_at_before_type_cast, :updated_at_change, :updated_at_changed?, :updated_at_was, :updated_at_will_change!, :user_ids, :user_ids=, :users, :users=, :valid?, :valid ate, :validate!, :validate_associated_records_for_categories, :validate_associated_records_for_enrollments, :validate_associated_records_for_skills, :validate_associated_records_for_users, :valida tes_absence_of, :validates_acceptance_of, :validates_confirmation_of, :validates_exclusion_of, :validates_format_of, :validates_inclusion_of, :validates_length_of, :validates_numericality_of, :val idates_presence_of, :validates_size_of, :validates_with, :validation_context, :validation_context=, :with_lock, :with_options, :with_transaction_returning_status, :with_warnings, :write_store_attr ibute]
  35. @jmmastey macguffin.methods.grep /…?/

  36. @jmmastey The model in my head is what I use

    to search.
  37. HTTP Verb: DELETE SQL Statement: DELETE FROM * Arrays: delete,

    delete_at, delete_if Every OS Ever: DELETE
  38. @jmmastey macguffin.methods.grep /delete/ => [:delete]

  39. @jmmastey macguffin.destroy

  40. @jmmastey It’s completely unnecessary friction

  41. @jmmastey Gulf of Evaluation

  42. @jmmastey Did it work?

  43. @jmmastey This is easy(ish) in code

  44. @jmmastey macguffin.delete => #<MacGuffin id=75 …>

  45. @jmmastey macguffin.destroy => #<MacGuffin id=75 …>

  46. @jmmastey class MacGuffin private def self.retrieve … end end

  47. @jmmastey Natural Mappings

  48. @jmmastey

  49. @jmmastey

  50. @jmmastey What does that look like in code?

  51. @jmmastey my_stuff.sort

  52. @jmmastey my_stuff.first

  53. @jmmastey my_stuff.delete :foo

  54. @jmmastey brew update brew upgrade

  55. @jmmastey path realpath absolute_path dir_path realdirpath

  56. @jmmastey Design for Errors

  57. @jmmastey Software is screwed up most of the time

  58. None
  59. @jmmastey undefined is not a function

  60. @jmmastey “also, screw you”

  61. @jmmastey Spooky Nulls at a Distance

  62. @jmmastey Exploit the Power of Constraint

  63. @jmmastey Make it hard to do it the wrong way

  64. @jmmastey mysql --i-am-a-dummy

  65. @jmmastey irb(main):042:0>

  66. @jmmastey irb(main):042:0> User.last.destroy => <User name=“Ron Rando” …>

  67. None
  68. Whitney Hess

  69. @jmmastey “So You Wanna Be a User Experience Designer”

  70. @jmmastey 4. Group Related Objects

  71. @jmmastey Proximity implies relationship

  72. @jmmastey

  73. @jmmastey

  74. @jmmastey what about methods in a class?

  75. @jmmastey what about similarly named classes / methods?

  76. @jmmastey macguffin.accounts_add macguffin.accounts_delete macguffin.accounts_list

  77. @jmmastey 18. Be Consistent

  78. @jmmastey I’m not saying your code isn’t a beautiful and

    unique snowflake
  79. @jmmastey rails dbconsole production rails console production rails server -e

    production
  80. @jmmastey def update @macguffin = MacGuffin.find(params[:id]) … end def show_macguffin

    m = MacGuffin.find(params[:macguffin_id]) … end
  81. @jmmastey “gulp”.upcase => “GULP”

  82. @jmmastey “gulp”.upcase => “GULP” “GULP”.upcase => “GULP”

  83. @jmmastey “gulp”.upcase => “GULP” “GULP”.upcase => “GULP” “gulp”.upcase! => “GULP”

  84. @jmmastey “gulp”.upcase => “GULP” “GULP”.upcase => “GULP” “gulp”.upcase! => “GULP”

    “GULP”.upcase! =>
  85. @jmmastey “gulp”.upcase => “GULP” “GULP”.upcase => “GULP” “gulp”.upcase! => “GULP”

    “GULP”.upcase! => nil?!
  86. @jmmastey params[:product_code].upcase!

  87. @jmmastey params = { product_code: “foO” } # do work

    expect(macguffin.upc).to eq(“FOO”)
  88. @jmmastey Consistent with what?

  89. @jmmastey 16. Use Emotion

  90. @jmmastey We have an emotional relationship with the software we

    use
  91. @jmmastey A demonstration

  92. @jmmastey Rails

  93. @jmmastey Elm

  94. @jmmastey SOAP

  95. @jmmastey See?

  96. @jmmastey

  97. @jmmastey This isn’t about kitsch

  98. @jmmastey Warmth and kindness make software a pleasure to use

  99. @jmmastey 9. Avoid Jargon

  100. @jmmastey stop_csrfs versus protect_from_forgery

  101. @jmmastey AJAX

  102. @jmmastey def __private_method

  103. @jmmastey 7. Provide Signposts and Cues

  104. @jmmastey Where you came from, where you’re going

  105. @jmmastey [:!, :!=, :!~, :<=>, :==, :===, :=~, :Pathname, :[],

    : []=, :__class__, :__extend__, :__id__, :__instance_variable_defined_p__, :__instance_variable_get__, :__instance_variable_set__, :__instance_variables__, :__marshal__, :__respond_to_p__, :__send__ , :__show__, :_commit_callbacks, :_commit_callbacks=, :_commit_callbacks?, :_create_callbacks, :_create_callbacks=, :_create_callbacks?, :_destroy, :_destroy_callbacks, :_destroy_callbacks=, :_des troy_callbacks?, :_find_callbacks, :_find_callbacks=, :_find_callbacks?, :_initialize_callbacks, :_initialize_callbacks=, :_initialize_callbacks?, :_read_attribute, :_reflections, :_reflections=, :_reflections?, :_rollback_callbacks, :_rollback_callbacks=, :_rollback_callbacks?, :_run_commit_callbacks, :_run_create_callbacks, :_run_destroy_callbacks, :_run_find_callbacks, :_run_initialize_ callbacks, :_run_rollback_callbacks, :_run_save_callbacks, :_run_touch_callbacks, :_run_update_callbacks, :_run_validate_callbacks, :_run_validation_callbacks, :_save_callbacks, :_save_callbacks=, :_save_callbacks?, :_touch_callbacks, :_touch_callbacks=, :_touch_callbacks?, :_update_callbacks, :_update_callbacks=, :_update_callbacks?, :_validate_callbacks, :_validate_callbacks=, :_validate_ callbacks?, :_validation_callbacks, :_validation_callbacks=, :_validation_callbacks?, :_validators, :_validators=, :_validators?, :`, :acts_like?, :actually_destroyed?, :add_to_transaction, :after _add_for_categories, :after_add_for_categories=, :after_add_for_categories?, :after_add_for_enrollments, :after_add_for_enrollments=, :after_add_for_enrollments?, :after_add_for_skills, :after_add _for_skills=, :after_add_for_skills?, :after_add_for_users, :after_add_for_users=, :after_add_for_users?, :after_remove_for_categories, :after_remove_for_categories=, :after_remove_for_categories? , :after_remove_for_enrollments, :after_remove_for_enrollments=, :after_remove_for_enrollments?, :after_remove_for_skills, :after_remove_for_skills=, :after_remove_for_skills?, :after_remove_for_u sers, :after_remove_for_users=, :after_remove_for_users?, :aggregate_reflections, :aggregate_reflections=, :aggregate_reflections?, :approve, :approve!, :approve_transition, :approved?, :arel_attr ibutes_with_values_for_create, :arel_attributes_with_values_for_update, :as_json, :assign_attributes, :association, :association_cache, :attribute_aliases, :attribute_aliases?, :attribute_changed? , :attribute_changed_in_place?, :attribute_for_inspect, :attribute_method?, :attribute_method_matchers, :attribute_method_matchers?, :attribute_missing, :attribute_names, :attribute_present?, :att ribute_was, :attributes, :attributes=, :attributes_before_type_cast, :attributes_changed_by_setter, :autosave_associated_records_for_categories, :autosave_associated_records_for_enrollments, :auto save_associated_records_for_skills, :autosave_associated_records_for_users, :becomes, :becomes!, :before_add_for_categories, :before_add_for_categories=, :before_add_for_categories?, :before_add_f or_enrollments, :before_add_for_enrollments=, :before_add_for_enrollments?, :before_add_for_skills, :before_add_for_skills=, :before_add_for_skills?, :before_add_for_users, :before_add_for_users=, :before_add_for_users?, :before_remove_for_categories, :before_remove_for_categories=, :before_remove_for_categories?, :before_remove_for_enrollments, :before_remove_for_enrollments=, :before_remo ve_for_enrollments?, :before_remove_for_skills, :before_remove_for_skills=, :before_remove_for_skills?, :before_remove_for_users, :before_remove_for_users=, :before_remove_for_users?, :blank?, :ca che_key, :cache_timestamp_format, :cache_timestamp_format?, :can_approve?, :can_deprecate?, :can_hide?, :can_publish?, :capture, :categories, :categories=, :category_ids, :category_ids=, :changed, :changed?, :changed_attributes, :changed_for_autosave?, :changes, :changes_applied, :class, :class_eval, :clear_aggregation_cache, :clear_association_cache, :clear_changes_information, :clear_dest roy_state, :clear_transaction_record_state, :clone, :clone_attribute_value, :column_for_attribute, :committed!, :concern, :connection_handler, :created?, :created_at, :created_at=, :created_at?, : created_at_before_type_cast, :created_at_change, :created_at_changed?, :created_at_was, :created_at_will_change!, :decrement, :decrement!, :deep_dup, :default_connection_handler, :default_connecti on_handler?, :default_scopes, :default_timezone, :define_singleton_method, :defined_enums, :defined_enums=, :defined_enums?, :delete, :deprecate, :deprecate!, :deprecate_transition, :deprecated?, :description, :description=, :description?, :description_before_type_cast, :description_change, :description_changed?, :description_was, :description_will_change!, :destroy, :destroy!, :destroyed? , :destroyed_by_association, :destroyed_by_association=, :display, :dump_schema_after_migration, :dup, :duplicable?, :enable_warnings, :encode_with, :enrollment_ids, :enrollment_ids=, :enrollments , :enrollments=, :enum_for, :eql?, :equal?, :error_on, :errors, :errors_on, :extend, :find_by_statement_cache, :find_by_statement_cache=, :find_by_statement_cache?, :fire_events, :fire_events!, :f ire_status_event, :force_clear_transaction_record_state, :freeze, :from_json, :from_xml, :frozen?, :gem, :handle, :handle=, :handle?, :handle_before_type_cast, :handle_change, :handle_changed?, :h andle_was, :handle_will_change!, :has_attribute?, :has_transactional_callbacks?, :hash, :hidden?, :hide, :hide!, :hide_transition, :html_safe?, :human_status_name, :id, :id=, :id?, :id_before_type _cast, :id_change, :id_changed?, :id_was, :id_will_change!, :in?, :include_root_in_json, :include_root_in_json=, :include_root_in_json?, :increment, :increment!, :init_with, :initialize_internals_ callback, :initialize_state_machines, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_values, :instance_variable_defined?, :instance_variable_get, :instance_variable_names, :ins tance_variable_set, :instance_variables, :invalid?, :is_a?, :is_haml?, :itself, :kind_of?, :load_dependency, :lock!, :lock_optimistically, :lock_optimistically?, :locking_enabled?, :logger, :mark_ for_destruction, :marked_for_destruction?, :method, :method_missing, :methods, :model_name, :name, :name=, :name?, :name_before_type_cast, :name_change, :name_changed?, :name_was, :name_will_chang e!, :nested_attributes_options, :nested_attributes_options?, :new_record?, :nil?, :no_touching?, :object_id, :organization, :organization=, :organization?, :organization_before_type_cast, :organiz ation_change, :organization_changed?, :organization_was, :organization_will_change!, :partial_writes, :partial_writes?, :perform_validations, :persisted?, :pluralize_table_names, :pluralize_table_ names?, :populate_with_current_scope_attributes, :presence, :presence_in, :present?, :pretty_inspect, :pretty_print, :pretty_print_cycle, :pretty_print_inspect, :pretty_print_instance_variables, : previous_changes, :primary_key_prefix_type, :private_methods, :protected_methods, :public_method, :public_methods, :public_send, :publish, :publish!, :publish_transition, :published?, :query_attri bute, :quietly, :quietly_with_deprecation_silenced, :quietly_without_deprecation_silenced, :quoted_id, :raise_in_transactional_callbacks, :raise_record_invalid, :read_attribute, :read_attribute_be fore_type_cast, :read_attribute_for_serialization, :read_attribute_for_validation, :read_store_attribute, :readonly!, :readonly?, :record_timestamps, :record_timestamps=, :record_timestamps?, :rel oad, :remember_transaction_record_state, :remove_instance_variable, :require_dependency, :require_or_load, :reset_created_at!, :reset_description!, :reset_handle!, :reset_id!, :reset_name!, :reset _organization!, :reset_status!, :reset_updated_at!, :respond_to?, :respond_to_without_attributes?, :restore_attributes, :restore_created_at!, :restore_description!, :restore_handle!, :restore_id!, :restore_name!, :restore_organization!, :restore_status!, :restore_transaction_record_state, :restore_updated_at!, :rollback_active_record_state!, :rolledback!, :run_callbacks, :run_validations!, :sanitize_for_mass_assignment, :sanitize_forbidden_attributes, :save, :save!, :schema_format, :send, :serializable_hash, :set_transaction_state, :should, :should_not, :silence, :silence_stderr, :s ilence_stream, :silence_warnings, :singleton_class, :singleton_class?, :singleton_methods, :skill_ids, :skill_ids=, :skills, :skills=, :skip_time_zone_conversion_for_attributes, :skip_time_zone_co nversion_for_attributes?, :slice, :status, :status=, :status?, :status_before_type_cast, :status_change, :status_changed?, :status_event, :status_event=, :status_event_transition, :status_event_tr ansition=, :status_events, :status_name, :status_paths, :status_transitions, :status_was, :status_will_change!, :store_full_sti_class, :store_full_sti_class?, :suppress, :suppress_warnings, :syck_ to_yaml, :table_name_prefix, :table_name_prefix?, :table_name_suffix, :table_name_suffix?, :taguri, :taguri=, :taint, :tainted?, :tap, :time_zone_aware_attributes, :timestamped_migrations, :to_enu m, :to_gid, :to_global_id, :to_json, :to_json_with_active_support_encoder, :to_json_without_active_support_encoder, :to_key, :to_model, :to_param, :to_partial_path, :to_query, :to_s, :to_sgid, :to _signed_global_id, :to_xml, :to_yaml, :to_yaml_properties, :to_yaml_style, :toggle, :toggle!, :touch, :transaction, :transaction_include_any_action?, :transaction_record_state, :trust, :try, :try! , :type_for_attribute, :unloadable, :untaint, :untrust, :untrusted?, :update, :update!, :update_attribute, :update_attributes, :update_attributes!, :update_column, :update_columns, :updated_at, :u pdated_at=, :updated_at?, :updated_at_before_type_cast, :updated_at_change, :updated_at_changed?, :updated_at_was, :updated_at_will_change!, :user_ids, :user_ids=, :users, :users=, :valid?, :valid ate, :validate!, :validate_associated_records_for_categories, :validate_associated_records_for_enrollments, :validate_associated_records_for_skills, :validate_associated_records_for_users, :valida tes_absence_of, :validates_acceptance_of, :validates_confirmation_of, :validates_exclusion_of, :validates_format_of, :validates_inclusion_of, :validates_length_of, :validates_numericality_of, :val idates_presence_of, :validates_size_of, :validates_with, :validation_context, :validation_context=, :with_lock, :with_options, :with_transaction_returning_status, :with_warnings, :write_store_attr ibute]
  106. @jmmastey RTFM? STFU.

  107. @jmmastey User.find_by_email_and_first_name

  108. @jmmastey User.find_by(email: ‘’, first_name: ‘’)

  109. None
  110. @jmmastey 㽩 /export/nonce (master) > rspec bomb_spec.rb Failures: 1) MyObject

    works at all Failure/Error: expect(1).to eq(0) expected: 0 got: 1 … stacktrace … Finished in 0.00375 seconds (files took 0.29196 seconds to load) 1 example, 1 failure Failed examples: rspec ./bomb_spec.rb:4 # MyObject works at all
  111. @jmmastey 㽩 /export/nonce (master) > rspec bomb_spec.rb Failures: 1) MyObject

    works at all Failure/Error: expect(1).to eq(0) expected: 0 got: 1 … stacktrace … Finished in 0.00375 seconds (files took 0.29196 seconds to load) 1 example, 1 failure Failed examples: rspec ./bomb_spec.rb:4 # MyObject works at all
  112. @jmmastey 㽩 /export/nonce (master) > rspec bomb_spec.rb Failures: 1) MyObject

    works at all Failure/Error: expect(1).to eq(0) expected: 0 got: 1 … stacktrace … Finished in 0.00375 seconds (files took 0.29196 seconds to load) 1 example, 1 failure Failed examples: rspec ./bomb_spec.rb:4 # MyObject works at all
  113. @jmmastey rspec ./bomb_spec.rb:4 # MyObject works at all

  114. @jmmastey @macguffin = MacGuffin.find(1)

  115. @jmmastey So what’s the point?

  116. None
  117. @jmmastey “The world is filled with plenty of anguish —

    make your life goal not to add to it.”
  118. @jmmastey This is the mechanism for self documenting code

  119. @jmmastey The part where I ask you for things

  120. @jmmastey “So you wanna be a user experience designer” -

    Whitney Hess (http://bit.ly/1Hn1nQS) “The Design of Everyday Things” - Don Norman (I dunno, Amazon?)
  121. @jmmastey Thanks! Frustration Photo by jseliger2 (https://www.flickr.com/photos/91262622@N02/) Happy Kids by

    deepblue66 (https://www.flickr.com/photos/deepblue66/14503838952) Annotated code by Avdi Grimm (https://avdi.org) All icons from the NounProject (https://nounproject.com)