My colleagues have been bandying about various "quips" that encase "good engineering wisdom" in playful quotes.
My favorites, to date:
"If you can't describe (in prose) what you're doing, then you're doomed to wasting time trying to sort out what you REALLY want to achieve -- and mistakenly claiming that all to be 'Engineering'"
"The sooner you start, the longer it will take"
Both leverage the notion of having some sort of specification that defines your goal -- so you know where you are headed and when you've attained it.
There are others, of course, but many are old saws ("if it doesn't fit in one brain, it's too complex"; "it should fit on one *page*"; etc.)
Beyond that, there are far too many that address "specifics" instead of The Big Picture.
Didn't find your answer? Ask the community — no account required.
How hard have you looked ? I find it hard to believe you can't find a...
E
Edward Rawde
You're reminding me of
formatting link
And this
formatting link
An this
formatting link
D
Don Y
Corporate environments are full of people protecting turf -- their own notion of relevance. For a project to succeed, it has to do so IN SPITE OF these leeches.
That's why you have domain experts instead of letting the engineers/designers decide what they're going to build.
I listened to a (very competent!) engineer explain his "revolutionary" solution to a particular design problem (we have historically designed devices that are self calibrating and validating). When he was done, I pointed out that he had presented a circular argument -- that A relied on B relied on C ... relied on A.
Of course, every individual step made perfect sense. But, until you looked back at it objectively, you couldn't see how your assumptions enabled your other assumptions (and none was based on the reality on the ground).
I.e., calibrate this by relying on the fact that THAT is calibrated (which, in fact, had been calibrated by relying on the fact that THIS was calibrated!)
trying to do -- simply because they "set off on foot" without a map, compass or intended destination. Great if you are paid by the hour but foolhardy, otherwise!
M
Martin Brown
My favourite is that you need to split every level down to 7 +/- 2 sub levels to stand a chance of being able to implement it reliably.
Ironically my Cyclic Complexity Index tool does not pass this test!
+1
Or put another way:
Until you actually know where you want to go setting off is premature.
The management suits side of it was distilled to a mantra in my project management course: WHISKY - Why Isn't Sammy Coding Yet ?
That said managing software engineers *is* like herding cats.
My other favourite applicable to all project management is:
When you are up to your arse in alligators it is hard to remember that the objective is to drain the swamp.
+1
The other important one is never underestimate the stupidity of users to do really dumb things even when you *warn* them of the consequences. e.g.
DO YOU *REALLY* WANT TO WIPE YOUR ENTIRE HARD DISK ?
- EVERYTHING WILL BE DESTROYED (Y/N)
A worrying proportion of people still press "Y" :(
C
Cóilín Nioclásín Glostéir
Martin Brown <'''newspam'''@Nonad.co.UK> wrote: |-----------------------------------------------------------------------| |"[. . .] never underestimate the stupidity of users | |to do really dumb things even when you *warn* them of the consequences.| |[. . .]" | |-----------------------------------------------------------------------|
Truly. (S.
formatting link
fuer Kontaktdaten!)
D
Don Y
I see that as a consequence/manifestation of the "fit in one brain" mantra. Cut a task into chunks that you can COMPLETELY wrap your head around -- and explicitly define any assumptions you make (better yet, codify them with invariants, keyed connectors, etc.)
IMnsHO, that's been reified in Agile: just start and THEN sort out that you're headed in the wrong direction!
Said another way: "I don't know what I want -- but, if you spend time building SOMETHING, I can tell you that it's NOT what I want!"
But, a lot of developers (HW & SW) seem to think picking up a pen
*soon* is a good way to get done quicker. I spend a shitload of time just "cogitating" about the model I want to map onto the problem. Then, poking holes in it to verify that it really *does* fit the problem -- or, why it deviates.
So, when I actually pick up a pen, I know the boundaries of the module that I will be implementing WITHOUT worrying about the other modules (because they've already been conceived as independant entities)
I think that is largely because the folks who manage software projects aren't particularly "skilled in the art". And, those that are, quickly lose their skillsets and intuition for the process.
"If you're in a hole, STOP DIGGING!"
The lip side of this is developers who don't make it clear *which* disk is going to be affected. "sda" and "sdb" don't mean squat to most users. Would it kill you to take whatever information you have on the available choices and present it in a non-nerdy manner? So even *nerds* can resolve any ambiguity?
E.g., *describe* the drive (make, model, capacity) AND ITS CURRENT CONTENTS (unformatted, NTFS partitioned, etc.) so the user can have a chance at making an INFORMED decision. For example, if I select the formatted drive to be operated on, leaving the UNFORMATTED one "as is", you might want to prompt me: "Why are you looking to copy the contents of the unformatted drive onto the formatted drive THAT ALREADY HAS CONTENT???"
But, people have simplistic models of the world. I worked PT for a hand tool manufacturer. Some of the litigation that came along was mind-numbing: "You don't mean someone was THAT stupid??" (yes, and here are their medical bills to prove it!)
OTOH, in each case, you could see how a simpleton's view of the world would lead someone to thinking that what they were doing made sense!
D
DJ Delorie
I've been telling people: Those comments you put in your code are for your future self, and should answer the question "what the hell were you thinking?"
D
Don Y
Comments should add value -- not restate what the code is already unambiguously stating.
Many developers never revisit their code so you can't rely on The Next Guy to understand your design choices. The same is true of hardware designs -- if you do something that looks a bit out-of-the-ordinary, justify your design choice.
E.g., I used Boyer-Moore in an application that would likely have confused anyone not familiar with it or its advantages, especially in that specific implementation. So, I explained my "why" and included a reference to the original paper, assuming anyone interested (or, tempted to tinker with my implementation) would track it down.
Where possible, comments about what is *happening* in the code should take the form of invariants as this also verifies the integrity of the code at those points.
M
Martin Brown
I recall a friend recounting how he had left an undocumented as to why it was done booby-trap in some kernel code for a particularly obnoxious know-it-all to trip over after he had left the company.
He was spot on about what would happen. The OS slowed down considerably as a result of the "obvious optimisation" that know-it-all found.
It is particularly important when you are doing something that is intrinsically complicated like transposing big matrices in place in a multi-level cache aware routine. You only want to do those sorts of tricky ice-pack-on-head calculations once and make it clear how all the magic numbers have been derived for when things change in the future.
Today there are libraries like BLAS with highly optimised routines derived from those early hand written academic codes.
Sometimes you can get caught out by invariants. There are too many other orthogonal rotation transforms that are not quite FFTs for example.
You have to test that for a few simple cases the one way application of the algorithm gives the expected result. I always liked using spreadsheets to make test data because the odds of making the same error in that environment as in in procedural language was almost nil.
For most of my work the generation of test data from correct answers was relatively easy, but the inverse problem was fiendishly difficult. (and that was what we wanted to solve for real experimental data)
D
Don Y
In the early 80's, a colleague was always RE-bugging our floating point library in the name of micro-optimizations. (back then, you didn't even have a multiply opcode). It was standard practice to keep a copy of the working sources squirreled away so your build machinery wouldn't fetch his latest f*ckups.
Exactly. The tables in my kernel are not organized in the way that one would conceptualize them -- because that would result in all sorts of cache thrashing. You need to explain this to The Next Guy so:
- he doesn't FIX things
- he stops grumbling about the "idiot" who made these decisions
It has to BE an invariant to be coded as such! :>
I use them liberally as a form of documentation that the compiler can then enforce.
E.g., verifying constraints on inputs -- and outputs.
But, also littered through algorithms to make obvious the conditions that are in effect at a particular point. Silly example:
if (n is odd) n--;
ASSERT(n is even)
I tag different types of invariants with conditional compilation qualifiers so I can choose which will remain in the production code (and impact performance)
In my world, most of the code is controlling mechanisms, directly or indirectly. So, you want to keep the algorithm's notion of "what the world looks like" in sync with what YOU think it looks like. And, liberally make those assertions *in* runtime checks to ensure the world DOES look that way.
[If the assertion fails, then the safest bet is to give up because the program logic no longer corresponds with what the program is experiencing. You don't know *how* to recover because those basic assumptions on which the code relies are demonstrably untrue -- something is broken]
(Again, "in my world",) I typically have to create physical conditions that contradict the code's expectations, in order to get good test coverage. But, do so in a way that doesn't physically break something or injure bystanders. And, do so "at speed" as there are mechanical consequences that the mechanism will manifest in those situations.
E.g., in a tablet press, you have an upper and a lower "punch" that form the top and bottom surfaces of a tablet -- *in* a die (that forms the sides). You can control the (eventual) mechanical position of the upper and lower punches within the die at the point where the tablet is actually formed (compressed). The difference between the upper and lower punches AT THIS POINT determines the thickness of the tablet.
formatting link
I.e., the upper and lower "rollers" can be individually raised or lowered thereby affecting the positions of the punches as then are FORCED between the rollers.
[You want to be able to determine where, within the die table, you form the tablet as this impacts how well the granulation fills the die. And, gives you a way to eke extra life from a set of dies as the dies "bulge" from the mechanical stresses, over time (compression forces can reach 10T -- at 200Hz)]
But, the range of adjustment is such that you can position the top of the lower punch ABOVE the bottom of the upper punch -- shattering the punches in the process. You obviously don't want to test this by forcing a "real" set of punches to destroy each other. So, you have to monkey with the mechanism *or* the sensors/actuators to simulate this. Realizing that you need to detect it as a singleton event and not "across the board".
Or, validate the "weight control" performance in the presence of dimensional variations (manufacturing tolerances) in the punches. E.g., an upper punch that is a bit long will result in a thinner tablet (higher compression force -- which makes you think it is overweight) while a lower punch that is too long will result in a tablet (same overall thickness) that is too *light*. What happens to the control loop when this pattern repeats every time that punch pair is encountered? Do you "hunt" needlessly? Do you end up worsening your control by trying to treat that punch pair the same as the other "normal" pairs??
Or, detect the consequences of someone having wired a motor backwards. Or, a broken sensor. etc. I.e., you spend more time trying to figure out a way of reliably simulating such failures without incurring the consequences of them!
If you naively trust your inputs, then anomalies can send your algorithm off in completely unexpected directions. So, you need to embed smarts in how you interpret those inputs. But, then need a way to simulate their misbehaving. And, hope you've imagined ALL of the ways they can do so!
L
Lasse Langwadt
and comments that are wrong or obsolete are worse than no comments
D
Don Y
... because many developers debug the comments and not the code!
J
john larkin
Someone wrote a program that strips comments from a c program, on the theory that comments are always wrong. I assume that program was uncommented.
I saw a bit of Windows source code. Apparently there is/was a sort of form required at the start of any block of code. It contained title, author, date, function, things like that.
The "Function" section was filled out as "what it says."
John Larkin Highland Tech Glen Canyon Design Center Lunatic Fringe Electronics
S
Simon Simple
"Simple things work, and complex things can be made from simple things."
(Stephen Pelc of MPE)
E
Edward Rawde
In the case of many of the projects I've worked on, we did know exactly what we wanted. But only after the project was finished.
D
Don Y
The most reliable parts of a system are the parts that aren't there!
G
Gerhard Hoffmann
Am 17.08.26 um 02:18 schrieb DJ Delorie:
See the famous comment in the Unix process switcher routine
*you are not expected to understand this*
A friend of mine who did the Unix port to the Fairchild Clipper insisted that there is yet another bug in the task switcher still not surfaced after years of use.
<
formatting link
>
<
formatting link
>
Gerhard
G
Gerhard Hoffmann
Am 16.08.26 um 20:41 schrieb Don Y:
Vonada's Engineering Maxims are a group of pithy observations about computer engineering compiled by Don Vonada, an engineer at DEC, and reproduced in: • C. Gordon Bell, J. Craig Mudge, John. E. McNamara, "Computer Engineering: A DEC View of Hardware Systems Design" (Digital Press, Bedford, 1978) They are: 1. There is no such thing as ground. 2. Digital circuits are made from analog parts. 3. Prototype designs always work. 4. Asserted timing conditions are designed first; un-asserted timing conditions are found later. 5. When all but one wire in a group of wires switch, that one will switch also. 6. When all but one gate in a module switches, that one will switch also. 7. Every little pico farad has a nano henry all its own. 8. Capacitors convert voltage glitches to current glitches (conservation of energy). 9. Interconnecting wires are probably transmission lines. 10. Synchronizing circuits may take forever to make a decision. 11. Worse-case tolerances never add - but when they do, they are found in the best customer's machine. 12. Diagnostics are highly efficient in finding solved problems. 13. Processing systems are only partially tested since it is impractical to simulate all possible machine states. 14. Murphy's Laws apply 95 percent of the time. The other 5 percent of the time is a coffee break.
(#10 is apparently a reference to meta-stability. The seeming typo in #11 - "Worse" - is in the original.)
Related observations Maurice Wilkes is reported to have said something like: "A digital circuit is like a tame animal, the analogue circuit is a wild animal. Every so often the tame animal reverts to the wild."
D
Don Y
An employer set out on a multi-man-year development -- for a successor to an existing product. When done, they scrapped the design -- and started on it's successor.
Isn't the role of Managlement, Sales and Marketing to know these things BEFORE starting on a project?
D
Don Y
My go-to-comment was always "Here be dragons". Not a disdainful comment but, rather, one suggesting a need for heightened awareness. This was particularly important when juggling parameters in a stack frame to take advantage of register operations -- where three or more entities might be "in motion" in one or two opcodes.
Or, when copying a section of data from A to A+1 -- exploiting a "failure" of the routine to accommodate overlapping regions. (it's a great way to perform a crude check on memory)
That's possible -- even likely. Not all bugs manifest or do so in ways that can clearly be identified as such. If the system keeps making progress -- albeit in an unexpected way -- then there is often no need to go hunting for a "problem".
If you carefully read the details of how many things work, you will often note that there is no guarantee of fairness in selection processes. Rather, that "something" is selected that CAN be selected. We just assume that will be done fairly.
Ah, but *everyone* has a copy of Lions' on their bookshelf, don't they? :>
Ditto Organick, McKusick, Knuth, Winston, Foley&van Dam, Mick&Brick, Newman&Sproull, etc.
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required
Report Content
You are reporting this content to the moderators. They will look at it
ASAP.