3/12/2019

Wait, but why?

Writing Code No One Else Can Read

Poorly written code is more costly in the long-run

  • more time to understand
  • more time to debug
  • more time to fix
  • more time to migrate
  • more time to test

Writing code is reading code

“Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …[Therefore,] making it easy to read makes it easier to write.”

– Robert C. Martin | Clean Code (p. 14)





So… be kind to your future self, and make your code easier to read.

Reading as a skill

Reading is a universal, trainable skill. Reading code is no exception.

  • Elementary Reading
    • “Do I understand the syntax of this line of code?”
  • Inspectional Reading
    • “If skim this file, do I understand what it is trying to do?”
  • Analytical Reading
    • “What is this application trying to do?”
  • Syntopical Reading
    • “What are these applications trying to do as a whole?”

Naming things is hard

How to make less bad names

Consider making your names:

  • Informative
  • Meaningfully Distinct
  • Consistent
  • Searchable
  • Contextual

Un-Informative Variables

d = 90 # elapsed time in days


What is good and bad about the context of this line?

  • Good: Comment provides context on the variable contents and usage
  • Bad: Later uses of d won’t have that same context attached

Informative Variables

elapsed_days = 90


What is so good about this version?

  • context is baked into elapsed_days
    • a numeric value
    • some representation of time that has passed
  • context will travel with the use of the variable

Un-Informative Functions

get_them = function(the_list){
  list1 = list()
  for (x in the_list) {
    if(x[0] == 4) {
      list1 = append(list1, x)
    }
  }
  return(list1)
}

What are the redeeming qualities of this function?

  • It runs, maybe.

Informative Functions

extract_flagged_orders = function(orders){
  flagged_orders = list()
  for (order in orders){
    if (is_flagged_order(order)){
      flagged_orders = append(flagged_orders, order)
    }
  }
  return(flagged_orders)
}

is_flagged_order = function(order){
  return(order[0] == 4)
}

What questions are left unanswered by the code above?

Meaningful distinctions

active_accounts        = harvest_active_accounts()
active_account_info    = collect_active_account_info()
active_account_data    = retrieve_active_account_data()
active_account_details = magically_generate_active_account_details()

Inconsistent names

ad_data             = fetch_adgroup_information(ids = ad_ids)
adgroup_performance = retrieve_ad_performance_data(x = ad_ids)
account_detail      = collect_adgroup_details(account_numbers)


Questions a reader might have:

  • What is the difference between fetch, collect, and retrieve?
  • What does ad_data and adgroup_performance contain? Why is it different?

Consistent names

adgroup_details     = collect_adgroup_details(ids = adgroup_ids)
adgroup_performance = collect_adgroup_performance(ids = adgroup_ids)
account_details     = collect_account_details(ids = account_ids)


  • What are the common verb(s)? What do they indicate?
    • collect, we are probably pulling in data
  • What are the common nouns (i.e., objects)?
    • adgroup, account, id, details
  • What additional knowledge does the reader need?
    • Probably need some context on paid search accounts and ad groups

Un-Searchable Names

for (ii in 1:length(ic)){
  if (it[ii] > ith){
     ti = ti + ic[ii]
  }
}

Searchable names helps find code when you are

  • fixing errors
  • refactoring
  • enhancing functionality

Searchable Names

for (impression_index in 1:length(impression_totals)){
  current_value = impressions[impression_index]
  if (current_value > impression_threshold){
    total_impressions = total_impressions + current_value
  }
}

Without context

library(zeallot)
generate_and_send_guess_statistics_message = function(character, count){
  
  if (count == 0) {
    c(number, verb, modifier) %<-% c("no", "are", "s")
  } else if (count == 1) {
    c(number, verb, modifier) %<-% c("1", "is", "")
  } else {
    c(number, verb, modifier) %<-% c(toString(count), "are", "s")
  }
  guess_message = sprintf("There %s %s %s%s", verb, number, character, modifier)
  print(guess_message)
}

With more context (and encapsulation)

create_and_print_guess_statistics_message = function(character, count){
  message = select_guess_statistics_message(character, count)
  print(message)
}

create_guess_statistics_messages = function(character, count){
  if (count == 0) { 
    return(create_no_count_message(character)) 
  }
  if (count == 1) { 
    return(create_single_count_message(character)) }
  }
  return(create_many_count_message(character, count))
}

And now the next layer down…

create_no_count_message = function(character){
  create_statistics_message("are", "no", character, "s")
}

create_single_count_message = function(character) {
  create_statistics_message("is", "1", character, "")
}

create_many_count_message = function(character, count) {
  create_statistics_message("are", toString(count), character, "s")
}

create_statistics_message = function(verb, number, character, modifier){
  sprintf("There %s %s %s%s", verb, number, character, modifier)
}

Now, an exercise.

Description: Find a partner and exchange a block of code you have written. 50-100 lines. Try and refactor the code based on our discussion while maintaining functionality. For the first 10 minutes try not to ask any questions, and allow the code to “speak” for itself.

Time: 30 Minutes Total

  • 10 Minutes - Refactor partner code, no questions
  • 10 Minutes - Refactor partner code, with questions
  • 10 Minutes - Review your results with your partner

Questions to keep in mind while you are refactoring?

  • Are the names of functions and variables informative?
  • Do the names provide meaningful distinction?
  • Are the verbs and nouns consistent throughout the block?
  • Are the key terms easy to search for?
  • Does each section of code provide enough context to make it understandable?