Comment by zbentley

9 months ago

It's striking to me how out of touch Martin seems to be with the realities of software engineering in this transcript. Stylistic refactors that induce performance regressions, extremely long and tortured method names for three-line methods, near-total animus towards comments ... regardless of who is right/wrong about what, those takes seem like sophomoric extremism at its worst, not reasoned pragmatism that can be applied to software development in the large.

When I encounter an Uncle Bob devotee, I'm nearly always disappointed with the sheer rigidity of their approach: everything must be reduced thus, into these kind of pieces, because it is Objectively Better software design, period. Sure, standard default approaches and best practices are important things to keep in mind, but the amount of dogma displayed by folks who like Martin is really shocking and concerning.

I worry that his approach allows a certain kind of programmer to focus on like ... aesthetic, dogmatic uniformity (and the associated unproductivity of making primarily aesthetically-motivated, dogmatic changes rather than enhancements, bugfixes, or things that other coders on a project agree improves maintainability) instead of increasing their skills and familiarity with their craft.

Maintainability/appropriate factoring are subjective qualities that depend a lot on the project, the other programmers on it, and the expectations around how software engineering is done in that environment.

Pretending that's not true--that a uniform "one clean code style to rule them all" is a viable approach--does everyone involved a disservice. Seasoned engineers trying to corral complexity, new engineers in search of direction and rigor, customers waiting for engineering to ship a feature, business stakeholders confused as to why three sprints have gone by with "refactor into smaller methods" being the only deliverable--everyone.

The Uncle Bob thing is something I'm experiencing right now.

I hired a friend who was a huge Uncle Bob mark, and he kept trying to flex his knowledge during interviews with other people in the company. I didn't really think much of it and told the other interviewer that it was just his personal quirk and not to worry much.

I had him work with some junior devs on a project while I took care of something more urgent. After finishing it, I went over to take a look at how it was going on his end. I was horrified at the unnecessary use of indirection; 4 or 5 levels in order to do something simple (like a database call). Worse, he had juniors build entire classes as an interface with a database class that was "wrong".

No practical work was done, and I've spent the past 4 weeks building the real project, while tossing out the unnecessary junk.

I liked Clean Code when I read it, but I always assumed a lot of it was meant for a specific language at a specific time. If you are using it verbatim for a Python project in 2025, why?

> I worry that his approach allows a certain kind of programmer to focus on like ... aesthetic, dogmatic uniformity (and the associated unproductivity of making primarily aesthetically-motivated, dogmatic changes rather than enhancements, bugfixes, or things that other coders on a project agree improves maintainability) instead of increasing their skills and familiarity with their craft.

Funny, I find the opposite. In my experience people that are willing to take a "dogmatic" position on code style are those who are able to actually get on with implementing features and bugfixes. It's the ones who think there's a time and place for everything and you need to re-litigate the same debates on every PR who tie themselves in knots getting nothing done.

Do I agree with absolutely everything Martin writes? In principle, no. But I'd far rather work on a codebase and team that agrees to follow his standards (or any similar set of equally rigid standards, as long as they weren't insane) than one that doesn't.

I'm not familiar with the Clean Code book etc; my introduction is the article. UB seems to be advocating consistently for patterns that are not my cup of tea! For example: Functions sometimes make sense as 2-3 lines. Often 5-20. Less often, but not rarely, much more than that!

I'm also a fan of detailed doc comments on every module and function, and many fields/variants as well. And, anything that needs special note, is unintuitive, denotes units or a source etc.

  • Function length also depends on language. Every line of one language requires three line in another if the former has implicit error handling and the latter explicit. But I find the cognitive load of the two to be similar.

    I am also okay with 1000 line functions where appropriate. Making me jump around the code instead of reading one line at a time, in a straight line? No thanks!

> It's striking to me how out of touch Martin seems to be with the realities of software engineering in this transcript

It was always like that. And Fowler the same thing with his criticism of anemic domain model. But software-engineering is no exceptions to having a mass of people believing someone without thinking by themselves.

  • > It was always like that. And Fowler the same thing with his criticism of anemic domain model.

    What leads you to disagree with the fact that anemic domain models are an anti-pattern?

    https://martinfowler.com/bliki/AnemicDomainModel.html

    I think it's obvious that his critique makes sense if you actually take a moment to try learn and understand what he says and where he comes from. Take a moment to understand what case he makes: it's not object-oriented programming. That's it.

    See,in a anemic domain model, instead of objects you have DTOs that are fed into functions. That violates basic tenners of OO programming. It's either straight up procedural programming or, if you squint hard enough, functional programming. If you focus on OO as a goal, it's clearly an anti-pattern.

    His main argument is summarized in the following sentence:

    > In essence the problem with anemic domain models is that they incur all of the costs of a domain model, without yielding any of the benefits.

    Do you actually argue against it?

    Listen, people like Fowler and Uncle Bob advocate for specific styles. This means they have to adopt a rethoric style which focuses on stressing the virtues of a style and underlining the problems solved by the style and created by not following the style. That's perfectly fine. It's also fine if you don't follow something with a religious fervor. If you have a different taste, does it mean anyone who disagrees with you is wrong?

    What's not cool is criticizing someone out of ignorance and laziness, and talking down on someone or something just because you feel that's how your personal taste is valued.

    • "It's not object oriented programming" is only a good case to make if you think object oriented programming is synonomous with good. I don't think that's true. It's sometimes good, often not good.

      Why would focusing on OO be a goal? The goal is to write good software that can be easily maintained. Nobody outside of book writers are shipping UML charts

      24 replies →

    • > it's not object-oriented programming. That's it.

      Yes, exactly. And this "classical" object-oriented programming is an anti-pattern itself.

      (That being said, OOP is not well defined. And, for example, I have nothing against putting related data structures and functionality into the same namespace. But that's not what OOP means to him here)

      8 replies →

I haven't seen a lot of evidence that Martin really has the coding chops to speak as authoritatively as he does. I think when you become famous for giving advice or being an "expert", it can be difficult to humble yourself enough to learn new things. I know personally I've said a lot of dumb things about coding in the past; luckily none of those things were codified into a "classic" book.

What strikes me about the advice in Clean Code is that the ideas are, at best, generally unproven (IE just Martin's opinion), and at worst, justify bad habits. Saying "I don't need to comment my code, my code speaks for itself" is alluring, but rarely true (and the best function names can't tell you WHY a function/module is the way it is.) Chopping up functions and moving things around looks and feels like work, except nothing gets done, and frankly often strikes me as being the coding equivalent of fidget spinners (although at least fidget spinners dont screw up your history). Whenever Martin is challenged on these things he just says to use "good judgement", but the code and advice is supposed to demonstrate good judgement and mostly it does not.

Personally I wish people would just forget about Clean Code. You're better off avoiding it or treating it as an example of things not to do.

  • I watched some talks he gave 15 years ago and what struck me was that he would use analogies to things like physics that were just objectively incorrect. He was confidently talking about a subject he clearly didn't understand at even an undergraduate level.

    Then for the rest of the talk he would speak just as confidently about coding. Why would I believe anything he has to say when his confidence is clearly not correlated to how well he understand the material?

  • > I haven't seen a lot of evidence that Martin really has the coding chops to speak as authoritatively as he does

    From what I can deduce, his major coding work was long in the past, and maybe in C++.

I read Clean Code when I started out my career and I think it was helpful for a time when I worked on a small team and we didn't really have any standards or care about maintainability but were getting to the point where it started mattering.

Sure, dogmatism is never perfect, but when you have nothing, a dogmatic teacher can put you in a good place to start from. I admired that he stuck to his guns and proved that the rules he laid out in clean code worked to make code more readable in lots of situations.

I don't know anything about him as a person. I never read his other books, but I got a lot out of that book. You can get a lot out of something without becoming a devotee to it.

EDIT: I think even UB will agree with me that his dogmatism was meant as an attitude, something strong to hit back against a strong lack of rigidity or care about readable code, vs a literal prescription that must be followed. See his comment here:

> Back in 2008 my concern was breaking the habit of the very large functions that were common in those early days of the web. I have been more balanced in the 2d ed.

And maybe I was lucky, but my coding life lined up pretty neatly with the time I read Clean Code. It was an aha moment for me and many others. For people who had already read about writing readable code, I'm sure this book didn't do much for them.

I'm going to have to admit to never having read Clean Code. It's just never appealed to me. I did read some of UBs articles a fair number of years ago. They did make me think - which I'd say is a positive and along the lines you are putting forwards.

Rigidity and "religious" zeal in software development is just not helpful I'd agree.

I do however love consistency in a codebase, a point discussed in "Philosophy of Software Design", I always boil this down to, even if I'm doing something wrong, or suboptimal, if I do it consistently, once I realise, or it matters I only have one thing to change to get the benefit.

It's the not being able to change regardless, in the face of evidence, that separates consistency and rigidity (I hope)!

I don't know why people take UB seriously. He never provided proof of any work experience - he claims to have worked for just a single company that... never shipped any code into production. Even his code examples on GitHub are just snippets, not even a to-do app (well, I think that his style of "just one thing per function" works as a self-fulfilling prophecy).

Maybe people like him are the reason why we have to do leet code tests (I don't believe he would be capable of solving even an easy problem).

  • Uncle Bob is one of the core contributors to Fitnesse, which had moderate success in the Java popularity era back in the day.

    Also, you do understand that people worked as software engineers even before Github became popular, or open sourcing to begin with, do you? So if someone is 60+ year old, chances are that most of his work has never been open sourced, and his work was targeting use cases, platforms, services which have no utility in this age any more.

    Which have all nothing to do with how good a software engineer someone is.

    And finally, do you have any proof that he never shipped any code into production?

    • > So if someone is 60+ year old, chances are that most of his work has never been open sourced,

      John Ousterhout is 70 years old and one of the open source pioneers. We don't know what Uncle Bob shipped or did not ship but his friendly opponent in this discussion definitley did ship high profile projects.

      1 reply →

    • The criticism was that UB worked at a company that allegedly didn’t ship code to production, not that he doesn’t have a corpus of open source projects on GitHub.

    • > So if someone is 60+ year old, chances are that most of his work has never been open source

      Somewhat ageist? I'm 72 and have produced a number of FOSS tools.

      2 replies →

Another example of not quite pragmatic advice is Screaming Architecture. If you take some time to think about it, it’s actually not a good idea. One of the blog posts I’m working on is a counter argument to it.

  • I’d love for you to expand on this!

    • Short version: when designing new software, you don't have its architectural picture in the beginning. So when starting from scratch, the architecture shouldn't be screaming, but rather, it has to be non-committal/non-speculative to allow wiggle room for the future. (How to achieve non-committal architecture is the biggest topic I'm interested in, and I find 1 good tactic every few years). Specifically, the architecture should ephasize entry points and outputs. That's exactly what frameworks like Rails provide. You go by entry points until some sort of custom architecture starts emerging from the middle, which is when it can slowly begin "screaming" over time.

> It's striking to me how out of touch Martin seems to be with the realities of software engineering in this transcript. Stylistic refactors that induce performance regressions, extremely long and tortured method names for three-line methods, near-total animus towards comments ... regardless of who is right/wrong about what, those takes seem like sophomoric extremism at its worst, not reasoned pragmatism that can be applied to software development in the large.

I think you're talking out of ignorance. Let's take a moment to actually think about the arguments that Uncle Bob makes in his Clean Code book.

He argues in favor of optimizing your code for clarity and readability. The main goal of code is to help a programmer understand it and modify it easily and efficiently. What machines do with it is of lower priority. Why? Because a programmer's time is far more expensive than any infrastructure cost.

How do you make code clear and easy to read? Uncle Bob offers his advise. Have method names that tell you what they do, so that programmers can easily reason about the code without having to even check what the function does. Extract low-level code to higher level methods so that a function call describes what it does at the same level of detail. Comments is a self-admission you failed to write readable code, and you can fix your failure by refactoring code into self-descriptive member functions.

Overall, it's an optimization problem where the single objective is defined as readability. Consequently, it's obvious that performance regressions are acceptable.

Do you actually have any complain about it? If you read what you wrote, you'll notice you say nothing specific or concrete: you only throw blanket ad hominems that sound very spiteful, but are void of any substance.

What's the point of that?

> Maintainability/appropriate factoring are subjective qualities that depend a lot on the project, the other programmers on it, and the expectations around how software engineering is done in that environment.

The problem with your blend of arguments is that guy's like you are very keen on whining and criticizing others for the opinions they express, but when lightly pressed on the subject you show that you actually have nothing to offer in the way of alternative or guideline or anything at all. Your argument boils down to "you guys have a style which you follow consistently, but I think I have a style as well and somehow I believe my taste, which I can't even specify, should prevail". It's fine tha you have opinions, but why are you criticizing others for having them?

  • > Comments is a self-admission you failed to write readable code, and you can fix your failure by refactoring code into self-descriptive member functions

    This may be true for some cases, but I don't see a non-contrived way for code to describe why it was written in the way it does or why the feature is implemented the way it is. If all comments are bad, then this kind of documentation needs to be written somewhere else, where it will be disconnected from the implementation and most probably forgotten

    • > This may be true for some cases, but I don't see a non-contrived way for code to describe why it was written in the way it does or why the feature is implemented the way it is.

      I have to call bullshit on your argument. Either you aren't even looking because you have the misfortune of only looking at bad code written by incompetent developers, or you do not even know what it looks like to be able to tell.

      The core principles are quite simple, and are pervasive. Take for example replacing comments with self-descriptive names. Isn't this something obvious? I mean, a member function called foobinator needs a combination of comments and drilling down to the definition to be able to get a clue on what it does. Do you need a comment to tell what a member function called postOrderMessageToEventBroker does?

      Another very basic example: predicates. Is it hard to understand what a isMessageAnOrderRequest(message) does? What about a message.type == "command" && type.ToUpperCase() == "request" && message.class == RequestClass.Order ? Which one is cleaner and easier to read? You claim these examples are contrived, but in some domains they are more than idiomatic. Take user-defined type assertions. TypeScript even has specialized language constructs to implement them in the form of user-defined type guards. And yet you claim these examples are contrived?

      I'm starting to believe all these vocal critics who criticize Uncle Bob or Eric Evans or any other author are actually talking out of sheer ignorance about things they know nothing about. They read some comment in some blog and suddenly they think they are an authority on a subject they know nothing about.

      So much noise.

      4 replies →

  • > The main goal of code is to help a programmer understand it and modify it easily and efficiently. What machines do with it is of lower priority.

    This mentality sounds like a recipe for building leaky abstractions over the inherent traits of the von Neumann architecture, and, more recently, massive CPU parallelism. Bringing with it data races, deadlocks, and poor performance. A symptom of this mentality is also that modern software isn‘t really faster than it should be, considering the incredible performance gains in hardware.

    > Comments is a self-admission you failed to write readable code

    I‘m not buying this. It’s mostly just not possible to compress the behavior and contract of a function into its name. If it were, then the compiler would auto-generate code out of method names. You can use conventions and trigger words to codify behavior (eg bubbleSort, makeSHA256), but that only works for well-known concepts. At module boundaries, I‘m not interested in the module‘s inner workings, but in its contract. And any sufficiently complex module has a contract that is so complex that comments are absolutely required.

    • > This mentality sounds like a recipe for building leaky abstractions over the inherent traits of the von Neumann architecture, and, more recently, massive CPU parallelism. Bringing with it data races, deadlocks, and poor performance.

      No,not really. Just because you think about how to name functions and what portions of your code should be easier to read if the were extracted to a function,that doesn't mean you are creating abstractions or creating problems.

      The rest of your comments on von Neumann architecture etc is pure nonsense. Just because your code is easy to read it doesn't mean you're writing poetry that bears no resemblance with how the code is executed. Think about what you're saying: what is the point of making readable code? Is it to look nice at the expense of bugs, or to help the developer understand what the code does? If it's the latter, what point do you think you're making?

      1 reply →

  • > Comments is a self-admission you failed to write readable code, and you can fix your failure by refactoring code into self-descriptive member functions

    # This is not the way I wanted to do this, but due to bug #12345 in dependency [URL to github ticket] we're forced to work around that.

    # TODO FIXME when above is done.

    Oh no, I so failed at making self-descriptive code. I'm sorry, I totally should've named the method DoThisAndTHatButAlsoIncludeAnUglyHackBecauseSomeDubfuckUpstreamShippedWithABug.

  • > What machines do with it is of lower priority. Why? Because a programmer's time is far more expensive than any infrastructure cost.

    This assumes that code runs on corporate infrastructure. What if it runs on an end user device? As a user I certainly care about my phone's battery life. And we aren't even talking about environmental concerns. Finally, there are quite a few applications where speed actually matters.

    > Comments is a self-admission you failed to write readable code, and you can fix your failure by refactoring code into self-descriptive member functions.

    Self-explaining code is a noble goal, but in practice you will always have at least some code that needs additional comments, except for the most trivial applications. The world is not binary.

  • I'm not going to spend a long time responding to your comment, since it seems accusatory and rude; if you modify it to be more substantive I'll happily engage more.

    The one specific response I have is: it's not that I

    > say nothing specific or concrete: [I] only throw blanket ad hominems that sound very spiteful

    ...rather, it's that I'm criticizing Martin's approach to teaching rather than his approach to programming. I expand on that criticism more in an adjacent comment, here: https://news.ycombinator.com/item?id=43171470

> sheer rigidity

That looks more like a communication style difference than anything else. Uncle Bob's talks and writing are prescriptive -- which is a style literally beaten into me back when I was in grade school, since it's implied just from the fact that it's you doing the speaking that you're only describing your opinions and that any additional hedging language weakens your position further than you actually intend.

If you listen to him in interviews and other contexts where he's explicitly asked about dogmatism as a whole or on this or that concept, he's very open to pragmatism and rarely needs much convincing in the face of even halfway decent examples.

> animus toward comments

Speaking as someone happy to drop mini-novels into the tricky parts of my code, I'll pick on this animus as directionally correct advice (so long as the engineer employing that advice is open to pragmatism).

For a recent $WORK example, I was writing some parsing code and had a `populate` method to generate an object/struct/POCO/POJO/dataclass/whatever-it-is-in-your-language, and as it grew in length I started writing some comments describing the sections, which for simplicity's sake we'll just say were "populate at just this level" and "recurse."

If you take that animus toward comments literally, you'll simply look at those comments and say they have to be removed. I try to be pragmatic, and I took it as an opportunity to check if there was some way to make the code more self-evident. As luck would have it, simply breaking that initial section into a `populate_no_recurse` method created exactly the documentation I was looking for and also wound up being helpful as a meaningful name for an action I actually wanted to perform in a few places.

That particular pattern (breaking a long method into a sequence of named intermediate parts) has failure modes, especially in the hot path in poorly optimized runtimes (C#, Java, ..., Python, ...), and definitely in future readability if employed indiscriminately, but I have more than enough experience to be confident it was a good choice here. The presence in my mind of some of Uncle Bob's directionally correct advice coloured how I thought about my partial solution and made it better.

> other animus

- Stylistic refactors that induce performance regressions can be worth it. As humans, we're pre-disposed to risk avoidance, so let's look at an opposite action with an opposite effect: How often are you willing to slow down feature velocity AND make the code harder to maintain just to squeeze out some performance (for a concrete example, suppose there's some operation with space/time/bandwidth tradeoffs which imply you should have a nasty recursive cte in your database to compute something like popcount on billion-bit-masks, or even better just rewrite that portion of the storage layer)? My job is 80% making shit faster and 10% teaching other people how to make shit faster, but there are only so many hours in the day. I absolutely still trade performance for code velocity and stability from time to time, and for all of those fledgeling startups with <1M QPS they should probably be making that trade more than I do (assuming it's an actual trade and not just an excuse for deploying garbage to prod).

- The "tortured method names" problem is the one I'm most on the fence about. Certainly you shouldn't torture a long name out of the ether if it doesn't fit well enough to actually give you the benefits of long names (knowing what it does from its name, searchability), but what about long names which do fit? For large enough codebases I think long names are still worth the other costs. It's invaluable to be able to go from some buggy HTML on some specific Android device straight to the one line in a billion creating the bug, especially after a couple hiring/firing sessions and not having anybody left who knows exactly how that subsystem works. I think that cutover point is pretty high though. In the 100k-1M lines range there just aren't enough similar concepts for searchability to benefit much from truly unique names, so the only real benefit is knowing what a thing does just from its name. The cost for long names is in information density, and when it's clear from context (and probably a comment or three) I'm fine writing a numeric routine with single-letter variable names, since to do otherwise would risk masking the real logic and preventing the pattern-recognition part of your brain from being able to help with matters. HOWEVER, names which properly tell you what a thing does are still helpful (the difference between calling `.resetRetainingCapacity()` and `.reset()` -- the latter you still have to check the source to see if it's the method you want, slowing down development if you're not intimately familiar with that data structure). I still handle this piece of advice on a case-by-case basis, and I won't necessarily agree with my past self from yesterday.

> "Uncle Bob devotees" vs "Uncle Bob"

This is maybe the core of your complaint? I _have_ met a lot of people who like his advice and aren't very pragmatic with it. Most IME are early-career and just trying to figure out how to go from "I can code" to "I can code well," and can therefore be coached if you have well-reasoned counter-examples. Most of the rest IME like Uncle Bob's advice but don't code much, and so their opinions are about as valuable as any other uninformed opinion, and I'm not sure I'd waste too much time lamenting that misinformation. For the rest of the rest? I don't have a large enough sample I've interacted with to be very helpful, but unrelenting dogmatism is pretty bad, and people like that certainly exist.

  • Thanks for the thoughtful response. I generally don't want to get into the specifics of what Martin advocates for. Whether to prefer or eschew comments, give methods a particular kind of names, accept a performance penalty for a refactor--those are all things that are good or bad in context.

    I think a lot of engineers hear "there's a time and a place" or "in context" and assume that I'm saying that the approach to coding can or should differ between every contribution to a codebase. Not so! It's very important to have default approaches to things like comments, method length, coupling, naming, etc. The default approach that makes the most sense is, however, bounded by context, not Famous Author's One True Gospel Truth (or, in many cases, Change-Averse Senior Project Architect's One True Gospel Truth). The "context boundary" for a set of conventions/best practices is usually a codebase/team. Sometimes it's a sub-area within a codebase. More rarely, it's a type of code being worked on (e.g. payment processing code merits a different approach from kleenex/one-off scripts). Within those context boundaries, it's absolutely appropriate to question when contributors deviate from an agreed-upon set of best practices--they just might not be Martin's best practices.

    Rather, the core of my critique is that Martin's approach lacks perspective. Perspective/pragmatism--not some abstract notion of "skill level in creating well-factored code according to a set of rules"--is the scarce commodity among the intermediate-seeking-senior engineers that Martin's work is primarily marketed toward and valued by.

    From there, I see two things wrong with Martin's stance in the Osterhout transcript:

    "Out of touch" was not an arbitrarily chosen ad-hominem. When Osterhout pressed Martin to improve and work on some code, Martin's output and his defense of it were really low-quality. I can tell they're really low quality because, in spite of differing specific opinions on things like method length/naming/SRP, almost everyone here and to whom I've showed that transcript finds something seriously wrong with Martin's version, while the most stringent critique of Osterhout's code I've seen mustered is "eh, it's fine, could be better". That, and Martin's statements around the "why" of his refactors, indicate that the applicability of his advice for material code quality improvements in 2025 (as opposed to, say, un-spaghettification of 2005 PHP 5000-line god-object monstrosities) is in doubt. On its own, that in-applicability wouldn't be a massive problem, which brings me to...

    Second, Martin is a teacher. When you mention '"Uncle Bob devotees" vs "Uncle Bob"' and I talk about the rigidity I see in evidence among people that like Martin, I'm talking about him as a teacher. This isn't a Torvalds or Antirez or Fabrice Bellard-type legendary contributor discussing methodological approaches that worked for them to make important software. Martin is first and foremost (and perhaps solely) a teacher: that's how he markets himself and what people value him for. And that's OK! Teachers do not have to be contributors/builders to be great teachers. However, it does mean that we get to evaluate Martin based on the quality of his pedagogical approach rather than holding the ideas he teaches on their own merit alone. Put another way, teachers say half-right things all the time as a means of saving students from things they're not ready for, and we don't excoriate them for that--not so long as the goal of preparing the students to understand the material in general (even if some introductory shortcuts need to later be uninstalled) is upheld.

    I think Martin has a really poor showing as a teacher. The people his work resonates the most strongly with are the people who take it to the most rigid, unhealthy extremes. His instructorial tone is absolute, interspersed with a few "...but only do this pragmatically of course" interjections that he himself doesn't really seem to believe. His material is often considered, in high-performing engineering departments, to be something that leaders have to check back against being taken too far rather than something they're happy to have juniors studying. Those things speak to failures as a teacher.

    Sure, software engineers are often binary thinkers prone to taking things to extremes--which means that a widely regarded teacher of that crowd is obligated to take those tendencies into account. Martin does not do this well: he proposes dated and inappropriate-in-many-cases practices, while modeling a stubborn, absolutist tone in his instruction and responses to criticism. Even if I were to give his specific technical proposals the greatest possible benefit of the doubt, this is still bad pedagogy.