Thursday, April 21, 2011

SoCal .NET Architecture Presentation

Just finished my presentation on designing enterprise applications for Windows Phone 7. Many thanks to Mike Vincent, David Wells, and everyone who attended. Here are the links to slides and source code of the sample application. Feel free to contact me if you need any help building the solution.

Sunday, March 13, 2011

Source Code Comments Revisited

I have to admit I don't get much traffic on this blog - usually a few hits per day, according to Feedjit. That's why I was pleasantly surprised when I saw a steady stream of comments earlier today. Some of them were submitted here on blogger.com, but most went to the discussion on reddit.com. Since I can't possibly reply to every single comment, here is a summary response.

First of all, I'd like to thank everyone who agreed with my view of automated unit tests as a perfectly good substitute of source code comments (of course, unit tests are much much more than a replacement for comments!). I also appreciate the folks who submitted constructive criticism and shared their personal rules of thumb for writing comments.


Some readers took offence on my use of terms like "cohesion", "coupling", and "cyclomatic complexity", calling them buzzwords. My friends, if these terms are just buzzwords to you, then you clearly are missing some important trends in our industry. If you are writing objects with hundreds of methods that pertain to dozens different responsibilities, or if your thousand-line functions have so many if-else statements it makes you dizzy, then no amount of source code comments will hide one simple fact: your code is bad and is in dire need of refactoring.

One often-repeated mistake was that I am advocating against ALL source code comments. This is simply not true, and if you read the blog post through the end, you will see a pretty funny example of a very legitimate comment one programmer left in his code.

Speaking of examples - I got a few posts saying they are "stupid", "straw-man", and not real. Well, I don't even know what to say... There are just two examples in my blog post, and both are taken verbatim from the StackOverflow discussion called "What is the best comment in source code you have ever discovered".


To all people who questioned my credibility, I am happy to say that I have been a professional programmer for over 16 years, used more programming languages than I care to remember, and was involved in the maintenance of large codebases. I do code reviews on a regular basis, and I always enjoyed respect of my colleagues. True, my current job title is no longer a "programmer", and I've been coding in C# exclusively for the last several years, but make no mistake - I am no "dabbler" when it comes to software development.

Tuesday, January 11, 2011

Don't Waste Your Time Commenting Source Code

I recently had an argument with a colleague about source code comments. He called it one of software development best practices and suggested that any programmer worth his salt writes extensive comments. You hear this pretty often from people who consider themselves "old school". Well, I have been writing code since early 90s, but I strongly believe that 90% of source code comments are a waste of time. Let's review the arguments...
Pro: Comments explain what the program does, so the person maintaining the code can understand it easily.
Well, it sounds good on the surface, but if you think about it, a well-designed program doesn't need comments to be maintainable. A well-designed program uses classes and design patterns; it has high cohesion, low coupling, and limited cyclomatic complexity. The names of classes and variables are carefully chosen to be self-explanatory. We know that programmers don't generally have unlimited time for development. If the choice is between a well-designed program without comments and a thoroughly commented but poorly architected one, I will choose the former any day of the week. Frankly, I would rather have developers spend time polishing their design skills than technical writing skills.
Contra: Automated unit tests explain what the program does just as well, and they never become obsolete.
The truth about source code comments, and any written documentation for that matter, is that it quickly becomes obsolete. Take a look at this real-life example I took from StackOverflow discussion:

/**
 * Always returns true.
 */
public boolean isAvailable() {
    return false;
}

There is no guarantee that the person changing the code will take time to update the comment. There is nothing your integration server can do to enforce this. On the other hand, consider this unit test:

var result = myobject.isAvailable();
Assert.IsTrue(result);
As soon as someone changes the method to return "false" instead of "true" and checks the code in, the unit test will break on next build, and pretty soon the developer will be looking into the issue.
Contra: What makes you think people can write clearly?
Let's face it, not every programmer can write well in English (that goes without saying for us immigrants, but I have seen comments written by native English speakers that were profoundly confusing). On the other hand, unit tests are written in programming languages, so developers can apply their core competencies. Natural language comments can be ambiguous, vague, sarcastic, or humorous. Some may be even fun to read (that StackOverflow discussion has some real gems!), but unit tests are much more practical - they leave no room for different interpretations.
Pro: Sometimes you just need to leave a note...
This is the only case that I would concede. Here is an example to illustrate this point:

// 
// Dear maintainer:
// 
// Once you are done trying to 'optimize' this routine,
// and have realized what a terrible mistake that was,
// please increment the following counter as a warning
// to the next guy:
// 
// total_hours_wasted_here = 39
// 

Friday, December 17, 2010

Mobile Enterprise Application. Step 3: Registering For Push Notifications

This is a third post in a series. Previous posts:
 - Step 1: General Architecture
 - Step 2: Authentication

I briefly defined Push Notification Service in the previous post. Here we will take a closer look at implementing notifications. PNS has cloud-based infrastructure maintained by Microsoft; phone application registers with it and assumes a unique endpoint address. That address is sent to the server portion of our system which uses it to forward messages to PNS infrastructure which, in turns, forwards it to the phone. There are three different types of alerts that can be sent:

  1. Tile notifications. If an application is pinned to the start screen, its image (a.k.a. tile) can change in response to tile notification. We can either change the entire image or just display a number on the default tile.
  2. Toast notifications. These are essentially short text messages that are briefly displayed on top of the phone screen. If user touches the message, associated application opens up.
  3. Raw notifications. If previous two are used to communicate with the phone OS, this one is targeted at the phone application itself. Therefore, message contents and system response will be application-specific.
Check User Preferences
According to Microsoft certification requirements, users should be able to opt out of push notifications. The most straightforward approach is to store user preferences in the application setting.
   1:      public class AppSettings
   2:      {
   3:          private readonly IsolatedStorageSettings _isolatedStore;
   4:   
   5:          public bool CanUsePNS
   6:          {
   7:              get
   8:              {
   9:                  return GetValueOrDefault<bool>(Constants.Settings.CanUsePNSKey, Constants.Settings.CanUsePNSDefault);
  10:              }
  11:              set
  12:              {
  13:                  AddOrUpdateValue(Constants.Settings.CanUsePNSKey, value);
  14:                  Save();
  15:              }
  16:          }
  17:   
  18:          public AppSettings()
  19:          {
  20:              _isolatedStore = IsolatedStorageSettings.ApplicationSettings;
  21:          }
  22:   
  23:          public bool AddOrUpdateValue(string key, Object value)
  24:          {
  25:          }
  26:   
  27:          public TValueType GetValueOrDefault<TValueType>(string key, TValueType defaultValue)
  28:          {
  29:          }
  30:   
  31:          public void Save()
  32:          {
  33:              _isolatedStore.Save();
  34:          }
  35:      }


Register Push Channel.
This needs to be done when application starts and after user confirmed he or she wants to use PNS.
   1:          public void RegisterPushChannel()
   2:          {
   3:              if(!(new AppSettings()).CanUsePNS) return;
   4:   
   5:              _httpChannel = HttpNotificationChannel.Find(Constants.ChannelName);
   6:   
   7:              if (null != _httpChannel)
   8:              {
   9:                  SubscribeToChannelEvents();
  10:                  SubscribeToService();
  11:                  SubscribeToNotifications();
  12:              }
  13:              else
  14:              {
  15:                  _httpChannel = new HttpNotificationChannel(Constants.ChannelName, Constants.Channels.Service);
  16:                  SubscribeToChannelEvents();
  17:                  _httpChannel.Open();
  18:              }
  19:          }


Method SubscribeToChannelEvents simply adds application handlers to process various events raised by the HttpNotificationChannel object.

   1:          private static void SubscribeToChannelEvents()
   2:          {
   3:              // Register to UriUpdated event - occurs when channel successfully opens
   4:              _httpChannel.ChannelUriUpdated += new System.EventHandler<NotificationChannelUriEventArgs>(HttpChannelChannelUriUpdated);
   5:   
   6:              // Subscribe to raw notifications
   7:              _httpChannel.HttpNotificationReceived += new System.EventHandler<HttpNotificationEventArgs>(HttpChannelHttpNotificationReceived);
   8:   
   9:              // General error handling for push channel
  10:              _httpChannel.ErrorOccurred += new System.EventHandler<NotificationChannelErrorEventArgs>(HttpChannelErrorOccurred);
  11:   
  12:              // Subscribe to toast notifications
  13:              _httpChannel.ShellToastNotificationReceived += new System.EventHandler<NotificationEventArgs>(HttpChannelShellToastNotificationReceived);
  14:          }

Method SubscribeToNotifications binds channel notifications to Windows shell:
   1:          private static void SubscribeToNotifications()
   2:          {
   3:              if (!_httpChannel.IsShellToastBound)
   4:              {
   5:                  _httpChannel.BindToShellToast();
   6:              }
   7:              if (!_httpChannel.IsShellTileBound)
   8:              {
   9:                  _httpChannel.BindToShellTile();
  10:              }
  11:          }

Associate User and Channel URI
Method SubscribeToService needs to send unique endpoint URI (which can be accessed via _httpChannel.ChannelUri property) to the server portion of the system, e.g., by calling a web service. The service will associate the URI with the ID of the currently logged in user. This is an important consideration: since different users may be using the mobile application (or the same person may have different user accounts), but channel URI will always be the same. If we do not properly associate URI with the current user, he or she will be receiving other person's notifications. By the same rationale, when user logs off from the application, a web service call needs to be made to disassociate her from push notifications URI.

Wednesday, November 17, 2010

Mobile Enterprise Application. Step 2: Authentication

This is a second post in the series. Previous post:
 - Step 1: General Architecture

Authentication - as in supplying proper user credentials - is an essential part of any enterprise application. Consumer apps and games usually allow unauthenticated users to execute them, but enterprise systems have higher security requirements. So, your login page is likely to be set in WMAppManifest.xml as default task:

    <Tasks>
      <DefaultTask Name ="_default"
            NavigationPage="/Views/LoginPage.xaml"/>
    <Tasks>

It's not difficult to put together a simple page with two text boxes and a button, then make a web service call to verify user credentials and return an object containing user context. However, there are a couple of things to consider.

Push Notifications Opt-In
Push Notification Service (PNS) is a powerful tool that allows your server application to initiate communication with the client even while the client isn't running. There is no equivalent functionality on the desktop or in web applications; it is one of the unique features of the mobile client. I'm sure any enterprise system could use PNS, and in my next post I will show how to implement it. Normally, you would register a user for push notifications as soon as he or she authenticates. However, according to Windows Phone 7 Application Certification Requirements, the application must ask the user for explicit permission to receive a toast notification. Once the opt-in is obtained from the user, it can be saved in isolated storage settings. Below is a code snippet that checks settings and redirects user accordingly:
   NavigationService.Navigate(
      IsolatedStorageSettings.ApplicationSettings.Contains(Constants.Settings.CanUsePNS)
         ? new Uri(Constants.Urls.LandingPage, UriKind.Relative)
new Uri(Constants.Urls.PNSOptInPage, UriKind.Relative));


Session Management
Authentication usually implies a time-limited user session. Unlike ASP.NET, which is a server-side platform, Silverlight doesn't provide session management features out of the box. My recommended approach for mobile application is to implement a dual session management mechanism along these lines:

  1. Client ask user for a preferred session duration (not to exceed a predefined system limit) before login
  2. Client successfully authenticates, and server returns a unique session token (a GUID, for instance)
  3. Client keeps session state in the isolated storage
  4. Every time the application is activated, it checks if session length has exceeded timeout
  5. Every time the client makes a webservice call, it includes the session token as a parameter. Server uses it to validate the session and optionally create an audit trail of user activity.
Restoring Session State On Activation
When application is running, session state is stored in a public static property of the App class (App.xaml.cs), for example:
   public static UserLogin CurrentUser { getset; }
However, the value goes away when application becomes inactive (again, this is unique behavior of mobile clients) and we need to restore it as part of reactivation:

   1:  private void Application_Activated(object sender, ActivatedEventArgs e)
   2:  {
   3:      if (AppController.CurrentUser == null)
   4:      {
   5:          using (var store = IsolatedStorageFile.GetUserStoreForApplication())
   6:          {
   7:              if (store.FileExists(Constants.Files.UserLogin))
   8:              {
   9:                  using (var file = new IsolatedStorageFileStream(Constants.Files.UserLogin, FileMode.Open, store))
  10:                  {
  11:                      var serializer = new DataContractSerializer(typeof(UserLogin));
  12:                      AppController.CurrentUser = (UserLogin)serializer.ReadObject(file);
  13:                  }
  14:              }
  15:          }
  16:      }
  17:  }

(to be continued)

Wednesday, November 10, 2010

Mobile Enterprise Application. Step 1: General Architecture

I decided to follow up on my previous post and write a series of more practical articles to illustrate various decisions that are specific to mobile enterprise applications. Being is Microsoft platform developer, I am going to stick to Windows Phone 7 in this series. This first blog post discusses general architectural issues.

Choosing Client Technology
WinPhone 7 supports two development paradigms: Silverlight and XNA. The latter targets game developers, providing them with game loop, sprites, and stuff like that. Silverlight, on the other hand, is a subset of the traditional desktop UI platform (WPF). It has a rich set of controls plus the ability to do cool visual effects. Silverlight is a natural choice for a mobile enterprise application.

Relative Merits of MVVM
Model-View-ViewModel design pattern has a widespread adoption in the XAML world, including Silverlight. The question isn't whether or not MVVM can be used in WinPhone 7 applications (it can) but whether or not it should be used. On the negative side, MVVM makes your app larger and slower, which is no small thing on the mobile device. On the positive side, it provides the separation between user interface and logic which is extremely beneficial in two scenarios: unit testing and sharing projects with a designer.

Unit Testing
Generally, I am a big proponent of unit testing - I believe they are essential to building high-quality maintainable programs. However, WinPhone 7 unit testing is a little wobbly at the moment. Test framework built into Visual Studio doesn't support phone applications, so we are supposed to download Silverlight Unit Test framework, which is included into Silverlight Toolkit. Only problem is that latest version of the toolkit supports Silverlight 4, but not WinPhone 7... I'm sure eventually Microsoft will sort everything out, but for the time being it's probably best not to concentrate on unit tests.

Sharing Projects With Designer
If your project team has a dedicated designer who actually works with the same project as developers, MVVM provides a nice clean separation of concerns. If, on the other hand, you do not have a designer, or the one you have prefers exchanging images and screenshots with you over email, MVVM doesn't really give you much of an edge.

Choosing Server Technology
We should try to shift as much logic as possible to the server. This makes sense from several points of view. First of all, mobile client doesn't offer a lot of processing power while server side can be very scalable. Second, if you support more than one client platform, it helps to have as little code to port as possible. Third, your business logic is your intellectual property, and it is definitely more secure on the server.

SOAP or REST?
When it comes to building web services, WCF allows the choice between SOAP and REST. On the high level, SOAP is really a remote procedure call mechanism which can support sophisticated logic and advanced  security requirements. REST, on the other hand, operates with a simple set of HTTP verbs and is therefore better suited for simpler CRUD-type logic.

Secure Communication
Mobile clients communicate with web services over 3G or WiFi networks, which makes them vulnerable to security attacks (open public WiFi are especially fertile ground for packet sniffing - read more here). It is therefore essential to encrypt all messages, not just those related to authentication. Using SSL protocol for communication is a good start.

(to be continued)

Thursday, October 21, 2010

Mobile Clients of Business Applications

As of today, there are over 200,000 applications in Apple AppStore targeting iPhone, iPod Touch, or iPad. Android Market has over 100,000 applications. Windows Phone 7 will start selling in November, and there is already a rush to fill up its Marketplace. Now, overwhelming majority of all these applications are consumer-oriented: games, social networking, news, and much more (even books these days are often made into phone applications). Does that mean that business apps (sometimes they are called "line of business" apps) don't have a place on a mobile client?

Given the huge popularity and widespread adoption of modern smartphones, combined with changes in the workplace, the answer must be a resounding "no". However, creating a mobile client that really adds value to the system as a whole is not a trivial task and requires careful planning. In this post, I will try to highlight some of the challenges involved in designing a mobile client for a business application.

Challenge 1. Define a Reasonable Subset of Functionality
Typical enterprise app has a very large scope, which tends to grow as business users demand more and more features with each release. Trying to squeeze as much as possible into the mobile client is probably not a good idea. First of all, consider the form-factor: will user be able to accomplish the task with tiny screen and soft keyboard? Then take into account specific needs of the mobile user - they are guaranteed to be different from someone who is comfortably sitting in front of a computer. For example, the latter may need the ability to sift through large sets of data with different search/sort criteria, while the former wants to see just the relevant data - and upfront.

Challenge 2. Mobile-Specific Features
Modern smartphones like iPhone or Windows Phone 7 have advanced hardware, and developers can incorporate such compelling features as multi-touch interface, camera, microphone, location services, and accelerometer. Naturally, applications can also have the ability to place phone calls and send email. These features may or may not be applicable to a specific business system. A mobile client for a customer-relationship management application is likely to take advantage of location services, phone and email, but it's difficult to imagine why it would need an accelerometer.

Challenge 3. Choose Appropriate Architecture
When it comes to choosing a specific technology, there are two main choices: develop mobile client as a web application or a native one. Although a web application is often a better choice for a desktop client, the situation is opposite in the mobile world. Even if the business system already has a website, a special version will be required to support small form-factor of the mobile device. On the other hand, browsers that are included with mobile operating systems vary in their support for various features of HTML, JavaScript, and CSS. The lowest common denominator website will probably not satisfy the users. Another drawback is the inability to tap into the mobile-specific features, such as location services or camera.

Going native allows full control over application UI, plus it enables access to hardware features, but it's hardly an easy task. Sheer number of available platforms is the main difficulty, with little or no code reuse between them. Android development should be done in Java, iPhone apps are written in Objective C, and Windows Phone 7 relies on C#/.NET.

Challenge 4. Security and Session Management
Pretty much all enterprise systems deal with sensitive data one way or another, and mobile clients will most likely need to work with it, too. Mobile devices have a security disadvantage compared to office computers: they are easily lost or stolen. It is therefore important not to store anything sensitive on the device itself and employ two-way authentication mechanism. User sessions cannot be open-ended and user activity within the application must be logged on the server for auditing purpose. Another potential vulnerability is the network: smartphones communicate over public Wi-Fi and 3G networks. This can be mitigated by using SSL protocol.