The Physics of Software
physicsofsoftware.com
physicsofsoftware.com
A much much more rigorous proposal was put forward by an American mathematician several years ago regarding the geometry of trajectories of computer programs, which holds considerably more promise than whatever flimflam this author was going on about:
https://rd.springer.com/content/pdf/10.1007%2FBF00046564.pdf
http://ai2-s2-pdfs.s3.amazonaws.com/5454/5a907a43c798c1193be...
His resulting model of software evolution explains many observations we engineers make about "feature creep," "technical debt," balance of effort between development and maintenance, etc.
I think his model also helps point the way to techniques we can use (e.g., DSLs in preference to OOP) to help improve how we build and maintain software.
I of course realize that people are not perfect (along any axis at all), but I think the importance of this work is highlighting:
(1) software must evolve in order to continue being useful (is this the "cultural" part of your comment?), and
(2) that there are some unavoidable limitations of human capability to achieve that (is this the "people being shit" part of your comment?), particularly in dealing with complexity. And that complexity is an increasing function of lines-of-code count.
So, the obvious conclusion to draw (for me, anyways), is we should work to minimize SLOC by various means: DSLs, &/or expressive/powerful languages.
(1) we perform vastly below our potential because we spend so much time working around our own and each other's bugs. People are shit not because they're dumb, but because they stick to the wrong attitude in the face of disastrous results.
I believe Lehman formalizes the dichotomy you imply as bugs in the "model" (you say "specification"), and bugs in the model's implementation. I think the distinction is important in that the model/spec is an evolving/moving target, subject to evolutionary forces. And the number of bugs in the implementation of any given model's snapshot in time is an increasing function of SLOC, and that updating the model can produce more/latent bugs in previously un-buggy code. (Which I take to mean we need minimize lines of code for any given amount of functionality. Less to write, less lines containing bugs, less to modify, etc.)
Regarding (1): I agree that we perform vastly below our potential due to bugs, but also many other factors - though it might be hard to agree on the what those contributory factors are, and their relative contributions.
I’ve been striving to find a set of fundamental laws or first principles for software development for several years now. I don’t think we should confuse a need for first principles with physics itself. I see no benefit to finding parallels between each aspect of physics and contrived relationship with software.
What I humbly believe is necessary is an understanding of the natural fundamental laws that come into play when making software. These would be evidenced by natural observable phenomena. I believe that most of these laws WILL NOT COME FROM COMPUTER SCIENCE. This is because making software is more than computer science.
As a brief introduction to my thesis let’s consider what things come into play when making software and their relationships to each other. Then let’s consider the areas of study which come into play for each relationship.
We have humans, computers, and software. There are fields of study for each relationship.
Humans <-> Software (HCI, semiotics) Humans <-> other Humans (group psychology, language) Humans <-> themselves (positive psychology, et.al.) Software <-> groups of humans (complex adaptive systems, economics, ?) Software <-> computers (computer science, computer engineering) Computers <-> other computers (networks, information theory) Software <-> other Software (complex adaptive systems)
If we look at each of these fields what laws or axioms can we find that come into play when making Software? Can we reason logically from those principles into a better understanding of software development? Perhaps some kind of field theory? That would be nice.
Software also suffers in that it is largely unconstrained by physics. If I want to design a new car I am physically limited in how components can interface with each other.
The same constraints are largely lifted inside a computer. I can write a module that interfaces with 5000 other modules directly (it'd be horrifying to maintain, but it can be made). In order to get a handle on software engineering, we have to introduce artificial constraints into our process. Systems engineering and the other engineering disciplines already have these constraints built-in (what materials are available, how does physics work, what kind of power can we actually send down a wire of certain gauge and metal).
What sorts of constraints do I mean? Well, first is simple the structured and modular code of old. This just makes reasoning about the system much easier. The second is things like layered architectures or designing to interfaces. By having to narrow down my activities and communication at and across boundary layers I force myself to come up with either more reasonable designs or something horrifying. Hopefully I go for the former.
You can also introduce constraints via our languages (this is going to come out of CS). Static type systems introduce a constraint. These force you to negotiate with the type system and be more deliberate in your decisions. A dynamic type system or duck typing lets you get away with a lot of things (for good or ill) that can produce hard to maintain systems and hard to reason about systems. Does this mean we need static typing everywhere? No. But if we don't have it, we need to find other ways to constrain ourselves.
Perhaps it's with conventions. Thou shalt have 100% code coverage in unit testing! If it's not covered, you have to get it covered before it can be integrated into the master branch.
Practices help. TDD introduces a physics to the world of your code. TDD may result in a test that says: It is a violation of the physical universe I'm creating for this module to ever change this value (say you're using shared memory across multiple threads, processes, or objects). Obviously, it can be violated, but your test tells you when this violation occurs so you can address it. Much like a CAD system may help a vehicle designer realize that the door cannot open because it will hit some other object. Sure they can place the door there, but physics will not allow it to behave the way they want it to.
Ultimately, to engineer a system is to design within a set of constraints. We need our software to be constrained in order to start engineering it. There will be no single set of constraints for every activity (see Fred Brooks' No Silver Bullet). But there are activities and techniques we can use, language options, etc. that will help within and across many of our programming domains.
While not as well-thought out and presented, I've been working on a similar project for the past 6-8 years. I called it the "Grand unified theory of software" (after its physical equivalent) [1] and the attempt was to define, describe and quantify code, how its created, and changed.
The best exposition of my thoughts is probably this mindmap:[2], but the TLDR version is:
* Software has size. Sequences of code adds height, modules add width; together giving area
* Software has weight, like page weight or memory weight.
* Forces act on software to change it, and they could be design constraints, organizational will, etc
* Code is data REALIZED, data is code ABSTRACTED
* and so forth
There is also a book (not mine) called the "Grand Unified Theory of Software Engineering"[3] which takes into consideration not just what software is, but the processes and organizations that cause it to be created and explores justifications for statements like "you ship your organization", for example.
We need more such exploration and discussion, IMO. Since software is largely an abstract thing, having models to help thinking about it in ways analogous to concrete things is useful, if not precise.
1: https://github.com/vinodkd/guts
2: Mindmap flash version: http://vinodkd.github.com/guts/mmap/full/guts.html
Mindmap non-flash version (look below diagram for complete text): http://www.vinodkd.org/guts/mmap/basic/guts.html
3: GUTSE: https://books.google.com/books/about/The_grand_unified_theor...
See also some ideas in https://codeburst.io/software-estimation-in-the-fractal-dime... or https://www.quora.com/Engineering-Management/Why-are-softwar... for more thoughts that head in that direction.
However, this has been fraught with problems, because software engineering differs from physical engineering in fundamental ways and many people have realized that applying physical engineering principles to software leads one to commit an fundamental error in paradigm.
At a basic level, software is a procedural epistemology that manipulates ideas that do not necessarily have to correspond to physical objects. It doesn't mean that physical principles cannot be applied to a subset of the software development process.
However, there are usually better ways to achieve ends in software if one is not constrained by paradigms adopted from the physical world. Even paradigms that are natives to the virtual world (like mathematics -> category theory, functional programming) have not gained the kind of widespread acceptance that one would think they ought to.
This is why I often argue software development is applied semiotics.
On a quick skim there was no solid empirical principle, only a couple of wishy washy equations thrown in to support some wishy washy principles.
Or
It is often easier to add code than refactor code.
Refactoring is a way to fight against the entropy of software code growth. But it is a deliberate activity and rarely happens by happenstance. Outside of languages like Forth where factoring is a way of life, and disciplined environments like what I read about in Smalltalk shops, entropy is the order of the day.
I'm not sure how much sense that makes but anyway I look forward to reading more
In my opinion, this is pretty like Test Driven Development, which has lots in common with the practice of physics (aka Popper's falsification).
TDD has almost nothing in common with physics. Engineering is about repeatable process. Science is about repeatable results. Testing, CI, and all the rest are part of a process of repeatably shipping releases of software that are functional. That's all a distraction for science (though some engineering may be necessary to construct the apparatus you want).
TDD is about people, not software.
But QM is at least 99% about information, maybe 100%. How information is organised - how it can evolve. And QM is code + data rolled into one. It's also made of pure functions; actually reversible ones.
It would be good to understand entanglement from a programming perspective; the article does try to shoe-horn it into his system, but it seems like a very shallow understanding of the physical situation.
Physics is based on measurable values and measurable effects.
You've misinterpreted the author's message and didn't realize he actually agrees with you.
He wrote, "However, a property in physics [...] precise stimulus [...]" to contrast that "coupling" and "cohesion" is not measurable using our current mental models for discussing software.
His 2nd paragraph explains the the flaw in his 1st paragraph just like your 2nd paragraph did to your 1st paragraph.
I feel like he's straining too hard to make the analogy with physics, which doesn't seem very beneficial. Spoken as a fan of both physics and software, the analogy with physics just doesn't seem to offer much additional perspective on the target field (software).
Civil engineering seems like a better analogy (constructed artifacts involving engineering tradeoffs that must work in a complex environment), or biology (evolving systems responding to selection effects in complex, evolving environments).
There is no scientific value in it, so it shouldn't be presented as a scientific theory (or even as a draft version of one), and especially not as “applied physics to software”.