In my experience when you do this you end up with anaemic tests that are basically useless. As the page comes close to admitting, all you do is write the same code twice. The result is a lot of wasted effort on unit tests that never fail.<p>In an app designed like this the integration tests are the useful ones, because they're more contentful and test assumptions that are more likely to be wrong. The article flatly asserts that code written in this extremely decoupled style will require fewer integration tests, but I see no evidence for this. And you still need to figure out how to make them run fast.
Pluggable systems (loose coupling) are the easiest way to create a system that is cheap and easy to maintain. I've found that a lot of Rails developers in particular don't see the benefits of this and they really, really like tightly coupled systems because of the convenience of it all.<p>Benefits like fast, easy testing, easier maintenance, swappable external things like databases, queues, external api's are apparently not enough of a benefit to change away from rails.<p>I wrote a pattern (<a href="http://obvious.retromocha.com" rel="nofollow">http://obvious.retromocha.com</a>) that makes pluggable systems easy based off of ideas from Uncle Bob, Alistair Cockburn, and Kent Beck which I think makes writing pluggable systems a lot easier, but as with all similar structures like Hexagonal Architecture and the like, Rails devs seem to not see the value in it until their app is a complete mess, at which point they would rather add more rails code than fix the underlying problems.<p>For a lot of developers, now that rails is popular, rails IS the architecture and things that go off the rails are either a waste of energy or too difficult.<p>Rails is what Kent Beck calls a connected architecture and as his incredibly scientific graph describes, the cost of change spikes dramatically over time compared to a modular architecture: <a href="http://www.threeriversinstitute.org/blog/wp-content/uploads/2009/08/connectedAndModularDesign.jpg" rel="nofollow">http://www.threeriversinstitute.org/blog/wp-content/uploads/...</a><p>Until developers adopt modular or at least more service oriented designs, nobody should be surprised by slow tests, features taking too long to ship, the cost to ship code to rise dramatically over time. It's mostly our own fault.
Was mostly with the author right up until he shows an example of the worst possible unit test. Testing the implementation and not the intent.<p>This feels like how Spring must have been born. Trying to think of an alternative, and I think I would be happy with the fat controller example originally given. It's simple enough and straight forward.<p>Perhaps it's just bad examples all the way around...
I don't know (and don't care) if this makes your unit tests faster, you shouldn't write code like that. He took something that should be simple and made it really complicated. The execution time of your tests shouldn't dictate how you will design and write your application. Especially if it makes things harder to maintain and understand.<p>Edit: I love tests and they should be fast so that you can run them every time before pushing your changes but as I said they shouldn't dictate how you design and write your application.
Isn't part of the problem the fact that Ruby is ridiculously slow? I'm not even trolling, I am a Ruby programmer, I've used the language for about 5 years now and seeing friends of mine run their 200+ files test suite in under half a second (C programmers), I can't help but think about how nice that must be to be able to run your tests when you want to without thinking of the consequences (and yes I understand comparing C and Ruby is ludicrous, just pointing to the fact that Ruby is still extremely slow and would very much benefit from a good speed bump eventually).<p>Cause slow tests as a symptom pretty much means that if you're not an excellent programmer then tough sh*t, testing will be slow and painful, which ultimately drives people away from those good practices.<p>Also, I find ironic that Rails (as a framework that is supposed to empower people and make them efficient) is, according to many comments in this thread and "tech pundits" conducive to the kind of tight coupling and dependency that will lead to bad design choices and slow tests.
The slowest part of most tests suites are the integration and acceptance tests. Regardless of how decoupled my actual domain logic is, these will usually be the bottleneck, so I can't really agree with slow tests always being a symptom of some underlying architecture problem.
Personally I would have<p>1: Added a users resource beneath the mailing list, ie<p><pre><code> resources :users
resources :mailing_lists do
resources :users
end
</code></pre>
add_foo is almost always a sign that a new nested controller should be made, and there is almost always a need for a delete as well - in this case users should be able to remove themselves from a mailing list.<p>2: Put the add method on the mailing list and not on the user, because that is where I'd expect the least logic to be.<p>because:<p>3: I'd put the actual mailing list mailer logic in a separate class for the configuration of it.
We've published two blogposts how we sped up our test and boot times considerably. Maybe helpful to some:<p><a href="http://blog.codeship.io/2013/08/21/faster-test-suite-boot-times-with-ruby-on-rails.html" rel="nofollow">http://blog.codeship.io/2013/08/21/faster-test-suite-boot-ti...</a><p><a href="http://blog.codeship.io/2012/11/15/speeding-up-our-test-suite.html" rel="nofollow">http://blog.codeship.io/2012/11/15/speeding-up-our-test-suit...</a>
after reading sandi metz POODR[1], I tend to prefer the approach on the post too. However, I also must say that the time it takes to execute unit tests, even with factories, db access etc is still an order of magnitude <i>faster</i> than running things like feature tests with capybara. This is by far the biggest drain on test time (and resources), and these are also the tests most difficult to write and maintain. Way too often, when we decide to change some functionality, there's a whole battle with tweaking capybara tests to work again.<p>Perhaps I'm showing my lack of knowledge or experience with capybara, or integration testing, but that's one aspect I wish there were some better tools / approaches. Having to dig through css/xpath elements to click on or perform interaction is still a major PITA. If anybody has some suggestions to share, I'd love to learn more!<p>[1]<a href="http://www.poodr.com/" rel="nofollow">http://www.poodr.com/</a>
It's worth stating that this is the MailingListsController and there is no mention of a MailingList. It seems to me like some functionality in the "before" example could live in the MailingList class.