- Interfaces suddenly seem like a good idea.
- You stop using singletons and static methods.
- Private makes less sense than it used to.
- You pass dependencies in the constructor (the so called 'fat constructor')
- Smaller methods are the norm.
- You read tests before the code; it better explains the intention.
- Usability trumps cleverness.
- Premature performance optimisation is bad (YAGNI)...
- ... but test performance is crucial.
- Dependency is bad; you avoid 'God classes' and 'global hubs'.
- 'Clever' is dead. 'Clever' is hard to refactor. 'Clever' is hard to isolate, hard to internalize, hard to phrase in tests.
- Your IDE is only good if it allows you to do quick write/build/test cycles.
Thursday, August 30, 2007
Testing Will Challenge Your Conventions
I've just stumbled upon a fantastic blog post Testing Will Challenge Your Conventions, by Tim Ottinger. In it he lists a number of ways that doing TDD fundamentally changes the way you code:
Tuesday, August 07, 2007
Masters, Journeymen, and Apprentices
I've really enjoyed reading this series of blog posts by Fred George, Masters, Journeymen, and Apprentices. In it, he says what everyone knows, but few teams seem to accept: all programmers are not created equal. He divides programmers into Masters, Journeymen and Appentices. I must say, that reading his descriptions, even the lowest level on his scale, the Apprentice, is more skilled at OO development than most of the developers I encounter. He's another thoughtworker, a company that consistently seems to attract the best programmers, so it's not really surprising that there's such a high bar. The truth is that your average Microsoft programmer in your average company's development shop knows almost no OO at all. I don't consider myself a great programmer, I'm probably at his Journeyman level, but I'm consistently the only guy who's doing OO programming (as Fred George describes it) at the majority of my clients.
I think it's really down to the fact that it's very hard to measure the ability of a programmer at programming and so it's ignored by management. There tends to be no concept of growing programming skills by mentoring or training. This is especially true of OO skills. I would say that being skilled at OO provides a step change in any programmers productivity, but this is rarely measured or encouraged. In fact OO programming practices are relatively uncommon in most Microsoft shops and are often dismissed as an academic waste of time. I was told by one 'architect' that we were doing OO programming because we were using C#, regardless of the fact that most of his procedures where hundreds of lines long and had a cyclic complexity of about a million:)
Sure you can read lots of books on technologies and do lots of Microsoft exams, but that's about APIs and technology, the actual art itself is often totally neglected. And it is an art. With no way to measure ability most management simply measure seniority by length of service. What I often find is that the quality of the whole team is governed by the quality of the senior developer(s), the guy who does the recruitment interviews. If he's good then then he tends to be able to recognise good people and recruit them, if he's not so good then the team too tends to be poor. But even if he's good it's a struggle, you have to be prepared to turn away a lot of people with all the right qualifications and pay good money to get the few people out there who really know OO. That's a hard sell to management who far too often see developers as plug and play components.
It's quite depressing really. I constantly hope that I'm going to get to work with a Master programmer because I know that's the only way I have any hope of ever attaining that level myself, but apart from the odd great team (only two I can actually think of in my career), it's a vain hope.
Monday, August 06, 2007
The Castle Project's Windsor Container and why I might need it.
I've recently had a bit of a eureka moment after reading about the Castle project. I've been hearing about Castle for a while now, but it's taken until now for me to grep what it's all about and why I need it. A quick look at the home page left me a little bemused. There's a thing called "MicroKernel" that's described as "A lightweight inversion of control container core". Now I know all about inversion of control, it's an essential ingredient to building scalable, testable applications, but what is an 'inversion of control container'? And why would I need one? Below "MicroKernel" is "Windsor Container". Nice, "Windsor Castle", get it? It's obviously aimed at the UK programming community. Windsor is described as "Augments the MicroKernel with features demanded by most enterprise projects", but I still don't see why I would need one. After seeing the Castle project mentioned for about the fifth time by bloggers who have far more brains and sense than me, I decided to knuckle down and RTFM by reading Introducing Castle by Hamilton Verissimo who's one of the main developers.
Now let me take you on a little coding journey to show you how Castle, and more specifically Windsor, solves an problem that's become more and more apparent to me, mainly because I've adopted test driven development (TDD). I'm going to use a similar example to Hamilton's, but try and drive out the need for Windsor from a test driven perspective.
OK, for my little example, say I've got a reporting class, 'SimpleReporter', that creates a report and then emails it. The code that uses it might look something like this:
SimpleReporter reporter = new SimpleReporter(); reporter.SendReport();And the SendReport method might look like this:
public void SendReport() { ReportBuilder builder = new ReportBuilder(); Email email = builder.CreateReport(); EmailSender sender = new EmailSender(); sender.Send(email); }It creates uses a class called ReportBuilder to create an email report and then another class called EmailSender to send it. This is the kind of thing I used to write before I got into TDD. It works, but in order to test it I've got start up my application and use the UI to create and send a report. I then have to check my emails to see if the report has arrived. I'm not testing just my SimpleReporter class, I'm testing the SimpleReporter, the ReportBuilder and anything it relies on, the EmailSender, my SMTP server, my email client, my application's UI and probably a relational database and my data access layer. In short I'm testing a large chunk of my application and infrastructure. If something goes wrong I'm into a serious debugging session trying to work out why my Email hasn't arrived. I can't automate this test easily so I'm not going to do it very often and if a bug is introduced by a change to some other part of the system I'm not going to notice it immediately. Now I would use inversion of control and dependency injection with a mock object framework like NMock to just test my Reporter and nothing else. I blogged about NMock a while back. Here's the new Reporter class, note how I pass a report builder and emailSender in the contructor and how I'm only referencing interfaces not concrete classes.
public class Reporter { IReportBuilder _reportBuilder; IEmailSender _emailSender; public Reporter(IReportBuilder reportBuilder, IEmailSender emailSender) { _reportBuilder = reportBuilder; _emailSender = emailSender; } public void SendReport() { Email email = _reportBuilder.CreateReport(); _emailSender.Send(email); } }And here's its NUnit test.
[Test] public void ReporterTest() { string theText = "Hello, I'm the report!"; Mockery mocks = new Mockery(); IReportBuilder reportBuilder = mocks.NewMockNMock provides me with mock object instances to pass to the Reporter class' constructor. I don't even need to have writen concrete implementations of ReportBuilder or EmailSender at this stage. I can test that the Reporter class does the correct thing with reportBuilder and emailSender and I'm not testing anything else about the application at this stage. Most importantly this is an automated test that can be run in an instant along with every other automated test for my application. If I make a change that breaks Reporter I'll find out instantly. Discovering TDD has made me a much better and productive developer. Not only are my apps more robust, they are also better architected because testing forces you to do good software design. However, I've noticed a rather unfortunate side effect of doing things this way, in the finished product we'll have to provide concrete instances of EmailSender and ReportBuilder.(); IEmailSender emailSender = mocks.NewMock (); Email email = new Email(theText); Expect.Once.On(reportBuilder).Method("CreateReport").Will(Return.Value(email)); Expect.Once.On(emailSender).Method("Send").With(email); Reporter reporter = new Reporter(reportBuilder, emailSender); reporter.SendReport(); mocks.VerifyAllExpectationsHaveBeenMet(); }
ReportBuilder reportBuilder = new ReportBuilder(); EmailSender emailSender = new EmailSender(); Reporter reporter = new Reporter(reportBuilder, emailSender);Now that doesn't look too bad, but this is a really really simple example. In a real application there could be hundreds of classes that need to be knitted together like this and it becomes a complex piece of code, not only to maintain, but to decide where in your app you should do it because the class(es) that do the knitting have to know about everything. An alternative that I experimented with was to have a default contructor for each class that provided the concrete instances alongside the one that injected the dependency, so our Reporter class would now look like this:
public class Reporter { IReportBuilder _reportBuilder; IEmailSender _emailSender; public Reporter(IReportBuilder reportBuilder, IEmailSender emailSender) { _reportBuilder = reportBuilder; _emailSender = emailSender; } public Reporter() { _reportBuilder = new ReportBuilder(); _emailSender = new EmailSender(); } public void SendReport() { Email email = _reportBuilder.CreateReport(); _emailSender.Send(email); } }But this feels really dirty. I've now got a direct dependency from the client back to the server thus breaking the Inversion of Control priciple. I can't easily use a different kind of reportBuilder or emailSender without recompiling the Reporter. Another possibility would be to use the provider pattern that's a core part of .NET, but it's not really intended for this scenario and to use it for every service class in your application would be total overkill. Of course the .NET framework also provides a component architecture, but it's also quite heavy for what we want here since it requires that each component implement IComponent and provide the plumbing to publish its service. What I need is something that will magically provide concrete instances of the interfaces that each class requires without me having to maintain a vast wiring exercise somewhere in the startup code of my application. Enter Windsor! Here's how you could use it with our Reporter example:
WindsorContainer container = new WindsorContainer(); container.AddComponent("reportBuilder", typeof(IReportBuilder), typeof(ReportBuilder)); container.AddComponent("emailSender", typeof(IEmailSender), typeof(EmailSender)); container.AddComponent("reporter", typeof(Reporter)); Reporter reporter = container.Resolve<Reporter>(); reporter.SendReport();You create a new container instance and register each interface in your application along with the concrete class that you wish to represent it. You can get a new instance of your class by using the Resolve method. Here we get an instance of Reporter and call SendReport(). Nowhere in the code did we have to explicitly pass instances of ReportBuilder or EmailSender to Reporter or even know that Reporter required those instances. Windsor also allows you to describe your components in a configuration file rather than hard coding all those AddComponent statements. You can see the benefits. Say I wanted to write another class that needed to use IEmailSender. I would just write that class with an IEmailSender as one of its constructor parameters and add it to the container. The container would then automatically provide an IEmailSender instance. In fact, by default it would provide the same IEmailSender instance that it supplies to any other class that required this interface, although that behavior can be modified. Now, say I want to use ExchangeEmailSender rather than my existing EmailSender throughout my application, I only have to change the one configuration entry (or line of setup code) to do it, rather than searching through my application looking for every place where an IEmailSender is passed as a constructor parameter. If you want to pass ExchangeEmailSender to some components and EmailSender to others, then that can be configured too. There's much more to the Windsor container than just the inversion of control container, it also provides Aspect Oriented Programming features, automatically providing interface proxies so that you can intercept method calls and provide cross cutting services. This opens up all kinds of exciting possibilities, the obvious ones being logging, auditing, transactions and security, and I hope to blog about it some more in the future. I haven't used any of this in anger yet so I can't say what the drawbacks might be, but I can imagine that maintaining the component config file for a large project could get a bit tiresome. The advantages are obvious. It really is lightweight component based development where you provide service components that can be consumed by other components without ever having to have any direct dependencies. I'd really like to see it used in a major application. It also begs the question: shouldn't this stuff be provided by your programming language? The CLR has the potential to do a lot of this quite easily. It already knows about all the types that an application requires, it knows about interface implementation, it can intercept method calls. It's easy to imagine a future version of C# where component based programming is provided out of the box.
Subscribe to:
Posts (Atom)