Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Boost Maintainability

Boost Maintainability

In your codebase, to understand a random line, how many lines do you need to read back? Cloud you make it zero?

This talk will start with the impact of the maintainability, define the maintainability as “to understand a random line, the lines you need to read back”, show the practical techniques to make it zero, or nearly zero, and finally, reach the goal: boost the maintainability.

It's the revision of “Beyond the Style Guides” [1] and the talk at PyCon TW 2016 [2], PyCon APAC/KR 2016 [3], and GDG DevFest Taipei 2016 [4].

[1]: https://speakerdeck.com/mosky/beyond-the-style-guides
[2]: https://tw.pycon.org/2016
[3]: https://www.pycon.kr/2016apac/
[4]: https://devfest-taipei-3cbee.firebaseapp.com/

Mosky Liu

June 03, 2016
Tweet

More Decks by Mosky Liu

Other Decks in Programming

Transcript

  1. Boost
    Maintainability

    View Slide

  2. File "api.py", line 101, in generate_response
    next_page = page + 1
    TypeError: must be str, not int

    View Slide

  3. page + 1
    ?

    View Slide

  4. page = make_html(...)
    next_page = page + 1
    !

    View Slide

  5. We read lines randomly.


    View Slide

  6. page_html = make_html(...)
    next_page_no = page_no+1

    View Slide

  7. page_html + 1
    !

    View Slide

  8. — Joel on Software
    Making wrong code look wrong


    View Slide

  9. —Joel on Software
    Making Wrong Code Look Wrong
    • “Making Wrong Code Look Wrong”
    • http://bit.ly/joel-wrong
    • This talk will be more systemic than it.
    • But exception is good, IMO.

    View Slide

  10. Maintainability

    View Slide

  11. To understand a random line,
    the lines you need to read back.


    View Slide


  12. Time is just

    View Slide

  13. ❤ Python & Open Source
    Mosky
    • Backend Lead at Pinkoi.
    • Has spoken at:
    • PyCons in TW, JP, SG, HK, KR,
    MY, COSCUPs, and TEDx, etc.
    • Countless hours
    on teaching Python.
    • Own Python packages:
    • ZIPCodeTW,
    MoSQL, Clime, etc.
    • http://mosky.tw/

    View Slide

  14. Boost Maintainability
    • “Maintainability”
    • Lines need to read back.
    • Making It Zero
    • Progressive From Zero

    View Slide

  15. Making It Zero

    View Slide

  16. The
    Dominant Rule

    View Slide

  17. Be consistent & exact.


    View Slide

  18. user = User(user_id)
    buyer = user_id

    View Slide

  19. buyer = User(user_id)
    buyer_id = user_id

    View Slide

  20. result = ...
    result = ...

    View Slide

  21. resp = ...
    parsed_dict = ...

    View Slide

  22. Get a dictionary, please.

    View Slide

  23. Ops Clues

    View Slide

  24. page = ...

    View Slide

  25. page_no = ...
    page_html = ...

    View Slide

  26. requested_fields
    &
    allowed_fields
    ?

    View Slide

  27. set(requested_fields)
    &
    allowed_field_set

    View Slide

  28. user = User(...)
    user = {}
    ?

    View Slide

  29. user = User(...)
    user_dict = {}

    View Slide

  30. resp = requests.get(...)

    View Slide

  31. resp.text
    resp.json
    ?

    View Slide

  32. resp.text
    resp.json()
    !

    View Slide

  33. resp.text
    resp.parse_as_json()

    View Slide

  34. Req.is_secure()

    View Slide

  35. is_secure = True

    View Slide

  36. with_tls = True
    req_is_secure = True

    View Slide

  37. to_use_tls = True
    secure = True

    View Slide

  38. The General Rules
    Ops Clues
    • Clue the ops you should use.
    • _no: numeric.
    • : sequence, usually is mutable sequence (list).
    • _: if no intuitive way.
    • _:
    • _seq: for sequence.
    • _gen: for generator.
    • More: collections.abc – Python Docs.

    View Slide

  39. For Callable
    Ops Clues
    • _ = imperative sentence.
    • → boolean.
    • to_ → thing.
    • from_ ← thing.

    View Slide

  40. For Boolean
    Ops Clues
    • The normal objects took the nouns.
    • The callables took _ and .
    • We have:
    • _

    • to__

    View Slide

  41. For Return Value
    Ops Clues
    • Clue the return value:
    • get_page_no → numeric which >= 1.
    • query_user → user object.
    • parse_to_tree → tree object.

    View Slide

  42. Avoid None and Null
    Ops Clues
    • Consider:
    • user = query_user(uid)
    user.is_valid()
    • Then query_user returns None.
    • Boom! An AttributeError! ∵ None supports almost no op.
    • Accept an exception?
    • Y: Just raise when you wanna return None.
    • N: Use a dummy object like a dummy user or an empty str, etc.

    View Slide

  43. tmpl = '{}'
    tmpl.format(name)

    View Slide

  44. name = '...'
    !

    View Slide

  45. tmpl_html = ...
    tmpl_html.format(
    escape_to_html(name)
    )

    View Slide

  46. arg = parse(arg)
    ?

    View Slide

  47. arg_dict = parse(arg_json)

    View Slide

  48. str/x
    Ops Clues
    • _key: str/key (of a dict).
    • 'lowercase_n_underscore'
    • _json: str/json.
    • JSON is a string, not dict.
    • _url: str/url.
    • Clue percent-encoding;
    avoid URL injection.
    • _html: str/html.
    • Avoid XSS.
    • _sql: str/sql.
    • Avoid SQL injection.

    View Slide

  49. numeric/x
    Ops Clues
    • _no: number, #.
    • ≥ 1.
    • _idx: index.
    • ≥ 0.
    • Or just i, j, k.
    • _secs
    • It's seconds!
    • _pct
    • n = 10%
    n_pct = 10
    • _month, _day, ...
    • Use month_str if in string.

    View Slide

  50. Structure Clues

    View Slide

  51. users
    ?

    View Slide

  52. users = {
    'mosky': '[email protected]',
    ...
    }

    View Slide

  53. uid_email_dict = {
    'mosky': '[email protected]',
    ...
    }

    View Slide

  54. uid_email_dict

    View Slide

  55. uid_email_pairs = ...
    uid_email_dict = dict(↖)

    View Slide

  56. # select uid, email
    for uid, email in uid_email_pairs:
    ...

    View Slide

  57. For Dict & Tuple
    Structure Clues
    • __dict
    • For tuples:
    • _pair: 2-tuple.
    • _pairs: 2-tuples.
    • <1st>_<2nd>_<3rd>_tuple: n-tuple.

    View Slide

  58. Others

    View Slide

  59. “Don't use me!”
    • _
    • Don't use when out of:
    • A module.
    • A class.
    • Don't guarantee the behavior.
    • Make it easier to trace and refactor.
    Private Clues

    View Slide

  60. “Should I cache it?”
    Performance Clues
    • get_ / set_: memory op.
    • parse_ / calc_ : CPU-bound op.
    • query_: IO-bound op.
    • query_or_get_: IO-bound op with cache.

    View Slide

  61. Progressive
    From Zero

    View Slide

  62. Paragraph
    & Section

    View Slide

  63. def request_or_get(url):
    if has_cache(url):
    return get_cache(url)
    content = request(url)
    set_cache(url, content)
    return content

    View Slide

  64. # check arguments
    ...
    ...
    # query from tables
    ...
    ...
    ...
    ...
    # transform
    ...

    View Slide

  65. With Blank Line and Comment
    Paragraph & Section
    • Like writing in Markdown.
    • Paragraph:
    • A paragraph contains no blank line.
    • A blank line separates paragraphs.
    • Section:
    • A section contains paragraphs.
    • A comment with blank line separates sections.

    View Slide

  66. Line Units Up

    View Slide

  67. Func A
    Func U
    Func B
    Line No

    View Slide

  68. Func A
    Func U
    Func B
    Line No

    View Slide

  69. Func A
    Func U
    Func B
    Line No

    View Slide

  70. Func A
    Func U
    Func B
    Module 1
    Module 2

    View Slide

  71. By Calls
    Line Functions Up
    • Measure the “orderliness”.
    • Keep them have the same direction.
    • May become module.
    • Try to line the classes and modules up by the imports?

    View Slide

  72. Face
    Bad Smell

    View Slide

  73. Don't get lost!
    Face Bad Smell
    • Comment:
    • For the pitfalls, the actual return type, the side effects, etc.
    • Use # FIXME: ... or # XXX: ... .
    • Seal it:
    • good = poor()
    • def good(): poor()
    • Stay focused!

    View Slide

  74. Use clues to
    boost maintainability!

    View Slide

  75. Photo Credits
    • “The Money“
    https://commons.wikimedia.org/wiki/
    File:Forex_Money_for_Exchange_in_Currency_Bank.jpg
    • “The Bricks”
    https://pixabay.com/zh/%E5%BB%BA%E8%AE%BE-
    %E6%92%AD%E6%94%BE-%E7%8E%A9%E8%80%8D-
    %E4%B9%90%E8%B6%A3-%E5%88%9B%E6%84%8F-1159776/
    • Thanks!

    View Slide