beyond the style guides

92
Beyond the Style Guides Mosky

Upload: mosky-liu

Post on 28-Jul-2015

235 views

Category:

Technology


1 download

TRANSCRIPT

Beyond the Style Guides

Mosky

It's all about time.

I can write a 4x faster program than you!!

But the hardware is super powerful now, it may be just 0.0001 ms v.s. 0.0004 ms.!

I can write 4x faster.!

And human brain haven't changed a lot,so it may be even 1 week v.s. 1 month.!

Human Time ⋙ Computer Time

- Benjamin Franklin

“Time is money.”

How to write faster?

Good language, e.g., Python!

Powerful libraries!

Experience!

∈ The things you can't change immediately.

Understandable codebase. i.e., codebase which has high maintainability.!

∈ You can just learn from this share.

Style Guide?

# It looks okay! count += 1

Not enough

# But it was initialized as count = '1'

# In JavaScript, # there's even no an error.

You remain only 10k days in your life.

Spend time on writing exciting feature, not debugging.

MoskyPython Charmer at Pinkoi!

The author of the Python packages!

MoSQL, Clime, …!

The speaker of the conferences,!

PyCon TW/JP/SG, …!

Also teaching Python!

mosky.tw

Outline

How human brain read code?!

Name thing meaningful but short.!

Paragraphing & Sectioning.!

Find the hidden “lines”.!

Face bad smell healthily.

Human Brain

A Computer

Read the code line by line.!

Cover all of the code, usually.!

Just complain when it doesn't understand.

A Human Brain

We can't read code like a computer.!

CPU is super slow, and even can't focus.!

RAM is tiny, programmer especially.!

Disk is losing bytes all the time.!

Nobody to complain.!

So we prefer to leave code alone.

But, computer is always complaining.!

We jump to the failed line.!

Read back from the line.!

Finally, we leave immediately after we fix it.

Or, new requirement comes.!

We still jump to the related line.!

Read back from the line.!

Finally, we also leave immediately after we finish it.

We read lines randomly.

Maintainability

To understand a random line, how many lines do you need to read back?!

Lesser → Higher maintainability

Name

Nothing But

Have a good dictionary.!

Be exact to avoid ambiguity.!

Be consistent to avoid misleading.!

Hint, hint, and hint.

Be Exact

“Apple”!

Which “Apple”?!

“Apple, the company.”!

apple_the_company

date_a-date_b

Which dates?!

today-joined_date

user

User's what?!

user_name

user_email

name

Who’s name?!

user_name

store_name

Be Consistent

Saw this in somewhere:!

apple = Company('apple')

Now you read:!

apple

Then you will guess it is a company. So don't:!

apple = Fruit('apple')

Too Long?

The context helps.!

fruit.py

apple

Type Hint

We operate variables.!

count += 1

parse(json)

If we know how to operate it at first glance,it saves time from tracing or running.!

Not the “Type Hint” in PEP 0484

Make It Intuitive

count

should be numeric!

name

string thing!

names

many strings; may be a list

page

page_no

so should be numeric!

event

event_key

so should be string stuff

List or Set?

requested_fields & allowed_fields

?!

set(requested_fileds) & allowed_field_set

List or Generator?

large_rows

large_rows[0] # ?

large_row_gen # generator

large_row_it # iterator

Object or Dict?

user

What is the type of user?!

user['name'] # ?

user.name # ?

user_dict['name']

user_d['name']

Is it a bool?

new_user

A bool? A User instance?!

is_new_user

A bool? A Function?!

new

user_is_new

Is it a function?

Use imperative, i.e., start with a verb.

.text

.json

A function? A string thing?!

.get_text

.parse_from_json

.text # string thing

def parse(x, return_dict=False): …

?!

def parse(x, to_return_dict=False): …

Explicit Unknown

arg

May be tuple, dict, or anything.!

arg_x

Avoid None

d = None if failed else {} d['key'] = value value = d.get('key')

It causes TypeError or AttributeError in Python,!

and extra effort in other language.!

Be consistent in type.

Some tips!

Raise exception.!

Use zero and infinite.!

Use constant.!

Filter the Nones out.

Content TypeUser Input!

The “Keys”!

URL!

JSON!

HTML!

SQL!

∈ string thing

json['keyword'] # ?

Actually the json is a dict-like.!

JSON: JavaScript Object Notation → a string!

arg_dict = json.loads(arg_json)

Transformation!

You can see the domain and codomain.

template.format(name)

If!

template # -> "<a>{}</a>"

name # -> "<script src=…></script>"

!

template_html.format(escape(name))

Safe :)!

“Making Wrong Code Look Wrong “

Abstract Type

it — iterator!

seq — sequence!

map — mapping

Structure Hint

We operate the variables.!

If we know how to operate it at first glance,it saves time from tracing or running.!

(Yeah, I copied it from the type hint.)

Map

users

A dict? What are the key and the value?

uid_user_map uid_user_map['mosky'] # -> User('mosky')

# ok users = { 'mosky': User('mosky'), … }

# even better uid_user_map = { 'mosky': User('mosky'), … }

Tuple

uid, name = uid_name_pair

a, b, c = a_b_c_tuple

key_value_pairs = sql('select key, value')

for key, value in key_value_pairs: …

key_value_map = dict(key_value_pairs)

Composite

If apply structure hint and type hint,!

It will be long.!

You may shorten.!

Keep long description in comment or doc.

Use common abbreviation!

http://abbreviations.com/!

Use acronym, e.g., rlname for really_long_name.!

Do comment if you use them.

# compromise between meaning and length # # event key: e.g., 'monthers_day' # config_d: config dict # # - start_date: … # … # event_key_config_d_map = { 'monthers_day': {…} }

# focus on reducing length # # ekey: event key # config: config dict # # - start_date: … # … # ekey_config_map = { 'monthers_day': {…} }

adj. new_user

past participle joined_date

present participle working_queue

infinitive keys_to_remove

another noun template_args

intn, m

i, j, k twd_int

int/range

page_no birth_month birth_daytids_idx

bool

new, joined user_is_new new_or_not new_bool

str name, month_str

str/key event_key

str/url next_url

str / json user_json

str/html page_html

str/sql to_update_sql

dict user_d, user_dict

list uids, uid_list

set uid_set

mapping uid_user_map

generator uid_gen

date start_date

datetime joined_dt

re email_re

decimal total_dec

currency total_currency, total_ccy total_twd

key uid_user_d_map

(x, y) uid_user_pair

[(x, y), …] uid_user_pairs

(x, y, z) uid_nick_email_tuple

Return Type Hint

We operate the variables.!

If we know how to operate it at first glance,it saves time from tracing or running.!

(Yeah, I copied it from type hint, again.)

.parse

What we will get?!

.parse_to_tree

.allow_to_log_in

Allow something to log in?!

.do_allow_to_log_in

If return value is a bool, use yes–no question.

Performance Hint

get_name # Memory op.

parse_from_json # CPU op.

query_html request_html # IO op.

Let people know the roughy cost.

Private Hint

“Don't touch me hint”!

A simple underscore prefix (_)!

Don't use me out of the module or file.!

Non-privates are just public APIs.

Hints

Type Hint!

Structure Hint!

Return Type Hint!

Performance Hint!

Private Hint

A random line now is more understandable.

Blank Line

Blank Line

Use blank line to separate your code into:!

Paragraph!

Section!

Like lightweight markup language,e.g., Markdown, RST.

Paragraph

Lines without any blank line.!

Group similar lines into a paragraph.!

Contains sub-paragraph.!

Use blank line to separate paragraphs.

try: html = read_html_from_cache(url) except IOError: html = request_html(url)

Section

Paragraphs.!

Group similar paragraphs into a section.!

Avoid sub-section.!

Use two blank lines to separate sections.

<section A's paragraph 1> <section A's paragraph 2> <section B's paragraph 1> …

Still don't understand? Try to read a paragraph, then a section.

The “Lines”

Dependency

The F function calls the G function.!

F depends on G.!

F → G!

It's a “Line”.

How messy?

Are the directions are all same?!

Usually ↑ in a file and files.!

Order your code.!

Are they point to limited sections or a files?!

Lesser is better.!

Section or modularize them.

At least, easier to trace.

Bad Smell

Reality

Don't have time to refactor.!

They actually work well.!

They itch you, but won't beat you.!

You may already understand.

So Just Seal It Off

Comment the pitfalls.!

Use # TODO rather than really refactor.!

Assign return value to a better named variable.!

Wrap them.!

Just write new code.

Stay focused.

Recap

Recap

We read lines randomly.!

Type hints and other hints!

Paragraph & section by blank line.!

Line your functions.!

Bad smell won't beat you.!

http://mosky.tw

Pinkoi

Pinkoi 亞洲最⼤大設計商品購物網站

Pinkoi a.k.a. 買禮物的好地⽅方

在找⼈人

⼀一定有適合你的職缺

Back-End Engineer Quality Assurance Engineer Data Engineer Search Engineer Android Engineer iOS Engineer

Pinkoi pinkoi.com/about/pinkoist