5 ms·
> The behavior is not fully captured by the interface - if it was, it wouldn't be an interface, it would be an implementation. I think your argument is weakene
by cbsmith 10y ago
> The behavior is not fully captured by the interface - if it was, it wouldn't be an interface, it would be an implementation.
I think your argument is weakened by the reality that even "behaviour" has plenty of abstraction in it... particularly if you are using a compiler. You've got the compiler, library linkages (and to different libraries), the OS's abstraction, and of course these days there's usually a hypervisor in there. Then there's the abstractions in the hardware... You just can't get away from it.
Good interfaces allow encapsulation, which tends to be very helpful, although there is a point where it does more harm than good.
> That subtlety of the design process is completely lost by this love of abstraction where it is assumed that anything with an abstract interface is completely flexible whereas anything without one is not.
It's all abstract. Design is concerned about the rightabstraction. The wrong abstraction gives you no flexibility, or no flexibility where you need it, or just a ton of unneeded complexity. Abstraction for abstraction's sake suggests a lack of design.
- userbinator 10y ago> Abstraction for abstraction's sake suggests a lack of design. And yet a surprisingly large number of people think "good" design is entirely about adding abstractions until no more can be added. The classic example of this is enterprise Java, where designs are almost always overly abstract and flexible, but only in these narrow directions that were thought to be where extreme flexibility will be required in the future; and inevitably, the flexibility that's eventually needed turns out to be in a completely different direction.
- catnaroek 10y agoThe real problem is abstraction leaks. When an abstraction leaks, the user of the abstraction is forced to think both about the abstraction and its internal implementation, which results in a net increase in the cognitive burden of understanding the code. However, Java doesn't lend itself to designing very tight abstractions, since all but the most elementary arithmetic operations can fail in utterly miserable ways. If you read a line of code like: someMap.get(someList.length()).someMethod() In how many ways can it throw an exception? Using temporary variables doesn't help: it only makes less things go wrong per expression or statement, at the price of making each individual expression or statement do less work for you. Fortunately, there exist languages that offer less room for things to go wrong.
- cbsmith 10y agoMuch as with generics in C++, the correct approach generally tend to be too assume exceptions can be thrown at any time. Java's try-with clauses make that a bit more natural than it used to be. Ironically, I think a lot of Java's abstraction pain comes from having much more fixed behavior. The static type system, the late introduction of generics, the large base class hierarchy, and the concern with backwards comparability means you've got a ton of behavior and interfaces that are locked down with specific (often poor) abstractions.
- catnaroek 10y ago> Ironically, I think a lot of Java's abstraction pain comes from having much more fixed behavior. Fixed behavior isn't necessarily a bad thing. What is always a bad thing is when types don't accurately capture what your program really means. Java's own collections documentation says: “To keep the number of core interfaces small, the interfaces do not attempt to capture such subtle distinctions as mutability, modifiability, and resizability. Instead, certain calls in the core interfaces are optional, enabling implementations to throw an `UnsupportedOperationException` to indicate that they do not support a specified optional operation. Collection implementers must clearly document which optional operations are supported by an implementation.” https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html https://docs.oracle.com/javase/8/docs/technotes/guides/colle... In Java, this API design style is the norm rather than the exception, which validates the criticism coming form dynamic language advocates: “You still need to use tests, so why bother with types?” The only way forward is to use types in a way that actually eliminates the need for (some) nontrivial tests. At the core, the fundamental problems with Java are: (0) Its type system is too nominal. Every notion, primitive or derived, needs a separate name. The result is that making crisp distinctions takes more effort than programmers are willing to make. In a structurally typed system, a derived notion is just a combination or more basic ones, whether you give the combination a name or not. (1) It doesn't offer a principled way to express that an operation can naturally have multiple kinds of results. And such operations abound in practice! For example, if you try to get the value associated with a key in a container, the key might or might not be there. Or, if you try to get the i-th element of a list (assume 0-based indexing and nonnegative i for the sake of the example), then i is either a valid index or j positions after the end of the list. None of these possible results is intrinsically “wrong”, but Java can only express operations with one kind of correct result.
- cbsmith 10y agoChoosing the wrong abstraction is an occupational hazard with software development. ;-) In a lot of cases in enterprise Java, it felt to me like the problem was exacerbated by commercial interests that had an abstraction to sell, and needed to find use cases for it.
- contravariant 10y agoIn their defense mathematicians have gained huge advances in algebra (and other areas) precisely by abstracting away all unnecessary parts (most notably by Emmy Noether). Of course working out which parts are necessary and which aren't is a very subtle process, and one of the areas of programming where a mathematical background can be a huge advantage.
- cbsmith 10y agoYou nailed it. Getting the right abstraction is very hard. One does one's best, and generally fails miserably.