Tuesday, December 31, 2013

A happy, healthy and professional 2014

Woe to the software developer who entrusts his career to his employer. Martin, Robert C. (2011-05-13). The Clean Coder: A Code of Conduct for Professional Programmers (Robert C. Martin Series) (Kindle Location 603). Pearson Education. Kindle Edition.

Uncle Bob cuts through any inkling of entitlement you may feel, and calls it out. If you decide you want to be a professional: spend time on yourself; practice and perform, and know the difference; learn; collaborate; mentor; work toward the best solutions for your employers problem.

At raise.com, we often talk about raising our game. Others might say we "bring it", day in and day out. In the engineering realm, I'd like to think we try to uphold Uncle Bob's view of professionalism.

My wishes for the New Year include greetings of happiness and good health. Both of those complement the idea of professionalism. By balancing our lives, working for both personal and team success, we can achieve both happiness and good health without skimping on either.

Happy New Year!

Monday, December 31, 2012

13 Habits to Becoming an Excellent Software Developer in 2013

We are what we repeatedly do. Excellence, then, is not an act, but a habit. Aristotle

Excellence is a habit something that we repeatedly do. You can make excellence part of your daily routine as well, particularly if you develop and maintain software for a living.

I'm continually surprised by how many "experienced" developers are actually not excellent developers. However, it does not have to be that way. By paying attention to a few small details, consistently and repeatedly, even the most inexperienced developer can execute and deliver flawlessly.

With the upcoming New Year, I've put together my thoughts on thirteen (13) practices that can quickly turn anyone into a great developer. These practices apply to most development environments, languages and configurations. I make few assumptions about the tools you are using to develop software. I do assume the following:

  • You are using source control.
  • You have a fully-functioning local environment.
  • You have a production-like test environment.

Test everything

I should probably rename this to "run everything". I mean running your code, and looking at your application to make sure there are no obvious errors. Your program compiles cleanly. There are no spelling mistakes, no typos, nothing obvious. Run through the primary path, that most of your users will encounter, as well as any alternate paths, error paths and the the like. Try to run through all branches in your code to make sure they work.

In addition to your application code and visible screens, also run any scripts, jobs and utility tasks that are part of your system. If you're scheduling an offline task, run it manually to make sure it works before scheduling it.

Even if you're using automated tests, take a look at your application as a user would, and make sure that there are no obvious errors.

Look at your outputs

When your running any part of your application, there is a lot of output generated that can provide you with valuable information about how your application is running.

When running your application, follow the logs and look at what is happening. Are the outputs the ones you expect? Is there anything extra there? Is anything missing?

When running any scripts, is the output what you expect? Did the script error out or end cleanly? Did the script produce the results and changes you were expecting?

If you have automated tests, did they finish cleanly? Did every test run as expected? Did the tests run fast enough?

Review diffs before committing

Look over each file that's changed and each line that's changed before making a commit, even if it's a local commit. Know exactly what changes you are making to the code base at any point. Too many times, I've run into the case where files were "accidentally" committed to the code base. These types of unexpected changes can be stopped with this one simple practice.

If you're working in very small increments on thin slices of functionality, the number of changes will be small and the review will be quick.

Review the functionality with someone

When you're done working on your feature, change or fix, bring someone over and show them what you've done. Talk them through what the system does, and show them how the different scenarios work. Even better, let them use the system and point out any issues or errors.

Don't get frustrated when the reviewers start asking for changes. No matter how well your team defined the feature, they don't have perfect vision into the future. By seeing the feature in action, your team now has more information about how to make it work even better. Change is an integral part of software development. Latch on to it and run with it, as a way to create some truly amazing products.

Review the implementation with someone

After you've got the feature working, and your implementation is complete, review what you've done with other developers. This could be done real-time while pairing, or after the fact with a code review or a pull-request.

Be open minded about what others have to say. Leverage any feedback as collective experience to produce the best code possible. Use this as a chance to learn new techniques, and to hear about new libraries. Remember that they're commenting on your code and the implementation, and not on you as a developer.

Work in small increments, stay stable and commit often

It is much easier to work on a small function or a small screen, than a complex business process or a series of screens. Break your functionality down into small functions, and build them out incrementally. Evolve your system to the desired fully functional system that everyone dreams of.

In addition to focus, you'll also get the motivation that comes from a rapid succession of wins as each function is created. You'll also be able to get to stability quickly, and change direction quickly.

When a teammate wants to see what you're working on, you should never be more than a few minutes from showing them. Your code changes should be small enough to thrown away and recreate as needed.

Once your small changes work, commit them to your repository. This allows you to experiment, while having a safe place to come back to. This also allows you to change gears as needed. By being incremental and focused, your system is always in some working state that can evolve towards full functionality.

Keep separate features on separate branches

For each feature or function that you are building, create a separate branch in your code repository. Don't mix features together. Let your features evolve independently. You never know what kind of feedback you may get, and which features will need more or less work after others have seen them.

Give each feature the option to be deployed independently, by allowing each branch to be deployed independently. Once you have two features on a single branch, you've coupled them.

Write (well) to your future self

Pay attention to the words you choose, whether it's variables, methods, classes, modules, comments or commit messages. In the moment when you're developing a feature, everything seems obvious, like you'll remember everything. But remember two things: your teammates don't have the immediate context that you do now, and you will not have that immediate context some short time into the future.

Editors look for ambiguous pronouns when they review writing, to make sure that everything is clear to the reader. Take that same level of care, and make everything as clear as you can.

Test everything again

Your engagement with a feature and the related code only starts when you commit to the repository. From there, follow your code through to a test environment, ideally an environment that is similar to production. Review your feature, show it off, get feedback, check that it works and that it performs.

Don't stop there, though. Once you're feature is deployed, do the same in your production environment. At that point, take a deep breath, smile, and really call your feature DONE.

Defend everything you do

Justify everything. Every line of code you write. Every line you don't write. Everything you add, and everything you delete. Every name you choose, and every name you avoid. Everything you decide to work on first, and everything you decide to put off for later. Every choice you make, and every option you weigh.

The answer can be as simple as "I saw an example on stackoverflow", or as nuanced as "I applied XXX pattern and referenced in YYY book, trading off ZZZ for WWW". Reply at your appropriate level, but know why you've done what you've done.

You're answer doesn't need to be right, but it does need to reflect the best you knew at the time.

Write things down

Development work gets complex pretty quickly. Don't add to the complexity by forgetting what you need to do. Whether you're discussing a new feature, or having a code review, or discussing what needs to be done that day.

Keep your list nearby. Even better, keep it public. Let everyone see what you're working on. You and a teammate might recognize some duplicate effort, or a way to streamline some of the work.

Communicate with your team

Become a radiator of information. What are you working on? What problems are you having? What solutions have you found? What could be done better? When are you integrating and deploying your changes?

Don't limit this to technical tasks, either. When are you taking time off? Are you coming in late tomorrow? Are you leaving early on Friday? Let your teammates know, early and often.

Don't be afraid of information overload, at least not in this case. The more information everyone has, the better the whole team can act and react.

You are not alone

Ask for help. That's what your pair, your team, your company and your community are for.

Happy New Year! Have a great 2013! Become an excellent developer!

Friday, July 22, 2011

From Months to Minutes

I found another presentation on InfoQ, this time by Dan North. In it, he puts many Agile practices through the wringer, and turns them inside out and on their head. Dan questions why we do them, what they do for us, and offers pointers on how to intelligently apply them to become a high performing team.

It's a great and very fast-paced discussion, and it got me thinking a lot about what I do and what I recommend to my teams.

My favorite parts, which are also the most important steps to effectively delivering software, is about the need for one team. In his case, he talks of developers working side by side with traders. He talks about how the developers know as much about trading as the traders do, having learned this by spending time talking with the traders while they work making trades. There is no difference between the business and the engineers. It's one team, consisting of both engineers and traders.

He also talks about minimizing boundaries and hand-offs, particularly within the team. The team does not have members who are analysts, QA's, DBA's, etc. Those roles exist, and are filled by the team members as needed. Particularly, the developers are the ones talking to the traders about features. There is no handoff from customer to analyst to designer to developer. The developers talk directly with the traders, and then implement the features. There is no loss of fidelity; the message does not have a chance to be misunderstood. This is helped by the fact that the traders and developers work together.

Thursday, July 21, 2011

Craft and Software Engineering

Glenn Vanderburg has a great presentation available on InfoQ titled Craft and Software Engineering. In it, he describes where Software Engineering came from, some of the fallacies, and a direction to make it more like other Engineering disciplines. It's a great talk and moves quite well through the content. I'd recommend it to anyone involved in software development.

One of the things he talks about is feedback, and how the different XP provide feedback at different levels of granularity, and at different timescales. He also discusses this in his 2005 paper XP Annealed. Here's what this looks like in a table:

XP Practice Feedback Timeframe
short releases solutions months
planning game priorities weeks
acceptance testing features
collective ownership architecture days
on-site customer
continuous integration design hours
system metaphor classes and interfaces minutes
unit testing statements and methods seconds
pair programming

In his paper, he goes on to describe how the nested levels of feedback are effective and efficient because the practices support each other, and cover for each other. Each practice, at each level of granularity and timeframe, covers and is covered by nearby practices.

Observation: The feedback can be broadly classified as technical at the lower levels, and business at the higher levels. Taken broadly, there are only two types of roles needed to implement the project. Technical (developers) to work out the design and testing, and business (non-technical) to provide the vision, the priorities and acceptance criteria.

Taking it one step further, putting these people together, as one collocated team, would be the most effective way to facilitate this communication. Nothing original here, but it seems to be a natural progression. It minimizes the number of hops that need to happen for any communication.

That's not to say there is no room for specialists, for things such as the environment, deployment, acceptance testing, UI design, and so on. However, they should all be part of the same collocated team.