The difference is, an elevator is a precisely defined problem and never needs to have its functionality improved and changed.
In fact, you could build the exact elevator almost identically. Software is never like that — it’s dynamic and constantly changing throughout the life cycle of the software.
Ha! As a mechanical engineer, no, nothing in reality is ever precisely defined. Consider that every single part in the elevator has a tolerance: none of the parts are exactly the same in every elevator. Did you account for thermal expansion? What about wear? Fatigue?
> Software is never like that — it’s dynamic and constantly changing throughout the life cycle of the software.
But elevators need to be shipped right the first time and can't make mistakes; with software, it almost never works perfectly no matter how much time passes.
> with software, it almost never works perfectly no matter how much time passes.
There is a person inside me -- whenever this is said -- that wants to shout "No! You can prove correctness of your program!". But this complicates the issue even more, since afaik no elevator's correctness is proven but it just works. Mechanical stuff somehow just magically work without proof whereas it's still debatable if proven software works (did we prove the software that proved it?). I don't know what's the difference. Maybe elevator has a well-defined structure, it goes up and down, opens the door etc, even though implementation can change (as you explained). But maybe software isn't like that. Idk.
Mechanical things allow a surprising amount of modularity, compared to software, and therefore make it easy to get test coverage.
E.g. your cable is rated for 10,000 kg and 6-month inspections, your driveshaft can go 5 million revolutions or 9 months before it needs to be greased...test all those things separately, put them together and you have a stateless system that if it works today will work tomorrow.
> Mechanical stuff somehow just magically work without proof whereas it's still debatable if proven software works (did we prove the software that proved it?).
It might seem like magic, but, of course, there is actually a science to it. Depending on the situation, a part can work if a certain length is 10.000 or if it's 10.001. In software, that is never the case: a value that should be 10 but is actualy 10.001 can stop everything. In engineering, there is a limited amount of leeway at every step of the process, and everything is slightly overengineered by some factor of safety to ensure that this is the case. For example, if an elevator cable is rated to hold 10,000lbs, the elevator will be sold as having a maximum capacity of 8,000lbs. In correct usage, (weight less than 8,000lbs), there is a sufficient factor of safety on the cable so that it won't break even if the cable is cracked, worn, etc.
I mean, we have that kind of thing in software too, when it comes to e.g. memory usage or runtime (in a sense, anywhere we start hitting physical reality, really).
What should we make these buffer sizes? There's not really a right answer, but there are definitely some wrong ones. Make it big enough to handle the expected use cases and pad a bit extra. Works exactly like a tolerance in physical engineering.
Physical systems work perfectly, until they don't. Roofs and bridges collapse sometimes, even though you'd think we would have figured them out by now. Rockets explode because materials behave slightly differently than the engineer expected.
Building things is really hard. I don't think software engineering is in any way special. It's just that the problems we solve with software are often more complicated than the problems we solve in meatspace and failure is much more benign so that QA is not done with as much diligence.
Indeed. Writing software is akin to drawing the design of the elevator, not building an individual copy of the elevator. Each elevator is equivalent to one instance of the software deployed to run in one place. The same design/code is used to build/create multiple instances. So when we write new software to solve a new problem, we are designing something new and unique - not another blueprint for the same elevator.
In fact, you could build the exact elevator almost identically. Software is never like that — it’s dynamic and constantly changing throughout the life cycle of the software.