> For the complete documentation index, see [llms.txt](https://heronyang.gitbook.io/clean-up-your-spaghetti/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://heronyang.gitbook.io/clean-up-your-spaghetti/2_be_like_a_writer/function.md).

# 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.
