The document summarizes key points from the first four chapters of the book "The Art of Readable Code" about writing code that is easy to read and understand. The chapters discuss techniques for improving variable and function names so they are more descriptive and unambiguous. Specifically, they cover packing important details into names, avoiding generic names, using consistent formatting and ordering of code, and breaking code into logical paragraphs. The goal is to minimize the time it would take someone unfamiliar with the code to understand it.
2. Ch1. Code Should Be Easy to
Understand
● collected bunch of examples of “bad code”
● analyzed what made them bad
● found principles/techniques that can be used to make them better
● Key Idea: Code should be easy to
understand
4. What Makes Code “Better”?
● sometimes it is vague
more compact !!!
less intimidating !!!
5. The Fundamental Theorem of Readability
● Code should be written to minimize the time it would take for someone
else to understand
● to fully understand your code:
○ be able to make changes to it
○ be able to spot bugs
○ be able to understand how it interacts with the rest of your code
● ‘someone else’ would be you
6. Some Different Views
● The Smaller The Better?
○ It probably takes less time to understand fewer lines BUT it is not
always better!
○ the time-till-understanding is an even better goal
● What about other constraints?
○ code efficiency? well architectured? easy to test? …
○ making code easy to understand often leads to meet the other rules
● the rest of this book discusses how to apply ‘easy to read’ in different
circumstances
7. ● There are four parts:
○ Part One: Surface-Level Improvements
○ Part Two: Simplifying Loops and Logic
○ Part Three: Reorganizing Your Code
○ Part Four: Selected Topics
● Surface-Level Improvements
○ picking good names
○ writing good comments
○ formatting your code neatly
Contents
8. Ch2. Packing Information into
Names
● Key Idea: Pack information into your names
● Six Specific Topics
1. Choosing specific words
2. Avoiding generic names (or knowing when to use them)
3. Using concrete names instead of abstract names
4. Attaching extra information to a name, by using a suffix or prefix
5. Deciding how long a name should be
6. Using name formatting to pack extra information
9. 1. Choose Specific Words
● def GetPage(url): …
○ from a local cache? from a database? from the Internet?
○ FetchPage(), DownloadPage()
● class BinaryTree {
int size();
...
}
○ height of the tree? the number of codes? memory footprint of the tree?
○ Height(), NumNodes(), MemoryBytes()
11. 2. Avoid Generic Names
● ‘tmp’, ‘retval’, loop iterators
● retval
○ var euclidean_norm = function (v) {
var retval = 0.0;
for (var i = 0 ; i < v.length; i += 1)
retval += v[i] * v[i];
return Math.sqrt(retval);
};
○ reval → sum_squares
○ sum_squares += v[i]; → spot a bug!!
○ Advice: Use a name that describes the variable’s value
12. 2. Avoid Generic Names
● tmp
○ if (right < left) {
tmp = right;
right = left;
left = tmp;
} // it is ok!
○ String tmp = user.name();
tmp += “ “ + user.phone_number();
…
template.set(“user_info”, tmp); // tmp → user_info
● Advice: ‘tmp’ should be used in cases when (1) being short-lived and (2)
temporary is the most important fact about the variable
13. 2. Avoid Generic Names
● Loop Iterators
○ for (int i = 0; i < clubs.size(); i++)
for (int j = 0; j < clubs[i].members.size(); j++)
for (int k = 0; k < users.size(); k++)
if (clubs[i].members[k] == users[j])
cout << "user[" << j << "] is in club[" << i << "]" << endl;
○ (i, j, k) → (club_i, memeber_i, users_i) or (ci, mi, ui)
○ if (clubs[ci].members[ui] == users[mi]) // Bug! First letters don't match up.
14. 3. Prefer Concrete Names Over
Abstract Names
● Example1) Google Code Guide for C++
○ #define DISALLOW_EVIL_CONSTRUCTORS(ClassName)
ClassName(const ClassName&);
void operator=(const ClassName&);
class ClassName {
private:
DISALLOW_EVIL_CONSTRUCTORS(ClassName);
};
○ ‘evil’ sounds too strong and more important, it isn’t clear what the
macro is disallowing
○ DISALLOW_COPY_AND_ASSIGN
15. 3. Prefer Concrete Names Over
Abstract Names
● Example2) --run_locally
○ --run_locally
■ printing debugging information
■ used when testing on a local machine
○ What if we need...
■ to print debugging information while the program run remotely?
■ to run a performance test locally (so we do not want the logging
slowing it down)?
○ --run_locally → --extra_logging
16. 4. Attaching Extra Information to a
Name
● string id; //Example: “af84ef845cd8”
→ string hex_id;
17. 5. How Long Should a Name be?
● the implicit constraint: ‘the name shouldn’t be too long’
○ the longer a name, the harder it is to remember and the more space it
consumes on the screen
○ However, if we take the constraint too far it also would make someone
else difficult to understand the code
18. ● There are some guidelines:
○ Shorter names are all right for shorter scope
○ Typing Long Names - Not a Problem Anymore
■ if ‘they’re harder to type’ mattered
■ Make full use of ‘word completion’ built in editors
○ Acronyms and Abbreviations
■ project-specific abbreviations: Bad Idea
■ common to programmers: OK!
● evaluation → eval, document → doc, string → str
○ Throwing out Unneeded Words
■ ConvertToString() → ToString()
■ DoServerLoop() → ServerLoop()
5. How Long Should a Name be?
19. 6. Use Name Formatting to
Convey Meaning
● In C++:
static const int kMaxOpenFiles = 100;
class LogReader {
public:
void OpenFile(string local_file);
private:
int offset_;
DISALLOW_COPY_AND_ASSIGN(LogReader);
};
20. ● In Javascript:
var x = new DatePicker(); // DatePicker() is a "constructor" function
var y = pageHeight(); // pageHeight() is an ordinary function
● in jQuery:
var $all_images = $("img"); // $all_images is a jQuery object
var height = 250; // height is not
● in HTML:
<div id=”middle_column” class=”main-content”>
6. Use Name Formatting to
Convey Meaning
21. Ch3. Names That Can’t Be
Misconstrued
● We have focused on how to put a lot of information into our names.
● We will do on a different topic: watching out for names that can be
misunderstood
● Key Idea: Actively scrutinize your names by asking yourself, “What other
meanings could someone interpret from this name?”
● example: filter()
○ results = Database.all_objects.filter("year <= 2011");
○ what does results now contain?
■ Objects whose year is <= 2011?
■ Objects whose year is not <= 2011?
22. Prefer min/max for (inclusive)
Limits
● CART_TOO_BIG_LIMIT = 10
if shopping_cart.num_items() >= CART_TOO_BIG_LIMIT:
Error("Too many items in cart.")
● MAX_ITEMS_IN_CART = 10
if shopping_cart.num_items() > MAX_ITEMS_IN_CART:
Error("Too many items in cart.")
25. Naming Booleans
● bool read_password = true;
○ We need to read the password: need_password
○ The password has already been read: user_is_authenticated
● adding words like is, has, can or should can make booleans more clear
○ SpaceLeft() → HasSpaceLeft()
● trying to avoid negated terms in a name
○ disable_ssl = false → use_ssl = true
26. Matching Expectations of Users
● Example: get*():
○ get: “lightweight accessors”
○ public double getMean() {
//Iterate through all samples and return total/num_samples
}
○ getMean() → computeMean()
● Example: list::size()
○ in C++, list::size() is an O(n) operation
○ size() → conuntSize(), countElements()
27. Matching Expectations of Users
● Example: Evaluating Multiple Name Candidates
○ experiment_id: 100
description: ‘increase font size to 14pt’
traffic_fraction: 5%
…
○ experient_id: 101
description: ‘increase font size to 13pt’
[other lines are identical to experiment_id 100]
...
○ ‘the_other_experiement_id_I_want_to_reuse: 100’ can be
renamed? If so, how?
28. ● Candidates:
○ template
○ reuse
○ copy
○ inherit
● ‘template’
○ experiment_id: 101
template: 100
○ ‘i am a template’ vs ‘i am using this other template’
○ ‘template’ is generally something abstract that must be filled in
● ‘reuse’
○ ‘This experiment can be reused at most 100 times’
Matching Expectations of Users
29. ● ‘copy’
○ ‘copy this experiment 100 times’ or ‘this is the 100th copy of
something’
● ‘inherit’
○ with inheritance
■ get all features from the inheritee
■ can modify inherited features
■ can add more own features
○ inherit_from_experiment_id might be the best
Matching Expectations of Users
30. Ch4. Aesthetics
● How good use of spacing, alignment, and ordering can make your code
easier to read
● 3 principles:
1. Use consistent layout
2. Make similar code look similar
3. Group related lines of code into blocks
36. Pick a Meaningful Order, and Use
It Consistently
● details = request.POST.get('details')
location = request.POST.get('location')
phone = request.POST.get('phone')
email = request.POST.get('email')
url = request.POST.get('url')
● some meaningful orders:
○ the order of the <input> field on the corresponding HTML form
○ from ‘most important’ to ‘least important’
○ alphabetically
38. def suggest_new_friends(user, email_password):
friends = user.friends()
friend_emails = set(f.email for f in friends)
contacts = import_contacts(user.email, email_password)
contact_emails = set(c.email for c in contacts)
non_friend_emails = contact_emails - friend_emails
suggested_friends = User.objects.select
(email__in=non_friend_emails)
display['user'] = user
display['friends'] = friends
display['suggested_friends'] = suggested_friends
return render("suggested_friends.html", display)
Break Code into Paragraphs
def suggest_new_friends(user, email_password):
# Get the user's friends' email addresses.
friends = user.friends()
friend_emails = set(f.email for f in friends)
# Import all email addresses from this user's email account.
contacts = import_contacts(user.email, email_password)
contact_emails = set(c.email for c in contacts)
# Find matching users that they aren't already friends with.
non_friend_emails = contact_emails - friend_emails
suggested_friends = User.objects.select(email__in=non_friend_emails)
# Display these lists on the page.
display['user'] = user
display['friends'] = friends
display['suggested_friends'] = suggested_friends
return render("suggested_friends.html", display)
39. Key Idea: Consistent style is more important than the
“right” style.
Personal Style vs. Consistency
40. Summary
● Ch2. Packing Information into your names
○ Use specific words
○ Avoid generic names
○ Use concrete names
○ Attach important details
○ Use longer names for larger scopes
○ Use capitalization, underscores, and so on in a meaningful way
● Ch3. Names That Can’t be Misconstrued
○ Use ‘max_/min_’ for an upper or lower limit for a value
○ Use ‘first/last’ for inclusive ranges
○ Use ‘begin/end’ for inclusive/exclusive ranges
○ Use words like is and has to make boolean variables clear
○ Avoid negated terms
41. Summary
● Ch4. Aesthetics
○ Try to give similar codes the similar silhouette
○ Align parts of the code into columns
○ Pick a meaningful order and stick with it
○ Break apart large blocks into logical paragraphs