Wednesday, July 02, 2008
Posted on Wednesday, July 02, 2008 12:00:37 PM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: .NET | Fundamentals | SQL Server | Virtual Earth

A reader recently asked me to expand upon the "Keep it Simple" advice in the fundamentals section of my web site. Just like my advice, I had kept this section pretty lean...

Keep it simple

Anybody can build complex software. Creating simple software that can accomplish the same task is much more difficult. In the end though, the simpler it is, the easier it is to test, which makes it easier to maintain, and easier to extend.

To illustrate the idea, I'll talk about a project that I'm working on right now. Basically I'm helping / mentoring a team through a short term project to build a data viewer application based on Virtual Earth, Dojo, ArcGIS Server (9.2) and ASP.NET.

One of the user stories in this project is:

As an administrator I want the Data Viewer to be database agnostic so that I can easily configure it to pull point data from SQL Server, Oracle or file based data sources.

Now, this is a great idea, and certainly possible. In fact it ends up being very interesting to design (plug-ins, configuration sections and Inversion of Control oh my!).

Simple works...

In looking at the project (it's very short term) and the team (new to web development) and the current problem they are trying to solve (display data from SQL Server), my recommendation to the team is that we "keep it simple" for now, and just address the SQL Server data source.

While we could define a set of interfaces, build out a whole configuration model, and create the actual data access objects for these various data sources, in the context of this project it's extraneous. To be "successful", we need to display the current data in Virtual Earth. With tight time frames and limited resources, I believe the tradeoff between building for an unknown complex future need, and applying time and effort to the core objective, is a good one. The team will be able to get the database access tier of the system completed in a short time, and it will be very simple to understand - parameters are passed to a class, which calls a stored procedure, which returns the point data. Simple, clean, and working.

But what about the "can accomplish the same task" bit? Good question - I'd suggest that in this situation, with the current data is in SQL Server, you are doing the same task - just using a simpler design to achieve the goal.

Add Complexity when it is Needed

If / when a need arises to add data from Oracle, it will be a very simple task to create another class which mimics the SQL Server class, with the only difference being that it uses the Oracle data connection classes. Should this Data Viewer become a huge hit, and is used so extensively that it must become configurable by non-developers, it could then be refactored to add in the additional complexity required to support configuration sections and a plug-in data provider model. But for now, the much simpler solution works just fine.

So - to summarize: Make choices which trend towards keeping the code as simple as possible. Don't add extra features or design elements to handle unknown or fuzzy future requirements. Add complexity only when it's really needed. While it's fun to monkey with internal design optimizations etc, keep your eyes on the prize: software that works for the user. And keep in mind who will be maintaining the software over the long haul - while you may be a whiz at generics (for example) keep in mind that for many people they tend to make understanding the code more difficult.

That's pretty much my take on this, but I'd love to hear your thoughts on keeping software "simple". How do you decide when to add complexity? How do you define complexity?

Other thoughts on Simplicity:

Joel On Software: Simplicity

The Fourth Law of Software Design: Complexity vs. Ease of Maintenance

Various Quotes on Simplicity in Software Design

Wednesday, June 04, 2008
Posted on Wednesday, June 04, 2008 7:28:43 AM (Mountain Daylight Time, UTC-06:00)  Comments [4] | 
Categories: .NET | Devt Tools | Fundamentals | Unit Testing

This is the third and final part of a three part series summarizing the results of the 2008 Geospatial Developer Survey. For further information, be sure to check out read part one and part two

 

Use of Source Control Systems

This is where we start to see some divergence from the larger developer community.

 scc

Source control is as much a part of most developers lives as the language they use. It should be automatic and used by default. Subversion is good, and free. It's not trivial to setup, but with free subversion hosting services like Assembla.com, there is virtually no reason not use it. (btw - although I have an "Assembla" badge in my sidebar, I am not paid to endorse them - their service is solid and so I promote it).

Automated Build Tools

With more than half of the respondents not doing automated builds, we are seeing more of the separation from main-stream development.

autobuild-tools

All the choices on this question were .NET, but I also compiled the "Other - Please specify" results into a chart.

 autobuild-other

Unit Testing

There were 3 questions on unit testing, mainly because I see this as a key element raising the quality of GIS software projects. Unit testing is as much a philosophy about how you develop software as it is the actual writing of tests. Committing to doing unit testing really says you care about quality, and that you realize that manual testing, while valuable, is never as consistent as automated tests. So, with that we start with a look at what percent of projects are using unit testing.

Using_Unit-Testing

I don't know how this stacks up to other industries, but I'd say there is room for some growth here. Everyone talks about GIS getting on the "service bus", but we need to make sure that when we get on the bus, our code does not fail!

The next question basically asked why you were not doing more unit testing.

why-not-unit-testing

This is actually pretty good. I'd have to question the 14% who don't think it's valuable, but I'll chock that up to them not knowing what's really involved.

I've heard the "not-enough time" thing before, but the problem is that you will have bugs. And someone will find them. Better the developer finding them sooner than a client finding them later. Also, in terms of time, on big projects, I think you actually save time.Having automated tests, helps you prevent regression. Think about all the stuff that breaks between a big ArcGIS releases - that's regression, and that's what good automated tests can catch.  

Difficulty. This is true. Writing good unit tests is hard. Using good design patterns help, and good tools can ease the pain, but even still it's not easy. Writing unit tests for ArcObjects code is very difficult, but not impossible. In these cases, I focus the tests on the most critical parts of a system - basically putting the effort where it will payoff the most. For these areas, I shoot for 100% code coverage - if they are the most complex, I want to make sure that my tests cover all possibilities. Again, difficult, but if you are writing a complex spatial rule engine, that works with relationships between multiple layers, business workflows, and user permissions, there is no realistic way to manually test it on any sort of a regular basis.

The next question was "If tests were easier to write, would you write more of them?"

unit-tesing-easier

So, a resounding YES on that. This is great, because as a community we can actually make this happen. 

A couple years back I threw some code out there under the umbrella of "ArcUnit" - the files referenced in those posts are now gone, but it was some demo code that showed how to unit test geometry operations, by serializing geometries and storing them in the unit test assembly. The code is now on Assembla in the ArcDeveloper project, under TestingUtilities. Seeing as there is interest in this, I'll likely write some more articles on this.

Unit Testing Frameworks

Ok - the Java people really ripped on this question. After adding an "Other", I did tabulate the results for all that as well.

unit-testing-frameworks

This gets somewhat interesting - 60% of people said they are not using any tools, but back in the "What percent of your projects use unit testing" only 38% said "None". I guess some "homegrown" unit testing could explain a few percent, but... anyhow. Interesting that MBUnit and MSTest are so low. MSTest is baked into Visual Studio 2008 (Professional and above), and MBUnit is both free and awesome.

As for the "other", here's how that stacked up.other-ut-frwk

Apparently I could have saved myself a heap of greif if I'd just added jUnit to the list!

The final Unit Testing question went out to the edge - "What do you think of Test Driven Development"

tdd

So at least one zealot in the crowd aims pretty high! For the "No opinion" crowd, TDD is the practice of writing your unit test before the implementation. The intent of this is to essentially define the desired behavior in the test, then make the software behave in that way. No doubt this is difficult, and requires you to be a total unit testing & pattern guru. I *think* this is possible, even on complex projects like GIS, but you'd need to be working with a test friendly GIS framework (as in don't come asking me to build you an ArcGIS Server .NET ADF site using TDD!)

 

Code Refactoring

As you write code, there are times when you need to change it's structure - usually to conform to a pattern, to facilitate extensibility, or just because your function got long and messy (i.e. you're making maintenance easier!). This is called refactoring. The first question was related to how often you refactor your code.

refactoring

The second question related to the use of .NET Refactoring tools. I appologize again to the non-.NET people, but I don't know of any Java Refactoring tools.

net-refactoring

What's interesting here is that the "Not Refactoring" people are not even using the tools in Visual Studio. When we were doing a lot of desktop development, we used RefactorPro - mainly because they had good Visual Basic.NET support. Now that we're using C# and doing 99% web development, we are finding that the IDE tools / manual refactoring is sufficient.

Code Documentation Generation

This was a quick question on the use of automatic code documentation generators. They are pretty common in the larger developer community, and relatively easy to bring into the mix, and spit out some good API documentation. Worth the effort in my opinion.

doc-tools

 

Comments

Fifty-Two respondents left comments at the end of the survey. Most were constructive, and others... well... lets look:

WTF, no C++ on the list of languages? What language do you think the bulk of geospatial software (from GDAL to ArcGIS) is written in? C# is just a evil marketing ploy from MS to try to deflate Java's market; nobody is expected to actually _use_ C#.

Reply: Not having C++ was an oversight. As for your issues with C#, can't help you there.

Summary:

Overall, this was an interesting experience. Clearly I could do a much better job on the questions, and have a much wider range of options on the answers. I think it does show that geospatial developers are adopting main stream techniques and tools, just at a somewhat slower pace. Thoughts?

Download the results (Excel 2007 format)

Thursday, May 29, 2008
Posted on Thursday, May 29, 2008 4:42:30 PM (Mountain Daylight Time, UTC-06:00)  Comments [1] | 
Categories: Fundamentals | General | Software

In this go round, we'll look at the questions related to Design Patterns...

Design Patterns

The question was "When you hear the term 'Design Patterns' what comes to mind?".

 GOF-Patterns

A majority of people did get that GOF = Gang of Four = Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides the authors of the book "Design Patterns: Elements of Reusable Object-Oriented Software", which describes recurring solutions to common problems in software design. Thick and meaty, it's highly regarded and worth reading if you have the time and inclination. Martin Fowler's site also has heaps of good info, and you're not chopping down trees to read it. However you slice it, using patters will make you a better developer, so dig in.

Pattern Adoption

I guess this one has a call to action for someone to setup a community site to document and evolve some geospatial patterns.

pattern-adoption

If people are interested, I can stand up a wiki at ArcDeveloper.net, but someone else will need to push this forward as I've got a full plate.

Model View Pattern Use

"Rate your use of Model View * Patterns" was the question.

 MVC-Usage

For those not familiar with MV* - this refers to a whole family of patterns, related to the Model-View-Controller pattern (Model View Presenter, Supervising Controller, Passive View), and the main intent of these is to separate business logic, user interface and data communications. Use of these patterns are helpful/ critical in enabling robust unit testing. I'll be writing more about patterns and unit testing in the coming months, but Martin Fowler has a (burly) overview of these patterns. You can also check out the ASP.NET MVC stuff to get the Microsoft take on this, or check out MonoRail, which is part of the Castle Project. And for a change of pace, you could check out Ruby on Rails which is rooted in this pattern.

Inversion of Control & Dependency Injection

Ok, this is really maxing out the pattern / architecture geek factor, but it's worth asking simply because this is another one of those patterns which enable unit testing.

IOC

So, with nearly 75% not knowing what this is... succinctly put, Inversion of Control and Dependency Injection patterns allow you to decouple classes from each other. This allows you to test things independently, which is critical if you want to have good test coverage. I had a series of posts partially written about this while at Sanborn, but I did not get them all polished off before leaving, and since I don't have access to the source code anymore, I'll need to look for opportunities to show some of this. For what it's worth, the ArcDeveloper.net projects both use the Castle Windsor IOC container.

Ok, I'll leave it here for now. Next time I'll finish it up with a look at Build Processes, Unit Testing, Refactoring, API Documentation and some choice comments.

Tuesday, May 27, 2008
Posted on Tuesday, May 27, 2008 10:00:58 AM (Mountain Daylight Time, UTC-06:00)  Comments [1] | 
Categories: Fundamentals | General

Newly refreshed after a week of vacation, I thought I'd start things up with the results of the informal "2008 Geospatial Developer Survey". I'll start by thanking the 320 people who took the time to complete it. Admittedly it was a little rough in spots - turns out that writing good survey questions is tougher than you'd think!

Since there were 30 questions in the survey, I'm breaking this into a few posts. As promised, I will post the results as an excel file with the last post.

Who are you?

I thought I should start off the survey with an easy one - what's your role.

who-are-you

The split across titles was somewhat interesting - almost even between "Analysts who write code", and those who consider themselves "GIS Software Developers", with "Software Engineer" trailing slightly. I see this as a progression from "getting things done" coding towards more "built to last" coding.

Primary Development Language

There were a lot of "other" responses on this one, mainly along the lines of "Mix of languages - VB.NET, VBScript, JavaScript, Python, and others".

The idea of this question was to get a feel for what you most commonly work with. I went through the "others" and tabulated them into the mix. Since there were so many variations in the "other" categories, I collapsed them into one group for the pie chart. Perhaps not surprisingly, .NET was the prominent platform with a 61% share.

 dev-lang 

Here is how the "other" broke out by count of times they were mentioned. I'm pretty surprised that there are still people using VB6 and VBA. While these tools get the job done, the lifecycle for VB6 apps must be coming to a close.

 

dev-other

Who do you Develop For?

Almost a 50-50 split on internal vs external clients. Some people were asking why I asked this. I was interested in seeing any relationships between engineering practices and the client base - would there be more advanced software techniques used for the external clients vs internal? With a 50-50 split, it's not entirely obvious, but I've since downloaded the data into a database and I'll try to split out the data a little more to see how this breaks things down.

clients

Use of ESRI GIS Products

This is another question that I got some flak for - but I think it's relevant in that I'm interested in knowing what my readers are using. 40% of the respondents are only using ESRI. Actually I had thought this would be higher - the idea that 60% of respondents are using some mix of non-ESRI GIS tools is very interesting. I'm sure a lot of that is Autodesk stuff, but there's got to be some MapServer, GeoServer, PostGIS and other open source stuff making an appearance in here. Next year I'll change this one up so we can see the mix of packages being used.

esri-mix

Coding Standards

It's nice to see that most respondents have some type of coding standards.

code-stds

Mostly informal, but that's a start, and if you have a solid team, it's likely all you need. Those folks with out any type of coding standards should really consider setting up something - most languages have some sort of recommendations or conventions. The goal of coding standards is simply to ensure that everyone on your team is writing code in such a way that anyone else on the team can easily tell what's going on. If nothing else - simply using clear names for your variables is a good starting point.

 

Development Life-Cycles

This was interesting, and will require more analysis, but here's how I look at this. 50% of respondents classified themselves as Developers or Software engineers, and just about 50% also fell into Agile or Waterfall. 30% classified themselves as GIS Analysts who Code, and we see about 35% of cowboy coders.

dev-proc

I'll cut things off here for now - next time I'm going to cover some of the more technical questions - design patterns, unit testing etc. I also need to get the data out of survey monkey in a database format so I can use SQL to tease more information out of the results.

Wednesday, May 07, 2008
Posted on Wednesday, May 07, 2008 7:36:28 AM (Mountain Daylight Time, UTC-06:00)  Comments [1] | 
Categories: Fundamentals | Unit Testing

...from Jeff Atwood author of the (wildly popular) Coding Horror blog. Hopefully you all subscribe to his blog, but for those who may not, it's full of goodness, and you should check it out on a regular basis.

As for MVC - the results of the Geospatial Developer Survey show only about 50% of respondents are using patterns, and about 46% were not using any sort of Model View * patterns. This article is a great entry point to a pattern that can be applied to a very wide range of scenarios (including easing the creation of unit tests!)

Check it out at CodingHorror.com

Thursday, February 07, 2008
Posted on Thursday, February 07, 2008 10:16:30 PM (Mountain Standard Time, UTC-07:00)  Comments [1] | 
Categories: .NET | Fundamentals | Utilities

If you are a .NET developer I recommend checking out DocProject. It's an open source front end for the SandCastle documentation engine. Sandcastle picks up where NDoc left off, and is a Microsoft open source project that provides services for creating MSDN style HTML and compiled help. Unfortunately it's a bit of a bear to work with (lots of Xml configuration files, batch files etc).

This is where DocProject comes in. The basic process is to add a "DocProject" or "DocSite" to your solution, and then add references to all the other sites/assemblies in the solution into the DocProject. Then during a build, DocProject actually runs Sandcastle to create the doc.

I've only just played with it a little, and it's pretty easy to get setup and running, but the actual compilation of the help was pretty slow. It was running for >15  minutes on my Core 2 Duo notebook! After digging around a little, it seemed the issue was that I have some ArcGIS Server WebService proxies in one of the assemblies, and it was cranking out all the help doc for that - which is substantially larger than the actual code I was trying to document. Once done, the output is pretty good.

docproject-example

Combine this with GhostDoc, and there is no excuse for not having good developer API documentation for whatever you write.

Check it out at www.codeplex.com/docproject

Thursday, August 09, 2007
Posted on Thursday, August 09, 2007 10:03:48 PM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: Blogging | Fundamentals | Productivity

Back at the 2007 ESRI Developer Summit, I did a presentation on "Being Agile". At that time, I mentioned that we simply followed general agile principles, but did not particularly follow any doctrine. For a variety of reasons we have had to become more formal in our quest for agility, and have adopted Scrum.

For those not familliar with Scrum, it's a very light-weight project managment methodology that's based on agile principles. Work items are managed in a set of backlogs and are done in a series of 2 or 4 week sprints at the end of which they produce a "potentially shippable product increment. Here's a good diagram that shows it all. Every day the team meets for 10-15 minutes to repost status - this is the "scrum".

What's really nice is that there are alot of success stories that one can reference with "selling" Scrum within an organization and to clients. Not to mention a slew of great books. Including what I'd recommend as a really good intro to the topic  Agile Project Management with Scrum (Microsoft Professional) by Ken Schwaber.

Thus far, I have to say that it's the best way to develop software that I've ever seen. It's easy - nothing in it seems to be "extra" - to put it another way - no TPS reports. Things proceed smoothly, the team is all bought in, and we are cranking out the code. Last week my co-worker Chris Spagnuolo and I attended a "Certified Scrum Master" training course in Denver. Led by Mike Cohn (blog), this was a great two day class that covered everything you need to know to run a scrum team - aka being a "scrum master".

We liked this initial class so much that we are heading out to Orlando in September for Mike's course on Agile Estimating (here's Mike's book on the same topic and YouTube videos - part 1 and part 2 - of a presentation he gave @ Google in March 2007). We are really excited about this because it will be driven by the detailed historical data from our team's sprints and it should be more much more accurate than other "gut-based" estimating systems.

If this sort of thing strikes your fancy, Chris Spagnuolo (our "scrum master") has started a GeoScrum blog where he will be covering the on-going journey of managing a cutting edge geospatial development group with Scrum. We are constantly adapting the process and our tools and Chris will share tips on what works and what doesn't, as well as general project managment zen.

Monday, June 04, 2007
Posted on Monday, June 04, 2007 10:12:28 PM (Mountain Daylight Time, UTC-06:00)  Comments [2] | 
Categories: .NET | Fundamentals | Software

During the ramp up for my current enterprise GIS development project I created a few simple VB.NET sample projects which illustrate some architectural practices I want the team to use.

The first one I'm going to share covers the creation of a plugin framework, and the use of the Supervising Controller pattern to expose user interface logic to unit tests. In order to keep the focus on the pattern, and not on the complexities of what the code is doing, this sample does not use any ArcObjects. It's just a very simple example of how you could create "property page" type functionality that can be extended via plugins.

What is a Plugin-Framework and why would I want one?

Using a plugin framework is a way to design an application so that other functionality can be added at a later time without needing to modify the original source code. Putting this in ArcGIS terms, this is similar to adding commands into ArcMap via it's plugin framework.

If you are building large complex applications, supporting a plugin model essentially enables the system to be extended in a very managed way. Thinking back to ArcGIS - by simply implementing ICommand, you can add alot of functionality into their application, and ESRI does not have to give you the source code, nor do you need to manage a very complex C++ build process.

Supervising Controller Pattern

Just a quick warning - we're diving into formal object oriented design patterns here. Previously known as Model View Presenter, this is a common object oriented design pattern.  Martin Fowler (who invented/named it) has officially retired the "Model View Presenter" pattern, and created two new ones - Supervising Controller and Passive View. You can read up on the details of these patterns by following those links, but the quick and dirty explanation is that they focus on extracting logic from an User Interface (windows or web form) into "controller" classes. (A little pattern nugget to impress your friends with: Autonomous View is the official name for  the "put all the code in the form" pattern) These controllers handle most of the User Interface logic - and since they are regular old classes - they are much easier to write unit tests for.

One of the prime reasons to use Supervising Controller is for testability. Assuming the view is hard to test, by moving any complex logic into the controller, we put the logic in a place that's easier to test. - Martin Fowler

At first blush this seems like more work - and it actually is more coding. BUT - if you write tests for the controllers (not covered in the sample), it will make your code more robust and manageable over the long term.

The Plugin Framework

The plugin part is pretty straight forward. We define an interface for the plugin, and implement it in the classes which we are going to plug-into the application.

This is exactly the same as implemeting ICommand. The difference is that instead of registering a COM class with the windows registry, we add the plugin by editing the host application's config file...

<propertypageplugins>

    <propertypageplugin name="Editor"  type="Research.EditorPluginView, Research.ExamplePlugin"  />

    <propertypageplugin name="Some Different Plugin"  type="Research.EditorPluginView, Research.ExamplePlugin"  />

  </propertypageplugins>

In order to load the plugins into the application we create a configuration section handler - which I've posted about in the past. For more details, I'd suggest checking out this MSDN article by Roy Osherove. I'd also suggest looking at the code, since there are some other interesting bits in there that I'm skipping over to keep this somewhat short.

 
The Host Application

The plugins must plug-into something - thus the host application. This is simply a windows form that will list the registered plugins, and then show the selected plugin interface on the right side of the form. The image below shows it running.


The Plugins & Supervising Controller

The plugins are located in the "ExamplePlugin" assembly. In fact there is only one plugin - "EditorPlugin " - I just register it twice. The pluing itself is a super simple text editor. As I metioned earlier, the plugins themselves implement the Supervising Controller pattern. Typically this is used with "forms", but in order to be pluggable, we are working with user controls. And to be fun, I'm using using inherited user controls.

Inheriting the user control forces a common look and feel - granted in this case, it's very simple (just the group box), but in our real app, it's got a lot more going on.

To keep things clear, I have setup a standard naming convention - the UI (user control in this case) is <somename>View, and the Controller is <somename>Controller. The interface that forms the contract between the two is I<somename>View. Looking at the class model above, we can also see that the View implements IPropertyPluginView - which means that it's the thing that actually plugs into the application.

So in this case we have:

  • EditorPluginView
  • EditorPluginController
  • IEditorPluginView

Since the Controller must manage the UI, one way to setup a contract between the two is using an Interface. The interface is implemented by the View, and consumed by the Controller. The interface simply specifies the methods that the Controller can call on the View (UpdateText and GetText in this case) and the events that the View raises and that the Controller can handle (ContentChanged and Store).


Run Time
When the form is initialized (IPropertyPluginView.Initialize()), it creates it's controller class and passes in a reference to itself as an IEditorPlugin. The Controller then sinks the Events on the interface, reads the file from disk (if it exists) and updates the text on the form. When the user edits the text the IEditorPluginView.ContentChanged event is raised in the form, and the Controller is notified. When the user clicks the store button, the IEditorPluginView.Store event is raised and the Controller gets the content via IEditorPluginView.GetText, and it stores it away.

Even this simple example could be extended, but this is enough to show how it all works.

Conclusion

While this was a whirlwind of terms and concepts, I encourage you to download the code, and play with it. It's actually quite easy to implement once you get the hang of it, and it can help make your applications much more testable. I find it much easier to look at real code than to just read the generic explanations of patterns, so I hope this helps if you are thinking about implemeting a plugin framework or Supervising Controller in .NET

 
Download the code


Other Reading:

The Polymorphic Podcast has a series of great screen casts and audio clips that go over the details of the Model View patterns. I highly recommend these specifically, and the podcast in general.

MSDN Article: Creating a Plugin Framework. This is from 2003, and deals with ASP.NET but the concepts have not changed.

Friday, September 01, 2006
Posted on Friday, September 01, 2006 11:52:20 AM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: .NET | Devt Tools | Fundamentals | Software
I just saw Rob Howard's posting - Build it quickly, use it as soon as possible and make it simple - about the evolution of Telligent's development philosophy. For those who are not famlilliar with Telligent - they make Community Server, which is used on a lot of sites, including ArcDeveloper.net

I like is take on the agile mantra of "Release Early and Release Often"  - rather than release, if possible start using the software prior to release. This will help you identify usability and stability issues early. Then get it out the door as fast as possible.

Rob makes a couple really good points:
One of the biggest lessons we've learned is one we didn't really anticipate: a shift from caring less about the underlying technology to how our software solves the user's problem...

... our philosophy is: (1) build it as quickly as we can (2) start using it as soon as possible (3) make it simple.

For consultants or small software companies, this is right on the mark and critical to success - focus on making the users life easier, and create the simplest solution that can work. If it's successful, evolve it from there. If not, then you don't have too much investment.


It's also worth noting that (from what I can tell anyhow) this is more or less the approach of Google these days.

Saturday, March 11, 2006
Posted on Saturday, March 11, 2006 6:57:48 PM (Mountain Standard Time, UTC-07:00)  Comments [0] | 
Categories: .NET | Fundamentals | Devt Tools
Developer Fundamentals: Refactoring - Keeping your code simple
Unit Testing and Refactoring are tightly inter-twinded, as unit tests can be used to ensure that your newly refactored code still runs, and once your code is refactored, it's easier to write tests for. But I'm getting ahead of myself - let's start at the beginning...

What is Refactoring? (from Wikipedia...)
Refactoring is the process of rewriting a computer program or other material to improve its structure or readability, while explicitly keeping its meaning or behavior.
Refactoring is simply re-organizing your code to make each function as simple as possible, while still retaining the same overall functionality of the system. Many times this means simply breaking up large complex functions into smaller simpler functions. Thinking in objects, this tends to mean one of two things: breaking a large multi-purpose object down into simpler single-purpose objects, or creating multiple private (internal) functions which are used by a public method. The image below shows this graphically.
 


There are multiple benefits of this: code that is simple, is easy to read, which means its easy to maintain. Keeping classes simple also increases the probability of re-use, and makes it easier to test. And if you're going to bother re-using code, you want to make sure it's well tested, which brings us back to Unit Testing. Ah, the circle of life!

It's very common to see large complex functions in ArcObjects code. I believe that this is due in part to how the developer thinks about the problem - as a linear series of steps. Maybe this is a throwback to AML? When writing code, they just follow the linear steps as one big function. While this can work, the down side is that it's very difficult to test the parts of the function, and it's very very difficult to re-use portions of the code without copy-pasting (a very common, yet bad practice because you now have two places where you need to maintain code that is similar or the same).

Thus, I highly suggest adding refactoring to your coding practice. It can be done manually, but all the copy pasting & renaming can be somewhat time consuming. Luckily, there are tools to help out. If you are using Visual Studio 2005, there are built in refactoring tools for both VB and C#. For Visual Studio 2003, there are a variety of third party tools which can help simplify the job. For detailed information on refactoring you can check out Refactoring.com.

Happy Coding!
Wednesday, February 15, 2006
Posted on Wednesday, February 15, 2006 7:01:12 PM (Mountain Standard Time, UTC-07:00)  Comments [0] | 
Categories: .NET | Devt Tools | Fundamentals
Time for another dose of developer zen. This time I'll try to take a quick look at OOP (object oriented programming) and some issues which can occur if you are transitioning from procedural languages (AML) or pseudo OOP languages (VB6 & Avenue). To start with, I think it's worth noting that just because you are using an object oriented language (Java,C#, VB.NET etc.) does not mean you are writing / designing your code in an object oriented manner. I think this may be an afront to some people, but it's just the truth. You can write procedural code in any OOP language. And it can work. But there's just so many reasons not to.
In this article, I am simply listing 3 things you should try to avoid. For more detail on Object  oriented programming, hit Google. Of course, you can ignore these warnings, but if you have to try to maintain or grow your code, you will run into problems.

Design As You Code
This is also known as "no design", or hacking. Honestly, if you ever take anything away from this blog, I hope it is this: Always design before you code. The level to which you take this typically depends on what you are doing. If it's a quick one-off VBA script to rename a set of files, then just jotting down a bullet list of "requirements" is enough. If you are trying to create complex workflow managment system for a diverse set of users, you may have several 1000 pages of requirements. In either case, having a design is critical, if for no other reason that it can tell you when you are done (i.e. all requirements are met). At some point I'll post about our design process, which tries to do "enough" design without going crazy with UML, but that's a little past the fundamentals.

GIS Data Objects "Special"
Many times I'll see code where the developer has used objects for all kinds of things, but when it comes to the actual GIS datasets (feature classes etc), they are alway treated differently. It's important to understand that in most cases, you can use these types just like any other types (string, int, arraylist etc). The reason we model things as objects is that there is some inherent relationship between them. And if one of the items that particpates in the relationship is a featureclass, then add it as a property of the class. Granted, you're not going to be able to serialize the class out to an XML file and expect the featureclass to go along, but you can work around those cases. The point here is to not be shy with these things. It's also a departure from typical GIS thinking, which can be hard for people just beginning to make the shift.

Side Effects (or Why Globals are Evil)

Unlike special effects in movies, these are bad things to encounter. A "Side Effect" occurs when something effects the internal implementation, in a way which is not expected. The end result is code which may "look" correct, but acts incorrectly in certain situations. The code below show a pretty contrived example. It has a property "ShoeSize" and a method "Add". Add takes two integers, and returns an integer. The developer would expect that add would simply return the sum of the two numbers. However, if ShoeSize is set, it returns the sum of the two numbers plus shoesize.

    1 Public Class SuperClass

    2 

    3     Private _shoeSize As Integer = 0

    4     Public Property ShoeSize() As Integer

    5         Get

    6             Return _shoeSize

    7         End Get

    8         Set(ByVal Value As Integer)

    9             _shoeSize = Value

   10         End Set

   11     End Property

   12 

   13     Public Function Add(ByVal firstNumber As Integer, ByVal secondNumber As Integer) As Integer

   14         Return firstNumber + secondNumber + _shoeSize

   15     End Function

   16 

   17 End Class



This is a very extreme example, but I think it shows the general idea. The method Add does not indicate that anything else is involved, yet in some cases (ShoeSize != 0) it will return an unexpected result, which will be very difficult to track down. A very common way to end up with a mess of side effects is through the use of "global" variables. In this case, a the variable gets set in one place, and then used in some other location which is not apparent to the developer. These sort of problems are really tough to track down. I've seen projects where it cheaper and faster to delete the application and start again rather than trying to sort out what was going on. Good Luck!

Posted on Wednesday, February 15, 2006 6:58:54 PM (Mountain Standard Time, UTC-07:00)  Comments [0] | 
Categories: Devt Tools | Fundamentals
While reading Jackie Goldstein's blog on .NET and "stuff", I saw these two free eBooks which would be good reading for the ArcObjects developer community.

Descriptions are from the APress Site...

COM and .NET Interoperability
COM and .NET Interoperability provides a complete overview of the process of building .NET applications that interact (interoperate) with existing COM code. Before digging into that critical topic, author Andrew Troelsen offers a concise overview of the COM architecture and provides examples using various COM frameworks (C++, ATL, and VB 6.0) as well as the core .NET managed languages (C# and VB .NET). After covering the preliminaries, the book explores numerous issues that arise in interoperability, including interacting with the Win32 API, dynamically generating source code via System.CodeDOM, creating serviced (COM+) components using managed code, manually editing (and recompiling) .NET metadata, and the process of constructing custom COM/.NET conversion utilities. Both intermediate and advanced developers will welcome the practical information they need to quickly work with COM and COM+ in .NET applications, and learn how to create .NET components that are COM compatible.
It's 792 pages, which is pretty weighty, but if you want to get some indepth coverage of this topic, it sounds like a good starting place. I'm not a huge fan of "reading" a PDF "cover-to-cover", but you can't beat them for searchability.
Direct Download Link (6.36 MB PDF File)

Programming VB .NET: A Guide For Experienced Programmers

In Programming VB .NET: A Guide for Experienced Programmers, authors Gary Cornell and Jonathan Morrison carefully explain the exciting new features of Visual Basic .NET. Since VB .NET is, for all practical purposes, a whole new language even for the most experienced Visual Basic programmers, developers need to think differently about many familiar topics. Cornell and Morrison are there to help you with careful discussions of each topic. All experienced programmers wishing to take advantage of the amazing new powers of VB .NET will benefit from this book’s careful treatment of fundamental topics, including inheritance, interfaces, and exception handling, as well as all the powerful new features, such as stream-based I/O and true multithreading. Cornell and Morrison write from the point of view of the experienced programmer, with constant references to the changes from earlier versions of VB. Developers learn how to use VB .NET for database programming through ADO.NET and web programming through ASP.NET. After reading Programming VB .NET: A Guide for Experienced Programmers, developers will have a firm grasp of the exciting new VB .NET language and its uses in creating powerful .NET applications.

This book would dovetail really nicely with the Fundementals series I've been posting. If you've got a background in programming, and are moving into VB.NET, this sounds like a good bet.
Direct Download Link (4.9 MB PDF File)

There are 6 other free books at the APress Site.

Thursday, February 09, 2006
Posted on Thursday, February 09, 2006 7:02:33 PM (Mountain Standard Time, UTC-07:00)  Comments [0] | 
Categories: .NET | Fundamentals
As we see the convergence of IT and GIS, many more traditional GIS users ("GIS Analysts") and other people are finding themselves faced with creating stable, maintainable GIS applications. To help out, I thought I'd start a series of postings about software development fundamentals. While this is not going to to replace "real" training, time spent reading books, and actual hands-on-the-keyboard coding, hopefully these posts will help people avoid common mistakes.

Posted on Thursday, February 09, 2006 7:01:59 PM (Mountain Standard Time, UTC-07:00)  Comments [0] | 
Categories: .NET | Fundamentals
It's very common that when you first transition to an OOP language that you still end up writing procedural code in "Big Ugly Functions". While it's common overall, I think it's especially prevalent in GIS, and at some level it flows from the fact that many times we are automating a series of tasks. When translating the series of tasks into code, the tendancy is to write this out in one big function. While this can work (many examples show this sort of thing), it does have some problems. I'm going to discuss two...

Maintenance:
How often have you seen or written a function that takes up 500 lines and does 10 or 20 operations in it? How often have you returned to this code a few months later only to be baffled as to what it's actually doing? How often have you been able to re-use one of these functions?

The point here is that (aside from not being object oriented), these big ugly functions are a maintenance nightmare. The rule of thumb I use is that a function should do 1 thing. One. Only one. That's it. This can be expanded up to the idea that a class should deal with one thing (or conversely it should not be a random collection of unrelated functionality). Why you ask? Quite simply code written like this is easier to maintain and easier to reuse (and easier to test - but that's another post). This is why there are so many classed in the ArcObjects framework. Each object deals with one thing (featureclass, cursor, graticule) via muliple properties & methods. It's also why you can re-use the ArcObjects to solve so many problems. It's also why we are seeing more coarse grained classed, which simplify common tasks, in the newer releases.

Error Handling
If the esoteric aspects of OOP and re-use are low on your priority list, this is likely something you need to address - dealing with errors. If you run a whole bunch of operations end to end, and an error gets thrown, do you know what caused it? Can your code take corrective action? Can it give the user a useful message? This little block of sample VB.NET code shows what I mean.

   20   Public Function RunModel(ByVal sourceDataFolder As String) As IRaster

   21         Try

   22             '-------------------------

   23             'lots of code in here

   23             'lots of code in here

   23             'lots of code in here

   23             'lots of code in here

   24             '-------------------------

   25             'If an error occurs, how do

   26             'you know what caused it?

   27             '-------------------------

   28         Catch ex As Exception

   29             'Do something

   30         End Try

   31     End Function



So, the better practice is to refactor (break up) this code into smaller, more discrete functions...

   33     Public Function RunModelRefactored(ByVal sourceDataFolder As String) As IRaster

   34         Try

   35             '-------------------------

   36             'Simple code here to just control

   37             'the program flow...

   38             '------------------------- 

   39             'This is junk code...

   40             Dim slopeRas, eleRas, coverRas As IRaster

   41             Dim maskRaster As IRaster = DoStep1(slopeRas, eleRas)

   42             Dim outRaster As IRaster = DoStep2(coverRas, maskRaster)

   43             Return outRaster

   44 

   45         Catch ex As Exception

   46             'Do something

   47         End Try

   48     End Function

   49 

   50 

   51     Public Function DoStep1(ByVal SlopeRaster As IRaster, ByVal ElevationRaster As IRaster) As IRaster

   52         Try

   53             '-------------------------

   54             'very simple code doing

   55             'just one thing

   56             '-------------------------

   57             'If an error occurs, you

   58             'know where, and likely what

   59             '-------------------------

   60         Catch ex As Exception

   61             'do something

   62         End Try

   63     End Function

   64 

   65     Public Function DoStep2(ByVal CoverRaster As IRaster, ByVal MaskRaster As IRaster) As IRaster

   66         Try

   67             '-------------------------

   68             'very simple code doing

   69             'just one thing

   70             '-------------------------

   71             'If an error occurs, you

   72             'know where, and likely what

   73             '-------------------------

   74         Catch ex As Exception

   75             'do something

   76         End Try

   77     End Function


We're still not OOPing, but at least this will be more maintainable, and exceptions will be much easier to track.

While I'm at it, if you are starting a new application using a language which does not have structured error handling, change! Really. Java has a great development environment (Eclipse) and right now you can get the Express versions of C# and VB.NET for FREE!! The advantages (structured error handling, unit testing, large developer community) should have you downloading them now. Really. Do it now!