Sunday, January 31, 2010

How Can Extension Methods Help You?

I am a huge proponent of extension methods in .NET (and other languages).  I believe they are a gateway to making complex code easier to follow and understand, also helps to maintain the object oriented paradigm that .NET is built on. They are also key to the notion of Fluent APIs which has been permeating throughout the programming space for the past year or so.

The idea of a Fluent API is an API that reads very much like an English sentence and is considered a tremendous advancement in readable code.

string value = "500";
int myValue = value.AsInt();

This is a sample code snippet that you see a lot in my projects as I tend to work a library I have created which contains many extension methods for formatting and parsing of values. Notice how as you read the code it flows and its concise with the parsing logic centralized.  Traditionally you might have seen code such as this:

string value = "a500";
int myValue = int.MinValue;
int myValue = int.MinValue;

int.TryParse(value, out myValue);
myValue = Convert.ToInt32(value);

Using TryParse, which is a standard method common to all primitive value types in .NET, this code does not throw an exception and myValue has a value of zero at operations end.  I dont like this because I would expect TryParse to leave the value of myValue unchanged if the parse fails, it does not.  As for the use of Convert it basically emulates what would happen if you called int.Parse on this value, it throws a FormatException.

In addition to the obvious problems of repeating this code anywhere you need to parse an int from a string, I find this to be very procedural.  Now there is no question that all programming, no matter how hard we try is going to be at some level procedural, however, my goal is always to minimize such code and keep things as Object Oriented as possible, after all that is what OO languages are designed for and, not surprisingly, very good at.

Extension methods are also exceptionally useful for custom formatting and outputting for certain types. For example, lets say you wanted to output a DateTime object is standard notation for the United States, mm/dd/yyyy.  Well simply calling ToString(“d”) easily accomplishes this. But littering your code with this code could turn into a potentially horrendous maintenance problem if your boss decides it ought to be dd/mm/yyyy (which is common in Europe), but use an extension method and your code could look like this:

DateTime dt = new DateTime(1983, 1, 13);
Console.WriteLine(dt.AsStandardFormatString());

Using this approach you can have a standard way out outputting a DateTime, perhaps stored somewhere in a different project, that you can easily update, perhaps make culture aware, all without your application ever being the wiser.

So, while Extension Methods are very useful for type conversion libraries and provides standardization out formats and outputs for types, they have another great use. Provides reusable ways to affect changes on objects, collections in particular, while maintaining a very clean interfaces and emphasizing “changes as a unit of work”.  I am sure someone has published something relating to the notion of change as a unit of work, but let me elaborate a little further.

The idea of change as a unit of work derives from the Single Responsibility Principle and Open Closed Principle laid out by Robert Martin.  The idea is that everything has one responsibility and it should carry out that responsibility effectively and thoroughly, from the construction of methods to the definition of classes, they amalgamation of these constructs comprises the application and only by working together can they do such.  Consider the following pieces of code that comes from some code that I wrote this week for a rather complex process that I am working on at work.

var scheduleList = dayList.GroupByShiperId().ConvertToSchedule();

(For those concerned, yes I did mutate this code so that it does not reflect what was actually written).

The idea here is to take a very complicated process and break it down into smaller units and then create functions to carry out those units of work.  Hence any changes to the information is a unit of work.  Easily testable and thanks to extension methods, very clean from an API standpoint. But extension methods are only a small part of this process, understanding the interfaces and classes you have available to you is critical as well as it can help you move code to where it should be.  The method in question could easily have been a 200 line function that would have been a nightmare for anyone to maintain.  Instead its five functions, all with less then 12 lines working together and producing a result.

Using this approach you can be less procedural in your code and leverage the object oriented paradigm of the .NET framework and help people who will come after you understand what is happening. Thus together with good function naming, you can create similar clean reusable APIs for your projects and further leverage the concept of change as a unit of work.

Sunday, January 17, 2010

Thoughts on CodeMash 2010

As CodeMash 2010 has come to a close I would like to take some time to reflect on the conference.  This year was, in my opinion, not quite as good as last year but a lot of fun.  I think this year more people decided to really forgo the sessions and focus on the networking and social interactions that really define what CodeMash is. To me CodeMash has ALWAYS been about the people; people that you meet and the people you get to talk to and learn from.  So that said, I didnt feel the sessions were quite as good as last year, so we will look forward to next year.

One thing that did happen was I did my first ever open spaces sessions where I spoke on Developing for Android. Considering I decided I want to talk about it earlier in the morning and did no formal preparation, it went very well.  I had about 20 people around me and we just talked.  I explained some of the things I have discovered in developing CodeMashDroid and really perked the interest for a lot of people.  I really want to speak next year, but for right now I am preparing to submit my first abstract to the New York City Code Camp, which would give me a chance to really push RCM’s name for web development in the New York area.  But I digress. Speaking of CodeMashDroid, I was amazed at how many people had Droids at the conference. It really is nice to see that Android is making good success against ATT.

I was also not the only one to develop a mobile application for Droid, as an entire company decided to get involved in the development. I also missed the emails about posting information on the app so other would know where to find it, in addition I targeted only Android 2.0+ so I limited myself to those with Droids or newer; but its good to take away lessons from such an experience.  I also learned about some of the shortcomings in my test methodology and emulator capabilities.

Overall, CodeMash was a great experience and I look forward to the same experience next year.  I will be posting my pictures to Facebook later this week as well as hopefully getting time to write up a few blog entries elaborating on the topics I spoke about in my Open Spaces discussion.

Wednesday, January 13, 2010

Introducing CodeMashDroid

I am pleased to announce the release of a new app in the Android app store which I have entitled CodeMashDroid.  This app was developed in response to the request from the CodeMash organizers that attendees develop a solution for managing the CodeMash schedule using a REST API containing information for all conference information.  In addition, I had just purchased a Motorola Droid and was curious in entering the world of modern mobile development.  So I set out to create such an application.

As I developed the application I began to think about the fact that each time I went to a conference we were always being handed a piece of paper with the schedule or people would use their laptops to look up times.  It seems with the prevalence of cell phones, especially in the geek community, the smart handset could be used to manage this information and be used to alert people if they are missing something.  Think of it as a specialized calendar, or even better based on what suggestion, allow integration with Outlook, gCal, and iCal.  From this feedback and train of thought the idea for a conference managing application was born.  CodeMashDroid is a proof of concept app for this idea, and should it prove successful the project will officially kick into gear after CodeMash when we have collected feedback.

To download this app please look for it in the Android App store, it is free and we welcome any feedback as we decide on how to move forward. Please leave these comments in the AppStore feedback section, we will be monitoring this and will work the features into planning as we move forward.  We also welcome naming suggestions as I have no idea what I am going to call this yet :)

Thanks

Friday, January 01, 2010

2009 Year in Review

Its amazing how much has changed in my life this decade, even in the last year. We all know how 2009 was bad for a lot of people and at the start there was much we wondered about.  For me, 2009 was a year of redemption, a chance to make my mark and advance in my industry.  When 2008 ended I had narrowly avoided being laid off from my company, and now as we ring in 2010, I feel that I can breath easy with a fair amount of job security.  Many other things occurred so I thought I would publish a year in review posting for this pivotal year.

Job Questions
As December of 2008 came around I already had a feeling that I would be included in the layoffs.  I hadn't really been on a billable project in quite some time and though the work I had done was valuable from a process standpoint, as a consultant it really comes down to billable hours. I steeled myself for the outcome which came to fruition.  But all was not lost to me, I continued to work even after I was told I didn't have to, I wanted to finish this final feature I was working on, as a token of thanks to the company that gave me my start.  As I started looking around I had garnered much interest from the tech community and my transition to a new company seemed assured when I caught a most fortunate break. I received a phone call from our head manager in Grand Rapids who asked me if I would like my job back.  I was taken aback by this and asked for some time as I was considering other offers.  But the more I thought about it, the more I wanted to be at RCM, I felt it was the best place to learn and grow.

So I had a conversation in which I asked the reasons behind the decision to let me go, it was because they had not put me on work because of the good work I was doing to improve process.  I said to them that if I were to come back, I would not like it if I were simply laid off again for the same reasons, something must change.  And so it did.  From the get-go they were true to their words and through work at me and I thrived.  I worked on one of the biggest projects the company had that year, and it became the most successful, a testament to good planning and a well organized team.

Then came another challenge, we had a client who wanted something done but only PHP could be used due to the existing technologies. This time I pulled out the skills that I had not used since converting to a .NET programmer (heavily anyway) and created a well architected easily extensible enhancement to an existing software product, this time working remotely in more of a leadership role for my potion of the project, again I thrived.  My boss, who had always believed in me, was thrilled, I was starting to really carve out a niche for myself.  Then it came, the need for someone to go to New York to work on a huge project for another division in RCM, one under the direct supervision of the RCM brass.  After a long interview process, I was chosen and so as I close 2009, I look back on the great breaks I had knowing full well that my positioning had a lot more to do with getting them then luck.

Preparations for Japan
With questions about my employment swirling at the end of 2008, my Japan trip for 2010 was also placed in doubt.  Once the employment situation stabilized, the stability led to me beginning to take the steps to prepare for my trip to Japan.  The first step was to refresh my knowledge of the Japanese language through study.  To aid in this study I purchased Rosetta stone with levels 1, 2, & 3 and immediately began my training.  The remote work in New York helped bolster my accounts and allowed me to purchase a new camera which is something that I indicated was necessary for my trip.  And now, as we enter the new year I am preparing final preparations for plane tickets and ryokan, hostel, and hotel reservations following CodeMash.  In addition, I am preparing for the final purchase, a Netbook to help with blogging details of my journey.  Truly 2009, was a great year that saw me take great strides in preparing for my trip.  The final detail that solidified my desire to go was learning that my host brother and sister would be graduating from juugaku (middle school) and shogaku (elementary school) and thus I would be in country and able to attend a juugaku entrance ceremony, and a kookoo (high school) entrance ceremony.  This is very exciting.

Final Reflections
I generally tend to think that each year should bring knowledge and new experiences from which you should grow as a person.  And you should be proactive in seeking these experiences and seeking new challenges to increase your knowledge.  I feel that in the past year I have done this and grown as a person.  I hope to continue to increase my experience and knowledge in 2010 by continuing to challenge myself professionally and grown from the experiences I will have in Japan.  Happy New Year everyone, have a happy 2010.

Sunday, December 13, 2009

The Android Experiment

Mobile development is something that I have always wanted to try, but I never owned a smart phone and so really had no deep drive to develop mobile applications. This all changed recently when I purchased a Motorola Droid and immediately began playing with the Android OS and developing applications for various purposes; mainly for conference management.  I have always hated how I would go to a conference and I would receive a piece of paper of have to check a website to know what sessions happened when.  I set out to create an Android app to help me manage the sessions available for the Codemash conference that I attend annually.

Setting up the Environment
The first step for me is always to set up an IDE and as is the case with most non-Microsoft products and technologies, the IDE in use will be Eclipse. I am not an overly big fan of Eclipse, mostly because I have been spoiled by Visual Studio, but it is a very useful tool for developing.  Aside from Eclipse you will also need the Android 2.0 SDK which will provide you with the emulator necessary for testing your app.  I found this links helpful in walking me through the process of setting things up: http://developer.android.com/guide/developing/eclipse-adt.html

Understanding Android Applications
The first thing to understand about Android apps is they are centered around an Activity.  An application can have many activities of differing types.  In general you will use a vanilla Activity, but other activity types, such as ListActivity, are also available. The primary functions of the Activity class is the onCreate functions which you will override to perform tasks associated with the app startup.  Creating an Android Project in Eclipse you will see your onCreate method defined as such:

@Override
public void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
}

The value being passed into setContentView is actually an integer which maps to a special class called “R” which contains mapped elements from the layout, I will elaborate more on this in the next section.

Understanding the layout
The layouts in Android can be defined in the program if desired but Android also supports defining the layout in XML.  By default, Eclipse will create a layout file called main in a directory called “layout” in a special folder called “res”.  Now look above at what is being passed to setContentView.  A special class called R is maintained by Android which contains references to elements in the view.  This makes it easier to references the items in the layout.

The next thing to understand is that everything that can be shown to the user or used to control the structure of the UI is a “view”.  TextView for example is used to show text, Button is a view which is used to represent a button, ListView which is a list of items.  Views can have IDs which can be added to R and allow them to be easily referenced in the code.  LinearLayout is also a view.  The important thing to remember when defining your layout in XML is all elements must define a layout_width and a layout_height.  If you fail to do this, your application will crash on startup when the content view is loaded.

Understanding Population of ListView
I want to talk about this as it caused a significant amount of pain for me when I was learning it, though looking back I am confused as to why it did, but that is normal I suppose :).  So the first thing to understand is if you are from the .NET world, throw what you know away since Android prefers to make the population of a List as complicated as possible.

First you need to have a ListView on the page, as you might expect.  Next if your activity does not derive from ListActivity you will need to create an Adapter class.  The following is my definition for the adapter I use in my CodeMash app:

public class CustomListAdapter<T> extends BaseAdapter
{
     @Override
     public int getCount()
     {
          return _data.size();
     }

     @Override
     public T getItem(int position)
     {
          return _data.get(position);
     }

     @Override
     public long getItemId(int position)
     {
          return position;
     }

     @Override
     public View getView(int index, View renderer, ViewGroup parent)
     {
          TextView view = new TextView(this);
          return view;
     }
}

This example uses generics for the internal list that will be applied to the ListView, but it is not required.  Here are some additional things that must be added to the class to make it work.

  1. Create a constructor that takes as parameters a reference to the Activity that is called it, a parameter to hold the list you are going to bind to the ListView, and finally a reference to the ListView that we are going to bind to.
  2. The most important thing to do is store references to the Activity and the data internal within the class, as they will be referenced and needed throughout.  You must also call the setAdapter method of the ListView reference and pass as a parameter “this”.

You will notice that inheriting from the abstract class BaseAdapter will require the implementation of several abstract methods: getCount, getItem, getItemId, getView.  Here is an explanation of these functions:

  • getCount()
    • This function is responsible for returning the size of the underlying data set
  • getItem(int position)
    • This function is responsible for returning an object from the underlying data set at a given position
  • getItemId(int position)
    • This function is responsible for returning an identifier for the selected object at a given position. In most of my examples I just return the position that was passed, depends on if I have a key to pass out.
  • getView(int index, View renderer, ViewGroup parent)
    • This is the most important function in the adapter, it allows you to define the ItemRow, that is how each item in the dataset is represented in the ListView.  Most often you will do this programmatically, though I have been working with XML inflation and that shows promise of removing UI building code from the code, which I think helps forge good separation.

So the basic idea with the adapter is to pass in the data, the activity, and the ListView that you intend to reference and use.  You then make a simple call to setAdapter and read your data from within the object creating a view to represent the object for each row in the ListView using the getView method required by the BaseAdapter abstract class.

Conclusion:
My general feelings toward developing on Android are a mixture of annoyance and sheer fun.  On the one hand it is nifty to develop applications for a mobile platform and Android has a wide assortment of features to help you.  On the other hand, I have never been a fan of Java as it feels like a hack next to C# and the absence of the many native syntax features in Java makes some development difficult.  Some of the common things seem more difficult then they should be, but that could be that coming from Silverlight and Xaml, I have a higher expectation for describing layouts through markup.

Overall, I like developing in Java because of how close it is to C# and .NET, and once you get used to the way it does things like events and generics it becomes less about the language and more about the platform, which is the idea.

Thursday, November 12, 2009

Separation of Responsibilities with MVC

Recently I have been working on a new pattern with ASP .NET MVC, based mainly on what I have learned from MVVm and other patterns.  That said, I dont know if I can really call this new, mainly because it really is an amalgamation of patterns working together to keep the architecture clean.

Step 1: The Controller Architecture
As with any system enforcement of DRY (Don't Repeat Yourself) is essential.  This can be achieved any number of ways, though the most common way is the abstraction of what is repeated into a separate layer, to that end we introduce the BaseController class.

public abstract class BaseController : Controller
{
     protected ServiceController CurrentServiceController
     {
          get; private set;
     }

     public void InitalizeServiceController()
     {
          CurrentServiceController =
               ServiceController.CreateNewServiceController();
     }
     
     public void DestroyServiceController()
     {
          CurrentServiceController.Dispose();
     }
}

Some things to note here.  This class is inheriting from Controller which is provided by Microsoft and is the standard class which all ASP .NET MVC Controller derive from.  The two public methods we will get to later.

Step 2: Creating the Controller
ASP .NET MVC has many points of extensibility, and we will take advantage of two of them, the first one is how we “build” a controller.  Whenever a request is made, MVC must determine which controller to instantiate based on the same found in the request (http://www.yourmvcwebsite.com/Series/Edit/1).  Once it has this it will attempt to call the action.  The reason we need to do this is for our data layer.  This is a very simple instance where the Dependency Injection pattern is used, though we are choosing to not use a DI framework such as Ninject or StructureMap because our needs are simple.  The goal is to set the Context reference at creation and then dispose it at release.  We can achieve this by using what is already available and simply leverage basic inheritance.

public class AnimeControllerFactory : DefaultControllerFactory
{
     public override IController CreateController(
          RequestContext requestContext,
          string controllerName
     )
     {
          IController controller = base.
               CreateController(requestContext, controllerName);
          if (controller as BaseController != null)
          {
               ((BaseController)controller).InitalizeServiceController();
          }

          return controller;
     }

     public override void ReleaseController(IController controller)
     {
          if (controller as BaseController != null)
          {
               ((BaseController)controller).DestroyServiceController();
          }

          base.ReleaseController(controller);
     }
}

We could have used Reflection here to determine the type name string and then used Activator to actually get an instance, but why do that when MVC already does it for you.  Thus we call the overridden method, which will return to us an instance implementing IController, from there we can do some simple casting to get to BaseController.  We then call our methods which take care of the initialization process while continuing to remain unaware of what is happening.  This is key, if we were to simply make a call to new() we would be coupling the two projects together, we dont want to that in our ControllerFactory.

Step 3: The Data Access Layer
One of my goals with this architecture was to totally separate generated entities from DTOs.  To that end we create a “service” layer which performs the translation of a DTO to and from a Model.  (Note: I tend to call my generated classes models and my DTOs entities).  The following in an excerpt from the ServiceController class which acts as a “service store” for all services in the application and provides access to these services for all controllers via BaseController.

public class ServiceController : IDisposable
{
     private ServiceController()
     {
          CurrentEntityContext = new AnimeEntityContext();
     }
     
     private AnimeEntityContext CurrentEntityContext { get; set; }
     public static ServiceController CreateNewServiceController()
     {
          return new ServiceController();
     }

     #region Service References
     private SeriesService _seriesService;
     public SeriesService SeriesService
     {
          get
          {
               if (_seriesService == null)
                    _seriesService = ServiceFactory.
                         GetServiceReference<SeriesService>(CurrentEntityContext);

               return _seriesService;
          }
     }
     #endregion

     public void Dispose()
     {
          CurrentEntityContext.Dispose();
     }
}

As you can see we create a private property in this controller for the EntityContext (we are using Entity Framework for the curious).  To reduce the repetitive and monotonous nature of writing the code for instantiating each Service class, I created a base class ServiceBase and then a Factory class (ServiceFactory) which takes care, generically, of setting the underlying context for those providers.

public static class ServiceFactory
{
     public static T GetServiceReference<T>(AnimeEntityContext context)
          where T : ServiceBase, new()
     {
          T returnObject = new T();
          returnObject.SetEntityContext(context);

          return returnObject;
     }
}

Step 4: The Model Binder
For the unaware, ASP .NET MVC permits a special type of parameter passing which analyzes a form collection and assigns properties based on name to an object of a given type. This instance is then passed to the action.  In a previous post, it was discussed how to do this – please visit http://www.jfarrell.net/2009/10/experiments-with-asp-net-mvc-model.html

Step 5: Validation of Models
One of the most monotonous tasks of any web application is validation.  As developers we cant always understand why users do what they do, but we do know we have to guard against it.  How many times have you made pages which touch the same object, thus you have to violate “DRY” and you pay for it later when something changes and you forget one of the spots.

Recently one of the new ways of enforcing validation is by annotating the objects, what I mean by that is the use of attributes to describe what kind of values a property can hold.  You will find these in the System.ComponentModel.DataAnnotations namespace (look for v3.5) as part of MVC 2.  The following is an example of decorating a class to enforce validation.

public class SeriesEntity : IEntity
{
     // simple data references
     public int SeriesId { get; set; }

     [Required(ErrorMessage = "Series name is required")]
     public string Name { get; set; }
        
     public bool IsActive { get; set; }

     // complex data references
     public IList<SeasonEntity> Seasons { get; set; }
     
     [CollectionLength(1, ErrorMessage = "At least one Genre must be selected")]
     public IList<GenreEntity> Genres { get; set; }
     public StudioEntity Studio { get; set; }
}
Note: CollectionLength is a non-standard validation attribute

Validation takes place in the Model Binder, so we will return to the custom model binder from the referenced blog post. The OnPropertyValidating method is called for each property the binder is called to bind, thus we need to have its value first, hence the previous post will explain how to accomplish this.

protected override bool OnPropertyValidating(
     ControllerContext controllerContext,
     ModelBindingContext bindingContext,
     PropertyDescriptor propertyDescriptor,
     object value)
{
     var validationAttributes = bindingContext.Model.GetType().
          GetProperty(propertyDescriptor.Name).GetCustomAttributes(false).
          OfType<ValidationAttribute>();
     foreach (var validationAttribute in validationAttributes)
     {
          bool result = validationAttribute.IsValid(bindingContext.Model.
               GetType().GetProperty(propertyDescriptor.Name).
               GetValue(bindingContext.Model, null));

          if (!result)
          {
               bindingContext.ModelState.AddModelError(
                    propertyDescriptor.Name, validationAttribute.ErrorMessage);
               return false;
          }
     }
     return true;
}

Something that I noticed working with the standard binder is that it tends ignore properties containing complex types.  That is if you had an array of type Genre, so Genre[], it would not bind because of Genre.  If you instead made it int[] and gave it an array of GenreId values, it would work just fine.  But I wanted to take things one step further and have my entity comeback mostly complete and not have extra properties just to support the binder.  Further, I wanted to be able to validate things, hence the reason for my custom validation attribute CollectionLength.

public class CollectionLengthAttribute : ValidationAttribute
{
     private int MinLength = 0;
     private int MaxLength = int.MaxValue;

     public CollectionLengthAttribute(int minlength)
     {
          MinLength = minlength;
          MaxLength = int.MaxValue;
     }

     public CollectionLengthAttribute(int minlength, int maxlength)
     {
          MinLength = minlength;
          MaxLength = maxlength;
     }

     public override bool IsValid(object value)
     {
          if (value != null)
          {
               var collection = value as IList;
               if (collection != null)
               {
                    return collection.Count > MinLength
                         && collection.Count <= MaxLength;
               }
           }
           return false;
     }
}

Conclusion:
The idea behind this pattern is separate things in a very thread safe sort of way, also to unify the context being used as well remain highly testable.  In addition, we want to reduce dependencies and the use of reflection.  Reflection is an expensive operation that we don't want to do more then we have to.  By using DefaultControllerFactory we are able to rely on what already exists.  This action alone reduces the amount of foreign dependencies (interfaces, base classes) we need to get our code to work.  We have two assets that are used for this purpose IEntity and BaseController.

The next piece to this is how to structure the controllers themselves and how to get the data from the DTOs to the Views in a structured way such that type safety is preserved and we refrain from duplicating as much as possible.  That post will follow early next week.

Friday, October 30, 2009

Reflecting on my first tour of duty in New York

So as I lay here in a hotel in Queens, New York I have had a chance to reflect a little on the experience I have gained over the last few months as I worked for the client out on Long Island.  There were many high points and a few low points, mistakes made and successes gained.  All in all, I really couldn’t have asked for things to have gone better.  I wanted to take some time and share with you some of the the things I learned and/or experienced.

1) The virtues of planning
As a programmer we often hear the stories about staying out late or working long hours to finish a project.  I can recall many people in college pulling all nighters to finish projects and the constant stream of rumors from the West Coast that programmers out there often sleep at the office.  I have never been a fan of such a thing and usually feel that when you find yourself in such a situation it is most often because you did not plan accordingly.

With this project, I made every attempt to plan. I planned what I was going to do, I planned what I was going to concentrate and think about for the future. I thought about what I would train my colleagues on for a given day. And in the end it really paid off, I worked very little hours and accomplished a great deal.  The application that was built was built in accordance with known practices.  In fact, a colleague was sent to a Microsoft technology seminar where practices for developing an application was discussed. Upon his return he shared with us what we learned, and essentially described the application’s architecture as I had intended it.  This was all thanks to proper planning as well as the invaluable lessons I learned from working with a host of people at RCM.

2) Communication is vital and can be redundant
I have always had a hard time remembering things, so I write stuff down.  But when I write stuff down I become too detailed and I miss stuff being said as I am writing stuff down.  Thus I am a person who likes to try to understand small detailed chunks and maintain a high level conceptual understanding of what I am doing.  I am also not someone who can understand everything via reading, I am very kinetic learner.  Thus sometimes I had to ask questions repeatedly to make sure I understood things, especially when it came to the sometimes complex business rules of my client.

To help with this I created a great working relationship with all of the members of the team by being myself.  By the end, I felt like one of the members in the company, not a consultant and I was able to speak candidly around them, always maintaining who was in charge.  There were times I had to take charge of a situation and explain what can and cannot be done on the fly.  I remember once that I had to explain that adding values to a table was great but unless the application knew what the value mean’t you could not add functionality this way, at least with the architecture that was put into place.

I owe this great level of communication to the high satisfaction the client has with what was produced and what they learned from this experience.  At the start of the project a couple people knew some .NET others had only ever done AS400 programming. By the end today, they were able to speak about various abstract concepts that they had come across in their own research or things that I had spoke about during training. And they were able to understand why I had made the decisions that I had and how to help each other continue with the design concepts already in place.

3) Dont accept tools and frameworks blindly
If you read and follow this blog you know that we decided to use the Coolite UI framework for this project.  Coolite is an set of controls built around the ExtJS framework that is designed to help developers quickly create a rich and visually appealing websites quickly.  With the lack of a designer on the team this framework was very appealing and was chosen as the backbone for the application; this was all before I arrived on the scene.

Initially, people were ready to go with MVC and Linq2Sql so we started down that path. But I quickly noticed that this application was going to be complicated and require an advanced architecture to support the requirements.  I have no doubt that such an architecture is possible in MVC and I would really loved to have done this application in MVC.  However, given that I have far more experience with Webforms and Coolite worked better with the event model offered by Webforms I convinced the client switch to Webforms.  While I also tried to convince them to move away from Linq2Sql in favor of the the Kinetic Framework, which we have used at EIS for numerous large web projects.

In the end, because the application was designed so modularly it really could support a change in ORM without a major change, but the reason that was given to me was since the client wanted to use SQL stored procedures for the operations Linq2Sql seemed the best choice to them, so I lost that argument. However, by the end I spoke with the client again about this decision, and he agreed that given the chance he would have revised his decisions and decided to use Linq in place of the stored procedures.

All in all the experience was exceptionally positive for both myself and the client. The application that was created was visually appealing and rich in functionality, and all through the QA sessions very few bugs were found and no critical bugs.  Of course, as the application moves to the official QA team I expect that problems will be found but with the excellent communication regarding project requirements I feel that these problems will not be serious.  In addition, I was able to impress upon those I was training the value of not just .NET and its languages, but also the value and ability to think abstractly enough to work in a object oriented environment.  I look forward to my return in two weeks to assist the client with a second .NET project while the approval for phase two of the current project is decided.