A few days ago, I wrote about the idea of merging the roles of developer and tester, and touched on some of the ways this could improve software delivery processes. That post considered resistance to the idea on the part of people who self-identify as testers. What about resistance on the part of people who self-identify as developers?
Naresh Jain posted an interesting tweet the other day that is relevant to this topic. It reads as follows:
Software developer means "person who writes code" while the English word developer implies EVERYTHING required to build something.
The well-known testing specialist Michael Bolton, in a response to a comment on his blog, recently wrote:
But when it's not universally practiced, practiced at varying levels of quality, and addressed towards discovering solutions rather than discovering problems, I don't see any reason to relax vigilance.
In context, "it" refers to test-driven development, or more generally, good software development practices that are not widely used at present. By "vigilance" he means vigilance in looking for the kinds of bugs developers really ought to be embarrassed to deliver to testers in the first place, but (strangely) aren't.
Personally, I've been quite astonished at some of the things developers have said to me with respect to testing and code quality in the past few years. In 2008, I spent a day visiting development teams and IT management at a fairly large company, as a sort of extended interview process pursuant to a coaching opportunity. I asked the developers how they ensured their code was sound before handing it off to the testing group. I expected they would say they did a bit of ad hoc manual testing, at least, before proudly showing their code to anyone else. They didn't. They found the question puzzling. They felt that it was the responsibility of the testing group to find bugs in their code. Quite honestly, I did not understand how they could be satisfied with that; how they could look themselves in the bathroom mirror every morning and feel that they were really professionals. I asked them, What do you do, then? Do you just compile the code and throw it over the wall? They found that question puzzling, too. They glanced at one another for moral support, and shrugged. And that is not the only example of this attitude that I've encountered over the years. I can't help but wonder, if a developer doesn't bother to make sure his/her code works, then what function does he/she serve in the organization?
If I were one to theorize on the basis of very little data (and I am, as it happens), I would theorize that this attitude is largely the result of two influences:
- Behavioral conditioning. Developers have produced crap for so many years, and testers have ferretted out trivial programming errors for so many years, that everyone assumes this is the way things must be. We have become so accustomed to the problem that we accept it as normal. We don't even see it as a "problem."
- The lure of the next challenge. Most developers enjoy figuring out a design that solves a problem. Once they've figured out how to solve a problem, following up to tie off all the loose ends just isn't as much fun. They want to move on to the next problem. It takes a certain amount of self-discipline to finish up all the little details of the current problem before moving on. If you have a handy excuse, like "it's the testing group's job to find my bugs for me," then it's easy to succumb to the lure of the next interesting problem.
For the very simplest of applications, it may be feasible to promote code directly from development to production. But what about software that runs in enterprise IT environments that have stringent non-functional requirements? What about embedded software that has to be tested with the hardware before the product can be mass produced? Depending on the domain and context, additional testing may be required in between development and production; testing that the development team may not be set up to perform. This is where testing specialists can add significant value. I think this will remain true even when (or if) my vision of development generalists becomes a reality.
For context, let's assume an enterprise IT organization with certain characteristics. This picture will be familiar to those who work in large IT shops. The organization has a SOA environment that provides an ESB for accessing shared technical assets, back-end legacy applications, and externally-hosted services. The SOA environment provides single sign-on support, most of the -ilities, and supports multiple classes of service with an appropriate charge-back structure for internal departments that use IT resources. Typically, business applications are based on Web technologies, even though they are internal applications. The technical infrastructure comprises different network subdomains with different security profiles. The internal webapps use the familiar MVC-based layered architecture and may be deployed in multiple subdomains on various configurations of real and virtual servers, depending on operational requirements.
For development, business application development teams work in a technical environment that is far different from the production environment. Let's assume the company uses Java and one of the popular Java-based webapp frameworks for these internal business apps. For development and basic testing purposes, people may deploy their code to a single instance of a container such as Jetty or Tomcat. This may be embedded in an IDE, such as Eclipse or JetBrains, or it may run in standalone mode on the developer's workstation and/or on a test server or continuous integration server. Nearly all the development and testing work in this environment uses a monolithic deployment of the application; that is, all architectural layers are deployed together under one instance of the server or container, and there is one instance of each layer.
In the production environment, different layers of the application may be deployed in different subdomains. For instance, the presentation layer may be deployed to the outer DMZ, the business layer to the inner DMZ, and the persistence layer also to the inner DMZ, where it interacts with the ESB and not directly with database systems or other back-end resources that may reside in the core subdomain. Presentation and business layer application components may not run under the same container, and neither may run under the containers used in the development environment. Client-side niceties such as Web 2.0 scripts actually live outside the corporate network perimeter altogether. The presentation layer code is subject to various mechanisms external to the application, such as single sign-on support, reverse proxies, load-balancing switches, or what-have-you. To support changing workloads, operations may redeploy portions of the application to more or fewer virtual server instances. To support availability, recoverability, and performance requirements, operations may move the application from one server cluster to another (and no application can depend on "owning" a server), add or remove hardware resources, and so forth. All the business applications publish events that feed logging, audit trail, chargeback, fraud detection, license management, and business intelligence facilities. None of this is directly testable in the development environment, and yet new or modified applications must not cause problems in the production environment.
That means there is another level of testing to be done in between development and deployment. This is where testing specialists can add the most value.
The purpose of this level of testing is not to "find bugs." The purpose is to gather information about the operational parameters of the software, to be used in capacity planning, workload balancing, hot failover site configuration, quality of service management, and other matters above and beyond the basic functionality of the application. To do this, testers must be given software that works; not software so full of trivial bugs that it won't even run.
Development teams have the professional responsibility to deliver code that meets all functional requirements and as many of the non-functional requirements as are feasible to test in the development environment. Testing teams have the right to expect the applications they receive already work. Otherwise, they cannot perform the level of testing they need to perform for the benefit of the enterprise.
Some developers choose not to "believe in" contemporary software engineering techniques that help us deliver working code with relatively little personal stress. That's fine. Everyone has the right to "believe in" whatever they please. As long as the developers deliver code that meets all functional requirements and as many of the non-functional requirements as possible, they are free to use any methods; even methods that make their own lives harder than necessary, if they insist. The only thing they are not free to do is to continue delivering crap, as in the previous century.
One of the most straightforward ways developers can learn to deliver working code effectively is to learn the skills of testing. Those of us who pursue a generalizing specialist path in our career development have found that there is a sort of mental "switch" to be flipped; we shift ourselves from development mode to testing mode. Thinking as developers, our goal is to ensure our code performs its intended functions and handles "normal" error conditions gracefully. Thinking as testers, our goal is to find the cracks in the wall; find the ways our code can be broken. This is something that requires awareness and practice, but is not such a great mental leap that it actually calls for two different individuals on the team, not to mention all the waste inherent in silos, hand-offs, WIP inventories, and back-flows between the two specialists. More than anything else, though, it requires us to accept our professional responsibility to deliver working code, and stop depending on testers to find our trivial programming errors for us. They have better things to do than that.
