Programming is for girls!

My buddy Anne recently posted some of her favourite articles on the subject of women in Computer Science. I wrote an article last year which presupposed her question, "Programming is for girls?" My answer? Programming is for everybody!

Granted, not everyone who writes an Excel macro will be so enamored with their creation that they feel the need to master Haskell. The wonderful thing about Computer Science today is that they could. Thanks to the tiny (almost negligible) barrier to entry, the only thing left to tackle is the stigma.


Programming is already social. I prefer pair programming because I'm ADHD and it's the only way I can ever accomplish anything. But I also get to hang out with friends all day as a side benefit. Code is literature, a communication medium. It's fascinating that our little code-robots do something but it's a great deal more important that it speaks to people.

But: Not every software company is an inherently social environment. Yet.

Programming is already creative. In many ways, it's a purely creative endeavour. Outside the speed of light, there aren't many limitations placed on the raw imagination in a world of code.

But: Many software projects are still about doing the same old thing to a different piece of data.

Programming is already sexy and relevant. Startups are sexy by their very nature. Everyone knows what you're talking about if you say you work for Google or Apple. Most people you know already have a phone they've used to install software while they ride the bus.

But: Not everyone gets to work for a startup or Apple.


You can't have it all but you can certainly have most of it. Think your job isn't sexy? Automate the boring parts or quit. It's a seller's market these days. Try out a new technology, if that excites you. Talk to your coworkers. Work with them directly. Find a broader solution to an entire category of problems. Send your resume to that one company you think is really kicking ass.

There is a real spectrum of significance to the machines we build and the companies we build them for. Create some partial orderings to demonstrate this to yourself. Which is more significant? Clean water or banking? Auto insurance or rice? Diabetes research or zinc? Middle school education or vodka? Public transportation or plywood?

Not everyone considers the world in the same way and most of us will change our opinions over the course of our lives... but some parts of our society have obvious gravity. If you're already in software, let that gravity pull you in. If you're considering a career in software, contemplate the fact that a career in software really means a career in any field you want: from water purification to zinc froth flotation.

Girls, software is already sexy. Get on the trolley.

Clojure Macros: How Evil?

Dan asked me at the Chicago Clojure Meetup this week if Clojure macros tend to send developers into the death spiral of metaprogramming Ruby's various hooks did when we first discovered those.

tl;dr: no.

The canonical example of evil Ruby metaprogramming is everyone's favourite this-will-trim-8-lines-of-code hack: strings to method names. Have you ever written something like this?

x.send("#{a}_#{b}")

Sure you have. It's okay. We've all sinned. Are you prevented from doing this sort of thing in Clojure? Nope. No more than you are prevented from doing it in Java. But in Clojure and Java, the apparent innocence of Ruby's `send` method is revealed to be a sham: Reflection feels bad in these languages.

All of Ruby's other metaprogramming hooks have something in common: define_method, const_get, method_missing, every flavour of eval, monkey-patching... and all their friends... happen at runtime.



The behaviour of my first few Clojure macros confused me because I was accustomed to Ruby's runtime powers. Clojure's macros are expanded, go figure, at macro expansion time. As such, they have a few interesting and related properties:

  • macros feel like adding a feature to the language
  • ruby metaprogramming feels like mutating the language
  • macros cannot use runtime data to generate dynamic code
  • ruby metaprogramming requires runtime data to generate dynamic code
  • macros require a new way of thinking about code generation
  • ruby metaprogramming is just a higher-level imperative layer 
Macros also have a very clear usage pattern (see Christophe's wonderful (not= DSL macros) presentation from the first ClojureConj):

data formats > functions > macros

This is to say: Build your functions on top of your data. Build your macros on top of your functions. Macros should always be a convenience rather than a requirement. This one little rule is often enough to remind yourself that "write a macro!" usually isn't the solution you're looking for.

We're probably better off to avoid comparing Ruby's metaprogramming facilities with macros at all. It makes more sense to compare Ruby's hooks to Clojure's reflection and Ruby's eval to Clojure's eval -- neither of which I've seen used in a production Clojure application. Macros actually stand out on their own, since Ruby doesn't have an equivalent feature.

Can you still write a steaming pile of magic in Clojure? Of course. Once you suffocate your desire for elegance, you can reflect and eval and macro your way into a painful and confusing labyrinth of obfuscated code just as you can in any other modern language. But Clojure's libraries and language features usually display enough power on their own that you aren't tempted to shortcut your way into an impenetrable structural abstraction. At least, I haven't seen it yet.

Open Letter to Pascal

My friend Pascal recently asked me what books I would recommend he read to learn the basics of programming. He'd been looking into it for a while but simply couldn't decide where to start, given the multitude of programming books available.

I'd be the last to claim I've swum a majority of the book lagoon, but I have found over the years that the majority of programming books are neither timeless nor all that well-written. Pascal's response seems obvious, in retrospect: if I could start it all over, what would I read?

In Pascal's case, I'd recommend The Structure and Interpretation of Computer Programs. As a Math teacher, he should find the calculus-based examples in the early chapters relatively easy -- if not downright intuitive. SICP is easily the richest and most thoughtful programming book I've ever read. Were it not for all the math it assumed familiar to the reader, I'd recommend it to everyone above and beyond all other texts in the discipline.

For everyone else (myself included), I'd put The Little Schemer at the top of the list, quickly followed by The Seasoned Schemer and The Reasoned Schemer. The books are a joy to read thanks to their peculiar style and between them convey many of the ideas SICP presents as a more traditional academic text.

Why not Learn to Program or Learn Java in 21 Days?

Most introductory programming books and online tutorials (even Why the Lucky Stiff's Poignant Guide to Ruby, in all its humour and beauty) make a grave mistake in their introduction to programming: They misrepresent syntax as the first principle of writing code.

If the first chapter of your introductory literature explains the representation of strings and numbers in [insert-your-language-of-choice-here], you've already started your reader off on the wrong foot. Worse yet, there's a temptation to teach new programmers about variables, mutation of state, and side-effects -- such as printing to the console.

One does not require dozens of books and years of practice to understand the essence of writing software. But in my case, it took as much to unlearn the bad habits taught by my first texts.

FlyMake does not like JRuby

JRuby often works out-of-the-box wherever MRI does. FlyMake is not one of those cases.

Flymake expects a particular format for error messages returned from the interpreter: MRI error messages. Charlie and Friends have decided the MRI error messages can be a bit opaque, and upgraded them to something a little more readable. Sadly, this breaks anything attempting to parse those messages.

Gaz and I decided to try switching things back to MRI so we could get our syntax errors highlighted in emacs. Lo and behold! Everything's happy again. As an added bonus, you don't need to wait for JRuby (and thus, a JVM) to start up every time FlyMake runs.

You can grab our changes with our latest emacs-starter-kit: https://github.com/drwti/emacs-starter-kit

If you're using Phil Hagelberg's emacs-starter-kit, make the appropriate change to starter-kit-ruby.el:

- (list "ruby" (list "-c" local-file))))
+ (list "/usr/bin/ruby" (list "-c" local-file))))

Enjoy!

TiddlyBuild, the single-file build light.

Joel and I threw together a super-simple build light for TeamCity today. The standard project views are too cluttered for broadcasting big colourful messages.


Tech Leaderisms.

Are you a developer? Yes? Then I'm sorry to tell you, friend: There is a Tech Lead in you. Rather, someone will try to make you a Tech Lead one day. For your future Tech Lead self, I recommend reading the corresponding articles, A Tech Lead Manifesto and Behaviours of a Tech Lead (written by colleagues Sam Newman and Pat Kua, respectively).

To those insights, I add these recommendations:

Know Your Teammates

Before you start, talk to everyone. Understand each developer's goals and fears with respect to your upcoming project. Know the strengths and weaknesses of everyone on your team, and formulate a plan for dealing with both. Sketch out your team roster and ensure that the experience and skill level is balanced.


Use Two-Pizza Teams

I'm not sure who first coined this, but I love the idea. I also like the idea of trying it out in reality: Have an in-office team dinner. Order two pizzas. Were you left hungry? Your team is too large. Or you have one gluttonous developer. But probably your team is too large.

Given an oversized team by this yardstick, work with all stakeholders involved to divide up the project. You may even find additional value in simplifications required to divide up your previously bloated project.


Develop Horizontally Until Release 1

It may seem obvious, but I'm still surprised how often this rule is ignored. If you haven't deployed into a production environment yet, build out -- not down. Complex business rules will materialize in every story. They always do. Create new stories from these rules and put them on the shelf until they are truly more important than the next functional story coming down the pipe.

As a Tech Lead, you share this responsibility with your stakeholders. At the end of the day, they will decide what is most important. However, the unseen complexity of a business is visible to you because it materializes as code; share this with everyone.


Build It Yourself First

All too often slogans such as "You Aren't Gonna Need It" are thrown around the the software community until they're almost law. Lately, I find the most troubling to be "Not Invented Here Syndrome"; more often than not, I find the opposite Syndrome afflicting developers: "There's a Framework For That! Syndrome"

Sure there is. Build it yourself anyway.

The majority of frameworks are simply implementations of patterns. Whether as ubiquitous as Dependency Injection, or as domain-specific as a shopping cart, try implementing the pattern yourself before reaching for the nearest third-party library. You very well might throw it away, but often you'll end up with an implementation which is significantly lighter and easier to test.


Keep Metrics and Ratchet Your Build

Chris wrote about "ratcheting" recently. Go read it! The flip side of ratcheting is, of course, preventative medicine. Why wait until you have 60 TODOs before breaking the build? Place as many reasonable limits on yourself as you can, early on. In the thick of the project your motivation to do so might be overruled by the desire to Just Write Code. Tools such as Panopticode, metric_fu, PMD, and Gendarme will help you a great deal, but they're just the tip of the iceberg. Be creative not only in the tools you choose, but the rules you write and the metrics you extract.

The C# expatriate: Tips for settling in Java.

Friday signaled the end of my first Java project in 6 years. Coming from a C#/.NET background, the learning curve was not steep -- but by the end of the project I had learned enough small lessons to serve as the basis for this little document.

If you happen to move from a .NET project to a Java project, have a look through these pointers. This is all the advice I wish I had when I started this project six months ago.

1. Learn all your new tools, inside and out.


As a C# developer, you're already utterly dependent on ReSharper. You will undoubtedly feel at home in IntelliJ. The majority of your day-to-day keyboard shortcuts will remain the same. Those that map directly map closely (CTRL+- is replaced with CTRL+ALT+LEFTARROW).

However, ReSharper is a plug-in which makes .NET development tolerable. IntelliJ is a work of art -- and it makes programming a joy. Install the Key Promoter plug-in and never look back.

2. Find New Tools

As far as I know, nothing like Panopticode exists for C#. Guice almost certainly doesn't. Explore the landscape and enjoy the rich open source bibliotheque that we're missing on Microsoft-funded frameworks.

3. Testing and Mocking

Use JUnit 4. Use Mockito. Try jBehave.

4. Collections

Eagerly write custom collections and provide yourself with methods for collecting, filtering, and all that other fun stuff. You can augment this with Hamcrest Collections, but keep in mind it's still v0.1.

5. Other Wrappers

Be even more aggressive about wrapping standard APIs than you would be in .NET. Why? Like collections, the .NET base class libraries have a (small) leg up on Java, thanks to watching Java grow and change. Because of this, you will periodically find features missing you might expect from the standard API. To be fair, once you've become accustomed to eagerly wrapping standard APIs in Java, carry that back to .NET with you. Chances are good you weren't wrapping enough stuff when you were last writing .NET. (I know I certainly wasn't.)

6. Dates and Times

The Java DateTime libraries are beyond useless; use JodaTime from day one. If anyone imports the JDK DateTime packages, fail the build. Joda comes with all the Hibernate jazz you need to persist Joda's DateTimes, so you're good there.

7. Apache Commons

Use it. It rocks. When you go back to .NET, steal ideas.