I’ve seen a similar thing with tests written in rspec where lets are exclusively used in place of local variables. Any thoughts on how to strike the balance there?
YES! This advice completely applies to let variables in RSpec tests too. A let is a memoized method definition in my book. I am happy to recommend using more local variables over let variables in tests.
Another anti-pattern is making the Controller instance manage the Serializer. Ideally, the Controller just returns an object, and any need to transform that object to a specific format is handled decoratively or via DI. Transformations don’t belong in business logic.
I somewhat regret using a controller as the example, because this is applicable to any Ruby object. Its so easy to get into controller analysis rather than my main gist.
My rule still applies- controller or not, they should just return the structure that makes sense to them. If it doesn’t make sense to the consumer, put a layer of indirection between them. As much as I am wary of indirection, objects should do what makes sense to the object.
I’ve found when I’m initially developing something that it’s hard to find 3 use cases for everything, just very common things.
This has lead me to do two things:
Find places in older / unrelated code where my new abstraction might be useful, because I like it so much. This has been a great motivation for me to refactor.
Throw out abstractions with confidence. If I cant find 3 use cases, then throw it away. The moment a third use case is added or discovered, it’ll be obvious it should be abstracted.
I’ve seen a similar thing with tests written in rspec where lets are exclusively used in place of local variables. Any thoughts on how to strike the balance there?
YES! This advice completely applies to
letvariables in RSpec tests too. Aletis a memoized method definition in my book. I am happy to recommend using more local variables overletvariables in tests.Another anti-pattern is making the Controller instance manage the Serializer. Ideally, the Controller just returns an object, and any need to transform that object to a specific format is handled decoratively or via DI. Transformations don’t belong in business logic.
I somewhat regret using a controller as the example, because this is applicable to any Ruby object. Its so easy to get into controller analysis rather than my main gist.
My rule still applies- controller or not, they should just return the structure that makes sense to them. If it doesn’t make sense to the consumer, put a layer of indirection between them. As much as I am wary of indirection, objects should do what makes sense to the object.
I’ve found when I’m initially developing something that it’s hard to find 3 use cases for everything, just very common things.
This has lead me to do two things:
Find places in older / unrelated code where my new abstraction might be useful, because I like it so much. This has been a great motivation for me to refactor.
Throw out abstractions with confidence. If I cant find 3 use cases, then throw it away. The moment a third use case is added or discovered, it’ll be obvious it should be abstracted.
Local variables are also mildly faster. I did some tests here https://itscode.red/posts/the-cost-of-using-methods-as-variables/
Funny, this has a name, Point Free Style
This is not really the same thing. Here we’re talking about folks extracting local variables into methods unnecessarily.
Pointless Free Style