fulldump/golax

View on GitHub
doc/developer.md

Summary

Maintainability
Test Coverage

<!-- MarkdownTOC autolink=true bracket=round depth=4 -->

- [Implementation decisions](#implementation-decisions)
    - [Decision #1: Only context](#decision-1-only-context)
    - [Decision #2: The Hollywood Principle](#decision-2-the-hollywood-principle)
    - [Decision #3: Interceptor flow](#decision-3-interceptor-flow)
    - [Decision #4: Custom methods](#decision-4-custom-methods)

<!-- /MarkdownTOC -->

# Implementation decisions

This part cover some of the implementation decisions taken along the development process.

## Decision #1: Only context

Handler functions has 1 parameter:

```
func (c *golax.Context) {
    
}
```

Why not `w`, `r` and `c` and maintain developer compatibility?

We would ended up with the following signature:

```
func (w http.ResponseWriter, r *http.Request, c *golax.Context) {
    
}
```

Old code is not going to work by doing copy&paste, but you only have to replace:

* `w` by `c.Response`
* `r` by `c.Request`

Making this decision is hard but `c *golax.Context` is much easier to remember and to write.

About code readability, `w.Write(...)` is shorter but `c.Response.Write(...)` is more semantic.

## Decision #2: The Hollywood Principle

Changing _Middleware_ vs _Interceptor_ is a semantic decision to break up with Sinatra styled frameworks.

Typical middlewares should call to `next()` to continue chaining execution. On the other hand, an interceptor has two parts `Before` and `After` and you don't have to call any `next()` or similar. It follows the _Hollywood Principle_ known as "Don't call us, we'll call you".


## Decision #3: Interceptor flow

![Normal flow](figure_1_normal_flow.png)

Each node in the routing hierarchy executes all its parent nodes interceptors. Why?

This is the desired behaviour for the 95% of the cases or even more. With several advantages:

* You don't have to repeat the interceptor (or middleware) in every endpoint.
* You get prettier, more readable and understandable code.
* Avoid human errors.


## Decision #4: Custom methods

Support for custom methods is a routing feature, you are free to use or not. It does not mean
coupling with other libraries or adding non-routing responsibilites.

If you do not use custom methods (`.Operation("your-custom-method")`) the router behaves
exactly as if it does not support them. In other words, it is backwards compatible.