Archive for the ‘Development General’ Category

As a continuation to my recent rant about the differences between programmers and developers and how programmers love to code and … well, everything it is mentioned in that post, I felt like sharing a little bit of fun I had with this stackoverflow question.

Since it had already been answered and actually there was a little debate going on about the pros and cons of the accepted answer I was about to close it and look for something else when I decided to have a little bit of fun and make the solution generic.

Not like it was difficult, after a couple of minutes I had this:

    public class PropertyValidator
    {
        public bool Validate<T, TResult>(IEnumerable<T> list, Func<T, TResult> expression)
        {
            return list.Select(expression).Distinct().Count() <= 1;
        }
    }

But the fun didn’t end there, since this was not needed in what I was working on I had to demonstrate that it worked by other means, what could those means possibly be? You guessed it, unit tests!

    [TestClass]
    public class SameValueInPropertyValidatorTests
    {
        private PropertyValidator _validator;

        [TestInitialize]
        public void Initialize()
        {
            _validator = new PropertyValidator();
        }

        [TestMethod]
        public void ReturnsTrueIfListIsEmpty()
        {
            var list = new List<string>();
            Func<string, string> expression = x => x;

            var result = _validator.Validate(list, expression);

            Assert.IsTrue(result);
        }

        [TestMethod]
        public void ReturnsTrueWhenValuesAreSameForStrings()
        {
            var list = new List<string> {"1", "1", "1", "1", "1", "1"};
            Func<string, string> expression = x => x;

            var result = _validator.Validate(list, expression);

            Assert.IsTrue(result);
        }

        [TestMethod]
        public void ReturnsFalseWhenValuesAreNotSameForStrings()
        {
            var list = new List<string> { "1", "1", "2", "1", "1", "1" };
            Func<string, string> expression = x => x;

            var result = _validator.Validate(list, expression);

            Assert.IsFalse(result);
        }

        [TestMethod]
        public void ReturnsTrueWhenValuesAreSameForKeyValuePair()
        {
            var list = new List<KeyValuePair<string, int>>
            {
                new KeyValuePair<string, int>("any1", 1),
                new KeyValuePair<string, int>("any2", 1),
                new KeyValuePair<string, int>("any3", 1),
                new KeyValuePair<string, int>("any4", 1),
            };

            Func<KeyValuePair<string, int>, int> expression = x => x.Value;

            var result = _validator.Validate(list, expression);

            Assert.IsTrue(result);
        }

        [TestMethod]
        public void ReturnsFalseWhenValuesAreNotSameForKeyValuePair()
        {
            var list = new List<KeyValuePair<string, int>>
            {
                new KeyValuePair<string, int>("any1", 1),
                new KeyValuePair<string, int>("any2", 1),
                new KeyValuePair<string, int>("any3", 456),
                new KeyValuePair<string, int>("any4", 1),
            };

            Func<KeyValuePair<string, int>, int> expression = x => x.Value;

            var result = _validator.Validate(list, expression);

            Assert.IsFalse(result);
        }

        [TestMethod]
        public void ReturnsTrueWhenValuesAreSameForEnumProperty()
        {
            var list = new List<Car>
            {
                new Car {Color = Colors.Red},
                new Car {Color = Colors.Red},
                new Car {Color = Colors.Red},
                new Car {Color = Colors.Red},
            };

            Func<Car, Colors> expression = x => x.Color;

            var result = _validator.Validate(list, expression);

            Assert.IsTrue(result);
        }

        [TestMethod]
        public void ReturnsFalseWhenValuesAreNotSameForEnumProperty()
        {
            var list = new List<Car>
            {
                new Car {Color = Colors.Red},
                new Car {Color = Colors.Red},
                new Car {Color = Colors.Black},
                new Car {Color = Colors.Red},
            };

            Func<Car, Colors> expression = x => x.Color;

            var result = _validator.Validate(list, expression);

            Assert.IsFalse(result);
        }

    }

And since we were on a roll, why not remove the duplication by creating generic methods to assert the results:

    [TestClass]
    public class SameValueInPropertyValidatorTests
    {
        private PropertyValidator _validator;

        [TestInitialize]
        public void Initialize()
        {
            _validator = new PropertyValidator();
        }

        [TestMethod]
        public void ReturnsTrueIfListIsEmpty()
        {
            var list = new List<string>();
            Func<string, string> expression = x => x;

            AssertIsTrue(list, expression);
        }

        [TestMethod]
        public void ReturnsTrueWhenValuesAreSameForStrings()
        {
            var list = new List<string> { "1", "1", "1", "1", "1", "1" };
            Func<string, string> expression = x => x;

            AssertIsTrue(list, expression);
        }

        [TestMethod]
        public void ReturnsFalseWhenValuesAreNotSameForStrings()
        {
            var list = new List<string> { "1", "1", "2", "1", "1", "1" };
            Func<string, string> expression = x => x;

            AssertIsFalse(list, expression);
        }

        [TestMethod]
        public void ReturnsTrueWhenValuesAreSameForKeyValuePair()
        {
            var list = new List<KeyValuePair<string, int>>
            {
                new KeyValuePair<string, int>("any1", 1),
                new KeyValuePair<string, int>("any2", 1),
                new KeyValuePair<string, int>("any3", 1),
                new KeyValuePair<string, int>("any4", 1),
            };

            Func<KeyValuePair<string, int>, int> expression = x => x.Value;

            AssertIsTrue(list, expression);
        }

        [TestMethod]
        public void ReturnsFalseWhenValuesAreNotSameForKeyValuePair()
        {
            var list = new List<KeyValuePair<string, int>>
            {
                new KeyValuePair<string, int>("any1", 1),
                new KeyValuePair<string, int>("any2", 1),
                new KeyValuePair<string, int>("any3", 456),
                new KeyValuePair<string, int>("any4", 1),
            };

            Func<KeyValuePair<string, int>, int> expression = x => x.Value;

            AssertIsFalse(list, expression);
        }

        [TestMethod]
        public void ReturnsTrueWhenValuesAreSameForEnumProperty()
        {
            var list = new List<Car>
            {
                new Car {Color = Colors.Red},
                new Car {Color = Colors.Red},
                new Car {Color = Colors.Red},
                new Car {Color = Colors.Red},
            };

            Func<Car, Colors> expression = x => x.Color;

            AssertIsTrue(list, expression);
        }

        [TestMethod]
        public void ReturnsFalseWhenValuesAreNotSameForEnumProperty()
        {
            var list = new List<Car>
            {
                new Car {Color = Colors.Red},
                new Car {Color = Colors.Red},
                new Car {Color = Colors.Black},
                new Car {Color = Colors.Red},
            };

            Func<Car, Colors> expression = x => x.Color;

            AssertIsFalse(list, expression);
        }

        private void AssertIsTrue<T, TResult>(IEnumerable<T> list, Func<T, TResult> expression)
        {
            var result = _validator.Validate(list, expression);

            Assert.IsTrue(result);
        }    

        private void AssertIsFalse<T, TResult>(IEnumerable<T> list, Func<T, TResult> expression)
        {
            var result = _validator.Validate(list, expression);

            Assert.IsFalse(result);
        }    
    }

Not exactly a break through discovery or even a coding kata but still it was a cute exercise for me to kill some time.

Would you like to share your favorite exercises or your sources of inspiration for coding research? I’d love to hear about them.

Advertisements

Recently I read a blog post that discusses the differences between a programmer and a developer. After reading the first couple of paragraphs my first reaction was to think that I consider myself to be a programmer but, because of all the “inherent characteristics” that programmers must have, according to this definition, this thought was very short lived.

The first characteristic that is discussed about programmers is that they love to write code. Well, this is something that it is very easy to feel identified with. Not very many people who write code for a living do so without loving it, and those who do usually move on to other things in a relatively short while. Personally I love to write code and I am never satisfied with the end result, no matter how much work I put into it, I always have this nagging feeling that there are ways to improve it. I will confess that sometimes after the writing is done I stare at the overall solution and marvel at a piece of code that is elegant, simple to understand, easy to maintain, fully testable and, to a reasonable extent, covered in unit tests. Even though that, I still get the feeling that I could improve the work further but that does not mean I sometimes do come up with code that is still beautiful, even if I say so myself, and these characteristics that have been mentioned are my definition of beautiful code. Up until this moment I still complied with this definition of programmer.

The second characteristic is that a programmer writes code just for the mere pleasure of it, even if that code does not fulfill any particular need other than programmer’s needs. Even this makes perfect sense to me since we, as programmers, by writing code just for the sake of it we keep sharp, enhance our skills, feed our curiosity and encourage the everlasting search of the best way to implement something. How often do you just happen to be writing some random code and realize that what you are implementing, or the way you are implementing it, could be used to improve some code you wrote a while back or that it solves the problem in which you are currently working on? I bet this has happen more than once to you. This overall idea still made sense in making me put myself in the “programmer club”.

The next trait that a programmer has, according to the author, is that she knows how her code works so she does not need to write tests at all since she knows where the code might break and she knows how to avoid it. Wait a second, WHAT?! Are you serious? Are you trying to tell me that this is a trait and something to be proud of? Hell, no! Of course any programmer, or coder for that matter, can write code without tests, just like any manufacturer of any product you can think of can manufacture said product without any kind of quality assurance process and still every single manufacturing plant in the world ensures that their products comply with a minimum quality standard. In my book, anybody who aspires to have the noble title of programmer should go out of her way to make sure her code has a minimum code coverage that ensures that said code does what she intends it to do. Even if it is just an exercise, a kata, research something or an excuse to hang out with the computer and forget about society for a while.

So I kept reading and I got to the part where, as a programmer, the author would rather be in his study coding day and night without talking to anybody and having nobody talking to him and be able not to attend any meetings. So he says that real programmers are like geeky theoretical physicist locked up in university labs and who alienate themselves from all human beings. Wait, I’ve seen this before, oh yeah, right! He thinks programmers should be like Sheldon Cooper from The Big Bang Theory! Jokes aside, there are quite a few things to say about this but that will be on a later post.

Honestly this kind of stereotypical description of what a programmer should be is so 1980’s that I am very concerned that there may be a lot of people out there who still believe it. People who think they are doing Agile but in reality they are still doing waterfall with daily stand up meetings, people who claim to be professional programmers and in reality are just cowboy coders putting a huge amount of spaghetti code together that only they can change, and even then they cause a lot of regression errors in the process which they solve by entangling the spaghetti even more. There even is still people who refuses to learn the necessary techniques to go into these kind of messes and start to improve them even though there is a lot of literature available that discusses which techniques are those and how to apply them like this one and this one.

Seriously if you want to be called a programmer instead of a developer like the author of this blog suggests that is fantastic, but embrace the modern definition of it, learn, acquire, and apply the right set of skills and, most importantly, develop the right attitude required for the job, forget about this old school mombo-jumbo and become a proud professional programmer.

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.

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.

In the last few years a lot has been written about the benefits of automated testing, unit testing, TDD, and mocking frameworks. So much has been written about it, even demonstrated in the field, that I find quite surprising, and frightening, that there are some blogs out there in which their authors claim that the effort required to write the tests and let the tests drive the design is a huge overhead, not necessary, increases the complexity of both the production code and the tests themselves, a bad approach among other things.

Unfortunately I was unable to find the exact quote, but I believe that it was in his book, Architecting Applications for the Enterprise, that Dino Esposito says, I am paraphrasing, that there is no difference between a working piece of software that is testable and another one that is not, but the one that is designed with testability in mind will have a much better design. Even though I do not agree with the first part of this claim, the reasons and arguments are the subject of another post, I absolutely agree with the second part of it. When we design our software with testability in mind the end result is a much more maintainable and loosely coupled design.

With these ideas in mind, the next series of posts will aim to address some of the, what I consider, misconceptions about designing for testability, loosely coupling, and the YAGNI and KISS principles. I hope that by the end of them I will be able to add a small contribution to the development community in trying to make software development a more robust discipline.

Designing for testability does pose a number of challenges that have been addressed in a number of ways. One of these ways has been the Inversion of Control (IoC) principle, and more specifically by using Dependency Injection. Another way has been by the creation of tools like TypeMock and Microsoft Fakes. In a nutshell these tools are able to reach into unreachable code and replace static methods and tightly coupled classes with stubs so that untestable code can be unit tested. We will discuss this type of tools at another time, what I am more interested right now is to talk about an online argument in the comments section of this blog post between two people about the use of these tools.

The person who was against the use of this tools was concerned about the unmaintainable and tightly coupled software that could be developed since the limitations of replacing those hard coded dependencies were no longer there. The other person, who was not only in favor of these tools but avidly encouraged their use, claimed that his concerns were the result of the idea of “the ability for code to be unit testable in classical terms” and that the use of an abstract factory would reduce the coupling even further. This last comment was what drew the line for me. Don’t get me wrong, I love the abstract factory pattern and I think is an invaluable tool to abstract the creation of objects from the components that will use them. This does not mean that an abstract factory in itself will be loosely coupled to the code that needs to decide which concrete factory to instantiate and have it create the required object.

To be able to demonstrate these ideas, let’s think about a smart phone manufacturer that has different lines of products and these products can be subdivide into sub-products to satisfy the increasing demands of a hungry market. Of course when the manufactured products reach a certain point in the assembly line a certain number of, what do you know, tests will have to be performed to make sure each product comply with the company’s quality policies. In order to do that all products need to have a common interface to be handed to the testing process, which will not be interested in the exact model of the product.

    public interface IPhone
    {
        void DoSomething();
    }

    public class HighEnd16Gig : IPhone
    {
        public void DoSomething(){}
    }

    public class HighEnd32Gig : IPhone
    {
        public void DoSomething(){}
    }

    public class LowEnd16Gig : IPhone
    {
        public void DoSomething(){}
    }

    public class LowEnd32Gig : IPhone
    {
        public void DoSomething(){}
    }

We can see that we have a high end and a low end phone and that each of them comes in 16 and 32 gigs of storage models. Since the testing process should not care about what kind of phone it will receive at any given time, we define an abstract factory to create the concrete product before starting the tests.

    public interface IPhoneFactory
    {
        IPhone Create();
    }

    public class HighEndFactory : IPhoneFactory
    {
        private readonly StorageSize _storageSize;

        public HighEndFactory(StorageSize storageSize)
        {
            _storageSize = storageSize;
        }

        public IPhone Create()
        {
            switch (_storageSize)
            {
                case StorageSize.Gig16:
                    return new HighEnd16Gig();
                case StorageSize.Gig32:
                    return new HighEnd32Gig();
                default:
                    throw new ArgumentException("Unknown high end model.");
            }
        }
    }

    public class LowEndFactory : IPhoneFactory
    {
        private readonly StorageSize _storageSize;

        public LowEndFactory(StorageSize storageSize)
        {
            _storageSize = storageSize;
        }

        public IPhone Create()
        {
            switch (_storageSize)
            {
                case StorageSize.Gig16:
                    return new LowEnd16Gig();
                case StorageSize.Gig32:
                    return new LowEnd32Gig();
                default:
                    throw new ArgumentException("Unknown low end model.");
            }
        }
    }
    public interface IManufacturingProcess
    {
        void ProcessProduct(ProductType productType, StorageSize storageSize);
    }

    public class TestingCell : IManufacturingProcess
    {
        public void ProcessProduct(ProductType productType, StorageSize storageSize)
        {
            //Do some stuff.

            IPhoneFactory factory;
            switch (productType)
            {
                case ProductType.HighEnd:
                    factory = new HighEndFactory(storageSize);
                    break;
                case ProductType.LowEnd:
                    factory = new LowEndFactory(storageSize);
                    break;
                default:
                    throw new ArgumentException("Unknown Product Type");
            }

            var product = factory.Create();
            ExecuteTests(product);
        }

        private void ExecuteTests(IPhone product)
        {
            product.DoSomething();
        }
    }

This is a very good design, we can see that the component that is going to start the testing process is completely abstracted from the creation mechanism of the different types of products, but there is still one problem, this component is tightly coupled not only to the abstraction but to the two concrete implementations as well. This component is deciding which kind of factory it needs to instantiate to ask for the product it will send to the testing process so if new product lines are added, it will have to be modified to include the new concrete factories and this is a big maintenance issue. Even worse, this is just one step of the whole process, other processes will have to implement the same logic to determine which factory to use.

A much better approach would be to inject the factory to this component so it is completely agnostic of the kind of factory it will be calling.

    public interface IManufacturingProcess
    {
        void ProcessProduct();
    }

    public class TestingCell : IManufacturingProcess
    {
        private readonly IPhoneFactory _factory;

        public TestingCell(IPhoneFactory factory)
        {
            if(factory == null) throw new ArgumentNullException("factory");
            _factory = factory;
        }

        public void ProcessProduct()
        {
            //Do some stuff.

            var product = _factory.Create();
            ExecuteTests(product);
        }

        private void ExecuteTests(IPhone product)
        {
            product.DoSomething();
        }
    }

The benefits of this approach are so many that it just cannot be underestimated:

  • These factories are used by a lot of components throughout the manufacturing process so the code to decide which factory to instantiate will not have to be duplicated in each one.
  • If the factories, the products, and their interfaces are each defined in their own assembly the components that use them only need a reference to the one with the interfaces so, even if new factories are constantly added the assemblies that use them will not have to be recompiled making all of your assemblies truly decoupled.
  • The instantiation of the factories can be isolated in a single place of the application, preferably in the Composition Root.
  • The components that require the factories’ adhere more to the Single Responsibility Principle.
  • The component that will perform the tests can be unit tested in complete isolation without any concern of how the factories create the products.
  • Once you have made your peace with the concepts of abstract factory, dependency injection, and composition root, a nice implementation of all of these concepts working together can be used.

Even though abstract factories are a wonderful tool to isolate and abstract the creation of components from their callers, they are not, in their own sense, a way to achieve a loosely coupled design. To this day the best design technique that I have seen to achieve absolute and truly loose coupling, not only from individual classes but from full assemblies, is dependency injection. I will not presume to say that this is the golden hammer of software engineering, but so far it has proven itself to be the best we’ve got.

In the twelve years I’ve been developing software I’ve seen quite a few methods, classes, subroutines, scripts, among others. A statement that has been true ever since day one of my development years is that I have spent more time reading code than writing it and I’m sure I don’t have to tell you about some of the horrors I’ve seen during this time. Thinking about this, I’ve come to realize that after so many years of hearing and reading about best practices, self-documented code, small classes and methods, single responsibility purpose, and quite some others nifty concepts it’s amazing how you can still find 500 or more lines of code methods, huge classes that have multiple responsibilities, tightly copuled and low cohesive objects and all sort of development nightmares that make the code difficult to read and maintain.

Surely there is not a single developer who has not written a method only to come back to it some time later and not being able to understand what on earth is it doing, or at the very best to have to spend quite some time figuring it out. And of course that is even more true when we stumble upon a piece of code written by someone else.

With legions of excellent developers all over the world, I truly believe that there can never be enough talk about ways of trying to improve the readability and ease of maintainability of code so, in that tone, I would like to post here a very small demonstration of a piece of code we had at our current project that was, well quite bad, and how it became much more readable after doing some very simple refactoring.

private void SetPermissionToAdjustOrCancell(CustodyTicketDto custodyTicketDto)
{
  var userRole = PortalInternalService.GetRolesforUser(UserSettings.Current.UserId, UserSettings.Current.CompanyId);
  bool canCancelAdjustTicket = false;

  foreach (RoleDto role in userRole)
  {
     if (role.RoleName == Roles.FIELD_OPERATOR_RECEIPT && Activity.ToUpper() == “RECEIPT”)
       canCancelAdjustTicket = true;

     if (role.RoleName == Roles.FIELD_OPERATOR_DELIVERY && Activity.ToUpper() == “DELIVERY”)
       canCancelAdjustTicket = true;
  }

  _view.IsUserAllowedToAdjustOrCancel = canCancelAdjustTicket &&
    (
     (custodyTicketDto.IsCancellable.HasValue && custodyTicketDto.IsCancellable.Value) ||
     (custodyTicketDto.IsAdjustable.HasValue && custodyTicketDto.IsAdjustable.Value)
    );
}

Now this method is by far not the worst anybody has ever seen, but it’s bad enough to illustrate what we should be after. As you can see it has quite a few lines of code, there are several things going on at different levels of abstraction and you need a few moments to analyze each conditional within the method to understand what each one does.

So the first thing we had to do was to write a few unit tests just to make sure we were not breaking anything and once that was set we started breaking up this creepy method into something much more manageable and quite more readable. The end result, at least for now, was this:

private void SetPermissionToAdjustOrCancell(CustodyTicketDto custodyTicketDto)
{
   var userRoles = PortalInternalService.GetRolesforUser(UserSettings.Current.UserId, UserSettings.Current.CompanyId);

   _view.IsUserAllowedToAdjustOrCancel = IsUserInRoleThatAllowsCancelOrAdjust(userRoles) && IsTicketAdjustableOrCancellable(custodyTicketDto);
}

private bool IsUserInRoleThatAllowsCancelOrAdjust(IEnumerable userRoles)
{
   bool canCancelAdjustTicket = false;

   foreach (RoleDto role in userRoles)
   {
      if (IsReceiptRoleAndReceiptActivity(role) || IsDeliveryRoleAndDeliveryActivity(role))
         canCancelAdjustTicket = true;
   }
   return canCancelAdjustTicket;
}

private bool IsReceiptRoleAndReceiptActivity(RoleDto role)
{
   return role.RoleName == Roles.FIELD_OPERATOR_RECEIPT && Activity.ToUpper() ==
“RECEIPT”;
}

private bool IsDeliveryRoleAndDeliveryActivity(RoleDto role)
{
   return role.RoleName == Roles.FIELD_OPERATOR_DELIVERY && Activity.ToUpper() ==
“DELIVERY”;
}

private bool IsTicketAdjustableOrCancellable(CustodyTicketDto custodyTicketDto)
{
   return (custodyTicketDto.IsCancellable.HasValue && custodyTicketDto.IsCancellable.Value) ||
(custodyTicketDto.IsAdjustable.HasValue && custodyTicketDto.IsAdjustable.Value);
}

Now I am very well aware that this method could still be improved, for example the loop in the IsUserInRoleThatAllowsCancelOrAdjust method could very well be replaced by linq queries or that the IsTicketAdjustableOrCancellable could be broken in two methods, but the point is that now someone who has never seen this code will have very little trouble if at all to understand what each method is doing, and without having to add a single comment !!!!

I do not mean to say that this is THE way to go but at least it has been working for us. We’ve had a few new developers say that it is so simple to understand this kind of code and add features or fix defects in it so, if you think this kind of style could be beneficial I encourage you to give it a try and decide if it could prove to be usefull in the long run.