uncle bob siendo completamente destruido
https://github.com/cmuratori/misc/blob/main/cleancodeqa.md
https://github.com/cmuratori/misc/blob/main/cleancodeqa-2.md
en el 2 podeis leer el final, donde casey basicamente se rie en su puta cara
CASEY: Well, I disagree with most of that, but if we're ending it here, I'll just add my final responses for github posterity:
Regarding "as I wrote in Clean Code (which, by the way, is not the same as your "Clean Code")," well, the point of this discussion was for you to elaborate on what is not the same. But your design for this IO system looks exactly like my "Clean Code" example - a virtual function for every operation, and one class per element in the system with no predication. So what are these differences that you're referring to? Now would be the time to explain what they are, since that was the point of the concrete example. If this is a bad example for illustrating the differences, that's fine, but it was the first one you gave so I assumed it would be one you'd want to use.
Regarding "when operations proliferate more rapidly than types, switch statements are better," that was not the case here. In no way are operations proliferating more rapidly than types in this system. Vendors will add drivers to an OS constantly, perhaps monthly or even weekly, whereas the number of operations in a particular system tends to go up much more slowly (once every few months at maximum, but more like once a year for something like an IO subsystem). It is the opposite of what you said. This is an important distinction, because what I am demonstrating here is the opposite of your rule: this is showing that even in the case where types proliferate far more rapidly than operations, as is the case with drivers in an OS, the principle doesn't work. Enums are better in both cases. Specifically because you have potentially thousands of types in the system (all the different drivers all the vendors have ever shipped), adding a single operation, however rarely, can cost massive programmer cycles due to the unnecessary work multiplication across types that vtables cause. Another way to say this would be, enums are more important in a system where types proliferate rapidly, not less.
Regarding "you eventually chose a design that sacrifices machine cycles to save programmer cycles," I did no such thing. This design achieves both, that's why I like it. It is dramatically faster to use something like a packet-based system than something like your original proposed design, because you do not take a ring transition on every operation. New OS IO APIs are now all designed this way: the user writes data without talking to the OS, and a kernel thread picks up those data writes. Nobody ever makes a function call, except occasionally to ensure the kernel thread hasn't gone to sleep :) This is what I meant by the bullet point, "If at some point we decide that users should be able to do multithreaded/bulk IO ops" I am talking about the necessity that actually occurred in both Linux and Windows of removing the frequency of ring transitions for saving CPU cycles. None of this is trading CPU cycles for programmer cycles. It's achieving both. The Linux kernel design of io_uring looks like my design! They did not add that to save programmer cycles. They added it because they wanted the highest possible IO throughput. This is an almost universal principle of modern OS design: anything that can be turned into data writes should be, and function calls should be minimized. It's been true for GPUs, for NICs, and for our example, disk IO.
Regarding "And so I think we wind up in the same place. When operations proliferate more rapidly than types we both use switches. When types proliferate more rapidly than operations we both use dynamic dispatch," Again, I don't see how you got there. Obviously types are proliferating more rapidly in this system, so that part is not true. If we don't believe drivers are proliferating rapidly, why are we loading them dynamically? I thought that was the entire point of the example! But perhaps more importantly, we are not "using dynamic dispatch" here in the way you seem to be suggesting. As I said when I posted the proposed design, I would also do this inside the drivers themselves. I would not duplicate drivers to remove if statements and switches inside a driver that allowed that driver to handle multiple similar devices. The only reason there are function pointers in this system is because the problem definition required that we load the driver from a different module, and we are not presuming a JIT or something which can weld things together for us. That introduces a mandatory cut, so we cannot get rid of it because the problem is defined to contain it.
But note that that is not the same between our two approaches. I have the function pointer there because it's required. And you'll note I minimized the number all the way down to one. I didn't put it in there because I think it saves programmer time. In fact, I'm not really sure I want it there at all. I haven't actually implemented this particular system in an OS, so it was somewhat off the top of my head, but it's very possible that if I actually went to write this, I wouldn't actually include that function pointer at all. Instead, I might just have the OS thread reading the queue and prefiltering the packets for quota/permissions, then updating a shared memory address that lets the driver know it can process the packets directly. Without actually implementing, I can't say that's for sure what I would do, but, it's probably something I would try.
So it feels like you're overstating the similarity of our approaches, but, if you think they're that similar, then, I guess that's just where we end up! Thanks for taking the time to create this thread which pushed the github emoji checker well beyond its limits.
Bob: Thank you Casey. I believe we should let our disagreement stand at this point and let our audience be the final judge. This has been fun. Perhaps we'll do it again some day.
Fijaros como uncle bob no deja de irse por las ramas con casos hipoteticos, inventarse nuevo vocabulario para justificar sus analogias, decir cosas que casey no ha dicho y demas falacias...
Menuda master class del señor Muratori.