Thursday, May 31, 2012

The Single Best Thing For My Career

In 2004 I was working at nelnet - for one of the best bosses I've ever had. I was the lone developer working on NextGen projects, our customers were happy, I was paid well, & I had plenty of vacation - things were good. Truthfully, I felt like I was on top of the world. However, I couldn't help but feel like something was missing. I'd seen a bit of 'how things could be' by reading Refactoring & Extreme Programming Explained. I was 24 years old, and I felt like my current situation wasn't going to allow me to grow much. I'm convinced that if I were older I wouldn't have changed a thing, but I was young, and I dove into the deep-end of consulting.

Like I mentioned, I'd seen a bit of the light before I made the jump. I had read a few good books, I was using Test Driven Development (TDD) and Continuous Integration at work, and I'd seen the (successful) results of my efforts. Before I joined the NextGen team I was working with a larger group of developers, and at one point we were in the middle of delivering a huge release. While everyone else was working weekends I was either not in the office or I was at my desk reading about poker theory. My component of the release worked, 100% of the time. My tests prevented regressions even as the release evolved. Through the many month ordeal, I never once had an issue. I had seen the benefits of TDD, there was no turning back, and I wanted to mature my skills even further.

I joined ThoughtWorks in early 2005. From the moment I walked into the office I felt like I was drinking from a fire-hose. What's firefox? Better than IE, okay then. What's DI? Inject the dependencies so you can use mocks or stubs in the tests, got it. Ruby on Rails, PostgreSQL, I'm on it. Then there's all the other things that aren't technology related, but are still worth knowing: international travel, frequent flyer programs, points credit cards, car rentals, etc etc. In my first year with ThoughtWorks I grew more as a person than I had in the previous 3 years combined.

Obviously, it's not all roses. In my orientation class I remember everyone admitting that they were going to put in 2 years for the experience and get out - I had the same plan. The guy with the most experience made it 6 months, two other guys made it a year, and I stayed for 3. The constant travel can wear on you, but it's worth doing it for as long as you possibly can.

There's three reasons that consulting was like steroids for my career: Each project of my consulting career was very different: C# in the Travel Industry, VB.net in Insurance, Ruby (& DSLs) in Credit Cards, Ruby on Rails (RoR) in VoIP, RoR in Auctions, RoR in Advertising. Projects often used different operating systems (ms, linux, apple) and databases (mysql, postgres, oracle, sql server). Naturally, I couldn't become an expert in everything I touched, but the exposure gave me views into each world. Additionally, I was able to meet experts from each of those worlds. When I joined ThoughtWorks I was a C# developer carrying a Dell, when I walked out I was carrying a MacBook Air and I was best known in the Ruby space - consulting completely changed the trajectory of my career path.

As I mentioned, I often got the opportunity to meet with various experts. I don't know Oracle well, but if I have a problem, I know I can email Pramod. Even though he never worked there, I met Stu Halloway while working for ThoughtWorks. Stu introduced me to Rich Hickey, which is pretty nice, since I spend the majority of my time working with Clojure these days. I met Martin Fowler and eventually wrote a book with him. My network gets me invited to conferences, allows me to co-organize speakerconf, and when I joined DRW, I brought 13 friends with me. If you believe that "your network determines your net-worth", then the majority of my net-worth is due to what I built while I was consulting.

At speakerconf 2011 I noted that everyone involved in the Software Craftsmanship movement was either a consultant or had very recently left consulting. The question of why this was the case was sent to the twitterverse. Brian Guthrie's response rang very true (it was something along the lines of): as a consultant, our craft is the only thing we own. Consultants hone their craft endlessly. I'm convinced that's the reason that consultants are almost always ahead of the technology curve. As a consultant, to invest in your business is to invest in yourself. If you work for a consultancy you'll not only have the time to focus on your craft, you'll also likely be surrounded by a group of people who have been doing the same - and are happy to show you what they've learned.

These days, I'm no longer at ThoughtWorks. In the end, I couldn't deal with the travel or the business model. However, that doesn't change the fact that it was the single best thing that has ever happened to my career. I would highly recommend consulting to everyone who is truly serious about maturing their software development skills.

note: Not all consultancies seem to require as much travel, Relevance, for example, requires very little travel - from what I hear. I also hear that it's an amazing place to work. It would be near the top of my list if I were to get back into consulting.

Labels: , ,




Wednesday, May 30, 2012

Is Productivity Killing Your Creativity?

I listen to audio books while I work out. I've been known to leave earworms 'Rapid Italian' on while trying to go to sleep. I read books on trains. I answer emails while eating dinner. I clear out my Google Reader while watching TV with my wife. I wanted to learn Ruby and Blackjack perfect strategy, so I wrote a perfect strategy simulator in Ruby. I'm a multi-tasking machine. I am the worlds most productive man, or so I liked to pretend.

About 4 years ago at a conference in São Paulo, Chad Fowler told the audience to delete every feed in their blog reader if they wanted to gain an incredible amount of productivity. I was appalled. I already believe that engineers don't spend nearly enough time staying current, and Chad was telling the audience to spend even less time reading about current events. I had (and have) way too much respect for Chad to call bullshit, but I definitely didn't agree. Then again, I'm aggressive about removing noise from my subscription list, so I chalked up the disagreement to him recommending that the audience remove what were likely very noisy subscription lists anyway - probably a net positive act.

A few years later I found myself on a train from NYC to Greenwich, CT - listening to the Zen and the Art of Motorcycle Maintenance audiobook. The book changed my perspective greatly, and I'll never forget the line: I haven't really had a new idea in years. The following paragraph haunted me as well.
What is in mind is a sort of Chautauqua...that’s the only name I can think of for it...like the traveling tent-show Chautauquas that used to move across America, this America, the one that we are now in, an old-time series of popular talks intended to edify and entertain, improve the mind and bring culture and enlightenment to the ears and thoughts of the hearer. The Chautauquas were pushed aside by faster-paced radio, movies and TV, and it seems to me the change was not entirely an improvement. Perhaps because of these changes the stream of national consciousness moves faster now, and is broader, but it seems to run less deep. The old channels cannot contain it and in its search for new ones there seems to be growing havoc and destruction along its banks. In this Chautauqua I would like not to cut any new channels of consciousness but simply dig deeper into old ones that have become silted in with the debris of thoughts grown stale and platitudes too often repeated. "What’s new?" is an interesting and broadening eternal question, but one which, if pursued exclusively, results only in an endless parade of trivia and fashion, the silt of tomorrow. I would like, instead, to be concerned with the question "What is best?," a question which cuts deeply rather than broadly, a question whose answers tend to move the silt downstream. There are eras of human history in which the channels of thought have been too deeply cut and no change was possible, and nothing new ever happened, and "best" was a matter of dogma, but that is not the situation now. Now the stream of our common consciousness seems to be obliterating its own banks, losing its central direction and purpose, flooding the lowlands, disconnecting and isolating the highlands and to no particular purpose other than the wasteful fulfillment of its own internal momentum. Some channel deepening seems called for.
As I said, Zen and the Art of Motorcycle Maintenance changed my perspective. I began to look back at the last few years of my life, and I felt like my creativity had been stunted. At one point in my life I would stare out the window of a plane for several hours a week pondering whatever technical problem that was troubling me. But, for the last several years I've been being 'productive' by listening to an audiobook or reading something on my iPad. I've been listening, but I haven't been thinking, not deeply.

If you listen to the people around you, they are saying the same things - whether they know it or not. I'm sure at one time you read an article where a CEO swore they were most productive while they were on a plane, unreachable. Just last week a story made the rounds about a company that moved to Hawaii temporarily. In that story they describe how walks on the beach brought a greater understanding, something that probably couldn't have happened while they were all distracted by the day-to-day activities of living in Silicon Valley. And, I now believe that Chad was talking about the same issue - distractions (masked as productive tasks) stealing your creativity.

I'm convinced that my iPhone was the root of my creativity issues. Life is full of 'waiting time' - waiting for the subway, waiting to see your doctor, waiting in the elevator, waiting in line at airport/grocery store/coffee shop, and waiting at the bar to meet your friends. Pre-iPhone I would spend this waiting time pondering anything that was troubling me. Now, I open Safari on my iPhone to see who is the latest injury on the Knicks, who is the lastest football player to sign with FSU, or who's tweeting about what (seems like it's mostly sponsorship requests these days). I don't spend that time thinking about anything, I spend that time reading - reading about things that have very little impact on my life, but seem to always more than fill my waiting time.

At least, that's what I used to do. Now, I've moved anything that can steal my waiting time to the 2nd page on my iPhone. It's no longer taunting me to check twitter, facebook, sports scores, or anything else. My main page allows me to get things done if I need to do them, but it doesn't offer me anything to fill my 'waiting time'. Those apps are just a page away, but not having them staring at me when I instinctually unlock my phone reminds me that I need that time to think, even if it's not deep thinking, I need to 'do' less and 'think' more.

Even this small step has led to better organization in my mind. Now that I'm not 'productive' 100% of the time, I find myself solving issues with more innovation and greater efficiency. The small step and the noticeable improvement have led me to make larger changes - I still multitask as much as I can, but I also set aside time to stare out the window. No agenda, no priorities, just stare and let my mind go wherever it needs to go. After making these changes, I feel better. I have more mental energy to produce innovative solutions at work, and I find that I'm getting things done in a way that leads to greater long-term productivity. My priorities feel right, if you will.

This isn't the kind of thing I usually produce on this blog, but the impact that my changes have made on my life compelled me to share. And, as I already said, if you listen, more and more people are saying the same thing, even if they aren't using the same words. Technology has driven us to greater 'productivity', but often at the cost of deep concentration and thought. Not everyone is okay with that, and more and more people are beginning to push back in their own ways.

Labels: , ,




Tuesday, May 29, 2012

Clojure: Freezing Time in expectations

The current version of expectations (1.4.3) contains support for freezing time within an expectations scenario. I already put this information out in a previous blog entry, and I'm going to use the same examples here.

The following code is a test I was working on at work:
(scenario
 (handle-fill (build PartialFill))
 (expect {:px 10 :size 33 :time 1335758400000} (first @fills)))
The test builds a PartialFill domain object, and passes it to handle-fill. The handle-fill fn converts the domain object to a map and conj's the new map onto the fills vector (which is an atom). The above test would fail due to the time not being frozen, and the traditional way to deal with this issue was to change the test to use (in ..) and ignore the :time key-value pair.

The following code would have resulted in a passing test:
(scenario
 (handle-fill (build PartialFill))
 (expect {:px 10 :size 33} (in (first @fills))))
The above code is fine, as long as you're not interested in verifying the time; however, things get a lot uglier if you do want to verify time. The following code freezes (joda) time, allowing for time verification:
(scenario
 (DateTimeUtils/setCurrentMillisFixed 100)
 (handle-fill (build PartialFill))
 (expect {:px 10 :size 33 :time 100} (first @fills))
 (DateTimeUtils/setCurrentMillisSystem))
While the above code does result in a passing test, it would cause unexpected issues if expect ever failed. In expectations a failure throws an exception (to terminate scenario execution) and the time reset would never occur. Even if that wasn't the case, the time related code takes away from the actual focus of the test.

Therefore, expectations has been modified to take a :freeze-time parameter as part of a scenario definition. The :freeze-time parameter can be a string or a boolean - when specifying a string, anything parse-able by Joda will do; if you specify a boolean time will simply be stopped at the moment of execution.

With :freeze-time available we can rewrite the above test in the following way:
(scenario
 :freeze-time "2012-4-30"
 (handle-fill (build PartialFill))
 (expect {:px 10 :size 33 :time 1335758400000} (first @fills)))
The resulting code is easier to work with, while still allowing verification of time.

I believe the domain related code does a better job of demonstrating the point; however, the following examples are available if you'd like something simplified.
(scenario
  :freeze-time true
  (expect (DateTime.) (do (Thread/sleep 10) (DateTime.))))

(scenario
  :freeze-time "2012-4-30TZ"
  (expect (.getMillis (DateTime.)) 1335744000000))

Labels: , ,




Thursday, May 24, 2012

Clojure: expectations, colorized

The current version of expectations (1.4.3) prints colorized results by default on non-windows boxes.

The following screenshot is an example of the output when no tests are failing:


And, the following screenshot is an example of the output when there are failures or errors:


Colorized output is one of those small things that is easy to de-prioritize, but once it's done you can't figure out why you didn't do it earlier. The code to colorize your results is very simple, and there's even a lib, colorize, if you prefer to simply include a dependency instead.

Of course, if you prefer to stick with non-colorized results that's possible as well - simply set the environment variable EXPECTATIONS_COLORIZE to 'false'.

Labels: ,




Wednesday, May 23, 2012

Killing IntelliJ Launched Processes

I often use IntelliJ to run applications, and on occasion things go wrong. For example, a thread that wont terminate can cause a running application to become unstoppable via the IntelliJ UI. Usually when this happens I end up running ps aux | grep java and following up with a kill -9 for each process that looks like it might be the one I'm looking for. On good days there's only a few processes; however, things are more complicated when I have several to look through.

Last week I noticed that the command used to launch the process printed in the Console window, and, more importantly, the idea.launcher.port is part of that command: e.g. idea.launcher.port=7538. Assuming the port is unique, or even almost unique it's much easier to ps aux | grep for than java.

Labels: , , , ,




This page is powered by Blogger. Isn't yours?