Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Collection Class (Limited Version)

pascal

  • Please log in to reply
No replies to this topic

#1 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1320 posts
  • Programming Language:PHP, Delphi/Object Pascal, Pascal, Transact-SQL
  • Learning:C, Java, PHP

Posted 23 January 2011 - 07:04 AM

Sometimes we need to limit the number of items we collected in our collection class. For example if we are to develop a chat system, usually we want to collect the history of the conversation in the collection of sentences. Since usually this kind of system must anticipate large number of conversation at one time, we have to conserve our memory by limiting how many sentences we have to store in memory for a chat session.

This tutorial is about to design and implement a collection class that automatically limit/trim its members.

For simplicity and easy of use, in this tutorial we will create a custom class that wraps an instance of TList. New custom class making sure our class is simple, without many properties and methods that indirectly related. This making sure that we could take advantage of Delphi's IDE autocompletion feature to the fullest. See this post to get a sample of how to take advantage of autocompletion feature. The TList is the one who does the actual job of collecting items internally.

Let's name this class TLimitList. And here the skeleton interface of our class. I believe most of the properties and methods functionality could be easily guessed from their names. But we will explain some important ones.

  TLimitList=class
  public
    procedure Add(AItem: TObject);
    procedure Trim;
    function Delete(AItem: TObject): Boolean; overload;
    function Delete(AIndex: Integer): Boolean; overload;
    procedure Clear;

    property Count: Integer read GetCount;
    property Capacity: Integer read FCapacity write SetCapacity;
    property OwnItems: Boolean read FOwnItems write FOwnItems;
  end;

Basic scenario

Property Capacity defines the maximum number of items that should be hold in the collection. Whenever we add new item or change the capacity value we should inspect the current number of collected items. If we detect the items are more than allowed, we should remove the older ones. The inspection and removals is done by the Trim method.

So the implementation of Add method is:
procedure TLimitList.Add(AItem: TObject);
begin
  FList.Add(AItem);
  Trim;
end;

See that we run Trim immediately after we add new item to our internal list.

And when we change the capacity value we will execute SetCapacity. And here is the implementation of it.
procedure TLimitList.SetCapacity(const Value: Integer);
begin
  if FCapacity <> Value then
  begin
    FCapacity := Value;
    Trim;
  end;
end;

Like what we are doing in Add method, here we also immediately execute Trim when we changing the capacity value to make sure the number of collected items does not exceed the capacity.

And here is the implementation of Trim method.

procedure TLimitList.Trim;
begin
  while FList.Count > FCapacity do
    Delete(0);
end;

Simple, right? It just delete the first item (the oldest item) while the number is exceeding the current capacity.

For full source code of the TLimitList class please check LimitList unit in the attached source code. Feel free to post queries or critics here.

DUnit Testframework

For this tutorial I did not write a customized demo project. This time I use DUnit test framework for testing our TLimitList library. I found using DUnit gave you at least these advantages.
  • You make sure your code run as expected, since it is for testing your code.
  • You don't have to write special demo project to illustrate your codes.
  • You already provided code snippets on using your library/code in your DUnit tests units.
  • When you do refactoring your code, the DUnit tests tell us ummediately whether the new changes break existing behavior.

DUnit library itself is a free and open source project. Currently hosted in SourceForge.Net. If you don't have it, go download it here and read the wiki here.

Using DUnit test framework, we create a test class containing methods to test our TLimitList class. In this tutorial we want to test if the add, trim, and clear methods work as expected, and also the count property should return correct amount. So the skeleton of our test class:

  TTestLimitList=class(TTestCase)
  published
    procedure Test_Add_And_Count;
    procedure Test_Clear;
    procedure Test_AutoTrimming;
  end;

For the automatic recognition of the tests methods, you must declare them parameterless in published section as shown above.

So for the implementations:

procedure TTestLimitList.Test_Add_And_Count;
var
  vItems: array[1..3] of TObject;
begin
  vItems[1] := TObject.Create;
  vItems[2] := TObject.Create;
  vItems[3] := TObject.Create;

  Check(List.Count=0);
  List.Add(vItems[1]);
  Check(List.Count=1);
  List.Add(vItems[2]);
  Check(List.Count=2);
  List.Add(vItems[3]);
  Check(List.Count=3);
end;

procedure TTestLimitList.Test_AutoTrimming;
const
  cTestCapacity = 10;

var
  i: Integer;
  vItems: array[1..100] of TObject;
begin
  // explicitly set the capacity of the collection class
  List.Capacity := cTestCapacity;

  // init the test objects
  for i := 1 to 100 do
  begin
    vItems[i] := TObject.Create;
    List.Add(vItems[i]);
    Check(List.Count <= cTestCapacity);
  end;
end;

procedure TTestLimitList.Test_Clear;
var
  vItems: array[1..3] of TObject;
begin
  vItems[1] := TObject.Create;
  vItems[2] := TObject.Create;
  vItems[3] := TObject.Create;

  List.Add(vItems[1]);
  List.Add(vItems[2]);
  List.Add(vItems[3]);
  Check(List.Count=3);

  List.Clear;
  Check(List.Count=0);
end;

Here is our test program in action, before we execute the tests.

[ATTACH]3654[/ATTACH]

And here it is after we execute the test. Note that this prove that the tested methods and property of TLimitList work as expected.

[ATTACH]3653[/ATTACH]

Full source and executable are attached. Fell free to query anything.

[ATTACH]3652[/ATTACH]

Attached Thumbnails

  • LimitListTests_BeforeRun01.png
  • LimitListTests_AfterRun01.png

Attached Files


  • 0





Also tagged with one or more of these keywords: pascal

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download