One of the big problems writing Rubymotion code for OSX or iOS is that Cocoa forces you into writing unrubyish code which after some time becomes really bloated, ugly and consequently hard to understand and maintain. Here are a few links and tips from my (young) experience.
1 Read the Ruby style guide
If you are like me and you are relatively new to Ruby AND Cocoa then this is a good read. It gives you lots of good practices on how to write readable and maintainable code: https://github.com/bbatsov/ruby-style-guide
2 Consult the following resources
There are lots of really good resources on code style and refactoring:
- Don’t Let The Cocoa API Crush Your Ruby Code - Presentation by Alex Rothenberg at Inspect 2014 (the annual Rubymotion conference). Alex gives some good examples where Cocoa and Ruby styles collide and what you can do about it.
- Soroush Khanlou an iOS/Cocoa developer has some very interesting thoughts on good and bad coding habits. In his post „Emergence“ he shares some thoughts about a crufty codebase and why you need to do something about it. In his article „The Right Level“ he gives some insight into where to tackle which kind of problems and why View Controllers can easily become really bloated.
- In the above mentioned article Soroush provides a link to a talk by Sandi Metz on refactoring the Gilded Rose Kata. This one is a must-see if you would like to simplify your current code. I can also really recommend Sandi’s book “Practical Object-Oriented Design in Ruby” (also mentioned in Alex Rothenberg’s talk).
- Last resource I would like to recommend is the article „Beware the Siren Song of Comments“ by Andrew Warner in which he shows how comments can make your code worse.
3 Use Rubocop
Rubocop helps you to stick to the above mentioned Ruby code style guidelines. It even corrects the simple mistakes for you. You can install it via gems:
$ sudo gem install rubocop
To check your files go to your project dir and run:
It will output a list with all things rubocop considers bad style. That is probably quite a lot! For my project the first run found around 1500 mistakes. Quite a lot of the messages in the report are:
- Mistakes which can be corrected by Rubocop automatically. For example using double quotes instead of single quotes, missing spaces in Hash braces etc.
- Mistakes which are due to Objective-C coding style which we need in a Rubymotion project and should be ignored. For example when implementing the NSOutlineViewDelegate Protocol you will have lots duplicate methods like:
def outlineView(outlineView, **someAdditionalParam:param**)Rubocop will interpret these methods as duplicate methods. Furthermore it will complain about cocoa style method calls with keywords in front of the arguments (e.g.
In order to have Rubocop autocorrect offenses run
$ rubocop -a
and Rubocop will correct all offenses which it can. If your coding style is as bad as mine this will get rid of a lot offenses.
You can also configure Rubocop to ignore offenses. Duplicate method names as explained above is one offense which occurs automatically when writing Rubymotion code. There two ways to fix this:
Alternative 1: Include the following comment in your code to make Rubocop ignore the following lines:
# rubocop:disable Lint/DuplicateMethods
Alternative 2: Create a file named
.rubocop.yml in your root project directory and add the following line:
Lint/DuplicateMethods: Enabled: false
Rubocop will now ignore all duplicate methods. I would recommend to go with alternative 1, in order not to miss any duplicate methods in non Cocoa-based code.
If you plan to use Rubocop on a regular basis I would recommend building your own custom
.rubocop.yml file for Rubymotion projects. You can check out my custom file as a gist here which is based on this post here.
So the first time I ran Rubocop I was really shocked when I got about 1500 offenses for about 25 files. A lot of the issues could be fixed automatically. Others were really hard to fix. Especially offenses regarding code complexity and class or method lengths needed lots of work. Fixing these forced me to use more classes and write more small methods than a few long ones. This refactoring took me a full week without adding a single new feature. So now I have 36 class files but all of them are shorter than my 25 old files. Overall I feel that my codebase improved very much and I hope that future features will be easier to add.
Hey! This is my first blog. If you have any additions, comments or questions just drop me a mail.