Slide 1

Slide 1 text

/** Code readability session 3 */ // Comments

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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): Boolean A long comment compared to the simplicity of the behavior Comments > Introduction

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

Topics - Documentation - Informal comment Comments > Documentation

Slide 17

Slide 17 text

Topics - Documentation - Informal comment Comments > Documentation

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Contents of documentation Let us take a look at anti-patterns first Comments > Documentation

Slide 21

Slide 21 text

Anti-patterns: Neglecting auto-generated comment /** * @param keyword * @return */ fun getDescription(keyword: String): String Comments > Documentation > Anti-patterns

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

Anti-patterns: Referring to private members /** * Returns a string stored in a private map [dictionary]. */ fun getDescription(keyword: String): String Comments > Documentation > Anti-patterns

Slide 25

Slide 25 text

Anti-patterns: No summary /** * Throws an exception if the given `keyword` is empty. */ fun getDescription(keyword: String): String Comments > Documentation > Anti-patterns

Slide 26

Slide 26 text

Anti-patterns: Mentioning to callers /** * ... * This is called by class [UserProfilePresenter]. */ fun getDescription(keyword: String): String Comments > Documentation > Anti-patterns

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

How to write short summary Techniques - Find an important part of code - Find common factors of code Comments > Documentation > Short summary

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

Limitations: Example - Arguments and receiver state - Instance lifecycle - Caller thread - Reentrancy - Calculation cost, memory size - External environment (e.g., network, database) Comments > Documentation > Details

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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 {... Comments > Documentation > Details

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

Topics - Documentation - Informal comment Comments > Informal comment

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

What requires informal comments - Large code - Complex/unintuitive code - Workaround Comments > Informal comment

Slide 55

Slide 55 text

What requires informal comments - Large code - Complex/unintuitive code - Workaround Comments > Informal comment

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

What requires informal comments - Large code - Complex/unintuitive code - Workaround Comments > Informal comment

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

What requires informal comments - Large code - Complex/unintuitive code - Workaround Comments > Informal comment

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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