3 ms·
We'll have to agree to disagree. You're right that there's a tension between present and future. But that's always true. My statements aren't contradictory in
by akkartik 7y ago
We'll have to agree to disagree.
You're right that there's a tension between present and future. But that's always true. My statements aren't contradictory in isolation, they just reflect this underlying tension. You have to navigate it no matter what point you choose on the spectrum.
> If we don't provide means for making systems where it is easy to validate their backwards compatibility...
This begs the question of why you need to validate backwards compatibility. What benefits do you get? If we have a list of benefits we can start working through them and figure out if something else may substitute for compatibility.
> This is how biological evolution became a great success, not by "starting from scratch" every time but by making sure that new individuals were always more or less "backwards compatible".
This analogy isn't helpful, because evolution is constantly testing lots of different approaches all at once, extremophiles and bacteria and cheetahs. While many lessons are shared between simple and complex life forms, there is also a lot of branching where different organisms come up with disjoint solutions to the same problems. Human supply chains are not nearly so redundant. Lessons from evolution don't always apply to something that's 'intelligently' designed.
> ..the idea of reusability, which is very closely related to the idea of "compatibility"..
It's worth separating these two ideas. You can have reuse without compatibility (reworking an existing codebase to fit an entirely new interface) and compatibility without reuse (cleanroom implementations of protocols).
Reuse is a difficult word to wrap my head around because it encompasses so much:
a) Calling a function at a new call-site.
b) Selecting a library for a use case it was designed for.
c) Mangling a library to support a use case it was not designed for.
d) Deploying copies of an AMI.
e) ... and much more
I'm very supportive of post-deployment reuse (e.g. d above) which is usually entirely automated. But I'm suspicious of large-scale reuse during the development process. We've been trying to make it work for decades now, and it just hasn't panned out. At what point do we reframe a goal as a delusion? I think we're way past it in this case.
- galaxyLogic 7y ago> But I'm suspicious of large-scale reuse during the development process. We've been trying to make it work for decades now, and it just hasn't panned out. At what point do we reframe a goal as a delusion? I think we're way past it in this case. Software Reuse is not a "goal" but common well-understood practice. Call a function from more than one location, instantiate a class more than once and call its methods from several locations. We do that because it is helpful for development and maintenance, not because that would be our "goal". I would think most software written say in Java uses that approach, in practice. Create multiple instances of a given class. So what would be the evidence that this approach has not "panned out" and is "delusional goal"? Maybe your "avoid reuse" is a better approach. But I don't think there's a lot of evidence that would prove it to be so, not at least yet.
- akkartik 7y agoI'd argue there isn't a lot of evidence either way. What you call "common well-understood practice" I strongly suspect is just cargo culting. As evidence: it doesn't seem to make any projects turn out better. All projects eventually suck over time, no matter how well they follow "best practices". If you're copy-pasting code everywhere rather than creating a function, that's obviously terrible. But on the other hand we've all also seen functions with twelve arguments and 3 boolean flags that are trying to do too many things at once. Is there any "practice" that gives us good guidelines on at what point to fork a function into two? I haven't heard of any such. The fact that our "best practices" are one-sided is a strong sign that they're more religion than science. Science reasons about trade-offs. Software isn't yet much of an evidence-based science. There's just too many variables. We don't know how to reason about the interactions between them. Here are some writings on the dangers of over-abstraction. At the very least they're evidence that I'm not alone in these suspicions. http://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction http://www.sandimetz.com/blog/2016/1/20/the-wrong-abstractio... http://programmingisterrible.com/post/139222674273/write-code-that-is-easy-to-delete-not-easy-to http://programmingisterrible.com/post/139222674273/write-cod... http://bravenewgeek.com/abstraction-considered-harmful http://bravenewgeek.com/abstraction-considered-harmful http://dimitri-on-software-development.blogspot.de/2009/12/disadvantages-of-code-reuse.html http://dimitri-on-software-development.blogspot.de/2009/12/d...
- galaxyLogic 7y ago> All projects eventually suck over time, no matter how well they follow "best practices". Yes they (often) "suck" but many of them work as well, produce widely used software. I would not call subclassing a "best practice" but a widely used form of reuse. It is a useful feature to have in your toolbox, in my experience, having programmed in Java and other OOP languages. I think it boils down to "There is no Silver Bullet". Reuse is not a Silver Bullet. But it is "a" bullet. :-)
- akkartik 7y agoIf we've gone from thinking of it as essential to just "a" bullet, I'm happy. Now we can have a productive conversation about what other bullets this bullet displaces in your toolbox, and whether that's worth it. I'm not claiming functions are bad, or classes are bad, or inheritance is bad (there is evidence of the last, but it's orthogonal to this discussion). I'm claiming freezing interfaces for compatibility guarantees is often a bad idea. There needs to be far broader awareness of what you give up when you freeze an interface and commit to support it indefinitely. It's about minimizing zones of ownership within a single computer. Right now our computers have thousands of zones of ownership, and it's easy for important use cases and bugs to fall through the cracks between zones of ownership. Freezing an interface fractures what used to be a single zone of ownership into two.