Foundations of Programming – Part 1 – Introduction

A few years ago I was fortunate enough to turn a corner in my programming career. The opportunity for solid mentoring presented itself, and I took full advantage of it. Within the space of a few months, my programming skills grew exponentially and over the last couple years, I’ve continued to refine my art. Doubtless I still have much to learn, and five years from now I’ll look back on the code I write today and feel embarrassed. I used to be confident in my programming skill, but only once I accepted that I knew very little, and likely always would, did I start to actually understand.

My Foundations of Programming series is a collection of posts which focus on helping enthusiastic programmers help themselves. Throughout the series we’ll look at a number of topics typically discussed in far too much depth to be of much use to anyone except those who already know about them. I’ve always seen two dominate forces in the .NET world, one heavily driven by Microsoft as a natural progression of VB6 and classic ASP (commonly referred to as The MSDN Way) and the other heavily driven by core object oriented practices and influenced by some of the best Java projects/concepts (known as ALT.NET).

In reality, the two aren’t really comparable. The MSDN Way loosely defines a specific way to build a system down to each individual method call (after all, isn’t the API reference documentation the only reason any of us visit MSDN?) Whereas ALT.NET focuses on more abstract topics while providing specific implementation. As Jeremy Miller puts it: the .Net community has put too much focus on learning API and framework details and not enough emphasis on design and coding fundamentals.  For a relevant and concrete example, The MSDN Way heavily favors the use of DataSets and DataTables for all database communication. ALT.NET however, focuses on discussions about persistence design patterns, object-relational impendence mismatch as well as specific implementations such as NHibernate (O/R Mapping), MonoRail (ActiveRecord) as well as DataSets and DataTables. In other words and despite what many people think, ALT.NET isn’t about ALTernatives to The MSDN Way, but rather a belief that developers should know and understand alternative solutions and approaches of which The MSDN Way is part of.

Of course, it’s plain from the above description that going the ALT.NET route requires a far greater commitment as well as a wider base of knowledge. The learning curve is steep and helpful resources are just now starting to emerge (which is the reason I decided to start this series). However, the rewards are worthwhile; for me, my professional success has resulted in greater personal happiness.

Design Goals
Although simplistic, every programming decision I make is largely based on maintainability. Maintainability is the cornerstone of enterprise development. Frequent CodeBetter readers are likely sick of hearing about it, but there’s a good reason we talk about maintainability so often – it’s the key to being a great software developer. I can think of a couple reasons why it’s such an important design factor. First, both studies and first hand experience tell us that systems spend a considerable amount of time (over 50%) in a maintenance state – be it changes, bug fixes or support. Second, the growing adoption of iterative development means that changes and features are continuously made to existing code (and even if you haven’t adopted iterative development such as Agile, your clients are likely still asking you to make all types of changes.) In short, a maintainable solution not only reduces your cost, but also increases the number and quality of features you’ll be able to deliver.

Even if you’re relatively new to programming, there’s a good chance you’ve already started forming opinions about what is and isn’t maintainable from your experience working with others, taking over someone’s application, or even trying to fix something you wrote a couple months ago. One of the most important things you can do is consciously take note when something doesn’t seem quite right and google around for better solutions. For example, those of us who spent years programming in classic-ASP knew that the tight integration between code and HTML wasn’t ideal.

Creating maintainable code isn’t the most trivial thing. As you get started, you’ll need to be extra diligent until things start to become more natural. As you might have suspected, we aren’t the firsts to put some thought into creating maintainable code. To this end, there are some sound ideologies you ought to familiarize yourself with. As we go through them, take time to consider each one in depth, google them for extra background and insight, and, most importantly, try to see how they might apply to a recent project you worked on.

The ultimate tool in making your code maintainable is to keep it as simple as possible. A common belief is that in order to be maintainable, a system needs to be engineered upfront to accommodate any possible change request. I’ve seen systems built on meta-repositories (tables with a Key column and a Value column), or complex XML configurations, that are meant to handle any changes a client might throw at the team. Not only do these systems tend to have serious technical limitation (performance can be orders of magnitude slower), but they almost always fail in what they set out to do (we’ll look at this more when we talk about YAGNI). In my experience, the true path to flexibility is to keep a system as simple as possible, so that you, or another developer, can easily read your code, understand it, and make the necessary change. Why build a configurable rules engine when all you want to do is check that a username is the correct length? In a later part, we’ll see how Test Driven Development can help us achieve a high level of simplicity by making sure we focus on what our client is paying us to do.

You Aren’t Going to Need It is an Extreme Programming belief that you shouldn’t build something now because you think you’re going to need it in the future. Experience tells us that you probably won’t actually need it, or you’ll need something slightly different. You can spend a month building an amazingly flexible system just to have a simple 2 line email from a client make it totally useless. Just the other day I started working on an open-ended reporting engine to learn that I had misunderstood an email and what the client really wanted was a single daily report that ended up taking 15 minutes to build.

Last Responsible Moment
The idea behind Last Responsible Moment is that you defer building something until you absolutely have to. Admittedly, in some cases, the latest responsible moment is very early on in the development phase. This concept is tightly coupled with YAGNI, in that even if you really DO need it, you should still wait to write it until you can’t wait any longer. This gives you, and your client, time to make sure you really DO need it after all, and hopefully reduces the number of changes you’ll have to make while and after development.

Code duplication can cause developers major headaches. They not only make it harder to change code (because you have to find all the places that do the same thing), but also have the potential to introduce serious bugs and make it unnecessarily hard for new developers to jump onboard. By following the Don’t Repeat Yourself (DRY) principal throughout the lifetime of a system (user stories, design, code, unit tests and documentation) you’ll end up with cleaner and more maintainable code. Keep in mind that the concept goes beyond copy-and-paste and aims at eliminating duplicate functionality/behavior in all forms. Object encapsulation and highly cohesive code can help us reduce duplication.

Explicitness and Cohesion
It sounds straightforward, but it’s important to make sure that your code does exactly what it says it’s going to do. This means that functions and variables should be named appropriately and using standardized casing and, when necessary, adequate documentation be provided. A Producer class ought to do exactly what you, other developers in the team and your client think it should. Additionally, your classes and methods should be highly cohesive – that is, they should have a singularity of purpose. If you find yourself writing a Customer class which is starting to manage order data, there’s a good chance you need to create an Order class. Classes responsible for a multitude of distinct components quickly become unmanageable. In the next part, we’ll look at object oriented programming’s capabilities when it comes to creating explicit and cohesive code.

Coupling occurs when two classes depend on each other. When possible, you want to reduce coupling in order to minimize the impact caused by changes, and increase your code’s testability. Reducing or even removing coupling is actually easier than most people think; there are strategies and tools to help you. The trick is to be able to identify undesirable coupling. We’ll cover coupling in detail in a later part.

Unit Tests and Continuous Integration
Unit Testing and Continuous Integration (commonly referred to as CI) are yet another topic we have to defer for a later time. There are two things that are important for you to know beforehand. First, both are paramount in order to achieve our goal of highly maintainable code. Unit tests empower developers with an unbelievable amount of confidence. The amount of refactoring and feature changes you’re able/willing to make when you have safety net of hundreds or thousands of automated tests that validate you haven’t broken anything is unbelievable. Secondly, if you aren’t willing to adopt, or at least try, unit testing, you’re wasting your time reading this. Much of what we’ll cover is squarely aimed at improving the testability of our code.

Although this first part was void of any actual code, we did managed to cover quite a few items. Since I want this to be more hands-on than theoretical, we’ll dive head first into actual code from here on end. Hopefully we’ve already managed to clear up some of the buzz words you’ve been hearing so much about lately. The next couple parts will lay the foundation for the rest of our work by covering OOP and persistence at a high level. Until then, I hope you spend some time researching some of the key words I’ve thrown around. Since your own experience is your best tool, think about your recent and current projects and try to list things that didn’t work out well as well as those that did.


This entry was posted in Foundations. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

15 Responses to Foundations of Programming – Part 1 – Introduction

  1. Rascal2pt0 says:

    Thanks for writing such a great article. Although I’m new to your site I’m finding it very helpfull.

    This really validates a lot of what I’ve been trying to explain to my colleagues for years!

    Don’t over design, don’t over produce. Trying to implement for every possible scenario makes an unmaintainable application that never works right.

  2. Bill Campbell says:

    Great Post!! And I’m off to read the next (isn’t it great to have a Christmas break to catch up on some really good reading?).

    As a developer for some 27 years, I’ve seen lots of changes in the industry as I started with writing assembler punching cards for a microprocessor. As things have changed, so have I and I find myself trying to catch up with this last big move from working with folks from a VB6 procedural background to OO. I’ve found it interesting that most of the MS Webcasts focus on things that do not demonstrate OO ideas but more on the whole RAD concepts. The whole point and click thing. I’m totally intrigued by the whole philosophy and am excited about getting an understanding of where it’s heading. I’ve been an avid follower of Jean-Paul Boodhoo, Jeremy Miller, and most of the folks here at CodeBetter for some time now and find all the articles and webcasts extremely instructive – there’s just so much to learn to get there. Hopefully this series will help me in this endeavor.

    A big THANKS to you and this community for trying to help us get a grip on all this!! Your time and sharing is making this possible and I sure understand how time consuming an activity this is. I just wanted to let you know that I (and I’m sure hundreds if not thousands) of other developers completely appreciate this devotion to to the developer community!!!!

    Warm Regards and Happy Holidays!

  3. Pingback from Development Central (2007-12-19)

  4. kellyb says:

    Great post – glad to see a nice round up of these concepts and ideas so more people in the .NET community can start groking them.

    One thing I would change slightly is your example of “Last Responsible Moment” applied. I would argue that this principal shouldn’t be applied when feature planning with your business owners as your example talks about. I’m not sure this should be a factor there because as we know – sometimes the time to deliver a feature isn’t what you think it will be and should be delayed just because you can. Feature priority and business value should be the drivers there.

    “Last Responsible Moment” as Jeremy Miller talks about frequently, is more of an execution principal…. delaying implementation decisions for as long as possible, until an important alternative is about to expire. It gives you the ability to have the most information behind your decisions as possible.

    Your example of this principal might confuse/distract folks who are new to these ideas and miss the point (which is a very good point).

    Thanks for a great post

  5. KSS says:

    Familiar principles but it is a pleasure to see them organized and presented in a concise way. Thanks for the good post.

  6. karl says:

    a high school math teacher used KISS all time (said the last s stood for student)…Great teacher, but I hated when he said it :) since then I’ve never much cared for KISS

  7. EG says:

    Why did you use “Simplicity” instead of “KISS”? “KISS” parallels DRY and YAGNI.

  8. Dan Martin says:

    Thanks for the great post!

  9. Charles says:

    Great advice. A valiant effort my friend. Looking forward to the rest of the series!

  10. coder says:

    can’t agree more!

  11. Guy says:

    …, awesome read … keep it coming :)

  12. Tobin Harris says:

    Great post, I totally agree with this.

    In fact, I was recently thinking about this. It seems that developing solutions is getting much much easier for me, not because I’m more familiar with tools, but because my mind seems to “instinctively” pick better coding alternatives.

    This makes a *massive* difference to your development speeds. For example, when you continually keep coupling in mind, and minimise the coupling between software artefacts. Or when you learn to lean on the language to reduce duplication. Or when you make the effort to find simpler solutions.

    One thing you didn’t mention is reuse . I’m a *big* fan of investing time to find other peoples work that achieves what I’m trying to do. It’s about leaning on existing, mature bodies of work. I think its a *good thing* when my job becomes more about *glueing* components together, rather than trying to build them from scratch. You can achieve a lot this way IMHO!

    My 2 pennies worth :)

  13. karl says:

    Joe’s a funny guy 😛 This is like attempt 17 at doing this..hopefully this one will stick. I already have the first 3 parts written….and know what the next 4 are going to be…if I get those 7 parts out, I’ll be a happy guy :)

  14. Joe says:

    Hey Karl – you should demonstrate this series via an ongoing book and web site. Maybe call it CodeWiki or something… :)