Wednesday, August 5, 2009

A Polling Service


As mentioned, I am starting off the technical posts.

I found the following use of windows services very useful. Just wanted to share this with everyone.
There are certain situations where you need to monitor changes, and trigger actions, like changes in data in a database. Sure, you can use database triggers, but here is an alternative to using database triggers, which involves using a windows service.
I will not go over the basic steps of creating a windows service here. Rather, I will go through the idea of polling for information in a windows service. If interested in the basic structure of a windows service, this article in Codeproject is a good source of information.
A service class is created. Apologies for the (lack of) indentation - I blame the Post editor :-


   1:  public class MonitorService : System.ServiceProcess.ServiceBase
   2:  {
   3:  /// 
   4:  /// Required designer variable.
   5:  private System.ComponentModel.Container components = null;
   6:  ServicePollingService pollingService;
   7:   
   8:   
   9:  public MonitorService()
  10:  {
  11:  // This call is required by the Windows.Forms Component Designer.
  12:  InitializeComponent();
  13:  }
  14:   
  15:   
  16:  // The main entry point for the process
  17:  static void Main()
  18:  {
  19:  System.ServiceProcess.ServiceBase[] ServicesToRun;
  20:   
  21:  // More than one user Service may run within the same process. To add
  22:  // another service to this process, change the following line to
  23:  // create a second service object. For example,
  24:  //
  25:  // ServicesToRun = new System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
  26:  ServicesToRun = new System.ServiceProcess.ServiceBase[] { new PollingService() };
  27:  System.ServiceProcess.ServiceBase.Run(ServicesToRun);
  28:  }/// 
  29:  /// Required method for Designer support /// 
  30:   
  31:  private void InitializeComponent()
  32:  {
  33:  components = new System.ComponentModel.Container();
  34:  this.ServiceName = "Monitor Service";
  35:  }/// 
  36:  /// Clean up any resources being used.
  37:  protected override void Dispose( bool disposing )
  38:  {
  39:  if( disposing )
  40:  {
  41:  if (components != null)
  42:  {
  43:  components.Dispose();
  44:  }
  45:  }
  46:  base.Dispose( disposing );
  47:  }/// 
  48:  /// Set things in motion so your service can do its work.
  49:  protected override void OnStart(string[] args)
  50:  {
  51:  pollingService = new PollingService();
  52:  pollingService.Start();
  53:  }/// 
  54:  /// Suspends this service.
  55:  protected override void OnPause()
  56:  {
  57:  pollingService.Suspend();
  58:  }/// 
  59:  /// Resume this service.
  60:  protected override void OnContinue()
  61:  {
  62:  pollingService.Resume();
  63:  }/// 
  64:  /// Stop this service.
  65:  protected override void OnStop()
  66:  {
  67:  pollingService.Stop();
  68:  }
  69:  }
  70:   
Like most service classes, PollingService has a Start and a Stop method. The Start method starts a listener thread which monitors changes - it could periodically run another function/stored procedure, etc to "poll" or look for changes. This is shown below:


   1:  public class PollingService
   2:  {
   3:  private Thread listenerThread; 
   4:   
   5:   
   6:   
   7:   
   8:  // Response Server States.private const int STOPPED = 1;
   9:  private const int RUN = 2;
  10:  private const int STOP = 3;
  11:   
  12:   
  13:  private int state = STOPPED;
  14:  public const string ServiceName = "Polling Service";
  15:   
  16:  public PollingService()
  17:  {
  18:  }/// 
  19:  /// Starts the Listener thread.
  20:  public void Start()
  21:  {
  22:  listenerThread = new Thread(new ThreadStart(this.Listener));
  23:  listenerThread.Start();
  24:  }
  25:   
  26:  /// 
  27:  /// Stops the Listener thread.
  28:  public void Stop()
  29:  {
  30:   
  31:  // Signal to the worker thread that it should stop ...
  32:   
  33:  state = STOP;
  34:  listenerThread.Interrupt();
  35:  // Save required data here.
  36:  }
  37:   
  38:  /// 
  39:  /// Suspends the Listener thread.
  40:   
  41:  ///
  42:  public void Suspend()
  43:  {
  44:  listenerThread.Suspend();
  45:  // Save required data here.
  46:  }
  47:  /// 
  48:  /// Resumes current thread.
  49:  /// 
  50:   
  51:  public void Resume()
  52:  {
  53:  // Initialize again.
  54:  listenerThread.Resume();
  55:  }
  56:   
  57:  /// 
  58:  /// Listens for changes.
  59:  /// 
  60:   
  61:  protected void Listener()
  62:  {
  63:  try
  64:  {
  65:  state = RUN;
  66:  while ( state == RUN )
  67:  {
  68:  PollForChanges();
  69:   
  70:  // Where the intervals come from configuration.
  71:   
  72:  Thread.Sleep(new TimeSpan(hoursInterval, minutesInterval, secondsInterval));
  73:  }
  74:  }
  75:  catch ( ThreadInterruptedException )
  76:  {
  77:   
  78:  // No need to log the fact that the thread has been interrupted.}
  79:  catch ( Exception e)
  80:  {
  81:   
  82:  // Log to database or event log.
  83:   
  84:  LogHelper.LogError(e.ToString());
  85:  }
  86:  finally
  87:  {
  88:  state = STOPPED;
  89:  LogHelper.LogWarning(string.Format("The {0} has shutdown.", ServiceName));
  90:  }
  91:  }
  92:   
  93:  /// 
  94:  /// The Main method which polls for changes and
  95:  /// processes them.
  96:  /// 
  97:   
  98:  private void PollForChanges()
  99:  {
 100:  try
 101:  {
 102:  // Method which processes the changes
 103:  ProcessChanges();
 104:  }
 105:  catch(Exception e)
 106:  {
 107:  LogHelper.LogError(e.ToString());
 108:  }
 109:  finally
 110:  {
 111:  // Save data
 112:  }
 113:  }
 114:   
 115:   
These type of services have proved extremely useful for us over the past few years - it has allowed us to monitor changes, pull/push data - quite good for integrating diverse systems.

Hope you find this useful.

Tuesday, July 28, 2009

What makes a good software developer?


I have often thought about this - "What makes a good software developer?" The answer to me, is not that straightforward - in fact, I may appear to be contradicting on some points. I will attempt to go over them (in no particular order):

A good software developer has to have:
  • The ability to see the bigger picture (or as my senior colleague used to say "the ability to see the forest through the trees") as well as pay attention to detail. As a software developer, one is required to keep the overall architecture in mind, and design and program solutions that are in harmony with the bigger picture. The bigger picture may also be extended to mean that it is not necessary that all business problems or needs are met by software solutions - that sometimes changes to business processes are required to fulfil a business need.
  • The ability to be pragmatic while preserving the integrity of the software solution. This can be a bit of a gray area - you have to be pragmatic to a certain extent to deliver what the users require, and you have to maintain the integrity of the solution to have clear boundaries and a clean architecture. In some cases, these may be a bit mutually exclusive - for example, it is of no use having a realtime application going through five web services for a simple business function - while this may maintain the purity of the solution, in practice, it is unworkable and a pain to support.
  • The ability to keep an open mind, being receptive to new ideas, at the same time, not pursuing infeasible or bad ideas. Sometimes it may require you to investigate new ideas, sometimes it may require you to completely trust your team members, but the overall objectives need to be kept in mind - what we are delivering (the intention and the scope of the delivery), and the limitations or bounds in terms of time and resources.
  • The ability to filter out unneeded "noise" and be solution-focused. Many people go around in unproductive circles, get involved in the "drama", rather than being solution-focused, having a plan, and resolving issues effectively. A good software developer needs to look at things objectively and be driven by sound skills and principles which help in delivering a solution.
  • The ability to work well in a team, as well as work well individually. This may seem easy.. but it can be challenging - especially working in a team made up of people from different technical backgrounds. I think that for a team to function properly, the roles and responsibilities of the team members need to be clearly defined. A healthy atmosphere needs to be created where productive discussions about different ideas are encouraged and an atmosphere where people move away from autonomous to consensual decisions. Working individually has its own challenges - you have to have a broader skill set, to name one.
  • The ability to contribute to, adhere to, and support processes/standards, and question them when needed. Processes and standards are put in place to make our lives easier. When a process/standard hinders software development rather than aid it, it needs to be questioned/improved/rectified.
  • Finally, a good software developer has a passion for the IT industry. It is quite essential for the software developer to be actively involved in new technologies, take an interest in current trends (eg cloud computing). Have a good understanding of where technology is at and being aware of how particular business needs could be met by fit-for-purpose technological solutions.
Most of the above points are not necessarily specific to software development - they can be taken out of the software development context and be applied to most industries.

Any comments, thoughts, discussion are most welcome.

Sunday, July 26, 2009

Introduction

Hi,

I would like to think that I have gained a bit of knowledge during my career as a software developer - from supporting legacy applications written in archaic languages, to jet setting to some of the remotest places in the world to support and "sell" applications, to working on large software development projects.

Here is an attempt to share some of my experiences - but be warned, some posts can get really technical. Hope you find them useful.