Intention-revealing Code

computers, design, golang, pragmatic, programming, rant

Lets start off with very simple code:

1
2
3
4
5
6
7
func toJSON(post Post) string {
        return fmt.Sprintf(
                `{"post_title": "%s", "post_content": "%s"}`,
                post.Title,
                post.Content,
        )
}

This is very simple code and it is easy to understand what it is doing and what it is doing wrong:

  • It tries to marshal post struct to custom JSON representation.
  • It fails when there are special characters in these strings.
  • It does not use standard MarshalJSON interface.

It can be fixed in a pretty simple way:

1
2
3
4
5
6
func (post Post) MarshalJSON() ([]byte, error) {
        return json.Marshal(map[string]interface{}{
                "post_title":   post.Title,
                "post_content": post.Content,
        })
}

And at the usage site, you can now just use standard encoding/json package capabilities:

1
2
3
4
5
6
rawPost, err := json.Marshal(post)
if err != nil {
  return err
}

// do stuff with rawPost

And now you can notice that tests do not pass. And the place that failed is totally unrelevant. Long story short. Name of the original method was not revealing any real intent: it was actually specific json representation for usage with external API, but normal json.Marshal is used by this same application for providing responses to its own HTTP clients.

Were the name a bit more intention-revealing, nobody would waste their time on finding this out by trial and mistake:

1
2
3
4
// should probably even sit in different package
func marshalToExternalAPIFormat(post Post) ([]byte, err) {
        // ...
}

And this is only a tip of the iceberg of how non-intention-revealing code can trip you over.