The Well-Bred Grapefruit

Musings on Software Development

Manage Up and Down, but Not Sideways

I’ve officially been managing the development team at Treehouse since last December or so, which puts me near my six-month mark here in May. During that time, I’ve been trying to come up with a good management style: I’ve been exposed to a lot of different management techniques and attitudes, ranging from deplorable, to annoying-but-useful, to fantastic over the course of my career thus far. Now that management is a key component of my day-to-day responsibilities, it’s important for me to have a good management philosophy in much the same way as it’s important to have a good coding philosophy: thinking through a lot of this stuff up front will help me to be more consistent and decisive when I’m faced with an issue.

One sort of mantra I’ve developed - and the other developers at Treehouse can attest to this, as they’re probably already tired of hearing it - is “Manage up, and down, but not sideways.” It’s a simple way to remind myself of where my responsibilities should lie. Here’s what it means if you break it down:

Managing Up

"Dilbert comic strip, 12/05/2010"

What this means:

“Managing up” is the act of managing the leadership team in your company as it relates to your team and the work your team is doing. Specifically, it involves the following:

  • Representing your team to leadership: if any other member of leadership has a question about what the dev team is working on, or why we’re executing on our tasks in a certain way, or anything like that, they should be able to get that information from me. If anybody else on the team needs to be bothered for answers, then they’re getting pulled off of whatever they’re working on, which isn’t good. This also involves making your team look good; not in the sense of hiding failures, but in terms of actively promoting successes.
  • Advocating for your team to leadership: if there’s anything about the way Treehouse works, as a company, that causes any sort of inconvenience or hardship for my team, I need to be bringing that up as long as there’s a possibility it can be resolved by leadership.
  • Managing expectations for your team with leadership: Making sure that everyone is on-board with what your team is doing and when/how their tasks are going to be completed is important; not only does it help ensure that your team’s focus is in the right place, but it also keeps leadership informed enough to make responsible decisions when strategic decisions need to be made.

Why this is a good thing:

For lack of a better way to put it, if you manage up properly then your team doesn’t have to worry about leadership being on their backs. Managing up properly effectively means that you’ve created a barrier between your team and the leadership level, and by acting as a go-between you can help your team stay on-task and productive.

Managing Down

"Dilbert comic strip, 11/25/2009"

What this means:

“Managing down” is the act of managing the careers of the individual members of your team. Specifically, it involves the following:

  • Managing the workload of your team members: making sure that everyone is working on the appropriate tasks and is cognizant of any deadlines or other pressures that might affect those tasks. This is what most people think of when they traditionally think of “management.”
  • Improving the career of your team members: making sure that on top of everything else, your employees are building a better career for themselves. This can take several forms, from making sure that they’re happy with their job to actively working with them to improve or add to their skills.
  • Communicating with your team members: if you’re managing up properly, then your team often isn’t included in a lot of the conversation that happens at the leadership level - which is good, because a lot of that conversation isn’t very useful to your team; it can be a lot of back-and-forth about ideas that will never come close to being implemented. But there is a lot of valuable information that you will need to convey to the rest of your team - filtering the useful stuff from the distracting stuff and disseminating that to your team is a very important part of the job description. Beyond that, you’ll also need to be sure to communicate clearly on any decisions that you have to make, and make sure that your team is communicating well within itself.

Why this is a good thing:

When you get a job as a manager, this is what people are expecting you to do - manage your direct reports. By making sure that your team is working on the right stuff, is focused on self-improvement, and are on the same page with leadership about the company’s direction and vision, you’re building a team that will execute effectively and efficiently.

Managing Sideways

"Dilbert comic strip, 12/07/1998"

What this means:

“Managing sideways” is the act of setting yourself up as a go-between between your team and the rest of the company. It means that all communications go through (or otherwise include) you, and that you put yourself in a position to “approve” work before it’s finished.

Why this is a bad thing:

Aside from the obvious observation that you’re generating a lot more work for yourself by managing sideways, you’re also at least implicitly saying that you don’t trust your team to do their jobs. This is a problem for everyone in the company - it’s a problem for your employees, because without freedom to act without oversight they’ll never grow in their careers. It’s a problem for you, because you’ll never be able to truly delegate any tasks. And it’s a problem for the company at large, because now all the work that gets done by your team has one overloaded point of failure: you.

So I constantly try to remind myself to manage up, and down, but never sideways. I’ve encouraged everyone on my team to call me out if I ever seem to be inserting myself between them and their work, and hopefully they’ll honor that - the temptation is pretty strong to try to control everything, and although I feel like I’ve been getting better about it I’m sure there are still times that I try to get too involved in specific tasks for my team. I still think that there’s a lot of value in the other two “directions” of management, though, and try to practice those as zealously as I am able.

Is this a good way to look at the task of management? So far it seems to be for me, but I’m still relatively new to the trade. We’ll see how it works out as time goes on, I suppose.

Take Time to Be Awesome

Don't forget to be
awesome

At Treehouse, we have 6 developers in a team of 50+ people. I’m told that’s unusual for a web-based startup, and that typically the company’s staff (and hence direction) is dominated by a team of developers.

There’s good reason for this difference - at heart we’re a content production company, so that has to be our focus. The development team at Treehouse is really there to support that goal. We don’t get to set the priorities for what gets worked on and what doesn’t, but we’re all ok with that.

We had lately fallen into a trap though, and as the team leader I’ll admit that it was mostly my fault. With 40+ internal ‘clients,’ the list of “really important things to do” is kind of overwhelming. There’s a huge temptation there to just plow through the list as quickly as possible, and that’s what we were doing - each of our developers would spend 1-3 weeks completing project A, and then immediately turn around to start on project B.

The reason this is a trap is because it ignores the importance of self-motivated work in creative disciplines (And yes, software development is a creative discipline - I wish I had a nickel for every time I heard someone say something dismissive like “it’s just engineering…” but that’s a topic for another post, perhaps). Staying on top of the priorities for the rest of the company is a great thing, but it also can turn into kind of a grind when you never get to tackle any of those awesome little ideas you have day-to-day.

This was manifesting itself on our team, and it was really apparent once I started looking for it - we believe pretty strongly in the 4-day work week and maintaining a healthy work/life balance at Treehouse, but the dev team (including myself, back when I actually wrote code) was consistently spending a lot of time working on nights and weekends. Why? Because stuff we did during working hours was all the stuff we had to do, and on nights and weekends we could work on those little things that we wanted to do. It’s fantastic to work with a team of guys who are that motivated, but that’s a solid recipe for burnout.

To try to address this problem, I’m giving the developers at Treehouse time to be awesome. Specifically, after every major iteration they do on the app (one of those 1-3 week chunks of work), I’m encouraging them to take some time (a few hours, a day, maybe a day and a half) to do something they think is awesome or important even if it isn’t on our “big list of stuff to do.” Maybe that means refactoring an ugly part of our code, or adding in a “nice-to-have” feature to the site, or fixing a workflow for our teachers in admin that’s been bothering them. The big thing is that it’s something they choose, and is something they think is awesome.

We’re just starting this policy, so I can’t yet report on results, but I really like the theory of it. Delays to our company-wide priorities are going to be minimal (we’re talking about a few hours here and there), and while I don’t expect it to totally eliminate the extra work that the team is doing, it will allow the team to be more expressive in what they work on. I think it’s a win-win.

I am curious, though, if anybody has any other ideas or thoughts about my “take time to be awesome” initiative.

Pow, ZSH, and Rbenv

I just spent the better part of an hour trying to figure this out, so I thought I’d share.

Pow, ZSH, and rbenv are all great tools in their own right, but they really don’t want to play well together. Despite all my attempts to the contrary, pow refused to recognize my rbenv setup and tried to load up my Rails application using the system (1.8) version of ruby.

This issue in the Pow repository kind of illustrates how weird the issue is - the history is littered with a bunch of different suggested fixes (and even an allegation that Pow 0.4.0, which is the current version as of the time of this blog post, will do away with the issue altogether… which it doesn’t appear to have done). After trying several different alternatives, this is the one that finally worked for me:

  1. Create a file named .powconfig in your home directory
  2. Put the following in that file: export PATH=`brew --prefix rbenv`/shims:`brew --prefix rbenv`/bin:$PATH
  3. Restart pow by running touch ~/.pow/restart.txt.

That immediately cleared up my problems and ended a rather frustrating search for answers.

I’m Doing It Wrong.

Far too often in our industry, people climb to the top of their blogs and shout to the rest of the world: “You’re doing it wrong! I’m doing it right! Maybe if you were more like me, you’d be more successful. Maybe if you were more like me, I’d consider you to be a real programmer. Maybe if you were more like me, I’d want to work with you, and I wouldn’t shudder in the very depths of my soul every time I looked at your code.”

And I know. I do it too, sometimes. But I want to make up for it. Here’s a brief list of some things I know I’m doing wrong:

  • I don’t write tests first as often as I should.
  • I regularly make changes/bugfixes in code without taking a few minutes to make the surrounding code any better.
  • I break code out into new objects when I shouldn’t, and I pile methods onto existing objects when they should be split into their own class.
  • I regularly succumb to the pressure of my todo list, and let myself push quick fixes out the door when I feel overwhelmed.
  • I often care more about how the code looks to me than about how it works for the customer.
  • I sometimes approach problems with a “we can’t do that” attitude instead of approaching it from the “how can we make this work?” angle.

Everybody makes mistakes, and everyone has pet problems they’re working on. Maybe we should be less worried about telling every other developer how to do their job, and focus more on sharing what we’ve learned about our own habits?

Computer Science Considered Harmful

Jason Gorman wrote a post titled Let’s Not Call It “Computer Science” If We Really Mean “Computer Programming”. Good read.

A few notes:

The feedback I get from CS graduates who’ve been working in software (and from their employers) is overwhelmingly that their degree didn’t prepare them at all for software development. Time spent learning the UML meta-meta-model and Object Z is, for 99.9% of developers, time completely wasted - time that could have been spent learning something useful like how to write good automated tests or how to write an efficient and robust build script.

Are there really CS programs out there that focus on UML and Obj Z? I mean, we covered UML, but it was a couple of days as part of another course.

I should also probably mention that software developers, unlike computer scientists to some degree, need to have very well-rounded general educations, too. Their ability to communicate - and not just through code - as well as their ability to reason and quickly learn in a wide range of problem domains requires more than just coding skills. It is possible to be a successful computer scientist and not know how the futures market works or how gas propogates through pipelines or what the tax laws are pertaining to international online sales. As a freelance developer, I worked in everything from engineering to corporate law, via retail, TV and banking. Without a good general “classical” education, I think I might have struggled to wrap my mind around some of the domains I’ve been parachuted in to fast enough to get anything useful done.

A-freaking-men. Being a programmer is like being a writer - the more “real-world experience” you have, the better your craft is.

Developers will need some theory, and I’m painfully aware, too, of the degree snobbery that most employers harbour. So I propose that the right course would be a 5+ year apprenticeship with part-time degree study - CS in the classroom 1 day a week, software development in the office the other 4.

Apprenticing as a developer isn’t exactly a new idea, but… what are the chances that our higher education system actually implements that?

Oh, and sorry about the title. I couldn’t resist.

On Higher Education

I’m writing this post in reference to a tweet from Chris Strom:

This is a pretty common mindset these days. As someone who works at Treehouse, I obviously either agree that college is a horribly inefficient way to prepare yourself to enter the workforce, or… well… I need to find a new job. :) Treehouse bases its value on the idea that you can gain all the skills you need to get a job in the tech sector - not by paying thousands of dollars a year and spending four years taking classes, but by paying tens of dollars a month and learning what you want, when you want.

It seems like a no-brainer, right? The “higher education” system is a dying leviathan that refuses to acknowledge its own mortality; much like newspapers, phone books, and the once-burgeoning pager industry.

I think there is a nugget of truth to all of this, but it’s not new and it’s definitely not a product of the internet age. That nugget is:

If your aim is to become proficient in a specific profession, attending college for four years is one of the most inefficient ways to achieve that goal.

This is true for a number of reasons:

  • Colleges are always behind the times on industry standards. This isn’t really the fault of colleges or professors, it’s just how it works. It takes time to learn about new techniques, realize their importance, update curriculums… and that assumes that the professors have the time and energy after fulfilling their other duties to keep a close eye on the industry.
  • You’re spending four years out of the workforce. Since you can’t get up-to-date information on your industry (per the above bullet point), you’ve effectively delayed your real expertise-gathering experience by several years.
  • There’s a lot of stuff you don’t need. None of those pesky graduate requirements apply directly to your field, but you still have to spend weeks (if not months) of your time learning about literature and history and philosophy.

So why do we pay tens of thousands of dollars to go to college? If it’s such an inefficient return on our investment and doesn’t provide us with up-to-date experience we can use to be a better entry-level employee, then why do companies require us to have a degree before we can apply for employment?

College was never intended as a means of preparing ourselves to enter the workforce; it was originally intended as a means of further preparing ourselves to enter humanity. Much like teaching children things they may never find practical in grade school - art, music, algebra, poetry - college was a guided tour to broaden our horizons and allow us to gain a certain communion with the greater history of western science and culture. It was an experience interesting to few and one that fewer could take advantage of. If you were interested in learning a trade, you didn’t go to school - you apprenticed.

What blog post is complete without an XKCD comic?

Over the last fifty+ years that has changed - various programs (including the grossly bloated student loan industry) encouraging attendance in college has shifted the idea of college from being a luxury of those who had the money and the desire to being almost as compulsory as grade school. Job recruiters turned to the possession of a college degree as a quick and easy filter to cut down on the number of applicants they needed to consider, which in turn drove up demand for college education even further and put pressure on colleges to impart “useful” skills to their students. The whole mess very quickly descended to the point where people who wouldn’t have even considered college 60 years ago now see it as a necessary (and horribly expensive) evil.

But in a lot of ways, a college education still retains a lot of its earlier value - it’s not great for training you to fill a certain position, to be sure, but much like those music lessons you took in grade school it’s a fantastic way to expand your mind and expose yourself to new ideas and ways of thinking.

Does that mean that everyone should go to college? Of course not. Intellectual pursuits like that aren’t going to be valuable to everyone, and employers seem to be coming around to the idea that a college degree isn’t always a value-add when it comes to the worth of a potential employee.

That said, I got a lot of value out of my college education. The technical training I got in computer science hasn’t had much of a direct impact on my career, but I wouldn’t be anywhere near the person I am today without the general education I received. College may not have a lot of value for preparing you to enter the workforce - which is why I believe so strongly in Treehouse and others like it - but that doesn’t mean that it’s without value altogether.

OS X Apps, Environment Variables, and You

There are a lot of things I really don’t like about OS X. This isn’t a secret. At the top of my list right now is the weird pseudo-shell OS X uses when it launches native applications. Don’t know what that means? I don’t either, really. I still haven’t figured it out. Here’s what happened, though, and maybe someone will find it useful.

I use ZSH for my default shell. I have a lot of customizations to it, and some very important shell functions that get instantiated (especially RVM, which I use to manage the various versions of Ruby I have installed for different projects). Normally, my $PATH variable looks like this:

1
/Users/duwanis/.rvm/gems/ruby-1.9.3-p0/bin:/Users/duwanis/.rvm/gems/ruby-1.9.3-p0@global/bin:/Users/duwanis/.rvm/rubies/ruby-1.9.3-p0/bin:/Users/duwanis/.rvm/bin:/Users/duwanis/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin

I wanted to poke around with Sublime Text 2 (I’m a vim guy at heart, but I like to play around with alternatives to expose myself to new ideas). However, I noticed that most of the plugins that interacted with a shell process were failing (I couldn’t run ruby tests, generate ctags… a whole host of issues). With a bit of hackery I was able to determine that my $PATH variable from inside ST2 looked like this:

1
/usr/bin:/bin:/usr/sbin:/sbin

…Well, that’s not right. As far as I’ve been able to determine, OS X starts up applications with a very basic shell environment, regardless of your user settings or shell profiles.

After lots of futile attempts at fixing the problem by trying to figure out where I could configure that basic shell environment, I finally found a workaround in a StackOverflow question. By creating a shell script that wraps the default application executable like so:

1
2
3
4
5
6
7
#!/bin/sh                                                                       
                                                                                
source ~/.profile                                                               

logger "`dirname \"$0\"`/Sublime Text 2"                                        

exec "`dirname \"$0\"`/Sublime Text 2" $@

…and updating the application’s Info.plist file as described in the first answer to the SO question I linked above, ST2 now always starts up with the appropriate environment configuration and child processes have all the information they need in order to execute correctly.

Why this doesn’t happen by default, I’ll never know.

Why Toolsmithing Is Important

This weekend I took a few hours and read through Brian P. Hogan’s book on tmux.

While I did get a lot out of the book, I’m not going to talk about tmux itself. Instead, I’d like to talk a bit about toolsmithing.

It’s generally understood that as software developers, we don’t actually spend a whole lot of time writing code. A significant portion of the time we spend in our code editing environments is actually spent reading and understanding code - there’s a comparatively significant amount of effort involved in getting to the point where we can contribute anything material to the code base. On top of that, most of us actually don’t spend all day in the editor - there are calls/chats with coworkers and bosses, support issues to look through, data the client needs gathered, and all manner of other non-coding tasks that we get sucked into over the course of a normal day.

Often people look at toolsmithing as a means of gaining efficiency - by becoming more familiar with your tools overall and discovering shortcuts, you can shave seconds off of common tasks and end up being more productive in the long run.

This is one of the attitudes conveyed in the tmux book. The reason you should familiarize yourself with tmux is because it will make you faster and save you the excruciating few seconds it takes to reach for your mouse.

But if we don’t spend all that much time, comparatively, using our tools… how much does a few extra seconds actually buy us? Even if we’re generous and assume that we’ve saved ourselves 5 minutes over the course of the day, is 5 minutes of extra productivity really going to do us that much good?

(A common fallacy here is to say “Well, that adds up to 25 minutes per work-week, or about 100 minutes a month, or about 20 hours over the course of a year - that’s like getting two and a half extra days of effort every year!”. If only the world worked like this, though. I can’t take the 5 minutes I saved today and put it into some kind of time-bank where I can redeem it later - I’ll either use it to work on something right now (which has to be simple if it’s going to be done in 5 minutes) or I’ll waste it on leisurely pursuits, like taking an extra little break to walk around the house.)

So why do it, then? If it doesn’t provide us with huge daily wins in our productivity, is there any point in trying to improve our tools?

Obviously I think so, or I wouldn’t have wasted my Saturday doing so. To me, the real answer is about pride (the good kind), and passion, and motivation to a much greater extent than it is about efficiency and productivity.

A carpenter can build great things with tools from Wal-Mart. A chef can cook delicious dishes with pots and pans from IKEA. A writer can pen a brilliant novel using a Bic and a $0.79 college-ruled notebook. But when you look at how the great artists in their field work, you find that they tend towards more expensive tools. Does the soft leather cover on a writer’s notebook enable them to write faster? Does the chef’s copper cookware help her prepare more dishes at once? Does the carpenter’s sleek titanium hammer help him drive more nails?

Great tools are inspirational. When we’re confronted with tools that are interesting we are inspired to work with them, whether that interest comes from their beauty, elegance, simplicity, or specification. This inspiration helps to yield better results from our labor.

So the next time you get a chance to mess around with a new tool or tweak your existing workflow, I would encourage you to get in there and do it. Even if you decide not to change anything, taking the time to appreciate the tools of your trade will push you to become better.

Introducing Nutrasuite

Just a quick note about a little minitest-enhancing library that Alan Johnson and I hacked up today. Nutrasuite is a dirt-simple gem that adds contexts to minitest for you. It might do more in the future, it might not. But for now you can get organization in your tests as easy as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
require 'nutrasuite'
class SomeTest < MiniTest::Unit::TestCase
  a "newly instantiated test object" do
    setup do
      some_setup_stuff
    end

    it "tests for stuff" do
      assert true
    end

    that "has some other setup stuff done" do
      setup do
        some_other_setup_stuff
      end

      it "tests for more stuff" do
        assert true
      end
    end

    teardown do
      some_teardown_stuff
    end
  end
end

A few notes:

  • a, an, and that all define contexts. Between those three you should be able to put together grammatically-correct sounding tests.
  • it defines a new test.
  • Setups and teardowns are run for each test. This means that you can safely take advantage of minitest’s natural test randomization.
  • If you care about LOC (I don’t, really, but it kind of speaks to the simplicity) this stuff is set up in 122 lines, and doesn’t monkeypatch anything or pollute the kernel namespace. Hard to get much simpler than that.

So nothing too special, but we found a need for it and put it together (in fact, if you’re curious, it’s already in use over on Timberline, which I haven’t announced yet). And by “we put it together” I mean Alan figured out how it was going to work and I filled in the code and came up with a quirky name (p.s. Nutrasweet - please don’t sue me. You have better things to do).

Introducing Redis::ExpiringSet

Yesterday I released a new gem: Redis::ExpiringSet. It creates a new datatype for use with Redis - an Expiring Set.

What’s an Expiring Set and why should I care?

Expiring Sets behave exactly like normal Sets in Redis, with one exception: each item in the set has an expiration time, and once that expiration time is past the item will be removed from the set. This is particularly useful for keeping track of recent items.

Suppose, to create a contrived example, you want to keep statistics on the number and type of emails you’ve sent from your site in the last 24 hours. Suppose that this data has a string representation. Every time you send an email you can just put that data into an expiring set along with an expiration time:

1
2
3
4
5
6
7
require 'redis-expiring-set'

# assume @redis is your redis database connection,
# and @email is your email job
expset = Redis::ExpiringSet.new(@redis)

expset.xadd("email_data", @email.to_s, Time.now + 1.day)

Now if you want to access your data, you can just call xmembers, and you’ll be guaranteed to only get info from the past 24 hours:

1
expset.xmembers("email_data")

There’s also a “monkeypatch” file you can include to make all of this available directly off of your Redis objects:

1
2
3
4
5
6
# again, assume @redis is your redis database connection
require 'redis-expiring-set/monkeypatch'

@redis.xadd("email_data", @email.to_s, Time.now + 1.day)

@redis.xmembers("email_data")

This isn’t the default behavior because I didn’t want to force you to monkeypatch the Redis library if you didn’t want to.

More details and documentation are available at the github page.