Wednesday, August 16, 2017

Chapter 4 Scala book review and notes by Rick Hightower Part 3

Chapter 4 Scala book review and notes by Rick Hightower Part 3


Chapter 4 Scala book review and notes by Rick Hightower
Chapter 4 Scala book review and notes by Rick Hightower. (Note link is to second edition book, but I am reading the first edition because that is the one I own).
Notes and random thoughts. Any opinions stated in this document are not carved in stone. Read at your own risk.
Chapter 3 spoke of the ill of var versus val. Chapter 4 ChecksumAccumulator uses a var. Earlier I noticed the use of semicolons in the Scala examples, which I thought strange given Scala does not need them. Here I see methods that use return which Scala does not need. When I write Scala, I do it with IntelliJ so it can warn me not to use this superfluous concepts. I guess Author(s) did not have IntelliJ available.
Spoke too soon. They just dropped the return (but the semicolons in the other examples were never mentioned so probably wont be there in the second edition).
Ok so vars and val are public by default, which I think means is that Scala generates sum() and sum(int) by default (accessor methods). But that is what it seemed to do when I was using it with/Java.
The recommended style for methods is in fact to avoid having explicit, and especially multiple, return statements. Instead, think of each method as an expression that yields one value, which is returned. This philosophy will encourage you to make methods quite small, to factor larger methods into multiple smaller ones. On the other hand, design choices depend on the design context, and Scala makes it easy to write methods that have multiple, explicit returns if thats what you desire. --Odersky, Martin; Spoon, Lex; Venners, Bill (2010-12-13). Programming in Scala: A Comprehensive Step-by-Step Guide (Kindle Locations 1408-1412). Artima Press. Kindle Edition.
Ok. Tons of one liner methods that are just expressions. Oh joy. That will take some getting.
As mentioned in Chapter 1, one way in which Scala is more object-oriented than Java is that classes in Scala cannot have static members. Instead, Scala has singleton objects. A singleton object definition looks like a class definition, except instead of the keyword class you use the keyword object. Listing 4.2 shows an example. --Odersky, Martin; Spoon, Lex; Venners, Bill (2010-12-13). Programming in Scala: A Comprehensive Step-by-Step Guide (Kindle Locations 1455-1458). Artima Press. Kindle Edition.
So static methods are bad, and we use singleton objects instead.
I too was once a singleton lover. If you prevent yourself from doing singletons for 1 year straight, you will find out one thing....singletons are evil. If you have not prevented yourself for 1 straight year, you have no right to talk. That is like never eating ice cream and saying you know the fries are better. Maybe the fries are better but shut up until you have tried the ice cream first! You can still represent the real world and only have one thing (though naturally you just need to make sure you only instantiate one). That is usually done in some top level module and passed down to services (ie. Dependency Injection). The worst thing I have found out about singletons is when it comes to wanting to write reset code (specifically in tests). In a no singleton system, I can just new Service() and if it was designed right, the use of static keyword is rarely used except maybe for constants and all state will be reset....Great for the test setup method. So, you are suggesting that your reset is accomplished through the constructor? This forces the constructor to look for previously existing conditions on the real world device and do the appropriate things to knock the device down before setting it back up again. Okay, I can buy that. Now, how do you "make sure" that only one instance of the device is present in your system? --http://c2.com/cgi/wiki?SingletonsAreEvil
I find the dogmatic proclamations of evilness are evil and dont see much difference between static methods which are associated with the Class object and having an object Foo notation in a language (there are pros and cons to both approaches). I respect his thoughts, but...
My point is... So this book says dont use static methods and singletons are good, and classic Spring DI, IoC, etc. injections and traditional Java say that singletons are evil. Joy. No wonder people quit being developers and become managers. So much conflicting dogma to deal with.
I actually dont care. When in Rome (Scala), I will use object singleton, when back in Java/Spring world I will not use singleton and when not in Spring/Guice world of DI,.... When back in Boon/QBit with no Spring world I will use static methods where they make sense, and design by interface most of the time. I even design by interface when I write Python, and it drives my Python pals batty. I believe in the concept. I believe in mock objects, and testability.
I finally learned how to write a proper main method. I have been calling my Scala main from a Java main method. (My hidden super power is to hack things to work until I find time to do it the right way. First make it work. Then fix it up to work right. It is a skill brought on by always meeting schedule deadlines even if it means sacrificing personal health, and always cleaning up tech debt even if it is months later after 1.0 has been delivered and the project has not been canceled. There is the right way, and there is right now way. You have to pick you battles. End users dont care if you are using the right way. They care if there app works. You care because later you have to maintain this ball of goo, and your name and reputation is on it. I write comments a lot on contracts because I want to be able to hand this code off to someone else when I move on, and/or when I come back to this code in three months or a year, I want to be able to read what I wrote. Which reminds me, I add less comments to QBit then I do to code I use on contracts. QBit microservices lib is my calling card. It should have a lot more comments.)
object ReadFileShowWithLinesScala {

def main(args: Array[String]) {
if (args.nonEmpty) {
val lines = Source.fromFile(args(0)).getLines().toList

val longestLine: String = lines.reduceLeft(
(a, b) => if (a.length > b.length) a else b
)

val maxWidth: Int = widthOfLength(longestLine)
for (line <- lines) {
val numSpaces: Int = maxWidth - widthOfLength(line)
val padding = " " * numSpaces
println(padding + line.length + " | " + line)
}
}
}

def widthOfLength(s: String) = s.length.toString.length
Why I had to wait until chapter 4!
I dont have to do this shit now.
package foo;

import scala.collection.JavaConversions;
import scala.collection.mutable.Buffer;
import java.util.Arrays;
import java.util.List;

public class ReadFileShowWithLines {


public static void main(String... args) {

... // Java code

//This was how I was launching Scala code since they decide
//not to show me how to do this until Chapter 4,
//BTW I have some production code that does this because I could not find this online easily.
Buffer<String> seq = JavaConversions.asScalaBuffer(Arrays.asList(args));
ReadFileShowWithLinesScala.main(seq);
}

}
Thanks Chapter 4. Thanks for finally telling me what a Scala main method looks like. I tried everything and gave up and called it from Java.
One difference between Scala and Java is that whereas Java requires you to put a public class in a file named after the class�for example, youd put class SpeedRacer in file SpeedRacer.java�in Scala, you can name .scala files anything you want, no matter what Scala classes or code you put in them. In general in the case of non-scripts, however, it is recommended style to name files after the classes they contain as is done in Java, so that programmers can more easily locate classes by looking at file names. --Odersky, Martin; Spoon, Lex; Venners, Bill (2010-12-13). Programming in Scala: A Comprehensive Step-by-Step Guide (Kindle Locations 1526-1531). Artima Press. Kindle Edition.
Yeah... so Java forces the convention and Scala does not. I think will become important when we are working with a lot of case classes. I wish they added case classes to Java. I am sick of Java beans which is almost reason enough to switch to Scala. Almost.

Application trait

This is probably why I could not easily google how to do a Scala main method. You dont, you use the Application trait.
To use the trait, you first write "extends Application" after the name of your singleton object. Then instead of writing a main method, you place the code you would have put in the main method directly between the curly braces of the singleton object. --Odersky, Martin; Spoon, Lex; Venners, Bill (2010-12-13). Programming in Scala: A Comprehensive Step-by-Step Guide (Kindle Locations 1562-1565). Artima Press. Kindle Edition.
Ok.. I like this. Damn Odersky, quit making me like Scala. This defeats my previous narratives.
Ok.. Application trait is deprecated. So that was a quick elation with an even quicker deflation. Maybe I should not be using a book that is five years old. Maybe I should commit to going through a book before I buy it.
Here I am...
http://www.scala-lang.org/api/2.10.1/index.html#scala.Application
So it seems that I can use the App instead of the Application trait. Chapter 1-4 does not really cover a trait yet, but since Scala people can never shut up about how great Scala is, I sort of know what a trait is already, and have in fact already used them. Although, I wish I knew more.. Must read on...
Here is the code refactored to use App.
package foo

import scala.io.Source

object ReadFileShowWithLinesScala extends App {
def widthOfLength(s: String) = s.length.toString.length


if (args.nonEmpty) {
val lines = Source.fromFile(args(0)).getLines().toList

val longestLine: String = lines.reduceLeft(
(a, b) => if (a.length > b.length) a else b
)

val maxWidth: Int = widthOfLength(longestLine)
for (line <- lines) {
val numSpaces: Int = maxWidth - widthOfLength(line)
val padding = " " * numSpaces
println(padding + line.length + " | " + line)
}
}

}
It is kicking Java ass just a little bit more now.
package foo;

import org.boon.IO;
import java.util.List;

import static java.lang.System.out;
import static org.boon.Str.lpad;
import static org.boon.Str.str;

public class ReadFileShowWithLines {


public static int widthOfLength(final