Making Trojans Easier To Remove
It occurs to me that there’s no way to stop trojans from working – there will always be a way to disguise it so that it looks like a valid application – if by no other means than by making it a valid application. There is also no way to allow the user to get their work done and prevent trojans from doing any damage or being annoying – even with privilege separation, the trojan has access to all the user’s files. Note that this only applies to trojans, not to other types of malware – viruses for instance can be prevented by writing secure code.
Refactoring Without Tests
Refactoring without tests is hard and really, really scary but sometimes you’ve inherited (or perhaps written yourself) a big ball of untestable mud and the only way out is to refactor and make it testable. One of our engineers found himself in that situation today so we sat down together to try and make sense of it.
I tried to follow a few simple rules:
- Go slow. No big sweeping changes. Keep the way it does things the same and just break the code down to make it more readable and create multiple small balls of mud instead of one big one.
- Use the automated refactorings in the IDE unless you absolutely have to make manual changes. We discovered a number of bugs in Eclipse this way where it didn’t detect identical code – who knows why not. In once case I managed to convince it the code was identical by repeatedly trying the extract method until it picked up the duplicate block but in a second case I had to revert to manually replacing the duplicate code.
- Use the simplest refactoring that could possibly make it testable. Mostly this meant applying extract method with a smattering of extract local variable to pull out the differing pieces so duplicate code could be merged. In hind-sight I may have been better off leaving the duplicate code in and writing tests for it separately, it would then have been easier and safer to remove the duplication.
All in all I think it went really well, slow going but effective and we now have half as much code and it’s much easier to test. There’s still a lot more work needed to stop that code from smelling but it’s a start and that’s enough for one day. You can’t spend all your time refactoring legacy code, new features have to be added – just make sure that you’re constantly improving and eventually you’ll get there.
Stats Should Rotate, Not Reset
I’ve come to discover a really annoying trend among blog statistic services – they all seem to show graphs of vistors by day, week or month instead of showing the past 24 hours, 7 days or 30 days. The difference is quite substantial, by viewing by the past 24 hours you always get a useful graph, by viewing by the day at the start of the day there’s just a blank graph.
XP – It’s Good For What Ails Ya
Doug suggests that XP isn’t a solution to your problems. Mostly I agree, however XP does make you feel bad – and in this case, feeling bad is good. As Doug points out, XP brings things out into the open which makes people feel bad about them. The lack of tests for your product – oh, that’s not good. Not doing continuous integration – tut tut tut. Your build is regularly broken? Shame on you! Feeling bad about these things is good and will encourage you to fix them.
Knowing When You’re Tired
There’s a big difference between code you write when you’re fresh and code you write when you’ve just had enough. I obviously had a relaxing weekend, because today my approach to coding was surprisingly well behaved – even when I had to modify legacy code that had no test coverage I made sure I wrote new tests before I touched it. Getting into TDD for new code is one thing, building up the discipline to add tests to existing code before making even a simple change is really tough.
Generating Languages Via TDD
As you spend more and more time developing good unit tests as part of TDD, you regularly find yourself writing the same thing time and time again. Fortunately, TDD also includes a refactor step to remove this duplication again. I’ve found it quite interesting that over a few weeks of this, we’ve actually developed a complete language for asserting the correct output. For example:
assertStartTagSpec(HTML.Tag.HTML);
assertStartTagSpec(HTML.Tag.BODY);
assertStartTagSpec(HTML.Tag.P);
assertContent("Hello World!");
assertLineEnding();
assertEndTagSpec();
assertEndTagSpec();
assertEndTagSpec();
assertEndOfSpecs();
Even without the domain knowledge, it should be fairly obvious what is expected. It’s definitely a lot clearer than:
Chuq On Tagging
Chuq Von Rospach has some interesting thoughts on tagging – must come back to this and have more of a think about it.
Pair Blogging?
It seems I finally pestered Doug into blogging again, so for his side of the story check out Experiments in Software Design.
Introducing Bob
Bob is our build server – just like the children’s TV character, he spends all day building stuff. Bob has to be one of the most beneficial improvement projects we’ve taken on at Ephox in quite some time. Every build of our key products that we ship both as full releases and hot fix patches are built by Bob. He even uploads them to the web server when told to make them available to clients.
Sustainable Pace != 40 Hour Week
One of the tenets of XP is that you work at a sustainable pace. Mostly that means that you don’t work such long hours that your brain turns to mush and you start churning out bad code, however there is more too it.
Working at a sustainable pace also means knowing when to take a break from a task. After weeks of slogging away at replacing this 3rd party library – constantly making progress and getting small wins from each acceptance test we got to pass – this afternoon both Doug and I seemed to have stopped caring as much as we should, so we took the afternoon off of that project and went and caught up on the other things we needed to do. When we return to working on it we should be refreshed and able to approach the problems with a more open, creative mind and thus write better code.
Acceptance Test Driven Development
Doug and I are currently busy replacing a third party library which we’ve used in our product for quite some time. Thus, the first thing we need to do is create a new component which behaves in exactly the same manner as the original component. Once we have that we can start adjusting the code to add features and work in the way we really want.
To ensure we get an exactly compatible replacement, we started out by creating a suite of automated acceptance tests against the original implementation and they all passed. Then we removed the third party library and they all failed. From there we could gradually begin building our new component by attempting to make each acceptance test pass – one at a time.
Test Driven Development And The Myth Of Better Code
Claim: TDD Generates High Quality, Maintainable Code
Proponents of TDD argue that by writing the tests first, you are forced to focus on how the component will be used and thus will come up with a better design. My experience has actually been the opposite; TDD encourages you to just do whatever needs to be done to make the test pass and not think about design at all. I’ve never copied and pasted code so much in my life and the number of times I’ve written code that’s so messy I feel like I need a shower is getting scary. That’s okay though, it’s meant to be that way. TDD encourages short-sightedness, short-cuts and general sloppiness and that’s a good thing.