When the shunting person persuaded everyone to imagine the two-car units as if they were symmetrical, the passengers still complained. Toilets can break, and when they did the doubly unlucky passenger would be forced to walk four car lengths to get to the nearest toilet.
Also, those helpful arrows would be guiding the passenger the wrong direction for two of those car lengths.
So we have comments that go out of sync with the running program, a spec that lies about reality, and an implementation that doesn't match the spec. Yep, that sounds like programmers to me.
Legit parable.
Edit: just realized the least lucky passenger would have to walk six car lengths. If the passenger is already at the wrong end of the "symmetrical" two-car unit with a broken toilet, the arrow will point them in the direction of the broken toilet. If the broken toilet is the last car, then they must walk back two car lengths to get where they started. Now if the next two-car unit is turned the wrong direction they must walk two more car lengths.
So add to this a spec that's difficult to reason about.
> the least lucky passenger would have to walk six car lengths
I just want to elaborate on this to show which assumptions you are making. There are two ways to make a paired unit:
--+ and -+-.
In your scenario I think you assume the first. The end of the train is thus ...+----+, since you mention the second last car's orientation being reversed. The +'s represent toilets. Then, what you are saying is to consider a passenger located at the ^ symbol: ...+--^--+. In this configuration, your observation makes sense.
I do think that a more practical solution is to work only with (-+,-) pairs. The symmetry that Dijkstra talks of is then that (-+,-) and (-,+-) are equivalent for the purposes of the problem. Then an end of a train would be: ...-+-+-. This is then the "extra few feet" that he talks of.
Indeed. Dijkstra specifies two cars joined with the toilet in the middle:
"When each car with a toilet was coupled, from now until eternity, at its toileted end with a car without a toilet, from then onwards the shunting yard, instead of dealing with N directed cars of two types, could deal with N/2 identical units that, to all intents and purposes, could be regarded as symmetrical."
I think what bothers me about this is that it's an analogy which crosses the digital divide.
On the physical "train" side of the analogy, we've got a believable scheme to save money by only having a toilet in every other car. Given the constraints, it is indeed clever to make these two-car atomic units and reimagine them as symmetrical. All the fixes in the story taken together could pale in comparison to the cost of putting a toilets all the cars.
But when we cross the digital divide we get a completely different set of constraints. Even if dealing with 100 million train cars it may be cheaper to just fork the entire train yard and add a toilet object to each car.
> I just want to elaborate on this to show which assumptions you are making. There are two ways to make a paired unit: --+ and -+-.
Why are there three characters to represent a pair?
Do you mean something like this:
car with toilet: [+-]
car without toilet: [--]
my pair: [+-][--]
your pair: [-+][--]
?
> This is then the "extra few feet" that he talks of.
Using my notation (sorry to flip it):
[-+][--][-+][--]
That's four cars. If someone is sitting at the right end of car #2, they have an arrow pointing them to car #1 for the toilet. If that toilet is broken, then they must walk back through car #2 all the way to the end of car #3.
But I may be misunderstanding your initial notation.
Your bracket notation in effect works the same as mine. The difference is that -+- could be any of [-+][--] or [--][+-] by symmetry and so leaving out brackets. In my notation "+" is a character which does not occupy space. Hence [-+][--][-+][--] is the same as -+--+-.
Sorry about the error earlier: "...-+-+-" was a typo that I couldn't edit anymore.
Yes, though I think the last three feet refers to the vestibule connecting the two carriages, which a passenger in the non-toilet carriage must traverse.
I learned this stuff from Roland's 'Program Construction'. Great book. Once you've been through that, then suddenly Dijkstra's writing becomes really practical.
I feel like the actual moral of the story should be "don't underestimate how trying to scrimp on a vital resource can result in horrible logistical complexities and a nightmare UX".
All true, but I would add that "in order to get back to the previous system that actually worked, you may have to provide a fig leaf for management, so that they can pretend no such thing is happening." We are back to one toilet per car, but we have to use cars of twice the size (with superfluous coupling in the middle that is never uncoupled) in order to pretend that we did not go back to the original system.
Also, note how the shunting department was severely underequipped, "and it was only by virtue of the most cunning ingenuity, that they could just manage". Also sounds very realistic to me.
That, plus a manager inventing and enforcing specific requirements for dubious reasons, causing trouble in the company, and - as 'jancsika points out in their comment - quite likely introducing many new problems into the product.
Nah, it'd be more realistic if they were stuck with this expensive mess, and had to reverse all their work, and still had to do one toilet per car, because no one figured out this solution.
And the one guy who would have thought of this, they passed on three months before because he wanted 10% more in salary.
The final paragraph is my favorite. I have a PhD in mathematics but I've since realized I'm not a mathematician, I'm more of a logician/philosopher. I find the parable very interesting, but I can totally believe a lot of real mathematicians don't. Too many mathematicians, if you crack open a random page of their work, you'll see lots of opaque integrals and calculations. None of that ever appealed to me. Even when I was the top of the class among undergraduate mathematics majors, I was basically doing the bare minimum I could get away with of that kind of "grind", and focusing all my time and passion on things more closely resembling this kind of "parable".
I don't think he was saying mathematicians don't find it interesting because it lacks sufficiently convoluted mathematics.
Rather a 'true mathematician' (who by definition ignores all practical considerations) would find it unsatisfactory because the problem of finding a way of allowing toilet-less carriages is solved by not allowing toilet-less carriages.
Frankly I think they should have just put the toilet in the middle of the toilet-carrying carriages, but maybe I'm weird.
So in the end the permanently coupled tuple of cars is handled as a single car, it kind of proves that every car must have a toilet? Or perhaps the next manager reiterates the rationale and decides to put just one toilet every two car tuples...
For me, one moral of the story is when approaching any issue in a live system, it often pays to go back to modeling the actual problem instead of iterating on broken assumptions. Good solutions should have documentation which explains their take on the problem and the reason the solution in particular was chosen versus other potential designs.
Of course, outsourcing, interdepartmental or interpersonal politics can create commercial misincentives to remove such time and money saving features...
I feel like that's still the point irrespective of Dijkstra's apparent view on the parable. Creating exceptional cases is the best way to increase costs.
Yea, that's where I thought it was going too. I've been on a lot of project lately that try to pre-optimize instead of building a solution and then determining where the bottlenecks are.
A lot of times when we try to build for speed, the real bottlenecks are no where we think they'd logically be.
There's politics involved as well. The solution creates units that all have toilets without countermanding the commercial directors initial edict.
Programmers sometimes have to triangulate too.
With the end solution, a passenger is only one car length from a toilet (which would be the case if toilets are at the end of cars for structural reasons anyway) and they only pay for toilets in half of the cars.
Is Haskell still a preferred introductory language to enter the Functional Paradigm with? Or do you think other alternatives do a better job at that than Haskell ? I'm learning Scheme with the SICP Book ATM, and am confused where to go next to get better at Functional thinking(and programming).
> Is Haskell still a preferred introductory language to enter the Functional Paradigm with?
I say yes, for a two reasons. 1) Enforced purity means you can't just fall back to your old imperative style as coding and use it as a crutch, and 2) it's the "most different" functional language, it will expose you to more than just functional programming and thus teach you more.
Learning Haskell will teach you: pure functional programming, algebraic datatypes, laziness, and ML-style types. All of which are worthwhile imo.
ML-style typing and algebraic datatypes you could also learn in F#/Ocaml/SML, but pure FP and laziness are two things that are very much worth learning and only apply to a handful of languages. And of that handful Haskell is really the only one with an ecosystem and community that makes it practical to write actual projects in.
Note that the arrow solution failed because to the shunting yard the cars were immutable objects. They could only control the direction of the arrows in the non-toilet cars by how they oriented the whole car when they composed it into the train they were building.
If the non-toilet cars were made mutable, specifically if they were made so the arrows could be reversed, then the shunting yard could compose the cars without regard for the orientation of the non-toilet cars, and someone later could go through and set the arrow directions. I'd guess there is some sort of preload inspection done by the crew, which might be a good place to handle setting the arrows.
> I have told the above story to different audiences. Programmers, as a rule, are delighted by it, and managers, invariably, get more and more annoyed as the story progresses; true mathematicians, however, fail to see the point.
I see the point. In fact I'd go so far as to call myself "delighted". But I thought I was a true mathematician.
'Scuse me while I go have a little existential crisis.
I guess the ultimate solution assumes that all the turntables are long enough to deal with at least two-car consists? Seems strange that the company would cheap out on a little bit of porcelain in each car and then overprovision its turntables in such an extravagant way.
With the toilet at the end of the carriage that is connected to its corresponding non-toilet carriage, and consequently approximately in the middle (the offset is the "last three feet" that Dijkstra mentions), there is no longer a need to reverse any two-carriage set.
Turntables are not just for reversing. A turntable also moves cars (and engines) between multiple tracks and storage facilities. Two-car sets need to be moved even if not reversed.
You can do that with tracks and switches - in fact, you can also reverse rolling stock with a 'Wye'. I believe turntables were mostly used to reverse steam locomotive - tender sets, and to build engine sheds in constricted urban areas where there wasn't a lot of room for a switch network.
I thought that originally as well. However I'm not sure that the cars both need to be on the turn table to remain paired. If cars #45 and #44 are paired, can we repeat the turntable operation to keep them oriented in the same way without needing to generically solve the problem of car orientation?
TGV trains in France have a very strict structure. For the TGV atlantique lines, for example, "short" trains contain exactly 10 cars (and "long" trains are composed of two "short" trains), with the following distribution:
- Car 1 and 10 are engines, and include some second class seats.
- Cars 2 and 3 are first class.
- Car 4 is the bar-restaurant.
- Car 5 is first class.
- Cars 6, 7, 8 and 9 are second class.
All the infrastructure is designed to treat the train as a single unit, during all operations at the shunting yard, in repair workshops, and son on.
And the position of toilets (including special toilets for nappy changes) is fixed.
This seems like it has potential for being the core of an interesting interview question. Maybe something along the lines of "You are hired as the Chief Shunter (lol) of a new rail company and the CEO, to cut costs, has stated that only half of all cars will have toilets. What instructions will you give the shunters? What complications could arise? What is the optimal solution and how would it impact UX?" etc. etc.
Rolling stock needs maintenance, and if you keep units permanently paired you can easily run out of units.
In fact there is no easy solution given realistic business constraints. You can either put toilets in every car, which has a cost because it reduces available seating. In the best case you’ll lose money because of the lost seats. In the worst case overcrowding will make the toilets ineffective.
Or you can buy enough spare units to allow for maintenance, which has a larger up front cost, and continuing costs in terms of stabling, and possible issues with shunting yard size.
Working out the most efficient answer given real trains, real passenger loads, likely future passenger loads, and shunting yard constraints, is not a trivial problem.
Unlike Dijkstra, some of the managers in his audiences will have understood this. It’s no wonder they found his glib hand-waving annoying.
The actual lesson of the parable is the opposite of the one Dijkstra is making: the real world is hard, and if you think a solution fits neatly into a trivial software construct, you’re almost certainly wrong.
It's a parable which means it is fiction that that ignores details to make a point. As such it does it's job quite well unless you yet to read more into it than the author intended.
To me this says that parables are fairly useless: with enough padding any trivial insight may seem wise. I can't at the moment imagine something that I would think important to communicate which would be made more clear by a parable. I would also be concerned about being patronizing. I'm sure this makes good fodder for academic quibbling, but I am beginning to doubt whether Dijkstra was more insightful than arrogant.
It's like the joke with boiling the pot of water and just dumping out the water; reducing it to the previous problem with a known solution ... or something like that...
>With growing size or sophistication of the program, the operational argument quickly becomes impossible to carry through, and the general adherence to operational reasoning has to be considered one of the main causes of the persistence of the software crisis.
What "software crisis"? Since its inception in the 50s or so, software has only gone from strength to strength.
1) we don't get increasingly bigger and more powerful systems
2) we're behind some previously existing "no crisis" state
Both (1) and (2) are factually wrong.
Projects running over-budge, over-time, often not meet requirements etc, are not a crisis in the actual meaning of the world.
It's just a normal state of affairs.
And despite that we have got from the laughingly primitive software in the 50s and 60s, to the software "eating the world" today, and have systems with 10 to 100 or 1000 more lines of code, and way more functionality -- even in our pockets.
If only "crisis" looked that way in other domains too.
It's not a crisis, it's just unrealistic expectations.
Even if we could do 100x better in the _future_, it wouldn't justify the term crisis for the state we're in, and have been for decades.
You are factually wrong because you know only the status quo that emerged from that crisis.
> Projects running over-budge, over-time, often not meet requirements etc, are not a crisis in the actual meaning of the world.
> It's just a normal state of affairs.
To you it is.
To the people in the 1960s, it wasn't.
Because they had previously experienced a state where the hardware imposed such drastical limits on the possible size and complexity of software that each programmer working on a project could intimately know and understand every piece of code in it and the requirements that influenced it.
The change from that to one where programmers understand only part of a project is absolutely fundamental and completely changes the way you have to work to achieve your goals. Now your project will fail if you cannot manage and divide-and-conquer its complexity in some way.
Since we're talking about Dijkstra, thought I'd bring up the letter he wrote to the University of Texas when they replaced Haskell with Java in their introductory programming course:
I absolutely adore Djikstra's stubborn and always eloquent insistence on rigor and purity in CS education, his unabashed refusal to see even one tendril of its mathematical connections be sacrificed for mere code production efficiency. If this case isn't going to be made at the university level, then where?
I agree with you! Something I've wondered, though, is how he would propose writing a formal specification for, say, a graphical application. Does anyone know?
One thing I noticed even decades ago when I was in school is that the education system - from kindergarten up until grad school - encourages "bare minimum" thinking. The goal is an A - if you happen to learn something en route to getting that A, great, but the goal is an A. Everything about the way things are structured encourages you to find the path of least resistance to that A. Now that I'm (much) older, I'm going back and trying to re-learn the things that I learned just enough to get by when I was in college, I wonder - if the curriculum had been more "rigorous", would I have learned more, or would I have been washed out?
GPA and class rankings do seem to be counterproductive measures if you're trying to get people to challenge themselves. The classes I got the most out of are the ones I got B's and C's in, or even had to redo in one case.
It definitely makes more sense if you look at the idea of the "sheepskin effect" where the degree is not a signifier of material mastered, but a signifier that you are a good worker. In that case, what you learn is generally far less important than whether you work well on a team. And a high GPA means you are orderly, methodical and conscientious.
It seems like college taught you "how to learn", which I think is way more important that learning Haskell vs Java, etc., especially in a field as ever changing as Comp Sci.
I don't know how many decades ago you were in school, but imagine all those people who were "rigorous" with learning punch cards in 80s in depth, at the expense of getting a wider education...
That's pretty reductive. Rigorous learning in the punch card era would have involved a lot of programming on paper, which requires you to understand the program you are writing in a more comprehensive way than does trial and error. There's a discipline to that type of work that lends itself more naturally slowing down and to thinking about architecture.
Also, while software engineering changes frequently, I'm not convinced that computer science is changing rapidly. It's expanding, but it's not as if fundamental computer science concepts are being rendered obsolete.
Great letter (2001). It predictably focuses on language quality and side-steps practicality-- the assumption being practicality isn't as important as learning a high-quality language in an introductory course.
> A very practical reason for preferring functional programming in a freshman course is that most students already have a certain familiarity with imperative programming. Facing them with the novelty of functional programming immediately drives home the message that there is more to programming than they thought.
While later on, he does gripe about language quality, I think this is the most salient point of that letter. It touches upon IMO one of the most misunderstood things about Computer Science- it's a science curriculum, not a vocational school. The best (only?) way to build practical skills is doing practical things and learning through experience. Computer Science is more about rigorous reasoning about programs and their mathematical properties.
While learning about practical things like building web apps is fine and well, universities are not well equipped for this sort of vocational curriculum. They are primarily institutions optimized for performing scientific research.
> it's a science curriculum, not a vocational school
I griped about this to my CS/SE professors until my senior year of college, when I finally understood why they were teaching us all these weird languages and styles instead of the C/C++ that I assumed everybody used at the time: Programming languages come and go - hell, entire platforms come and go - but the underlying concepts (and the ability to teach oneself) are forever. I haven't written a single line of C/C++ professionally, but thank goodness I have the mental tools necessary to pick up all the different programming languages, libraries, protocols, etc. I did end up using.
In a sense, those two are not conflicting, but reinforcing - practicality in software "engineering" usually means lowest-common-denominator, cheapest-workforce technology. It's good to have exposure to more powerful tools and ways of thinking, and the industry isn't likely to give you one unless you actively come looking.
Depends on what you think you're teaching. Are you teaching computer science, or are you teaching software engineering?
Hint: Of your graduates, probably 95% will work as software engineers, and only 5% will be computer scientists. But CS departments think they're computer science departments, even though they mostly are located in the college of engineering. (I accidentally typed "enginerring", which I thought was amusing...)
> Depends on what you think you're teaching. Are you teaching computer science, or are you teaching software engineering?
> But CS departments think they're computer science departments, even though they mostly are located in the college of engineering.
I used to think this is true in the form you presented, but now I feel it's really a more relaxed form that's true - CS departments in universities think they're still in universities, not in glorified vocational schools. They try to teach you more than the immediate needs of your likely job, so that you understand the context of what you're working with, and are exposed to more powerful ways of thinking.
(I mean, 99% of the time, your typical JavaScript-slinger doesn't need to know what an "algorithm" is and what can be solved with one. These days, a popular language, StackOverflow and open-source libraries are enough to do acceptable levels of work. However, some extra theoretical knowledge will help tackle more complicated problems, solve them better, and will enable one to do something more challenging if they want to leave the web/CRUDsphere.)
Related: we now have "vocational schools" for programming too. They're called "bootcamps", for some reason.
Tangential: there's a feedback loop between workers, universities and employees in every industry. Progress of the "industry standard" must come from somewhere. If all the new people are being exposed to is Java(Script), the industry will forever keep being stuck on Java(Script). So I feel it's good that at least some people in some universities try to teach above the level required by the industry.
> Related: we now have "vocational schools" for programming too. They're called "bootcamps", for some reason.
Bootcamps are a joke. Germany has had proper vocational schools for programmers for decades. After high school, you can spend three years to become a Fachinformatiker (it's difficult to translate, but basically means "applied computer specialist"). There are two subflavors, Anwendungsentwicklung (application developer) and Systemintegration (systems integrator, this curriculum combines sysadmin and development tasks).
All that is entirely separate from CS courses at university, which is an alternate path that one can take (and one that has a higher entry barrier since you need to have at least 8 years in secondary education, i.e. until 12th or 13th grade). In the vocational training, you alternate between weeks at school and weeks at your employer where you work on actual projects under supervision of a qualified mentor.
In Finland we have three tiers of formal programming education. There's vocational secondary school awarding "technician" level degrees, an alternative to more academic Gymnasium type secondary education (grades 10 to 12). The learning is very hands-on and practicality oriented.
Then there's "vocational" or "applied science" colleges you can enrol in after either vocational or academic secondary school. They offer four-year bachelor-level degree programs in various fields from healthcare to engineering. The education attempts to mix theory and practice (with varying success).
Finally there's the "real" universities, offering primarily five-to-seven-year BSc+MSc programs (before the Bologna Process you used to go straight to master's; these days the steps are somewhat more discrete), and of course PhD programs for those wishing to pursue an even higher level of education.
The real problem here in the US is that we have gotten away from tracking students at all levels, and we were never even doing it much compared with most of Europe or Asia to begin with. It's dragging down the whole system. But I don't want to totally derail this thread, so I'll just leave it there.
US has lots of its specific problems, but here we're really talking about an issue which affects universities worldwide almost universally - that university degrees became a differentiator on the job market. The vast majority of undergrads these days are not seeking advanced education or trying to push the state of the art forward - they attend universities to get a piece of paper and some skills that'll land them a better job. As universities compete for students and are (indirectly) graded by how well they prepare them for jobs, a feedback loop has formed that slowly but surely turns undergraduate education into vocational one, usually to great dismay of the professors.
> They try to teach you more than the immediate needs of your likely job
I would actually take that even one step further - they specifically teach you the things that you're probably not going to encounter in your likely job. I've lost count of how many people I see complain that they never encountered SQL, version control or build management while in school and my response is - that's a good thing! You're going to learn all you need to know about those things when you need them, and they're veryamenable to learning on the job, a little bit at a time. Calculus, statistics, push-down automata, context-free grammars, and all the other "esoteric" stuff you encounter in a CS degree are not.
Software engineers should know and start from Computer Science, why not ? Mechanical and Electrical engineers have to learn Physics, Control dynamics and Differential equations the first couple of years.
I have some university degrees in (non-software) engineering. Engineering school is pretty far from a vocational program, but engineering students often mistake it for one. When I was in industry, it was easy to spot the people who'd made that mistake -- they couldn't engineer their way out of a wet paper bag. Engineering is applied science, and if you don't understand the science, you're going to have a heck of a time trying to apply it. The difference between engineers and scientists is that scientists know how to make new science, and engineers know how to make new things using science.
Yes, exactly. Chemical engineers needs to know chemistry, but they need to know more. They need to know "how do we make this stuff, efficiently, at scale, without blowing up the plant." They're not going to get that from the chemistry department.
So, does a software engineer need to know some computer science? Absolutely, but they need to know more than that. They need to know how to efficiently produce working software at scale.
And, to return to my previous post, starting with Haskell could still get you to a software engineering education, as opposed to a computer science education. But it feels to me like the initial direction is aiming at a CS education, not at a software engineering education.
Also, those helpful arrows would be guiding the passenger the wrong direction for two of those car lengths.
So we have comments that go out of sync with the running program, a spec that lies about reality, and an implementation that doesn't match the spec. Yep, that sounds like programmers to me.
Legit parable.
Edit: just realized the least lucky passenger would have to walk six car lengths. If the passenger is already at the wrong end of the "symmetrical" two-car unit with a broken toilet, the arrow will point them in the direction of the broken toilet. If the broken toilet is the last car, then they must walk back two car lengths to get where they started. Now if the next two-car unit is turned the wrong direction they must walk two more car lengths.
So add to this a spec that's difficult to reason about.
Again, legit programmer parable.