The behavior of specific code in a particular environment may be explored using the scientific method through observation of its execution in that environment. The operating system, the installed software packages and libraries, the computer hardware on which it runs, and the set of data on the system create an environment.
This computing environment is always changing – especially because the data on the system is always changing, but also software packages and libraries are installed, updated, and removed; hardware resources are occupied to varying degrees and may go away or be added; et cetera. Systems are interconnected now more than ever before: one could argue that the environment extends throughout the network of communicating systems. Even power fluctuations and the radiation from outer space can change the environment.
A significant challenge to scientific exploration of how high-level-language code runs in an environment would appear to be the inability to replicate the exact environment in order to recreate experiments. One solution is to create a multitude of duplicated, isolated, unchanging and controlled environments dedicated to research purposes. That may be a fruitful approach that is in some use now and will be common in the future.
But even for practical, real-world environments this challenge is mitigated significantly by the fact that most computing environments are far more similar than they are different when it comes to most program behavior, and most software developed to run in a variety of environments behaves similarly across different systems under most conditions.
The challenge is further mitigated by the ubiquity of computing systems, and the willingness of so many people who control these systems to use them to test other people’s software – something that can be seen in the testing results of any popular open source project. Still: some small amount of error or inconsistency should be expected because of environmental inconsistency (perhaps there is a parallel here to error and inconsistency caused by challenges to control, measurement and observation of the natural world in science more generally).
Development Practices and Science
It may be difficult to rebut the assertion that most software developers are not disciplined scientific practitioners. Yet many engage in behaviors related to the scientific method. Much of test-driven development (TDD), for example, proceeds on the basis of creating a system with a set of rules upon which further development can be based – that further development then adds an additional set of rules, ad infinitum, ultimately creating a high-level and sophisticated software application. Each rule is a hypothesis that needs to be proven. The TDD developer starts by writing the test of a hypothesis – which means he or she starts with a hypothesis and the test for it – proceeds to build the system that satisfies the test, and then moves to the next hypothesis.
When a test fails, it is proof that the developer has broken something in the system, and he or she needs to either repair the system to match the hypothesis, or update the (possibly malformed or outdated) hypothesis to match the current system. Each iteration is a new foundation upon which the next foundation will be built. Given the passion of some adherents to TDD, one could even make the case that the near-scientific method through which TDD proceeds tends to yield a certainty in the solidity of that foundation that many TDD developers find so psychologically and professionally rewarding that they become unwilling to complete any significant development project without it.
In addition to TDD and testing generally, any time a developer writes a short script to determine how some code works in isolation, or builds and runs a benchmark to compare the performance of different techniques, or examines the results of a profiler; their work relates – even if imperfectly – to the scientific investigation of the implications of their code through execution in an environment.
The Ability to Make Accurate Predictions
Indeed all effective writing of high-level-language code must be done with an understanding of the implications of the code being written. You can’t develop a complex system using functions and types, for example, if you do not understand what the functions do and what effect they have on values of the given types.
While the behavior of some elements of code may be intuitive, or obvious from language and package specification and documentation, it is a commonplace for software developers, especially those new to the discipline, to be mistaken or confused about how a particular element behaves under various conditions.
It is only through experience that most software developers really come to know what they are doing: through examination of the execution of code in an environment practitioners gain the ability to accurately predict what code will do before executing it – and therefore, the ability to efficiently write accurate code.