Tuesday, October 06, 2009

Getters and setters in vim

While writing an entity class, it's likely you have to manually write a bunch of methods to modify the state of the object, such as setName(), getName(), setDescription(), etc... It is very simple to setup vim, the powerful editor, for setters and getters prototyping, allowing you to tweak them after the one-time generation to add constraints on the parameters and docblock annotations. The boilerplate code for getters and setters can be very boring to write and this tutorial can save you quite some time if you invest a little in setting up this system.
In this how-to I will cover the php case, but feel free to change the template code for the language you want to use.

Disclaimer: I am not suggesting every class should have getters and setters; quite the contrary. In my opinion only certain classes whose responsibility is to maintain state should have these kind of methods, while stateless services should have no getters and no setters as their collaborators are wired in the constructor.

Step 1: vim snippets system
The first step to perform is downloading snippetsEmu, the set of vim scripts which provides support for snippet management. snippy_plugin.vba contains the plugin, while the package snippy_bundles.vba consists in out-of-the-box snippets for various languages, from php to python and C.
The workflow with this plugin is straightforward: you type a keyword for the snippet you want to use (for instance "for" or "if") while in Insert mode, and press Tab. Then the template code is inserted and you are asked to insert the variables of this template, filling in the blanks and pressing tab after each specification. Variables consist in identifiers and of every piece of code that cannot be predetermined too.
For instance, once the system is in place, to create a for construct you would type:
and the result will be:
for ( $i=1; $i < 10; $i++ )
Obviously you can tweak the template of the for snippet to accomodate your coding standard. It's simpler to try it than to explain it.
The installation is a quick process: open the downloaded .vba file with vim and type
:source %
while in Command mode. The vimball system will install the scripts in your .vim directory.

Step 2: setting up .vimrc
Now we need to include the scripts and define the getters/setters template every time vim is started. To do this, we can use the .vimrc hidden file in your home directory, which is read at vim's startup and whose commands are executed as if they were typed in vim Command mode.
These are the lines you need to add to .vimrc for php getters and setters support:
set tabstop=4
set shiftwidth=4
set expandtab
set autoindent
setlocal comments=sr:/*,mb:*,ex:*/
setlocal fo=cqort
source ~/.vim/plugin/snippetsEmu.vim
source ~/.vim/after/ftplugin/php_snippets.vim
exec "Snippet getset /**<CR>@return ".st."Type".et."<CR>/<CR>public function get".st."Name".et."()<CR>{<CR><Tab>return $this->_".st."name".et.";<CR><BS><BS><BS><BS>}<CR><CR>public function set".st."Name".et."($".st."name".et.")<CR>{<CR><Tab>$this->_".st."name".et." = $".st."name".et.";<CR><BS><BS><BS><BS>}<CR>"

The first lines tell vim to use the tab expansion and replacing all tabs with four spaces as said in the Zend Framework coding standard, which is my style of choice for php development. Other settings include auto indentation of lines and auto generation of * in case a docblock comment new line is created. You may want to not use these settings, but you'll have to edit the snippet line accordingly.
The two source commands import the plugin and the php snippets respectively. The second import is necessary to define the shortcuts st and et (start tag and end tag) used in snippets definition.
The last line set up a template for a snippet named getset. To use it, open vim and go to the line where you want to put the couple of methods getSomething() and setSomething(). Then go in Insert mode and type getset<Tab> and compile the various parts of the template, pressing tab after every template variable insertion. Note that you need to define a variable only once, which will be substituted in every place where it appears.
Again, feel free to adapt the snippet to your programming language and coding style. Note that there are no new lines in the template: they are inserted with the <CR> command which simulates the pression of the Enter key. The definition must be kept on one line.

I hope this tip can speed you up while writing boring getters and setters code. If you decide to create new useful snippets, let me know in the comments.


Fedyashev Nikita said...

I haven't thought about tweaking .vimrc for that purpose.
Thanks for the post! :)

Julian said...


the * for the */ clossing the comment is missing in your getset snippet, so it doesn't work correctly. You should add it to make your life easier.


Giorgio said...

I've transitioned to snipMate, which is an easier to use plugin.