Download - The art of readable code (ch1~ch4)
![Page 1: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/1.jpg)
The Art of Readable Code (Ch1~Ch4)
Jonghan Seo
![Page 2: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/2.jpg)
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
![Page 3: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/3.jpg)
What Makes Code “Better”?● sometimes it is fairly obvious
![Page 4: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/4.jpg)
What Makes Code “Better”?● sometimes it is vague
more compact !!!
less intimidating !!!
![Page 5: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/5.jpg)
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
![Page 6: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/6.jpg)
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
![Page 7: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/7.jpg)
● 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
![Page 8: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/8.jpg)
Ch2. Packing Information into Names● Key Idea: Pack information into your names
● Six Specific Topics1. Choosing specific words2. Avoiding generic names (or knowing when to use them)3. Using concrete names instead of abstract names4. Attaching extra information to a name, by using a suffix or prefix5. Deciding how long a name should be6. Using name formatting to pack extra information
![Page 9: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/9.jpg)
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()
![Page 10: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/10.jpg)
1. Choose Specific Words
![Page 11: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/11.jpg)
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
![Page 12: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/12.jpg)
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
![Page 13: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/13.jpg)
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.
![Page 14: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/14.jpg)
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
![Page 15: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/15.jpg)
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
![Page 16: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/16.jpg)
4. Attaching Extra Information to a Name● string id; //Example: “af84ef845cd8”
→ string hex_id;
![Page 17: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/17.jpg)
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
![Page 18: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/18.jpg)
● 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?
![Page 19: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/19.jpg)
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);};
![Page 20: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/20.jpg)
● In Javascript:var x = new DatePicker(); // DatePicker() is a "constructor" functionvar 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
![Page 21: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/21.jpg)
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?
![Page 22: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/22.jpg)
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 = 10if shopping_cart.num_items() > MAX_ITEMS_IN_CART: Error("Too many items in cart.")
![Page 23: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/23.jpg)
Prefer first/last for inclusive Ranges
![Page 24: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/24.jpg)
Prefer begin and end for inclusive/exclusive Ranges
![Page 25: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/25.jpg)
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
![Page 26: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/26.jpg)
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()
![Page 27: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/27.jpg)
Matching Expectations of Users
● Example: Evaluating Multiple Name Candidates○ experiment_id: 100
description: ‘increase font size to 14pt’traffic_fraction: 5%…
○ experient_id: 101description: ‘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?
![Page 28: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/28.jpg)
● 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
![Page 29: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/29.jpg)
● ‘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
![Page 30: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/30.jpg)
Ch4. Aesthetics● How good use of spacing, alignment, and ordering can make your code
easier to read
● 3 principles:1. Use consistent layout2. Make similar code look similar3. Group related lines of code into blocks
![Page 31: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/31.jpg)
Rearrange Line Breaks to be Consistent and Compact
![Page 32: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/32.jpg)
Rearrange Line Breaks to be Consistent and Compact
![Page 33: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/33.jpg)
Use Methods to Clean up Irregularity
![Page 34: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/34.jpg)
Use Methods to Clean up Irregularity
![Page 35: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/35.jpg)
Use Column Alignment When Helpful
![Page 36: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/36.jpg)
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
![Page 37: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/37.jpg)
Organize Declarations into Blocksclass FrontendServer { public: FrontendServer(); void ViewProfile(HttpRequest* request); void OpenDatabase(string location, string user); void SaveProfile(HttpRequest* request); string ExtractQueryParam(HttpRequest* request, string param); void ReplyOK(HttpRequest* request, string html); void FindFriends(HttpRequest* request); void ReplyNotFound(HttpRequest* request, string error); void CloseDatabase(string location); ~FrontendServer();};
class FrontendServer { public:
FrontendServer();~FrontendServer();
// Handlersvoid ViewProfile(HttpRequest* request);void SaveProfile(HttpRequest* request);void FindFriends(HttpRequest* request);
// Request/Reply Utilitiesstring ExtractQueryParam(HttpRequest* request, string
param);void ReplyOK(HttpRequest* request, string html);void ReplyNotFound(HttpRequest* request, string
error);
// Database Helpersvoid OpenDatabase(string location, string user);void CloseDatabase(string location);
};
![Page 38: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/38.jpg)
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 Paragraphsdef 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)
![Page 39: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/39.jpg)
Key Idea: Consistent style is more important than the “right” style.
Personal Style vs. Consistency
![Page 40: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/40.jpg)
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○ Be aware of users’ expectation about certain words
![Page 41: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/41.jpg)
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
![Page 42: The art of readable code (ch1~ch4)](https://reader034.vdocuments.mx/reader034/viewer/2022052522/554f986cb4c90586258b46a6/html5/thumbnails/42.jpg)
Q&A
Any Questions?