Random thoughts on software development, architecting systems and the tech industry

Text

Its been way too long since I last posted, hopefully my next post will not be next year!

The project I am currently working on has quite a significant code base, which has been developed over a period of 3 years. In that time my best guess is that there have been at least 50 different developers who have worked on the code at one point or another. In this kind of environment it is inevitable that some bad coding practices creep in.

One of these  patterns that I have come across a lot lately is returning nulls when the expected result is not available. In my mind if something has gone wrong in a method you should be throwing an exception. If a method returns a null then the caller has to provide for the following three scenarios:

  1. The method returns a valid result
  2. The method returns a null
  3. The method throws an exception

This leads to quite a lot of ambiguity and the caller has to jump through hoops to cater for all scenarios. There may be some scenarios where returning a null is acceptable, however for 90% of scenarios a null should never be deliberately returned.

Text

Here is a basic framework for a tabbed interface for Blackberry applications. The base class is shown below.

package com.example.tabScreens;

import com.example.tabScreens.ExampleMainScreen;

import net.rim.device.api.ui.Manager;

public abstract class TabScreen {
	protected boolean tabInit=false;
	protected ExampleMainScreen mainScreen;
	protected Manager manager;
	private TabField tabField;//the associated tab field on the main screen
	protected SetTabArea setTabArea;
	public TabScreen(ExampleMainScreen mainScreen,TabField tabField,Manager manager){
		this.mainScreen = mainScreen;
		this.setTabArea = (SetTabArea) mainScreen;
		this.manager = manager;
		this.tabField = tabField;
	}
	
	protected abstract void TabInit();
	
	public final Manager displayTab()
	{
		if(tabInit == false){
			TabInit();
			tabInit = true;
		}
		return manager;
	}
		
	protected final void SetTabAreaCall(TabScreen tabScreen)
	{
		tabField.setFocus();
		setTabArea.setTabArea(tabScreen);
	}
}

To implement a tab screen simply inherit from the above and add the fields that you want for the tab screen. The crucial thing is to override the TabInit method. Here you should add the components to the manager. Refer to the example below:


package com.example.tabScreens; import net.rim.device.api.ui.Manager; import net.rim.device.api.ui.component.LabelField; import net.rim.device.api.ui.container.VerticalFieldManager; public class TabScreen1 extends TabScreen{ protected final LabelField nameLabel = new LabelField("Name:Thomas Edison"); protected final LabelField hobbyLabel = new LabelField("Hobbies:Soccer, archery"); protected final LabelField ageLabel = new LabelField("Age:34"); public TabScreen1(ExampleMainScreen mainScreen, TabField tabField){ super(mainScreen,tabField,new VerticalFieldManager( Manager.VERTICAL_SCROLLBAR | Manager.VERTICAL_SCROLL)); } protected void TabInit() { manager.add(nameLabel); manager.add(hobbyLabel); manager.add(ageLabel); } }

The Tab screens are placed on a MainScreen and each TabScreen has an associated TabField. I used my own specialized field for TabField so that I could override the navigationClick event. This was done so that the Tab Fields are clickeable.

package com.example.tabScreens;

import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FocusChangeListener;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.Manager;

public class ExampleMainScreen extends MainScreen implements FocusChangeListener, SetTabArea /*PopulateEstimate*/{
	
	private TabField tab1;

	private TabField tab2;

	private TabField tab3;
	
	private LabelField spacer1;

	private LabelField spacer2;
	
	private Manager tabArea;
	
	
	private TabScreen1 tabScreen1;
	private TabScreen2 tabScreen2;
	private TabScreen3 tabScreen3;
	
	public ExampleMainScreen() {
		HorizontalFieldManager hManager = new HorizontalFieldManager();
		tab1 = new TabField("Tab1", LabelField.FOCUSABLE | LabelField.HIGHLIGHT_SELECT);
		tab2 = new TabField("Tab2", LabelField.FOCUSABLE | LabelField.HIGHLIGHT_SELECT);
		tab3 = new TabField("Tab3", LabelField.FOCUSABLE | LabelField.HIGHLIGHT_SELECT);
		spacer1 = new LabelField(" | ", LabelField.NON_FOCUSABLE);
		spacer2 = new LabelField(" | ", LabelField.NON_FOCUSABLE);
		
		tab1.setFocusListener(this);
		tab2.setFocusListener(this);
		tab3.setFocusListener(this);
		hManager.add(tab1);
		hManager.add(spacer1);
		hManager.add(tab2);
		hManager.add(spacer2);
		hManager.add(tab3);

		VerticalFieldManager vManager = new VerticalFieldManager();
		vManager.add(hManager);
		vManager.add(new SeparatorField());
		setBanner(vManager); //this keeps the tabs at the top of the screen even when scrolling
				
		tabScreen1 = new TabScreen1(this,tab1);
		tabScreen2 = new TabScreen2(this,tab2);
		tabScreen3 = new TabScreen3(this,tab3);
		
		setTabArea(tabScreen1);

	}
	
	public void setTabArea(TabScreen tabScreen){
		if(tabArea != null)
			delete(tabArea);
	
		tabArea = tabScreen.displayTab();
		add(tabArea);
	}
	
	public void focusChanged(Field field, int eventType) {
		
		if (tabArea != null) {
			if (eventType == FOCUS_GAINED) {
				if (field == tab1) 
					setTabArea(tabScreen1);
				else if (field == tab2) 
					setTabArea(tabScreen2);
				else if (field == tab3)
					setTabArea(tabScreen3);
			}
		}
	}
}

I added a few features that are not strictly needed like the SetTabArea interface. You can check out the entire example here. This is what the final product looks like:

Text

Recently I needed to serialize objects in Delphi so that I could transfer them across COM. Simple right? In .Net you simply use XmlSerializer, surely there is an equivalent in Delphi? Wrong! Let me just state that I am working in Delphi2005, so there may be an XML serializer in Delphi XE.

After looking around for a third party serializer I could not find something that I could get going easily and that worked the way I expected it to. So I decided to give XML serialization a go and what I could come up with.

Delphi has some fairly good RTTI, and I found the following article helpful: http://blog.dragonsoft.us/2008/04/21/how-to-serialize-delphi-object/. The below implementation is based on this. Also note that only object properties that are Public and Published can be traversed. Something else which I found, was that the objects should inherit from TPersistent.

The heart of this unit is the ‘Parse’ method. This was a very quick implementation so theres a lot that can be added, for example this can be extended to serialize arrays. What this serializer will handle is nested classes.

unit XMLSerializer;

interface

uses
  XmlIntf, XMLDoc, TypInfo, windows, sysUtils, forms;

type
   TXMLSerializer = class
   protected
      FXMLDoc : TXMLDocument;
      FCurrentNode : IXMLNode;
      FPreviousNode : IXMLNode;
      procedure Parse(AObject : TObject);

   public
      procedure Serialize(AObject : TObject;const RootName : string);
      //procedure WriteTofile(filename : string);
      procedure WriteToStr(var theString : WideString);
      destructor Destroy;override;
   end;

implementation

procedure TXMLSerializer.Parse(AObject : Tobject);
var
  i: integer;
  lPropInfo: PPropInfo;
  lPropCount: integer;
  lPropList: PPropList;
  lPropType: PPTypeInfo;
  //info : PTypeInfo;
  SubObject : TObject;
begin
   lpropCount := GetPropList(PTypeInfo(AObject.ClassInfo), lPropList);

   for i := 0 to lPropCount - 1 do
   begin
      lPropInfo := lPropList^[i];
      lPropType := lPropInfo^.PropType;
      if lPropType^.Kind = tkMethod then
         Continue
      else if lPropType^.Kind = tkClass then
      begin
         SubObject := GetObjectProp(AObject, lPropInfo.Name);
         FCurrentNode.AddChild(lPropInfo.Name);
         FPreviousNode := FCurrentNode;
         FCurrentNode := FCurrentNode.ChildNodes.FindNode(lPropInfo.Name);
         Parse(SubObject);
         FCurrentNode := FPreviousNode;
      end
      else FCurrentNode.AddChild(lPropInfo.Name).Text := GetPropValue(AObject, lPropInfo.Name, True);
      
      //To extend this check for different lPropType^.Kind
      //This could for example be extended to serialize arrays by checking lPropType^.Kind = tkArray
  end;
end;

procedure TXMLSerializer.Serialize(AObject : TObject;const RootName : string);
begin
  FXMLDoc := TXMLDocument.Create(Application);
  FXMLDoc.Active := True;
  FXMLDoc.AddChild(RootName);

  FCurrentNode := FXMLDoc.DocumentElement;

  //We should do some checking here that the object passed in is of type
  //TPersistent

  Parse(AObject);
end;

procedure TXMLSerializer.WriteToStr(var theString : WideString);
begin
   FXMLDoc.SaveToXML(theString);
end;

destructor TXMLSerializer.Destroy;
begin
   FXMlDoc.Free;
   inherited;
end;

end.

Here is an example of a class that is to be serialized:

   TPerson = class(TPersistent)
   protected
      FName : string;
      FAge  : Integer;
      FEmail : string;
   published
      property Name : string read FName write FName;
      property Age : Integer read FAge write FAge;
      property Email : string read FEmail write FEmail;
   end;

The resulting XML is as follows:

<Person>
  <Name>Bob Sinclair</Name>
  <Age>23</Age>
  <Email>bob@bobsinclair.com</Email>
</Person>

Typcial usage would be as follows:

procedure TForm1.Button1Click(Sender: TObject);
var
   s : TXMLSerializer;
   person : TPerson;
begin
   //Create the serializer
   s := TXMlSerializer.Create();

   //instantiate the person object and populate
   person := TPerson.Create();
   person.Name := 'Bob Sinclair';
   person.Age := 23;
   person.Email := 'bob@bobsinclair.com';

   //unfortunately you have to specify the root tag of the xml in this case 'Person'
   s.Serialize(person,'Person');
   s.WriteToStr(output);
   showMessage(output);
end;