My biggest passions in software development these days include Agile software development, architectural design, and functional, attractive user interfaces. While my first and favorite love is code, my primary focus these days is more on the processes and team structures that lead to rapidly developed high quality products. While I'm by no means and expert at these yet, I'm a firm believer in Agile and Scrum and avid practitioner of these whenever possible. I believe that continuous integration and thorough automated testing are critical to the success of any large-scale, long-term project. I've even experienced the surprising, counter-intuitive benefits of Pair Programming.
Sadly, most teams I've been a part of have done none of these and it was plainly evident; the overwhelming need for dedicated testers to catch even trivial bugs, the amount of seemingly daily refactoring necessary to compensate for short-sighted, tightly-coupled design, and the surprising lack of communication among team members leading to significant information silos. All of this contributes to the generally slow plod of development that most people seem to think is normal, acceptable, even optimal.
Among the biggest challenges of adopting Agile practices is the mental transition. Established teams are usually resistant to change, refusing to believe their process can be meaningfully improved. There can be figurative kicking and screaming as they are made to adopt processes they foresee no benefit from, but it's worth it. Eventually there will be a moment when their eyes are opened. Perhaps it's a unit test that breaks unexpectedly when a seemingly unrelated piece of code is changed, or perhaps they gain confidence as they watch the burn-down progress towards a completed sprint. Maybe they even finally buy into the value of code reviews when they begin to see the consistency of the code base improve. Despite their resistance at first, once they begin to see the benefits first-hand there's no going back.
I've been fortunate enough to be on teams transformed by adopting these development strategies and I've seen teams who have spent years mastering them. I know the before and the after, and I know which side of that line I want to be on.
22 July 2013
03 July 2013
// Evading Software Entropy
I've been thinking quite a bit recently about how effective software projects are managed. In previous posts I've talked about my thoughts on limiting the code you write to just what you have to write. The more code you have to maintain, the worse off you are, yet every project has to have some code. So how should that code be written and managed? No one sets out to write bad code but actively developed projects seem to head invariably in one direction: toward chaos. How fast your project experiences entropy depends on several factors but the most important factor seems to be how seriously you take staving it off.
In a post on the blog Joel on Software dated all the way back to April of 2000, Joel Spolsky argued against this idea. The article primarily warns of the evils of restarting a project from scratch, calling it "the single worst strategic mistake that any software company can make" and I somewhat agree with that idea, but supporting his argument he states that code does not rust. Instead, in his view, code grows more complex because it's battle-hardened. It's been used, tested, patched up, and every line represents significant investment in fixing buts and making the product work well. So why is old code so ugly? "It’s harder to read code than to write it," he says. This is why older code inspires the urge to start over, he claims, but this is where I disagree.
As software projects grow and evolve, things tend to get messy, and it's not entirely from being battle-hardened as Joel indicates. Many things contribute towards the entropy of source code and bug fixes, I argue, are not one of them. Instead I believe the primary cause of entropy is human fallibility. When a project is first conceived and architected, effort is made to ensure the design is flexible and scalable. Hopefully it can handle whatever new ideas and unanticipated features you can throw at it, yet even before the first line of code is written, your design could contain mistakes you don't see. Then as you begin to implement the design and later when you're building new features upon it, you're at risk of making mistakes every step of the way.
The client wants feature A now, so you compromise your design to implement it quickly. You set out to implement B and overlook an opportunity to refactor something to make B a better fit. A new junior developer joins the team and makes rookie mistakes that no one catches. All these and more work to make your code harder to read, maintain, and extend. Eventually you find yourself so frustrated with the state of your project that all you want to do is start over from scratch. Is this simply because code is harder to read than to write? No, it's because you're human and your code suffers for it.
So should you start over from scratch? No, that's probably a bad idea, but what you can do is learn from your mistakes and embrace processes and techniques to mitigate entropy going forward such as SOLID design principles, unit testing, and Agile software development. I'll explore some of these in future posts as I endeavour to become more familiar and experienced with them in practice.
In a post on the blog Joel on Software dated all the way back to April of 2000, Joel Spolsky argued against this idea. The article primarily warns of the evils of restarting a project from scratch, calling it "the single worst strategic mistake that any software company can make" and I somewhat agree with that idea, but supporting his argument he states that code does not rust. Instead, in his view, code grows more complex because it's battle-hardened. It's been used, tested, patched up, and every line represents significant investment in fixing buts and making the product work well. So why is old code so ugly? "It’s harder to read code than to write it," he says. This is why older code inspires the urge to start over, he claims, but this is where I disagree.
As software projects grow and evolve, things tend to get messy, and it's not entirely from being battle-hardened as Joel indicates. Many things contribute towards the entropy of source code and bug fixes, I argue, are not one of them. Instead I believe the primary cause of entropy is human fallibility. When a project is first conceived and architected, effort is made to ensure the design is flexible and scalable. Hopefully it can handle whatever new ideas and unanticipated features you can throw at it, yet even before the first line of code is written, your design could contain mistakes you don't see. Then as you begin to implement the design and later when you're building new features upon it, you're at risk of making mistakes every step of the way.
The client wants feature A now, so you compromise your design to implement it quickly. You set out to implement B and overlook an opportunity to refactor something to make B a better fit. A new junior developer joins the team and makes rookie mistakes that no one catches. All these and more work to make your code harder to read, maintain, and extend. Eventually you find yourself so frustrated with the state of your project that all you want to do is start over from scratch. Is this simply because code is harder to read than to write? No, it's because you're human and your code suffers for it.
So should you start over from scratch? No, that's probably a bad idea, but what you can do is learn from your mistakes and embrace processes and techniques to mitigate entropy going forward such as SOLID design principles, unit testing, and Agile software development. I'll explore some of these in future posts as I endeavour to become more familiar and experienced with them in practice.
Labels:
Agile,
architecture,
principles,
refactor,
reuse,
simplicity,
SOLID,
unit testing
02 July 2013
// On Rolling Your Own ORM
My last post was scratching a personal itch. I've been plenty guilty in the past of needlessly reinventing the wheel. Sometimes due to honest ignorance of an existing solution. Other times it was a more willful ignorance because I didn't want to do the research or "didn't have the time." That's a terrible excuse, by the way. Still other times in my hubris I thought I could do it better without ever really trying an existing solution. I'd like to think these mistakes are forever behind me and that I've learned to do better. In truth, I'm still growing and learning as a developer and I suspect that process will never end. Still, anyone who learns to recognize a problem of any kind will itch when they see it and I've been itching. A lot. I've come to welcome the itch, though, because despite it's downsides it drives me to learn and grow, even when the itch isn't self-inflicted.
In this case, the problem at hand is how to handle database access and choosing an existing ORM vs rolling your own. This is a very common theme in c#, it would seem, and there are many existing ORMs available. When you buy into the idea that code is a liability and making use of an existing solution is usually the best option, the option of building your own ORM becomes very unpalatable. I could go on, but LosTechies summed it up nicely in their post titled "Don't write your own ORM."
Labels:
architecture,
database,
orm,
principles,
reuse,
simplicity
01 July 2013
// On the Liability of Source Code
"Source Code is a liability, not an asset."
I have heard that said many times over the years but never so clearly stated, in my opinion, as in this blog post by Chris Parsons:
This idea is driven home more and more with every new programming challenge I aim to tackle and with every pre-existing code base I encounter. Simplicity is better than complexity. Every line of code you write becomes a line that you, and every other member of your team, have to read, test, maintain, and extend. Every statement adds complexity and is a potential point of failure.
Leveraging existing code libraries that handle tangential problems for you instead of reinventing the wheel is almost always better. They free you to focus more on the core challenges of your business which is where you want to be. Sure, sometimes the existing code libraries are meaningfully inadequate and the investment to reinvent the wheel is worth while, but those times are extremely rare. If you think you are about to undertake such a project, stop and really consider your options because you are probably wrong. Probably.
I have heard that said many times over the years but never so clearly stated, in my opinion, as in this blog post by Chris Parsons:
"Every line you write means more for someone else to read, digest and understand. Each complex ‘clever’ regular expression represents another few minutes per team member trying to interpret what you wrote and why you wrote it. Every line you add limits your project’s responsiveness to change.
Only the feature that your code provides is an asset. The more that we reduce the amount of code we write, the lighter weight and more agile our software. The easier it is to understand, the less of a intellectual drag it is on the team."
This idea is driven home more and more with every new programming challenge I aim to tackle and with every pre-existing code base I encounter. Simplicity is better than complexity. Every line of code you write becomes a line that you, and every other member of your team, have to read, test, maintain, and extend. Every statement adds complexity and is a potential point of failure.
Leveraging existing code libraries that handle tangential problems for you instead of reinventing the wheel is almost always better. They free you to focus more on the core challenges of your business which is where you want to be. Sure, sometimes the existing code libraries are meaningfully inadequate and the investment to reinvent the wheel is worth while, but those times are extremely rare. If you think you are about to undertake such a project, stop and really consider your options because you are probably wrong. Probably.
Subscribe to:
Posts (Atom)