Posts Tagged ‘software development’

Software development has changed a lot in just a few years. I remember not very long ago that it was common and expected to work long hours, even pull all nighters just to be able to meet a deadline or worse because the deadline was the following day and there were still dozens of defects to be fixed so the deliverable would barely work. Those days, fortunately, seem to be long gone. I have not been in a project where I have had to do those kind of stupid things, of course there have been times that I have worked a little overtime but those have been the exception rather than the rule.

Unfortunately there are a lot of managers who were developers in those days who still think that we live in those days and expect their development teams to work in that fashion. Not only expect it, but demand it.

Quite recently I was assigned to a project for one of the major credit card companies and we were having our planning game for the upcoming iteration. One of the stories was particularly large so we suggested to break it down in more manageable pieces and gave our estimates to which one of the customer’s managers said, and I quote, “I can lock down a couple of guys in a room and they will have this feature ready in a couple of days”. Needless to say every single one of the members in the team was quite upset about this remark. This was not a matter of challenging our estimate but to question our professionalism. Besides, it is widely known these days that this is the worst way of developing software since it is completely counterproductive and error prone, by the twelfth hour both guys would be making careless mistakes which would generate several very hard to debug defects and the readability of the code would be questionable to say the least.

Anyway, putting aside the fact that we were quite offended by his comment, you can probably imagine how this manager visualized how his team of a couple of guys could deliver his feature. In the end there is absolutely no doubt in my mind that these two guys would pull it off, I have seen it many times before, some brilliant hero style developer getting a required feature to work in record time just before the deadline and he saves the day.

Of course as time goes by this feature will have to be maintained, defects will have to be fixed and requirements will change and guess what, the only person capable of doing that maintenance would be the hero developer who wrote the code because it is so tightly coupled and so tangled up that he is the only one who can understand what it is doing. Of course there would be no tests whatsoever so every time the code would get changed there would definitely be regressions all over the place. Every developer in the organization would dread the idea of working on that piece of code. Not to mention the huge expense these maintenance efforts would be.

I find it hard to believe, and really sad, that there are people, managers and developers alike, who think that we can and should develop software in this fashion. It almost seems as if these people have been living under a rock and have not heard anything about the trends of how to increase the quality of a software product. These people truly believe that the effort put on properly engineering the code and covering it with tests is a waste of time.

To be honest, sometimes I feel I am on the losing end of the battle and the vision of seeing software being developed with discipline and sound engineering practices is but a dream. But you know what, I do not care. I will keep pushing for building software with all the quality characteristics that so much literature, both off an online, is talking about. I will keep fighting against the idea that software development is somewhat of an art; that has got to stop. I will keep trying to evangelize as many people as I can and someday, maybe, we will see that software is built the same way as buildings, bridges, cars, or airplanes, with repeatable practices and solid discipline. I know I am not alone, there are lots of people who are striving for this, and we really hope you will be on our side.

A little while ago I mentioned that in his book Microsoft .Net Architecting Applications for the Enterprise, Dino Esposito says that a working untestable software product is no different than a working testable one; I am paraphrasing, but that the second one will have a better design. I also said that I did not agree with the first part of this statement and I promised that I would expose my arguments so, here we are.

First of all I want to make perfectly clear that I have the highest respect for Mr. Esposito. I believe he is brilliant and every developer who uses Microsoft’s technologies should read as much of his work as possible. So with that out of the way, let’s begin.

I believe that a software product is a living organism that after it is born it grows, changes, reacts to external stimuli, it can even reproduce in the form of other software that uses some of its components. Of course it cannot do it by itself, it is us the developers who make that happen and of course, we do not do it because we have nothing better to do, we do it because someone asked for it. The important thing to keep in mind is that whoever requested the work to be done on that software needs it for one of two reasons: to make money or to save money.

Our customers embark themselves on the arduous, painful, and stressful activity of sponsoring a software product because they have a specific business need and they hope that their new or enhanced software will eventually produce an increase in sales or profit, an increase in productivity, an improvement of their processes, or something of the sort which in the end it just drills down to making or saving money.

To illustrate this let’s imagine there are two competing companies that have a software product which provides all kinds of academic support to schools and universities. It turns out there is a new trend among universities which provides an amazing business opportunity to these companies but they need to enhance and add new features to their products in order to support it. Both products have been developed in-house and they still have their original teams working for these companies so all the developers know their respective code inside out. Both products work well and their code bases are reasonably clean.

After just a few months the first company has implemented just enough of the new features in order to provide the new services. They were able to do it quickly because every time a modification was ready their automated tests told them right away which existing features would break so the issues were dealt with immediately and the QA team did minimal regression testing so they could focus on testing deeply the new requirements.

On the other hand, the second company is still struggling with their release. Every time a new feature is checked in, the QA team needs to spend a few days on a full regression testing effort and when they find either something that broke or a defect on the new features the code goes back to the dev team, of course, which spends a few days figuring out how is it that the new feature broke the old one and how they can make both of them coexist.

Eventually the second company releases its product. Unfortunately their competitor’s has been around for some time now and they have been able to keep their existing customers, get new ones and even take a few of their competitor’s ones.

As you can see, in this fairy tale which can very well happen in the real world, both companies had a working software product, I never said that neither of them had a mess in their code quite the opposite, the only difference was that the first one was designed for testability and had a good suite of tests. Their product helped them to increase their sales so its main objective was fulfilled. The second company since they could not get their product to market quickly enough, lost market share, lost sales and the big investment on their software will be recovered later, if at all.

And there you have it, even though the second company had a working software product, in the end, it did not work for their benefit so do yourselves and your employers or customers a huge business favor and be sure to insist on designing the product with testability in mind and having a great suite of tests to protect it.

Just this week I blogged about how to assert the message of an expected exception and one of the things I was mentioning is how quite some people had proposed different implementations.

Today I found this post from a fellow blogger in which he talks about the MSTest Extensions library. Basically it explains how to install the NuGet package and shows a small example of how to use the ExceptionAssert method to fulfill the need of asserting the thrown exception’s message.

Unfortunately this implementation still suffers from the limitations that we discussed the last time, it can only deal with Actions so if you want to test a method with a return value or a constructor, this option will not provide a solution.

Not everything about this option is bad though, the use of generics is a nice touch so I thought I could include a couple of improvements to the solution I proposed:

    public static class AssertException
    {
        public static void Is<T>(string message, Delegate action, params object[] parameters) where T : Exception
        {
            try
            {
                action.DynamicInvoke(parameters);
                Assert.Fail(string.Format("Expected exception of type <{0}> with message <{1}> but none was thrown.", typeof(T).Name, message));
            }
            catch (Exception ex)
            {
                if (ex is AssertFailedException || ex is AssertInconclusiveException) throw;

                if (ex.InnerException == null)
                {
                    Assert.IsTrue(ex is T, string.Format("Expected exception type: <{0}> Actual: {1}", typeof(T).Name, ex.GetType().Name));
                    Assert.AreEqual(message, ex.Message, true, CultureInfo.InvariantCulture);
                }
                else
                {
                    Assert.IsTrue(ex.InnerException is T, string.Format("Expected exception type: <{0}> Actual: {1}", typeof(T).Name, ex.InnerException.GetType().Name));
                    Assert.AreEqual(message, ex.InnerException.Message, true, CultureInfo.InvariantCulture);
                }
            }
        }

        public static void Is(Exception expected, Delegate action, params object[] parameters)
        {
            try
            {
                action.DynamicInvoke(parameters);
                Assert.Fail(string.Format("Expected exception of type <{0}> with message <{1}> but none was thrown.", expected.GetType().FullName, expected.Message));
            }
            catch (Exception ex)
            {
                if (ex is AssertFailedException || ex is AssertInconclusiveException) throw;

                if (ex.InnerException == null)
                {
                    Assert.IsTrue(expected.GetType().IsInstanceOfType(ex), string.Format("Expected exception type: <{0}> Actual: {1}", expected.GetType().Name, ex.GetType().Name));
                    Assert.AreEqual(expected.Message, ex.Message, true, CultureInfo.InvariantCulture);
                }
                else
                {
                    Assert.IsTrue(expected.GetType().IsInstanceOfType(ex.InnerException), string.Format("Expected exception type: <{0}> Actual: {1}", expected.GetType().Name, ex.InnerException.GetType().Name));
                    Assert.AreEqual(expected.Message, ex.InnerException.Message, true, CultureInfo.InvariantCulture);
                }
            }
        }
    }

As you can see now the class has two overloaded methods, a generic and a non-generic versions. Also the names of both the class and the method changed so it reads a little bit better and finally both now support inherited exceptions.

This is what the use of this class will now look like:

        [TestMethod]
        public void ConstructorThrowsExceptionWhenArgumentsAreInvalid()
        {
           AssertException.Is<ArgumentNullException>("Value cannot be null.\r\nParameter name: number",
              new Func<int?, string, Foo>((num, name) => new Foo(num, name)),
              null, "any");

           AssertException.Is<ArgumentNullException>("Value cannot be null.\r\nParameter name: name",
              new Func<int?, string, Foo>((num, name) => new Foo(num, name)),
              1, string.Empty);

           AssertException.Is(new ArgumentNullException("name"),
              new Func<int?, string, Foo>((num, name) => new Foo(num, name)),
              1, string.Empty);
        }

        [TestMethod]
        public void MethodsThrowExceptions()
        {
            var firstFoo = new Foo(-5, "something");
            AssertException.Is<ApplicationException>("Number should not be negative",
               new Action(firstFoo.DoSomething));

            var secondFoo = new Foo(5, "something");
            AssertException.Is<DivideByZeroException>("Number cannot be divided by zero",
               new Action<int>(secondFoo.DoSomethingElse),
               0);
        }

        [TestMethod]
        public void FunctionsThrowExceptions()
        {
            var foo = new Foo(1, "invalid");

            AssertException.Is<InvalidCredentialException>("Authorization denied",
               new Func<bool>(foo.Validate));

            AssertException.Is<NullReferenceException>("Seriously Foo cannot be null",
               new Func<string, int?, Foo, Foo>(foo.GetNewFoo),
               "any", 3, null);
        }

As you can see the code now almost reads as regular English. It is still more verbose than the attribute option but we discussed the advantages and disadvantages of both approaches on the previous post.

So a couple of conclusions that I can get are that even though we may have a good solution for a particular problem we can always find inspiration and ideas to improve those solutions and we should always be humble enough to realize that our solutions could be improved, no matter how much we might like them.

The same as last time here you have several options to assert the message of exceptions in your unit tests. Use the one you consider the most appropriate. Happy coding.

I dare say that anyone who has worked with software developers has come to the realization that we are very proud people. We take pride in solving challenging problems, in the smart way we implement solutions, sometimes even in the sheer beauty of the code we have written. And we should, software development is not a simple trade, we must develop a strong capacity to abstract the world around us and model it into a working solution by using some arcane language that not everybody can understand. In a nutshell, we must be good at describing and communicating our world to machines.

The only problem with that is that some developers take so much pride in these things that they forget why they are doing what they are doing.

Let’s think about it for a moment. There are only two possible reasons someone would be willing to pay huge amounts of money for a piece of software: make money, or save money. That’s it! That’s all there is to it. Those are the most important goals our incredibly smart crafted solutions should meet. Those are the motivations that drove our customers’ stakeholders to sponsor the project we are currently involved in.

The implications of this are really important. I cannot tell you how many times I have been involved in projects in which the customer wants to enhance its software, add features, adapt it to new requirements because of changes in their industry or their markets, or to fix defects only to come to the realization that all of this is going to take a very large amount of resources, mainly time and money, because of the poor quality of the code in their solution.

Usually I always hear the same reasons as to why this has happened. This code might have been produced by an amazingly brilliant developer who put it together in a few hours or a few days, but it is so complex that he is the only one who knows how to modify it (patch it, and keep patching it). Maybe it was the result of a very tight deadline and the team just did not have enough time to code it properly. It could have been because the managers were always pushing the developers to finish it quickly.

Regardless of the reason, the code is there and now its owner has to invest large amounts of time and money for even the simplest modifications. Guess what? The main goals cannot be met anymore since the company is spending too much money in their software’s maintenance, hence it is not helping them to save money, and it is not helping them to make the money it was supposed to.

We, as developers, need to start thinking about Total Cost of Ownership. This means how much will it cost to own this piece of software over time, and our main objective as developers should be to keep that number as low as humanly possible.

So be proud about the code you write, but focus that pride in the ease in which other developers are capable of adding features, fixing defects or modify that code in general without breaking it all over the place. Take pride in the small investment that your customer needs to put on its maintenance. Take pride in the huge business the code that you wrote is generating for your customer.

Go young grasshopper, code responsibly and make yourself proud.

Nowadays is really difficult to be reading anything about software development without stumbling upon a web page, blog, book, article or the like that discusses software development / design principles. SOLID, KISS, and YAGNI are acronyms that come up in lots of discussions among developers which is good, it means that most people are aware about the importance of good practices in order to build robust applications that do not end up in a maintenance nightmare. The only problem is that I have seen people use them in such a way that they end up being the justification for poor, tightly coupled, difficult to maintain software.

But, I hear you say, how can principles that are supposed to enforce good software be used to produce the opposite? I believe is part of human nature. We can find in history too many examples of things that were created for good that end up being used for evil. In the case of these design principles I believe that a lot of developers really do not want to change the way they have always develop software because, let’s face it, once you are comfortable doing something it is really painful to do the exact same think in a completely different way, so it seems that it is much easier to try to convince others, and ourselves, that our way of doing things is the way that comply with said principles.

Unfortunately most of the time this way is not the way things should be done because it is, well, the way things have always been done that have ended in tightly coupled, spaghetti code. In particular I have been involved in some discussions in which people argued that the idea that good development techniques to decouple software like IoC or dependency injection should not be used, at least not at the beginning, under the YAGNI flag. The “You Ain’t Gonna Need It” idea does have a lot of promise of not adding unnecessary complexity to a piece of software if at that moment there are no requirements that justify it. This is always helpful when you hear someone saying something like “but what if they need to add more types of foo?” That is a valid question to which the answer can always be “what if that requirement is never defined?” The problem comes when you hear people saying that decoupling infrastructure should only be implemented as the need arises because it is not needed from the beginning and it will only add complexity to the code.

By following this last recommendation, the question that comes to mind is when will this decoupling optimization be needed? When the code is so tangled up that it would take weeks to refactor it and break all the dependencies? Is it when each time we are trying to add a feature or fix a defect we end up breaking the application in lots of different places? Maybe when you start hearing developers say they do not want to touch or change a particular section of the code? If all of these scenarios are not something we would like to have in our code then how can employing proved techniques, like IoC or dependency injection, that really do not add that much to the complexity of the code be harmful?

Now days we can even unit test all kinds of tightly coupled messes thanks to tools like TypeMock and MS Fakes. The problem is that these tools are making some people believe that IoC and dependency injection are no longer needed because those techniques’ only purpose was to achieve testability and now we can mock hard coded dependencies. But even with this kind of code all covered with tests, refactoring, fixing defects, and adding features can be a titanic endeavor just because we did not take the time to properly design the application from the beginning because of YAGNI.

As professional, software developers, coders, software engineers, or whatever you want to call us, we need to understand that if someone is going to need more than a couple of hours to at least figure out how the code we wrote works, and that includes both the production code and the tests, then it is not quality code. Having loosely coupled, isolated code aids in this understanding and we need to defend the practices and ideas that have come to improve the way we develop software and not use them to go back and do the ones that we have already left behind.