Showing posts with label value object. Show all posts
Showing posts with label value object. Show all posts

Thursday, 3 March 2011

Getting Started with JUnit and TDD in Scala

Dear Junior

As I like the flow of test driven development, it was natural to me to try TDD when starting using Scala. As Scala runs on the JVM and interoperates well with Java it should be easy to just use JUnit. However, it was not totally obvious how to do it, and looking around the net I found no "start from scratch, this is how to do it"-tutorial. Anyway, this is how I did it, starting from scratch.


A First Test - without JUnit

Let's start with writing a test for the now-classical Money-example. Using my IDE at hand (IntelliJ), I created a file 'MoneyTest.scala' and wrote the test checking that one swedish krona is one swedish krona.
class MoneyTest {
  def should_equal_same_amount_same_currency = {
    new Money("SEK", 1) == new Money("SEK", 1)
  }
}
Let us pick this apart. This is a class (MoneyTest) that can be used to create instances of that class. Such an instance ("a MoneyTest") is in other words "an object that can test properties of Money". One of the properties it can test is that Money "should equal same amount same currency". Testing the property is done by running the method.


We have not yet got JUnit in the loop, but this is the anatomy of a unit test in place.


Get it to Compile


To get the test through the compiler we need a Money class as well, which will reside in Money.scala.
class Money(currency : String, amount : Int) {}
Yepp, that's it - class declaration and constructor rolled together.

Now we are in shape having our first unit test and enough implementation to satisfy the compiler. Time to run the test. If we want to we can run it on the interactive read-eval-print-loop (REPL).
scala> new MoneyTest().should_equal_same_amount_same_currency  
res0: Boolean = false
Well, this is actually a failing unit test, giving us the permission to hack away. 


Taking the Red Test to JUnit

However, I have come to be used to JUnit - I like the assert methods, I like how it integrates with my IDE, I like how it integrates with build servers. So, I would like to pimp up this pretty naked unit test to make use of JUnit.

First step was to add JUnit to the Scala project. In IntelliJ I created a new "External Library" named "junit" to which I added junit-4.4.jar - I happened to find it in ~/.m2/repository/junit/junit/4.4/junit-4.4.jar. Then I added the new external library to the project.


Next step is the code. As JUnit is now on the classpath, I can do the imports, annotations, and use the methods I am used to (albeit the import will be Scala-scented). 
import org.junit.Test
import org.junit.Assert._
class MoneyTest {
  @Test
  def should_equal_same_amount_same_currency = {
    assertTrue(new Money("SEK", 1) == new Money("SEK", 1))
  }
}
Looks familiar, doesn't it? Now I can run it from within IntelliJ like any JUnit-test. Running it gives another familiar message:
java.lang.AssertionError: 
at org.junit.Assert.fail(Assert.java:74)
at org.junit.Assert.assertTrue(Assert.java:37)
at org.junit.Assert.assertTrue(Assert.java:46)
at MoneyTest.should_equal_same_amount_same_currency(MoneyTest.scala:10)
...
Well, using assertTrue never gave helpful error messages. Let's do better.


Using JUnit


Let us change the assert and use assertEquals instead. This works fine as the mother-class in Scala (named AnyRef) is nothing but "java.lang.Object" so there will be an equals method around.


To be precise, there is actually a class above "AnyRef" named "Any" which include the immutable value-types in Scala that parallel the Java primitives. But that distinction does not matter here.


Changing the code to use assertEquals we get:
  @Test
  def should_equal_same_amount_same_currency = {
    assertEquals(new Money("SEK", 1), new Money("SEK", 1))
  }
 This lands me with the error message:
java.lang.AssertionError: expected:<Money@348bdcd2> but was:<Money@4a4e79f1>
at ...
at MoneyTest.should_equal_same_amount_same_currency(MoneyTest.scala:10)
OK, two Money instances with different hashcodes are obviously not considered equal, even though their data are the same. This might be what we want for entities or domain events, but not for value objects such as Money.

However  the error message looks kind of obscure due to the default toString. Let us add a custom toString to get readable messages in the future.
class Money(currency : String, amount : Int) {
  override def toString() : String = currency + " " + amount
}
Running the tests again gives:
java.lang.AssertionError: expected: Money<SEK 1> but was: Money<SEK 1>
at ...
This is definitely more readable. Arguably it would be more confusing had we not remembered the last error message: they are different instances. So, the equality test that Scala gives us from the Scala top class AnyRef (which is the same as java.lang.Object on the JVM) does not cut it for value objects - exactly as in Java.


Fixing Equality

What to do? Of course we could get into Money and add an override def equals returning true. Then we could add a testcase to provoke a failing equals, forcing us to elaborate our equals method etc. However, in Scala there is a simpler solution at hand - declare Money as a "case class".
case class Money(currency : String, amount : Int) {
  override def toString() : String = currency + " " + amount
}
Let us not get into the details, but apart from giving us well-behaving equals and hashcode, it actually makes sense for value objects to be case classes.


Green Test, Refactoring, and Ready to Start over again


The good part is that this change take us home to a green bar. There is not much refactoring to do, so now we have gone a full TDD cycle using Scala and JUnit. Time for next round. 


Now we have gotten started

Yours

   Dan 


ps Once getting started, you might want to try out some actors in scala.

Wednesday, 14 October 2009

Ensuring Indata Validation

Dear Junior

Creating a username class and a validation method has taken us a fair amount towards solving SQL Injection by focusing on a domain model API that is both easy to use correctly and hard to use incorrectly. I would say that we have this far achieved to make the API easy to use.

Integer authenticate(Username username, String passwordMD5)

public class Username {

// final making it immutable

public final String username;

public Username(String username) { this.username = username; }

public boolean isValid() { return username.matches("[a-z]+"); }

}

What remains is to ensure that indata validation actually is done. I can see two choices: either putting validation inside the authentication service, or to enforce validation before the call to the authentication service.

Let us first look at putting validation inside authentication.

/** Authenticates a user with a given password.

* @throws IllegalArgumentException if username invalid

*/

Integer authenticateWithUsernameValidation(Username username, String passwordMD5)

throws IllegalArgumentException, SQLException {

if(!username.isValid())

throw new IllegalArgumentException(

"Cannot authenticate with invalid username: " + username);

...

}


This definitely hardens the interface – now there is no possibility to not validate upon authentication. However, the same trick has to be used in every service method around, including the “create new account”, the “change account username” and all those that are to come in the future. Risks are high that the small isValid-call will be missed somewhere – and one hole is all an attacker needs.

Another drawback is the rather awkward “throws IllegalArgumentException” which feels like a very late validation – should not such validation be made much earlier, preferably up in the presentation and client tiers?

An alternative is to not allow invalid usernames to be constructed at all:

@Test(expected = IllegalArgumentException.class)

public void shouldNotCreateUsernameFromInjectionAttackString() {

new Username("' OR 1=1 --");

}

This request the constructor to do the validation on the inside, responding with an exception if given an invalid username candidate.

public Username(String username)

throws IllegalArgumentException {

this.username = username;

if(!isValid())

throw new IllegalArgumentException();

}

Now we also need some way to validate from the outside without taking the pain of provoking and handling an exception, so finally there will be a static method after all:

public static boolean isValid(String username) {

return username.matches("[a-z]+");

}

Of course the old methods and constructor should be refactored to uphold the don’t-repeat-yourself (DRY) principle. Interesting enough this will lead the isValid() method to consistently return true – so I guess we can delete it from the class and inline it wherever it was used. That is, unless we for some bizarre reason want to have a method that explicitly tells the rest of the world that “this object is always valid”.

I definitely prefer this latter “strictly-validated-value-object” style before the "validating-service-methods" style. It creates an API that besides being easy to use correctly, also is hard to use incorrectly. It “guides” the client side programmer without being intrusive or obstructive about it.

In some sense, it "enforce" a behaviour upon the client side programmer. However, that does not trouble me. If someone just is nice to me, and don’t cause me trouble, I see no obstacle in letting her have her way.

Yours

Dan


Thursday, 1 October 2009

Domain Driven Security and Making Stuff Explicit in the Model

Dear Junior

”But ’ OR 1=1 -- is not a valid username! That is just bad indata validation!”. Well, ‘ OR 1=1 -- might not look like the kind of username we had in mind, but invalid? Says who?

If we have a look at the code, the signature of the authentication method says:

Integer authenticate(String username, String passwordMD5)

Basically, in the code there is nothing saying that username is any special kind of data – it is just a string. And, as such, it can be any string – including ’ OR 1=1 --.

There might be conventions, even documented such, that a username should have certain structure – but the model represented in the code consider any string to valid to send into the method.

The Domain Driven Design take on this is that if you have more restriction in your intended model, then you should better put those restrictions in the code – explicitly.

So, let us take a small step in that direction – let us make Username an explicit part of the model. Later on we can elaborate that part of the model by making restrictions on usernames explicit, and even enforcing them. But let us not take too big a bite – for now we settle for shaping up the model.

If we think about it we can surly agree that username is a special kind of data, separate from amounts, order numbers, or phone numbers. It would simply not make sense to have a phone number “+4615210000” used as a username. This is analogous to the distinction between int and boolean. Under the hood they are both “just bits and bytes”, but we want to keep them distinct in our language so that we do not accidentally use an int as the condition in an if-statement, for example. In C many hard-to-find bugs have been caused by that specific mistake.

In static typed programming languages like Java, C# or ML, we use the type system with interface and classes to separate different kinds of data. However, if we audit the authentication code we will see that there is no representation of username on that level. The only place “username” show up is as the name of a String-typed variables and parameters. The knowledge “username is a specific kind of data with its own rules and restrictions” is not explicit in the code.

Enter class Username, which at this stage might be the simplest kind of value object.

public class Username {

public final String username; // final making it immutable

public Username(String username) { this.username = username; }

}

The important part here is of course that we now have a new type, which can be used by variables, fields, parameters, and returns to make the code explicitly talk about usernames.

The authentication method will change somewhat.

/** Authenticates a user with a given password.

* @param username

* @param passwordMD5 hash of password

* @return user id, or null if no matching account

*/

Integer authenticate(Username username, String passwordMD5)

throws SQLException {

Connection con = accountDs.getConnection();

Statement stmt = con.createStatement();

String sqlSelect = "SELECT uid FROM Accounts";

String usernameMatch = "username = '" + username.username + "'";

String passwdHashMatch = "passwdHash = '" + passwordMD5 + "'";

String sql = sqlSelect +

" WHERE " + usernameMatch +

" AND " + passwdHashMatch;

ResultSet rs = stmt.executeQuery(sql);

Integer result;

if(rs.next()) { // found account with matching password

result = rs.getInt("uid");

} else { // no matching account

result = null;

}

return result;

}

So, whoever wants to call the authentication method with a username, must first create a Username object via the constructor.

public class LoginAction {

void doit() throws SQLException {

Username username = new Username(form.username);

String passwordMD5 = form.password;

accountService.authenticate(username, passwordMD5);

}

}

Now the concept of username is explicit throughout the code, and actually talks the same language as the people working with it. In effect, we have made username a part of the ubiquitous language talking about the system.

Note that we are still not yet protected from bad usernames, that will be a later step - but at least we talk about usernames, not strings.

The distinction between username strings and usernames is subtle. This distinction might seem small, but I think it is essential – as the language form how we think. The moment the programmer start expressing herself in domain terms (creating a Username object), chances are higher that she will also question the indata parameter: Is this string really a username? Where did it come from? Has it been properly checked? No guarantee, but chances are higher.

We still have some way to cover before we have an API that is both easy to use correctly, and hard to use incorrectly – but at least we have taken a step in that direction. We still lack the constraints on usernames, and there is no enforcement at all.

However, if we can guide the programmers into thinking about the model a la DDD, and thus decrease the risk of severe application security flaws, then we have at least done something useful.

And it is usefulness that is the ambition of Domain Driven Security.

Yours

Dan

PS My colleague John Wilander just published a nice example on how they did with Swedish "person number" (roughly social security number) [Swedish]

Monday, 15 June 2009

Philosopical Difference between Values, Entities, and Events - a Matter of Existence

Dear Junior

There are numerous ways and rules-of-thumb whether to choose entities or whether to choose value objects when modelling a domain; but I have for long felt that there is a deeper philosophical distinction that I have still not been able to nail down – but now I stand the risk of a try. It is the distinction of their “nature of existence”.

For things that we view as entities, e g people, the set is clearly partitioned between those that do exist and those that don’t. For example, the person I reference as ‘me’ does exist (proof: cognito). On the other hand, the person ‘Dan’s brother-in-law’ does not exist, as none of my sisters is married (at the time of writing, and to my knowledge). Whether the person ‘the father’s father of Dan’ exists is of course a modelling choice – do we only model people alive, or anyone that has been alive? In either case the class ‘people’ is split in two disjoint and exempting subset, those that exist and those don’t.

This is also the reason for entities often come with a repository for finding specific entities (if they exist), and why we have to be prepared for handling entity-does-not-exist conditions. So the question of existence makes a huge difference in the use of entities.

For things that we view as values, e g colours, the question of existence become more academic. Does ‘blue’ exist? Well, there are definitely blue things around us, so we can say that it does exist. Does the colour defined by RGB (112.345, 43.23, 203.447) exist? Well there might be a thing in the world (even in our modelled part of the world) with exactly that colour. On the other hand there might be no thing with exactly that colour. The end point is that, whether there is such a thing or not does not feel relevant to the question of existence of the ‘colour as such’. So, if the mentioned colour exists, it does so rather in Plato’s world-of-ideas, rather in the physical one.

This is also the reason that value objects do not come with repositories. There is simply no usefulness that comes with answering the question ‘does blue exist’. The question of existence makes no difference in the use of values.

What finally set me on track for these thoughts was the use of ‘domain events’ (e g the arrival of a delivery, or a failed authentication) as a modelling tool. I think it is the ‘nature of existence’ that has felt awkward when modelling these as value objects, as that is what I have done. I simply modelled them as value objects because domain events are immutable, and so are value objects – but that is obviously (in hindsight) a line of reasoning en-par with “roses are red, so is father Christmas, ergo father Christmas is a rose". Now I see the faults of my way.

To my defence, I have also acknowledged that events either have-not-happened or have-happened, so there has been repository-like functionality from time to time to account for that distinction. So, they have been value objects with flavours of ‘entitiesm’ to them.

Finally, ‘domain events’ have sprung out of this Hegelian didactic tension. They are immutable as value objects, but they are not value objects as they have a conceptual identity. They have the same ‘nature of existence’ as entities, but they are not entities as they do not evolve their state over time.

Put another way: mutability makes the distinction between entities and domain events; substitutability makes the difference between entities and value objects; and ‘nature of existence’ makes the difference between value objects and domain events.

At least one way of putting it …

Yours

Dan