Earlier quoted context omitted.
Java is a quite awful language honestly. And I use it everyday at work. Generics implementation with type erasure is a pain and complicates things a lot. There is no automatic static type inference and before Java 7 you had to specify twice the generic types in the same statement. This adds a lot of "complexity" or noise when reading some code. Checked exceptions..do we want to speak about all the complexity that the…
I think there's two definitions of simple being used between you and I. Let's use different words instead: obviousness and terseness. Obviousness is how clear the goal of the code is; terseness is how much typing it takes to get there. I'm using simple to mean obviousness; this seems to be in line with the article, as being "clever" typically means exchanging obviousness for terseness. You seem to be taking terseness…
Why most “clever” code ain’t so clever after all
91–100 of 104 posts
Re: Why most “clever” code ain’t so clever after all
#92Earlier quoted context omitted.
Composition increases boilerplate code. With simple inheritance hierarchies there is an inherent advantage in this regard. If you use inheritance you don't need to encapsulate the "base" object and implement all the methods of the interfaces doing most of the time just a routing to the base object, you can just extend from the abstract base object and implement only the methods that you need. Obviously if your hierar…
> If someone says Composition > Inheritance it is like saying Screwdriver > Hammer, a complete non-sense. You're stretching a bit too far. Inheritance is nothing but composition with some default implicit virtual method routing. You admit as much in your comment. If you want tools, it's more like a hammer vs a mallet and a prybar. Same tools, same purpose, just one is bundled.
Re: Why most “clever” code ain’t so clever after all
#93Earlier quoted context omitted.
> If someone says Composition > Inheritance it is like saying Screwdriver > Hammer, a complete non-sense. You're stretching a bit too far. Inheritance is nothing but composition with some default implicit virtual method routing. You admit as much in your comment. If you want tools, it's more like a hammer vs a mallet and a prybar. Same tools, same purpose, just one is bundled.
The purpose is completely different. You use interfaces and composition to decouple the implementation of some objects, you use inheritance to define some object hierarchy. Inheritance specifies the is a relationship, Composition the has a . As you can see these two are totally different concepts.
EDIT: To be clear, in inheritance, the contract being implemented is the implicit contract specified by the parent type. (Assuming you're following the Liskov substitution principle, which you should be.)
Re: Why most “clever” code ain’t so clever after all
#94Earlier quoted context omitted.
I think there's two definitions of simple being used between you and I. Let's use different words instead: obviousness and terseness. Obviousness is how clear the goal of the code is; terseness is how much typing it takes to get there. I'm using simple to mean obviousness; this seems to be in line with the article, as being "clever" typically means exchanging obviousness for terseness. You seem to be taking terseness…
I don't think Java is obvious at all apart the aforementioned simple statements. With generics you have actually no idea of what type you receive at runtime, you receive just an object. If the goal of the code is to return some sensible default for a specific type in Java you cannot use generics. And it's not obvious at all for anyone that doesn't know the generics implementation details. About closures, do you think…
That's kind of the point of generics? I don't understand this argument at all. If you need a specific kind of type, then bound the generic using `extend` and you can use the bounding type's methods and fields. [0]
You're still using a different definition of obvious, despite my having defined it for this use case. For instance:
> Why should be obvious to call stream() on an object that is already a collection?
That's the very definition of obvious. You are making it quite clear that you intend to use this collection as a stream. It's extremely obvious. Same with the buffered reader; Readers are unbuffered, and it's very obvious that you are buffering the reader when you wrap it. (Also, Java has `java.nio.Files.readAllLines` [1], so I'm not sure what you're going on about.)
Extention methods are very non-obvious; where is an extension method defined? The answer is anywhere; it can live in any type you imported. It's not obvious looking at the line of code where execution is going to flow. (And yes, an IDE will track it down for you. Just because an IDE can do the work for you, doesn't mean that there's not work to be done.)
[0] http://docs.oracle.com/javase/tutorial/java/generics/bounded...
[1] http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files...
Re: Why most “clever” code ain’t so clever after all
#95This article hinges on a rather silly fallacy. Luckily the author does us the favor of making his mistake very clear in the curve-fitting analogy; but first look at the code. He gives several examples of poorly-written FP code (which we're supposed to believe is "clever" by virtue of being FP), then introduces some new problem constraint which is carefully selected to make the FP solution break but some equally ridic…
But with mathematics, nitpicking is ~kind of~ the point. For example when dealing with real numbers, you can get away with defining Compact sets as bounded and closed sets; however when you enter a different Topological space, that definition will surely fall apart. So in retrospect, defining compact as bounded and closed was working in your limited test cases (real numbers) but in the real world you really have to e…
In what sense could that even conceivably be a true statement? I could define compact sets as sets which make me think of the color purple and it would be a completely valid definition. Nothing will fall apart. I think you are vaguely referring to the fact that proofs concerning compact sets in general topological spaces are not valid if you replace compact sets with bounded and closed sets, but that's just confusing the term "compact set" with what it refers to; the proofs aren't about the term but about the thing, which doesn't change. If "compact set" meant "bounded and closed" and, say, "cover-compact set" referred to sets where (ahem) every open cover has a finite subcover, then the concept of "cover-compact" will have certain general proofs associated to it and the term "compact" will have a different collection of general proofs associated to it.
So in some ways you're making the same mistake the author did: carefully selecting a certain way to generalize a concept (real -> topological) and a certain ill-conceived claim about the original concept (compact=bounded and closed), and then acting all surprised when, oops!, the claim doesn't generalize.
Re: Why most “clever” code ain’t so clever after all
#96Earlier quoted context omitted.
The purpose is completely different. You use interfaces and composition to decouple the implementation of some objects, you use inheritance to define some object hierarchy. Inheritance specifies the is a relationship, Composition the has a . As you can see these two are totally different concepts.
What is an is a relationship? It is the promise that a type implements a contract. That sounds like an interface to me; implementing interfaces also forms is a relationships. Allow interfaces to be externally defined for a type, and now you have Haskell classes or Rust traits. This isn't a new idea I'm proposing here; it's quite workable and very straight-forward. EDIT: To be clear, in inheritance, the contract being…
Re: Why most “clever” code ain’t so clever after all
#97I run a small dev company. This is the first lessons we teach our programmers. If your code cant be understood by someone else with minimal efforts it is not good enough.
This is a very delicate subject. If the program is using language constructs and can't be understood because the reading programmer doesn't know it, then who's fault is it? why have multiline if/else when a tenary operator can do? I rather read a = b ? c : d; than possibly 4 lines of code, p/s ignore the names of the variable. There are plenty of code out there that are so easy to understand if you read them one line…
It also happens to make testing a lot easier.
It's probably just a crystalization of the old idea of keeping business logic out of your code, but somehow misses the open invitation to create rules engines...
Re: Why most “clever” code ain’t so clever after all
#98Earlier quoted context omitted.
What is an is a relationship? It is the promise that a type implements a contract. That sounds like an interface to me; implementing interfaces also forms is a relationships. Allow interfaces to be externally defined for a type, and now you have Haskell classes or Rust traits. This isn't a new idea I'm proposing here; it's quite workable and very straight-forward. EDIT: To be clear, in inheritance, the contract being…
you were not speaking about interfaces, you were speaking about composition. As I said composition and inheritance are two completely different concepts. And I'm not making up the definitions, is a and has a are very well known concepts in computer science. You can argue ad libitum, but this doesn't change the definition. https://en.m.wikipedia.org/wiki/Has-a https://en.m.wikipedia.org/wiki/Is-a
> Also, maybe eliminate inheritance and force interfaces and composition instead.
Implementing an interface meets all the conditions of an is a relationship; no redefinition is necessary. [0] After all, interfaces are nothing more than abstract base classes with no method bodies to inherit. I haven't argued anywhere that composition defines an is a relationship, so I have no idea where you're pulling that from.
[0] https://en.m.wikipedia.org/wiki/Is-a#Java
EDIT: I really like this article you linked. It has all sorts of things that help me prove my point. For instance, the Rectangle example from the LSP section. If Rectangle were an interface:
interface IRectangle {
double getWidth();
double getHeight();
}
It's trivial to implement concrete Rectangle and Square classes that don't violate any principles. Inheritance, on the other hand, is pretty much guaranteed to be broken as long as Rectangle is mutable, because Square cannot add additional constraints to Rectangle and still pretend to be a Rectangle in all use-cases.Re: Why most “clever” code ain’t so clever after all
#99Earlier quoted context omitted.
I don't think Java is obvious at all apart the aforementioned simple statements. With generics you have actually no idea of what type you receive at runtime, you receive just an object. If the goal of the code is to return some sensible default for a specific type in Java you cannot use generics. And it's not obvious at all for anyone that doesn't know the generics implementation details. About closures, do you think…
> With generics you have actually no idea of what type you receive at runtime, you receive just an object. That's kind of the point of generics? I don't understand this argument at all. If you need a specific kind of type, then bound the generic using `extend` and you can use the bounding type's methods and fields. [0] You're still using a different definition of obvious, despite my having defined it for this use cas…
Re: Why most “clever” code ain’t so clever after all
#100Earlier quoted context omitted.
you were not speaking about interfaces, you were speaking about composition. As I said composition and inheritance are two completely different concepts. And I'm not making up the definitions, is a and has a are very well known concepts in computer science. You can argue ad libitum, but this doesn't change the definition. https://en.m.wikipedia.org/wiki/Has-a https://en.m.wikipedia.org/wiki/Is-a
I'm starting to feel like you're not actually reading anything I write. I specifically include interfaces. To quote myself: > Also, maybe eliminate inheritance and force interfaces and composition instead. Implementing an interface meets all the conditions of an is a relationship; no redefinition is necessary. [0] After all, interfaces are nothing more than abstract base classes with no method bodies to inherit. I ha…
Edit: I don't see any composition in your example, just an interface implementation.