Greetings :)

Hi, I'm Louis!
I like to code, but I don't do enough of it.

This blog is about trying my best to keep up with the ever evolving stream of technology.

Friday, December 17, 2010

ASP.NET MVC dependency injection

Dependency Injection frameworks such as Ninject can be used to 'inject' dependencies into your ASP.NET MVC web application.

Steps with Ninject:

  1. Download Ninject
  2. Reference the Ninject.dll library
  3. Next we have to stop making ASP.NET MVC call controller classes directly, and instead call the controllers through the Dependency Injection framework.

    In order to do this, we do the following:

      * Create a subclass of ASP.NET MVC's DefaultControllerFactory class, overriding the GetControllerInstance method. (To make this call existing controllers like normal, return new StandardKernel.Get(controllerType)

      * Inside the Global.asax.cs file's Application_Start() method, set the new DefaultControllerFactory class's subclass as the current controller factory (i.e. ControllerBuilder.Current.SetControllerFactory(new MyNewClassName());
OK, so that's done, I'll explain the next bit with my subclass of DefaultControllerFactory, the only extra bit here is that I've set up some keys in my web.config.

Here's my subclass:
public class NinjectControllerFactory : DefaultControllerFactory
    {
        private IKernel kernel = new StandardKernel(new SportsStoreServices());
        protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
        {
            if(controllerType == null)
            {
                return null;
            }
            return (IController) kernel.Get(controllerType);
        }

        private class SportsStoreServices : NinjectModule
        {
            public override void Load()
            {
                Bind()
                    .To()
                    .WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString);
                Bind()
                    .ToSelf().WithConstructorArgument("numberOfItems",int.Parse(ConfigurationManager.AppSettings["ProductsPerPage"]));
            }

        }
    }


And here's the relevant bits in my web.config:

<connectionstrings>
    <add connectionstring="Server=.\SQLEXPRESS;Database=SportsStore;Trusted_Connection=yes;" name="AppDb">
  </add></connectionstrings>

  <appsettings>
    <add key="ProductsPerPage" value="5">
  </add></appsettings>
Yeah, so that's pretty much it - now my controller takes a IProductsRepository, as well as a ItemsPerPage (an int wrapper) object which I inject. The cool thing I find with this is that now I can make my configuration in my web.config; so I can make changes to my application without writing a line of code :)

Thursday, September 23, 2010

Agile vs XP

From my current understanding...

Agile is about high level principles, and best practices when developing software.

A manifesto is "a public declaration of principles and intentions"; and from the agile manifesto we get:


  • "Individuals and interactions over processes and tool
    I interpret this as:
    When building non-trivial systems, we need to work as a team (including the client); A process is just the framework we work within to give the software development structure, and tools are the mechanisms used to create the software. The real value is created  when we extract requirements, and work out who is developing what, and what issues are being encountered.
    Without a high level of communication and interaction, we can't know what issues are currently present, and whether we're truly building something of value that solves the problems at hand.
    Therefore, the main focus should be on communicating with people, and getting feedback from people. Tools and processes are secondary, as they are more like catalysts (or helpers).

  • "Working software over comprehensive documentation"
    I interpret this as:
    Write software that is simple and easy to understand, and which is user friendly. This will avoid having to write a large amount of documentation.

  • "Customer collaboration over contract negotiation"
    I interpret this as:
    OK... first off, contracts will need to be made (to say what will be delivered for what money). The point is though, that the customer doesn't dictate what the requirements are through a contract - we are all part of a team that determines what will be in the contract. So the principle is that the client is actually part of the team, and requirements are 'discovered' rather than negotiated.

  • "Responding to change over following a plan"
    I interpret this as:
    What developers have found in the majority of projects, is that
    "most projects have changing requirements". With traditional processes like the waterfall process, requirements were gathered all up front, and a big long plan was made of exactly how the system would be built.
    When requirements are changed however, it is then expensive to change, because you invested so much time up front creating, and planning the software design (which will now be for little use, as it needs to be changed).
    It therefore makes sense to structure the development process to incorporate the fact that requirements are likely to change (as history has shown it to be very likely). It also makes sense to be open to changes, as the end product should solve the given problem better, and make clients happier (which means they'll tell their friends, and you can charge more because you have higher demand ;))
Of course there are the other 12 principles, which say what we should be doing in order to be Agile. These tell us specifically the way in which we should be working.

Basically the principles say:
  • Communicate well and often with clients and your team
  • Ensure that the team has high levels of trust, motivation, and that work is done sustainably (e.g. not working everyone 60 hours a week every week).
  • Learn about how to design software well, and use these learnings (build competence).
  • Develop in short iterations so that you can get feedback from clients, and be willing to incorporate change requests (be flexible).
  • Keep things simple (complex == complications).
  • Look back and reflect on how you've done, and continually seek improvement and excellence.
OK, so then what the heck is Extreme Programming (XP)?
Well think of Agile as saying what to do (like an interface - it's abstract), and XP as one way to do it (a concrete implementation - it's specific)...

XP is an agile process, which means that it agrees with what the Agile Manifesto says. It has its own values, and has rules for doing things the agile way, as well as the Extreme Programming way.

XP says stuff like:

  • The team must have a stand up meeting every day (for communication).
  • Move people in the team around, so that they work on different parts of the system (to reduce risk of having only one person know about a particular part of the system).
  • Do test driven development.
  • Ensure you refactor your code to make it manageable.

I hope that what I've said is clear; if there's anyone that disagrees with anything I've written, I'd be happy to hear it :)

I'd also be interested to hear if anyone thinks that some of agile doesn't make sense. For me it seems quite logical, and it gives you a warm feeling - it seems like it's really about looking out for one another, being efficient, flexible, and effective.

Friday, September 17, 2010

Refactoring


Steps to take while refactoring:
  1. One SMALL change at a time
  2. Run tests to ensure functionality is the same
  3. Go to step 1

Things to remember while refactoring:
  • Don't add any additional functionality
  • Make the solution easier to understand, and easier for future modification (separation of concerns, good variable naming practice etc).
Refactoring Tactics:
You can also find a lot of information on the refactoring.com website, or Canterbury's OO wiki.
  • Divide and Conquer / Piecemeal refactoring - break the problem into manageable chunks, make only a small change at a time.
  • Rejected Parameter - when extracting a method it is often useful to remove some of the parameters passed to the new method. This can be done by:
    • Inlining local variables into the code that is about to be extracted (so the variable is not declared prior to the method call).
    • Converting local variables to fields, so that the new method will be able to see the data (only do this if it makes sense to make the local variables fields).
  • Caller Swap - Instead of having something like "var2.getX().equals(var1.getX()), you extract the code into a new method isCompatibleWith(var1, var2), and then you move the isCompatibleWith method to the class of var1 or var2 to look like var1.isCompatibleWith(var2)"
  • Inline then extract - when you wish to move a method to another class, you can inline the contents of the method to the other class, and then extract the resulted inlined code into a new method.
  • Temporary static - when wishing to move a method to another class, there may be problems with moving it with refactoring tools. This problem doesn't occur if the method is static, so you can temporarily make the method static, fix any dependencies on local variables (e.g. by passing in a reference to an object as a parameter), and then move the method to a new class, and remove the static declaration.
  • Scaffolding - creating methods temporarily to help transition to a better design. Once the methods no longer have a use, the code in the methods can be inlined into their appropriate positions.


    Code Smells



    Code smells describe code that complicates, duplicates, bloats or tightly couples code.
    Code smells were first described by Kent Beck.


    Books describing / relating to code smells:

    Useful sites covering code smells:


    Common types of code smells:

    Dead code
    Code that is no longer used.
    The Problem
    • Harder to comprehend the code base.
    • Wasted time - reading through, or even changing dead code.
    • More dead code - monkey see, monkey do.
    The Solution
    Remove dead code. The following factors will help in doing so:

    • Domain knowledge - to ensure that the code is in fact dead.
    • Tools - is the code called from anywhere?
    • Testing coverage - can tests be run after deletion to ensure functionality still works?
    Version control will also help ensure that code can be restored if accidentally deleted.

    Duplicate code
    Code that is the same, or performs the same function are showing up in multiple places within a program.
    The Problem
    • Bloat - more code will increase the size of classes, making them more time consuming to read and understand.
    • Maintenance - changes to one of the blocks of code will most likely cause other blocks of code to also be changed. This can also lead to greater defects if the duplicate code isn't updated.
    The Solution
    Refactor the code, combine duplicate code into a method, or into separate classes.

    Comment
    Comments are being used to describe code, as the code readability of the code is poor, making the code hard to follow and understand.
    The Problem
    • Bloat - commented code is often bloated code, making it harder to understand what's going on.
    • Understanding - commented variables can be a sign that the variable name doesn't describe well enough what it is.
    The Solution
    Name things sensibly, and break the problem down.


    Spell variables out rather than using crytpic acronyms.


    If a piece of code is complex, try to split the code into other methods or classes.

    Long Method
    A method is too long
    The Problem
    • Readability - longer code takes longer to read and comprehend.
    • Reusability - a long method may be able to be split into methods or classes that can then be reused.
    • Testability - a long method is likely to need more testing.
    The Solution
    Break the method up into a greater number of methods, or into other classes. Have one method represent a single function, and one class a single concept.

    It may look like breaking a method up into many methods may cause performance degradation, but given the advancement in compilers, there may be no performance hit at all.



    Long Parameter List
    A method has too many parameters
    The Problem
    • The method is doing too much - why does it need all of that information?
    • Understandability - lots of parameters will make code harder to understand.
    The Solution
    Put the data into their own classes, and possibly break the method up into several methods. Ensure that each method is performing a single function, and each class modelling a single concept.

    Large Class
    A class has taken on too much responsibility, and is modelling within it more than one concept.
    The Problem
    • Complexity - if your class represents more than a single concept, it will be harder to understand.
    • Bloat - a greater number of fields and methods will mean the class will take longer to understand.
    The Solution
    Ensure that the class represents a single concept, and break it into several classes if it represents more than a single concept.


    You may find that functionality or state could belong to a different class, in which case functionality or state could be moved to the other class.

    Primitive Obsession
    Code is using primitive data types and method calls to generate desired outcomes, and could be written in a more descriptive and sustainable way. E.g. when generating XML, a primitive obsession smell would be code that writes each tag out line by line. The solution would be to encapsulate the concept of a Tag, and the Tag's attributes into classes, and to render the XML from the classes instead.
    The Problem
    • Code written is not reusable.
    • It may be less clear to someone reading the code what is going on.
    The Solution
    Encapsulate data concepts in classes, and create and call methods on objects of a class to attain desired results.



    Speculative Generality
    Creating today what we speculate will be needed in the future (where there is no current need for a particular feature / design).
    The Problem
    • Wasted time creating code that isn't actually going to be used (it is dead).
    • Greater complexity - now there is more code to sort through
    The Solution
    Design code to a specification. If a feature is needed in the future, you can always refactor code if need be. Until that time, remember YAGNI (You ain't gonna need it!).