David Scott Bernstein's Blog, page 19
September 27, 2017
Name Things Well
I’ve said that the five code qualities we’ve been discussing are quantifiable. That is, we can create more of them if we want. Let’s discuss how to do this.
The one code quality I’d like to focus on is cohesion. To me, it makes the most sense and I can easily see when my code is cohesive and when it isn’t. The number one way I do this is to ask myself if I can come up with a good name for it. If I can come up with a good name for something then I’ve scoped it correctly. I’ve defined its place in the world. I’ve said what it does so its intention is clear.
To non-software developers, the act of naming something may seem mundane or even trivial, but to professional software developers we know that the greater part of developing software is all about coming up with really good names. After all, everything gets named in code: data and behavior.
Naming is how we imbue the system with knowledge. It’s how we communicate what we’re doing in our code to other developers. Names should be active and say plainly what the code does. I like using long names for things so I can clearly articulate what it is. In every IDE I’ve worked in in the last ten years, you just have to type the name in once and the next time you need to refer to the name it will autocomplete after a few key strokes. Today, with most compilers, names can be up to 256 characters and I like to use as many as I feel I need to so I can express the intention behind what it represents.
Invariably I find that if I’m having trouble naming something that one or more of the code qualities are missing, especially cohesion, and that tells me to break things down into simpler entities.
I try to include domain terms in the names I use, and I try to exclude software jargon as much as possible. I know it’s a lofty goal that I can’t fully achieve but I like to keep my code as readable as possible to non-developers.
My wife is not a developer. She’s a filmmaker. If she can read through some code I’ve written and get a general sense of what’s going on and what it’s all about then I’m pretty satisfied it’s clear. But if she’s completely confused, I’ll take the time to rewrite the code so it’s more understandable rather than pepper it with comments.
In fact, every time I see a what comment that describes what the code is doing, I find I can usually replace it with a method call and give that method a meaningful name. This is far more valuable than a comment. It makes the code itself expressive.
I have been chastised before for telling programmers to “write uncommented code.” But many lines of comments in code are either a nuisance or are downright misleading, and everyone would be better off if it didn’t exist. If you want to write a lot of comments then do it with your check-ins in version control where it could be more useful to say what you did.
One thing I find that’s interesting as a design pattern developer is that I often end up with rather generic names for things. For example, the polymorphic method in a strategy pattern might be called process and the class name may represent how the strategy is processed. Since I use design patterns a lot, I often end up with generic method names, but I’m fine with that.
I like my methods to create observable behaviors in the system and I like to name my methods to reveal what observable behavior will happen when the method is invoked.
I also like naming things for how I use them. I find I do this a lot when I write automated tests. Doing test first development, I think about how I’m going to call a behavior before I think about how I’m going to implement that behavior. That’s a really important, fundamental approach of good software development because it allows me to define what I want to do before I start focusing on how to do it.
I talked a lot about encapsulation in the past and one of the ways I define encapsulation is by hiding implementation details and only revealing what a service does. This involves more than just defining method parameters and return values. The method’s name is also important. Names imply behavior and we want to imply the right behaviors with as few presuppositions on implementation details as possible. In other words, we want to name things for what they do, not how they do it.
September 20, 2017
Pairing and Collective Code Ownership
I’ve been writing a lot recently on pair programming and mob programming and I’ve been syndicating my posts at Dzone.com, which is a web portal for software developers. I’ve received some scathing comments about pairing and mobbing from people who’ve obviously never tried it. If something doesn’t work for you then by all means abandon it, but don’t talk with authority about something you have no experience actually doing. I have experience introducing hundreds of professional software developers to pair programming and when done well, I can tell you the people who were most skeptical—and there were several—often turned out to be my biggest supporters and the people who go on to organize pairing within their organizations.
There is a damn good reason for that. The reason is that it works—it’s helpful, it’s useful. Once we get over the stigma of actually doing what we do in front of someone else and realize that just like us the other person is fallible but has figured out things, different things than we have figured out, and that we can become a lot better by learning what they do—when we’ve figured these things out, we get excited about pairing.
If you value the code qualities we’ve talked about here, and work together with your team by just doing code reviews, you don’t even have to pair. Just talk to each other. If you just do that, you’ll see the knowledge and skill level of the team start going up rather quickly.
If you don’t pair then at least read each other’s code, and write code in such a way that it blends with the rest of the code in the system so that people reading the code can’t tell who wrote it. That’s what collective code ownership is all about.
The code in your system should embody the standards and practices of your team and that means everyone on the team. What good are standards and practices if not everyone follows them?
If most of the team can work on most of the code it makes for a healthier work environment. Critical team members don’t exist so people can take vacations when they need to. If someone gets sick, it doesn’t stop the whole team from working.
Pairing and collective code ownership are fundamental practices in Extreme Programming and help promote cross functional teams.
September 13, 2017
Collective Code Ownership
Like many artists I used to sign my work. When I wrote a class or a module, I put my initials in a comment that indicated I was the developer who wrote that code. This was a common practice at virtually everywhere I worked from IBM to small shops that developed financial or banking software. This wasn’t just me, every developer I knew did the same.
Today I code anonymously, and not because I don’t want to get caught in a mistake. It’s because I want to promote collective code ownership.
I believe software should be written in such a way that it conforms to standards and practices and you couldn’t tell by looking at it who actually wrote the code. This is what collective code ownership means, and it’s an important concept in software.
I’m a strong believer in best practices for software developers. I spent my life studying them and I’ve found just a few dozen distinctions can make all the difference in terms of writing a system that’s straightforward to construct and maintain versus ending up with a system that’s a mess.
Developing software in silos, where every developer has their own piece of code to build, which then get integrated into the system later, is how most software is built. This is a problem. A lot of things can go wrong. We have had to figure a lot out for ourselves as software developers and we all have our own style of building software. I’m not saying one person’s style is better than another’s but different people’s styles can be incompatible when they go to integrate their code. So, for maximum compatibility, we have to arrive at some common standards and practices for software development.
Writing code is an incredibly rich medium of expression that few programmers actually take advantage of. We should be studying great code like we study great literature. But instead we teach a few programming languages to people, which is equivalent to teaching them a basic vocabulary, and then tell them to go and create great literature. It doesn’t work like that.
Developers don’t learn to write great code in school. In fact, most of the curricula I see, in colleges within the United States at least, are pretty lame. There are a few notable exceptions, but overall Agile, Extreme Programming, design and architecture skills, are not part of undergraduate curricula in software development. So developers have to learn on the job, if they’re lucky enough to work under people who know how to build good software.
But the industry has been growing by leaps and bounds. The number of software developers doubles every five years according to Uncle Bob Martin’s estimates, and if that’s true then the average level of experience in the industry is just two and a half years.
We can learn a lot from each other, and this is one of the main benefits of pair programming, mob programming, doing code reviews, doing retrospectives, and all of these are core practices within Extreme Programming.
September 6, 2017
Forget About Velocity
I wrote about increasing velocity in my last post, but I just can’t let it be. I have to tell you about the dark side of velocity and why I don’t recommend that teams track velocity.
Velocity is the amount of work a team can accomplish in a fixed period of time. It’s used to estimate the number of stories that can be implemented in a very short time horizon, which is usually between one to four weeks.
The way we compute velocity is variable and because of that, it can’t be used for comparisons. Velocity is a form of estimation that exists solely for the purpose of estimating the amount of work a team can accomplish within an iteration. Velocity is optimized for this one purpose and not for measuring productivity or comparing one team to another team, or even comparing the same team to itself just a few months earlier.
The way we like to say it is that velocity is a capacity measurement, not a productivity measurement. Of course you can say that but it might be a lot harder to get people to hear it and this is one of the main reasons I don’t like to use velocity. Invariably people who are somehow removed from the team see the numbers and think of them as some kind of measurement as to how the team is doing.
Far too many times I’ve seen teams sacrifice code quality for velocity when it was the absolute wrong thing to do. Software development is not a race. Don’t let the terms “velocity” and “sprints” confuse you. Software development is a thoughtful engineering discipline and when it’s practiced well, it’s practiced efficiently and effectively. When it’s being micromanaged, it’s operating at suboptimal levels.
I had the honor of working with many of the top software development teams on the planet. I trained over 2,000 software developers and testers at Microsoft and nearly 4,000 software developers at IBM. I have trained software developers for about a third of the Fortune 100 companies as well as hundreds of smaller companies. In my thirty-year career as a professional software developer, I have seen what goes on in the industry and I perhaps have a better view of this than most people.
We do have a legacy code crisis, but that doesn’t mean we have to freak out and panic. It’s just telling us that there’s a lot of room for improvement in our industry and we do have solutions, we have best practices. We simply have to use them together to reap the benefits.
I do teach teams how to measure and track velocity because I offer Scrum Developers Certification, so I have to. It’s one of the requirements that developers understand the basics of the Scrum framework. Of course, I add the usual caveats.
What is important is understanding that the amount of work a team can get done in a fixed period of time is not itself fixed, it’s variable and it depends on a variety of different factors from the difficulty of the tasks to the weather outside.
The very best teams I know do not track velocity. They just don’t find it a useful measurement. They’re mature, they understand their process, and they don’t find that velocity informs them of much. So rather than track data that’s not valuable to them they simply don’t measure it.
For those who do measure velocity, I would suggest that the unit of measure you select represents effort rather than ideal hours.
I used to measure velocity as “ideal hours” where one ideal hour represents about two real hours. But then I noticed that the team was limiting their efforts in terms of hours. So a “four-hour task” would get done in four hours even if it really turned out to be just one hour of effort.
Measuring effort turns out to be more useful.
To measure effort what we do is we take the smallest story, the one we think is easiest to implement, and we call it a “two.” We call it a two because we may come across one that’s even easier. Then we look at the other stories we have to do in this iteration and we rank them relative to the first story so the next category would be a story that would be about twice as difficult as the first story. The category beyond that would be twice as difficult as the previous story, and so on, allowing us to rank at a gross level the relative difficulty of the stories that are going into iterations. Some teams find that helpful.
If you really want to track work, the best teams I see simply count stories. They’ve gotten so good at breaking stories down into their smallest components that each story is small and somewhat uniform. So they simply measure the number of stories they accomplish in an iteration and it gives them an idea of how many stories they’ll accomplish in the next iteration.
Sounds pretty simple, and it is. Let’s not make things harder than they have to be.
August 30, 2017
How to Increase Velocity
Do you want to know a trick to increase your team’s velocity?
Now that I have your attention I want to tell you that tricks don’t work. I’ve seen people play tricks and sacrifice quality in order to get something out only to regret it later.
So here’s my non-trick trick: Increase code quality today to increase your velocity tomorrow.
This might not sound very sexy, and it isn’t. It means you’ve got to put in the hard work now to reap the benefits later, but that’s how it really works. You can’t harvest before you plant. And honestly, most of the code I’ve seen requires some degree of restoration before it can be safely extended.
The iron triangle, or the project management triangle, as it’s called, talks about three factors that are in relationship to each other on any project: scope, time, and resources. So if the scope of the project increases it’ll take more time and/or require more resources. But unlike in the construction of physical things, the relationship between these three factors in software development is not at all obvious.
For example, it’s well-known that if you’re running behind on a software project and you add more programmers it’s likely you’ll run even farther behind. We call this Brooks’s Law because it was first pointed out by Frederick Brooks in his book The Mythical Man Month. I’ll take that on at another time. Here I just want to say that there is a fourth dimension in the iron triangle, but it’s one we don’t talk about or recognize very often. If we’re running behind on a project and we can’t add more time and we can’t cut scope, and we already know from Brooks’s Law that when we add more developers to a project it slows things down, what do we do? If each of the three points on the iron triangle are inflexible then what has to give?
When I ask software developers this question, they immediately know the answer because it’s probably something they’ve had to deal with a lot. If we can’t flex scope, time, or resources on a project then we’re left with the only thing we can flex: the quality of our own work. But as soon as we start skimping on quality, as soon as we start forsaking our professional best practices, I propose it doesn’t help us get more done and, in fact, there are enumerable examples of the harm it does. So I will say that forsaking quality in the way I’ve been defining it, in terms of these five key code qualities, is just about the worst thing you can do on a project.
Now, I completely understand the need to make tradeoffs. I know we’re in business and we have to be practical. So do I cut corners at times? Absolutely, yes. And in my thirty-year career as a software developer I’ve faced the issue of having to choose between writing good quality code or getting something out the door to save my company—and I’ve faced that question more than once, and have always picked the latter answer, thank goodness. What good is beautiful code that no one ever gets to use? So please let me assure you that I am a pragmatist and when I talk about code quality, I’m speaking truly pragmatically. I’m speaking purely in terms of dollars and cents.
In software, quality is always cheaper. That’s the bottom line. It may not be true in goods. Poor quality materials can be cheaper than high quality materials. In service, one could argue that quality is also essential. I see companies waste a lot of money on poor quality service. But quality is definitely always more cost-effective in software.
But again, remember that I’m defining quality in very specific ways, so if you haven’t already, please read my last thirty blog posts or so.
One pattern I see time and time again on software teams is that they adopt Scrum, pay little attention to technical practices, and they’re able to consistently increase their velocity for the first few years. But after about three or four years the technical debt they’ve accumulated in their code is so great that their velocity starts to grind to a halt and they find it difficult to even get simple features implemented. This is a place you do not want to get to, though I see it far too often in the software community—teams stuck there without a clue how to get out.
Software is actually quite forgiving, and that’s a bad thing. It lets us form suboptimal habits. There is no swift retribution for poor code quality. If you make a class poorly cohesive it may not be a big deal, but do it over and over again throughout a system and believe me, it becomes a big deal.
It’s these little practices that make the difference between good code and unmanageable code. So start in the small. It’s easy to understand and it’s something we can implement right now. As we do, as we build code that’s more CLEAN, we’ll find that our team’s velocity, as well as our own, increases in a sustainable way.
August 23, 2017
Testability Affects Code Quality
Why is it that if we all agree that CLEAN code is good to strive for that the vast majority of software as written lacks these qualities? The only answer I can come up with is that we’re so focused on short-term gains that we forget about the long-term consequences. I have to point out that by being a little lazy today we’re making much, much more work for ourselves tomorrow. But there’s more than one kind of lazy.
Writing CLEAN code really doesn’t take that much more effort up front, and on the back end it can save us a lot of time. This is another reason it’s so clear to me that testability is a fundamental virtue in software development. If we value testability then clearly, CLEAN code is the most cost-effective code to write.
Here’s why:
As the responsibilities of a class increases, so does the possibility of those responsibilities interacting in unintended ways. The number of tests we need in order to verify that this doesn’t happen grows exponentially in proportion to the number of responsibilities. For example, if a class has five different responsibilities then we would need 2^n tests (32 tests) to assure that those responsibilities don’t interact with each other in unintended ways. By contrast, if we have five encapsulated classes, each with only one responsibility, then those responsibilities can’t interact with each other in unintended ways and we would only need five tests to cover the code. There is a huge difference between writing five tests and writing 32 tests. So if we value testability then clearly the most cohesive classes are the most testable and therefore testability tells us to value cohesion.
Code that is tightly coupled is impossible to test in isolation. Code that is loosely coupled requires us to mock out dependencies in order to test in isolation. The more coupling an object has, the more mocking we have to do in order to test that object. If we need to use ephemeral external services then we have to mock it out in order to run automated tests against our code that uses the service.
But there are many situations in which people use mocks when they don’t have to. You typically don’t have to mock out your own code. Designing a system with a good layered architecture often gives us the level of testable we need without having to resort to using mocks.
Encapsulated code is more straightforward to test. Assertive code is also easier to test because the results can be observed from the code being tested whereas unassertive code requires the use of spies, objects to interrogate other objects in order to validate that they were called correctly.
Finally, redundancy in code means redundancy in tests. These things can add up quickly and turn into major headaches that make both code and test hard to maintain.
This is what I love about testability. It’s the best teacher. It tells me all the good stuff. I don’t expect you to take me on my word that testability is so valuable. But think about it for a while and I’m sure you’ll see how valuable it is to evaluate designs in terms of testability.
BY ALL MEANS, BE A LAZY PROGRAMMER.
But be this kind of lazy: too lazy to make a mess, too lazy to make poor code that requires a lot of extra effort in testing. If you’re this kind of lazy, you will actually make less work for yourself and your colleagues. The best developers I know are this kind of lazy.
August 16, 2017
Let Testability Guide You
In my last blog post, Let Code Quality Guide You, I said you don’t have to focus on all five CLEAN code qualities and that if you improve one, it’s typical that the others improve as well because they’re all interrelated.
And that’s true, but they’re interrelated at a higher level, which points to a higher quality or a meta-quality they all conform to. This meta-quality is testability.
Testability is not testing. The testability of code is determined by simply asking, ”How would I test this code?” We understand the testability of software without necessarily having to write tests. When software is testable, the five CLEAN code qualities are present. When I’m working with code that’s untestable, invariably I find the reason it’s untestable is that one or more of these code qualities are missing. There is a direct relationship between the five CLEAN code qualities and testability.
Cohesive classes are straightforward to test because they deal with one and only one responsibility. This means we don’t have multiple responsibilities in the same class, so we don’t have to test responsibilities in combination with each other and we can rely on our object model and programming language to protect us.
To me, testability is the one guiding light, the one eternal principle, the one thing I look to that tells me what’s good and virtuous in software. More than anything else, I want the software industry to know that testability of code is paramount and more than anything is what distinguishes good code from bad code.
And you can’t ask the testability question too soon. Even before I code, when I’m thinking about my design, I think about how testable my design is, or how testable the code would be in support of the design, and I find that this one question more than anything else has guided me in the process of discovering better ways of building software. And by the way, that’s what I do. That’s my job, to figure out better ways of building software that’s more cost-effective and efficient and that doesn’t come from a Taylorist approach. It comes from an approach that is decidedly different, one aspect of which is to pay attention to code qualities.
Several posts ago, I said that these code qualities are quantifiable, that we could look at code and measure whether they’re present or not, and this is entirely true. A fellow programmer could look at a piece of code I wrote and we could discuss its cohesiveness or assertiveness or lack of redundancy. This is extremely helpful for developers to do in order to improve their craft. Far too often we build software in isolation and that doesn’t help anyone. I’m as good as I am because of other people, because I stand on the shoulders of giants, as DeMorgan once said. I learn from my colleagues and I’ve had the great opportunity to pair and work with them.
The very best way to write testable software is to write a test first because when you build code by making a failing test pass, all of the code you built is focused around behaviors, the CLEAN code qualities are present, and of course all the code is testable.
But test driven development is much more than just a trick to get developers to write testable code. It’s a discipline that has many, many advantages that I no doubt will write about in the coming months. Stay tuned…
August 9, 2017
Let Code Quality Guide You
Back in the 1990s when I was faced with multiple design choices, I’d have to code them up in multiple ways in order to figure out which one was best. This was time consuming, and evaluating design choices was one of the hardest things for me.
But now I have a better approach, thanks to code qualities. If we agree that CLEAN code is good code, then we simply have to evaluate each design choice in terms of their code qualities and we’ll find the better options. I find that this is a fast way of evaluating design choices and now that I do it all the time, I can make these evaluations almost instantly.
Each code quality represents a key aspect of code. Cohesion means that code is more focused to deal with only one thing at a time, and it makes code much clearer and more straightforward to work with. Loose coupling means the code is more independent and easier to test in smaller units. Encapsulated code can’t be overwritten by something external so it’s more reliable. Assertive code is more performant and better organized. Code that is nonredundant costs less to maintain and extend.
Each code quality represents an important aspect in code that when missing can distort the object model and make code difficult to work with in the future.
These code qualities guide me. They are my teachers in the pursuit of understanding good code and I find that when I pay attention to these code qualities, I end up building code that’s more maintainable, more straightforward to work with, that’s in better alignment with the principles of good programming, and I even discovered design patterns.
Understandability in code is for us humans. Computers don’t care but we should. In order to maintain software, we have to understand it. We have to start by building software in such a way that it’s understandable. Architects don’t go off and just draw whatever they want on a blueprint without paying attention to the standards and practices of their industry. In the software industry, we need to establish good standards and practices that we can follow just like builders and architects follow.
Pay attention to code qualities that will help you more than anything else to stumble upon the right designs and have you use principles, patterns, and practices that support good software development. Let code qualities be your teacher and guide you to build code that continues to provide value into the future.
But don’t stop with code. If CLEAN is fundamental to the way we understand the world, then we should see it reflected everywhere—and we do. Good communication is cohesive. Healthy relationships are loosely coupled. Well-formed ideas are encapsulated. Healthy people are assertive. And unique ideas are nonredundant. These same code qualities are in the arts, in sciences—they’re everywhere because they help us understand the world around us. And because they’re everywhere, because they’re at the foundation of how we humans understand, we can and must imbue our software with these same qualities so that it can be understandable to us.
The good news is you don’t have to focus on all five code qualities. Just pick one or two that make the most sense to you and focus on those. What you’ll find is that as you improve one code quality, all the other code qualities will improve as well. They are not independent of each other. In fact, they are very much interrelated, like facets of the same gem.
August 2, 2017
What I Mean by CLEAN
If you’re reading my blog posts as they come out then you already know about CLEAN, which is my acronym for five code qualities that improve the testability and maintainability of software.
If you’re reading these posts as archives in reverse chronological order, then the acronym is: NAELC. It’s unpronounceable, but it still contains goodness. As you read through my previous posts you’ll find out about these code qualities: nonredundant, assertive, encapsulated, loosely coupled, and cohesive. Of course, there are many more than five but let’s just focus on these five for now.
Regardless of whether you read these blog posts chronologically or in reverse order, these five code qualities are important indicators of the overall quality of code. They’re little things that make a big difference, like the bolts on a bridge.
Bridges are huge, expensive projects and they are held together in part by inexpensive bolts. If we try to build a bridge without paying attention to tightening the bolts then the bridge will collapse. We all know that a chain is only as strong as its weakest link. The same is true with virtual things but strength and resilience and longevity depend on things that are subtle, like these five simple code qualities. I know people who disagree with me and say that users don’t directly see code so what does it matter if it’s “clean”? But users do see these code qualities indirectly and they experience how well a program is able to respond to change and meet a user’s needs. Drivers may not see the bolts on a bridge but they expect them to be there or they’d never drive across it.
When these code qualities are present, software is vastly more understandable, which makes it more straightforward to work with. Software is, after all, an asset and in order for our asset to continue to provide value it has to be at least somewhat flexible. But software that is not CLEAN can be inflexible and difficult to change, which is one of the main reasons it costs so much to change existing software.
To me it’s ironic that we complain about the little extra effort it takes to write CLEAN code, but we seem all too willing to pay exorbitant prices to extend it later on because guess what guys—when we don’t pay attention to code quality, we end up with legacy code.
Legacy code isn’t just the bane of our industry, it’s the bane of all industries because all business depends on software and the way we build software is fundamentally broken. It’s broken because we don’t pay enough attention to implementing CLEAN code. We don’t want to take time to think about the object model or to put some little bit of behavior that we discover is needed into its own class. Why? Is it really so hard to type in those eight characters “class {}”
If we want to build an industry then we have to promote practices that work for everyone. We have to build software that’s more reliable, that’s more efficient, and most of all that’s more extensible. Because it turns out that the vast majority of expense in software is making minor enhancements to already existing systems.
But it doesn’t have to be that way. There are best practices and techniques that we can use to help us build a shared understanding of what we’re doing and how we’re doing it, which, by the way, is not nearly as obvious as constructing a building. Software is invisible in many ways, and being clear on exactly what we’re doing and why we’re doing it has profound implications on how well we do it. That’s why I’ve written this series, to discuss the concept behind these key code qualities.
One thing I’ve noticed about virtually all of the very best practices I’ve seen in software development in my career, as well as everything I’ve learned about good principles and patterns, is that all of them imply CLEAN code. All of the example implementations of design patterns are CLEAN. The SOLID principles are CLEAN. When we do TDD, the code that we produce is CLEAN. And so by studying CLEAN code, we can infer many of the principles, patterns, and best practices used by expert software developers.
In case you want to read my series of posts in CLEAN Code Qualities in chronological order, here’s the first one.
July 26, 2017
Nonredundancy and Testability
Redundancy is always a maintenance issue. If you have to change redundant code, you have to do it in multiple places. If you have to extend redundant code, you have to do it in multiple places. When you have to test redundant code, you have to modify tests in multiple places.
You get the idea.
Have you ever heard of Shalloway’s Law? Al Shalloway is a brilliant thought leader, the CEO of Net Objectives, and a good friend. He was trained as a mathematician at MIT and likes to poke fun at himself so he has what he calls Shalloway’s Law—I actually own a t-shirt that has Shalloway’s Law written on it.
Shalloway’s Law says that “When n things need to change and n is greater than one, Shalloway will find at most n-1 of these things.”
In other words, like the rest of us he’s fallible and when there’s more than one thing that needs to change in a computer system, it’s easy to miss at least one of them.
As a result, he came up with what he calls Shalloway’s Principle, which states: “Avoid situations where Shalloway’s Law applies.”
This is good advice. Build code that’s maintainable by minimizing the impact of what needs to change when business rules change.
This relates to the Open-Closed Principle, which states that software entities, such as classes and methods, should be open for extension but closed for modification. In other words, I want to limit the code in my system that needs to be changed as I extend the system. I want to build systems in such a way that whenever I extend it I’m having a minimum impact on existing code even if that means I have to write a lot more new code to compensate for or accommodate this new requirement.
Developers don’t mind writing new code. They actually like it. It’s what we do. What developers don’t like is changing existing code, especially if someone else wrote it.
First of all, you have to understand it and invariably when someone else writes software they do it differently than the way we would. We then have to sort of get into their minds because there are currently very few standards and practices in our industry. I do hope and pray that it will change soon. But as of now, and in the foreseeable future, we’ll be dealing with a lot of poorly written and difficult to work with legacy code.
I do have faith that we’ll slowly dig ourselves out and start building software that’s more in alignment with those principles because this, I believe, is the guiding light in software development. We developers should focus on finding ways to support the Open-Closed Principle by building software that can be extended rather than changed to accommodate more features. We do this by centralizing business rules, centralizing instantiation by taking common routines and putting them in a shared place so they can be used by multiple callers rather than having each caller have its own implementation.
How much software in production today would you say is redundant?
Even within a single operating system, I propose that if we pay attention to collapsing redundancy we can reduce the executable footprint by at least 50%. That’s my guess. I have no facts to back that up, but I do have lot of anecdotal evidence to suggest that we developers reinvent the wheel over and over but with subtle and sometimes not so subtle differences.
Sometimes I don’t see the redundancy in my code but I find myself writing a redundant test and realize that my code is redundant as well. There are lots of techniques for finding redundancy and eliminating it in code, and I’ve written about this here and in my book Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.
The bottom line is: The less redundancy in a system, the more straightforward and cost-effective testing and maintenance becomes.


