I don’t know Java books, but I would like to react to this part anyway:
Most Java programmers seem to basically not believe in many of the ways I have learned to write good software (e.g. be precise and concise, carefully encapsulate state, make small reusable modular parts which are usually pure functions, REPL-driven development, etc. etc.) or they apply them in ways that seem unfortunate to me.
There are much more bad programmers than good programmers, so any language that is sufficiently widely used is necessarily a language mostly used by bad programmers. (Also, if the programming language is Turing-complete, it also means that you can reinvent any historical bad programming practices in that language.) On the other hand, there are often genuine mistakes in the language design, or in the standard libraries. So here is my opinion on which is which in Java:
precise and concise—sorry, no can do. Using proper formatting, merely declaring a read-only integer property of a class will cost you five lines not including whitespace (1 line declaration, 1 line assignment in constructor, 3 lines read accessor). (EDIT: Removed an obsolete info.)
carefully encapsulate state—that’s what the “private” and “public” keywords are for. I don’t quite understand what could be the problem here (other than bad programmers not using these keywords; or the verbosity).
make small reusable modular parts which are usually pure functions—this is not how Java is typically used, but it can be done. It has the garbage collector. It has immutable types; and for the mutable ones, you could create an immutable wrapper class (yes, a lot of writing again). So you can write a module that gets immutable values as inputs, returns them as outputs, which is more or less what you want. The only problem is that “immutability” is not recognized by the language; you only know that a class is immutable by reading the documentation or looking at the source code; you cannot have the compiler check it for you.
REPL-driven development—it could be technically possible to make an interactive functional shell, and maybe someone already did it. But that’s definitely not how Java is typically used. A slightly more traditional solution, although not exactly what you want, would be to use the Groovy language for the interactive shell. (Groovy is more or less a “scripting Java”. Very similar to Java, with minor differences; can directly call functions from the Java program it is included in.) The traditional solution is to do unit testing with JUnit.
As a beginner, avoid Java EE like hell. That is the really ugly part. Stay with Java SE until the Stockholm syndrome kicks in and you develop feelings for Java, or until you decide you do not want to go this way.
Feel free to give me a short example in other programming language or pseudocode, and I will try to write it in Java in a functional-ish style.
I might try Groovy for the REPL stuff—I was trying Clojure before, but I ran into problems getting it to get the dependencies and stuff all into the REPL (I work on a big project that uses Gradle as a build system, and Clojure doesn’t usually use Gradle.)
carefully encapsulate state—that’s what the “private” and “public” keywords are for. I don’t quite understand what could be the problem here (other than bad programmers not using these keywords; or the verbosity).
One pattern I have in mind here: if I have some algorithm I have to perform that has some intermediate state, I will break it down into some functions, pass the state around from function to function as necessary, and wind up composing five or six functions to get from the start to the end. Java programmers seem to often instead do something like make a class with the five or six functions as methods, and then set all the state as fields on the class, which the methods then initialize, mutate, and consume, and call the methods in the right order to get from the start to the end. That seems a lot harder for me to read because unless there is also great documentation I have to read very closely to understand the contract of each individual method.
(I’m also incidentally confused about when in Java people like to use a dependency injection tool like Guice and when people like to pass dependencies explicitly. I don’t think I understand the motivation for the tool yet.)
Java programmers are usually familiar with procedural programming, not functional. The older ones are probably former C/C++ programmers, so they mostly write C/C++ code using Java syntax. That probably includes most textbook authors.
Nothing in Java prevents you from having intermediate states, and composing the functions. You just have to specify the data type for each intermediate state, which may require creating a new class (which is a lot of typing), or typing something like Pair, List>, so yeah, there are inconveniences.
As a crazy creative solution, I could imagine wrapping the “class with the five or six functions” into multiple interfaces. Something like this:
I don’t know Java books, but I would like to react to this part anyway:
There are much more bad programmers than good programmers, so any language that is sufficiently widely used is necessarily a language mostly used by bad programmers. (Also, if the programming language is Turing-complete, it also means that you can reinvent any historical bad programming practices in that language.) On the other hand, there are often genuine mistakes in the language design, or in the standard libraries. So here is my opinion on which is which in Java:
precise and concise—sorry, no can do. Using proper formatting, merely declaring a read-only integer property of a class will cost you five lines not including whitespace (1 line declaration, 1 line assignment in constructor, 3 lines read accessor). (EDIT: Removed an obsolete info.)
carefully encapsulate state—that’s what the “private” and “public” keywords are for. I don’t quite understand what could be the problem here (other than bad programmers not using these keywords; or the verbosity).
make small reusable modular parts which are usually pure functions—this is not how Java is typically used, but it can be done. It has the garbage collector. It has immutable types; and for the mutable ones, you could create an immutable wrapper class (yes, a lot of writing again). So you can write a module that gets immutable values as inputs, returns them as outputs, which is more or less what you want. The only problem is that “immutability” is not recognized by the language; you only know that a class is immutable by reading the documentation or looking at the source code; you cannot have the compiler check it for you.
REPL-driven development—it could be technically possible to make an interactive functional shell, and maybe someone already did it. But that’s definitely not how Java is typically used. A slightly more traditional solution, although not exactly what you want, would be to use the Groovy language for the interactive shell. (Groovy is more or less a “scripting Java”. Very similar to Java, with minor differences; can directly call functions from the Java program it is included in.) The traditional solution is to do unit testing with JUnit.
As a beginner, avoid Java EE like hell. That is the really ugly part. Stay with Java SE until the Stockholm syndrome kicks in and you develop feelings for Java, or until you decide you do not want to go this way.
Feel free to give me a short example in other programming language or pseudocode, and I will try to write it in Java in a functional-ish style.
Lambda syntax is definitely present in the currently available version of Java. I use it on a daily basis.
Oops. The version is out there for almost a year. I missed it, because we do not use it at work.
Embarassing to find this out after pretending to be a Java expert. Does not add much credibility. :D
No worries, you obviously know what you’re talking about in general. I just wanted to make sure false impressions don’t spread.
I might try Groovy for the REPL stuff—I was trying Clojure before, but I ran into problems getting it to get the dependencies and stuff all into the REPL (I work on a big project that uses Gradle as a build system, and Clojure doesn’t usually use Gradle.)
One pattern I have in mind here: if I have some algorithm I have to perform that has some intermediate state, I will break it down into some functions, pass the state around from function to function as necessary, and wind up composing five or six functions to get from the start to the end. Java programmers seem to often instead do something like make a class with the five or six functions as methods, and then set all the state as fields on the class, which the methods then initialize, mutate, and consume, and call the methods in the right order to get from the start to the end. That seems a lot harder for me to read because unless there is also great documentation I have to read very closely to understand the contract of each individual method.
(I’m also incidentally confused about when in Java people like to use a dependency injection tool like Guice and when people like to pass dependencies explicitly. I don’t think I understand the motivation for the tool yet.)
Java programmers are usually familiar with procedural programming, not functional. The older ones are probably former C/C++ programmers, so they mostly write C/C++ code using Java syntax. That probably includes most textbook authors.
Nothing in Java prevents you from having intermediate states, and composing the functions. You just have to specify the data type for each intermediate state, which may require creating a new class (which is a lot of typing), or typing something like Pair, List>, so yeah, there are inconveniences.
As a crazy creative solution, I could imagine wrapping the “class with the five or six functions” into multiple interfaces. Something like this:
Old version:
New version:
This would force users to write things like:
I also admit my colleagues would kill me after doing this, and the jury would probably free them.