# Function

```
FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. THEY SHOULD DO IT ONLY.
```

* Ideally, a function should be less than 15 \~ 20 lines.
* Describe the function by describing it as a brief TO paragraph: "To ..., we have firstly ..., then, ..."

Check our [previous example in Session 1](/clean-up-your-spaghetti/1_dont_code_now/what_clean_code.md).

## Sections within Functions

If one function is divided into sections like *declarations*, *initializations*, and *sieve*. It's wrong.

Again, functions should do one thing.

## One Level of Abstraction per Function

* Mixing levels of abstraction within a function is always confusing.

## Reading Code from Top to Bottom: The Stepdown Rule

* Connect with "TO paragraphs".
* Vertical distance of function definitions.

## Use Descriptive Names

* You know, it's important.
* Don't be afraid to make a name long.

## Function Arguments

* Less is better.
* Arguments are even harder from a testing point of view.
* The function and argument should form a very nice verb/noun pair.

## Have No Side Effects

* Side effects are lies. Your function promises to do one thing, but it also does other hidden things.

```java
public class UserValidator {
    private Cryptographer cryptographer;
    public boolean checkPassword(String userName, String password) {
        User user = USerGateway.findByName(userName);
        if (user != User.NULL) {
            String codedPhrase = user.getPhraseEncodedByPassword();
            String phrase = cryptographer.decrypt(codedPhrase, password);
            if ("Valid Password".equals(phrase)) {
                Session.initialize();
                return true;
            }
        }
        return false;
    }
}
```

Can you find the effect side in this function?

## Prefer Exceptions to Returning Error Codes

When you return an error code, you create the problem that the caller must deal with the error immediately.

```java
if (deletePage(page) == E_OK) {
    if (registry.deleteReference(page.name) == E_OK) {
        if (configKeys.deleteKey(page.name.makeKey() == E_OK)) {
            logger.log("page deleted");
        } else {
            logger.log("configKey not deleted");
        }
    } else {
        logger.log("deleteReference from registry failed");
    }
} else {
    logger.log("delete failed");
    return E_ERROR;
}
```

But, if we use try/catch:

```java
try {
    deletePage(page);
    registry.deleteReference(page.name);
    configKeys.deleteKey(page.name.makeKey());
} catch (Exception e) {
    logger.log(e.getMessage());
}
```

## Don't Repeat Yourself

Duplication may be the root of all evil in software.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://heronyang.gitbook.io/clean-up-your-spaghetti/2_be_like_a_writer/function.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
