Perfection Paralysis

A major problem with many projects is the quest for perfection. We don’t want to release a software application until it looks perfect, there are no bugs, it’s fast, and the user experience is flawless. And that’s a great ideal for any project. Unfortunately, the quest for perfection invariably adds scope-creep. What was originally deemed a good design is now less than perfect and requires tweaks. The performance is just not fast enough yet, so we’ll tune the servers. An executive decided there is a new piece of required functionality that simply must go in. On and on we go, and the app release is pushed back further and further. Projects can go on for a year or more before being released. Certainly we want solid software applications, but what does this quest for perfection bring us? In the end, very little of value. As release dates get pushed back, the customer begins to lose faith in the abilities of the development team to deliver. Increased time-to-market means we miss opportunities to sell our product. Increased release cycle times make us less responsive to user issues we didn’t see. These problems are among the issues solved by agile development. Frequently releasing code means that users can start getting essential functionality quicker, time-to-market is diminished, and teams can react to changing user requirements quickly. But to get there, we have to determine what the minimum viable product is and accept that things may not be perfect. We need to accept that our initial version will not be the best there is, but that it’s good enough to do what we set out to do. Understandably, this may feel uncomfortable to the perfectionist in us – after all, we want to give our absolute best. We want a product that we can be proud of and that the customer is dying to have. But if we wait, with delay after delay, we run the risk of having the best app that will never be used because someone else beat you to it.

Bring Your A-Game

A-Game

Recently, I was contacted by an individual leading a group of young engineers into a state-wide competition. This leader wanted to discuss the project and see if I had any advice. I provided him a simple improvement that would have greatly improved the product that the team was working to produce. Then, a few days later, I heard that he had decided not to take my advice. Instead, he would use my suggestion as an improvement if his team was selected to advance to round two of the competition. This really disappointed me. This leader has taught his team to try just hard enough – not to do your best. And, he made the mistake of assuming that his inferior product would advance to the next round. In today’s highly competitive market, this is the exact opposite of what the next generation needs to see. Instead, we need to install in those underneath us a quest for excellence – not mediocrity. If you can do better, why aren’t you? If you can make the product better, what’s stopping you? Innovation and excellence require pushing yourself every day – you can never settle for anything less. In everything you do, bring your A game. If you don’t, someone else will and you’ll be left on the sideline.

Planning & Execution

January is a month when people plan changes for their life. Some will change their diet, others will start exercising. I have decided to focus on setting and meeting my goals this year.  Having a full-time job in addition to running my own business leaves little time to be wasted – so I really need to be intentional with how I spend my time in order to achieve my goals. In order to learn how to better achieve my goals, I have been reading books and watching videos online. One key point I see over and over in achieving goals is to take action. You can’t talk about what you’re going to do – you need too start doing it! This applies to anything in life – but today I was pondering how it applies to software development. If we want to release a piece of software, we have to start writing software. But here’s the problem – all too often is seems that too little time is spent planning how to write the software. We focus so intently on the end goal of releasing a software application that we ignore coding standards, fail to document code, avoid refactoring, etc. In the end, we meet the goal – but we end up with unmaintainable spaghetti code. So, while we may have met the goal, we end up ensuring that future development will take more time and be littered with potential problems. And, ironically, while we met the original goal, we could have likely released early if we had simply spent more time upfront planning direction of the code, determining good data models, etc. So, while inaction will paralyze any project, improper action will will end up being just as counter-productive.

Bad Teachers

Today, more and more tech realms require a bit of programming knowledge. If you’re a QA, you may be writing test cases in Python or Java. If you’re engaged in Devops, you may be writing scripts or code for automation or other tasks. If you’re a hardware hacker, you may be writing C++ code for an Arduino board or Python for interacting with GPIO pins on a Raspberry Pi. Unfortunately, most of the code written by QAs, devops teams, and hardware hackers is not up to the standards of good software engineering. Indeed, all of the above fields are more software hackers than real engineers in the software realm. What that means, is that when you view tutorials or documentation created by people skilled in areas outside of software engineering, that you’re likely learning poor coding standards. Of course, it’s seems hardly fair to hold QAs to the same standards as you do software engineers. But the problem comes later when the QAs say “I know Java.” Or when the hardware hacker says “I can program in C++.” Now, you end up with bad code entering your codebase because of untrained developers. I want to be clear – my point is not to discourage QAs and devops teams from programming. But rather to encourage developers to assist programmers in these fields to adopt proper coding standards. Treat there code with the same scrutiny you would a developer – subject it to code reviews, and demand proper coding standards. Otherwise, the same problems that plague software projects will end up causing problems in your devops environment or your QA testbed. Don’t assume that a QA can program in Java because they’ve written some test cases. After all, you wouldn’t trust me to replace the engine in your car just because I’ve changed the spark plugs in mine.

What is Refactoring?

To me, refactoring is one of the most important parts of the software development lifecycle. Most developers are familiar with the idea of refactoring, but customers and managers may not be.  So, what is refactoring and what value does it bring to the development process? Refactoring is the process of going through code and redesigning, updating, and fixing with the intent of improving the code. This can encompass a lot of different improvements. For example, a developer may find that certain blocks of code are repeated over and over again. Repeated code can cause all kinds of problems. At the very least it increases the size of the application needlessly, but on the more problematic size, it also decreases maintainability of the application. For example, if a code block is repeated 8 times, and the required logic for that code must change, the code will need to be replaced in 8 different places. Chances are good that developers will only find 7 and you’ll spend months trying to figure out where the problem is. Other common tasks involve redesigning to make the application cleaner, removing unnecessary code, and all sorts of things to generally improve the codebase. Why is this important, and what is the benefit to the organization? Without refactoring, code tends to become messy. Each new developer adds something new, code is duplicated, paradigms change, data models are updated, technologies are improved, etc. As these things happen, the application becomes increasingly difficult for developers to follow. Additionally, bugs increase, the size of the code increase, and things run less than optimally. In the end, refactoring is kind of like getting a tuneup on your car. As a good developer, I am always looking for ways to improve the code so that future developers will have an easier time maintaining the application. It’s incredibly important and should be a priority not only for developers but for management and customers as well.

Why I Write Simple Code

Simplicity

As per Kernighan’s law: “Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.”

Brian Kernighan, the author of the above law, is among the most famous of all computer scientists. He, along with Dennis Ritchie, authored “The C Programming Language”, one of the most well known of all computer programming books. As such, Brian Kernighan’s ideas carry a lot of weight.

Kernighan’s law sounds simple, but it carries a profound truth – that clever code is bad code. When I was a younger programmer, I thought writing clever code was a great idea. I loved writing code that made me appear to be a wizard of coding. Of course, when you write complex code, you realize the first time you try to fix a bug that the code isn’t maintainable. Now, after 20 years of programming, I aim to write simple code – the simpler the better. I want any programmer – today or in a decade – to be able to look at my code and figure it out without any effort. Simple code is maintainable code.

Do you write simple code? Do you hire programmers that write simple code? More importantly, when you hire contractors do they write simple code? Contractors are notorious for writing ‘clever’ code so that you have to keep them onboard long-term to maintain the code they wrote.  For a business, this is a huge – and costly – mistake! Clever code will cost you far more than you think over the lifetime of an application!

 

Code Warnings

As a developer, I often look at someone else’s code. It may be a coworker, an open source project, or a code snippet on Stack Overflow. No matter the source, I often look at the code and wonder why something was done the way it was. That’s ok – that’s just part of being a developer. But some things make you seriously question the original developer’s technical prowess. For example, I was looking at some code today that was annotated to ignore all warnings. That’s a pretty brave move, as it assumes you know better than the computer does where problems may be. Reality is, you don’t. And when you ignore all warnings, you set yourself up for failure. For example, today I saw a piece of code with countless variables that were all context-specific in Android. When I removed the ‘hide warnings’ annotation, I saw countless warnings about how these variables would cause memory leaks. That’s pretty serious for a long running application, and it negatively impacts the user experience. Certainly some, in fact many, warnings can be safely ignored. But ignoring all warnings is a recipe for disaster.

Stored Procedures

Of all the technologies out there today, databases are among the most important. Boring as the idea may be, the storage of data drives the information age. Indeed, databases are as ubiquitious as the webpage itself. Order information from Amazon, posts on Facebook, content from WordPress sites – all stored in databases. Because of this, database management is hugely important – so much so that people work full time jobs in database management.

One of the technologies that databases provide is what’s called a stored procedure. Stored procedures are code that runs on the database to aggregate data, calculate information, perform business logic, etc. Many people love to put all kinds of logic in stored procedures so that they don’t have to rewrite the business login on multiple platforms. And, indeed, they can be useful at times. However, during my career I have grown to despise stored procedures.  Why? While stored procedures give the promise of simplifying logic on your application code, what they also do is increase the complexity of deployment and circumvent source control systems.

Since stored procedures are external to the application code, deploying an app is more complicated than simply placing an application on a user’s computer. Now, you have to first upgrade the database functions and then upgrade the application. No big deal, of course, since applications often require database updates. However, unlike table structure, stored procedures are more likely to change frequently in order to fix or tweak the logic. Thus, you end up with different versions of the stored procedure on different databases. Now, the same application will behave differently when running against a different database. This becomes a support nightmare. Is the issue a software bug, or is it a problem with the stored procedure? This leads directly to the second problem – no source control. Traditional application code is managed by source control systems. Every change is logged, and the history of the project can be observed for the entire lifetime of the project. Stored procedures are code applied directly to the database, and tweaks are often not entered in source control. Thus, you can’t easily revert back to a previous version since you have no record of it. This lack of history means we can’t see what other developers did and you have no idea why something was changed.

In my opinion, stored procedures often become the wild west of software development. For all the value they can bring, what I’ve seen them bring is additional bugs and confusion to the software process. When I work on projects, I will fight against the use of stored procedures unless an incredibly strong argument can be provided for their inclusion.

The Importance of Source Control

While professional programmers always submit their code to a source control system such as git, svn, or tfs; most hobbyists and learners do not. This is a huge mistake. I always encourage people to check their code into a source control system. But why? For the learner or hobbyist, there are a few big reasons to do so. First, as developers we often realize we’ve solved the exact same problem before. But when? Where? How? Having a repository of your own demo code gives you reference material for future projects all neatly stored away. Second, as that repository grows, and you mature as a developer, you may want to pursue a job in software engineering. A growing number of companies ask to see your GitHub account – this is a great way for an organization to see what your code really looks like. Start building that portfolio of code now! Third, source control serves as a backup for your code. When the project you spent months working on is destroyed because of a hard drive error, what do you do? If you have your code on committed to a source control system, you download your most recent copy and move on. Very little is lost. There are countless other benefits to source control, but these are some of the simplest benefits an up-and-coming developer can realize quickly. If you don’t have an account, go to BitBucket.org or GitHub.com and set one up!

Developer Maturity

Today, I was onsite at a customer location. This particular customer has an interest in programming, and showed me a site he was checking out that asked a variety of questions to determine what language he should learn. Do you want to write games, web apps, desktop apps, etc. For nearly every sequence of answers, I could predict what language they would pick. Why? Because I have used countless languages over the years and know where each one excels. Another customer recently asked me to create a very trivial service that would consume JSON messages sent from a server. You could write a Java app for this, but why? My suggestion was either a simple PHP script or a Python app running a REST service with Flask. Either option is far simpler than writing Java code to handle the processing. One of the key indicators of a developer’s maturity is their ability to pick the proper technology for the problem at hand. For the customer, the technologies selected can make a huge difference not only in the price of the software, but in it’s success as well. This extends beyond programming languages. Mature developers understand build systems, revision control systems, project management methods, design patterns, and so much more. For customers, picking an inexperienced developer can mean substantially higher development cost, increased long-term cost of ownership, increased development times, and numerous other problems. An experienced developer can help you navigate the technology map and select the best options in order to provide the best user experience at the best cost.