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

Code readability: Session 3 (ver. 2, En)

Code readability: Session 3 (ver. 2, En)

Munetoshi Ishikawa

May 11, 2023
Tweet

More Decks by Munetoshi Ishikawa

Other Decks in Programming

Transcript

  1. Brushup: Naming Use accurate and descriptive names - What to

    describe: "what" rather than "who/when" - Grammar: word order - Word selection: narrow meaning, non-abbreviated, affirmative
  2. Contents of this lecture - Introduction and Principles - Natural

    language: Naming, Comments - Inner type structure: State, Function - Inter type structure: Dependency I, Dependency II - Follow-up: Review Comments > Introduction
  3. Comment Explanations or notes written in the code - Usually

    ignored by a complier/interpreter /** * Explanation of `fooFunction`... */ fun fooFunction(parameter: Parameter /* note of the parameter */) { barFunction() // Explanation of why `barFunction` is called /* A comment with multiple lines. */ Comments > Introduction
  4. Benefits of comments - Makes code easy to understand -

    Prevents mistakes - Helps refactoring We do not need a comment if the code is simple enough (depending on the convention) Comments > Introduction
  5. Benefits of comments - Makes code easy to understand -

    Prevents mistakes - Helps refactoring We do not need a comment if the code is simple enough (depending on the convention) Comments > Introduction
  6. Refactoring with comments: Example /** * Adds a new pair

    of keyword and the definition to this dictionary, * can be referenced by [getDefinition(String)]. * * If the keyword is already registered, this registration fails. * Then, this returns a boolean representing whether the registration * succeeded. */ fun add(newData: Pair<String, String>): Boolean A long comment compared to the simplicity of the behavior Comments > Introduction
  7. Refactoring with comments: Refactoring plan Determine why a long comment

    is needed Ideas for improvement - Rename the function - Split the parameter - Simplify the error cases - Remove the unnecessary return value Comments > Introduction
  8. Refactoring with comments: Refactoring result /** * Adds or overwrites

    a definition of a given [keyword]. * The registered definition is obtained by [getDefinition(String)]. */ fun registerDefinition(keyword: String, definitionText: String) For simple behavior, write a simple comment Comments > Introduction
  9. Types of comments - Documentation: Formal comment for class/variable/function... /**

    * A list of pairs of a string keyword and the explanation text. * * ... (details of usage, limitations, etc.)... */ class Dictionary { ... } Comments > Introduction
  10. Types of comments - Documentation: Formal comment for class/variable/function... -

    Informal comment: Comment written at various places in code // Call `toList` here to create a copied list explicitly. val listSnapshot = list.toList() Comments > Introduction
  11. Types of comments - Documentation: Formal comment for class/variable/function... -

    Informal comment: Comment written at various places in code - To do comments: // TODO: , // FIXME: Comments > Introduction
  12. Types of comments - Documentation: Formal comment for class/variable/function... -

    Informal comment: Comment written at various places in code - To do comments: // TODO: , // FIXME: - Comments for IDE/compiler/code-generation: // $COVERAGE-IGNORE$ Comments > Introduction
  13. Types of comments - Documentation: Formal comment for class/variable/function... -

    Informal comment: Comment written at various places in code - To do comments: // TODO: , // FIXME: - Comments for IDE/compiler/code-generation: // $COVERAGE-IGNORE$ Comments > Introduction
  14. Roles of documentation and informal comment Documentation - Allows to

    understand code without reading it - Explains what it is/does Informal comment - Helps understand code while reading it - Explains the overview, reason, background and pitfalls Comments > Introduction
  15. What we write documentation for - Class, interface, enum, struct,

    protocol, trait... - Variable, property, field, parameter, constant value... - Function, method, procedure, subroutine... - Scope, package, module, namespace... Comments > Documentation
  16. Format of documentation Starts with... - `/**` for Kotlin, Java,

    Swift and Objective-C - `///` for Swift and Objective-C - `/*!` for Objective-C Follow the format of documentation generator e.g., KDoc, Javadoc, Swift Markup, HeaderDoc, Doxygen Comments > Documentation
  17. Anti-patterns: Neglecting auto-generated comment /** * @param keyword * @return

    */ fun getDescription(keyword: String): String Comments > Documentation > Anti-patterns
  18. Anti-patterns: Same as the name /** * Gets the description

    for a keyword. */ fun getDescription(keyword: String): String Comments > Documentation > Anti-patterns
  19. Anti-patterns: Translation of the code /** * Calls [doA] if

    `conditionA` is satisfied. * Otherwise, calls [doB] and if ... */ fun getDescription(keyword: String): String { if (conditionA) { doA() } else { doB() if (...) {...} } Comments > Documentation > Anti-patterns
  20. Anti-patterns: Referring to private members /** * Returns a string

    stored in a private map [dictionary]. */ fun getDescription(keyword: String): String Comments > Documentation > Anti-patterns
  21. Anti-patterns: No summary /** * Throws an exception if the

    given `keyword` is empty. */ fun getDescription(keyword: String): String Comments > Documentation > Anti-patterns
  22. Anti-patterns: Mentioning to callers /** * ... * This is

    called by class [UserProfilePresenter]. */ fun getDescription(keyword: String): String Comments > Documentation > Anti-patterns
  23. Lessons from anti-patterns Write documentation only when explanation is required

    - Fine to skip if type/value/procedure name is enough Summarize "what it is/does" - Without mentioning to callers - Without using implementation details Comments > Documentation > Anti-patterns
  24. Contents of documentation Short summary (Mandatory) "What it is/does" in

    a phrase/sentence Details (Optional) Additional sentences to explain usages, limitations, and so on Comments > Documentation > Overview
  25. Contents of documentation Short summary (Mandatory) "What it is/does" in

    a phrase/sentence Details (Optional) Additional sentences to explain usages, limitations, and so on Comments > Documentation > Short summary
  26. How to write short summary Techniques - Find an important

    part of code - Find common factors of code Comments > Documentation > Short summary
  27. How to write short summary: Important code 1/2 Find the

    most important line, block, element of the code if (!user.isValid) return val rawProfileImage = getProfileImage(user.id, ...) val roundProfileImage = applyRoundFilter(rawProfileImage, ...) profileView.setImage(roundProfileImage) Comments > Documentation > Short summary
  28. How to write short summary: Important code 2/2 Complement information

    based on the most important point /** * Shows a roundly cut profile image of a given [user]. * ... */ ... profileView.setImage(roundProfileImage) The summary will also be a good hint for naming Comments > Documentation > Short summary
  29. How to write short summary: Common factor Abstract common factors

    of the code /** * Updates message layout with a newly received message data. */ fun ...(receivedMessageData: MessageData) { messageView.text = receivedMessageData.contentText senderNameView.text = receivedMessageData.senderName timestampView.text = receivedMessageData.sentTimeText } Comments > Documentation > Short summary
  30. Convention of short summary Refer to standard library documents Examples:

    Kotlin, Java, Swift, Objective-C - Class, variable: Starts with a noun phrase e.g., "A generic ordered collection of elements."4 - Function: Starts with a verb with 3rd-person singular form e.g., "Adds a new element at the end of the array."5 5 https://developer.apple.com/documentation/swift/array/3126937-append 4 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/#list Comments > Documentation > Short summary
  31. Contents of documentation Short summary (Mandatory) "What it is/does" in

    a phrase/sentence Details (Optional) Additional sentences to explain usages, limitations, and so on Comments > Documentation > Details
  32. Contents of "details" in documentation - Specification and usage -

    Function return value - Limitation and error values/conditions - Examples - ... Comments > Documentation > Details
  33. Contents of "details" in documentation - Specification and usage -

    Function return value - Limitation and error values/conditions - Examples Comments > Documentation > Details
  34. Specification and usage Comment on typical usage and expected behavior

    /** * ... * To update view components such as message text and sender name, * give [MessageData] model object to [bindView]. */ class MessageViewPresenter(messageView: View) Comments > Documentation > Details
  35. Contents of "details" in documentation - Specification and usage -

    Function return value - Limitation and error values/conditions - Examples Comments > Documentation > Details
  36. Function return value 1/2 Question: What does the following return

    value mean? fun setSelectedState(isSelected: Boolean): Boolean Possible answer: isToggled // true if the state is changed wasSelected // previous state before the function call isSuccessfullyUpdated // true if there is no error isSelected // pass through the given `isSelected` value ... Comments > Documentation > Details
  37. Function return value 2/2 Comment on a return value if

    the function name is not enough - has side effects for function call - has contract on the return value Comments > Documentation > Details
  38. Function return value 2/2 Comment on a return value if

    the function name is not enough - has side effects for function call - has contract on the return value /** * ... * ... returns true if it was selected before this function call. */ fun setSelectedState(isSelected: Boolean): Boolean Comments > Documentation > Details
  39. Function return value 2/2 Comment on a return value if

    the function name is not enough - has side effects for function call - has contract on the return value /** * ... * The profile ID is non-negative value. */ fun getProfileId(): Int Comments > Documentation > Details
  40. Contents of "details" in documentation - Specification and usage -

    Function return value - Limitation and error values/conditions - Examples Comments > Documentation > Details
  41. Limitation and error values/status Comment on the precondition and what

    happens on violation - A required receiver state to call a function - Restrictions on the arguments Comments > Documentation > Details
  42. Limitation and error values/status Comment on the precondition and what

    happens on violation - A required receiver state to call a function - Restrictions on the arguments /** * ... * [prepare] must be called before calling [play] or [seek], * or this throws [ResourceNotReadyException]. */ class VideoPlayer(videoPath: String) Comments > Documentation > Details
  43. Limitation and error values/status Comment on the precondition and what

    happens on violation - A required receiver state to call a function - Restrictions on the arguments /** * ... * Returns `null` if the given `position` is out of the array range. */ fun valueAt(position: Int): T? Comments > Documentation > Details
  44. Limitations: Example - Arguments and receiver state - Instance lifecycle

    - Caller thread - Reentrancy - Calculation cost, memory size - External environment (e.g., network, database) Comments > Documentation > Details
  45. Contents of "details" in documentation - Specification and usage -

    Function return value - Limitation and error values/conditions - Examples Comments > Documentation > Details
  46. Examples Make code more understandable with examples - Example code

    for usage - Parameter or return value example /** * ... For example, this returns `listOf("a", "bc", "", "d")` * for argument `"a, bc ,,d"` */ fun splitByComma(string: String): List<String> {... Comments > Documentation > Details
  47. Documentation: Summary Target: class, variable, function, scope Contents: short summary

    (mandatory), details (optional) Cautions: - Write only when the name is insufficient as explanation - Do not mention to the caller or the implementation detail Comments > Documentation > Summary
  48. What informal comment is: Kotlin case // Function explanation, which

    won't appear on KDoc fun function(param /* Parameter explanation */: Param) { // Code block summary someMethod(value) // Reason of a statement newId = param.id + 123 /* Reason of constant value */ + ... ... - Comment with whatever helps readers - Short summary is not mandatory Comments > Informal comment
  49. Informal comment for large code Make code blocks with comments

    to summarize what they do ... val messageKey = ... val messageData = messageCache[messageKey] ... if (messageData == null || ...) { // <- When this satisfies? ... // <- Hard to overview code in a nest } Comments > Informal comment
  50. Informal comment for large code Make code blocks with comments

    to summarize what they do // Get message data cache if it's available val messageKey = ... val messageData = messageCache[messageKey] ... // Load message data from DB if there's no cached data. if (messageData == null || ...) { ... } Comments > Informal comment
  51. Informal comment for unintuitive code Explain summary/reason if it is

    hard to understand // // wordReplacementData.reverse() .forEach { (startIndex, endIndex, newText) -> stringBuilder.replace(startIndex, endIndex, newText) } Question: Why do we need to call reverse()? Comments > Informal comment
  52. Informal comment for unintuitive code Explain summary/reason if it is

    hard to understand // Replace texts in the reverse order because `replace()` // affects the following indices. wordReplacementData.reverse() .forEach { (startIndex, endIndex, newText) -> stringBuilder.replace(startIndex, endIndex, newText) } Prevent from removing reverse() by incorrect "refactoring" Comments > Informal comment
  53. Informal comment for workaround Explain what a workaround does and

    explain the reason // We restore the previous state here // because libraryFunction() may break the receiver state Add links to explain // To avoid Device-X specific tinting bug (see, ISSUE-123456) Comments > Informal comment
  54. Informal comments: Summary Essentially the same as documentation - Short

    summary is not mandatory Explain large, complex, unintuitive code - Code block, summary, reason, links Comments > Informal comment
  55. Summary - Comment with whatever readers require - Refactor before/after

    writing comments - Documentation: Short summary (mandatory) and details (optional) - Informal comment: Explanations for large, complex, unintuitive code Comments > Summary