Tuesday, August 23, 2016

Law of Demeter and perhaps something more strict that isn't quite

Looking at a piece of code today and thinking about the consequences of discovering things about objects a method is passed.

If I have a method that is responsible for performing a mapping, let's call it from type A to type B so

A -> B

or to use a more Scala-ish syntax:

f(A): B

then I might argue that the method f, should not attempt to enhance in any way the object of type A.  If the properties that require the construction of B are not immediately present in A as per the law of Demeter, or if we recast the system slightly such that A may represent a composite, the set of objects represented by A, then there should be an intermediary method that gathers the required information for the mapping operation and creates an enhanced context.  This would be a separation of concerns, one being the enhancement of the object of type A, and the other the operation of generating a B.

A -> B then expands to A -> C -> B

where C is the set of information required to construct B, so we might get two methods:

constructB(C): B so that our type arrow is C -> B

and enhance(A): C so that the type arrow is A -> C

This means that should somebody construct logic that does some kind of side-effecting operation in enhance(), that operation can be isolated from the mapping.

This means that when we look at a mapping function, we can say it should not contain ANY additional type arrows within.  It should only access and map properties from the composite C to create an object of type B.  Any additional mapping or derivation that occurs within, or the processing of a type arrow breaks separation of concerns.

This feels pretty strict, but I'm looking at code today where if that rule had been followed, a very nasty side-effecting piece of code that was buried several levels deep in an abstraction would never have been permitted!

Thursday, August 20, 2015

Java 8 - Exploring FunctionalInterface

A few days ago I posted a highly frustrated post on Facebook about Java having Lambdas, but not having any Try<> mechanism meaning that in most cases, you're left declaring a try block inside a lambda.  Turns out there's a different way to approach this that gives a different resolution.

Say you're a Scala person like me, and have discovered that checked exceptions actually are more of a pain than they're worth, and believe they actually break SOLID engineering principles, particularly the part about encapsulation.  When first exploring Java 8, it seemed to me that the lack of a Try<> type was pretty bad news.  I still think Try<> would be useful, but there is at least a way to get around having a very ugly try/catch block inside a lambda.

So Java, I take it back - you've done something weird, but cool.  Turns out you don't need to worry about Function<> specifically; any interface that declares only a single method is functional, and will be eligible for syntax magic.  (Though I don't like magic, it's at least traceable magic).  It's perfectly valid to declare:

@FunctionalInterface
public interface ExceptionalFunction<A, B> {
    B f(A a) throws Exception;
    default B apply(A a) {
        try { return f(a); }
        catch (Exception e) { throw new RuntimeException(e); }
    }
}

and then your call that uses thusly:

public <T> T withMyThing(ExceptionalFunction<MyThing, T> f) {
  f(fetchMyThing);
}

and then

withMyThing(x -> isAwesome(x));

or because apparently you can:

withMyThing(this::isAwesome(x));

This means that if isAwesome() throws a checked exception, our wrapper will capture it and it will be suppressed down to a runtime exception.  I'm not going to debate the merits of that here, only to say that here be dragons, and that probably breaks expected behavior in many situations, but, at the same time can be pretty useful too, particularly in Test Suites, where exceptional behavior is either being explicitly elicited, or explicitly checked against.  Though I supposed that if you're eliciting it, getting back a RuntimeException containing the expected might break the test case... like I said, here be dragons.

Though we might have noticed that now apparently interfaces in Java can have method bodies... Uh wut?  This is doesn't seem any different to me than having say:

@FunctionalInterface
public abstract class ExceptionalFunction<A, B> {
  public abstract B f(A a) throws Exception;
  public <B> B apply(A a) {
    try { return f(a); }
    catch (Exception e) { throw new RuntimeException(e); }
  }
}

I suppose it does have the syntactic implication, that the function you're declaring could be something other than public, which in a function interface context wouldn't make sense, but perhaps that should be a compiler error rather than changing what an "Interface" fundamentally means in Java?

So be here yea forewarned: Interfaces in Java 8 may have method bodies!!

Wednesday, July 9, 2014

Software Development -- Why we need software engineers

I frequently see posts by some folks talking about how software development is the realm of the elite and erudite, requiring much training and arcane knowledge. Somehow, these people seem to think this is a bad thing, or an odd thing that is in need of remediation. It doesn't. And there are many simple analogies that can help demonstrate why.

The most basic one goes as follows. As a business owner, you have an office probably, or a place of business. This place has electrical systems, and plumbing, and a building with doors and a roof and other such infrastructure. If your sink gets clogged, you might pour some drano down it and try to unclog it. Anything beyond that - you call a plumber. If a roof leaks, you call a roofer. If your door needs fixing, you call a carpenter. Without training, you can't just make a new door, or install a new sink, or do a major roof repair. These things require skill and training to do well, and in some cases even at all. You don't know which tools you need, and you certainly don't own them. As a business person, you also understand that your time is much better invested in doing things you are an expert at doing, and using that revenue to pay someone who is an expert in plumbing to do that rather than wasting ten times the effort of our own time trying to do it yourself. It's called delegation, and whilst I'm no Harvard MBA, I'm pretty sure it's a major component in how you make a business successful. What on earth would posses you to believe that given you have zero training and knowledge of computer systems, that you could whip up a piece of software that was anything more than the software equivalent of drano down a sink, or duct tape on a pipe?! Or to the people writing these kinds of articles, what on earth would posses you to think that what you do is any less difficult than what many professionals do, and is something that any ordinary Joe could manage with little or no training? Software deals with many highly complex interlocking problems and requires training and specialized knowledge to do, and certainly to do well. You have to know about the tools that exist, and you have to know how to use them. For a software engineer who does this full time and then some, the range of tools and techniques available is dizzying, far more than is available to a carpenter or a plumber. The notion that a regular Joe should be able to write software, of any kind, anything really beyond basic spreadsheet macros is ridiculous. For decades, people have been trying to make these magical 4GLs that allow you to plug big blocks of awesome together to make systems that get things done. To date, they have all failed to one degree or another.

I believe that most people, even programmers often have little idea about what we actually do every day. What we do everyday is mostly not engineering. That's right, I'm a programmer, and what I do everyday is mostly NOT engineering. There is an engineering component, but I believe that most of what I do every day is philosophy.

Programming is a discipline that is more akin to philosophy that it is to engineering, and I believe that this is often true for higher mathematics and higher physics also, though I'm not in those fields, so I may be wrong.

What we do everyday is reason about the universe around us, and then turn it into a model that the computer executes. Most of the programming we do is essentially a simulacrum. It's a mirror of the real word, defined by us, the philosopher and executed by a machine, the computer. How good our software is, is typically far more to do with how well we can reason about our problem domain and far less about how good an engineer we are. Any programmer who has seem code written by Math people has an idea about this. From an engineering perspective, the code is often pretty terrible, but the things it can do are amazing, and us lowly engineers often don't have the mathematical knowledge and understanding to reason about it, and thusly can't understand it. The mathematicians software is brilliant because she knew a language with which to describe the universe that was very advanced, and could precisely describe that universe back to a machine to do interesting things with it.

Why do you think people do postgraduate work in science on a thing called a PhD, it's not a Doctor of Science, it's a Doctor of Philosophy.

To describe our model of the universe to the computer, we need engineering, and that is honestly the part that is pretty tedious after you've been around the wheel a few times. The languages we user are arcane because a computer has to know precisely what to do. There can be no ambiguity to a computer, and when there are ambiguities in our code, that's one major cause of bugs. Humans are very bad at describing things precisely, but it's the only way a computer can function and so we have a disjoin. We also have a disjoin because our model of the universe is typically very small, and only represents a very very small part of the universe. And sometimes the universe we're modeling is centered around things that only exist as constructs in human conception, like money. They don't have solid rules and have weird exception cases and often don't make a lot of sense from a purely logical perspective. They are models of human behavior, which humans who study psychology and neurology don't even fully understand, so what chance as a software developer do we have, trying to describe it for a computer to understand?! The raw fact of the matter is that that model is incomplete and imperfect. No amount of hand-wringing is ever going to make it less than that because we ourselves don't have a perfect model of the universe, and certainly not of human behavior, all we have are approximations.

I also am coming to believe that engineering, the actual implementation of our models is a secondary concern to the philosophy. That is to say regardless of what languages and methodologies we use, if our fundamental model of the universe, the shapes of the pieces of our simulacrum we defined in our mind are a poor fit, no amount of brilliant engineering will make the software good. The most elegant code that doesn't serve the user is ultimately not going to be useful and have a long life beyond being a teaching aid. The most ugly code that serves the user well, is going to have a long life, even if it is the bane of the engineers maintaining it, and we've all worked on that kind of code in our career. That legacy app that is just so critical to the business that it can't be left to die, despite it being the most horrible piece of code ever conceived? That little gem, is a wonder of philosophy, but a travesty of engineering, and guess what, it's value as a model as a machine as a tool for the business outweighs it's ugliness as a work of engineering.

So I would call programmers to be philosophers and historians first, and engineers second. Take the time to gain a better understanding of the world around us first, learn about what other programmers have done before you and the challenges they faced second, and then be a syntax god and engineer third. And most of all, what we do, day in and day out is hard. It's part philosophy, part art, part music, part mathematics and part engineering. To be good at programming, you have to be at least capable in all of those disciplines, and whilst engineering might be third, it's still really important. Not many people have the capacity to be cross-disciplined to that level, programmers have to be, and that quite frankly, makes us pretty special, and that's okay!

Saturday, April 5, 2014

Subcut with GlobalSettings and Filters in the Play Framework

Quick post on an issue with Filters when using the Subcut template from activator.  If you use the Subcut template from TypeSafe Activator, and decide you want to use Filters on your Global object, you will likely run into this issue:

java.lang.ClassCastException: Global cannot be cast to play.GlobalSettings

or you will see that you can't call super.doFilter(next) as suggested in the documentation.

This is because there are two GlobalSettings classes in Play, one which is a Java class, and the other that is the Scala trait.  In most scala applications you will be extending a Scala trait. The Subcut template uses the Java class, and that's because the Subcut template relies on your Global being an instance, rather than a companion object, and the Scala GlobalSettings trait only works on an object, not an instance.

You can fix this problem by extending from both of these classes:

class Global extends GlobalSettings with play.api.GlobalSettings {

  override def doFilter(next: EssentialAction): EssentialAction = {
    Filters(super.doFilter(next), LoggingFilter)
  }

Thank goodness for traits!

Thursday, April 3, 2014

Raising Option[T] to Try[T] - Handling error situations with aplomb

I've started using this pattern for dealing with situation where functions I'm working with may return an Option[T] for a given query, but the contextual meaning of returning None is really an error case. A good example of this is looking up an Item in a database by it's ID based on a shopping cart. If the application receives an item ID during a shopping cart process of an item that doesn't exist in the DB, then returning None on the DAO access is fine, but the upshot is an error condition. The application has received bad data somewhere along the way, and this should be manifested as an Exception state, which I'm choosing to encapsulate in a Try[T] so I can pass it cleanly up the stack rather than violating SOLID by throwing an exception, which I know is a subject of some debate.

To help with this, I wrote a simple wrapper class that I've called MonadHelper thusly:

object MonadUtil {
  implicit def option2wrapper[T](original: Option[T]) = new OptionWrapper(original)

  class OptionWrapper[T](original: Option[T]) {
    def asTry(throwableOnNone: Throwable) = original match {
      case None => Failure(throwableOnNone)
      case Some(v) => Success(v)
    }
  }
}

This allows one to construct a for comprehension elevating None returns to an error state somewhat gracefully like this slightly contrived example:

case class CartItemComposite(account: Tables.AccountRow, item: Item)

trait AccountDAO {
  def findById(userId: Long): Option[Tables.AccountRow]
}
trait ItemDAO {
  def findById(itemId: Long): Option[Item]
}

def findShoppingCartItem(itemId: Long, userId: Long)(userDAO: AccountDAO, itemDAO: ItemDAO): Try[CartItemComposite] = {
  for {
    user <- userDAO.findById(userId).asTry(new Throwable("Failed to find user for id " + userId))
    item <- itemDAO.findById(itemId).asTry(new Throwable("Failed to find item for id " + itemId))
  } yield CartItemComposite(user, item)
}


But you get the idea. You can check a set of conditions for validity, giving appropriate error feedback at each step along the way instead of losing the error meaning as you would with simple Option[T] monads in a way that looks less than insane.

Don't know if this is a great pattern yet, but, I'm giving it a whirl!

Wednesday, November 6, 2013

SimpleDateFormat sillyness

Ran into an amazingly dumb bug yesterday. I would say that this is clearly a bug in the behavior of SimpleDateFormat in Java. Why is it that when I give it a date that looks valid, and a format string that's not right, and in fact contains invalid numbers, it will go ahead and parse my date string producing a ridiculous result. But not so ridiculous it's obvious, or in fact, just throws an Exception, which for my money would be the desired outcome.

So this is the scenario. Parsing a date like this:

val dateStr = "2013-02-04 05:35:24.693 GMT"

with the date parsing string:

val dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss.SSS z")

If you're paying very close attention, you will see the problem here; the month component is repeated. This yields the following date in the resulting Date object: "Tue Nov 03 21:00:24 PST 2015"

This result is clearly very different than what was sent in. I see two problems here. The date string contained two references to the same field. I can see where sometimes this might be useful, but honestly, I feel like you should have to set a flag or something for this to be silently ignored. In most cases having a reference to the same part of a date within a format string seems like a warning flag at least. The second problem is that the erroneous value for month that was give is beyond the scope of a calendar year. You can't have 35 months in a year. In my opinion this should have thrown an exception. I understand that potentially in some calendar system somewhere on this earth there maybe more than 35 'months' in a year or something, but this is very unexpected behavior, way outside of what I would considered normal.

In short, if you have a date string that is being parsed and coming out the other end with a very strange unexpected and wrong result, there's a good chance the format string is off, and probably only very slightly and in a way that's hard to spot without a very very careful eye.

Monday, June 10, 2013

On folding, reducing and mapping

I haven't updated in a while, but it's time to get back into doing this blog.

Today I want to do a brief little thing on folding, reducing and mapping. In the past, I've found myself doing things like this when building a SQL query:
val k = Map("name" -> "John", "address" -> "123 Main St", "city" -> "Los Angeles")

(k.foldLeft("")((a,b) => a + " and " + b._1 + " = ?")).drop(6)

Which on the face of it doesn't seem so bad, might have done something not that disimilar using a for loop in Java.  The thing about this is that it's actually kind of stupid.  There is a more idiomatic way to do this.  When you think about it, the initial operation is actually a matter of mapping the input list to a set of string, and then joining those strings with the and clause.  In Scala, the reduce operation essentially does what join does in the new Java, or other languages, but with any list.  When we think about it this way, we can therefore do this:
val k = Map("name" -> "John", "address" -> "123 Main St", "city" -> "Los Angeles")

k.map(x = > x._1 + " = ?").reduce(_+" and "+_)

or:

k.map(x = > x._1 + " = ?").mkString(" and ")

Ultimately ending up as something like:
val query: PreparedStatement = buildStatement(k.map(x = > x._1 + " = ?").mkString(" and "))
k.zipWithIndex.foreach(x => query.setObject(x._1, x._2))

Much cleaner, and more idiomatic.  Some might say this is obvious, but, it wasn't obvious to me immediately, and so I'm gonna guess it's not to others either!