Defining Principles for Software Engineering
Several months ago I wrote about my personal principles of software engineering. That post was informed by a talk a watched by Peter Campbell. Since then, I have been reflecting how to align various ideas I have been addressing independently up to this point. To help bring these various ideas together I want to start at what I think is the most fundamental and address how to define the principles that drive software engineering efforts.
What are Principles?
A principle is the most fundamental source or basis for something. Principles are the roots of ideas and practices. They are the most basic elements that give shape, structure, and direction.
Religions, governments, fields of study, businesses, and even software systems have their form guided by certain principles. When principles are recognized, accepted, and reinforced a degree of sustainability and stability tends to emerge. When principles go unspoken, neglected, and thus degrade instability and uncertainty emerge until failure, disintegration, or reorganization around new principles occurs.
Characteristics of Principles
One of the key characteristics of principles is that they inform other beliefs or practices. This gets to the notion of being foundational, or basic. Without a given principle it is difficult to sustain other ideas or activities. An example of this building-block tendency that I will draw from my background as a student of Biblical Studies and Christian History is a basic principle that undergirds the Protestant Reformation idea of sola scriptura: the clarity of Scripture.
The principle of Scripture’s clarity is derived from certain other beliefs and certain readings of the Bible; but without it, the belief in Scripture as the final and sole authority for all matters of Christian faith and practice would be unsustainable. The principle of Scripture’s clarity is the affirmation that the meaning of a biblical text can be clear to the ordinary reader. The implications of this principle gave rise to the efforts that continue today to make the Bible available in every language, the democratization of church life, and much more.
In addition to promoting derivation of other ideas and actions, another characteristic of principles is that they tend to be exclusionary in some fashion. A principle tends to include certain ideas or actions as acceptable, and others as unacceptable. This is best revealed in the way principles of logic work, such as the principle of non-contradiction which holds that a thing cannot be both the same and different from another thing at the same time and in the same sense. So, the principle of noncontradiction excludes the possibility that its opposite can be the case if it is accepted. And, this logical principle informs work down to the present in such seemingly disparate fields as physics and theology.
Principles both promote the derivation of other ideas and actions; and they tend to exclude other ideas and actions as well.
In fields other than software engineering there are other characteristics that principles within that field may possess. But, for the purpose of exploring the idea of principles in software engineering, these two characteristics suffice.
Principles in Software Engineering
In software engineering, there are some specific implications of these two characteristics that bear addressing. Some principles within the field of software engineering can be contrary to each other.
As an example, both brevity and clarity may be reasonable principles to adopt for the production of a software system. But, these two principles exclude the other.
Only when external domain knowledge is available is the more brief code on top equally clear in comparison to the example on the bottom. Code that is brief also tends to require more knowledge of alternative language features, such as the parallel assignment behavior of line three in the top example. Whereas, clear code allows for the expression of what the algorithm is doing, and thus communicates more to the individual coming along later.
In addition to some principles being contrary to each other, in software engineering, some principles can overlap in many respects but be contrary to only a subset of their implications. An example of this, which is very semantic and may seem pedantic, is the distinction between evolvability and changeability.
Both evolvability and changeability involve the notion that a system should be able to change, but that is all changeability necessarily entails. And, so to assert that a changeable system should be able to change in any particular way is not encapsulated within the principle. Evolvability, on the other hand, implies that changes ought to improve suitability for a particular purpose and that those changes ought to be incremental. For this reason, it would be odd to seek to embrace both evolvability and changeability since the former necessitates purpose and practice, while the latter emphasizes mere ability to change. The only thing that undermines this kind of distinction, which can be incredibly subtle, is the matter of presupposed principles.
Some principles can seem so fundamental that they don’t need to be stated explicitly. Such principles can include ideas of suitability and operability. If suitability is presupposed to be a necessary principle then the distinction between changeability and evolvability noted above nearly evaporates. But, there is a cliche about what happens when you assume that bears remembering. So, I don’t believe we should presuppose principles in relation to software engineering.
I think it is a mistake (especially in a team context) to leave principles, no matter how seemingly basic and fundamental, as assumptions.
Another facet of principles with relation to software engineering is the notion of context. Sometimes certain principles are difficult or impossible to sustain in a given context. This relates to the notion of situational ethics, which insists on judging a decision based on the context in which it occurred rather than exclusively on the basis of some objective standard.
Going back to my background in Biblical studies, there is an example of the importance of context that is embedded in the Ten Commandments. The King James Version of the Bible renders the sixth commandment this way.
Thou shalt not kill.
In contrast, the New International Version of the Bible renders the same text this way:
You shall not murder.
Murder and killing are not the same, the latter involves the bringing about of death in any context while the former assumes the context of killing a person who did not otherwise deserve to die. Some principles in software engineering exhibit a similar need for context to make the principle appropriately actionable.
One example of such a contextually bound principle is that of performance. Without context, what level of performance is reasonable and acceptable? Without additional context building software with the principle of caring about performance is not actionable. So, it is important to not merely state the principles one’s self or a team believes are important but to also supply any necessary context to make the principles actionable.
Individual and Collective Principles
The final detail of principles I believe is essential is to distinguish between individual and collective principles. When these two are aligned conflict can be better managed and the process of decision-making becomes clearer. But, perfect alignment is not a necessity, so long as differing principles can be helpfully prioritized and do not come into strong, direct, conflict. However, sometimes a mismatch between personal and team principles reveals a mismatch that is best resolved by changes in staff, as uncomfortable as that might be.
Developing Personal Principles
Thinking through our own software engineering principles is at its most basic about what kind of code we like to work with. Personal aesthetics and preferences weigh heavily in this exercise. I recommend thinking about a project you have worked on that was pleasant to modify or add on to. Those two tasks comprise what many software engineers spend a majority of their time doing. Because of that, it is important to think about what principles you believe will have the greatest impact on those tasks.
I intentionally use the term believe, because developing principles in relation to software engineering has a lot to do with what we think is best. I prefer code that is clear with regards to its intentions, which leads me to choose names for classes, methods, and variables that I feel convey lots of detail. I also enjoy working with code that is well-tested, so I emphasize making my own code easy to test. These are the kinds of factors that should be considered when thinking about your personal principles of software engineering.
I suggest starting with no more than two or three such principles. If you can’t recall any projects that prompt you to think positively about them, then you’ll have to start from something more abstract. This is a much more daunting task because you do not have the benefit of practical examples. One good resource for developing principles from nothing is the list of system quality attributes available on Wikipedia.
Developing Team Principles
Software engineering is not often a single-player activity. Large projects often necessitate an entire team of talented individuals, who likely each have their own ideas about what is best. Investing the time to identify the principles that are most meaningful to the teams you work on can pay extraordinary dividends. Teams that are able to, for example, agree on what such principles as testability, modularity, or deployability mean for their shared context will be less likely to invest effort in activities that are not seen as beneficial by the whole.
Again, I recommend identifying no more than three principles at the beginning. This will keep initial discussions shorter and less intense. Agreeing on the highest priority principles up front should also provide an opportunity to consider the broader priorities of the business or organizational context of the team. Hopefully, this discussion can be had on projects that already exist, or their components, which are pleasant to work on. Even in large, monolithic, projects that a difficult to work in; there are typically areas that exhibit qualities that will be preferable to the team as a whole.
The Value of Principles
Working on software from a set of principles helps guide decision-making by reducing the broad range of choices we are confronted with. Some principles also encourage us to take into account things beyond the purely technical and thus produce code that is more accessible to the others we work with. And, sometimes the principles we embrace are just about meeting our own aesthetic sensibilities. Whatever reasoning exists for the principles we embrace and act on, it is important to hold on to them loosely since the discipline of software engineering is not ruled by immutable rules beyond the need for reconsideration from time to time.
If you want to explore these ideas more I recommend starting with Peter Campbell’s presentation from the O’Reilly 2016 Software Architecture Conference in London: Architecture As Belief. And, to get convenient access to this content, and much more to help you stay up to date with the latest technology consider subscribing to Safari Books Online.