The trajectory of a software engineer… and where it all goes wrong.

I’m going to do something difficult and controversial and, since this is a first cut at it, I probably won’t do it perfectly. I’m going to develop a system for evaluating the skill and impact of a software engineer or, at the least, outline a trajectory for the idealized growth of a software programmer. The scale runs from 0.0 to 3.0, with each whole number representing a threshold in professional development.

Largely, this is an engineering scale based on the needs of software businesses. It’s not about mathematical ability or the capacity to write fast algorithms. Nor is it about the depth of knowledge a programmer has about the internals of the Linux kernel. Those are important, and will usually develop in tandem with an engineer’s skill, but not the primary focus of this system. It doesn’t represent everything one needs to know in order to evaluate a software developer. It’s also not a substitute for “performance reviews” or to be used for “HR matters”. Sometimes a “2.1″ may need to be fired for personality reasons, whereas an amicable “1.2″ is an asset to a company.

Finally, this scale is somewhat context-dependent, noting the difference between skill and impact. Change the programming language or technology stack, and a developer can rise or drop by a full point. Also, a developer needs to be on a team for 6 to 12 months (in most cases) to reach a level of impact commensurate with her capability. It’s tempting to speak of levels like “1.5″ as if they were objective ratings of a person’s skill. More accurately, they describe scopes of contribution and fit between a person and job role. The size and needs of a company also have a major impact. Small technology companies often encourage their people to “experiment” 0.2-0.5 points above their level of demonstrated skill, and to thereby grow quickly, while large and bureaucratic firms usually slot people an equal amount below their skill levels (because of inherent limitations on leadership positions).

The scale I’m about to define comes from one insight about human organizations. Teams, in general, have four categories into which a person’s contribution can fall: dividers, subtracters, adders, and multipliers. Dividers are the cancerous people who have a broad-based negative effect on productivity. This usually results from problems with a person’s attitude or ethics– “benign incompetence” (except in managers, whose job descriptions allow them only to be multipliers or dividers) is rarely enough to have a “divider” effect. This is an “HR issue” (dividers must improve or be fired) but not the scope of this professional-development scale, which assumes good-faith and a wish for progress. Subtracters are people who produce less than they cost, including the time of others who must coach and supervise them. As a temporary state, there’s nothing wrong with being a subtracter– almost every software engineer starts out his career as one, and it’s common to be a subtracter in the first weeks of a new job. Adders are the workhorses: competent individual contributors who deliver most of the actual work. Finally, multipliers are those who, often in tandem with “adder” contributions, make other people more productive. In many industries, being a multiplier is thought to be the province of management alone, but in technology that couldn’t be farther from the truth, because architectural and infrastructural contributions (such as reusable code libraries) have a broad-based impact on the effectiveness of the entire company.

What this scale intends to measure is the transition from a subtracter to an adder (0.0 to 1.0), from an adder to a multiplier (1.0 to 2.0), and from a “local” to a “global” multiplier (2.0 to 3.0). I ignore issues associated with “dividers” (who may be highly competent engineers; as I alluded above, a 2.0+ engineer can be a “divider” if there are personality problems) because those are “HR issues” (improve quickly or fire) while this scale is concerned with skill and long-term professional development.

Approximately speaking, the ranges are:

0.0 to 0.4: Complete novice: this is the level of a person who is still “learning programming”, by which I mean the person is likely to have trouble getting code to compile. This person has technical limitations that make unsupervised professional-level contributions impossible. Typically, this level of development is observed only in introductory programming courses. Most college interns are already at 0.5 or above when they start programming professionally.

0.5 to 0.7: Sound grasp of fundamentals: this is the level of someone who can call herself a “programmer” but not yet an “engineer”. Can competently build small systems (up to 3000 lines of code or so) but the code is likely to be sloppy and unmaintainable. At this level, getting the code “to work” is not an issue, but the code is likely to be inefficient, and the person’s architectural skills (due to inexperience) are likely to be weak. Typical level for a college student from a strong school before her first software internship.

0.8 to 0.9: Becoming an adder: this is a person who is aware of the practical concerns (maintenance, runtime safety) associated with software development. She can deliver useful scripts and has a decent understanding of software engineering. She is capable of using Google and online resources to answer small-scoped questions about development (such as how to do File I/O in an unfamiliar language).

1.0 to 1.3: Full-fledged adder: this person has demonstrated full competence as a software engineer and can be trusted to manage a small project “full-cycle”: design, implementation, testing, and integration. Code will usually be of reasonable quality, but the engineer is not ready to be responsible for meeting deadlines, production support (being “the 3:00 am guy”), or company-wide concerns. A team of mostly 1.3 engineers can produce solid work (the average software engineer is around 1.1; note that the 50th-percentile software job is a low-autonomy “Java jockey” position) but a software company whose best engineers are in this range will struggle to produce quality software.

1.4 to 1.6: Solid adder: well above-average (top 10%) by software-industry standards, but average (at 5-10 years’ experience) in the context of the best companies (e.g. elite startups, Google, and research divisions of IBM). Can be trusted to independently solve most problems in an elegant and maintainable way. Engineer can make reasonable time estimates and communicate in both business and technical terms with management as well as other engineers. Can handle small levels of deadline/delivery responsibility and should be encouraged to participate in architectural decisions (“multiplier” concerns). Technical leadership non-urgent projects is a serious possibility.

1.7 to 1.9: Becoming a multiplier: top 5%. Engineer is on track toward full “multiplier” status. Her contributions not only solve immediate problems, but improve the state of company infrastructure. She routinely suggests architectural and process improvements, and is ready to be “tech lead” for important projects.

2.0 to 2.3: Full-fledged multiplier: engineer is an objective multiplier whose contributions add immense, demonstrated value to the team– an obvious technical leader. This represents the top 2-3% of software engineers in problem-solving, architectural, and leadership skills.

2.4 to 2.6: Becoming a global multiplier (“Fellow”): engineer’s achievements are vast and astonishing. Contributions are company-wide or extend even further (e.g. to the open-source community). Represents the top 0.25% of software engineers. Can be trusted to work on independent research (with full autonomy) and lead major initiatives.

2.7 to 3.0: Senior fellow: engineer is known within and outside the company as one of the best computer programmers alive. These are people who can design new programming languages and produce good ones.

How does this scale play out? What practical conclusions can we draw from it? Ideally, it exists to plot the trajectory that most programmers will take. Sadly, the reality of the software industry is that the average software engineer never gets far above 1.0. Since the difference between these awful programmers is not (at least, in my estimation) a problem of intellectual ability– perhaps it’s one of curiosity and drive– this is unfortunate.

Software is, by far, one of the most structurally cooperative systems in the world. What I mean by “structurally cooperative” is that our own well-being is correlated positively with the performance of others in our industry, even when they’re nominally (and transiently) “competitors”. Great programmers teach other programmers to be great and build great technologies, which are often released into the open-source community. Conversely, the badness of the average software developer causes a world of suffering for the good ones. Why are so many programming jobs (and libraries) in brain-dead languages (such as Java) rather than functional-programming languages (e.g. Scala, Ocaml, Clojure, Haskell)? Because while the Java+IDE environment makes it extremely difficult for an individual engineer to have a 1.5+ impact –there are two cases in recorded history of programmers breaking 2.0 in Java; one is Martin Odersky, who wrote Scala, and the other is Rich Hickey, who wrote Clojure– the state of the tooling makes it possible for the 0.7′s and 0.9′s to get a 0.1- to 0.3-point bump, so long as they stay within their IDEs and don’t have to work with a computer (gasp!) at the (God, no!) command line.

Sadly, the “half-life” of a software developer is about 6 years. The trajectory of an “average” software developer looks like this: he leaves a JavaSchool at a competency around 0.6 and grows by approximately 0.1 point per year– that’s not blazing along this stretch (0.1/year would be quite fast above 2.0, but it’s poky below 1.0) but a reasonable pace for a person with little mentoring and a lackluster environment. Around 1.2, he reaches a technical ceiling, convinced that “programming” has intrinsic limits on individual contribution, except for “geniuses” who have 167 IQs and 40 years of programming experience (at age 44). This is because the Java+IDE environment, and operating systems like Windows, are designed to bring up the rear (0.7 to 0.9) while holding back the best programmers, artificially imposing that “ceiling” around 1.2-1.5; these technologies are intentionally designed for a performance-middling effect– to make it possible for huge teams of “commodity” developers to produce something while holding the excellent back from producing great things.

If he had spent some time reading Hacker News and learning about this fancy “functional programming” stuff, he might have seen a credible path (for non-geniuses like this writer) to 1.5 and beyond. But he hasn’t, so he burns out on “code monkey” work and moves into management. Or he goes to law school. Or business school. Because he wrongly concluded that this “engineering” thing (as he experienced it) was just too limited and dull to do for another decade. Even after six years, he was a mediocre, bottom-90-percent programmer and so no one misses that he’s gone, but with better guidance and exposure to superior technologies, he could have become great.

This is what’s at stake in “language wars” and arguments about the configuration of the software industry. It’s not just about hating to write (much less maintain) code in unattractive languages like Java and C++, or use hideous and inelegant operating systems like Windows. Far more is involved here.

About these ads

38 thoughts on “The trajectory of a software engineer… and where it all goes wrong.

  1. There are two cases in recorded history of programmers breaking 2.0 in Java.

    Now you’re just getting silly. Sure, Java programming is annoying. But people have written things with huge multiplier effects in much clunkier languages than Java. A moment’s reflection will bring any amount of examples to mind. There is nothing inherently constraining about writing in Java.

    When I began to write the first version of my TagSoup parser for HTML, I wrote in Java because at the time (around 2002) Java had the best Unicode story, and I knew I needed Unicode to get the job done. At the time, the alternative would probably have been C; Python wasn’t up to it.

    • I’m obviously exaggerating Java’s defects, but I think it is exceedingly rare to break 2.0 in a demanding software environment in Java or C++, and I think it is true that when a 2.0+ engineer is forced to use such a language, her first move is to create a DSL to overcome its defects. (Sub-2.0 programmers also do this, badly; hence “Greenspun’s Tenth Rule”.) That’s essentially what Odersky and Hickey did. They saw that some cool technology (JVM) was tied to a horrible, dead-end language and they wrote really good languages that interoperate with it.

      Java the language, by design, has a mediocritizing effect. It’s not just about the language. It’s about those stupid-ass, flow-breaking singleton directories (“com”) and the reliance on IDEs and the requirement of package names matching directory name and the insane-fucking-pinging about the file system because every class has to be in its own file.

      I would generally argue that the transform for Java (on engineer ability) is 0.5(X-1) + 1, which means it actually brings up the rear (turning 0.6s into 0.8s) and that’s why it remains “the standard”– because there are a lot of 0.4 to 1.0′s out there and Javaland helps them. For C++ as used out in the field, that transform is more like 0.8X– not quite as mediocritizing as Java, but across-the-board demoting. This difference in formulas also explains why Google’s best engineers (2.5+) prefer C++ over Java; at 2.5, Java takes you down to 1.8 while C++ only brings you down to 2.0.

      There probably is such a thing as 3.0+, which makes it possible to reach levels above 2.0 in Java and 2.4 in C++, but it has got to be pretty rare. I don’t know what a 3.4 looks like, because that’s someone so far above me in capability that I can’t even hope to measure it.

      As for my confidence that 2.0-level engineering contributions are very rare in Java, I’d say that 2.0 is a high bar, and that this is an engineering scale, not a programming one. It’s possible to write great (fast, as elegant as the language will allow) individual programs in Java or C++, so long as only one person touches or has to maintain the code, and the programs don’t get longer than about 5000 lines. I think it’s incredibly rare that a person can be a great engineer in them.

      To give you a sense of what 2.0 is, I’d rate myself around 1.6-1.7 at this point in my career, even though I’ve definitely had a lot of multiplier-level contributions at companies where I’ve worked. The 1.0 – 2.0 interval is actually about the (gradual) transition from being a reliably competent adder to being an initiative-taking, architecturally-capable multiplier, so even people at 1.1-1.2 have multiplier contributions (“flashes of brilliance”)– an occasional well-written script that others can use, or a fix to the build system that shaves 15 seconds off everyone’s compile cycle. 1.5-1.9 is the range of people (usually called “senior” engineers) who are on their way toward being multipliers (automation, source code cleanup, excellent architectural decision-making) but still tend to fall back to less elegant and generally useful “adder” patterns, especially if there are deadlines involved.

      “Language wars” might seem like pointless pissing contests, until one considers that this is what some of the most highly driven, talented people in the world do for 40-50 hours per week, and a change in language can bring about a half-point drop in one’s skill level, and that’s something no one wants. The argument that “a good programmer can be productive in any language” is nominally true but not very useful. 1.7′s don’t drop to 0.4 when they use braindead languages, but they can drop to 1.1-1.2. (Personal experience, C++ and Java.) In a highly demanding arena, a 1.2 is only 1/10 as valuable as a 1.7, so that’s a huge drop.

      What I like about functional programming is that it (like working in a startup) is rocket fuel. Switching to Ocaml if you’ve never used it before isn’t going to bump someone from 1.1 to 1.7 immediately but it gives a person the direction he needs in order to get there, and the freedom to try. (The way to become a 2.0 engineer is to attempt 2.0 engineering.) Given the freedom to use powerful languages and abstractions in new and interesting ways, an intellectually strong person can go from 0.5 to 1.0 in a few months, 1.0 to 1.5 in about three years, and 1.5 to 2.0 in maybe five more. This means that a person can go from being a compete beginner to being a technical leader in 7 to 8 years. Compared to the plodding rate of the Java jockey, who might reach 1.5 by the time his hair starts turning gray, that’s ridiculously fast progress. I also believe that the difference between the elite programmers and Java jockeys isn’t one of innate ability; I think Java (and those insane “design patterns”) actively retards them, slowing an engineer’s rate of improvement to 1/4 of what it should be.

      • At 9 years (if you don’t count school) of professional dev, I’ve worked in JS, JS frameworks, C++,Java + java frameworks, C#/.NET/MVC + frameworks, SQL and NoSQL, Max MSP and vvvv, cloud computing + messaging, HaXe. I’ve lead (engineering) projects and have been a grunt. My criteria are: your engineering works and your code works at the end of the day, and improves the future of the stakeholder(s). Meeting deadlines, managing expectations and working well with others is just a given. All these OOP languages (except functional) all start looking the same. I’d put myself at a 2.0 – 2.3 but would never consider it under the lens of the current technology being used (at the company or project or role or whatever). I actually hate the fact that larger corps don’t let you cross boundaries as much as an engineer. Maybe I want to do front AND back end…

      • Micheal you make such broad trolling statements it is obvious you really aren’t up on your modern architectures. I told you in another post about Groovy/grails which is Java and make huge steps to break that paradigm you are talking about and is popular for just that reason. So stop ranting and try to pay attention to what people are saying for a second, ok?

    • Have to agree. Obviuously the author is unawares of Scala and Groovy/Grails and the convention over configuration changes in Java in the last 5 years. Aside from that, Hibernate is leaps above anything else out there, Spring security is a standard, and if you have never tried the Grails plugin environment, you are truly missing out on a simplified web experience in Java.

  2. [1, 2, 3] is a three-point scale.

    [0.0, 0.1, 0.2, 0.3, ... 2.8, 2.9, 3.0] is a 31-point scale.

    I stopped reading there, but I skimmed the rant about Java, and I sympathize.

  3. Fair point, but I actually don’t think of it as a “31-point scale” so much as a continuous 0.0 to 3.0 scale. I used 0.1 increments because t’s impossible to get more precision than that. Even at the +/- 0.1 level, it’s hard to measure. The differences between 1.0 and 1.5 and between 1.5 and 1.8 are noticeable, but the difference between 1.7 and 1.8 is probably not.

  4. “I think Java (and those insane “design patterns”) actively retards them”

    I agree. I had a slow progression from C (college) through LotusScript (VB’s crippled cousin), Java and beyond.

    Moving from LS to Java was mind-expanding and freeing.

    Getting beyond Java and exploring Lisp, Javascript, and Clojure was a big shift into higher gear, much more expansive and freeing.

    I think I have a capable intellect, but not that rare inspired mind that seems to create brilliance from within. In the proper environment, with the proper examples to follow, my growth is much more significant and accelerated.

    • C is a great mid-level language, and it gave us Linux (a clear example of a 2.8+ piece of work). At a time, the amount of complexity needed to have be a multiplier was less than it is in most jobs today. For example, grep had a huge multiplier effect but was simple enough to be written in C. It also doesn’t require ongoing maintenance by the user. It’s just working software.

      Java might be considered an acceptable mid-level language as the “assembly language” of the JVM, a piece of software that will enjoy at least 20 more years of relevance thanks to Scala and Clojure. I’m not sure how I feel about it. I’m reading Java Concurrency in Practice (I’m an avowed Java-language hater, and I like that book). I just learned today that longs and doubles are not thread-safe. If one thread updates a double, another thread may read a value with one 32-bit word of it updated and the other not. Holy fuck.

      You’ll like my follow-up post (which I’m working on now). What Java has become (inspired by Microsoft’s failed attempt to commoditize programmers) is a sandbox designed to make programming low-risk (a bad programmer can crank out shitty classes that can be thrown away) but the discouragement of risk ended up producing an environment with low growth. Lisp is “riskier” (you can paint yourself into corners with it) but allows faster growth.

      You should look into Ocaml, Haskell, or Scala. I think the next thing for you to learn is what static typing, done well, looks like.

  5. Pingback: The World In Links (1/30-2/5/2012) - Developers, Facebook, SQL

  6. Pingback: REPL or Fail « Michael O.Church

  7. I think you are far to negative when it comes to Java. Why can’t a Java programmer be a good architect as well? And your comment about the lack of thread safety for a double is missing the point I think. Why should such an operation be tread safe in the first place?

    • Functional programming encourages people to grow in a way that enterprise Java doesn’t. If the language is 10 times as verbose, that means you cover conceptual complexity (i.e. dealing with the hard stuff that teaches you things) at 1/10 the pace. Since software scales badly with bigness (a team of 10 does not accomplish 10 times as much as an individual, and most year-long projects are not 12 times as interesting as month-long projects) this aspect makes it even harder to get anywhere in a language like C++ or Java, where the accidental complexity imposes a lot of drag.

      There are Java developers who are great programmers, but they’re rare and they’ve usually had to push themselves in a way that would probably involve less resistance if they had languages without all that accidental complexity.

  8. Pingback: XWP vs. JAP « Michael O.Church

  9. Pingback: Quora

  10. Pingback: Quora

  11. Mr Church (or should I say Mr. Verbose / Bombastic) – have you ever worked as part of 20 – 25 person team with at least 3 entry and may be 5 junior developers to create some significant product like Photoshop?

    Do you know any significant desktop product that has been written in your favorite languages that is in mass scale use? Can you name one? (I am not counting depth first search here)

    And also can you please tell me as to why it is unsexy to work on big projects? With big teams sizes?

  12. Woah! I’m really digging the template/theme of this website. It’s
    simple, yet effective. A lot of times it’s difficult to get that “perfect balance” between user friendliness and visual appearance. I must say you’ve
    done a awesome job with this. Also, the blog loads super quick for me on Chrome.
    Superb Blog!

    • Honestly, speaking as a PHP dev who worked with Zend, they have no intention of changing the language and there have been so many in fights on their team that alot of people have left and the version of PHP 6 has been postponed indefinitely. Convention over configuration has been embraced by Java (Groovy/Grails), Python, Ruby but PHP will never get it.

      Just about every other language is improving and evolving while PHP trys to be more C-like. So if you want improvements, move to something like Groovy/Grails… otherwise you will be stuck in PHP hell forever.

        • @Andrew, there is no Groovy or Grails, without Java. They’re built on top of Java. They cannot exist without Java.

          Now, if you argue that raw Java is the only thing being considered, then fair point. But I would argue that web-based Java development takes into account not just the language, but some frameworks as well. First among these frameworks are Spring and Hibernate. And the best Spring/Hibernate stack out there is…Grails.

          To come full circle, in 2014, Grails is a serious contender in the web dev stack. Play might be another. Anything less is so 2004-ish. So…are we then talking about the productivity of Java or Grails?

          It amazes me how often a language is measured by what it does, or cannot do, without considering that many times a language is not used in isolation. Is Ruby a pain in the ass? I don’t know. I don’t code in Ruby. But my limited exposure to Rails left me thinking that I would probably enjoy it.

          @Michael O. Church…with all respect, the IDE comment as it relates to Java is garbage. I hope you’re not using Eclipse as your basis to say that. IntelliJ by no means “limits” you. Better yet, don’t use an IDE at all if it bothers you. But Java has no ties to an IDE. At all. None. Go to town on vim or Emacs. Java will still be the same. A class is a friggin text file for Christ’s sake. How do you impeach a language on the basis of the editor which produces the text file used by said language? Come on. That was a reach. Knock Java down where it deserves it, but not that.

          Is Java “great”? Hell if I know. I don’t code in seventeen languages, learning how to write a for-loop seventeen times. It gets the job done for me. Some things about it annoy me, but nothing that makes me cringe (mainly because I spend most of my time in Grails nowadays, and by extension Groovy, so I don’t feel that pain).

          You know what bothers me? Language du jour. Framework du jour. Learning how to do the same thing, in a new way, for the sake of being new, with no meaningful improvement. Now *that* would be a fantastic topic. Imagine I had moved from Struts, to Tapestry, to Wicket, to JSF, to Spring MVC, taking time to learning each one meticulously. Screw that. They all do the same shit, roughly.


        • @Andrew Groovy IS Java. It extends and uses Java and integrates with it 100%. It is the scripting language of Grails. Both use convention over config principles HEAVILY. No XML, makes changes on the fly without recompile… I can go on and on. It is HEAVILY convention over config in comparison to straight Java and all other Java framneworks.

  13. Pingback: Programmer autonomy is a $1 trillion issue. « Michael O.Church

  14. It’s kinda funny and ridiculous that supposed “trajectory” because functional programming advocates are at the very bottom of he pack! Why? Because the vast majority of them simply can’t code real world programs, not to speak of understanding higher level real world software engineering.
    Functional languages are nothing but tools made for mathematicians who don’t have the intellectual ability to learn oop languages.
    FP has been around for more than 30 years and failed to get into the industry for a very simple reason: it has some extremely undesirable characteristics that FP advocates mistaken them for qualities, like writing fewer lines of code in a very cryptical, ambiguous and unintutive way using alien syntax (this is a carry over from math notation – which they mistakenly believe it’s ok), hailing immutability as something extremely positive, while in real programs that really do something can’t really work without mutable states, and so on.
    They’re often either employed in academia or unemployed, because most companies can’t employ them, because they lack the skills to do real world stuff.

    • I agree that pure functional programming will never get out of a small and possibly shrinking niche. It’s like the idea that “performance won’t matter” some day because computers are getting so much faster. But our ambitions have grown (cf. “Big Data”, mobile). It still does. You can’t always afford a stateless approach. Good programmers need not just to understand functional programming, but also to know when the rules don’t apply and how to break them in a tasteful and maintainable way.

      Then I encountered this…

      Functional languages are nothing but tools made for mathematicians who don’t have the intellectual ability to learn oop languages.

      Oh, hi. I know you.

      What? That’s insane. If anything, the reverse is true. The FactoryFactory nonsense is there for people who can’t handle the mathematics that programming actually is, and have to replace intellectually hard but elegant and universal abstractions with flimsy, pointless, stereotypically “business” bullshit ones.

  15. I love that you stated Java intentionally holds you back when I just jumped onto it with Groovy/Grails; obviously you haven’t seen or heard anything about the new Java revolution taking place allowing non-verbose Java, scripted Java, and convention-over-configuration Java. I built the webhook api for grails and am working on a couple others and previously i was a LAMP dev for years waiting for Java to become more like everything I just described so that I could drop LAMP.

    And with Android taking off and Dalvik bypassing bytecode, I can write in Groovy and run in Dalvik. So tell me HOW is Java holding me back when I am now running as a mobile dev and web dev when before I was just limping?

      • I would agree with that statement. Java the culture is horrible… but it is slowly changing. Dalvik, Quercus, Grails. New and fresh ideas are pouring in and getting Java out of Oracles hands and making it open and new and exciting. I love to tell people that Java is FUN AGAIN and have them look at me in disbelief as I tell them what I can do and then SHOW them on my laptop.

        The ‘old school’ Java culture spits on these ideas though and its up to people like me to branch that gap and reach into PHP and show them that Java is not ‘scary’ and reach into Java and show them that ‘loosely coding’ isnt BAD.

  16. Pingback: The unbearable B-ness of software « Michael O.Church

  17. Pingback: Learning C, reducing fear. « Michael O.Church

  18. Pingback: Gervais / MacLeod 15: What is being rich? | Michael O. Church

  19. Pingback: The Effects of an Information Diet | Paul David Santana

  20. Pingback: Gervais / MacLeod 21: Why Does Work Suck? | Michael O. Church

  21. Pingback: Blub vs. engineer empowerment | Michael O. Church

  22. Pingback: Gervais / MacLeod 23: The shodan programmer | Michael O. Church

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s