Thursday, 29 December 2011

Security by obscurity and permutations

There are two methods of security in IT that are not usually wise. The first is security by obscurity, in other words, if we don't tell people how we implement security, they are unlikely to break it. The problem with that view is that it isn't true! DVD encryption was broken, various sites have been cracked by trying various attack vectors. In reality, it is better to be open about your security if you can ensure you have a suitably helpful audience who can then advise on areas that might be weak. Oyster Cards and even Chip and Pin have exhibited weaknesses that could possibly have been found by peer review before they were implemented but both were 'closed source' and both have been compromised.
The second method of security is by permutations. My system is safe because you would need to try X combinations before you can crack it and X is a very large number. Of course, as we know, X is never a large number for more than a few years as newer faster computers and networks allow higher bandwidth for hacking attempts. In reality, your passwords should be 16 characters or more with punctuation, upper and lower case etc to provide any decent level of brute force defence but remember again that just because something is unlikely, doesn't mean it won't happen. You can mitigate however against brute force by slowing down the responses either progressively or even by a fixed amount of time (say 10 seconds) which thwarts faster hacking equipment. You can also block suspicious activity (such as 5 failed login attempts) either for a period of time like an hour or until 'manually' unlocked. In any case, you should be open with people who use your systems what the limits of your security are with statements such as, "WPS requires an 8 digit pin which would require X days of brute force to get past" which allows someone to consider this statement, perhaps challenge it and then allow the manufacturers to re-design or upgrade the equipment to increase the security.
Sadly, we rely on hidden decisions made by people who may or may not be competent in their job and whose decision may or may not still be valid and which may or may not even be visible, being lost in the mists of time.
Anyway, hire competent and trained people and ensure they are keeping up-to-date with current threats otherwise your company will look stupid!

Another botched large IT project

http://www.theregister.co.uk/2011/12/29/csc_nhs_it/

The NHS electronic patient records system was like a lot of large IT projects going to deliver large benefits to patient care and why shouldn't it? Currently your GP and hospital records are mostly on paper or stored on independent systems which cannot communicate so you could be admitted to hospital and the doctors might not know that you visited your GP a month earlier with similar symptoms. However, also as with most large IT projects it ended up running late and being much over budget until the Government had little choice except to shelve it and cut their losses.
We use so much IT nowadays that we still haven't realised that we are mostly rubbish at running IT projects. In fact, we are pretty bad at running many projects but IT seems especially poor. What seems unreasonable to me is that the risks of IT projects are well known but yet they are not managed or removed to provide the ability to  produce a useful albeit large IT system of some kind.
There are various problems and I have outlined a few below. We need to understand these problems, many related to human nature, and then decide what we will do about them.

  • Price must not be the main factor when choosing a supplier. While there is so much pressure on price, people are inclined to avoid factors that are seen as low benefit/cost such as quality and process improvements. When things are running a bit late, nothing other than pure functionality is going to be given any space. With a more open relationship with our customers, we can show what we are charging for what and therefore negotiate if unforeseen things happen. A customer will pay a 40% margin if they know anything about business, we shouldn't need to keep this a secret.
  • Time must not be unrealistically short. Customers always seem to want 6 months of work in 3 months and we are inclined to agree because we want the work. We perhaps think we can just about manage but of course we can't. People leave, you can't always recruit new people in time etc. Part of quality assurance should require that a supplier will only agree to timescales related to the design and planning and NOT by an arbitrary deadline imposed by the customer unless this is specifically factored in. There needs to be protection against unscrupulous suppliers who will say whatever the customer wants to hear in order to win the work. "Prove it or lose it"
  • Someone once said, "the customer is always right" but that is nonsense when applied to all business scenarios. Specifically the customers is sometimes wrong and sometimes very wrong about many things. This balance needs re-addressing and as experts, we need to improve our profile so a customer will trust us when we say something cannot be done or not in the timescale required. I don't argue with my doctor over medical issues so why is it OK for a customer to argue with an IT supplier over a system?
  • The more people you involve, the more complex it gets. In order to counter this, you either involve less people (which risks alienating your users) or you make the system simpler as far as possible so there is something for everyone to use. For instance, an electronic patient record system could be very complicated but even if it was a multi-page document like a filing card system, that would be of enormous benefit just to record stuff like "administered 100mg of XYZ". I was once asked to write a database system for a Bariatric clinic even though there was a European-wide database. The Ero one was so complicated, it was useless to any one person.
  • Requirements capture needs to be much better understood and only people of a relevant level of understanding in the customer organisation should be allowed to have formal input into the process. Asking every man and his dog for their input even though they might not understand that complexity is cost and that a system is more robust if it is coherent is clearly nonsense. Ideally, you should have a single point of contact with a customer who can have the arguments with various stakeholders on your behalf from a position of understanding. We have some large customers who have 20 people on the authorisation list for functional documents. Can you imagine how long they take for approval?
  • We need to understand and manage change better. If we are taking 2 or 3 years to deliver a system, its requirements will change over time. It is futile to pretend we will set requirements in stone. This was done for electronic MOTs and we ended up with dial-up connections required for all garages even though the internet and broadband was in full swing. We need to accept that change will happen and at least consider some things that might happen (even if their details are not fully known). We need to communicate the cost of change to a customer so they don't change things for the sake of it and we need to try and get a system out of the door sooner, even if not all the functionality exists, so at least we can achieve milestones and get paid rather than having a continuous moving goalpost. We should obviously be writing code that allows for change as well and this needs to be taken seriously. All those short-cuts and "quick hacks" should simply not be allowed at all.
  • I think there needs to be better scrutiny of suppliers who are getting things wrong and even potentially legal action against people who might pretend to be doing it all right but are covering up incompetence and deliveries of systems that are basically rubbish as soon as they are released. If someone releases something under a quality assurance banner that cannot be maintained to any reasonable degree then they should have to pay some of the costs of re-designing it.
  • Quality needs to underpin the processes at every level and sadly this is still an after-thought or box-ticking exercise for many organisations. If they could understand what quality really means. The systems we deliver would be so much better.

Wednesday, 28 December 2011

Better Use of Email

For some reason, email hasn't changed fundamentally since it's original inception back in the computer dark ages of un-powerful PCs running over slow networks. It is basically a text-based protocol with no security whatsoever. You can spoof who the email is from and read any of them with a network sniffing tool. Everything since then has been tagged on the top like PGP for security, IMAP for mail servers, Exchange Server (whatever that adds). Basically I don't like email because it has few useful features and it is extremely over-used for a variety of tasks that it is definitely not suitable for.
In terms of functionality, I would like a feature to be added to email which is simply an "expiry" date. Many emails that are sent are only relevant for a period of time (long or short) and the ability to allow the email systems to delete expired mail would clear logs of unnecessary backlogs. For instance, using an email to tell you that a backup succeeded or failed is mostly irrelevant after the next backup occurs so if you get 10 of these over the weekend, probably 9 of them can be discarded. However, I do not have the influence to make that happen but I do have an influence over how I use email and require others to use it.
My old manager had something like 5000 emails in his inbox. He was an extreme example of badly used email. What is the point of having that many when you can only handle a few at a time? Here are some suggestions as to why he had too many and what you can do to avoid the same mistake:

  1. Self-importance! If you think you are too important, you want to be copied in on everything. This betrays major issues either with trust or just how badly the organisation is run.
  2. Incorrect use of email. Having emails for things like successful backups is perhaps acceptable if you only have one server and it backs up once per day but really, there are proper tools that monitor these things and which don't need to spit out tonnes of emails into your inbox. A monitoring system that has to send emails constantly to convince you it is running is not really much good!
  3. Incorrect use of email too. Lots of people claim they write emails to leave a 'paper trail' of decision making to cover their backs later on. This is tosh. Whatever you have written in an email is likely to be mis-construed which is a defence later on when someone decides that you didn't tell them to do X in the email. Pick up the phone if that's what is required. You can communicate 10 times more efficiently with your voice (and even more in person) than you ever can on email. Why take 10 minutes to try and formulate what you could describe and discuss in 30 seconds? If someone doesn't understand, they can ask you straight away rather than writing you a 10 minute reply!
  4. Make correct use of importance and expiry. Although expiry is not part of the email standard per-se some providers give you an expiry option which allows you to mark an email like "you have left your headlights on" to expire after 4 hours and not to be looked at by everyone who has been on holiday for 4 weeks.
  5. Use correct subjects. Your subjects should be very concise, especially on emails going to more than one person since some of those people might very much not be interested. An email with a subject like "Does anyone have a set of jump leads" is more useful than one with a subject of "request" and a body that contains the question.
  6. Consider alternatives. Sometimes you could write your own application to do something that you currently use email for (such as monitoring backups, lift sharing or general enquiries). You could use a separate system (like Yammer) to allow people to ask non-work related questions to keep your inbox down. Also, an email like "Potatoes are ready" being sent every day at lunchtime can be annoying. How about telling people that the potatoes will always be ready at 12 unless there is an email to the contrary?
I heard about the head of a car company who had banned his employees from using email for the fact it is really inefficient. Will be interesting to see whether they can break the email mindset!

Thursday, 22 December 2011

Why we must write clean code

Engineers are often (rightly) accused of being pedantic. We insist that we use an integer rather than a short or that we should or should not use a pattern. The sales type people don't understand this and will tell us that as long as the customer sees a system that does what they want, they couldn't give two hoots (or 2 dollars) for how it is implemented. This might seem like a pragmatic approach since in a sense that is true but sadly there are a few assumptions in that statement that need to be exposed and which reinforce the need for strict coding practices. Firstly, the life of software is usually much longer than it is assumed. Look at Windows XP for instance, when it was first released in 2001, MS would have a plan that in 5 years, it would be pretty much replaced by whatever their next OS was going to be (Vista or Windows 7 perhaps). In other words, don't get crazy with it, if a bug will survive 5 years, we can leave it in and then fix it later. In fact, XP still holds around 33% of internet connected machines 11 years later. It is still being used and the bugs that might have laid unlikely for 5 years are much more likely to surface over 11 years. In a similar way, do we really design software for 10 or 20 years? If we designed a car to survive that long, we would have to be very careful about all components yet in software we can still be quite glib about the level of quality that is acceptable. Secondly, it is quite glib to say something like, "as long as the customer gets what he wants", both because over time this will prove less true and also because it is not as black-and-white as that. MS Word pretty much OK but there are things I don't like about it and I live with them - it is not either perfect or useless. The level to which we can achieve this 'perfection' however is important in people trusting our software. Also, this acceptance is based on functionality as much as reliability and there is every chance after a while that a customer will want to change something, a good test of how well the software was originally written. Another reason why we should strive for quality is to ease maintenance. We have staff turnover and we have to change and fix things. There is nothing worse than being presented with an obvious defect but being totally overwhelmed by the code we have to look through to find the cause of the defect. This is why we should keep our objects classified specifically and deliberately. Data objects contain properties to describe their data and little else. Control objects provide methods to do stuff and should not generally be persisted. Interface objects translate between specific systems and can be added or removed as the boundaries change. We have probably all been in the situation where we notice an issue in code and are told it is so low a priority that we should not fix it (partly this is because of the build time overhead - something we should consider) but as with rust, what starts with a small bit can grow and grow until a full rewrite or re-factor is required. We must be careful that we don't break code that might be 'wrong' but works because something else takes account of its wrongness but at the same time, we should feel at ease making code more readable and obvious. Of course, the best way to do this is to get the code correct in the first place so it doesn't need to be changed and this again requires company buy-in because it involves training and reviews. It requires keen eyes that can spot where mistakes are creeping in and finding ways to mitigate the risks. Even subtle coding styles can introduce errors so sometimes we might require very high-level training about separation of concerns, correct use of comments and ensuring that we are using tools that make this easy to do so the time required doesn't become unacceptable. We need to treat our software with more respect and we need processes and people who understand that so that what we produce is still running as expected in 10 or 20 years time, hopefully with a lot of repeat work!

Monday, 19 December 2011

Software Patents Mostly Make my Blood Boil

I think I am probably of the opinion of many others that protecting your own ideas is fair enough (although I could be convinced that people should help each other) but let us say for instance that someone spends millions developing a working fusion reactor, it would be unfair if everyone just copied that idea and capitalised on someone else's investment but sadly for most software patents, they involve, in my opinion, virtually no 'intellectual property' but which are basically money making schemes that make lawyers rich and everyone else poorer. Let us start with something like MP3. Presumably this took time and effort to develop and is a protected technology, which although you might disagree with the marketing model, few people would argue with. Let us however look at some other patents like 'pinch to resize' and 'using clever routing to improve connection speeds'. Firstly, these require no intellectual prowess to conceive. In the same vein, I could conceive of flying cars and teleporters but without developing these I should not have the right to the intellectual property for these just because I can run fastest to the patent office. More significantly however, the idea itself does not provide a competitor with much. They still have to code it/implement it and this surely is where the cleverness comes in. It seems that most of these patent cases appear in the USA, the most materialistic and capitalistic country in the world? A country that panders to the dollar more than to the community or to progress in general. Even Google who are famously open and generous with their offerings seem to get stuck in this area since the old-fashioned companies attack them for sharing this amazing knowledge with the world at large rather than selling it for the money that only marketers dream of. Shame on you MS, BT, Apple, Google etc. Get over yourselves and start being proactive rather than reactive. Make stuff that people want to buy and don't pretend that you are unfairly losing market because someone made something that was the same colour as yours!

Monday, 12 December 2011

I need a new phrase...

I need suggestions for a new word. In software engineering, we get taught about things that are important like code clarity and maintenance but when we start work, we soon realise that only functionality that can be seen by the customer has any real worth. Things that have been done messy is resigned to being, "yeah, we'll fix that later" and we all know it won't. We all know that companies do not have capacity for people to tidy up (and potentially break) existing code. It's a bit like functionality is the bourgeois and the clarity and neatness is simply the illegitimate or maybe the working class of software engineering. Yeah, we care, just not that much. The sad fact is that this needs to be done correctly at the start or it never will be, which is sad because it causes so much pain and lack of quality issues further down the line. What word for this sadly neglected area of software engineering? For this butler/chauffeur of the software community? For this important but under-valued foundation? I reckon something like UnderCode?

Friday, 9 December 2011

A code quality test

Looks at the following code (which compiles) and see what is wrong with it:
var myDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month + 1, 1 );
Spot it? I didn't! The obvious intention is to create a date which is the 1st of the next month, in general it works as expected but when the month is December, month + 1 = 13 which will understandably cause the constructor to throw an exception. The compiler won't catch this because the types are correct. What point am I making? Well, quality is about learning from mistakes. What can we learn from the above code? Obviously we could simply attribute it to human error and say a code review might pick it up (but possibly/probably not) but what else can we decide? Well, one thing about strongly typed languages is that we should aim to get the compiler to test as much as possible on our behalf to catch these sorts of errors so the real issue is that there should NOT be a DateTime constructor that takes 3 integers for arguments. It sounds reasonable on paper but it means that for 99% of combinations of parameters, the constructor will throw an exception. What we should have instead is a constructor that takes enumerated values and then we could make use of the AddMonths method (which we could have used in the above code) to get something more like this:
var myDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DayOfMonth.First ).AddMonths(1);
Which would give a much more solid representation of what we are doing and would make it harder to fudge. That way, we would have to cast a number to an enum if we wanted to hack the code and this would be much more obvious in a code review:
var myDate = new DateTime(DateTime.Today.Year, (MonthOfYear)((int)DateTime.Today.Month + 1), DayOfMonth.First );
So you can get quality even in subtle ways - now all I have to do is update the code review process and get MS to drop the silly 3 x integer constructor.

Thursday, 8 December 2011

Understanding Mocks

When I first started using mocks, I must admit finding them slightly confusing. I knew what they were supposed to do but some of the language was a bit confusing so then I didn't know if I actually understood them at all. I wanted to write a very basic introduction to Mocks to get you in the mood for using them. Firstly, a mock object (and I will be referring to Rhino mocks) is designed to act in place of an actual piece of software whether a service or even one of your own sub-systems. This is good for two reasons. Firstly, you might not have access to the real-life object (perhaps a web service that you cannot call from your test environment) but secondly, they allow you to test only a part of your system without risking the introduction of defects from other parts of the system (which might be outside of your control or not finished yet). For example, suppose you are writing a user interface to a banking system and you want to test your user interface. If you connect it to the actual back-end, you might see loads of errors that are nothing to do with your code and which make it hard to know whether your code is correct or not. By "mocking" the back-end, you can tell the mock how to behave and therefore test whether your code does what it says without worrying about someone else's defects. To create a mock object you implement whatever interface you want to mock and then it is usual to encapsulate a generic mock property like so:
public class MyMockClass : IInterfaceIWantToMock
{
    private IInterfaceIWantToMockmock = MockRepository.GenerateMock();
}
If your mock is for a service, you should also implement IDisposable and setup your end point replacement for web config files. The mock could use any of the service bindings, in this case I use a named pipe:
public class MyMockClass : IInterfaceIWantToMock, IDisposable
{
    private IInterfaceIWantToMock mock = MockRepository.GenerateMock();
    private readonly Uri uri = new Uri("net.pipe://localhost/TDD.IInterfaceIWantToMock");
    private readonly ServiceHost host;

    public MyMockClass()
    {
         host = new ServiceHost(this, uri);
         host.AddServiceEndpoint(typeof(IInterfaceIWantToMock), new NetNamedPipeBinding(), uri);
         host.Open();
    }

    // Optional property to access mock
    public IInterfaceIWantToMock Mock { get { return mock; } }

    public void Dispose()
    {
        host.Close();
    }
}
You would then need to implement any members of your interface and in most cases will simply forward the call onto the mock object
    public void IInterfaceIWantToMock.SomeMethod()
    {
        mock.SomeMethod();
    }
Now the bit that can seem quite tricky, the "expectations". The reason it is tricky is because although it is called an expectation, you do not have to "require" the call to be made and you can either be very specific about expectations or very general. It is better to be specific but in some cases this might mean lots of extra code. You can also specify things like how many times to expect the call to be made and what to return when the method is called in this way. It is probably neater to specify expectations inside the Mock class itself but you could expose the mock in a property and set them up elsewhere (just a choice of how tidy you want it). Let us specify a very simple expectation on our mock:
    // In the Mock class
    public void ExpectSomeMethod()
    {
        mock.Expect(proxy => proxy.SomeMethod()).Repeat.Once();
    }
When this method is called, it tells the mock that if someone calls the mock method SomeMethod, you should allow it once but if it was called a second time, the mock would throw a null reference exception. You can specify a specific number of times or even Any() but don't be lazy with Any(), hopefully you will know how many times the method should be called. We will now look at a method which takes an argument and returns something to see what these look like. Bear in mind that lambda expressions are used extensively to make the syntax neater.
    // In the Mock class
    public void ExpectSomeOtherMethod(Guid id)
    {
        // Note that in this example, SomeOtherMethod takes a MethodRequest (which includes a Guid id) as a parameter and returns a MethodResponse
        mock.Expect(proxy => proxy.SomeOtherMethod(Arg.Matches(a => a.id == id))
            .Return(new MethodResponse { success = true })
            .Repeat.Times(2);
    }
If we dissect this, we need to remember that this method is NOT what is going to be called during our testing, that would be the method called SomeOtherMethod(MethodRequest req). This is merely saying that when we do call that method with the id given in the call to the expect method, to return a response which includes a flag called success. This time we have said this will be called twice. We have specified that the arguments to the mock are important by matching id with the subsequent call to SomeOtherMethod() (we could setup the expectation to not care about some or all of the arguments but again that is in danger of being lazy). One of the things that this implies is that we could call this expectation method more than once with different Guids and the mock would then expect SomeOtherMethod() to be called twice for each different Guid passed in. This allows us to be very specific about what we expect and what we don't expect. Suppose for instance we are dealing with 2 different Guids in a test, we want to make sure the correct one is passed to a certain mock method, therefore we ensure that the call to the mock matches the parameter to one we told it to expect (like we did about in ExpectSomeOtherMethod()). There are of course two sides to this story, one is that we want to tell the mock what we expect to pass to the mock but also we must specify what we would then expect the mock to return. This can cause us a risk because we might have to assume what the real-life object will return and we might get it wrong. Therefore, ideally, we would have input from the people who are writing the real object to ensure our mock expectations (specifically what they return for our arguments) are correct. The consumer of the mock then has to create the mock object, setup expectations, optionally verify that all expectations were met and then dispose the mock if required. If using something like NUnit, it is easiest to setup, reset and dispose the mocks in the [Setup], [TearDown], [TestFixtureSetup] and [TestFixtureTearDown] methods to ensure they are always reset correctly (otherwise you might have a previous expectation hanging over from a previous test). An example of doing it all in a single method is shown below:
    // In your test class
    [Test]
    public void SomeTest()
    {
        var mock = new MyMockClass();
        var id = Guid.NewGuid();
        mock.ExpectSomeMethod();
        mock.ExpectSomeOtherMethod(id);

        DoSomethingWhichWillCallOntoTheMock(id);

        mock.Mock.VerifyAllExpectations();        // Could also be done as a method on MyMockClass
        mock.Dispose();                           // Only if implements IDisposable (i.e. creates a service host)
    }
The assumption in this test is that DoSomethingWhichWillCallOntoTheMock() will do whatever it does including calling onto our mocked service. From our examples, it will call SomeMethod() once and SomeOtherMethod() twice with the given id. The call to VerifyAllExpectations is optional and when called will ensure that every single expectation was received. This would fail if you only called SomeOtherMethod() once for example or if you called it with the wrong arguments and it therefore hit a different expectation. Hopefully you get the idea now...

Tuesday, 6 December 2011

Exceptions for Exceptional Things Only!

Exceptions are a strange beast. They are actually worded correctly and are supposed to relate to things that shouldn't happen such as malformed values being parsed and calling services with incorrect data. However, the line has been blurred between what is genuinely exceptional and what is merely incorrect. For example, if you have a service that is called by a web application and a certain method on that service takes a string which represents an integer, it would be reasonable to throw an exception if the string is null or not parsable as an integer. It would be part of the contract for that method (and could be enforced other ways as it happens) but represents a genuine "exception", a problem in application logic or design. Consider a similar example where a user inputs an integer into a text field on a web app and submits it to the code behind. In this case, an exception should NOT be used since this is not exceptional at all but completely expected (people type things in wrongly all the time). Why not use exceptions in this case? Well they seem pretty useful so I guess we could but there are two reasons why we shouldn't. Firstly it confuses our minds as to the correct use of exceptions, we start blurring the line between logic/business/coding errors and simple error handling. The second reason is performance. When an exception is thrown, the framework has to load up a debugging engine which loads the call stack data and which takes a significant amount of resource. This resource is closed once the exception is handled and then opened again if another exception occurs. Why? Because it is designed to be for exceptional conditions and not for normal logic flow. As an example, I ran a test app to compare Int.Parse with Int.TryParse while parsing a bad string. I caught the exception from Parse locally and ignored it. It took 4.24 seconds to run 100,000 exceptions and only 2mS to run 100,000 Tries (2000 times slower to allow exceptions to be part of normal logic). That last line gives a clue to how we might avoid exceptions. We can use alternative methods and operations. It should only be at boundaries that we need to check formats (user interface and interfaces with other systems) anything internally to our application should behave. If we are therefore testing text fields for correctness then we can either use the TryParse family of methods or use a RegEx to specify exactly what we want something to look like. That way we can call IsMatch as a boolean check rather than allow a parsing operation to throw. We can similarly check other fields and types using simple if ( ... ) return false or if ( ... ) DisplayError() bearing in mind that our checks are only useful if we can inform the user or a system admin that something has been entered correctly. As an acid test, you should generally never see an exception caught and ignored. Catching, logging and then continuing might be valid (as long as you have a way of fixing the underlying problem) but if you ignore the exception, you have made it unexceptional.