November 19, 2009 Leave a comment
As programmers, we are expected to write code that is efficient, readable, and scalable. There are quite a few things that we can do to meet these expectations from using design tools to adopting code standards to using code analysis tools. One thing that you can do to improve your overall development process is to create your own code libraries. There are many benefits to this. The most obvious benefit is it reduces the time you spend writing code as you don’t waste time writing the same code over and over.
Another benefit is centralization. If you’ve been following my previous articles you’ve probably noticed there are several classes that have been included in each of the sample projects. By including these classes, we’ve eliminated the need to keep writing that code each time we want to use it. However, what if we found a bug in that code? As it stands now, we would have to fix the bug in each project that contains the class. If we had instead put those classes into a common code library we would only have to fix the bug in one place, saving us a lot of time while ensuring that the same fix is applied in each project. The same would be true if we decided to extend one of those classes to add new functionality.
Creating your own code libraries is relatively easy to do. The most important thing is to give it some thought before you get started and design a system that will work best for you. I’ll spend the rest of this article going over some of the things we here at GISi came up with when implementing the code libraries that we use for our projects. There is also a sample project that you can download that demonstrates some of these ideas.
Before getting started, there are a few things to think about. First and foremost is what your library (or libraries) will be used for. Here at GISi, we develop both web and desktop solutions so we created 3 separate libraries. One library is for web development, one is for desktop (Windows) development, and the other is a common library that can be used for both. This makes sense for two reasons. First, web development and desktop development are very different from each other so it really makes sense from a logical standpoint to separate the two. The second is a technical reason. The web classes will most likely reference the ESRI web assemblies and the desktop classes will most likely reference the ESRI desktop assemblies. If we didn’t separate the two, then our library would require both ArcGIS Server and ArcGIS Desktop to be installed on the client machines. This is certainly not feasible so we really had no choice but to create two libraries. We then created a third common library that doesn’t reference any ESRI assemblies and contains classes that are compatible in both environments.
The first step is creating the code project. Open Visual Studio and create a new project, choosing Class Library as the project type. Choose the name of this project carefully as it will be with you for a long time and changing the name after you’ve deployed it a few times could be troublesome. After you’ve created the project, it’s time to start adding your classes.
We use namespaces to organize the classes in our libraries. This is how the .NET Framework is structured so we thought it would be good for consistency to do the same. It is a good idea from a technical standpoint because it allows us to create globally unique types which are important when it comes to deploying the library. It seemed only natural for our root namespace to be GISi. You can set the root namespace for each of your code libraries on the Application tab of the Project Properties page.
It is common practice to organize the class files in your project by using folders that mimic the namespaces defined by your class model. Since we created 3 libraries, we created a namespace for each library. We created GISi.Web, GISi.Windows, and GISi.Common. This way we can tell which code library our classes belong to without having to look them up. Each of our code libraries contains an appropriate root folder.
You may decide that you need to further organize your classes within your code library. For our Windows library we needed several levels of organization to keep things from feeling cluttered. For example, all classes dealing with user interfaces go into GISi.Windows.UI and all classes dealing with ArcObjects go into GISi.Windows.ArcObjects. Since we have many classes dealing with ArcObjects we further organize them according the to ArcObjects library they primarily use. So, our code library contains classes in GISi.Windows.ArcObjects.Carto, GISi.Windows.ArcObjects.Display, and several others. You are certainly not required to do it the same way but I just wanted to mention it so that you’d be aware of it and could use this information when planning your own libraries.
So let’s take a look at the sample project and see some examples of what I’ve just been talking about. If you look at the Application tab in the Project Properties you’ll see that the Root Namespace has been set to CodeLibrary. This will be the root for all of the classes in the library. You’ll also see that there have been several folders added to the solution. These folders mimic the namespaces used by the classes they contain. For example, if you look at the code module for the TabProcessorDialog you will see the namespace has been declared as Windows.UI and if you look at the MapHelper class you will see its namespace has been declared as Windows.ArcObjects.Carto. This is very important and is something you will need to do for all of the classes that you add to your library if you want your classes to be organized into namespaces. Note that the namespaces defined in the classes do not include the CodeLibrary root. This is because the root namespace you defined at the project level will be applied to all of the classes when the project is compiled.
I think it’s also important to mention that all of the classes contained within a namespace do not have to be in the same code project or solution. Each of our code libraries has its own code project contained within its own solution yet all of them use GISi as their root namespace. As long as you define the namespace in your class code it does not matter where that class is located.
The sample project is pretty simple but should be enough to get you started. The classes it contains are simplified versions of the same classes that we use in our own projects. In future articles I’ll go over how we use these code libraries in our projects and how we handle deploying them. Future sample projects will also contain this code library and I’ll probably be adding a class or two as we go along.