To be fair to the Wrights, they did design and build a wind tunnel to test their ideas. Early design is almost always like that. The first pyramids tended to fall down, the ones we know were Rev. 2.
Sure; I didn’t mean to impugne the Wrights other than to highlight that how they developed the original flying vehicles then, at the dawn of the modern techological age and without any prior art or engineering processes to leverage upon would not meet the criteria of doing good engineering today, any more than hacking out code without a structure of requirements and interfaces would be considered acceptable software engineering practice. Testing is an important part of the engineering process (and failing in development testing gives more insight than success) but while anyone can iteratively build and break a product indefinitely until they get something workable it is the function of an engineer, whatever the discipline, to understand what the product is intended to do, come up with requirements that can be flowed down and applied to individual components, and then build and test conceptually and analytically workable prototypes efficiently to go from concept to economically manufacturable design within a defined schedule and budget.
Note that there is nothing wrong with hacking code any more than there is going into the workshop and playing with electronics or building a mechanism without a specific requirement; we often learn best by unstructured experimentation, i.e. playing, and sometimes discover things that we would not have found by following a more defined process. But if you want to take an idea from concept to market in a foreseeable timeline, or build a really complex system with multidisciplinary functions that is beyond the scope of a single person or small team to develop, test, and build, applying system engineering processes is crucial to success and product reliability, regardless of the field.
Stranger
I can tell you from experience that hacking code starting from an understanding of what good practice is is very different from hacking code starting from ignorance. One of the questions on my oral - during the height of the hate go-to mania - was an example where a go-to (today a loop exit) was absolutely necessary to make the code decent. I used to teach PDP-11 assembler and writing assembly language code from a good base of structured programming is even more vital.
So following development processes is vital - and doing so allows you to violate them when necessary.
I have no idea where people are getting the idea that there is a magic subset of software that is so important that it is automatically flawless.
No it isn’t.
These programs have numerous errors. Some of them quite ridiculous. (Mars probes seem especially prone to software errors.)
If there’s a problem with a probe, chances are it’s a software problem, not an engineering problem.
(What is going on with the Dope lately about claims that things being “refuted” that aren’t remotely refuted at all???)
Space probes have the problem that they are one off and that the software can only be tested with some sort of simulator, not in true use conditions. The software that goes into your appliances is probably a revision of earlier software and has been tested in true use conditions. And is of course simpler.
Don’t think hardware, done by “real” engineers is perfect either. Every processor comes with a list of known bugs. The famous Intel FDIV bug (hardware, not software) was on the list, but no one thought it was very important.
Hardware verification and software verification are somewhat similar, and both suffer from the problem of lack of good metrics and fault models. Manufacturing test is much easier since nature is less creative than man at introducing bugs.
If most bugs are software, it is because there are a lot more lines of code than lines of Verilog in your typical system.
And that’s just microprocessors, which generally don’t have the liberty of covering up hardware bugs with a driver. CPUs have a public interface that has to be close to perfect, and yet they still have huge errata lists.
Any other ASIC in your system–GPU, audio, network, etc.–will likely have a much longer list of hardware bugs. But they aren’t noticeable because they get worked around in the driver.
A good fraction of “software bugs” are really just incomplete workarounds for hardware bugs.
Interesting discussion so far. I’ll just add the following to the above:
I’ve always thought that structured design was far more important than structured programming, which kind of makes the point about what software engineering is.
It’s true that back in the days when assembly language was prevalent code structure was somewhat more important, simply because sequences of machine instructions small enough to be manageable didn’t do much, so programs were huge and sprawling and how they were structured mattered. But with high level languages being used for everything including system programming, it’s really structured design that matters – who cares if you use GO-TOs! By which I mean a sound logical abstraction of a large software system’s major functions, isolating their interactions only to well-defined standard interfaces, and potentially cascading that philosophy through successive layers of decomposition until you end up with small, manageable pieces of code that are easy to write, unit test, and debug.
And that’s probably a pretty good paradigm for describing software engineering. The programmers code the module functions and their interfaces and unit test them. One would like them to adhere to good coding practices but in the large scheme of things if some of them don’t, within reason it doesn’t matter that much – as long as their component works and is robust. The software engineer is responsible for defining the module functions and their relationships and ensuring the reliable operation of the system as a whole, as well as quality assurance, standards compliance, documentation, usability, and integration and system testing. And it matters a hell of a lot that he does his job well – the centerpiece of the job, IMHO, being the system design.
It is ironic that you single out the Mars Climate Orbiter as an example specifically because the root cause of the failure to identify the units mismatch was a reduction in systems engineering and mission assurance efforts (intended to catch exactly this kind of system interface problem) in line with Dan Goldin’s “Faster-Better-Cheaper” (FBC) approach to planetary missions. The failure of the Mars Climate Orbiter and its sister Surveyor mission the Mars Polar Lander marked the end of the FBC appoach, and shortly thereafter Dan Goldin’s tenure as NASA director. Goldin’s only lasting legacy was eliminating the NASA “worm” logo. The International Federation of Professional and Technical Engineers release a 2003 report strongly criticizing the FBC model in general and specifically its impact on NASA culture and the subsequent failure to address several long-standing problems that led to the destruction of Columbia and problems with the ISS.
This is not to say that software can’t have errors; in fact, it is such a complex system that critical errors are inevitable. The point is that applying good system requirements analysis and requirements-based regression testing, i.e. software engineering practice, that such errors can be reduced in design and caught in testing. When you have a random intern writing your flight interface without any explicit requirement to check against, however, ‘stupid’ errors are practically inevitable.
Stranger
Thank you so much for this vid. I’ve already mailed it to three people.
Absolutely the correct response to OP.
And to Casy Jones.
Dijkstra’s polemic was reasonable for its time, but like so many things, was overused, used outside of its useful range, and nowadays both a whipping boy and internet mneme.
Some would argue that there is no difference between structured design and structured programming. The idea that structured programming means you only exit a block at the bottom isn’t really the point. It isn’t as if compilers don’t emit goto instructions either.
What was more important was making a point about spaghetti code, and really any code structure that you could not reason about in a sensible manner. If you can’t guarantee code coverage in testing you already have a problem. If someone new to the code can’t maintain it, it becomes worse. These hint at the genesis of true software engineering.
I got into trouble once in my introductory lecture to a software engineering class. Indulging my sense of humour (such as it is) I told the class that for the last few years we had been teaching them how to write code, and letting them think that writing code was the really important bit. The next slide simply said “We Lied”. Lesson for the future, in a multi-cultural class, not everyone takes kindly to being told they have been lied to. But the point was not lost on them. The code itself is a tiny part of what it takes to get even a relatively unimportant system (unimportant as in failures are not mission critical) going to the point where you could unleash them into production. The rule of thumb is 9 times the effort.
There are serious meta-issues in software engineering. Many are perceived as management questions, but they really should not. You get schools of software engineering. Some are IMHO little more than fads, but there is s serious intent. How you engineer a software production team to deliver software that meets the requirements, and does so into the future. You get meta-analysis paradigms, such as CMMI, that sadly seem to be badly misunderstood, and often misused.
As an aside, anyone talking about engineering in the abstract really needs to read some Henry Petroski. His To Engineer is Human is great, but even such wonderful deep cuts into the history of things, such as the Evolution of Useful Things, or even The Pencil are quite wonderful.
Actually there are tons of software fixes. First, it helps you to keep verifying after a bug has been discovered, so you might as well include it. Second, it is safer than fixing the hardware, assuming the bug is subtle. And when the bug is discovered in the “final” tapeout software fixes are faster and cheaper.
If you mean the go-to letter, it was a pre-internet meme. You’d see X Considered Harmful all over the place back then. He also critiqued the four candidates for Ada in SIGPLAN Notices, which was pretty fun. At least his least hated candidate won.
I went to a lecture by Dijkstra at one of my schools. His techniques would work very well - if all programmers were as smart as he was. In the real world, not so much.
As for the main point, it is clear that both are needed. You can have a great design with components so screwed up to be unreadable and unmaintainable, and you have problems, or you can have beautiful components put together with scotch tape and baling wire, and have a disaster.
I think perhaps we’re disagreeing on what was refuted.
The OP said in effect: “As a rank amateur I once diddled in Basic. How can anyone seriously call ‘programming’ by the name ‘software engineering’? After all, I did ‘programming’.”
The OP has been pretty thoroughly, and IMO accurately and well-foundedly disabused of his notion that what he did was “software engineering” and that the name is pure puffery. *That *is what has been refuted as the term is used in 2015.
That actual software engineering as practiced daily by several posters here falls short of perfection is hardly support for the OP’s contention. If you drop a bowling ball and a baseball off a tall tower, the bowling ball will hit the ground first. But by a tiny margin. To use that difference as proof of the ancient’s belief that speed of fall was exactly proportional to weight would be silly.
Yes, it is an immature field. And, like some branches of structural and mechanical engineering, it’s dealing with the reality that the substrate material upon which it works is itself changing and progressing rapidly.
Right now aerospace is still learning to master composites and some advanced alloys. Things are being badly overbuilt, and in some cases tragically underbuilt, as the engineers feel their way towards the true best use of their new materials.
Software has that problem 10 or 100x. It’s not surprising that reliability (both of projects and of products) accordingly suffers some degradation.
Dijkstra was an interesting lad. I have a copy of his A Discipline of Programming, but haven’t opened it in decades. IMHO he tended to ignore some of the more human parts of software engineering, and despite his immense contribution to computer science, he didn’t put much thought into the questions of how to get human beings to be able to create useful large software systems.
One of the common things you hear from some senior software guys is “Just give me a dozen top notch guys and I will have it done in a quarter the time.” To which the reply should be “So just why does your project justify taking all the really good people, and leaving the less good for all the other projects?” So, indeed, if everyone was as smart as Dijkstra, it would be much easier. Although not always, people that smart often don’t work well in large structured teams. Managing ego problems, and disagreements about technical directions gets hard when you have a lot of people like that. You can’t abstract away from the human part of software engineering. People are fallible, and any engineering discipline has to cope with this, and yet somehow manage to produce the goods.
There’s a converse to that, too, though, and you seemed to be hinting at it in this extract from post #90:
I wholeheartedly agree with this (and with everything else you said in #90). Process guidelines like CMMI serve some useful purposes but they are indeed badly misunderstood and misused. And the most egregious misunderstanding is that some IT executives mistakenly think it’s the magic answer to their elusive quest for the Philosopher’s Stone of software development, consistent excellence. To the ancient alchemists, the Philosopher’s Stone would enable them to turn lead into gold. To the modern ones running IT departments, CMMI will supposedly enable them to turn the unskilled dunderheads that they sometimes employ into proficient developers of excellent reliable software. Some will even go so far as to deny that software development skill is even a thing, so great is the magic of CMMI.
And of course it’s no such thing. It’s fundamentally nothing more than a series of checklists and documentation and review requirements that promote process consistency (and, if you’re very optimistic, maybe even process improvement). It doesn’t obviate the need for skilled software engineering, competent project management, and at least passably good programming skills.
I don’t know if the quote about a dozen top-notch guys producing software in a quarter the time is necessarily even true, though it’s undoubtedly true that they would produce higher quality software in terms of functionality and reliability. The fact that there’s not enough of these guys to go around doesn’t change that. The question is what to do about it. And the answer isn’t in generic process standards like CMMI. I think the answer lies predominantly in applying software engineering principles to leverage the skills of the best people in the most critical areas – high-level system design and component specification.
You obviously need both to some reasonable extent. But which is more important? If you have a component that works but is so badly written that it’s hard or impossible to maintain in the future as the system evolves, you at least have the option in a well-engineered, well compartmentalized system design to throw it out and write a new one. If the system design itself is deeply flawed, you have nothing.
Since he was an academic, I attribute this to good sense on his part. In my mostly non-software area, I’ve seen NSF proposals from academics which claim that unless their research is funded, some methods cannot be practical - stuff that you can buy and is shown on conference exhibit floors. That’s actually from not having enough resources and time to work on practical things.
Software verification back then was on toy programs like GCDs - which the famous paper showed the authors of papers on verification couldn’t get right. But those authors were not as smart as Dijkstra.
Barry Boehm measured 10x difference in software skills. Your point on teamwork is well taken, but I’ve not noticed that great programmers are any worse than mediocre programmers. So, I kind of agree with your software person whose response to the question should be “because my project is more critical than yours.”
When I was at Intel I learned that the only way to get priority from the CAD group was to say “if I don’t get this, tapeout will be delayed.” Which was one of the reasons I left.
Dijkstra wasn’t all the smart. He was incredibly brash and self-promoting. That goes a long way.
E.g., he wrote a paper on the generalized Dining Philosophers problem. He “solved” it by introducing “arrows” to decide who gets which fork. Ta-Da! Problem is: that doesn’t achieve a single thing. He merely restated the original problem. He left out how to implement the arrows. He was always missing stuff like that.
As to formal proofs of correctness: I’ve refereed many papers that contain such “proofs”. I always assume the algorithm is wrong and was never disappointed. One example was less than a dozen lines of code. The author was a major figure in the field of formal proofs. It had two really obvious errors.
I got an error in another paper by a guy I knew a long time. A simple 3 line code fragment. Formal proof. Completely wrong. Withdrew the paper. Still got a Turing Award years later.
The more “trustworthy” sounding something is, the less reliable it is. Ergo, do not trust these. Skeptics find more errors than believers.
Regarding CPUs. Um, these are microprogrammed. Almost all errors are in the microcode. Intel routinely rolls out microcode updates to fix some (but not all) such faulty CPUs.
You can over-engineer a bridge. You can’t over-engineer a program.
You ever meet him? Hear him lecture?
Are you familiar with the paper I mentioned? It was from around 76 or so, and found errors in many published proofs. I think Alan Perliss was a co-author, the main ones were from Georgia Tech. A long time ago… So, proofs being incorrect is nothing new. And of course the examples had well defined requirements and were small. I’d like to see anyone prove anything about interaction with as yet undefined drivers.
You are incorrect. x86 microprocessors are microprogrammed. Sparc microprocessors are not microprogrammed. The FDIV bug I mentioned was not a microcode bug. None of the bugs I hear about every day are.
Not that microcode doesn’t have bugs, but I sure wish the rest of a design was as perfect as you think it is. Microcode bugs do not require a new tapeout.
Did you know that Dave Patterson’s dissertation was on microcode verification? It was quite good.
An article in the Atlantic today is on the same topic as this thread and addresses some of its particulars in interesting ways. It’s title is “Computer Programmers: Stop Calling Yourselves Engineers” (Why Computer Programmers Should Stop Calling Themselves Engineers<!-- --> - The Atlantic).
It notes that the term ‘software engineering’ comes from a 1968 conference held by the NATO science committee. The conference explained its choice of words as, “The phrase “software engineering” was deliberately chosen as being provocative, in implying the need for software manufacture to be based on the types of theoretical foundations and practical disciplines, that are traditional in the established branches of engineering.”
The heart of the article is an attack on programmers as unprofessional and so alien to the world of engineering with its certifications and dense regulations. The quality of programmers’ work is generally so poor that people should not associate them with the reliability of regular engineers.
I’ve enjoyed the insights in this thread and would like to see if anyone has comments on how this article relates to them.
Once again the programmers are being blamed for doing the job they were paid to do. If you want higher programming standards then start paying more for software, and demand reliability. If structural engineers were told their job was to get the job done as quickly as possible with minimal cost we’d have bridges and buildings collapsing everywhere. Would the engineers be to blame for that? We engineer as much as anyone will pay us to do.
Every programmer is not an engineer. Programming itself may be nothing but implementation, but the engineering work is done at the design level, and it’s not all a bunch of crap either. It’s easy to complain about the mountains of garbage software out there, especially the consumer goods that are as well engineered as your average ‘As seen on TV’ gizmo. But underneath and all over the world there is a sub-structure of highly engineered reliable software that drives this modern world. You wouldn’t be online discussing this subject without it.