UX for Your Code

UX for Your Code

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 better, more usable code.

A9704266587836f7e784235e5073b93e?s=128

Joseph Mastey

April 23, 2015
Tweet

Transcript

  1. Bringing UX to Your Code Joe Mastey railsconf 2015

  2. @jmmastey | railsconf 2015 Joe Mastey @jmmastey josephmastey.com

  3. @jmmastey | railsconf 2015 I help companies build awesome internal

    education programs
  4. @jmmastey | railsconf 2015 I’ve worked in rails for five

    years
  5. @jmmastey | railsconf 2015 I am not a UX designer

    / developer
  6. None
  7. @jmmastey | railsconf 2015

  8. None
  9. @jmmastey | railsconf 2015 “Norman discussed door handles at length.”

    - Wikipedia
  10. None
  11. None
  12. It’s not your fault

  13. None
  14. None
  15. None
  16. @jmmastey | railsconf 2015 <rant>

  17. @jmmastey | railsconf 2015 Things We Ignore:

  18. @jmmastey | railsconf 2015 Things We Ignore: 1. Anything invented

    a long time ago
  19. @jmmastey | railsconf 2015 Things We Ignore: 1. Anything invented

    a long time ago 2. Anything invented by non-engineers
  20. None
  21. None
  22. None
  23. @jmmastey | railsconf 2015 < decades of research shit I

    made up
  24. @jmmastey | railsconf 2015 We’re missing out

  25. @jmmastey | railsconf 2015 Our code is an interface

  26. @jmmastey | railsconf 2015 </rant>

  27. @jmmastey | railsconf 2015 Let’s try it!

  28. @jmmastey | railsconf 2015 Gulf of Execution

  29. @jmmastey | railsconf 2015 Is there an action that corresponds

    to my intentions?
  30. @jmmastey | railsconf 2015 macguffin.methods.sort

  31. @jmmastey | railsconf 2015 [:!, :!=, :!~, :<=>, :==, :===,

    :=~, :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]
  32. @jmmastey | railsconf 2015 macguffin.methods.grep /…?/

  33. HTTP Verb: DELETE SQL Statement: DELETE FROM * Arrays: delete,

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

  35. @jmmastey | railsconf 2015 macguffin.destroy

  36. @jmmastey | railsconf 2015 Gulf of Evaluation

  37. @jmmastey | railsconf 2015 Did it work?

  38. @jmmastey | railsconf 2015 This is easy(ish) in code

  39. @jmmastey | railsconf 2015 macguffin.delete => #<MacGuffin id=75 …>

  40. @jmmastey | railsconf 2015 macguffin.destroy => #<MacGuffin id=75 …>

  41. @jmmastey | railsconf 2015 MacGuffin.destroy_all => 55

  42. @jmmastey | railsconf 2015 class MacGuffin private def self.retrieve …

    end end
  43. @jmmastey | railsconf 2015 Natural Mappings

  44. @jmmastey | railsconf 2015

  45. @jmmastey | railsconf 2015

  46. @jmmastey | railsconf 2015 What does that look like in

    code?
  47. @jmmastey | railsconf 2015 my_stuff.sort

  48. @jmmastey | railsconf 2015 my_stuff.first

  49. @jmmastey | railsconf 2015 my_stuff.delete :foo

  50. @jmmastey | railsconf 2015 brew update brew upgrade

  51. @jmmastey | railsconf 2015 path realpath absolute_path dir_path realdirpath

  52. @jmmastey | railsconf 2015 Design for Errors

  53. @jmmastey | railsconf 2015 Software is screwed up most of

    the time
  54. None
  55. @jmmastey | railsconf 2015 undefined is not a function

  56. @jmmastey | railsconf 2015 “also, screw you”

  57. @jmmastey | railsconf 2015 Spooky Nulls at a Distance

  58. @jmmastey | railsconf 2015 Exploit the Power of Constraint

  59. @jmmastey | railsconf 2015 Make it hard to do it

    the wrong way
  60. @jmmastey | railsconf 2015 mysql --i-am-a-dummy

  61. @jmmastey | railsconf 2015 irb(main):042:0>

  62. @jmmastey | railsconf 2015 irb(main):042:0> User.last.destroy => <User name=“Ron Rando”

    …>
  63. None
  64. None
  65. @jmmastey | railsconf 2015 “So You Wanna Be a User

    Experience Designer”
  66. @jmmastey | railsconf 2015 4. Group Related Objects

  67. @jmmastey | railsconf 2015 Proximity implies relationship

  68. @jmmastey | railsconf 2015

  69. @jmmastey | railsconf 2015

  70. @jmmastey | railsconf 2015 18. Be Consistent

  71. @jmmastey | railsconf 2015 “gulp”.upcase => “GULP”

  72. @jmmastey | railsconf 2015 “gulp”.upcase => “GULP” “GULP”.upcase => “GULP”

  73. @jmmastey | railsconf 2015 “gulp”.upcase => “GULP” “GULP”.upcase => “GULP”

    “gulp”.upcase! => “GULP”
  74. @jmmastey | railsconf 2015 “gulp”.upcase => “GULP” “GULP”.upcase => “GULP”

    “gulp”.upcase! => “GULP” “GULP”.upcase! =>
  75. @jmmastey | railsconf 2015 “gulp”.upcase => “GULP” “GULP”.upcase => “GULP”

    “gulp”.upcase! => “GULP” “GULP”.upcase! => nil?!
  76. @jmmastey | railsconf 2015 params[:product_code].upcase!

  77. @jmmastey | railsconf 2015 params = { product_code: “foO” }

    # do work expect(params[:product_code]) .to eq(“FOO”)
  78. @jmmastey | railsconf 2015 rails dbconsole production rails console production

    rails server -e production
  79. @jmmastey | railsconf 2015 16. Use Emotion

  80. @jmmastey | railsconf 2015 We have an emotional relationship with

    the software we use
  81. @jmmastey | railsconf 2015 A demonstration

  82. @jmmastey | railsconf 2015 Rails

  83. @jmmastey | railsconf 2015 SOAP

  84. @jmmastey | railsconf 2015 Adequate Record

  85. @jmmastey | railsconf 2015 CoffeeScript

  86. @jmmastey | railsconf 2015 See?

  87. @jmmastey | railsconf 2015

  88. @jmmastey | railsconf 2015 Warmth and kindness make software a

    pleasure to use
  89. @jmmastey | railsconf 2015 9. Avoid Jargon

  90. @jmmastey | railsconf 2015 Quiz Time!

  91. @jmmastey | railsconf 2015 Do you have CSRFs enabled on

    your app?
  92. @jmmastey | railsconf 2015 Do you use protect_from_forgery on your

    app?
  93. @jmmastey | railsconf 2015 AJAX

  94. @jmmastey | railsconf 2015 7. Provide Signposts and Cues

  95. @jmmastey | railsconf 2015 Where you came from, where you’re

    going
  96. @jmmastey | railsconf 2015 [:!, :!=, :!~, :<=>, :==, :===,

    :=~, :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]
  97. @jmmastey | railsconf 2015 RTFM? STFU.

  98. @jmmastey | railsconf 2015 user.find_by_email_and_first_name

  99. @jmmastey | railsconf 2015 user.find(email: ‘’, first_name: ‘’)

  100. None
  101. @jmmastey | railsconf 2015 㽩 /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
  102. @jmmastey | railsconf 2015 㽩 /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
  103. @jmmastey | railsconf 2015 㽩 /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
  104. @jmmastey | railsconf 2015 rspec ./bomb_spec.rb:4 # MyObject works at

    all
  105. @jmmastey | railsconf 2015 So what do I get?

  106. None
  107. @jmmastey | railsconf 2015 “The world is filled with plenty

    of anguish — make your life goal not to add to it.”
  108. @jmmastey | railsconf 2015 This is the mechanism for self

    documenting code
  109. @jmmastey | railsconf 2015 The part where I ask you

    for things
  110. @jmmastey | railsconf 2015 “So you wanna be a user

    experience designer” - Whitney Hess (http://bit.ly/1Hn1nQS) “The Design of Everyday Things” - Don Norman (I dunno, Amazon?)
  111. @jmmastey | railsconf 2015 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)