Tag Archives: srp

How To Hire Great Developers

In a previous set of posts I talked about how the difference between an average developer and a great developer is enormous, how bad developers can effectively cancel-out your good developers, and why you therefor need to hire just the very best.

So how do you tell if someone is good? or bad? What are the core competencies and key indicators of an ‘A’ player developer? And how do you interview for them?

Great Developer Key Indicators

The following is a list I’ve accumulated over time. It’s never complete, and certainly up for discussion, but in my experience is a pretty good set of indicators for whether a developer is an ‘A’ player or not.

Great developers:

  • Can deal with many levels of abstraction simultaneously.
  • Are masters at managing complexity.
  • Know space and time trade-offs of the major data structures.
  • Understands multi-threading, resource locking, and how it’s implemented.
  • Understands that simple is better than complicated, every time.
  • Has used a DVCS (git, mercurial, etc).
  • Are masters at managing expectations.
  • Plays with new technologies and languages and stays aware of upcoming developments.
  • Understands what TDD is and why it’s a valuable practice.
  • Is likely to develop iteratively and incrementally, adding value with each release.
  • Understands how to accomplish loose-coupling and encapsulation, especially in things that are likely to change.
  • Is not a lone-coder who goes dark for long periods of time.
  • Knows how to communicate well, not just with developers, but all levels of management and stakeholders, and can adjust communication vocabulary/style per context.
  • Knows SOLID principles and practices them effectively.
  • Recognizes that code reviews are excellent ways to improve yourself, both as an author or reviewer.
  • Can grasp the bigger picture.
  • Doesn’t just accept work items and marching orders, but also proposes alternatives and improvements.
  • Knows 1 procedural language, 1 object-oriented language, 1 functional language, 1 scripting language, 1 statically typed language, and 1 dynamically typed language. (There is much overlap between these categorizations)
  • Fluent in major design patterns and how/when to implement them.
  • Knows most of these books:  Code Complete, Pragmatic Programmer, Clean Code, Mythical Man Month, Design Patterns by the Gang of Four, Programming Perls, Code: The Hidden Language of Computer Hardware and Software, C by K&R.
  • Keeps up with development blogs/twitter/podcasts.
  • Is highly passionate about software development.

Bad Developer Red Flags

There are some simple things you can do to immediately weed out the really bad developers in an interview scenario.

  • Have them write FizzBuzz; believe it or not most developers do poorly on this, and it’s a great way to identify them early on in the process.
  • Ask them what the last new language or development environment they learned was. If it’s been a long time since they’ve learned a new one, that’s a red flag.
  • Ask them what they think a great developer’s best attributes are. If the answer isn’t in the list above, it’s probably a red flag.
  • Have them explain dependency injection to you, and a simple example. If you get a deer-in-headlights response, it’s a red flag.
  • Ask them to solve problems that involve in-place manipulation of a linked list or string. If they don’t understand pointers or space/time complexities of a problem, that’s a concern. ‘Reverse a linked list’ is a good one to ask.
  • Find out if they have a GitHub/BitBucket/Codeplex/SourceForge.  Look for evidence of development both inside and outside of work.

What NOT To Do

  • Don’t ask questions that are just quick facts. A programmer that knows what port IMAP runs on isn’t going to be a better programmer than one who doesn’t. Knowing little C compiler optimizations doesn’t make you a better programmer.
  • Don’t just ask questions with verbal answers, or open-ended answers. Actually have them write code on the whiteboard. A lot.
  • Don’t use questions that are common enough to where they could be googled before hand or memorized.
  • Don’t just be satisfied that someone answered something correctly. Talk to them about their solution. Ask them to modify it. Ask them to test it. Challenge their thinking.

This is an organic post, and I suspect I’ll add many suggestions from readers.

 

Just Throw More Bodies at the Problem

Fred Brooks authored a book in 1975 called ‘The Mythical Man Month‘. In it, he argued that adding manpower to a late software project makes it later. The core of this belief has been captured in Brooks’s Law:

It takes some time for the people added to a project to become productive. This is known as ‘ramp up’ time. Software projects are complex engineering endeavors, and new workers on the project must first become educated about the work that has preceded them; this education requires diverting resources already working on the project, temporarily diminishing their productivity while the new workers are not yet contributing meaningfully.

Communication overheads increase as the number of people increases. The number of different communication channels increases along with the square of the number of people; doubling the number of people results in four times as many different conversations. Everyone working on the same task needs to keep in sync, so as more people are added they spend more time trying to find out what everyone else is doing.
(Source)

Why do these death marches happen in the first place? These are some common reasons:

  1. Unrealistic expectations or timelines.
  2. Poor communication between developers and stakeholders.
  3. Overly optomistic feature scope.
  4. Lack of understanding about the problem being solved for.
  5. Inappropriate resources for the job.

The effects of this on the developers can lead to burnout, and a higher rate of bugs introduced into the system. Particularly challenging for the developers are when new ones are added to the project, because they’ve got to split their time between standard development and helping newcomers ramp-up.

There are some tactics that can be implemented to mitigate the impacts, but preventing the problem from being introduced in the first place is a management challenge. Some tactics that can be taken:

Iterative Development

Developing features iteratively and hitting smaller milestones works better than trying to hit a deadline far in the distance. The cone of uncertainty grows the farther out the deadline is. Shorter bodies of work are easier to estimate, and demonstrate progress towards a goal. In some places, this model of not necessarily having a hard deadline, and just developing iteratively/continuously can be a hard culture change to make.

Separation of Concerns

Separation of concerns is important to developing maintainable loosely-coupled software, but it’s also a valuable management technique. Having small teams with a focused ownership area can reduce the ramp up time and reduce the overhead involved with many developers. It’s important to remember however that the segmentation should not impeded cross communication between teams. The segmentation is only intended as an abstraction tool to limit the amount of information any one developer needs to hold on to. All developers should feel free to deal with any area of the code base.

Don’t Rely on Hero Programming

Sometimes an organization will find itself with a few developers who carry most of the weight, and become almost a sort of single-point-of-failure. Fostering this behavior will result in a dangerous situation in which you depend on a small number of individuals, as well as cause chafing between them and the ordinary body of developers. It’s not as important to have superstar programmers as it is a large pool of developers who can work together efficiently.

Summary

Even though this has been proven time and time again, death marches are still common in software development. They often involve a ‘home stretch’ of unsustainable work, in which poor management practices lead to the belief that throwing more bodies at the problem will allow the software to be shipped sooner. Obviously, if we assume Brooks Law is valid, this is false.

The Law of Demeter

Let’s talk about OO design.

Have you heard of the Law of Demeter? If you develop software, you should. You may actually be familiar with its concepts without actually knowing that it had a formal name. At it’s core, the Law of Demeter is the explicit capture of the intent of encapsulation. The rules are as follows.

A method FooMethod of a class Foo should only call the methods of these:

  • Foo
  • An object created by FooMethod
  • An object passed as an argument to FooMethod
  • An object reference held as an instance variable of Foo

Uncle Bob summarizes it nicely: “In other words, talk to friends, not to strangers.”

It’s easy to forget this when dealing with complicated designs, or designs that are poorly understood.

Happy coding.

What Makes a Good Software Developer?

I spend a lot of time talking about the craft of software development. So what do I think makes a good software developer?

Do you just go pick up an undergrad degree and you’re done? Of course not. At that point you know mechanical technique, without the deeper understanding of how to make good software.

The truth of the matter is that undergrad degrees are really just the primer. They teach you that to make sounds come out of the cello, you must draw the bow across its strings; But they don’t teach you how to make amazing sounds. In order to create amazing software you have to read about the craft, play with languages, try new patterns, keep up with the industry, and be passionate about writing reusable and highly-maintainable code.

So this is my list of the things that make a really great software developer, in no particular order.

  • Read. Lots. There are certain books that I would almost consider required reading.
  • Read software engineering blogs. Here are some good ones for .NET:
  • Connect with other software developers. The difficult part about software development is communication. You cannot grow as a software developer without interacting with your peers. This can include:
    • Code reviews
    • Pair programming
    • Software engineering discussions with friends
    • Participate in sites like Stackoverflow.com, Programmers, etc
    • Attend a local user group for whatever language or software engineering aspect interests you
    • Attend conferences
  • Be an encapsulation and loose-coupling ninja.
    • Orthogonality is key in creating maintainable, extensible software.
    • Loose coupling must be burned into who you are as a programmer. The only constant in our industry is change.
    • Dependency injection is your friend.
    • Don’t make anything public unless it needs to be.
  • Don’t use exceptions except in exceptional cases.
  • Project estimation is hard. Don’t make a mess just to meet a monolithic schedule. Develop incrementally and iteratively. Don’t accumulate technical debt by kidding yourself that you’ll clean things up later. Measure twice, cut once.
  • Embrace the agile mindset. Do prototypes. Pseudo-code. White board your ideas. Develop a skeleton application and then iterate on it. Have an agile approach/methodology to your software development, so that you can react quickly and painlessly to change.
  • K.I.S.S. Keep it simple stupid. Don’t over-think a problem. Favor the simpler solution over the complex one. Don’t optimize code up front. Readability of code is far more important than micro-optimizations for performance.
  • DRY: Don’t repeat yourself. If you find commonalities or duplication in your code, refactor it into a method/module/whatever. Refactor, refactor refactor.
  • Be explicit. You must write code with the future developer in mind. If the future developer will be confused by your code, refactor it so your intent is obvious. Code should be self-documenting. Code is for how, comments are for why. Program defensively. Name variables and types in an obvious manner. Don’t abbreviate or shorten variable names.
  • Know the greats. Stand on the shoulders of giants. In order to become a great software engineer, you have to know what to shoot for. You can learn an incredible amount by looking into the big names in our industry. These are some names that you should be able talk conversationally about:
    • Edsger Dijkstra
    • Scott Hanselman
    • Donald Knuth
    • Jon Galloway
    • Ward Cunningham
    • Anders Hejlsberg
    • Miguel de Icaza
    • Robert C. Martin
    • Joel Spolsky
    • Jeff Atwood
    • Jon Skeet
    • Scott Guthrie
    • Alan Turing
    • Bjarne Stroustrup
    • Grace Hopper
    • Phil Haack
    • C.A.R. Hoare
    • Bill Joy
    • Alan Kay
    • Tim Berners-Lee
    • George Boole
    • Ada Lovelace
    • Yukihiro Matsumoto
    • Dennis Ritchie
    • Richard Stallman
    • Ken Thompson
    • Linus Torvalds
    • Larry Wall
    • Bill Gates
    • Paul Allen
    • Larry Page
    • Sergey Brin
    • John Carmack
    • Ken Silverman
    • Steve Wozniak
    • Michael Abrash
    • Richard Garriott
    • Erich Gamma
    • Richard Helm
    • Ralph Johnson
    • John Vlissides
    • Tim Sweeney
  • Practice Test Driven Development. Write code with the goal of passing your unit tests; Don’t write tests later, because you’ll probably just write the tests so that they pass, and won’t uncover the bugs, one off errors, etc.
  • Don’t reinvent the wheel. If there is a quality software component or framework that will accomplish what you need, then use it.
  • Use the right tool for the job. This is true for the programming language, the tools, the frameworks, everything.
  • The code exists for solving a problem, not for itself. Recognize what adds value to your problem and what does not. Do not build castles in the clouds. Y.A.G.N.I. (You ain’t gonna need it.) Don’t build something into the system unless it helps solve the problem.
  • Strong-typing is your friend. Any errors you can catch at compile time helps you offload your imperfection as a human being onto the computer. Solve all warnings generated by your compiler, not just the errors. Recognize when dynamic typing is valuable and when it isn’t.
  • Favor convention over configuration. Nobody enjoys XML soup, especially when it’s unnecessary.
  • Understand what the abstractions are doing for you, at a basic level. You don’t need to know all the nitty gritty details, but you at least should know enough so that you understand the benefits and trade-offs of using the abstraction.

There is of course far more that could be said, but I think that’s a pretty good list for starters.