A significant amount of programming is done by superstition - <AUTHOR> http://utcc.utoronto.ca/~cks/space/blog/programming/ProgrammingViaSuperstition <comment><USER2> I'll have to admit something about myself -- I've never been able to learn how to do anything from just reading its first principles. I need to have a working example that I can then adapt and change and observe changes in the result.

This has been especially true in programming. I've been writing programs in some capacity for 18 years now and not once in that time have I been able to simply read the reference manual of anything and following that write working code on my first try. Well, obviously I've been able to do it for trivial things, like after the Python 2->3 switch when map/filter/range started returning iterables instead of lists, simply being told "map/filter/range/etc. now return an iterable and not a list" is sufficient to explain the change in behaviour, but that's only because I know all the concepts behind it. You could say the explanation is only one level removed from my intuitive knowledge. Things start getting exponentially harder the more levels removed they get, i.e. if it's a new concept explained using new concepts previously defined, but for which I have no intuitive knowledge what they mean.

<comment><USER3> Almost nobody can. Some people think they can, and charge forward with it, but rarely do they produce something that actually works. Usually, they bang on it and test it and cargo-cult it until it works, then convince themselves that it's from 'first principles'.

Even if it were a common ability to produce engineering work from written design principles, I'm not certain that's what we want. Experimentation is the key to science. You have to observe, change, guess, run, observe, change, observe until you can successfully predict what will happen for each change you make. The scientific method is taught to everyone, even if most ignore it and skip steps. 'Guess/check' is the _correct_ way to do real-world engineering and design, not pure-logic simulation, because we still don't know all the first principles.

<comment><USER4> > Experimentation is the key to science.

Computer science is a branch of mathematics. Here you build models, reason about them, find properties, then prove them, then rely on them. Tests - a.k.a. experiments - are usually not exhaustive and don't provide guarantees of correctness.

Having said that, I agree that experiment is of crucial importance - how else you would validate your models in the first place? However, both experimenting and reasoning can be flawed, and part of the trick is to learn how to do that properly. Computer science is difficult.

<comment><USER3> Programming is a branch of engineering. Very little programming is done by proof; It's done by experimentation, debugger, and tests are human-reasoned and hopefully cover all codepaths and critical junctures (for every x > 0, you test x=1, x=0, x=-1).

Proof is of critical importance - It's how you find those junctures, for example, how you optimize, how you design and how you reason about runtime, etc. But programming as practiced in the field is engineering first, mathematics second.

<comment><USER5> Reminds me of the famous Knuth quote:

> Beware of bugs in the above code; I have only proved it correct, not tried > it.

Deep thinking and mathematical proofs are tremendously useful when thinking about a well-defined and scoped problem at a more or less fixed level of abstraction.

The problem with software engineering is that in practice all abstractions are leaky, and so you inevitably find yourself dealing with issues that are too far-flung and random to be mathematically tractable. The best you can do is be rigorous about the core problem you are solving, but there is always some amount of hammering and duct tape to build it into a non-trivial real-world system. It's possible to attack this problem asymptotically with a rigorous engineering process such as NASA employs, but we don't because it's simply not cost effective for the majority of software.

<comment><USER6> _because it 's simply not cost effective for the majority of software._

That's a great point. We utilize best practices, like automated tests, to narrow the gap between pure experimentation and mathematical proof. Proofs in most code would be difficult to impossible because most of use libraries that use other libraries, etc., so we just do the best we can given the time and monetary constraints that we have.

</comment></comment></comment></comment></comment></comment><comment><USER7> That's right, but I guess we're missing the _real_ problem here.

The real gold are these words:

> You've really read the LSB specification for init scripts and your > distribution's distro-specific documentation? If so, you're almost certainly > a Debian Developer or the equivalent specialist for other distributions.

Many of us would agree, that it's true. But _why_ is it true? Shouldn't _that_ make us suspicious in the first place? It's almost paradoxical, even funny: making the work done is easier, than finding out, _how_ to do that work. You see, init scripts or makefiles aren't exactly rocket science. I mean, things we are willing to achieve with them are pretty simple: just _start_ some process, just _build_ some project (which means "execute bunch of shell commands in the right order", and not implementing out own superoptimizing compiler).

So when we arrive to situation like one we've got today, the right message wouldn't be "come on guys, you see what we're doing because of being lazy? we should stop being so lazy!". That is, yeah, we all are lazy and maybe we should stop it, but that's not the point. What this situation actually means is that our tools for doing simple stuff are overcomplicated shit, and our documentation for these tools is shit. If anything, it's pretty obvious that a couple of lines of code, showing how to do the work is better documentation than complete list of possible flags and parameters with no examples whatsoever. So no wonder people are reading stackoverflow instead of man- pages. And so on.

<comment><USER8> > it's pretty obvious that a couple of lines of code, showing how to do the > work is better documentation than complete list of possible flags and > parameters with no examples whatsoever. So no wonder people are reading > stackoverflow instead of man-pages. And so on.

the best manpage is a man page with a nice EXAMPLES section you can grep to quickly. though the permutations offered by many programs prohibit all bases being covered.

<comment><USER9> [http://bropages.org](http://bropages.org) to the rescue!

<comment><USER8> alias aprobros="bro"

</comment></comment></comment></comment><comment><USER10> I think a better title might be "A vast majority of programming is done at a level of abstraction that this author is slightly uncomfortable with".

If you work in Java or Ruby or Python or C#, or even C++ all day with say, an IoC container for argument's sake, you're certainly not constantly thinking "okay this interface will be resolved to this type, which has these dependencies which will be resovled to these types, which generate this byte code, which generates this JITed assembly code, which generates this machine code, which generates these executions of instructions on the processor and accesses these memories, which invokes these manipulations of these gates and flip flops on this particular part of the ALU".

Doing so would be the mark of an unproductive madman.

<comment><USER11> I don't think this is about abstraction. Abstraction implies having a deep understanding of the problem domain and encapsulating it in such a way that the implementation details can be ignored and the domain can be reasoned about at a higher level.

I think a better title would be "A significant amount of (shipped, so-called production-quality) code is not fully understood by its authors".

<comment><USER12> "A significant amount of (shipped, so-called production-quality) code is not fully understood by its authors"

Of course. Time spent fully understanding the code before it's shipped is time that it's not shipped.

This is sort of a Gresham's-Law situation, where "bad code drives out good code". The code that is fully tested & debugged with all situations understood isn't available to the user at first. As a result, they go with the "good enough" solution, build stuff off of it, and by the time "the right thing" comes along, all the momentum has shifted to its crappy competitor. A bunch of crappy software gets built on top of that, and as a result, we end users get the worst thing that could possibly work.

But work it does. Maybe it's worth a shift in perspective to be grateful for the stuff that works rather than worry about the stuff that doesn't quite work right.

<comment><USER13> Anyone can build a bridge that stands up, but only an engineer can build a bridge that _barely_ stands up.

Good Enough is our main design goal. Anything more than good enough means you're wasting resources.

<comment><USER14> This sounds like Engineering, but be aware that in mechanical engineering the requirements are well-defined for materials and load. Consider the famous bridge resonance problem and you will see why wind resonance is now a required subject for structural engineering.

ME has an advantage over CSE in this regard because in CS the requirements are usually very poorly stated. About the best and most rigorous requirements you get are from mathematicans, but most devs and managers now certainly view that as wasting resources.

To make not to fine a point of this, I always like to turn to Alan Kay's comparison: TCP/IP vs the web. When was the last time any human technology like TCP/IP scaled so well and so invisibly, it's like air we breathe without even thinking about it. The web in contrast was the work of rank amateurs.

Alas, mathematics is really the "good enough" standard we in CS should strive for just like physics is the "good enough" standard behind ME and EE. Unfortunately as CS opened to the mainstream, I think a deep fear of mathematics led us to view this as "over engineering" even when it wasn't. The results are that the majority of the web is woefully _under_ engineered, requiring far more money and time for inferior products.

We _know_ they are inferior, because even the simplest gui application has more consistency than a web variation of it. And that's what marketing constantly compares things too when they can't understand why the web sucks as much as it does.

"Good Enough"? Please! For the last 20 years we haven't even come _close_!

<comment><USER15> The web might have been created by amateurs, but it works incredibly well. Sure, we have browser incompatibilities and whatnot, but this is an effect of having multiple independent implementations of the standards, which is part of what makes the web work in the first place.

<comment><USER14> no, it doesn't. Having multiple independent implementations is a PITA, but that's why you have testing & validation labs along with standards. Take windows graphics driver labs... They test for pixel perfect compliance of output across hundreds of vendor implementations. Contrast that to the web where it took a separate group outside the w3c to embarrass browsers with the ACID2&3 tests. Now separate browsers look a lot closer in output.

Devs are trying to fix these ecosystems: why does react use a virtual dom? Why do we need css resets? Why do we need js shims and polyfills? Because its the only way to come close to normalizing the platform.

But have you ever wondered why you expect no two browsers display the same image? Postscript met that bar and is just as old as the web. Why didn't the w3c base the web on device independent coordinates instead of this confusing and unpredicatble layering of partial scalars and "angle subtended by a pixel on a 96dpi surface at a nominal arms length from the surface" crap? No one could have made a reference implementation off those requirements, much less a consistent verification & validation suite.

And no offense to TBL, but HTTP didn't even survive first contact with netscape's vision of shopping carts. Cookies? An elegant solution? Or simple a new hell of tunneling client/server state over a supposedly stateless protocol. HTTPS everywhere requires long lived sessions as the basis?!? No wonder people are heading towards web sockets, etc. webapps are client/server apps -- HTTP was always grossly misapplied to them.

Webdev is hard, not because I'm building beatiful bridges in the sky that are "good enough" poetic balances of constraints while coming in on time and on budget... Webdev is hard because of all the underlying assumptions I constantly have to check and recheck because I can't rely on them as an ME would (or hell, even as a backend J2EE engineer would). This is why some of us lament that people don't know the stack all the way down, because we have to in order to solve real problems. Every abstraction leaks, but hell, web abstractions are flipping sieves!

No, the thing that "works incredibly well" is not the web, but whats under it that lets us make so very many mistakes and yet keep on trucking.

<comment><USER14> Regarding Postscript vs web: I'm only talking about device independence. Specifically in the case of pixel perfect layouts. I am not talking about the layout constraint problem, which is extremely challenging no matter the technology. But layout constraints depend on a solid notion of coordinate system, which the web lacks. Device independence gives you that in postscript and SVG.

Besides, windows faces a similar problem of multiple resolutions and devices. How do they v&v? They set the resolutions the same for certain tests! Even if you do this for browsers, they cant pass the test. Yes, it would be nice if we could have device independent layout constraints as well, but even the simplest most constrained test not involving layouts fails. At least now, its close. Before ACID it wasn't even close.

If webdevs can't even rely on their browser coordinate system in the most heavily constrained case, how can they hope to trust it when they try to solve challenging problems of dynamic layouts across multiple resolutions?

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER16> I actually really like the content of the article, but I'm not convinced superstition is the right word here. Yes, absolutely I have copied an init script / makefile or whatnot and if it worked after I tweaked it then I went on my business. But I didn't use it as is because of superstition, but rather because it now worked I believed it correct.

Yes, quite often that came without a perfect knowledge of every single option, certainly usually without referring to the manual for every one of them.

Perhaps this is semantics. But the definition of superstition is:

 _a widely held but unjustified belief in supernatural causation leading to certain consequences of an action or event, or a practice based on such a belief_

Which ya, isn't quite the right thing. Anyways, agree with the sentiment of this 100%, just not the title. :)

<comment><USER17> I think this is more commonly called "cargo cult programming", defined by Wikipedia[1] as: "the ritual inclusion of code or program structures that serve no real purpose".

[1] [https://en.wikipedia.org/wiki/Cargo_cult_programming](https://en.wikipedia.org/wiki/Cargo_cult_programming)

<comment><USER16> I think there's a significant distinction here to be made between "configuration" and "programming".

Do I copy/paste swaths of code that I don't understand and put them in my programs? No, absolutely not, because each line is one I can reason about and want to understand.

But do I copy/paste swaths of configuration files / init scripts / etc, without understanding the implications of every single configuration? Yes, absolutely, because the depth behind each of those options is often irrelevant to me. (until I discover otherwise late at night when an alarm goes off (!!))

I think it is important to distinguish these. I don't think any dev that's done ops work would claim they aren't guilty of the latter, but at the same time I think very few good devs ever, and I mean ever, do the first.

<comment><USER18> Init scripts _are code_ though. I mean, they're code that's mostly boiler plate, but they're still code - I can do arbitary things in them, reasonably unconstrained by their stated purpose.

</comment></comment></comment></comment><comment><USER19> I've always enjoyed what I call uncoding, which is taking a working piece of code and taking stuff away until things break, and examining how they break. It's really helped me understand what each piece does, and be more efficient when I'm writing it myself.

<comment><USER20> Amusingly, that's also more or less how we've learned to understand the various functions of the different parts of the human brain. We don't know what it does until it's been removed/damaged.

</comment></comment><comment><USER21> I hate to call myself out, but I envy most of you. It sounds as if many here get the opportunity to work on interesting problems from end to end. As such, first principles matter, and approaching something from scratch makes sense. I however have been stuck in a segment of the market that doesn't appreciate the right solution, but rather just wants a solution as fast as possible. To be clear, I'm talking about a more consumer audience. My clients expect things done quick, and quick means leveraging cms, ecommerce platforms (magento, woo commerce, etc.). To be frank I find such work unsatisfying, and often need to hack things together to meet the requirements set forth within the constraints of the budgets I'm working with. I'd love to be able to work in an environment where doing things right mattered, but the plain fact is the deliverables aren't measurable based on quality, but expedition.

While I'm on a soap box, I'd like to point out to those in the positions where they're work is evaluated by professionals and peers how lucky they are. I'd kill for a job/client where my code is evaluated by other developers. This community sometimes forgets they are the 1% of the development world. Those who work for the googles, facebooks, and visionary startups with leaders who came from the same cloth. The rest majority of us are laboring away under management that have never produced a lick of code, or even design, for that matter.

I guess the Tl;DR is: appreciate the fact that you even get to consider the finer points, and pray for the rest of us.

</comment><comment><USER22> I've referred to this for years as "ritual-taboo programming". Ritual-taboo societies are ones in which things are done in certain ways because they worked in the past, but no one knows why. Too much of programming is like that.

If you work from the specifications for a library, you'll probably find that some of the documented features don't work. If they weren't used by some "framework", or mentioned in a how-to book, they probably haven't been exercised well.

</comment><comment><USER23> A nice example of this is yoda expressions in, say Java.

The initial reasoning for them was to prevent accidental assignment, since a C/C++ compiler will complain on this: if (null = x)

but not on this: if (x = null)

In Java, neither is allowed, so the whole yoda construct is almost pointless. The exception is boolean assignment which does benefit from this idiom, but the loss in readability is a trade off to consider. In any case, I suspect most uses of this construct in languages like Java fall into the "superstition" category, where the people using it aren't really considering why.

<comment><USER24> A lot of us find Yoda conditions easier to read:

      if(0 == very_long_function_name_here(param1, param2)) {

Tells me a lot after I've read a little of the line, whereas:

      if(very_long_function_name_here(param1, param2) == 0) {

Makes the == 0 part easy to miss, and buried behind a lot of clutter.

<comment><USER25> Why would you _ever_ have a function with a name that long in the first place?

Also, there are many more ways of dealing with readability: try different formatting and indentation rules, wrap lines manually where you think it makes sense and so on. As for your example, even the lowly C let's you do something like this:

        int (*short_name)(int) = &veeeeery_long_and_ugly_and_unnecessary_function;
        if(short_name(1) == 2) {
          printf("\n\nYay, it worked!");
        }

which completely solves the problem, no matter the order of compared objects. I'm not sure, but I suspect things like this are being optimized away by the compiler anyway, which would mean that you can use it anywhere you want without worrying about costs of indirection.

In higher level, modern languages you have even more, much more sophisticated tools for doing this kind of things.

<comment><USER26> Explicit function naming requires slightly longer function names, but you can actually read a program and get a sense of what is happening. Give me long function names over short ones any day. In my book, 5 words is a little long, but not out of bounds.

<comment><USER25> If you take a closer look at my example you'll see that the long name is there of course, it's still very close to the point where it's used. It's only aliased for a moment in this single section of code and because of lexical scoping there's no danger of name collision. Of course, doing this in a global namespace makes no sense.

How long identifiers are acceptable depends on a language. With languages without namespacing or modules you obviously have to use some naming convention so that there are no name conflicts and this makes your names longer. I'd say 5 words is ok in this case.

But I'm not arguing against long names of things: on the contrary, I like having names as descriptive as possible. OTOH, too long names are also bad, because they make the code less readable and harder to work with. Like almost always it's a matter of balance: you need to know when to stop adding words to a name. I think that "name is too long when it starts making other names in the same line much harder to spot" is a good heuristic for this.

<comment><USER24> The alias is just adding confusion. If I see such an alias in code, I would wonder where else that function is used in the function, and be confused that it isn't.

Not to mention it becomes more verbose once you make that alias a const ptr (which we do on all of our local variables).

<comment><USER25> > The alias is just adding confusion. If I see such an alias in code, I would > wonder where else that function is used in the function, and be confused > that it isn't

You'd be confused once or twice, then you'd learn the technique and you'd stop being confused. Every code pattern was unfamiliar to you at first. And confusing, until you internalized it. It's unrealistic to assume that you can ever _stop_ learning new patterns - try switching to another language and you immediately have dozens of unfamiliar, confusing patterns to learn. (it gets better after a certain amount of languages known (like [https://klibert.pl/articles/programming_langs.html](https://klibert.pl/articles/programming_langs.html)) because you start noticing meta-patterns)

My C is rather rusty nowadays and using function pointer here may not be the best option, but as someone else said, there are other language tools for doing this kind of aliasing, like #define. I'd go for function pointer probably, because it reveals not only a name, but also a type of function and it's guaranteed not to escape the current scope (unless explicitly returned) while #define has no knowledge of scopes at all. In languages which support real macros, and preferably lexically scoped macros (like Racket) I'd use those. In languages with closures and first-class functions I'd probably do it in yet another way. But in general, if I find myself working with a name so long that it makes it hard to spot other names on the same line I _will_ alias it locally.

Have you read [http://shop.oreilly.com/product/9780596802301.do](http://shop.oreilly.com/product/9780596802301.do) ? It's a good, short book on the topic and it discusses exactly this issue at length in one of the chapters.

</comment></comment></comment></comment></comment></comment></comment><comment><USER27> Since I began programming I don't believe in miracles. I count on them.

</comment><comment><USER28> A very sigifigant part of Ansible service module code was done to deal with misbehaving init scripts. They are very much cargo-culted just like RPM or debian package formats - borrow the ones from your previous project.

They are hard to get right and many apps don't daemonize correctly or return OK before they are ready to be running - and then are actually running much later. Upstart/systemd didn't neccessarily make that more clear for people to understand either.

While I haven't tried it, I recently encountered a reference to [https://github.com/jordansissel/pleaserun](https://github.com/jordansissel/pleaserun) and it sounds promising.

I don't know how much of this applies to programming in general, really, but init scripts are.. yes... special things.

<comment><USER3> I dislike tools that claim to automatically generate your configuration for you. At Google, one of the worst abuses that anyone had to deal with was auto- generated configuration; a tool purported to deal with configuration for you, but really just blutrted a boilerplate mess into your directory, many of the properties and setting set by cargo-cult or overriding sane defaults with baked-in versions of the same. Facebook is proceeding down this path; There's a new tool that will do all of your service stuff for you! I look forward to what a boondoggle those services that use it will be.

There was a discussion I recently stumbled upon about init systems in containers. Many processes spawned lots of zombies! You need a full init! Well, no; If your process is forking new processes, it should probably wait for them. If it's forking other processes that fork other processes, and they're not cleaning up zombies when they're done, _that is a bug in those processes_. If all else fails, your root-level process should probably implement a simple init on it's own (a wait() on loop in the background, dumping wait objects into a LRU map that other processes can do an equivalent of waitpid() on). Or just run under bash.

</comment></comment><comment><USER29> Maybe a better term than "superstition" might be "validated experience". We do what has worked in the past.

It is true that there are standards that should be read and followed; the ones referred to in the article are probably among these.

But other standards have a fair amount of wishful thinking in them. (How many of you JS developers have read the latest ECMAScript standard?) Sometimes, what _has worked_ in the past is a better guide for practice than what _ought to work_.

</comment><comment><USER30> sysv init scripts in particular are so pointless to write.

In the end, the whole script usually revolves around four lines of actual code (starting a process, stopping it, querying the status, optionally sending it a SIGHUP to make it reload its configuration), but the result is a script with 50 lines of boilerplate.

Which, of course, could nearly all be automated away by a sane, declarative format.

Leaving all the political mess aside, that's the part that systemd got right. You write sometthing like

        [Unit]
        Description=some human-readable text here

        [Service]
        Type=simple
        User=...
        ExecStart=/path/to/deamon --with=options
        KillSignal=SIGKILL

        [Install]
        WantedBy=multi-user.target

and that's it.

Quick comparison of sysv init script lengths on Debian Wheezy vs. systemd service files on Debian Jessie: ssh: 162 vs. 15 lines, cron: 92 vs 11 lines, dbus: 122 vs 9 lines

My point being: it's a bit too much to demand that people carefully engineer their sysv init files, when about 90% of those very same init files is simply boring, repetitive boiler plate code. Also, what happened to the "don't repeat yourself" principle?

I tried writing a sysv init script from scratch. I stopped because of sheer boredom, and resorted to copy&paste to save both time and nerves.

<comment> vezzy-fnord The issue isn't so much in the medium (shell), but the underlying program itself (sysvinit) being overly primitive. See the daemontools family where runscripts are largely as short or shorter than systemd unit files: [http://homepage.ntlworld.com./jonathan.deboynepollard/FGA/ru...](http://homepage.ntlworld.com./jonathan.deboynepollard/FGA/run- scripts-and-service-units-side-by-side.html)

In addition, the BSDs have much shorter rc scripts mainly by putting all the boilerplate functions into a single library file that is then sourced. Gentoo's OpenRC framework, as well.

<comment><USER31> Franly i find myself thinking that moving the boilerplate elsewhere is also what systemd and upstart does. But those implement it in C rather than shell script.

</comment></comment></comment><comment><USER32> While the article is dramatically true (credits to StackOverflow for some of my production code), there's a factor that isn't taken into account here: time.

Yes, because as engineers our _time_ is more valuable than a minimal and perfectly-standard-compliant solution. I would happily read all the RFCs, and all the significant papers in CS, and all...etc.

The reality is that we don't get paid to read, but to ship.

</comment><comment><USER33> I'm surprised by the number of people who don't see this as a problem.

I've worked pretty recently as the most senior developer on a team, and I saw tons of issues caused by copy/pasted code. It results in a lot of issues. Subtle bugs around `==` versus `===` in JavaScript, unecessary variables that obfuscate the code, Python that isn't Pythonic, C that was written as an example and therefore doesn't include the error handling that is _constantly_ necessary in C (how many C examples check the return value of malloc?).

The biggest problem, I think, is that often you end up with 10 different ways to solve the same problem in the code because instead of looking at the existing code, people Googled for a solution with subtly different keywords than the previous person and found a different blogger. This kind of duplication is very hard to identify and remove, and this _does_ cause bugs.

Of course a more experienced developer can work around these issues, but a more experienced developer also knows off the top of their head how to write the code themselves and usually does it.

<comment><USER34> >doesn't include the error handling that is constantly necessary in C

I mean, I'm sure there are some cases, but how many C programs are capable of gracefully recovering from a malloc failure? Probably very few. If the program is going to crash anyway...

<comment><USER33> I don't agree at all, but even if I did, that's only one of _tons_ of cases. There are plenty of very recoverable errors which aren't handled by example code you copy off the internet, but which you really _should_ be handling.

Take networking code for example: do you really want to be dying without a visible reason because you didn't check `errno` and do a retry? This is really basic stuff.

</comment></comment></comment><comment><USER35> The problem here is that if it works, how is it superstition? When I knock on wood or throw salt over my shoulder, I don't have a way of verifying that I've averted disaster. However, I can test the code I don't understand, and if it does what it says it does (or does what I want it to do, since that's why I've selected it in the first place), then we're a step removed from superstition. There might be unintended consequences if I truly don't understand the code, but that is something else than superstition.

<comment><USER36> If you do not understand the code, you cannot say you tested it. It may have corner cases you did not anticipate. The test may be incomplete and only cover what you think the program should do.

<comment><USER37> why write unit tests when we don't understand the microcode in the CPU? We can't have "tested" it because we don't understand said microcode.

Or wait... no, maybe your characterization is wrong.

Yeah... that's probably it.

<comment><USER36> Where exactly did I say you should understand the code down to how electrons flow through the chip's gates?

I said if you do not understand what you are testing (not the compiler, not the runtime libraries, not the OS, not the instruction decode, not the microcode, not the gates), you can't say you actually tested it. You merely observed what could be a side-effect.

<comment><USER37> you're drawing an arbitrary line, that was the point.

We specialize and abstract for a reason. No one understands everything about everything surrounded their code, and that includes other software. Don't tell me you've personally been through the code of every single project your projects touch.

You haven't and that makes you a hypocrite.

<comment><USER36> A line that encompasses the object you are testing but that you don't fully understand (or that is hidden from you) and nothing more is not arbitrary. The best you can do in these circumstances is say it adheres to a spec for the cases you tested (which could, for all you know, be the only ones that yield correct results).

<comment><USER37> It's an arbitrary line. Too many people come up with an opinion and then cast about for a way to make it seem valid.

<comment><USER36> This is, BTW, just what you did by claiming the line is arbitrary.

<comment><USER37> yes and I'm racist when I point out someone is being racist.

I'm also a troll when I point out someone is trolling.

do you know how I turn female? By pointing out that someone is female.

It's amazing how making an observation suddenly means you've become the thing you're observing.

Or not, but who am I to judge, amirite?

</comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER38> Such as, people are taught not to use global variables, but maybe they weren't taught the reasons why not. The reasons (some of) would be polluting the global namespace, having unexpected things defined in unexpected places, and so on. At some point, it could save the programmer oodles of time to just use global variables. It could be a project with limited scope where polluting and things won't be an issue. The reason for superstitions at all are stopping people from doing something when they can't understand the reasons yet. It's hard to explain to a child all of the reasons why they should be a good person, and much easier to tell them Santa will give them presents, until they can understand why being good is inherently its own reward.

</comment><comment><USER39> I'm a proud cargo culter.

Truth of the matter is you can't just stare at a man page or textbook all day and try to understand, then code. You'll code some mess you don't fully understand, sure, but later on you'll come back and either realize it was wrong and fix it, or you'll understand why it was right. But you will eventually understand.

The people trying to understand it will have gotten nowhere in the mean time.

</comment><comment><USER40> I am someone who tends to work from first principles, to a fault. It slows me down a lot. But it's like a compulsion.

StackOverflow has improved my programming life dramatically, because it makes it a lot easier to "memoize" the search from what you're doing down to first principles. Whatever question you're trying to get clarity on, there is probably a StackOverflow answer out there that builds a positive case for a particular option, going all the way back to primary documents like standards.

</comment><comment><USER41> This does not resonate with me at all. I can not stand having things in my code I don't fully understand. Without reading the source code of libraries, without reading relevant standards, without understanding the mathematics behind algorithms, there is always this feeling I may make really dumb mistakes. Really understanding all the bits and pieces obviously does not make your code bug free, but I am usually pretty confident that I did not do something horribly wrong.

<comment><USER42> This piques my interest. When was the last time anyone read the source code of (g)libc "cover to cover" before using it? Does anyone know the precise implications of (not) defining any of the myriad sensible permutations of its "feature test macros"? Is anyone even sure that those implications are actually implemented correctly before relying on them?

<comment><USER41> I obviously do not and can not trace the entire code path from a print statement through the class library, the operating system, the display driver and the hardware, some things I will still take for granted. But if there is a really critical aspect to what I am doing, say some thread synchronization, I will definitely not just follow some sample code, but read the relevant parts of the memory model of the language specification detailing why this works as expected. If the underlying hardware matters, I will grab the reference manual for it, too.

A lot of this is surly curiosity and you can get away without it most of the time, but at least as soon as I run into the first problem it really helps me a lot to have at least a basic understanding of what is going on in the layer of abstraction I am interacting with and maybe a layer or two below. And it gives me a really comforting feeling, that I know what is going on better than describing it as some black magic.

<comment><USER43> The computer doesn't care which code you consider to be in the scope of your concern, and which you take for granted.

If you examine why you're concerned about some code more, you will probably come to the realization that you're less confident in it because it is less old and mature, has fewer users, and has had fewer developer eyes on it and such.

I.e. whether explicitly or not, you're focusing your understanding where it will be needed and that coincides with where there is more risk if you don't understand.

<comment><USER41> It's not about the quality or maturity of the code I am relying on, it's about the quality of my code. I want my code to do the right thing in the simplest and most elegant way possible and part of this is knowing really well how everything works.

</comment></comment></comment></comment></comment><comment><USER44> A significant amount of everything is done by superstition.

<comment><USER45> Still, important to be occasionally reminded of your own assumptions and corner-cutting.

<comment><USER46> Though as the author himself implies, it's not always appropriate to allocate the time necessary to do anything but corner-cutting.

"If you say that you don't take this relatively fast road for Linux init scripts, I'll raise my eyebrows a lot. You've really read the LSB specification for init scripts and your distribution's distro-specific documentation?"

</comment></comment></comment><comment><USER47> A significant amount of programming is done without articulating either the problem or the solution.

</comment><comment><USER8> as a concerned cancerian, i am glad somebody is willing to admit it. i leave my sub conscious do the heavy lifting. "this is the general shape". making a list before starting is probably the extent of my preparation. if i can copy what's gone before without understanding it, all the better.

only when i get stuck do i engage critical thinking. maybe this has been to my detriment.

very often i notice myself and colleagues making up nonsense explanations for why c++ behaves the way it does without any real basis other than intuition and truthiness.

</comment><comment><USER48> What that means is that if you're writing the system you want someone to do 'right' \-- you better provide lots of good examples in the docs.

A 'good' example is one that you've actually tested for real to make sure it works, that follows the intended principles for the system in question, that meets actual use cases developers using it will have, etc.

A significant amount of software is released without good docs -- examples being just one part of good docs. So of course developers copy from the examples they can find.

</comment><comment><USER49> In my view, a lot of this is just trying to avoid learning yet another system. Learning systems is hard and takes time, and it's only worth it if you're going to be using the system a lot in the future.

For example, creating a new init script or a Debian package description is something I don't do all the time. I don't want to learn _all that stuff_ because by doing so I'd basically push out something else from my mind. Copying an existing configuration or script and making modifications without trying to create something original is an excellent pattern for things outside your immediate expertise target.

The "avoiding creating something original" part does indeed carry a sort of "superstition". It's like relying on a new culture by merely mimicking it, because you don't really know it well enough to break the rules correctly. You don't know why things are done the way they are but your best bet is just to copy and adapt. This creates a sphere of fuzzy knowledge where intents and black magic seem to alternate.

</comment><comment><USER50> This is specific to shell scripting and to the history of nix standardization. No-one follows or cares about the LSB[1]; certification is expensive and based on buggy test programs that practically force you to "code to the test" and not to the specification. And when so many implementations ignore the spec, it would be _more_ superstitious to code to the magical spec and assume it's going to work, rather than writing something and testing it empirically.

When I'm programming (in Python or Scala) I can and do check the language specification if something is confusing, and I don't think I'm alone in this. It may be a "significant" amount of programming, but there are definitely areas of programming with more rigour.

[1] I blame Debian, usually quixotic in its adherence to standards like the FHS - but when it came to the LSB they prefer to pretend that "alien" counts as RPM support. That set the tone for how much other distros tend to care about the spec.

<comment><USER51> IMHO "alien" isn't much of an issue since LSB packages are allowed to use only a small subset of RPM features; the fancier features aren't portable between different RPM-based distros either.

[http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core- gener...](http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB- Core-generic/pkgscripts.html)

[http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core- gener...](http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB- Core-generic/pkgdepend.html)

A bigger problem is Debian gratuitously using different SONAME than required by LSB for some libraries - your LSB binary can't use those system libraries if it wants to run on Debian. But at least it looks like they fixed that problem in Wheezy.

</comment></comment><comment><USER52> I have a tendency to not use things I dont feel that I fully understand. This makes me stick to using the more basic elements of the language. In C# for example recently, there was a part of a game I am writing in my spare time for which 'events' would have suited. But I still dont feel I understand what events in C# is doing exactly. So instead I just put all the things I want the event to happen to in a list, and when the event happens everything in the list has a particular function called on it. I will probably get around to using C# events eventually when I have looked at them more and feel like I understand them. There is _maybe_ a very small performance cost to what I did (according to some stuff I read, but I havent tested this so I dont know) But at least I have an architecture for my game and code that makes sense to me and that I feel like I understand completely (at least at the abstraction level of C#)

</comment><comment><USER53> The answer to "Why we can't build software the way we build bridges?" is that bridges and other physical works disintegrate over time. Code doesn't rot, so the mistake of 1980 can be freshly reused 40 years later.

</comment><comment><USER54> This explains why so many websites don't validate email addresses properly.

<comment><USER55> How do you validate email addresses properly?

</comment></comment><comment><USER56> even with code I write myself, I can't remember the line by line implementation on the entire code base. To be honest I often forget implementation details on code I wrote last week.

<comment><USER20> Ditto. When a coworker asks me about implementation details of some code a wrote just a few weeks ago, my first answer is always "I haven't a fucking clue". Then I scan the code in question and it all comes rushing back.

<comment><USER20> I should add that the extent to "it all comes rushing back" is directly and inversely correlated with how long ago I wrote it, and positively correlated with how interesting/difficult the problem was to solve at the time.

Also, almost every time I go back to review code I wrote more than a year ago, my first reaction is "jesus, that's a stupid pattern/implementation. Why did I do it that way?". I've been a professional developer for about 12 years now and I suspect that will never change.

<comment><USER57> It won't. And sometimes you'll start to change it, hit a wall, and then realize "oh that's why I did it that way."

</comment></comment></comment></comment><comment><USER58> I've worked with developers who seem to code mostly by going to stack overflow, finding something that seems to fit their problem and then they copy code into the app. No attempt to find a more recent version or a more correct solution of the problem is made. I've seen JavaScript code copied from a stack overflow answer that was dated 2009. There is nothing better than a 6 year old answer to a common JavaScript problem.

</comment><comment><USER59> Check .gitignore to see if it appears copy and pasted or actually thought through--this will invariably indicate the quality of the rest of the code.

</comment><comment><USER60> I think this is what I refer to as SODD - or 'Stack Overflow Driven Development'. Somebody is not sure how to do something, so they look for an example on SO and they copy the code without really understanding what they're doing. (note: this is different to when they get an answer on SO and copy it knowing what they're doing).

</comment><comment><USER61> The author sometimes confuses the work "superstition" with "abstraction". That is how Humans work everywhere. And that is why my idle PC cannot create a Facebook/Twitter/or even a plain website by itself.

</comment><comment><USER62> If init scripts are mostly boilerplate that people keep copy-pasting, maybe the init process is the problem, rather than the poor chumps who have to write the scripts?

</comment><comment><USER63> What would be an example of good programming primary sources?

</comment><comment><USER64> Superstition...right I don't shave until a project is done and I have lucky underwear that I program in...

</comment><comment><USER65> I realized that the entire piece is hinged upon this incorrect assumption:

> _This isn 't something that we like to think about as programmers, because > we'd really rather believe that we're always working from scratch and only > writing the completely correct stuff that really has to be there;_

This is the issue I have with this article - the author assumes everyone works in exactly the same way they do and so are vulnerable in exactly the same way to their vulnerabilities. I don't know anyone who actually approaches programming in such a way that they think they're writing things from scratch and it's correct. I mean, defensive coding is a concept that has existed for decades that specifically addresses how incorrect the code we interact with is. The fact that I started coding in an environment where I had to manage memory myself and now I don't makes me very aware of the fact that everything I'm using is an abstraction built upon other abstractions.

I dunno, the day I learned to program in Intro to C and Intro to Computer Science, defensive coding, not trusting user input, and the completely understandable at the time weirdness of the guy who came before you have been stressed as things to pay attention to.

<comment><USER66> Usually when I'm writing code it is "Let's get the infrastructure up and come back to clean up after I know it works..." Sometimes I never come back. It doesn't mean I think the code is correct, only that it is not the biggest problem.

</comment></comment><comment><USER67> I think when I was very young and new to programming I sometimes did coding via superstition. But it was a long time ago, in say my first year or two, when I didn't yet have a good mental model of how the computer worked and how the language compiler or interpreters worked. Once you become solid at that I've found that 99.9999% of the time that computing is refeshingly rational and deterministic and amenable to logic.

</comment><comment><USER68> I am sorry, the only reason I have been as successful as I have been is because I am not superstitious at all. I know that if something goes wrong, there is always a logical explanation for it. The quicker I can find that logical explanation the better I am doing.

I don't think I am alone in this.

<comment><USER69> I often wish to have investigation classes. How to systematically reduce the search space in order to find meaning in explaining a phenomenon, good or bad.

</comment></comment><comment><USER70> It's true. All of my programs go from line 665 to 667. I've never made a commit on Friday the 13th, ever--and the one time I did it caused irretrievable data loss. Once I walked under a ladder, and it broke the build.

</comment><comment><USER71> Article: Reinvent the wheel, because if you just mount whatever wheels fit the axle they will inevitably work poorly for your purposes.

Wheels work just fine. Choose the best wheel from those available and tweak it as desired. Test it to make sure it doesn't shatter under too much weight. Apply and move on.

This pervading notion of "if you don't understand you shouldn't do it" is silly. Sure it is nice to understand, but it doesn't put food on the table. Sometimes it's just handy to use the gun as is and go shoot your dinner in the woods. You don't need to understand the formulation of gunpowder or rifling in order to use a gun properly for it's intended use.</comment>


Ask HN: Is implementation of encryption by WhatsApp reliable? - <AUTHOR> In the privacy fiasco of Zoom, I am looking for documentary proof of WhatsApp encryption implementation. I want a documentary evidence that WhatsApp encryption is poorly implemented or it is easier for Facebook to ferret out the conversations. )Please also recommend alternative secure messenger for healthcare) <comment><USER2> You can't be sure the app is secure unless it's audited by a third party, open source, and compiled by you. I believe there are a few alls with these qualities, but I don't know what they are.

There are messaging companies that specifically comply with health care laws, which is a separate issue entirely.

<comment><AUTHOR> Thanks and appreciated. Agreed.

</comment></comment><comment><USER3> WhatsApp uses Signal's encryption but it's hard to verify how much they changed. While signal provides a way to check that using cross-compiling reproducible build even for server code you can verify.

<comment><AUTHOR> I agree about it too. Isn't that Skype and other Microsoft products offer the same protocol?</comment></comment>


RubySource » Everything About Ruby On Rails Development and Database Programming - <AUTHOR> http://rubysource.com/ <comment><USER2> hi there!</comment>


Eureka Science news - automated science news aggregator startup - <AUTHOR> http://esciencenews.com

<comment><AUTHOR> My new startup - a news aggregator for science, akin to what Google News does but better as it also find and publishes related press releases directly on the site. Science is the first vertical we chose to use the platform we developed on, but we plan to adapt it for general news (if we can get funding to aggregate AP news for example) and other verticals. Comments / criticism welcome :)

</comment><comment><USER3> Is this an aggregator of press releases? If so, it's hardly science news: there is no critical thinking reviewing the results. It's more like science spin. At best, it's will be a good source of story tips for bloggers. I'm talking from experience as a science blogger. Please correct me if I'm wrong about your sources - I don't mean to offend.

Also, your name is very similar to an existing science "news" service from the American Academy for the Advancement of Science (the AAAS). They call theirs EurekAlert ( <http://www.eurekalert.org/> ), and the title of their home page is "EurekAlert - Science News". Because of this, you'll have a tough time ranking in the search engines since eurekalert.org is such an established site.

<comment><AUTHOR> It's indeed targeted at non-scientific people; bloggers, highschool students, etc. It`s a press release aggregator, but it also cluster news from other sites, giving more sources for each story.

However, the big plus is that it ranks stories in order of importance.

And as for search engine ranking, Eurekalert is a public non profit service, so they dont market much. Science daily use their press releases and is #1 for 'science news', even if its horrible in usability / design. Of course, we intend to change that ;) But we know the competition is fierce in this niche.

<comment><USER3> Have you seen PostGenomic and BPR3.org? They're doing something very interesting.

<comment><AUTHOR> Aware of PostGenomic (great initiative!), gonna check out BPR3 thanks for the link :)

</comment></comment></comment></comment><comment><USER4> Very nice... How did you do the clustering? Did you use an open source tool or build the algorithms yourself? I like the niche you picked - science news! Good luck.

<comment><AUTHOR> Clustering is a 2 part process - calculate scores, then cluster. For the second part we used an open source perl API to a C library (very fast) for hierarchical clustering : <http://search.cpan.org/~mdehoon/Algorithm- Cluster-1.38/>

I picked this niche because Im a scientist, mainly ;) I built the now #1 biology news website on the web (biologynews.net - #1 according to search engines) 3 years ago - Eureka Science News is the logical continuation of this effort.

</comment></comment><comment><USER5> This looks very nice, I like it a lot. How much work did it take to make this?

<comment><AUTHOR> Considering that I'm doing my PhD (Retrovirology, I work on AIDS - I'm posting from a level 3 bioconfinement lab right now ;)) and that I could work only part time on it, it took me about a year (working at night - <USER2> insomnia!). Much longer than I previously thought, but it required lots of tweaking to get good clusters along with good performance / scalability. Im very satisfied with the result and plan to adapt it to other news verticals as well as add functionality (comments, voting, etc) in the future. Glad that you like it! :)

<comment><USER5> Are you looking for help? I may be interested, and this is something that I've been working on, too.

Where are you located? Are you in the SF bay area?</comment></comment></comment>


The Tragedy of Given-When-Then - <AUTHOR> https://theitriskmanager.com/2019/04/06/the-tragedy-of-given-when-then/ <comment><USER2> Whereas:

> The reduction of the tester to an expert translator/typist is a tragedy

> The Given-When-Then detracts from understanding and readability but provides > the much prized automation through tools like Cucumber

> Instead of abstract domain models in Rational Rose

Now I see how we got into this situation. All this misery comes from the people who understand the code and the people who understand the business being different, non-intersecting groups of people.

Since the BAs can't read the code, there is a desire to construct a technical representation that they _can_ read, representing a some kind of formal specification, and then derive as much as possible the program from that. This was the promise of Rational Rose and the whole UML project. Had it been successful, it would have reduced programmers to stenographers, "coders" in a very limited sense. As it is, in a "Rational" system of this kind, coders end up producing increasingly elaborate polyfills between the machine-generated parts of the system and the rest.

The target of this is always the "5GL" dream:

         - specify program in English
         - ???
         - automated tools transform to code

.. without programmers involved. Unfortunately we've not managed to reduce the irreducible complexity of the step in the middle.

GWT does this de-skilling to _testers_ instead; it's effectively TDD with tests in this quasi-human-readable format that gets unimaginatively translated into programs by the testers.

The proposed solution is to do more communication through spreadsheet- prototypes. Since these are effectively programs in Excel, with all the real programming capabilities thereof, you get a real working model of the system that actually behaves like a program.

Many businesses simplify this process by then just deploying the spreadsheet to production.

(I'm not familiar with Cucumber, but it looks like a thing for constructing toy "human readable" DSLs for tests? I wonder if we could get BAs to learn INFORM?)

<comment><USER3> Im surprised you missed it.

Businesses solve this problem by hiring and training programmers in their business model and domain.

Coders, are worthless. Coders with business acumen and domain knowledge are invaluable.

This is also why I will never work with anyone with a job title of BA. They are trying to do my job but can only do one half of it. They're a pointless bottlekneck in the system.

And no, there is no place for BAs who can code only those who do. They're called software developers.

At this point I don't know if software engineer, developer, programmer or coder is really the right term any more.

I'm more of a systems analyst. The amount of time I spend coding is miniscule and I don't think I'm alone in this.

<comment><USER4> That's a bit inflammatory... My experience with BA's is that they're like anyone else on a team. They are more skilled in certain areas, and they can provide a lot of value if their skills are used appropriately.

I've found BA's are very useful in the following areas specifically

\- Communication with the market (either customers or in-market staff such as sales/support) to gather feedback about what they'd want

\- Orchestrating decisions (asking all the dozen stakeholders what they want to do and arriving at a sensible conclusing)

\- Arbitrating feature/UI decisions (people on the team aren't agreeing on whether we should do something or not)

\- Documenting requirements (by this I mean the desired functionality that we believe customers need/want)

\- Iterating and getting feedback on requirements

\- there's more, but off the top of my head that's all I can think of

Sure, I as a lead developer have business knowledge and can also do the job of business analysis, but a dedicated BA will be able to spend more time doing that - increasing their skills, and freeing up me to do other things. If I take on all of the above tasks in a decent-sized project, it's going to suck up a huge amount of my time - in many cases almost all of it - so then basically I'm just a BA with a different job title. BA's are great if you learn to understand the role and how it can help a team

<comment><USER3> All of those things are what a developer worth anything to a company should be doing.

Similarly, BAs without business domain knowledge are even more worthless because of this.

I.e. consultant BAs are, as most of us know, a waste of money.

BAs are struggling to find a language to describe their business requirements in a way the programmer or computer can understand.

It's code. It's what programmers have been writing all along. That is the god damn language they need.

Given when then? If then else.

Surprise!

<comment><USER5> Ricardo strikes again. Relative comparative advantage says even if a developer is a better coder and BA, they're better off spending time coding and letting non coders be BAs to maximize overall throughput.

<comment><USER3> This assumes a BA is cheaper and more available than a programmer.

If they are cheaper, I guarantee you're going to have problems.

You're literally installing a weak link in the most crucial part of the chain.

<comment><USER5> BAs are by definition more available than developers, as all developers are BAs but not vice versa.

And given basic supply and demand they are cheaper.

Anyway read your Ricardo, you're right but wrong about the implications. Your development is an even weaker link in the chain because good developers are even rarer than good BAs.

<comment><USER6> > BAs are by definition more available than developers, as all developers are > BAs but not vice versa.

Plenty of developers are _not_ BAs. BAs are systems analysts with expertise in requirements elicitation (basically, goal-directed interviewing) and technically writing. Plenty of developers are neither systems analysts _nor_ skilled at interviewing or technical writing.

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER7> The article seems to assume that it is, in fact, possible to completely and correctly specify a system, and not only that, do so ahead of development.

This is a pipe dream in all but a minuscule slice of software projects.

GWT/cucumber is as decent a tool as any for creating automated tests of system actions (and especially interactions) in a mostly-human-readable format that is likely to be understood by BAs, testers, and devs, even if not all of them are expected to be able to write them.

I've used them across many projects with great success, with the understanding that it's not intended to replace unit tests for calculations, nor stories for initial specification.

As endian says downthread[0]: ", G/W/T isn't the solution to domain understanding, conversations are. You should be continually communicating to between all stake holders to maintain a current domain understanding."

[0] [https://news.ycombinator.com/item?id=19674013](https://news.ycombinator.com/item?id=19674013)

<comment><USER8> It seems pretty obvious to me that any way to "completely and correctly specify a system" is going to look a hell of a lot like a programming language, and be no less complex or hard to understand than one... it's almost a tautology.

</comment></comment><comment><USER9> >Although Given-When-Then is a fantastic way to describe interactions, state and behaviour, it is a lousy way to describe data and calculations.

I follow a slightly different technique that I think makes given/when/then also a useful tool for describing data and calculations.

1) Write the test as follows, using _deliberately simplified but still realistic data_ (this is crucial):

>Given <a set of market data and trades in a table> >When <arbitrary event such as calculation is performed> >Then <leave blank>

2) Write the code that outputs the data/calculation.

3) Run the test in a "rewrite" mode that fills in the results of Then based upon actual output (this process is somewhat similar to golden master).

4) You now have a passing test and generated data which you can eyeball to see if it is in line with what you would expect. This test with recorded output can then be shown to the PO (or whomever) and committed to source control and used for regression testing.

This obviously isn't possible with cucumber or other gherkiny tools and it does require your processes to be fully deterministic (a laudable goal anyway), but it works pretty well IMHO.

<comment><USER10> That's a pretty common technique. The problem I've found is that it risks incorrect results be assumed correct. If I refactor your algorithm, and fix a bug in the process, I'll be very confused if your tests start failing.

The benefit of calculating it yourself first is obvious, you get to cross check your result. That tends to highlight minor errors such as -/\+ errors.

This is not a problem if stability is more important than correctness of course, but that's not where I am.

</comment></comment><comment><USER11> Act 1 - G/W/T can be used to express iteratively aspects of an algorithm such that you can derive it without knowing or fully understanding it (algorithm triangulation: think GPS where each satellite is a constraint and you derive through iteration of each passing scenario the general algorithm).

Act 2 - is really about process rather than G/W/T (which is really just AAA, arrange, act & assert).

Act 3 - again process, G/W/T isn't the solution to domain understanding, conversations are. You should be continually communicating to between all stake holders to maintain a current domain understanding.

We wrote an article recently on the limits of BDD [1], G/W/T didn't really come up, there are other more glaring issues with BDD when it comes to systems that intersect mismatched understandings of the real world between experts and users. Unrealistic wants and goals are killer. Additionally we started writing a tool to attach metadata to scenarios (G/W/T) so you can capture technical details about things called SpecStack [2]

[1] [https://endian.io/articles/limits-of- bdd/](https://endian.io/articles/limits-of-bdd/) [2] [https://github.com/endiangroup/specstack](https://github.com/endiangroup/specstack)

<comment><USER12> Hi Endian

Interesting article. I would be interested to see if feature injection ("Working Backwards") would help you. I do not think the first of the problems is a BDD problem, its more a "reality" issue. The only way to solve it is to use financial derivatives and I suspect the lack of liquidity in the crypto would make that prohibitively expensive.

Judging from your web-site, you are only 5 mins up the road from me. Would you be interested in a lunchtime session to see if FI would help?

Chris

</comment></comment><comment><USER13> G/W/T is great at capturing the context/action/outcome of a test scenario in English. It isn't great for all cases though. Furthermore Gherkin could be updated to allow more flexibility.

Having structured format for tests/requirements, in English (et. al.), can be _incredibly_ helpful. I would love to see some innovation around helping programmers and non-programmers reach a shared understanding of what the system should do and the cases we will use to verify it.

I don't think unstructured conversation, unstructured English, or Excel tables are the solution. This is still an unsolved problem in our industry.

<comment><USER12> Hi Ryan

How about structured excel sheets. Excel sheets with quide rails for business people to structure the expression of their thoughts?

That's what I'm getting at.

Chris

</comment></comment><comment><USER14> The main problem with cucumber / GWD is that in most implementations it serves as an opaque abstraction layer which is an incomplete/incorrect model abstraction of the system itself.

Been doing a lot of API testing recently with karate dsl and writing cucumber tests that include json expressions with some syntactical sugar for validation. The tests serve as a specification for the system which is actually quite a bit more precise than even swagger since you can even go back in time and compare the deltas on request/response between test executions to troubleshoot regressions.

Agree that GWT can't help business understand the inherently complexity of a state machine, but individual tests can be used effectively to model state transitions, especially at the api level.

</comment><comment><USER15> I think a lot of the issue is the misconception that G/W/T feature files can essentially replace specifications/requirements. They can and absolutely should REFLECT the requirements, but they are ill suited to act as the actual specifications themselves.

Feature files to me are most effective when they act as a roadmap of the steps one needs to take to effectively test a given set of use cases, NOT a 1-1 carbon copy of the requirements. It should tell a non-programmer what the test is doing without having to dive into the code, while being a scaffold to which a programmer can build their test logic into. If one needs to look at the requirements, one should do just that, read the requirements document, or in the developer's case, read the requirements set forth in the user story. Scenarios are guides to how to navigate what the test is doing, not what the application itself should be doing.

Also, I often see programmers attempt to write a BDD test and run into a case that doesn't quite fit flush into G/W/T, then ask the community of how they might go about writing that test. Instead of understanding flexibility, they are met with an abrupt "that's not BDD, you are doing it wrong, if you did it the BDD way everything would work out". That's discouraging, frustrating, and destructive. G/W/T is not gospel, and it doesn't fit all test cases. I see nothing wrong with fudging some tests to not follow Gherkin to-the-letter if it better facilitates a test while still remaining clear what the test is doing in plain English within the feature file's scenario.

</comment><comment><USER16> I can't agree more. I'm still to see a testing tool that can be used for specification and used by end users. Today everything is developer centric. Maybe there's no escape to this. The solution is really to make your developers understand the business.

<comment><USER11> Thats where things like Domain Driven Design are going, and really it makes a lot of sense. Why express and model your domain in terms outside of it? Its like forever living through a translator instead of just learning the language in the first instance, you add more points of potential failure.

<comment><USER17> Domain Drive Design is one of those things that seems so easy to write off as "just another process" but looking closer it seems like it really is a solid method for resolving issues of modeling, requirements, implementation and communicstion on a project.

I expect to see is continue to organically grow in popularity as people try it and adopt it. It's both obvious and insightful at the same time.

</comment></comment></comment><comment><USER18> > We will realise that describing data and calculations using the Given-When- > Then format leads to tragedy, and will create and popularise tools and > approaches using Excel to document examples.

Given all the examples given, it sounds more like Cucumber is the problem. Having specifications/tests written in the form of given-when-then isn't shown to have any issues. Rather, taking those specs/requirements and disconnecting them from the people who need them is the issue.

<comment><USER19> Is the complaint literally just about aligning the text in tables of a Cucumber file because business analysts are more comfortable in Excel? Or just managing the text of your test suite across a whole project? I am struggling to parse out the underlying point of the article.

<comment><USER20> What I understood is:

You are supposed to capture requirements in Given/When/Then form _before_ coding, and they should be written in a way that is independent of the implementation

The complaint seems to be that what happens in practice is "the devs have taken over" the system, so Cucumber just becomes a test automation software

This has led to writing tests in Given/When/Then format which test overly specific elements of the implementation, and are often written _after the fact_ , instead of as a way to capture requirements.

And some other stuff, but that's primarily what I got out of it.

<comment><USER21> > _the devs have taken over [authoring tests]_

That's what happened in the projects where I used fitnesse, jbehave, cucumber, etc. The users couldn't understand the artifacts and what they're supposed to do, and the tools were highly idiosyncratic. It ended in becoming just yet another hassle for developers.

<comment><USER12> Exactly.

Whereas using Excel for specification of calculations (by Business Users or Business Analysts) actually brings the business and developers closer together, removing the need for intermediaries. Business Users are very happy using Excel and checking calculations etc. as it tends to be their home environment.

</comment></comment></comment></comment></comment><comment><USER22> _A common anti-pattern with Given-When-Then has the Three Amigoes collaborating on scenarios that are stored as acceptance criteria in user stories._

I agree with this. Writing Cucumber/Gherkin scenarios is extra effort if the Cucumber files themselves aren't used/read elsewhere. -- It'd be simpler to embed "Given/When/Then" statements within test code (like RSpec).

I'd emphasise that Gojko Adzic's "Specification By Example" suggests discussing examples before refining to a specification; that may get around the author's complaint that non-table formats don't allow for important cases.

That said, "Given/When/Then" is hardly magical, so doesn't deserve much praise/criticism itself. Any test involves "do an action, check the result" (with "setup the system" and "cleanup" being implied). Sometimes called "Assemble, Act, Assert". "G/W/T" is just a neat, consistent format for describing behaviour in English. A table of values specifies some computation; the column titles help to describe that behaviour.

<comment><USER23> You can embed G/W/T into RSpec. There's a library called Turnip[0], a play on Cucumber, that extends the syntax to Feature tests in RSpec.

\- [0] [https://github.com/jnicklas/turnip](https://github.com/jnicklas/turnip)

The reason RSpec didn't include this originally probably stems from the library being designed for testing at the class or module level, rather than an entire application.

</comment></comment><comment><USER24> This is why I like Spock [0]. You can go G/W/T/, W/T, T, or Expect [1]. It's billed as "multi-paradigm" which really just means you can do whatever feels right for a given case. Also its data table feature is wonderful [2][3].

[0]: [http://spockframework.org/](http://spockframework.org/)

[1]: [http://spockframework.org/spock/docs/1.3/spock_primer.html#_...](http://spockframework.org/spock/docs/1.3/spock_primer.html#_blocks)

[2]: [http://spockframework.org/spock/docs/1.3/data_driven_testing...](http://spockframework.org/spock/docs/1.3/data_driven_testing.html)

[3]: [https://twitter.com/dminkovsky/status/1116727735399976966](https://twitter.com/dminkovsky/status/1116727735399976966)

<comment><USER25> > you can do whatever feels right for a given case

Too bad you can't use whatever specification language feels right. Spock only provides Apache Groovy, with its tacky syntax hacks like long strings for function names, block labels having special meanings based on their name, or the OR and LOR operators being used for drawing tables in the code. In the past when software has provided Groovy for writing specs, they eventually provide an alternative when Groovy's shortfalls become obvious, e.g. Kotlin for Gradle [1], or the Declarative Pipeline Syntax [2] for Jenkins.

[1]: [https://docs.gradle.org/5.0/userguide/kotlin_dsl.html](https://docs.gradle.org/5.0/userguide/kotlin_dsl.html)

[2]: [https://jenkins.io/blog/2016/12/19/declarative-pipeline- beta](https://jenkins.io/blog/2016/12/19/declarative-pipeline-beta)

<comment><USER26> > Groovy, with its tacky syntax hacks like long strings for function names

Actually, Kotlin does that too. I think it is even encouraged for writing tests.

</comment></comment></comment><comment><USER27> This article would have been better if at some point it explained what Given- When-Then is.

<comment><USER28> That would have gotten in the way of making wild generalizations about what Developers & BAs do.

</comment></comment><comment><USER29> >Before the internet, user experience was considered of little value because most users of systems were internal employees of companies.

I'm skeptical of this claim. It would help if there were a year, considering it's not clear if the author means the modern Internet, the ARPANET, or when the modern Internet became widely available to a larger group of people. Based on the mentions of Excel, I'm inclined to believe it's the last option I listed.

The MIT AI lab and other research areas come to mind as places that cared about how the programs were operated and whatnot and these weren't exclusively used by employees. SHRDLU comes to mind. While I'm thinking about it, the Apple Macintosh also does.

I don't believe I was familiar with this Given-When-Then model beforehand, but I also think that's because it's somewhat natural, or at least seems natural. The author has failed to convince me why this is a bad thing. I suppose I can see why these larger business practices are poor, but that has me failing to see why this particular practice is singled out.

</comment><comment><USER30> Yeah; I suspect the core of the problem is that too many software developers fancy themselves business analysts while too many business analysts start to cower in fear whenever you suggest they check something in to GitHub.

<comment><USER13> When I teach BDD classes I sometimes joke that we might not need acceptance tests written in G/W/T if the biz people could read programmer tests.

</comment></comment><comment><USER31> You might want to check out Fit as a testing framework that may be more appropriate for your use case than Cucumber. Not sure if it's still well maintained, but it could be brought up to speed without much effort.

</comment><comment><USER32> To;Dr, given-when-then can sometimes obscure requirements rather than illuminate them. Use Excel or other tools to document such scenarios, as everyone in the software design process can understand Excel formulas.

<comment><USER19> Why would moving a table from The Place All The Other Requirements Are Kept to an Excel file stored elsewhere do anything other than obscure requirements?

</comment></comment><comment><USER33> I think there's a lot of people down on cucumber after experience with it, in several different contexts... what do you think, what has been your experience?

<comment><USER34> The dream of having the requirements be the test is not realistic:

* Good luck telling your PM their English has a syntax error

* Once that's out the window and the cucumber files are just maintained by devs, is the regex translation layer worth it?

* A lot of implicit state also gets wrapped up in the test in making these phrases at least semi-readable, which makes for a pain debugging failures.

<comment><USER35> You can also enter Cucumber-developer double jeopardy where you need to meet with the PM for an hour to write Cucumber specs, and then meet with the QA for an hour to implement them.

When you could have just written a simple integration test in 15 minutes, but the Scrum master thought Cucumber would be a good idea.

</comment></comment></comment><comment><USER36> > The discussion helped me realise that Given-When-Then is as much of a > hindrance in some contexts as it is a help in other contexts.

I like when authors express a strong viewpoint but then also include descriptions of circumstances where their viewpoint may not be applicable. This seems to be alluded in the above quote, but are there specific contexts where Given-When-Then _is_ helpful and the appropriate mechanism to document requirements?

<comment><USER22> I think rspec's Cucumber docs are fine. [https://relishapp.com/rspec/rspec- expectations/v/3-8/docs/bu...](https://relishapp.com/rspec/rspec- expectations/v/3-8/docs/built-in-matchers/equality-matchers)

It's an executable specification, but it's also in a format which is readable. If not "documentation", then it's at least "small, verified examples".

I'd find a table of values less readable. I don't mind if a document like this is the output of running the tests themselves, though. (Obviously, the important details are "input program, expected output", which might not lead you to use Cucumber, but I think it's a fine use of Cucumber).

</comment></comment><comment><USER37> That is pretty much the core of software engineering, I'd call it Data-If-Then and I fail to see why this is a tragedy.

<comment><USER38> I think that is the tragedy that the article covers. Described as a scenario where the engineering has ended up squeezed into the business analysis and there isn't good communication between there are the development which are seen as implementers.

This doesn't feel familiar to me but I've tended to always work in legacy systems where the opposite problem (no BA at all) is a more familiar problem.

</comment></comment><comment><USER39> What ever happened to Systems Analysts?

</comment><comment><USER40> arcfide has claimed on several occasions that non-programmers take to APL quite easily, and can read and collaborate on it with a programmer, be talked through it directly, in a way they can't/won't do for mainstream languages.

I find this such an unlikely sounding claim that I want to reject it without consideration, or at least assume that he's only talking to a very restricted subset of engineering non-programmers.

APL is decades old and very much a business language by origin in IBM System 360, there ought to be decades of people's experience with this on both sides to back it up or refute it - programmer and non-programmer. Is there?

</comment><comment><USER41> It's a fallacy that GWT has to be at the browser automation level. And it's a lot easier to understand the point of a test if it's got GWT comments interspersed with the code.</comment>


How Free Explains Israel's Flotilla Fail - <AUTHOR> http://www.wired.com/dangerroom/2010/06/how-free-explains-israels-flotilla-fiasco/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+wired%2Findex+%28Wired%3A+Index+3+%28Top+Stories+2%29%29&utm_content=Google+Feedfetcher

<comment><USER2> It cost the flotilla more than ten human lives. That's not free.

</comment><comment><USER3> _The asymmetry in money spent and effect achieved between the two sides is staggering. Call it the # sign versus the $ sign. The flotilla organizers spent almost nothing and won the day; Israel spent huge amounts of money and ended up with egg on its face._

If you don't find this incredibly fascinating and inspiring, you're in the wrong business. Hell, the wrong world-line.

Cory Doctorow welcomes you to his capital-F Future.</comment>