Siv Scripts

Solving Problems Using Code

Fri 22 September 2017

Code Complete

Posted by Aly Sivji in Thoughts   

2017 is the year I became deliberate about my approach to programming. Like most newbie developers, I hacked together spaghetti code around chunks of answers I found on StackOverflow (Praise Be).

I didn't care how I solved the problem, only that it was solved enough to cross off my todo list.

By ignoring recommended software development practices such as coding standards, version control, and testing, I ended up making things harder for myself in the long run.

I worried about introducing bugs everytime I touched the codebase. I couldn't reuse code because my functions and modules were tightly coupled. It was difficult to wrap my brain around the complexities of large projects with many moving parts.

Then I discovered Code Complete. Steve McConnell changed the way I thought about code. He made me realize that the process of doing things the "right way" methodically is a lot more important than simply solving the problem at hand.

If we break down tasks into manageable components, we can build anything we can imagine.

Go read Code Complete. It will change your life the way it changed mine. Doesn't matter if you're a beginner or a seasoned professional, you'll become a better developer just by reading this book.

In this post, I will summarize the themes of Code Complete.


Themes

Reduce Complexity

A primary goal of software design and construction is conquering complexity. The motivation behind many programming practices is to reduce a program’s complexity, and reducing complexity is arguably the most important key to being an effective programmer.

As we increase the number of things we keep track of, we increase our chances of introducing a bug in our program. If our code is readable, we are more likely to find logic errors.

Two ways to reduce complexity:

  • Use helper functions
  • Refactor conditional tests into readable boolean expressions

What's easier to read:

# okay
for employee in all_employees:
    if employee.active == True:
        print(employee)

# better
for employee in all_employees:
    currently_employed = (employee.active == True)

    if currently_employed:
        print(employee)

Process Matters

Observing large processes and small processes means pausing to pay attention to how you create software. It’s time well spent. Saying that “code is what matters; you have to focus on how good the code is, not some abstract process” is shortsighted and ignores mountains of experimental and practical evidence to the contrary. Software development is a creative exercise. If you don’t understand the creative process, you’re not getting the most out of the primary tool you use to create software—your brain. A bad process wastes your brain cycles. A good process leverages them to maximum advantage.

It's about doing things in a way we can best guarantee success. Sure we can create a product that works, but it only works now. What if requirements change? How are we going to handle those changes?

We are dealing with a living, breathing product. We need to leverage processes that help us handle changes as they arise.

One of the reasons I love Code Complete is that it introduced me to the concepts of TDD (Test Driven Development). After years of struggling with regression errors, I finally understood why testing is a large component of proper development methodologies. Tests make our lives easier in the long run.


Reability

You should go to the effort of writing good code, which you can do once, rather than the effort of reading bad code, which you’d have to do again and again.

Code is read by humans far more than it is written. Your interpreter or compiler doesn't care if it's clean or messy so write for your audience, i.e. you in six month's time.

Both of these blocks of code produce the same output, but which one makes more sense?

# bad
for x in my_list:
  print(x[0])

# good
for employee in company_roster:
  print(employee.name)

Program into Your Language, Not in It

Don’t limit your programming thinking only to the concepts that are supported automatically by your language. The best programmers think of what they want to do, and then they assess how to accomplish their objectives with the programming tools at their disposal.

This is a topic I explored when I dug into Context Managers: doing things a certain way in one language doesn't mean that we should follow the same pattern in another language. When I came into Python from C# and JavaScript, I brought all my habits with me. Instead of looking for a Pythonic solution, I looked for the Python syntax to do things the way I've always done them.

Always try to use your language of choice idiomatically.


Conventions for Clarity

The specific way in which ... a question is answered is less important than that it be answered consistently each time. Conventions save programmers the trouble of answering the same questions, making the same arbitrary decisions—again and again.

Programming is hard enough. Use style guides and logical variable names to make it easy for yourself and your team. Doing things in a standard way builds competency. Look for best practices and incorporate them into your process.


Program in Terms of the Problem Domain

Another specific method of dealing with complexity is to work at the highest possible level of abstraction. One way of working at a high level of abstraction is to work in terms of the programming problem rather than the computer science solution.

Keep business logic separate from the underlying implementation. Separate out parts of the project with helper functions, classes, or a REST API.

The This Developer's Life podcast featured an abstraction episode which discussed how we primarily concern ourselves with the layer we are currently working in. We might need to peel a layer or two from the onion when we encounter problems, but that's more on a need to know basis.


Watch for Warning Signs

Warning signs in programming alert you to the possibility of problems, but they’re usually not as blatant as a road sign that says “Watch for falling rocks.”

Code smells. Look out for patterns and symptoms that indicate a deeper problem. I'll dig into this more once I read Uncle Bob's Clean Code.


Iterate, Repeatedly, Again and Again

The more you iterate in each development activity, the better the product of that activity will be.

Iterating to a final product is a great way to build software since we can be sure that early versions of the feature are implemented in a manner that will be used.

This is also a good approach to life. Iterate your processes, optimize your workflow as you figure things out.


Don't be Religious about Software

Dogmatic methodologies and high-quality software development don’t mix. Fill your intellectual toolbox with programming alternatives, and improve your skill at choosing the right tool for the job.

Always use the best tool for the job at hand. This might require us to learn a new language, tool, technique, or framework. That's okay. As programmers, we are meant to solve problems. Sometimes this requires us to piece together a solution from many different components.


Conclusion

The first few chapters of Code Complete totally changed the way I look at software development. I've started to approach programming like a craftsman learning a trade. I am but a simple apprentice learning from the masters who have come before me.

I need to stay humble and realize that I don't know everything, but that I have the ability within me to figure out how to solve problems. Stand on the shoulders of giants. Use design patterns, algorithms, techniques, frameworks, or whatever else makes life easy. Just remember to approach development pragmatically.


References

McConnell, S. (2004) Code Complete: A Practical Handbook of Software Construction, Second Edition. Microsoft Press. [ISBN: 0790145196705]


 
    
 
 

Comments