Slide 1

Slide 1 text

Writing Beautiful Code Anand Chitipothu

Slide 2

Slide 2 text

Who is speaking? Anand Chitipothu @anandology Advanced programing courses @pipalacademy Building data science platform @rorodata

Slide 3

Slide 3 text

quality without a name

Slide 4

Slide 4 text

Programs must be written for people to read, and only incidentally for machines to execute. - Structure and Interpretation of Computer Programs (The Wizard Book)

Slide 5

Slide 5 text

Choose Meaningful Names

Slide 6

Slide 6 text

Two hard things in computer science are cache invalidation and naming things. - Phil Karlton

Slide 7

Slide 7 text

Avoid Generic Names tmp tmp2 manager data

Slide 8

Slide 8 text

ucf = UpperCaseFormatter() ba = BankAccount() formatter = UpperCaseFormatter() account = BankAccount() Avoid Abbreviations

Slide 9

Slide 9 text

Avoid using datatype as name sum(list) count_words(string) sum(numbers) count_words(sentence)

Slide 10

Slide 10 text

Nouns & Verbs Use nouns for variables and classes. size, price, Task, Scheduler, Bank Account Use verbs for functions. get_file_size, make_account, deposit

Slide 11

Slide 11 text

largest_line(lines) files = os.listdir(directory) file = os.listdir(directory) for lines in open(filename).readlines(): sum += int(lines) Use plural for a list

Slide 12

Slide 12 text

Reserve Loop Indexes Use i, j only as loop indexes. for i in range(10): print i for i in numbers: result += i for n in numbers: result += n

Slide 13

Slide 13 text

Can you improve this? def get_data(x, y): z = [] for i in x: z.append(i[y]) return z Example 1

Slide 14

Slide 14 text

def get_column(dataset, col_index): column = [] for row in dataset: column.append(row[col_index]) return column Example 1

Slide 15

Slide 15 text

Never use similar names for completely different datatypes. a1 = [1, 2, 3] a2 = len(x) values = [1, 2, 3] n = len(x) Similar names

Slide 16

Slide 16 text

Comments

Slide 17

Slide 17 text

Don’t say the obvious # increments x by 2 x = x + 2 # compensate for border on both the sides x = x + 2

Slide 18

Slide 18 text

# The following is an optimization to saves # lot of memcache calls. Handle with care! ... Explain why you made that choice

Slide 19

Slide 19 text

# -- XXX -- Anand - Sep 2015 -- # UTF-conversion was failing for a chinese # user for reasons I couldn't understand. # Added "ignore" as second argument to handle # that temporarily. name = name.encode("utf-8", "ignore") Document special cases

Slide 20

Slide 20 text

# find length of the longest line n = max([len(line) for line in lines]) n = len(longest(lines)) Make Comments Redundant

Slide 21

Slide 21 text

Make Comments Redundant # process documents … # upload them to search engine … docs = process_documents(...) search_engine_submit(docs)

Slide 22

Slide 22 text

Program Organization

Slide 23

Slide 23 text

Divide & Conquer Split the program into small independent modules and functions.

Slide 24

Slide 24 text

The 7 ± 2 Rule The number of objects an average human can hold in working memory is 7 ± 2. - Miller's Law

Slide 25

Slide 25 text

def add(input_data): try: x = int(input_data['x']) except ValueError: raise Exception("Invalid int value for x") try: y = int(input_data['x']) except ValueError: raise Exception("Invalid int value for y") return x+y Avoid Duplication

Slide 26

Slide 26 text

def get_int(dictionary, key): try: return int(dictionary[key]) except ValueError: raise Exception("Invalid int value for {}".format(key)) def add(input_data): x = get_int(input_data, "x") y = get_int(input_data, "y") return x+y Avoid Duplication - generalize instead

Slide 27

Slide 27 text

Avoid too many nested levels def update_post(...): post = get_post(..) if action == 'update-title': if title == '': ... else: ... elif action == "add-tag": ...

Slide 28

Slide 28 text

def update_post(...): post = get_post(..) if action == "update-title": update_post_title(...) elif action == "add-tag": update_post_add_tag(...) Avoid too many nested levels

Slide 29

Slide 29 text

Handle errors separately def get_user(email): if valid_user(email): if is_user_blocked(email): return Exception("Account is blocked") else: query = "...." row = db.select(query).first() return User(row) else: raise Exception("Invalid email")

Slide 30

Slide 30 text

Handle errors separately def get_user(email): if not valid_user(email): raise ValueError("Invalid email") if is_email_blocked(email): raise Exception("Account blocked") query = "...." row = db.select(query).first() return User(row)

Slide 31

Slide 31 text

Suppress the implementation details def main(): filename = sys.argv[1] words = read_words(filename) freq = wordfreq(words) print_freq(freq)

Slide 32

Slide 32 text

Summary ● Choose meaningful variable names ● Use comments when required ● Split the program into small independent modules & functions ● Avoid duplication ● Suppress implementation details ● Always optimize for readability

Slide 33

Slide 33 text

- The Tao of Programming “A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little nor too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity.”

Slide 34

Slide 34 text

- The Tao of Programming “A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little nor too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity.”

Slide 35

Slide 35 text

“A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little nor too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity.” - The Tao of Programming

Slide 36

Slide 36 text

Happy Coding! @anandology