Lots of refactoring, plus some initial tests.