Two years ago, I stood on my soapbox and yelled. I told the FP community that their languages were bad, and that they should feel bad. It was a post full of vitriol and frustration, but also a little bit of truth. I believed then (and still do) that functional languages are a poor solution if what you're looking for is a way to get B grade programmers to build scalable, concurrent systems. After trying to learn Erlang, Haskell, and then Scala, I couldn't see how using those languages was easier that just using separate processes, stitched together with message passing infrastructure, to build systems at scale. And with these thoughts running through my head, I vomited on the Internet. Then Hacker News picked it up.
A lot of people I've met don't use the private function definition in Clojure -- which is
defn- if you've never seen it. They don't see the point, or they think that private functions in Clojure are dynfunctional (pun!). Based on my use of it so far this year, this confuses me, because I think private functions in Clojure are awesome. The reason I think they're awesome is because I write tests for my code, so that I can refactor. Having a clear deliniation between code the that's tested directly and indirectly means I can refactor much more quickly.
When you're looking for ways to refactor code, you can use your fingers, or you can use your eyes. Refactoring with your fingers is nice. When you have a continuous test runner, running a suite of tests on each change, you can refactor pretty quickly. But refactoring with your eyes is much, much faster. Being able to see possible refactorings and think through them in your head is a much faster way to reason about how to clean up code.
If most of your functions are private, you can refactor with your eyes before you refactor with your hands. Unless you've been doing something dumb like subverting access controls to invoke private functions, you know that all of your private functions can be changed, inlined, extracted, and generally recombobulated without fear of breaking a test or messing with another module. This frees up your mind to think about the code that's right in front of you, rather than worrying about the other code that might be calling it.
The public functions, on the other hand, are expensive to change. You will probably break some clients. You probably break tests. All of this will require a lot of work that, essentially, adds no value on it's own. That's not to say that you shouldn't refactor public functions, of course. It's just that the costs are potentially higher. And I find that too many public functions in a module create a slight reluctance to refactor. A pause in thinking, if you will, that I'd rather do without.
So I love private Clojure functions. They're just new a way to implement an old-fashioned idea: Encapsulation. Clearly dividing my clojure modules into public (more expensive to change) and private (less expensive to change) has worked out very well for me. If you haven't tried it, I suggest that you do.
Unless, of course, you're not writing tests...in which case I have nothing for you!
This tool has some really awesome features, not the least of which is that the environment your tests run in is really webkit. That means that you don't have to mock out major parts of the browser environment like
window.location, localStorage and sessionStorage, and XMLHttpRequest if you don't want to.
Another great feature is the ability to generate an html file that will run all your tests in a real browser, whenever guard runs tests. Combined with the Live Page plugin for chrome, I get instant feedback about whether or not my Jasmine tests actually pass in the browser.
However, there is one downside compared the node.js technique I outlined in my book. jasmine-headless-webkit doesn't give you real stack traces in the guard output when tests fail. Usually this means you resort to looking at the test failure in the browser (using that generated html file). In practice, it's not a big deal, but it also means you need to make sure your tests pass in both environments, otherwise you might be stuck with a failing test that you can't diagnose.
I released version 0.4 of Jezebel last week. It now works with Node.js 0.6.2.
It's done! It's out. And I couldn't be happier.
Node.js is supposed to be all about an asynchronous style of programming. Rather than executing functions and getting results, we use a lot of first order functions and callbacks to do things asynchronously. Here's an example of this style from the djangode project. makeApp is a function that takes an array of arrays that are regex/function pairs. Some of those function invoke other functions (such as setTimeout) that take other functions.
I find this kind of code rather tricky to test, and to reason about. Functions nested four levels deep makes my spidey-sense tingle. A good technique for cleaning it up can be extracting those anonymous functions into named functions, but if there are variables that are shared across scopes, that can get a little messy too.
However, I really like Node.js and the approach they've taken, simply because the asynchronous style is a rather elegant (if not new) solution to the kind of performance problems you encounter when working with single threaded code. Blocking operations, IO is particular, can really kill your app, and using threads to avoid blocking can lead to code that is nigh-impossible to test or reason about...so the Node.js asynchronous style merely being a bit tricky is a huge upgrade.
I gotta say, this is pretty neat.
You know, just in case you forget what Huffman encoding is.
Twitter is a personal denial of service attack. If you want to steal someone's productivity for a day, just troll them on Twitter.
Oh, and I'm not posting this on Twitter, because I have better things to do than defend my argument.
After reading Tim Ottinger's excellent article on the meaning of "sustainable pace", I couldn't help but pose a question on Twitter. 140 characters just isn't enough to clarify this question, and so we move to the blog to fill in the details.
Let's assume that we have a customer (likely a proxy) who wants a development team to work overtime to complete a task. Let's further assume that this is really a task, that is, a day or two of work, to be done on a weekend or during a couple of really late nights. He thinks that this task requires an additional level of effort, and that working late is worth the sacrifice (to both morale and the later productivity of the team). To clarify, the customer isn't providing the budget for this project and he isn't any more of a stakeholder than the developers.
Let's also assume that we have a development team that has a decent understanding of the business concerns of the project. Their opinion is that this task is no more urgent or particularly valuable than anything else they've been asked to do. To use the terms from Tim's article, they don't think it's necessary to come to the rescue in this case.
My question is this: If the customer proxy
forces strongly suggests that the development team work overtime to complete the task, even though the developers think overtime is unwarranted for this task, is that unethical?
On the one hand, the customer is likely benefiting from the delivery of additional features, and the morale of the team may be damaged. If this is 'the last straw' for a key developer that can easily find work elsewhere, the customer may have cost the company dearly to benefit himself. Even if the customer truly believes that the sacrifice is worth the benefit, is he caught in a conflict of interest?
On the other hand, what if the customer is right? A good development team understand the needs of the business, but you would think that the customer would have a better understanding. Disagreements happen. Our goal is always better communication and understanding, but there's little point in having an 8 hour meeting to avoid 12 hours of overtime.
What say you, Internets?
"Continuous Testing with Ruby" is now available as a beta book on pragprog.com! This is the first beta, so there's still more to do, but Rod and I are very happy to have it out there so we can get some feedback.
Continuous Testing starts with a simple idea: Run your tests all the time. I think this book does a great job of communicating all the incremental improvements to that idea that Rod and I have come up with over the last few years. From using CT as an alternative to debugging, to finding ways to automatically check other project artifacts (like documentation and seed data), once you get hooked on having instant feedback for everything, you start to find all kinds of ways to apply it.
Probably the biggest effect, however, is how CT helps you write better tests. One of the points we made in the book goes like this:
An old axiom of Test Driven Development states that the tests test the correctness of the code; while the code, in turn, test the correctness of the tests. The tests also test the design of the code—code that’s hard to test is usually poorly designed. But what tests the design of the tests? In our experience, Continuous Testing is an effective way to test the design and overall quality of our tests...running our tests all the time creates a feedback loop that tells us when tests are misbehaving, as we create them. This means we can correct existing problems faster, and prevent bad tests from creeping into our system in the first place.
I'm very proud of what we've done with this book. I think it will be really valuable to anyone who's been writing automated tests and wants to get more out of them. I've been a doing TDD (and then BDD) since about 2003. My interest in continuous testing began in 2006 when I thought about all the time I was wasting figuring out which tests I needed to run after a change. After that, I wrote Infinitest, and now Continuous Testing with Ruby. I'm greatly looking forward to see where we go from here.