An article about a simple, but not obvious way how to make the code cleaner and get rid of copy-paste.
Conventionally, the problem looks like this:
class Awesome doFoo : (arg, cb) -> unless arg is 42 return cb Error """ only The Answer may be an argument, but got: |arg| = |#{arg}| """ cb null, "#{arg} is The Answer" doBar : (arg, cb) -> # hm... arg must be The Answer too
We have a piece of code (the one with the check), which in the first place seems to be repeated in the new method, and generally distracts from the main action in the method.
To get rid of copy-paste, we will slightly cheat and change the module code by entering one extra-class function, and the result will look like this:
ensureArgIsTheAnswer = (methodBody) -> (arg, cb) -> unless arg is 42 return cb Error """ only The Answer may be an argument, but got: |arg| = |#{arg}| """ methodBody.call @, arg, cb class Awesome doFoo : ( ensureArgIsTheAnswer (arg, cb) -> cb null, "#{arg} is The Answer" ) doBar : ( ensureArgIsTheAnswer (arg, cb) -> cb null, "#{arg*2} is The Double Answer" )
')
The same principle can be used for debug logging:
logOnDemand = (methodBody) -> (args...)-> __rval__ = methodBody.apply this, args if @_do_logging_ console.log "#{args[0]} -> #{__rval__}" __rval__
And all that you want.
A fly in the ointment (wherever without it) - the decorators themselves will have to copy-paste from the module to the module, I have not yet found a simple and obvious way to share them.A barrel of honey (thanks to
Infernal ) - to use decorators in the project - we simply collect them in the module (s) and import the required ones in the right place, which further reduces the amount of scribbling and improves readability.
This trick was honestly bought with the
CoffeeScript Ristretto book, for me the most sensible for understanding CoffeeScript.
Ps. This is an orthodox way of using decorators, without callee
and other devilry, it does not spoil karma.Pps. The brackets around the contents of the decorated method in the class are not necessary to use, but they help TM2 highlighting, so I include them in my code.