Most of the population of people who have read Roy Fielding's dissertation tell us that, while we may understand HTTP verbs, we don't know anything about hypermedia. Our REST APIs, they say, are not really RESTful, and certainly do not exhibit Hypertext As The Engine Of Application State, or HATEOAS. The fact that we have APIs you need to read documentation to understand is a clear signal, they tell us, that the client is using out-of-band information to navigate the server. Hypermedia, they say, is the answer. We simply embed enough information in our responses that the client can intelligently choose what action to take next using only the contents of the HTTP response.
When designing a hypermedia API, you're really designing for a client that does not, and will never, exist. Imagine you're asked by your manager to create a "REST API" for your business. Knowing the latest trends in API design, you come up with a hypermedia-driven design that uses HAL or some such nonsense. When your manager asks you if the API is ready, you answer in the affirmative.
When he asks if the documentation is ready as well, you gleefully tell him
that such extraneous information is not necessary, and that your API
responses include enough information for smart clients to use the
API without any explicit documentation, minus a brief spec that
describes what your rel
values mean and so-forth.
Your manager then asks you again: "Is the documentation also ready?"
At this point, you hurry to write the "standard" REST documentation with explicit endpoints, the verbs they accept, and how to use them.
What you've really provided by writing the "standard" documentation is exactly
the thing that makes hypermedia APIs ridiculous: lack of semantic understanding.
There is no magical "smart client" that somehow knows that rel=comments
means
that the link leads to comments about the current resource and can figure out
it should POST
there to create a new comment. It has no idea what the hell a
"comment" is.
Unless you tell it explicitly. But using out-of-band information to give meaning to your content is not acceptable. Instead, you must wait for the "smart client" that will never exist. Why am I sure of that? Because if it did, then it would effectively be a single client that could make use of every single (properly built) REST API in existence without requiring documentation. What would that even mean?
Here's a question:
Why are we collectively trying to build servers for which there can never be acceptable clients.
People are trying to wrangle their APIs into hypermedia formats or (worse) inventing new ones, all because someone decided that everything must be self-documenting, despite the fact that the consumers of that implicit documentation (machines) have no hope of understanding it.
Why are we killing ourselves to build HATEOAS systems? Are today's "don't call me REST" REST APIs so broken that we must write code with our heads in the sand, pretending that if we solve the server side issues, the client side will eventually catch up? Well, news flash. It won't catch up. Ever.
Rather than striving for hypermedia systems, design ones that people can actually use without having to read 12 different specs and no documentation. Today's automated REST API documentation tools are fantastic, use them. Keep building "REST" APIs and calling them that, because there is no sensible alternative.
Of course, if you want to design a system using principles which, by definition, your system can never be said to use, go right ahead. In the meantime, I'll be getting stuff done.
Go has a very versatile toolchain and commands that makes Go programming fun. One of the famous tools is gofmt, which automatically reformats the code according to some predefined rules. However there are many other tools like goimports, oracle, godef, etc.. which help to provide a more productive workflow.
There are many independent vim plugins that integrate these tools into Vim. We also have the offical Vim plugins that provides some basic Go support for Vim. However there are many flaws with these plugins:
The main reason to create vim-go was to integrate all these plugins, fix the flaws and provide a common and seamless experience.
vim-go improves and supports the following features:
vim-go automatically installs all necessary binaries if they are not found in the pre-defined path ~/.vim-go
(can be disabled if not desired). It comes with pre-defined sensible settings. Under the hood it uses goimports
, oracle
, godef
, errcheck
, gocode
and golint
. Let's see how we can make use of those tools.
vim-go is a pathogen compatible bundle. To use it just clone it into your bundle directory:
$ cd ~/.vim/bundle $ git clone https://github.com/fatih/vim-go.git
Auto completion is enabled by default via <C-x><C-o>
, to get real-time completion (completion by type) install YCM:
$ cd ~/.vim/bundle $ git clone https://github.com/Valloric/YouCompleteMe.git $ cd YouCompleteMe $ ./install.sh
On first usage it tries to download and install all necessary binaries. Let's see what commands we now can use. Below is a list of commands vim-go supports, most of the commands are improved and new ones were introduced (some of them are just from the official Go plugin).
vim-go uses goimports and reformats whenever you save your file. However you have the option to disable goimports and explicitly import/drop packages:
:Import <path> :ImportAs <localname> <path> :Drop <path> :DisableGoimports :EnableGoimports
Godoc can be called on any identifier. Just put your cursor under the identifier and call :Godoc
, it will open a new view and show the necessary documentation.
:Godoc :Godoc <identifier>
Godef is one of my favorites tools. It's find the source definition and jumps to that file (go to definition). To use it just put your cursor under a identifier and hit :Godef
. It opens a new buffer (just like ctags). You might add the following settings to your vimrc
, to open the definitions in vertical, horizontal or new tab with :
au Filetype go nnoremap <leader>v :vsp <CR>:exe "GoDef" <CR> au Filetype go nnoremap <leader>s :sp <CR>:exe "GoDef"<CR> au Filetype go nnoremap <leader>t :tab split <CR>:exe "GoDef"<CR>
Building, testing, running are all important steps in development workflow and should be seamless integrated. vim-go has several features that you can use. First check out the build commands:
:make :GoBuild
:make
is the default Vim command to build a project. vim-go integrates it in way that it doesn't produce any binary. That it is really useful because it doesn't pollute your work environment. Any errors are listed in a quickfix window and can be jumped easily with default :cnext
and :cprevious
. :GoBuild
is similar to :make
, but it creates a binary for the given main package.
Sometimes we only have small main package that we can want to run and see the output. For that we have:
:GoRun :GoRun <expand>
Just calling :GoRun
is going to include all files that belongs to the main package (useful for multi file programs). To run a single file just run `:Gorun %`. You can map this to a key, like <leader>r
:
au Filetype go nnoremap <leader>r :GoRun %<CR>
To call `go test` just run:
:GoTest
Another tool we have is errcheck
, which checks unchecked errors:
:GoErrCheck
Linting is useful to print out mistakes or tips about coding style. For example if you don't provide any documentation comment for a function golint
will warn you. To call it just execute:
:Lint
To see the dependencies of your current package run :GoDeps
. If you have multiple files you can easily see all source files (test files are excluded) via :Gofiles
.
And then we have the still experimental but powerful "oracle" tool. See the extensive official documentation for more info: Oracle docs vim-go implements and includes the following commands (which are part of the offical oracle vim plugin):
:GoOracleDescribe :GoOracleCallees :GoOracleCallers :GoOracleCallgraph :GoOracleImplements :GoOracleChannelPeers
These are useful especially if you want to find out how your Code is structured, how your channels are interacting with each other, which struct is implementing which interface, etc...
Thanks for the following users and projects to make this project happen:
Check out the github page for fare more information (snippets, settings, etc..):
There is also a Youtube vide that shows vim-go in action:
Youtube: Go development in Vim
There are still tons of modifications and improvements one can make to this setup. vim-go is a new project. Check it out and try it to see how it fits your needs. Any improvements and feedback are welcome.