David Scott Bernstein's Blog, page 24

November 2, 2016

Integrate Frequently

You want to create a build system that’s so easy to use that it’s invisible to the developers on the team. It should be able to be invoked with a single click and should automatically build, test, and validate new code that’s added to the system.


Teams that are first adopting continuous integration sometimes ask me how often their developers should integrate their code and I say: “Tell your developers to integrate at least once a day,” but this is a little bit of a trick.


It often turns out that the last person to integrate that day ends up with a huge burden of failing tests so they wind up not getting home in time for dinner.


Instead developers learn quickly that whenever they have even the slightest bit of functionality to add to the system they do it. Because by integrating code a little piece of a time, you take a very difficult problem and make it so small it’s barely noticeable, and if something does go wrong it’s easy to remedy because you know the problem was introduced between now and the last time you integrated.


The very best developers I know integrate all the time. When I look at their server logs I see them running their tests on average of about three times a minute. This is an enormous amount of feedback they’re getting. Think about how much more successful we can be with that level of feedback coming into us all the time as we’re building a system.


Continuous integration does require that you have the right tests and requires having a testable system, but given these things, continuous integration can become a cost-effective way of building and maintaining a system.


I like my builds to happen in a matter of seconds and usually if a system is well partitioned and architected then the dependencies for the code I’m working on shouldn’t be huge, and the dependent unit tests can run fast.


One key in making this work is to have a well-defined dependency tree for the build. It often reflects the nature of an architecture, so cleaning up and improving the dependency tree also improves architecture.


Continuous integration is a core prerequisite to emergent design. It’s far safer doing emergent design with code under test. So it’s valuable to write automated tests for code whose design is going to evolve.


We want to make it so that clicking the build button is so easy and uneventful we do it all the time.

 •  0 comments  •  flag
Share on Twitter
Published on November 02, 2016 09:48

October 26, 2016

Rearrange the Furniture

The best development teams that I know not only sit together but face each other so they can see each other and hear each other throughout the day. This is in direct contrast to most office spaces where individual team members have their own offices so they can work in quiet without being distracted. This kind of isolation turns out to be a big problem on teams that require high bandwidth communications.


In the old days—a few decades ago—office workers aspired to have their own office so they could work in solitude without being disturbed. This is how it was when I was a contractor at IBM in the 1990s. I shared an office with another developer, who wasn’t on my team. We were put together not so that we could work together but rather because there wasn’t enough offices to go around.


Later that year, our team grew larger and I was moved to a big common room that we contractors called “the bullpen.” Desks were smashed up against each other and there was no privacy. My manager apologized to us about the cramped quarters but I loved it—and my productivity skyrocketed.


When a team sits together and can see and hear each other throughout the day then learning can be amplified and spread across the team. This can be further supported if team members are working in frequently-rotated pairs. This kind of configuration helps to rapidly propagate knowledge across the team and significantly boost productivity.


Earlier in the year I had the pleasure of visiting Menlo Innovations in Ann Arbor, Michigan. They took over the bottom floor of a parking garage and turned it into a giant office space. In one corner, they set up a bunch of card tables where six pairs of developers can work together on six different stories. Being in close proximity, the team stays in sync with each other and can quickly resolve issues and answer questions. At Menlo, everyone sits together, even their CEO, Rich Sheridan. They have a few conference rooms used for client meetings that would otherwise be a distraction to the team but aside from that and rest rooms nearly everything else is common space.


I’m a big believer in pair programming for many reasons that I’ve blogged about in the past. What really impressed me about Menlo’s set up was how easy it was for someone in a pair to look up and ask a question of someone in a different pair. This allowed information to flow not just within a pair but across pairs as well. And when it comes time for swarming or mobbing, the whole team can be gathered in no time at all.


I used to want an office of my own but now I find it far more exciting and interesting to sit with the team.

 •  0 comments  •  flag
Share on Twitter
Published on October 26, 2016 14:59

October 19, 2016

Lifecycle Artifacts

One difference I see between the Waterfall projects I used to work on and the Agile projects I work on now is that my desk is much less cluttered now.


A lot of traditional software development methodologies require additional artifacts: UML diagrams, flowcharts, design specifications, UI layouts, the list goes on and on.


The Agile Manifesto says “working software over comprehensive documentation.”


But many development methodologies require several additional documents in the process of building their software. Individually, these additional artifacts may not seem like much but over the course of a development cycle these additional items can become a burden.


Every artifact has its purpose, but treating all documents with equal importance can be wasteful and unnecessary. A design artifact has its purpose. Design artifacts are valuable during design and implementation. Once a design document serves its purpose and is no longer useful it should no longer be updated.


Ultimately, the goal is to produce valuable software and software is the ultimate expression of complex processes. The asset that we are being paid to build is the software and the only reason we create additional artifacts is to aid the creation or usage of that software. I encourage developers to minimize the amount of artifacts they use and “think with their hands.”


Thinking with your hands means writing code. I used to think it was irresponsible to just jump in and start coding before I had a complete set of requirements but now I find it’s easier to start simple and only build what’s needed now.


Rather than using lengthy requirements documents I prefer a few well selected examples that I can work through with my Product Owner or customer. This usually gives me the right level of feedback to build a feature that’s useful to them.


Twenty-five years ago I subscribed to Brook’s “build a system three times.” I would design on paper then implement in code and then test all the software I created. But this approach wasn’t giving me three opportunities to improve my system. Instead I found I was improving three different sets of constraints on what I was doing. Today I let systems emerge by first writing a test for the behavior I want to create and then making that test fail. Next I implement that behavior so the test succeeds.


I typically do very little design up front. Instead I let implementation details emerge through refactoring so I end up with working code and an automated suite of unit tests. This gives me the platform to sculpt the code into the design I want and I can do it safely because all the code is already under test.


One of the big benefits of ending up with a suite of good unit tests that support code is that it clearly documents how the code is to be used and we always know that those tests are up to date by running them and verifying that they still work. This provides a level of assurance that our tests are in sync with our code. This kind of assurance is not available from any other artifact accept automated tests, which makes those automated tests not just advantageous to have, but in my mind essential.

 •  0 comments  •  flag
Share on Twitter
Published on October 19, 2016 08:40

October 12, 2016

Version Everything!

I’ve come across a few teams in my career who have unstable build and test environments. When they develop a feature and test it on their test servers everything’s fine, but as soon as they move the code into production bugs that didn’t show up before begin to manifest.


I had one client whose system was so sprawling and complex they weren’t able to reproduce production bugs on their test servers. Things got so bad they had to build a second data center.


For this company, releasing to production meant bleeding 1% of their traffic from their active data center to their inactive data center. If everything went well, an hour later they would bleed off another 1% of their traffic. And they kept doing this—as long as things went well—until after several days all of the traffic was moved over to the new data center. Then they’d start the process all over again with a new release on the other data center. This was an extremely painful and costly approach to releasing code in an unstable environment.


I’ve heard similar stories from other developers as well—and these are not amateur efforts but rather multi-million dollar businesses. I even heard a rumor that some of the bugs in Apple’s iOS operating system only show up in production and can’t be reproduced in their test environment.


These issues may be caused by different factors but one thing is for sure, they aren’t caused by the random nature of computers because computers aren’t random. They are entirely deterministic.


If there is a difference between the ways a test server operates and the ways a production server operates with exactly the same kind of inputs then it means that the servers themselves, the way they are configured, are not identical. Systems should be easily replicable and configurable and a system’s configuration depends on a lot more than just the code in the system.


Version everything that the build depends on, and this includes much more than the source code. It includes configuration files and database schemas, stored procedures and build scripts. It may include hundreds of files other than source code. But it’s only when we version all dependencies of the build that we’re able to create a reliable and traceable build.


It’s especially important to version everything the build depends on, including installation and configuration files. Having identical environments for build, test, and production is critical to making this work.


I’ve heard a lot of horror stories about how a system administrator gets a build server to work by updating the configuration but then forgets to check the file back into version control (or doesn’t have a policy to do this) and then the system fails in production because the configuration change never made it to the production server. Don’t let this happen on your team. Version everything!

 •  0 comments  •  flag
Share on Twitter
Published on October 12, 2016 11:41

October 5, 2016

One-Click Builds

We want to make invoking the build as simple as possible. So simple in fact, that it becomes a non-event that’s nearly invisible to us.


The build should be accessible from the desktop or in the IDE. It should require only a single click to invoke.


First, a local build should be invoked, compiling only those modules that have a direct dependencies on the changes that have been made. Once those modules have been recompiled, the corresponding unit tests should be invoked and if all of them pass, the code should be automatically promoted to the build server to be integrated within the system and invoke a larger suite of unit tests. If all of these tests pass, then the system can actually promote it to production, if desired.


All of this can happen automatically, with a single click on the developer’s machine.


Of course, we don’t have to release to production whenever a developer has a successful build but we could if we wanted to. By making the build automatic we’ll run it more frequently and reap the benefits of feedback from our build system more consistently.


There are even tools that run the build for you automatically as you’re typing code, so you don’t even have to bother with that single click to invoke the build.


NCrunch for.net (http://www.ncrunch.net/) and infinitest for Java (http://infinitest.github.io/) are plug-ins that runs in the background waiting for developers to type keystrokes into their IDEs. When they type something in that can be compiled, a build is automatically launched. This means that you can be happily typing along and when you come to the end of the line and type semi-colon, the system automatically builds what you typed and within a few seconds you get feedback on whether it worked or not. This can be immensely valuable and speed up developer’s workflow significantly.


A single click may not seem like a lot of effort but we invoke the build many times a day when we’re writing software. Making it easy to invoke the build can have are reaching implications for improving developer’s productivity. Getting immediate feedback on what’s being built is also immensely helpful. It gives us the opportunity to find bugs as they’re written so we can fix them immediately and with little effort. When a bug gets past the developer and QA finds it days later it can take much more time for the developer to go back, figure out what she was doing, understand the bug and fix it.


We want developer to run the build all the time because every time they run the build there is an opportunity to get feedback. If the build fails then it was probably caused by something done since the last time the build was run, which is usually just a few minutes ago so it’s easy to find. If the build is successful then our confidence rises because we know things are working as they should.

 •  0 comments  •  flag
Share on Twitter
Published on October 05, 2016 09:53

September 28, 2016

More Comments on Code Comments

In my last blog post, Comments on Comments, I was perhaps a bit harsh on the practice of comments in code. What I meant was that excessive what comments, which are comments that explain what the code is doing, are a possible indicator that the developer who wrote them was uncertain that the code could speak for itself.


There are other reasons to write comments in code. Sometimes it’s clear what we’re doing but not always clear why we’re doing it. Why comments, as I call them, say why something is being done in code. This could be because of a federal regulation or it could be expressing how a design comes together at a higher level. These kinds of comments can be breadcrumbs to the people maintaining the code so that they can get a sense of what is actually happening and maybe call out some design features that aren’t entirely obvious. But don’t resort to teaching your reader things they should already know.


Well-encapsulated code is often presented outside of the context in which it lives. This can make it difficult to understand, so visualization tools can be very helpful.


The domain model should be represented in the objects’ relationships to each other in the system. This makes the system understandable to other people. But in a lot of systems I’ve seen there were huge swaths of missing objects in their domain model. Sure they call out the important ones, the ones that are most visible, but many of them are actually made up of many smaller objects that they haven’t called out. Nor have they called out the main collaborator objects that their main objects interact with. This creates a shallow domain model and it forces developers to read every line of code in order to understand a system.


I don’t believe developers should have to read all of my code in order to understand what it does. I believe developers should have to read my method signature and understand what my method does. I don’t like surprises so I keep my APIs clear and to the point. If I’m developing a library or a framework, I will spend extra attention on writing good developer documentation and probably provide a range of good examples through unit tests. Developers can get a good sense of how to use my APIs but I’ll never bore them with lots of superfluous text.

 •  0 comments  •  flag
Share on Twitter
Published on September 28, 2016 09:43

September 21, 2016

Comments on Comments

I have been accused in the past of encouraging developers to write uncommented code and this is true, but not because I don’t care about maintainability. On the contrary, I care about maintainability a great deal and that’s exactly why I encourage developers to think twice before they write a comment in their code.


Commenting code sounds like a good idea but it can encourage poor programming habits. Developers are less inclined to use meaningful names for behaviors or make their code expressive because it’s explained in the comments. But comments are not code and comments and the code they’re describing can easily get out of sync with each other. And efforts to keep them in sync are actually quite expensive, so commenting code can quickly become a liability. We want to be careful not to assume this additional cost unless it’s absolutely necessary.


The software itself is by far the best medium to express what it’s doing. We should strive to write software that’s clear and understandable because software needs to be maintained.


In scriptwriting, it’s often considered a sad device to use a narrator to explain a scene. Exposition is boring and it’s the sign of poor storytelling. The same is true in code. Our primary focus as software developers should be communicating in our code. We want to communicate what our design is while hiding as much as possible as to how that design is implemented. We want our code to be encapsulated with strong contracts so they are straightforward to understand and maintain.


There is an art and a science to this but unfortunately I don’t often see it taught in school. Some of my clients have me train all their developers, including their new hires who are fresh from school. New hires in my classes often laugh when they hear my comments on comments because oftentimes their professors have drilled into them that they should have a comment for every line of code and that you should always explain what you’re doing in a comment.


This is not considered an industry best practice. Maybe these practices work when you’re building a simple software project like the kind you do within a semester in college, but not when you’re building enterprise software. Large projects require discipline and they also require a certain level of knowledge from the people who are writing and maintaining the code.


I expect the people who read my code in the future will understand the basics of software development. I shouldn’t have to explain what my code is doing. If I felt I had to then I should rewrite my code so it’s easier to understand. Of course, there have been times that I had to break this rule due to other considerations such as performance, availability, security… but other considerations aside, I try to avoid comments and I discourage other developers from adding comments that explain what their code does.


However, there is a class of comments that are important to include in code and I’ll discuss those comments in next week’s post.

 •  0 comments  •  flag
Share on Twitter
Published on September 21, 2016 09:36

September 14, 2016

The Heartbeat of a Project

For me, software agility is best summed up in the first principle from the Agile Manifesto, which talks about continuous delivery of valuable software.


Agile software development is supposed to be a flow that doesn’t conform to prescribed phases. Instead, it breaks projects down into features and tasks. We build the features that are most important to the customer first and we build them incrementally so we can show our progress and adapt new ideas.


A continuous integration server runs at all times, waiting for code to be checked in to version control. Just like our heartbeat, it operates in the background and keeps our projects alive.


Once code is checked in, the build server goes to work. It recompiles the projects and runs a whole suite of tests. If all tests pass, then it optionally promotes the release candidate to production.


We may not want to release our software as frequently as we update it, but it almost always makes sense to keep our software in a releasable state. When software is in a releasable state, the risk of a showstopper bug preventing you from building a system goes away. It also means that last minute changes are much easier to accommodate.


Remove all human intervention from building and validating release candidates. When you fully automate the validation of release candidates then you make one of the most expensive parts of software development: integration and testing, completely free. This takes an enormous pressure off the team, makes code more flexible to work with, and brings us into true Agile software development.


Remember to version everything—the build depends on including stored procedures, database schemas, configuration scripts, etc., not just source codes. Using standard configurations and a replicable set-up builds the reliability foundation a build system depends on.


There are a variety of techniques and approaches for speeding up the build, but the first step is to write good unit tests that only test what is needed so they run fast and have a good testable architecture. We can have thousands of unit tests that can run in just a few seconds if they’re well-written.


Of course unit test may not be the only thing required to validate a release candidate but the faster and simpler we can make this process, the more the team will appreciate it.

 •  0 comments  •  flag
Share on Twitter
Published on September 14, 2016 10:52

September 7, 2016

Implementation Independence

“Design to interfaces, not implementations.” This is the advice that the Gang of Four gave us in their book Design Patterns: Elements of Reusable Object Oriented Software. This means to hide implementation details and only present what is to be accomplished by crafting method signatures around testable behaviors. It means using APIs to create clear contracts for services while hiding as much as possible about how those services do their work. Much of the job of a good programmer is to find ways of encapsulating as much as possible while still creating the desired behavior.


I like to think of myself as an enlightened human being. I believe in equality not just for all humans but for all living things. But I don’t share that same attitude in my software. With people, I want to share as much as I can but with my objects I want to hide as much of the world as possible from them. All of my software is on a need to know basis. While that may sound a bit harsh at first, it stops my code from being pinned down by many implementation details and allows me to easily refactor and extend it with little friction.


I don’t want to give you the impression that I am cruel to my objects, nothing is further from the truth. I’m actually quite kind to them. I never overburden them with more than one responsibility, and I always keep them testable, so I’m constantly checking in with them and making sure they still work as expected. This reassures my code, and me, as well as my customers.


Implementation details can sometimes leak into our designs without us even being aware of it.


For example, I follow a practice called encapsulation of construction when I build my objects. I give each object the ability to create itself by adding a public static method that “news” itself up. I usually call this method getInstance(). I once worked with a client who was looking my code and asked me why I create so many Singletons in my code. I told him I try to avoid creating Singletons in my code and he pointed out all the “getInstance()” methods.


Why did he think I was creating Singletons in my code?


It turns out in the Gang of Four’s example of a Singleton in their book, they use the method name getInstance() but that doesn’t mean when you see the name getInstance() you should think of a Singleton. That’s an implementation detail. From the caller’s perspective, they’re simply asking for an instance. It shouldn’t matter whether you get a unique instance or you get access to some global resource through a Singleton. Perhaps a single resource becomes a bottleneck in the system and it needs to be refactored to a doubleton or a tripleton—or even an object pool. Would you ask all of your clients to rename the method they used from getInstance() to something else?


Hiding implementation details makes code more straightforward to test and understand.


The fewer assumptions we make in code, the less implementation details we expose and the more freedom we have to change our code in the future without impacting our callers. This dramatically drops the cost of ownership for the software we write. Given that over 80% of the cost of software happens after the initial release, writing code that is less expensive to maintain and extend is critically important.

 •  0 comments  •  flag
Share on Twitter
Published on September 07, 2016 09:56

August 31, 2016

Programming by Intention

In my blog post The Single Level of Responsibility Principle, I talked about the virtues of separating out perspectives in code so that any entity is only dealing with a single perspective. In this post, I’d like to tell you about the practice I use that helps me separate out perspectives in code without even thinking about it. This practice is called programming by intention.


Programming by intention is not new. I learned about it over thirty years ago. It’s the simple practice of thinking about how you call a service before you think about how you’ll implement it.


Back in the 80s I used a programming language called Smalltalk. The Smalltalk environment I used didn’t have a feature to create a new method. Instead, you made a call to a method in your code and if it wasn’t recognized Smalltalk would ask if you wanted to create it. Because of this feature, I got into the habit of thinking about how I’m going to use a service before thinking about how I’m going to implement a service, which turns out to be a good practice.


In programming by intention, we make our public APIs delegate to other methods so that the API code is clear and readable at the same level of abstraction.


Let public APIs delegate to private methods in order to do their work. Sometimes people ask me how you test private methods and the answer is usually: you don’t. Remember, the tests created by doing TDD are used to build out functionality and give us regression when refactoring. This is not QA activity. When we’re doing development, it’s typically better to write tests around behaviors. They give us more flexibility when refactoring code later.


My favorite technique to help keep code focused on creating testable behaviors is test-driven development. Writing the test first helps us forge an API from the consumer’s perspective, making it more implementation independent.


Both programming by intention and test-first development are excellent practices to help us build software that’s more understandable and straightforward to work with.

 •  0 comments  •  flag
Share on Twitter
Published on August 31, 2016 01:28