Archive

Archive for February, 2009

SVN commit basic policy guide

February 19th, 2009

Think twice before committing

Committing something to SVN has serious consequences. All other developers will get your changes once they are in SVN, and if they break something, they will break it for everybody. All commits will be publicly available in the SVN repository forever.

The baseline is: Be aware of the consequences of your commits. Take time to think about them before committing.

Never commit code that doesn’t compile

Compile the code and correct all errors before committing. Make sure that newly added files are comitted. If they are missing your local compile will work fine but everybody else won’t be able to compile.

Run all tests and check they passed.

You certainly should make sure that the code compiles with your local setup and platform. You should also consider what consequences your commit will have for compiling on another architecture. When you made a change to database structure, commit alter scripts as well.

Test your changes before committing

Build the packages and start the application affected by your change and make sure that the changes behaves as desired.
Double check what you commit.

Do a “svn up” and a “svn diff” before committing. Take messages from SVN about conflicts, unknown files, etc. seriously. The “svn diff” will tell you exactly what you will be committing. Check if that’s really what you intended to commit.

Always add descriptive log messages

Log messages should be understandable to someone who sees only the log. They shouldn’t depend on information outside the context of the commit. Try to put the log messages only to those files which are really affected by the change described in the log message.

In particular put all important information which can’t be seen from the diff in the log message.

Don’t add email, skype or any other communication as log message.

Respect special commit policies set by the release plans

Respect the policies of the current release phase, i.e. avoid commiting new features and code shortly before a planed release.

Source control systems are not a substitute for developer communication

When you plan to make changes which affect a lot of different code in SVN, announce them on the mailing list in advance.

Changes which affect a lot of code in SVN, like making use of a new feature in the libs, might break other code even if they look trivial, e.g., because an application must also compile with older versions of the libs for some reasons. By announcing the changes in advance, developers are prepared and can express concerns before something gets broken.

Take responsibility for your commits

If your commit breaks something or has side effects on other code, take the responsibility to fix or help fix the problems.

Don’t commit code you don’t understand

Avoid things like “I don’t know why it crashes, but when I do this, it does not crash anymore.” or “I’m not completely sure if thats right, but at least it works for me.”.

If you don’t find a solution to a problem, discuss it with other developers.

Don’t abuse your SVN account to push in changes with which other developers disagree

If there are disagreements over code changes, these should be resolved by discussing them on the mailing lists or in private, not by forcing code on others by simply committing the changes to SVN.

If you commit bug fixes, consider porting the fixes to other branches

Use the same comment for both the original fix and the back port, that way it is easy to see which fixes have been backported already.

If you fix bugs reported on the bug tracking system, add the bug number to the log message

In order to keep the bug tracking system in sync with SVN, you should reference the bug report in your commits, and close the fixed bugs in the bug tracking system.

This doesn’t mean that you don’t need an understandable log message. It should be clear from the log message what has been changed without looking at the bug report.

For example: “Fixed add to basket button (#1859)”

Don’t add files generated by standard tools to the repository

Files generated at build shouldn’t be checked into the repository because this is redundant information and might cause conflicts. Only real source files should be in SVN.

Don’t use SVN keywords like Id or Log in the source files

These tags cause unnecessary conflicts when merging branches and don’t contain any information which wouldn’t be available in the SVN repository anyway.

Make “atomic” commits

SVN has the ability to commit more than one file at a time. Therefore, please commit all related changes in multiple files, even if they span over multiple directories at the same time in the same commit. This way, you ensure that SVN stays in a compilable state before and after the commit.

Don’t mix formatting changes with code changes

Changing formatting like indenting or white spaces blows up the diff, so that it is hard to find code changes if they are mixed with reinventing commits or similar things when looking at the logs and diffs later. Committing formatting changes separately solves this problem.

Source versioning

Simple custom event handling

February 17th, 2009

The event model in C# is based on idea of publisher and subscribers. Each publisher can have more subscribers subscribed to each event. Publisher will do some logic and publish an event to all subscribers. Subscribers will do their logic reacting to raised event. In C#, any object can publish a set of events to which other applications can subscribe. When the publishing class raises an event, all the subscribed applications are notified. Example of this behaviour can be that the application will subscribe to event which will be raised from database connection control when the connection is lost. Main application will know, that this happened and can react on that event –reconnect, show alert message, etc.

Conventions

The following important conventions are used with events:

  • Event Handlers in the .NET Framework return void and take two parameters.
  • The first paramter is the source of the event; that is the publishing object.
  • The second parameter is an object derived from EventArgs.
  • Events are properties of the class publishing the event.
  • The keyword event controls how the event property is accessed by the subscribing classes.

Example

Lets say that we have Product class which has Name property. When the name is changed we want ot change this name in Label as well. We don’t know from where this name can be changed. We will “convert” product class into event publisher and the window where is the label will subscribe to this event.

First step will be to create the event and method which will fire this event.


public class Product
{
  public string Name { get; set; }
  // Delegate
  public delegate void PropertyChangeHandler (object sender,  EventArgs data);
  // The event
  public event PropertyChangeHandler PropertyChange;
  // The method which fires the Event
  protected void OnPropertyChange (object sender,  EventArgs data)
  {
    // Check if there are any Subscribers
    if (PropertyChange!= null)
    {
      // Call the Event
      PropertyChange (this, data);
    }
  }
}

We created delegate which encapsulates any method that takes these attributes, this delegate must be implemented by all subscribers. Now we need one small change to the class. That will be to fire the event, when Name property is changed. It can be nice to pass information about this change to subscribers with what have been changed and to have old value and new value. For this we will create PropertyChangeEventArgs class which will be derived from EventArgs.


public class PropertyChangeEventArgs : EventArgs
{
  public string PropertyName { get; internal set; }
  public object OldValue { get; internal set; }
  public object NewValue { get; internal set; }
  public PropertyChangeEventArgs(string propertyName, object oldValue, object newValue)
  {
    this.PropertyName = propertyName;
    this.OldValue = oldValue;
    this.NewValue = newValue;
  }
}

public class Product
{
  private string name;
  public string Name {
    get
    {
      this.name;
    }
    set
    {
      Object old = this.name;
      this.name = value;
      OnPropertyChange(this, new PropertyChangeEventArgs(“Name”, old, value));
    }
  }

  // Delegate
  public delegate void PropertyChangeHandler (object sender,  PropertyChangeEventArgs data);
  // The event
  public event PropertyChangeHandler PropertyChange;
  // The method which fires the Event
  protected void OnPropertyChange (object sender,  PropertyChangeEventArgs data)
  {
    // Check if there are any Subscribers
    if (PropertyChange!= null)
    {
      // Call the Event
      PropertyChange (this, data);
    }
  }
}

Now we are done with the Product class (publisher) and can subscribe to the OnPropertyChange event.


protected void Page_Init(object sender, EventArgs e)
{
  this.Product = new Product();
  this.Product.OnPropertyChange += new Product.PropertyChangeHandler(PropertyHasChanged);
}
protected void Page_Load (object sender, EventArgs e)
{
  this.Product.Name = "New name";
}

public void PropertyHasChanged (object sender,  PropertyChangeEventArgs data)
{
  if(data.PropertyName == “Name”)
  {
    this.ProductLabel.Text = (string)data.NewValue + " was " + (string)data.OldValue;
  }
}

In the Init event we created product instance and subscribe to OnPropertyChange event of Product class. In Load phase we changed name of that product. This operation fired PropertyChange and this was send to all subscribers. This calls PropertyHasChanged method with all informations.

Donwload example: Download

C# , ,

Google Analytics - tracking external links

February 4th, 2009

Recently I was asked to implement extension which will track external links into Google Analytics. For me I was facing to problems. One I that if you have running 3rd party system it’s hard to implement anything, that will change all external links and the second one is that Javascript is not my cup of tea.

I found and implemented one solution which looks simple and works. Main idea is to listen to click on page and if the clicked element is anchor, call Googles page tracking before browser goes to that page. Another solution is to use jQuery, I’ll show this solution later.

First step is to create a listener, what will listen events on page and call another function to handle the action.


function addListener(element, type, functionName)
{
  if(window.addEventListener) {
    element.addEventListener(type, functionName, false);
  }
  else if(window.attachEvent) {
    element.attachEvent('on' + type, functionName);
  }
  else return false;
  return true;
}

addListener(document, 'click', trackingExternalClick);

Second step will be to create function, which will contain the logic for onclick action. Lets say that we want to track anchors which point to external page (starting with http:// or https://) and wants to know whats the clicked domain, we don’t need to know whole url. Name of the function will be trackingExternalClick (third parameter in addListener).


function trackingExternalClick(event) {
  var cElem = (window.event) ? event.srcElement : event.target; //Get the clicked element
  //If it is an Anchor
  if(cElem.nodeName == 'A'){
    // Check if link is external, not contain local domain
    if(cElem.href.indexOf(location.host) == -1) {
    //Replace characters not supported by Google Analytics
      var url = cElem.href.match(/^([http|https]*):\/\/?([^\/]+)/g, "").toString().replace(new RegExp(/^([http|https]*)?:\/\//i),"");
      var str = '/outgoinglink/' + url;
      try{
        pageTracker._trackPageview(str);
      }
      catch(err){ }
    }
  }
}

Same practice can be used to track download links (.zip, .pdf, etc.). We will only change lines 6 to 9.


if(cElem.href.indexOf(".pdf") == -1) {
  //Replace characters not supported by Google Analytics
  var url = cElem.href;
  var str = '/download/' + url;

When you will have problems that these clicks are not tracked, try to move Google Analytics code to the head section of the page and these codes after GA. If you need anything more or wants to help with something, leave a message here.

google , ,

Import CSV into MSSQL database

February 1st, 2009

This is really common task in any database project. You always need to get initial data into database. Maybe most common file format is CSV.

We have CSV file in drive C: with name import.csv with following content. The location of the file is C:\import.csv.


id,login,name,surname
1,user1,James,White
2,user2,Johny,Walker
3,user3,Jim,Beam

We will create table with these four columns.


CREATE TABLE CSVImport (
  ID INT,
  Login VARCHAR(20),
  FirstName VARCHAR(40),
  LastName VARCHAR(40),
  BirthDate SMALLDATETIME
);

Now we have everything we need to import the file into database. We will use BULK INSERT to put the data into table. If there is any error in any row it will be not inserted but other rows will be inserted.


BULK INSERT CSVImport
FROM 'c:\import.csv'
WITH
(
  FIRSTROW = 2,
  FIELDTERMINATOR = ',',
  ROWTERMINATOR = '\n'
)
GO

Parameter FIRSTROW will tell BULK LOAD that we don’t want to import first line (= 1) because it contains headers.

If you will have table what have less columns than the csv file these columns will be added after text in the last column. If this column will reach maximum length, this line will not be inserted. With MAXERRORS you can specify the maximum number of error lines what are allowed before whole INSERT will be considered as failed.

Possible problems

Permissions

  • User which runs bulk insert must have BULKINSERT permissions.
  • SQL Sever must have access rights to the file.

Database , ,