BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

is there a better way?

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design
View previous topic :: View next topic  
Author Message
Paul Hectors
Guest





PostPosted: Sun Nov 16, 2003 1:15 am    Post subject: is there a better way? Reply with quote



Problem
======
I cannot put a certain piece of into an area where it can be re used,
therefore I am having to copy paste a specific piece of code for each
method.

Scenario
======
In my program I have a singleton that is a connection manager in my
application.
I have a unit that is an API to a hardware device. The API is a unit that
has one class with class functions and class procedures.
These class methods could be standalone functions or procedures.

For every operation required, a connection has to be retrieved from the
Singleton connection manager and when the operation is finished the
connected released.

Below is a typical method:

class procedure TB1000Procedures.StartTest(const AB1000ID: word;const
ATestPwd:string);
var
Connection:TPsModBConnection;
begin
TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,Connection);
try
with TPsB1kBatteryTest.Create(nil,Connection) do
try
AutomatedPwd := ATestPwd;
Write; // command is sent
finally
Free;
end;
finally
TPsB1000ConnectionMgr.Singleton.Release(Connection);
end;

end;

Question
======
Every method requires the GetConnection and Release code is there anyway of
eliminating this duplication of code in each method?

Ideally I could override a method on an object where the connection has been
obtained and is a private variable of the object and connection is released
when object is destroyed.
Note all the class method take an ID as a common parameter but the method
signature is different for each method.

The existing design from a use point of view I believe is nice as a single
line of code can send or retrieve information. The use in the above example
to start a test is TPsB1000Procedures.StartTest(1,'blah blah').

Is there a bettery way?

Thank you for your time.

Best regards,

Paul Hectors


Back to top
Wayne Niddery [TeamB]
Guest





PostPosted: Sun Nov 16, 2003 4:39 am    Post subject: Re: is there a better way? Reply with quote



Paul Hectors wrote:
Quote:
In my program I have a singleton that is a connection manager in my
application.
I have a unit that is an API to a hardware device. The API is a unit
that has one class with class functions and class procedures.
These class methods could be standalone functions or procedures.

For every operation required, a connection has to be retrieved from
the Singleton connection manager and when the operation is finished
the connected released.

Below is a typical method:

class procedure TB1000Procedures.StartTest(const AB1000ID: word;const
ATestPwd:string);
var
Connection:TPsModBConnection;
begin
TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,Connection);
try
with TPsB1kBatteryTest.Create(nil,Connection) do
try
AutomatedPwd := ATestPwd;
Write; // command is sent
finally
Free;
end;
finally
TPsB1000ConnectionMgr.Singleton.Release(Connection);
end;

Your overall layout of the classes is not clear. It sounds like you are
resisting the creation of instances of some or all of these. You say the
connection mamanger is a singleton, but I see it has a property *called*
singleton and the connection manager itself appears to have no instance.
Off-hand it looks to me you are making this much more complicated than it
should be. From what I can see (which is not yet enough really) I would say
that you should be creating an instance of TB1000Procedures so it can hold a
persistent reference to a connection, but perhaps releasing after every call
is important - is the app multi-threaded?

--
Wayne Niddery - Logic Fundamentals, Inc. (www.logicfundamentals.com)
RADBooks: http://www.logicfundamentals.com/RADBooks.html
"It is error alone which needs the support of government. Truth can
stand by itself." - Thomas Jefferson



Back to top
Joanna Carter (TeamB)
Guest





PostPosted: Sun Nov 16, 2003 10:04 am    Post subject: Re: is there a better way? Reply with quote



Sean Dockery wrote:

Could I ask you to keep the amount of text you are quoting to a minimum?

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker


Back to top
Paul Hectors
Guest





PostPosted: Sun Nov 16, 2003 8:33 pm    Post subject: Re: is there a better way? Reply with quote

I am very sorry about my explanation not being clear so I will try again.

The application is multi threaded and problem is in the middle layer of the
system.

The ConnectionMgr manages connections for a number of devices. The
connection is required to interact with a "B1000" Device, therefore a
solution is required to interface with the "B1000" device.
My answer to that problem is a unit called uB1000Procedures and contains one
class TB1000Procedures with all class methods. Note this could just as well
be a unit with procedures as at the moment all methods are class methods.

The duplication of code is just getting and releasing the connection, so
below is the outline of a method in the unit uB1000Procedures.

TB1000Procedures = class(TObject)
public
class procedure StartTest(const AB1000ID: word;const ATestPwd:string);
// more class methods for interaction with "B1000" device
end;

class procedure TB1000Procedures.StartTest(const AB1000ID: word;const
ATestPwd:string);
var
Connection:TPsModBConnection;
begin
// Singleton is the method name for access, in the book GoF the method is
called "instance"
TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,Connection);
try
// do StartTest stuff here
finally
TPsB1000ConnectionMgr.Singleton.Release(Connection);
end;
end;

I hope the above explanation is better and highlight my problem.

How do I avoid duplicating the GetConnection and Release connection for each
method?

Maybe this is a possible solution.

Create a class that provides all the interface methods for the "B1000"
Device (TB1000Device). Than have a list that has an instance of
TB1000Device for B1000ID. Just like the Connection Manager has an instance
of a connection for a B1000ID. This TB1000Device list would be a Singleton
just like the Connection Manager and be thread safe.

Then TB1000Device class could be something like below:

TB1000Device = class(TObject)
private
FConnection:TPsModBConnection;
public
constructor Create(const AB1000ID:integer);virtual;
destructor Destroy;override;

// put all the methods here for the interface to the device
procedure StartTest(const APassword:string);

etc...
end;

constructor TB1000Device.Create(const AB1000ID:integer);
begin
inherited Create;
TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,FConnection);
end;

destructor TB1000Device.Destroy;
begin
TPsB1000ConnectionMgr.Singleton.Release(FConnection);

inherited Destroy;
end;

Thank you all so far for your time and help.

Best regards,

Paul Hectors


"Wayne Niddery [TeamB]" <wniddery (AT) chaffaci (DOT) on.ca> wrote

Quote:
Paul Hectors wrote:
In my program I have a singleton that is a connection manager in my
application.
I have a unit that is an API to a hardware device. The API is a unit
that has one class with class functions and class procedures.
These class methods could be standalone functions or procedures.

For every operation required, a connection has to be retrieved from
the Singleton connection manager and when the operation is finished
the connected released.

Below is a typical method:

class procedure TB1000Procedures.StartTest(const AB1000ID: word;const
ATestPwd:string);
var
Connection:TPsModBConnection;
begin
TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,Connection);
try
with TPsB1kBatteryTest.Create(nil,Connection) do
try
AutomatedPwd := ATestPwd;
Write; // command is sent
finally
Free;
end;
finally
TPsB1000ConnectionMgr.Singleton.Release(Connection);
end;

Your overall layout of the classes is not clear. It sounds like you are
resisting the creation of instances of some or all of these. You say the
connection mamanger is a singleton, but I see it has a property *called*
singleton and the connection manager itself appears to have no instance.
Off-hand it looks to me you are making this much more complicated than it
should be. From what I can see (which is not yet enough really) I would
say
that you should be creating an instance of TB1000Procedures so it can hold
a
persistent reference to a connection, but perhaps releasing after every
call
is important - is the app multi-threaded?

--
Wayne Niddery - Logic Fundamentals, Inc. (www.logicfundamentals.com)
RADBooks: http://www.logicfundamentals.com/RADBooks.html
"It is error alone which needs the support of government. Truth can
stand by itself." - Thomas Jefferson





Back to top
Paul Hectors
Guest





PostPosted: Sun Nov 16, 2003 10:17 pm    Post subject: Re: is there a better way? Reply with quote

Regarding my possible solution I realised that it will not work
I hope my second explanation of the problem is better and then you can
follow the following thinking.

I believe the approach should be a TB1000Device Manager that creates and
destroys the TB1000Device objects as required for a given B1000ID.

The interface for using the manager and executing a method on a TB1000Device
object would be something like the following where B1000ID = 1

// this class being a singleton and thread safe.
TB1000DeviceMgr = class(TObject)
public
function GetDevice(const AB1000ID:integer):TB1000Device;
end;

Usage TB1000DeviceMgr.Singleton.GetDevice(1).StartTest('blahblah')
( Possibly more conventional should be
TB1000DeviceMgr.Instance.GetDevice(1).StartTest('Blahblah') )

The only problem now is that the TB1000Device instance needs to be
automatically destroyed to release the connection to the Connection Manager.

So maybe TB1000Device needs to be an Interface type to make the above work ?

I hope I am making sense and not confusing everyone including myself.

Thank you for your time.

Best regards,

Paul Hectors

"Paul Hectors" <paul (AT) pwrshield (DOT) com> wrote

Quote:
I am very sorry about my explanation not being clear so I will try again.

The application is multi threaded and problem is in the middle layer of
the
system.

The ConnectionMgr manages connections for a number of devices. The
connection is required to interact with a "B1000" Device, therefore a
solution is required to interface with the "B1000" device.
My answer to that problem is a unit called uB1000Procedures and contains
one
class TB1000Procedures with all class methods. Note this could just as
well
be a unit with procedures as at the moment all methods are class methods.

The duplication of code is just getting and releasing the connection, so
below is the outline of a method in the unit uB1000Procedures.

TB1000Procedures = class(TObject)
public
class procedure StartTest(const AB1000ID: word;const ATestPwd:string);
// more class methods for interaction with "B1000" device
end;

class procedure TB1000Procedures.StartTest(const AB1000ID: word;const
ATestPwd:string);
var
Connection:TPsModBConnection;
begin
// Singleton is the method name for access, in the book GoF the method
is
called "instance"
TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,Connection);
try
// do StartTest stuff here
finally
TPsB1000ConnectionMgr.Singleton.Release(Connection);
end;
end;

I hope the above explanation is better and highlight my problem.

How do I avoid duplicating the GetConnection and Release connection for
each
method?

Maybe this is a possible solution.

Create a class that provides all the interface methods for the "B1000"
Device (TB1000Device). Than have a list that has an instance of
TB1000Device for B1000ID. Just like the Connection Manager has an instance
of a connection for a B1000ID. This TB1000Device list would be a Singleton
just like the Connection Manager and be thread safe.

Then TB1000Device class could be something like below:

TB1000Device = class(TObject)
private
FConnection:TPsModBConnection;
public
constructor Create(const AB1000ID:integer);virtual;
destructor Destroy;override;

// put all the methods here for the interface to the device
procedure StartTest(const APassword:string);

etc...
end;

constructor TB1000Device.Create(const AB1000ID:integer);
begin
inherited Create;
TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,FConnection);
end;

destructor TB1000Device.Destroy;
begin
TPsB1000ConnectionMgr.Singleton.Release(FConnection);

inherited Destroy;
end;

Thank you all so far for your time and help.

Best regards,

Paul Hectors


"Wayne Niddery [TeamB]" <wniddery (AT) chaffaci (DOT) on.ca> wrote in message
news:3fb6ff96 (AT) newsgroups (DOT) borland.com...
Paul Hectors wrote:
In my program I have a singleton that is a connection manager in my
application.
I have a unit that is an API to a hardware device. The API is a unit
that has one class with class functions and class procedures.
These class methods could be standalone functions or procedures.

For every operation required, a connection has to be retrieved from
the Singleton connection manager and when the operation is finished
the connected released.

Below is a typical method:

class procedure TB1000Procedures.StartTest(const AB1000ID: word;const
ATestPwd:string);
var
Connection:TPsModBConnection;
begin
TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,Connection);
try
with TPsB1kBatteryTest.Create(nil,Connection) do
try
AutomatedPwd := ATestPwd;
Write; // command is sent
finally
Free;
end;
finally
TPsB1000ConnectionMgr.Singleton.Release(Connection);
end;

Your overall layout of the classes is not clear. It sounds like you are
resisting the creation of instances of some or all of these. You say the
connection mamanger is a singleton, but I see it has a property *called*
singleton and the connection manager itself appears to have no instance.
Off-hand it looks to me you are making this much more complicated than
it
should be. From what I can see (which is not yet enough really) I would
say
that you should be creating an instance of TB1000Procedures so it can
hold
a
persistent reference to a connection, but perhaps releasing after every
call
is important - is the app multi-threaded?

--
Wayne Niddery - Logic Fundamentals, Inc. (www.logicfundamentals.com)
RADBooks: http://www.logicfundamentals.com/RADBooks.html
"It is error alone which needs the support of government. Truth can
stand by itself." - Thomas Jefferson







Back to top
Paul Hectors
Guest





PostPosted: Sun Nov 16, 2003 11:30 pm    Post subject: Re: is there a better way? Reply with quote

Thank you Sean for your reply.

I agree and I am aware that my current approach is totally procedural and
hence my question to the group to change the approach.

I apologise for my first attempt at explaining my problem and I hope my
second go is a lot better.

Quote:
Remember that to take advantage of inheritance, you should only expose the
most specialized class that you have to as a parameter in your classes.
That is, if a TPsConnection parameter will suffice, don't bother
specifying
TPsModBConnection as the parameter type.
As I did not go into the detail but TPsModBConnection is an abstract class.


I am digesting your recommendations and trying to determine if they are
applicable given my vague explanation of my problem.

Thank you.

Best regards

Paul Hectors


"Sean Dockery" <usenet (AT) sbdconsultants (DOT) com> wrote

Quote:
I, too, share Wayne's concern that it looks like your simply doing
procedural programming in an OO language.

If your only concern is the code duplication in the various class
procedures, you can extract a parameterized procedure like this...

class procedure TB1000Procedures.StartTest(const AB1000ID: word;
const ATestPwd: string);
begin
ParameterizedStartTest(TPsB1000ConnectionMgr,
AB1000ID,
TPsB1kBatteryTest,
ATestPwd);
end;


TPsConnectionMgrClass = class of TPsConnectionMgr;

TPsTest = class(T...)
public
constructor Create(Whatever: Pointer;
Connection: TPsConnection); virtual;
end;

// TPsB1kBatteryTest inherits from TPsTest and override the constructor

TPsTestClass = class of TPsTest;

procedure ParameterizedStartTest(ConnectionMgrClass:
TPsConnectionMgrClass;
ID: Word; TestClass: TPsTestClass; ATestPwd: string);
var
Connection: TPsModBConnection;
// TPsModBConnection assumed to inherit from TPsConnection
begin
ConnectionMgrClass.Singleton.GetConnection(ID, Connection);
try
with TestClass.Create(nil, Connection) do
try
AutomatedPwd := ATestPwd;
Write;
finally
Free;
end;
finally
ConnectionMgrClass.Singleton.ReleaseConnection(Connection);
end;
end;

This would be only the first step. There are a lot of other improvements
to
this code that could be made. For example, if TB1000Procedures shared a
common ancestry with other TXXXProcedures, you could create an abstract
method named GetConnectionMgrClass and GetTestClass. Then your
TB1000Procedures.StartTest method would look like this...

class procedure TB1000Procedures.StartTest(ID: Word; PassWd: string);
begin
ParameterizedStartTest(GetConnectionMgrClass,
ID, GetTestClass, PassWd);
end;

...and because there is nothing specific to TB1000Procedures in that
method,
you could push it up to the common ancestor class. Then each of the
sub-classes need only fulfill two template methods: GetConnectionMgrClass
and GetTestClass. At that point, you may even want to "inline method" the
ParameterizedStartTest method again in the common base class StartTest
method.

Remember that to take advantage of inheritance, you should only expose the
most specialized class that you have to as a parameter in your classes.
That is, if a TPsConnection parameter will suffice, don't bother
specifying
TPsModBConnection as the parameter type.


--
Sean Dockery
[email]sean (AT) sbdconsultants (DOT) com[/email]
Certified Java Web Component Developer
Certified Delphi Programmer
SBD Consultants
http://www.sbdconsultants.com


"Wayne Niddery [TeamB]" <wniddery (AT) chaffaci (DOT) on.ca> wrote in message
news:3fb6ff96 (AT) newsgroups (DOT) borland.com...
Paul Hectors wrote:
In my program I have a singleton that is a connection manager in my
application.
I have a unit that is an API to a hardware device. The API is a unit
that has one class with class functions and class procedures.
These class methods could be standalone functions or procedures.

For every operation required, a connection has to be retrieved from
the Singleton connection manager and when the operation is finished
the connected released.

Below is a typical method:

class procedure TB1000Procedures.StartTest(const AB1000ID: word;const
ATestPwd:string);
var
Connection:TPsModBConnection;
begin
TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,Connection);
try
with TPsB1kBatteryTest.Create(nil,Connection) do
try
AutomatedPwd := ATestPwd;
Write; // command is sent
finally
Free;
end;
finally
TPsB1000ConnectionMgr.Singleton.Release(Connection);
end;

Your overall layout of the classes is not clear. It sounds like you are
resisting the creation of instances of some or all of these. You say the
connection mamanger is a singleton, but I see it has a property *called*
singleton and the connection manager itself appears to have no instance.
Off-hand it looks to me you are making this much more complicated than
it
should be. From what I can see (which is not yet enough really) I would
say
that you should be creating an instance of TB1000Procedures so it can
hold
a
persistent reference to a connection, but perhaps releasing after every
call
is important - is the app multi-threaded?

--
Wayne Niddery - Logic Fundamentals, Inc. (www.logicfundamentals.com)
RADBooks: http://www.logicfundamentals.com/RADBooks.html
"It is error alone which needs the support of government. Truth can
stand by itself." - Thomas Jefferson







Back to top
Wayne Niddery [TeamB]
Guest





PostPosted: Tue Nov 18, 2003 12:09 am    Post subject: Re: is there a better way? Reply with quote

Paul Hectors wrote:
Quote:

The application is multi threaded and problem is in the middle layer
of the system.

Key question: Are the devices themselves thread-safe, or must your code
serialize requests to these devices? I.e.can the device handle getting
concurrent requests?

Quote:
The ConnectionMgr manages connections for a number of devices. The
connection is required to interact with a "B1000" Device, therefore a
solution is required to interface with the "B1000" device.
My answer to that problem is a unit called uB1000Procedures and
contains one class TB1000Procedures with all class methods. Note this
could just as well be a unit with procedures as at the moment all
methods are class methods.

If requests to the B1000 must be serialized, then it makes sense for
TB1000Procedures to be a singleton, however it should still be an instance.
IOW the various methods like StartTest should not be class procedures, but
regular procedures. This would allow the instance to keep a connection to
the actual device instead of having to get one on every call.

Quote:
Maybe this is a possible solution.

Create a class that provides all the interface methods for the "B1000"
Device (TB1000Device). Than have a list that has an instance of
TB1000Device for B1000ID. Just like the Connection Manager has an
instance of a connection for a B1000ID. This TB1000Device list would
be a Singleton just like the Connection Manager and be thread safe.

I don't know why you need a *list* of TB1000Devices if it is going to be a
singleton.

Quote:
Then TB1000Device class could be something like below:

TB1000Device = class(TObject)
private
FConnection:TPsModBConnection;
public
constructor Create(const AB1000ID:integer);virtual;
destructor Destroy;override;

// put all the methods here for the interface to the device
procedure StartTest(const APassword:string);

constructor TB1000Device.Create(const AB1000ID:integer);
begin
inherited Create;

TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,FConnection);
end;

destructor TB1000Device.Destroy;
begin
TPsB1000ConnectionMgr.Singleton.Release(FConnection);

inherited Destroy;
end;

This is exactly right.

--
Wayne Niddery - Logic Fundamentals, Inc. (www.logicfundamentals.com)
RADBooks: http://www.logicfundamentals.com/RADBooks.html
"It is error alone which needs the support of government. Truth can
stand by itself." - Thomas Jefferson



Back to top
Bryan Crotaz
Guest





PostPosted: Tue Nov 18, 2003 1:49 am    Post subject: Re: is there a better way? Reply with quote

I would use a Device singleton per physical device to handle the calls (and
possibly serialise them) to that device.

Then some sort of message class with the params for that message.

So the device has the following declaration:

TMsgProc = procedure (Sender: TObject; Msg: TCustomDeviceMessage);

TCustomDevice = class
procedure SendMessage(Msg: TCustomDeviceMessage);
procedure SendMessageAndWait(Msg: TCustomDeviceMessage; out Reply:
TCustomDeviceMessage);
property OnMsgRx: TMsgProc ...
end;

Then a message could have a method that returns a data block, and all the
device needs to do is know how to send the message data without
understanding the message itself. You could use a class factory to get a
reply message object for an incoming stream. For example the first byte
might tell you which message it is.

I built a system to control a number of golf ball dispensers (I was short of
money, ok?!) over RS485 like this. It worked really well.

Bryan


"Paul Hectors" <paul (AT) pwrshield (DOT) com> wrote

Quote:
Problem
======
I cannot put a certain piece of into an area where it can be re used,
therefore I am having to copy paste a specific piece of code for each
method.

Scenario
======
In my program I have a singleton that is a connection manager in my
application.
I have a unit that is an API to a hardware device. The API is a unit that
has one class with class functions and class procedures.
These class methods could be standalone functions or procedures.

For every operation required, a connection has to be retrieved from the
Singleton connection manager and when the operation is finished the
connected released.

Below is a typical method:

class procedure TB1000Procedures.StartTest(const AB1000ID: word;const
ATestPwd:string);
var
Connection:TPsModBConnection;
begin
TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,Connection);
try
with TPsB1kBatteryTest.Create(nil,Connection) do
try
AutomatedPwd := ATestPwd;
Write; // command is sent
finally
Free;
end;
finally
TPsB1000ConnectionMgr.Singleton.Release(Connection);
end;

end;

Question
======
Every method requires the GetConnection and Release code is there anyway
of
eliminating this duplication of code in each method?

Ideally I could override a method on an object where the connection has
been
obtained and is a private variable of the object and connection is
released
when object is destroyed.
Note all the class method take an ID as a common parameter but the method
signature is different for each method.

The existing design from a use point of view I believe is nice as a single
line of code can send or retrieve information. The use in the above
example
to start a test is TPsB1000Procedures.StartTest(1,'blah blah').

Is there a bettery way?

Thank you for your time.

Best regards,

Paul Hectors





Back to top
Paul Hectors
Guest





PostPosted: Tue Nov 18, 2003 2:12 am    Post subject: Re: is there a better way? Reply with quote

Thank you Wayne for your reply.

For your information the current design works, I would like to refactor it
as I have a lot more functionality to add and could see the duplication in
the TB1000Procedures methods.

"Wayne Niddery [TeamB]" <wniddery (AT) chaffaci (DOT) on.ca> wrote

Quote:
Paul Hectors wrote:

The application is multi threaded and problem is in the middle layer
of the system.

Key question: Are the devices themselves thread-safe, or must your code
serialize requests to these devices? I.e.can the device handle getting
concurrent requests?
The requests to the B1000 device are serialised by classes that use the

given connection. These classes are used with a TB1000Procedure method.

Quote:
The ConnectionMgr manages connections for a number of devices. The
connection is required to interact with a "B1000" Device, therefore a
solution is required to interface with the "B1000" device.
My answer to that problem is a unit called uB1000Procedures and
contains one class TB1000Procedures with all class methods. Note this
could just as well be a unit with procedures as at the moment all
methods are class methods.

If requests to the B1000 must be serialized, then it makes sense for
TB1000Procedures to be a singleton, however it should still be an
instance.
IOW the various methods like StartTest should not be class procedures, but
regular procedures. This would allow the instance to keep a connection to
the actual device instead of having to get one on every call.
Ok, as I mentioned before the TB1000Procedures class method can be standard

procedures.
The problem with my architecture though is that within each procedure I am
having to reproduce the getconnection and release connection code.

So I guess the trade of is, I either use the standalone procedures or use my
possible solution of TB1000Device class.

"Start Test" Example
=============
signature of the StartTest method is
StartTest(const AB1000ID:const APassword:string);

B1000ID = 1
Password = 'BlahBlah'

Procedural architecture usage:

StartTest(1,'BlahBlah');

Possible solution mentioned below usage:
var
Device:TB1000Device;
begin
Device := TB1000Device.create(1);
try
Device.StartTest('BlahBlah');
finally
FreeAndNil(Device);
end;
end;

Ideal solution in my opinion:
TB1000DeviceCache.Singleton.Items[1].StartTest('BlahBlah'); // cache
would have to be treadsafe.
// The cache would hold a TB1000Device object for each B1000ID

Is my possible solution good enough?
Is the ideal solution possible?
Or is my ideal solution a bad idea?

Quote:

Maybe this is a possible solution.

Create a class that provides all the interface methods for the "B1000"
Device (TB1000Device). Than have a list that has an instance of
TB1000Device for B1000ID. Just like the Connection Manager has an
instance of a connection for a B1000ID. This TB1000Device list would
be a Singleton just like the Connection Manager and be thread safe.

I don't know why you need a *list* of TB1000Devices if it is going to be a
singleton.
The list idea I had was to create a cache so you do not have to create and

destroy the TB1000Device objects, I realised shortly after sending the post
that this will not work with the mentioned TB1000Device.

I have not figured out a way, but ideally if I could create a cache of
TB1000Devices than this would save the create and destroy code but I do not
know where to put the get connection and release connection. ( I am talking
about my "Ideal Solution" in the example StartTest above)
I would need a TB1000Device design that for a method call on TB1000Device it
would wrap the get connection and release connection around the method. Also
if multipe calls were made you could have the option to control the get
connection and release connection for that situation.

Quote:

Then TB1000Device class could be something like below:

TB1000Device = class(TObject)
private
FConnection:TPsModBConnection;
public
constructor Create(const AB1000ID:integer);virtual;
destructor Destroy;override;

// put all the methods here for the interface to the device
procedure StartTest(const APassword:string);

constructor TB1000Device.Create(const AB1000ID:integer);
begin
inherited Create;

TPsB1000ConnectionMgr.Singleton.GetConnection(AB1000ID,FConnection);
end;

destructor TB1000Device.Destroy;
begin
TPsB1000ConnectionMgr.Singleton.Release(FConnection);

inherited Destroy;
end;

This is exactly right.

--
Wayne Niddery - Logic Fundamentals, Inc. (www.logicfundamentals.com)
RADBooks: http://www.logicfundamentals.com/RADBooks.html
"It is error alone which needs the support of government. Truth can
stand by itself." - Thomas Jefferson


Thank you for your time.

Best regards

Paul Hectors




Back to top
paul hectors
Guest





PostPosted: Tue Nov 18, 2003 8:09 am    Post subject: Re: is there a better way? Reply with quote

Thank you for your reply.

"Bryan Crotaz" <bryan@%nospam%ivisionsystems.com> wrote

Quote:
I would use a Device singleton per physical device to handle the calls
(and
possibly serialise them) to that device.
Interesting, why not make a Device Cache/ Device Manager that holds an

instance for each device and therefore centralising the management of the
Devices rather than having a large amount of Singletons ?

Quote:

Then some sort of message class with the params for that message.

So the device has the following declaration:

TMsgProc = procedure (Sender: TObject; Msg: TCustomDeviceMessage);

TCustomDevice = class
procedure SendMessage(Msg: TCustomDeviceMessage);
procedure SendMessageAndWait(Msg: TCustomDeviceMessage; out Reply:
TCustomDeviceMessage);
property OnMsgRx: TMsgProc ...
end;

Then a message could have a method that returns a data block, and all the
device needs to do is know how to send the message data without
understanding the message itself. You could use a class factory to get a
reply message object for an incoming stream. For example the first byte
might tell you which message it is.
Sounds very interesting and I will keep this in mind for future projects.

Unfortunately the protocol that I have to work with I do not think will
allow that kind of design.
I have asked a question about a specific part of the application, the
application does support a certain level of functionality and the
communication part I believe / hope is not too bad. I have tried to
encapsulate the communication part of the design and the TB1000Procedures
class I mentioned in my question is unaware of the details of protocol or
the exact type of device it is talking too. The TB1000Procedures class is
there to retrieve or send information that is at a business logic type
level, at a lower level this is converted to the specific format.

Quote:
I built a system to control a number of golf ball dispensers (I was short
of
money, ok?!) over RS485 like this. It worked really well.
Sounds like my kind of project Smile

I think things get more interesting when you have to deal with some kind of
hardware device even if it is a golf ball dispenser :-)

Best regards

Paul Hectors



Back to top
Bryan Crotaz
Guest





PostPosted: Tue Nov 18, 2003 11:24 am    Post subject: Re: is there a better way? Reply with quote

Quote:
Interesting, why not make a Device Cache/ Device Manager that holds an
instance for each device and therefore centralising the management of the
Devices rather than having a large amount of Singletons ?

You probably could. The Device manager can be responsible for creating the
singletons when necessary.

Bryan



Back to top
paul hectors
Guest





PostPosted: Wed Nov 19, 2003 10:11 am    Post subject: Re: is there a better way? Reply with quote

Thank you Bryan.

"Bryan Crotaz" <bryan@%nospam%ivisionsystems.com> wrote

Quote:
Interesting, why not make a Device Cache/ Device Manager that holds an
instance for each device and therefore centralising the management of
the
Devices rather than having a large amount of Singletons ?

You probably could. The Device manager can be responsible for creating
the
singletons when necessary.

Bryan





Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.