05 Sep 2015. comments
Programmers often introduce themselves as being a “Ruby developer” or a “Java developer”. Or attach themselves to a technology; “I’m a rails developer”. In many of these instances it isn’t just about being a fan of the language or tech; It’s an identity. These developers have defined their identity by the language or technology that they choose. It isn’t always a conscious choice. So we shouldn’t judge these developers. But it is important to be aware that this is happening and reflect.
Identity for many is a way to communicate to the world “this is me”, “this is my worth”, etc. But to specify a language or technology as your identity is selling yourself short. You probably know a great many things beyond the thing you are identifying yourself as.
Perhaps some identify themselves in this way for job hunting purposes, acknowledging that recruiters are a known hurdle in this process and may not share the same views as us about identification. Maybe that’s pragmatic. Maybe we should take a stand and do the right thing anyway. Some might be in a position to do this easier than others.
Maybe some identify themselves by a specific language or technology because they feel it gives them status with the “in” crowd or are concerned that if they don’t that they may be “left out”. But languages and technologies are always changing. And even those languages that stick around may only be relegated to a minor role in your tool-set.
Given the rate of change and invention in software languages and frameworks, maybe we will reach a point where it becomes untenable to continue this practice of pigeonhole identification.
08 Aug 2015. comments
Interviewing is hard for both candidates and interviewers but some of the difficulty can be avoided if we’d just learn from the experience. I recently went through the process again and I want to share some things.
For many people the process of interviewing for a software developer role is stressful. But it can be less stressful if you reframe the situation a bit, and also do some preparation.
When I say to reframe the situation, I’m refering to how it can sometimes feel as though you are on the receiving end of an interrogation/inspection. Interpreted like that the experience is one where you’re primarily concerned with how to sell yourself and your abilities, and whether you measure up. If you feel you don’t then in comes the stress. It’s part confidence, part perspective.
An interview is about determining fit from both the company’s perspective as well as yours. If you interview for a role that isn’t a good match for you from the company’s perspective then it wouldn’t have been a good experience if you had landed it. The same goes for the other way round; You need to determine if the company is somewhere you should work as well and ask enough questions to ensure that it is.
If you think of the interview process as much more of a 2-way street where both you are interviewing with the company and the company is also interviewing with you then you may find the experience far less stressful.
If you don’t prepare for an interview you may not do well. Interviewing is unfortunately typically done in a way that is very unlike your day-to-day at a software development job (This is a real problem and I discuss it later in this post, but there are unfortunate realities today that we have to deal with.) So you need to practice your interviewing ability. It’s analogous to going to the gym after having not gone in a long while; You need to exercise your software development interviewing muscles a bit to get ready.
Some things you can do are:
If you have a software developer friend it can also sometimes help to have them perform a mock interview on you. How you prepare depends a lot on where you plan on interviewing; For example some places use whiteboarding while others have you code on an actual machine. Do some research and prepare.
So let’s switch gears a little bit from talking about the candidate side of things to the interviewer role. I can tell you right now that software development interviewing is all over the board in terms of quality and style. We’re extremely bad at interviewing in this industry. This is well known and yet it seems that for many companies it’s simply been accepted as a cost of doing business. There are however some companies that have learned from the repeated process and have made improvements that seem to be yielding better results.
When people think of software development interviews they naturally think of whiteboards since they’ve been the staple for many decades. From an outsiders perspective this might seem a bit odd since writing code by hand on a whiteboard has very little in common with the day to day software development activities at a job. It’s true that whiteboards are used for hallway discussions, diagrams, etc, but when it comes to code a text editor is used.
In my opinion the highest signal-to-noise ratio for an interview can be achieved by pair programming with the candidate. The benefits are numerous:
A few months ago I was the candidate in such a situation and I can tell you of a 5th and possibly more important benefit of this style of interview and one that’s harder to quantify: I had fun. I think the reason was that I felt like I could more accurately represent myself and my abilities clearly in this mode.
Another option is to give the candidate some really bad code and see what they do with it to clean it up. You can guage whether they break down things into smaller things, standardize the code to a style-guide, make iterative step-by-step improvements guided by tests, etc. There’s a lot to learn about a candidate from this style and it can also be as open-ended as you need or as specific as you need. When doing this or the pair-programming style it’s a good idea to constrain the exercise to a relatively small amount of code; perhaps a class or two or maybe a handful of methods. You can also mix this style with pair-programming for a pair-refactoring of sorts.
What’s the candidate done? It’s pretty common to ask this question in terms of what projects the candidate has worked on at past jobs/university but why not have them show you? If they have a GitHub account you can give them a machine and a projector and have them point you at some code they are proud of and walk you through it. If they don’t have a GitHub you can have them show you a product that they either built or supported and talk about that. The point here is that you can guage whether they are proud of work they’ve done, can explain to another human at the appropriate level of abstraction (not too in-the-weeds and not too high-level), and whether they can get excited about the product/service that they work on. This can be as open ended as it needs to be and you can guide it however you feel is best for what you’re looking for in a candidate.
Interviewers sometimes act like a noble gas. What I mean by that is that some interviewers make the mistake of pelting a candidate with enough questions and discussion to fill the space available. This doesn’t let the candidate guage you as a company very well because they don’t get a chance to ask you things. Let them have some time to ask you about your company. And if they don’t ask you anything that might be a red flag, which is an indicator you need to know about. Good candidates will be very curious about how your team works, how you develop software, etc.
I’ve seen a dramatic shift over the past 5 years which seems to indicate that interviews in this industry are getting better. We still have a long way to go but maybe you can help by taking some of these strategies to your company or your interviews with companies.
20 May 2015. comments
There have been a few things in internet-land recently that have touched on this idea that using simple, well-understood technology is preferable to using unproven new shiny tech; I agree with this viewpoint enthusiastically.
“Standard is better than better.” - John Hyland
There are a lot of reasons to use well-understood tech including:
With well-understood technology the rough edges and bugs have already been worked out which saves you from having to invest time/money running up against those things first. Others have already payed the cost and smoothed the way ahead.
On the other hand if you use the New Shiny then the downsides haven’t been explored, the rough edges will be yours to figure out, and the best practices don’t really exist yet. And if you add too much of this new tech you might start to feel like Bilbo Baggins:
“I feel thin, sort of stretched, like butter scraped over too much bread.” - Bilbo Baggins
New tech is expensive and distracts you from what you really need to be doing, which is solving your business problem instead of solving technology problems that are blocking you from solving your business problem. You need to innovate in the area of your products/services instead of the technology you’re building with. The alternative is to not ship and possibly never get your idea of the ground while you constantly chase the new shiny.
If you feel the same way I do you may be interested in John Hyland’s talk from Cascadia Ruby last year: Be Awesome By Being Boring
More recently, Dan McKinley wrote about this topic: Choose Boring Technology
02 May 2015. comments
If you ask a software developer what their job is many will say something like “I write code”. But is it? It’s very easy to slather more code onto a project when a project manager asks you to make WidgetX do ThingY but its a lot harder to dig in and find out why they want that. And the process of digging can yield some interesting insights that allow you to solve the customer’s problem without adding more code.
When I was a kid it was common game for people to play to continually ask “why” to annoy/exasperate peers/parents/etc.
“Why are we having broccoli?”
“Because it’s healthy”
“Why do we have to be healthy?”
“So we can grow strong and live long”
“Why do we need to grow strong and live long?”
In software development this practice can actually yield very positive outcomes because you may discover that instead of adding a ton of new code, all the customer wanted was a tree swing.
This might go down something like:
“What are you doing?”
“I’m building an authentication system.”
“Why are you building that?”
“Because people need to sign in on the website.”
“Why do they need to sign in?”
“Because we need to know who someone is to save their preferences.”
“Why do we need to save their preferences?”
“Because we want people to filter just the information they want.”
“For what reason?”
“So that customers who only want to see widgets can find them faster.”
In this example you now know that at the very least the problem you are trying to solve is that customers who want widgets need to be able to find them quickly, which gives you a great deal more context than “we need an authentication system”. Armed with this knowledge you might be able to solve the problem in a different way with far less code than blowing out an entire authentication system. And even if you do ultimately discover that you need to build an authentication system, you now know why you’re building it and can tailor the solution towards that goal.
A really great way to both ask these questions and capture the goals is to write tests based on conversations with your customer. In Behavior-Driven Development circles this is known as Given-When-Then syntax.
Given (some context) When (an action is taken) Then (an observable outcome)
Theres even software that will automate these tests (Cucumber) for you by allowing you to connect them up to executable code. It sounds great in theory but in practice I haven’t found it to be as successful as it promises to be.
Code is just a tool to solve problems. By itself code is not useful and every line you write is a line you must maintain going forward. So the act of writing code can actually be a negative cost unless its solving a customer problem and providing value. Good developers are out to reduce code and increase customer satisfaction via frequent communication and questioning.
12 Apr 2015. comments
I believe the Unix Philosophy is one of the most overused yet least understood set of concepts in software development. It is blogged about often, so I won’t be offended if you skip this post.
In his book The Art of Unix Programming, Eric S. Raymond wrote 17 rules to summarize the core of the Unix Philosophy and I’m going to pick each apart and provide my own commentary based on my own experiences in developing software.
This is really all about abstraction and separation of concerns. A part of a system is easier to understand on its own more-so than the entire system. And those parts are easiest to understand and maintain if they have tight cohesion around a single concept. It’s also natural and beneficial for a system appropriately broken down into small parts to have small interfaces. The abstraction should expose as few details as possible so that the consumer can focus instead on the broader system instead of the details for one of its parts.
I would argue this is the most important yet least practiced of all the rules on this page. Too often developers write code that is fancy rather than communicative. This is insidious as well because the pain of writing fancy code is not immediately felt since maintenance comes later. When the system needs to be extended, repaired, or otherwise modified it needs to be completely clear what it does otherwise it becomes a time/money sink. Your most important job as a software developer is to write code that other developers can maintain with ease. Write code for humans, not compilers.
The general idea is that if software can be re-used then it can be re-connected to other software and therefor provide long term dividends beyond the original project. We have to be careful with this one though because it can quickly lead to premature optimization or gold plating.
How a thing is accomplished is something that should be interchangeable. A basic example of this is the strategy pattern where logic can be pluggable. Another example is that the same system might be interactable via a web application, web API, command line interface, etc. This again touches on separation of concerns since you must have modularity before being able to vary a systems parts.
Get it working. Don’t gold plate. Don’t prematurely optimize. Only make performance optimizations when you have proven that a performance problem exists and system needs to be more performant. Don’t generalize until your specific problem has been solved and a more general approach would be useful for multiple parts of the system or other systems. Prove that complexity would be advantageous before sacrificing simplicity. Remember Rule #2 and write code for humans first, compilers second.
Really this is just Rule #5 (and #2) restated. Do the simplest thing that could possibly work. Have measurements that indicate adding code would be beneficial. Remember that every line of code added is a line that must be maintained and calculate that negative against the theoretical positives of adding more code.
This is Rule #2. Make it so that when things go wrong it requires very little inspection to know what happened. Keep inheritance heirarchies shallow so that behaviors can be tracked down easily. Break up large things into smaller things.
When things can be easily understood and composed into larger things the result is a system that can do more things without sacrificing those things that made it composable in the first place. Legos can be made into greater things in part because each piece can be easily composed into large pieces.
Let’s face it, programming is hard. When given a choice of making data complex vs logic complex we should always choose the data because code must be maintained and understood by future developers.
This is sort of like defensive driving for computer programming. Make it obvious what you code does by thinking carefully about your APIs. Ideally consumers of your code should be utterly bored with how expected everything is. Your code should fade into the background and allow consumers to instead focus on their own problems they are trying to solve.
Are status messages or other outputs necessary for a user? Is the information you are giving to a user useful or actionable? If it isn’t then it’s just noise to them and you shouldn’t concern them with it.
Nothing is worse than a system that goes wrong but brushes the problem under the rug for a while. Doing this makes it very difficult to know where the problem is since the root cause may be several levels removed from where the problem happened. Failing noisily makes us aware of the problem. Failing as soon as possibly makes localizing the failure easy.
This is rule #2 and #5 again. Your fancy code might make a system slightly more performant or flexible but at what cost? If it costs future developers too much time to understand it then you have a net negative. Developers always tend to underestimate the maintenance costs of the software they write, or how many future developers will run into their code.
Be lazy. The first time you have to do something by hand might not be too bad but if you have to do it again you should automate it. Twice is evidence that the likelihood of you or someone else having to perform this manual work again is high.
If you spend time making your software whiz-bang awesome, performant, or generalized before you understand a problem and get it working at a basic level then you’re really just wasting time. Doing these things early is dangerous because the shape of the problem or your understanding may change greatly as you explore the problem space and therefor all that extra code you’ve written just adds time and complexity as you evolve the system.
In software change is inevitable and nothing is one-size-fits-all. What solves your problem might not solve mine, and even if it does it may only be appropriate right now. In an industry as young as software we are still trying to figure things out (languages, patterns, practices). Saying you know the best way or tool is shutting off your search for even better ways/tools. This isn’t even really software specific and has wider applicability to life or science of any kind.
Don’t misunderstand this one; it isn’t about premature optimization or overgeneralizing. It’s about leaving doors open and not painting yourself into a corner. You don’t need to go all the way towards making something generalized or reusable; you just need to make it easy to do that down the road.
There are some other variations of these rules I’d like to mention:
These rules mean different things to different people. Comment if you have some of your own thoughts.
2015 Ben Lakey
The words here do not reflect those of my employer.