4 ms·
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 t
by jdmichal 10y ago
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 as your definition of simple.
Now Java is the king of obviousness; it's very clear exactly what is being done on every line of code. It pays for it in being very wordy. I don't like inheritance because it breaks obviousness; it's no longer obvious where a virtual call is actually going to be served. With composition, the immediate object has to serve the call, even if it's just to delegate it. The only virtual calls would be dispatching calls to interface methods. And this style isn't expensive after JIT; inlining these kinds of delegations is its primary optimization. (Think getter-method chains that return a field value, a common pattern in Java.)
Lambdas were a step towards terseness, but they sacrifice obviousness to get there. It hides things... What SAM type is a lambda implementing? You have to check to call site; the lambda itself won't tell you. The anonymous class syntax tells you exactly what is being implemented, but that means you have to type more to get there.
Now, I like properties because IMO they optimize both obviousness and terseness. You are obviously making a single property with a getter and a setter, as opposed to defining each separately. And you are more terse by removing the need to define each separately.
- tigershark 10y agoI 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 it is more obvious to define an entire anonymous inner class when you really just need to define a method delegate or an anonymous method? For me it's completely counterintuitive other than it makes my eyes bleed. If I need a local variable I obviously define it, I don't create a class which exposes an encapsulated field and use it. And it's exactly the same thing when I need an anonymous method. When the goal is reading a file why should be more obvious to create a buffered reader that encapsulates a file reader that wraps a file and use it to read when I can just do File.ReadAllLines() in C#? What is the added value of calling stream() on everything before using any enumerable? In C# obviously you just call Extension Methods on an IEnumerable. You even get IntelliSense. Why should be obvious to call stream() on an object that is already a collection?
- jdmichal 10y ago> 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 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.html http://docs.oracle.com/javase/tutorial/java/generics/bounded... [1] http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#readAllLines%28java.nio.file.Path,%20java.nio.charset.Charset%29 http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files...
- tigershark 10y agoThe point of generics is to pass generic arguments to a method/class, as the name says. In Java you are losing every type information and at runtime your method will accept objects, not arguments with a generic type. There are several situation in which preserving the type information is extremely useful. For this reason in Java you still find a lot of libraries that receive a type as argument, while in C# you can just specify the generic type. For me it is far more obvious in the c# way given that I cannot see why I should pass the type of an argument in a generic method. For the streams it is honestly ridiculous. I want to apply a filter, a map, a reduce or wathever to an Iterable. The stream is a very well known and completely different concept and it is widely used in reactive programming, they just stole that concept to use it in a completely non obvious way. For the other streams I still can't see how it is obvious that I should do manually all that wrapping that is completely counterintuitive and makes you lose track of the code purpose. Finally extension methods are perfectly obvious. They are just syntactic sugar for static methods, I hope that at least you agree that static method are the gist of obviousness.