Option and getOrElse in Scala

An Option can be thought of as a container (or proxy) for an object to prevent null pointer exceptions.

The paradigmatic case is returning an Option type from function calls, instantiated by either a Some or None subclass:

def toInt(in: String): Option[Int] = {
    try {
        Some(Integer.parseInt(in.trim))
    } catch {
        case e: NumberFormatException =>; None
    }
}

Some or None can be matched to functions by consumers:

toInt(someString) match {
    case Some(i) =>; println(i)
    case None =>; println("That didn't work.")
}

Say we have this type:

case class Person(age: Int)

In the case where it has a value:

val person = Option(Person(100))   > subclass Some
val age = person.map(_.age +5)     > Some(105)
age.getOrElse(0)                   > 105

In the case where it has no value:

val person = Option[Person] = Option(null)          > None
val age = person.map(_.age +5)                      > None
age.getOrElse(0)                                    > 0

You can see how getOrElse specifically requires the developer to specify the action for the null case.

Advertisements

Refactoring – towards a better definition

According to SAFe, refactoring is

“modifying an entity, such as a module, method or program in such a way that it’s external appearance, i.e. its functionality, remains unchanged.”

Refactoring, the author says, may increase speed or address security concerns. According to the preface of Martin Fowler’s book ‘Refactoring’, refactoring is

“changing a software system in such a way that is does not alter the external behaviour of the code yet improves the internal structure. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. In essence, when you refactor you are improving the design of the code after it has been written.”

Both agree that refactoring leaves the system ‘externally’ unchanged. Both agree it makes no sense to say, as I have heard developers say in the past, ‘I want to refactor the code to add this new feature for the end user.’ That is not a refactoring; it is a new feature. I have a question about this. Are performance improvements such as adding internal caching or adding an index examples of refactoring? SAFe thinks so. But is a performance improvement not a change for the end user? Moreover, you can make a horrible mess in the code when you implement a performance improvement. Is it helpful to call that a refactoring? Do we want to be able to say ‘I refactored the IdLookup component to make it faster, but I made a mess; we need to refactor it again to make it cleaner.’ Performance improvements are non-functional improvements or, better, quality improvements that affect external users. This is not exactly refactoring, which has a focus on the ‘internal’.

What about moving configuration from code to an external config file, to improve maintainability or flexibility? This is another example of refactoring given by SAFe. I can see how, from a certain point of view, this could be thought of as an ‘internal’ change. But some ‘external’ stakeholders will care greatly about this change. The time it takes to deploy a configuration change can be greatly affected by externalizing configuration from a hard-coded value, since the code does not have to be recompiled and rebuilt. Build and package enhancements are quality improvements that affect external stakeholders such as testing and operations, which is not, strictly speaking, refactoring.

When we do TDD, we say we ‘refactor’ after each passing test. What does this really mean? At it simplest, this typically involves removing duplication, reducing complexity, applying certain patterns, fixing style violations, and so forth. Note that these are quality attributes of the system that are generally measurable with static analysis and code review. And there is a stakeholder who cares about these qualities; the dev team as a whole, the team lead, or, better, QA.  These improvements are about code quality, technical debt, and primarily affect the internal development team.  These are true refactorings.