My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger.
https://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/E...
Except I think people have often overly focused on "lines of code" as the unit for this metric, leading many to overrate terse code, even when it is very dense.
But I'm not sure what wording would capture this idea succinctly enough to include it in a pithy quote.
APL (and it's many cousins) is a bridge too far for me, but I can see the appeal to having the entire program on a single screen.
In one short letter he makes an insightful critique yet misses the the point so hard I can practically hear the woosh 42 years later.
It's funny that you used Go as an example. Like 60% of its raison d'être is noticing that more lines of code is often better if each line is simple. And I think it's mostly right about that. Its inscrutable naming conventions are, on the other hand, a poor choice. (Notwithstanding that java's are a poor choice in the opposite direction.)
The phrase "considered harmful" has become a meme and is the go-to phrase (pun intended) for essayists looking to criticise some aspect of computing
https://www.cs.utexas.edu/users/EWD/transcriptions/EWD12xx/E... "I must confess that I was very slow on appreciating LISP’s merits. My first introduction was via a paper that defined the semantics of LISP in terms of LISP, I did not see how that could make sense, I rejected the paper and LISP with it."
For example in a language without GOTO inside an if statement the guarding condition is known to be a predicate (at least until another operation changes it) whereas in a language with unrestricted GOTO there is no guarantee whatsoever that the guard holds since execution could have jumped past it.
"At the I F I P Congress in 1971 I had the pleasure of meeting Dr. Eiichi Goto of Japan, who cheerfully complained that he was always being eliminated."
"For many years, the go to statement has been troublesome in the definition of correctness proofs and language semantics....Just recently, however, Hoare has shown that there is, in fact, a rather simple way to give an axiomatic definition of go to statements; indeed, he wishes quite frankly that it hadn't been quite so simple."
I cannot find anything written by Hoare about it, but Knuth goes on to describe it: the idea is that labels have associated preconditions and GOTOs have the semantics { precondition(L) } goto L { false }.
"Informally, a(L) [my "precondition(L)"] represents the desired state of affairs at label L; this definition says essentially that a program is correct if a(L) holds at L and before all "go to L" statements, and that control never "falls through" a go to statement to the following text. Stating the assertions a(L) is analogous to formulating loop invariants. Thus, it is not difficult to deal formally with tortuous program structure if it turns out to be necessary; all we need to know is the "meaning" of each label."
It is a very nice paper. Some sources:
http://www.kohala.com/start/papers.others/knuth.dec74.html
Thanks for sharing that paper! As an aside, it's really remarkable just how readable the state of the art papers such as the one you shared there from that era are. Either computing science has greatly advanced to the point where clarity is no longer achievable without years of specialized preparatory study or the quality of writing has regressed.
"I don't know how many of you have ever met Dijkstra, but you probably know that arrogance in computer science is measured in nano-Dijkstras"
Which, I dunno, feels kind of funny coming from him of all people.
The problem is not that he self-aggrandizes or is boastful; it's that he keeps tearing other people down. And that he was very willing to offer sweeping pronouncements on matters that he had no practical experience in. He basically stopped touching computers in the early 1970s, and certainly stopped writing practical programs. What basis then, did he have for dismissing object oriented programming, which for all its flaws has done decidedly more for human progress than program verification has?
And as the tense exchange with Backus shows, he was quick to dismiss the relevance of functional programming, which certainly has done a lot for the kind of mathematical reasoning he advocates for programming (Apparently he taught his students Haskell later. Did he ever apologize to Backus for his wrong headed initial assessment?).
Would computer science miss ANYTHING relevant if he had stopped working in the field in 1975? His output basically consisted of proving propositions over cherry picked toy problems. I don't think anybody doubts that this is possible, but is this a viable approach to build real systems (not only large ones, but also ones whose requirements evolve over time)? I consider this, at best, highly unproven, and yet he advocates this as the sole approach to be taught in CS education. Knuth noted, correctly, that neither Dijkstra's education nor any of the practical systems he built (Algol compiler, etc) were based on this approach.
Not sure what he meant by "object-oriented", but he - as the other members of the IFIP - was well aware of Simula 67, and he belonged to the faction that rejected van Wijngaarden's proposal and regarded Simula 67 as "a more fruitful development" [1]. So - if he said or wrote that at all - it's likely related to what Kay understood by the term, or the implementation as a dynamically typed, originally interpreted language done at Xerox PARC, not to the kind of "object-orientation" for which Simula 67 is recognized today (remember that the term "object-oriented" was originally not applied to Simula 67 by the public, but to Smalltalk).
[1] https://www.researchgate.net/publication/2948437_Edsger_Dijk...
See “TUG LINES”, Issue 32 [1]
> it's likely related to what Kay understood by the term, or the implementation as a dynamically typed, originally interpreted language done at Xerox PARC
I think the comment was referring to what they were doing at Xerox PARC - yes.
There are more recent writings of him taking jabs at Californian universities for teaching Java to freshmen instead of what he was doing in Austin - teaching functional programming via Haskell. [2]
[1] Dijkstra, E.W. Quoted by Bob Crawford. TUG lines, Journal of the Turbo User Group, 32, Aug.–Sep. (1989)
[2] https://www.cs.utexas.edu/users/EWD/OtherDocs/To%20the%20Bud... (2001)
Unfortunately I wasn't able to find [1] anywhere on the web; the CHM only seems to have issues up to 22. Do you have a link where I can access it?
The other one [2] is also interesting, but the claim is not against OO, but "that functional programs are much more readily appreciated as mathematical objects than imperative ones, so that you can teach what rigorous reasoning about programs amounts to", and that "Java [..] is a mess", which again applies to the language quality (see also Brinch Hansen's paper https://dl.acm.org/doi/10.1145/312009.312034), not the paradigm.
You end up being forced to co-mingle your data structure design, with your data processing design. Which tends to be rather unhelpful.
Keeping your data structures fairly separate from the processes/functions that operate on them makes it much easier to build composable software. Data structures tend to be very hard to change over time, because the migration process is always tricky. Any structure that’s exposed outside your programs address space, whether that be via an API, storage on disk or in a DB, needs a migration path so new code can deal with old structures correctly. On the other hand, algorithms operating on that data are trivial to change, there’s no migration risk, and indeed we should expect those algorithms to change often, as the requirements of the software change.
In an OOP world, because you’re strongly encouraged to tightly bind your data structures to the algorithms that operate on them. You quickly end up in a horrible situation where changing your algorithms is very difficult without also being forced to change your data structures. Suddenly what should be a simple and easy change (introducing a new way of processing data), becomes difficult because coupling created by objects makes it hard to change the processing without also changing the data structures.
In a simple “write-once” world, OOP is fine. But once you want to write software that’s expected to evolve and adapt over years, as business requirements change, OOP quickly becomes more a hinderance than help.
The fact that a language is strong typed and you get compilation errors if you forgot something is a big plus.
OOP is fundamentally about no static variables.
strong typing has nothing to do with OOP. static variable are replaced by singletons and other similar in spirit objects.
OOP today is a 'No true Scotsman' concept much like communism, agile, and other vague by design terms. You can't argue against it because every individual has at least one definition in his head and it shifts through the conversation toward the one that's not refuted by the claims.
the intent of such concepts is to hit you in the feels and trigger some ideals inside you, so that you associate the positive feelings you have toward those ideals to the concept.
if you argue about it as it is used in practice you will inevitably have someone bring up that java style OOP is not true OOP and that you should look intro Smalltalk or some other language that implement "Real OOP".
since arguing about specifics is a losing battle, lets argue about the bigger picture, if we take the goals of alain kay like he talked about in many of his talks his goals was to make systems more like biogology, but as a system designer the last thing you want to do is that. we don't know much about biology, people in that field a still reverse engineering pre-existing designs to this day and not designing much of their own from scratch. If you design a system you want to have the most control and foresight in the dynamics of your systems, uncontrolled & unintended emergent effects are your source of problems.
entangling data and behavior make your conceptual design state-space size explode, when you go full OOP you become an ontologist philosophizing about what is an X and what is an X-manager, X-Provider, ... and less of a system designer trying to make sure your system does not land in the wrong states.
One of the most influential books about OOP - "Design Patterns: Elements of Reusable Object-Oriented Software" - talks about composition, separating interface from implementation etc - not about hierarchies ( other than to prefer composition ).
Composition has been used since LISP I and ALGOL 60 in almost all programming languages.
"Separating interface from implementation" is also the main feature of the programming languages based on abstract types, starting with Alphard and CLU, which are not OOP languages and which predate the time when Smalltalk has become known to the public, launching the OOP fashion.
An abstract type is defined by an interface, i.e. by a set of functions that have arguments of that type and this is a programming language feature that is completely independent of the OOP features like member functions, virtual functions and inheritance.
All OOP languages have some kind of abstract types, though with a different point of view on the relationships between individual objects and types a.k.a. classes and the functions that operate on them, but there have been many languages with abstract data types without the OOP features.
Moreover "separating interface from implementation" has also been the main feature of all programming languages based on modules, starting with Mesa, Modula and Ada.
The features that identify an OOP language are the idea that the functions belong to individual objects, not to types, hence the member functions, the substitution of the union types (of the right kind, like in Algol 68, not of the pathetic kinds encountered in Pascal and C and derived languages) with virtual functions (to provide an alternative form of dynamic polymorphism, which is preferable for closed-source software, by allowing changes without recompilation, unlike with tagged unions where there are select/case/switch statements that must be recompiled when the union is extended), and the inheritance in a class hierarchy.
There are many languages that are multi-paradigm, like C++ or D, where you can choose whether to write a program in an OOP style or in a totally different style, but there are also languages where it is difficult to avoid using the OOP features, or even impossible, because all the available data types may be derived from some base "object" type, inheriting its properties.
That is not at all unique to OOP, and in fact OOP makes the problem undecidable due to ad-hoc subtyping. More structured languages like ML, Haskell, and Rust are much easier to reason about and have much stronger type systems.
Most people using OOP languages prefer composition over hierarchies and I almost never see those complex class structures modelled on data ( for some of the reasons you give ).
In terms of evolvability - encapsulation - a key feature of OOP - is a key tool in enabling that.
And also, can you give me a huge non-OOP codebase that shows in practice how it is better than the potential OOP implementation?
As for huge codebases, everyone knows that line of codes does not equal quality.
Unfortunately, when OOP has become fashionable, its proponents have tried to convince everybody that OOP is the best paradigm for absolutely all programming problems, not only for those where OOP is indeed the best, and they have been rather successful for some time, which was bad for the software industry in general, resulting in many sub-optimal programs.
You can find some criticism points in there
Nothing. It's just one of many useful tools we can use to develop software. It's like with food. Sometimes some people loudly claim that a certain food is unhealthy, and then a few months or years later you read the exact opposite. Fortunately, there are low-pass filters.
And it is the wrong choice, if you need a script and can make that function in python.
OOP, particularly Java, is good when you have a lot of functionality, especially if you can use already existing massive ecosystem.
If I would have to write something from scratch, I would not use OOP, but if you need something fairly complicated, chance is there is already a generic solution available, and you need to costomize it, where Java is pretty good.
When you're learning OOP, you deal with questions like "is a Circle an Ellipse or is an Ellipse a Circle?" F'in' neither, actually. You end up "modelling" "business objects" in "code", leading to monstrosities like Hibernate.
In reality, you have the real-world domain and you have the in-the-computer domain, and trying to make one look like the other is a mistake. OOP is a dandy way of managing some forms of complexity, but it's not often an especially good way of looking at most problems, much less the only way.
" a) 2 ≤ i < 13
b) 1 < i ≤ 12
c) 2 ≤ i ≤ 12
d) 1 < i < 13
There is a smallest natural number. Exclusion of the lower bound —as in b) and d)— forces for a subsequence starting at the smallest natural number the lower bound as mentioned into the realm of the unnatural numbers. That is ugly, so for the lower bound we prefer the ≤ as in a) and c).
Consider now the subsequences starting at the smallest natural number: inclusion of the upper bound would then force the latter to be unnatural by the time the sequence has shrunk to the empty one. That is ugly, so for the upper bound we prefer < as in a) and d). We conclude that convention a) is to be preferred."
I despise this guy
You either have an empty range be -1 .. 0, which is ugly, or 0 .. -1, which is also ugly. Thus, start-inclusive, end-exclusive.
This and column-major order for matrices (a vector is a column, not a row)
We can be thankful that this applied physicist in particular decided to dedicate time to think carefully about the needs of who would be his colleagues and successors, when he was pretty much inventing programming as a profession; he told of the anecdote of when he got married, and he wasn't able to write in "programmer" as his occupation in the Dutch paperwork, because it didn't exist as a job category yet.
And then, once you remove empty ranges, there's no reason to to choose a range style based on which you prefer for an empty range.
After reading the article it seems that he mostly produced hot takes, while others did the actual heavy lifing. Goto considered harmful? And some algorithm that would probably be found by someone else?
Will Linus get a monument made of pure gold when he dies?
He won a turing award for advocating for structured control flow. That is the modern standard style for programming. He contributed a number of algorithms including the shortest path algorithm.
"You can hardly blame M.I.T. for not taking notice of an obscure computer scientist in a small town in the the Netherlands."
I suspect geeks like Dijkstra because he is "edgy" more than because he is correct.
Also, Object-Oriented programming was actually invented in Norway, even though Alan Kay of Smalltalk fame tried to take credit.
He was right about GOTO though, but many developers did not even understand his argument but just read the headline and concluded "GOTO bad".
https://www.quora.com/What-did-Alan-Kay-mean-by-I-made-up-th...
I don’t know how amenable he was to his arguments possibly being incorrect, but I love working with/knowing people who are that combination of outspoken and not-overly-stubborn. People like that are a firehose of ideas and knowledge, even if not everything they say is correct. They also usually are “passionate” about their work and at least competent enough to have unorthodox opinions that don’t just sound blatantly stupid.
Most people are too timid or low-ability to be outspoken at all.
Not enough of us, that's how many.
Also, if he said this back when the majority of programs were written in assembly I think it makes a lot more sense.
A sampling:
> “The competent programmer is fully aware of the limited size of his own skull. He therefore approaches his task with full humility, and avoids clever tricks like the plague.” (Dijkstra, 1972)
> “The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offense.” (Dijkstra, 1982)
> “Object-oriented programming is an exceptionally bad idea which could only have originated in California.” (Dijkstra, 1989)