Don't use routes grouping functionality: a chance to rethinking your mindset of code reuse
Tags: go, discuss, productivity, antipattern
Published: 2022-06-04 14:06:56

## Issue

I've seen a lots of [Go](https://go.dev/) codes in my company's codebase, just like the example on [Gin's Group routes](https://github.com/gin-gonic/gin#grouping-routes), use this functionality to grouping the RESTful endpoints by just pulling some common prefix out for the sake of "reusability":

```go
router := gin.Default()
api := router.Group("/api")
api.POST("/login", loginEndpoint)
api.POST("/submit", submitEndpoint)
api.POST("/read", readEndpoint)
```

Even more, when we defined more RESTful manipulations on a  resource, we will more likely to refactor our code like this:

```go
api := router.Group("/api")
// ...
notification := api.Group("/notification")
notification.GET("/register", registerEndpoint)
notification.POST("/token/exchange", exchangeTokenEndpoint)
notification.POST("/token/revoke", revokeEndpoint)
// ...
```

If you ask yourself (or the junior engineer) why you code like this, probably the answer is: **I want to increase the code reusability for trying to make the code is better.**

So, what kind of problem behind this code?

## Reduce debugging time is more valuable for your life

It is very common to receive a bug description like following when your code has been deployed a few weeks:

"Client side receive an unexpected response like following..., when calling `/api/notification/token/revoke` endpoint with some request parameters..."

OK, we have a bug need to fix, and you know it is very possible there is a bug in the handling routine on that endpoint.

Thereafter, you open your IDE (e.g. VSCode) and search by the given endpoint `/api/notification/token/revoke` trying to find what handle function actually handling this endpoint.

But, nothing you got from searching results. **Because you split your URL path of endpoint into several parts by using the routes grouping functionality.**

So you try to search `api` or `revoke` word-by-word appeared on your codebase to approach the handle function, these journey is not very happy and time-consuming because you can expect that there are many noises on searching results.

## Rethink the benefits of code reusability

The benefits of code reuse is not just only thinking about you seem to reduce the development time when you create more and more routes, but should put more considerations on how you and other codebase maintainers would maintain and troubleshoot these codes.

I assume most programmers are more like coding instead of debugging, especially the bugged codes may be written in an unfamiliar coding style to you. (means the codes may be written by someone else or YOU in a few weeks ago.)

No one are happy to debug an unfamiliar codes, because you need to pay more cognitive loading to understand the codes. This activity is very unhappy and painful.

So, how to ease that pain?

## Proposed use cases of routes grouping functionality

From my experience, there is no benefits to group the routes by some prefixes or common path, but increasing the debugging cost in the future.

So, if you have no other actual requirements to use grouping functionality, just define routes in the explicitly way:

```go
router := gin.Default()
// ...
router.GET("/api/notification/register", registerEndpoint)
router.POST("/api/notification/token/exchange", exchangeTokenEndpoint)
router.POST("/api/notification/token/revoke", revokeEndpoint)
// ...
```

But what scenario you should actually consider to use routes grouping functionality? Some endpoints require authentication and some not.

The use case may looks like:

```go
router := gin.Default()
noAuth := router.Group("/")
noAuth.POST("/api/auth/login", loginEndpoint)

auth := router.Group("/", authMiddleware)
auth.GET("/api/notification/register", registerEndpoint)
auth.POST("/api/notification/token/exchange", exchangeTokenEndpoint)
auth.POST("/api/notification/token/revoke", revokeEndpoint)
// ...
```

## Conclusion
- Re-consider when you want to split your route definition into several parts, does it really gain any **benefits**?
- Put more considerations on how you would maintain your codes, try to find a way which suitable for you to ease the pain when debugging and troubleshooting