Code should feel good
One of the pleasures of working with RubyMotion is the frequent occurrence of wrapping obtuse Objective-C code within abstractions. If we do our job right, these abstractions will be helpful. The sheer number of letters that your mind has to parse to read code is lowered, which is usually a win. However, this gain only materializes if your abstraction is any good.
Consider the following module:
module StoredObject SERVICE = 'YOUR_SERVICE' def save(key, val) storage[key] = val end def secure_save(key, val) SSKeychain.setPassword(val, forService: SERVICE, account: key) end def val(key) storage[key] end def secure_val(key) SSKeychain.passwordForService(SERVICE, account: key) end def delete(key) storage[key] = nil end def secure_delete(key) SSKeychain.deletePasswordForService(SERVICE, account: key) end def nil?(key) storage[key].nil? end def secure_nil?(key) secure_val(key).nil? end private def storage @storage ||= NSUserDefaults.standardUserDefaults end end
This code feels good to me.* I like the following things about this code:
How an object is stored is abstracted away from the logic of whatever is doing the storing.
The DSL feels more intuitive than the library it wraps around. It does what you would expect it to do, which is aspect of the beauty of code.
The 'Hash' like quality of NSUserDefaults has been hidden behind messages. This prevents the user from interacting with the information in NSUserDefaults like a specific data-type. We could change the implementation of NSUserdfaults without includers of this module caring.
Things worth considering:
Separating out Secure Saving into a separate module. I'm not feeling the pain of secure storage being included right now, but we should pay attention to that if it were to arise.
Test our memoization of
@storage. Is it actually faster than calling NSUserDefaults.standardUserDefaults directly?
Is the secure_nil? method superfluous? Should we change that to just .nil?
*...right now. This might change the next time I look at this.