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 

Structure Question
Goto page 1, 2  Next
 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design
View previous topic :: View next topic  
Author Message
Jeffrey A. Wormsley
Guest





PostPosted: Mon Feb 14, 2005 10:36 pm    Post subject: Structure Question Reply with quote



I need a bit of advice on how to structure a piece of code making use of
Design Patterns. I've read the GoF book and many papers available on the
web, but am having trouble assimilating all of this into a real world
application. Right now, I am trying to start small (the description won't
seem small, I suppose, but compared to the apps this is a common component
of, it is tiny), so I'm not looking into persistence issues, or even
business rules.

Here's the background:

All of my apps deal with stored value payment cards. These cards can be
rewritable magnetic stripes, or microprocessor based chip cards. There are
three classes of devices that can read these cards. One is a serial device
that can only handle magnetic stripe cards, one is a serial device that can
only handle chip cards, and the other is a PCSC device for chip cards. The
serial mag card device has a small set of functions (read whole card,
format whole card, add value to card, deduct value from card, check for
card present, eject card from reader). The other two, while very different
internally, can map to the same interface at a fairly low level. The
functions include check for card present, check for card powered up, send
data to the card, read data from the card, verify card security codes,
power up the card, power down the card.

The cards themselves can have zero to two purses (and future cards may have
more). Each purse can be of a different type, with different fields. The
magnetic stripe card can only have zero or one purse, and if it has a
purse, it can only be one of two types, and this will never change, as
these cards are being depricated. The current chip cards can have zero to
two purses, and the first if present can only be of one type, and the
second if present can only be one of two types (so far). The second purse
cannot exist independent of the first. Cards with no purses can be either
unused ("blank") or special purpose cards, of which there are about 45,
which only share a couple of fields (a flag that identifies them as a
special purpose card and a field to define which one). Only about half of
the special purpose cards can be magnetic stripe cards, and the data for
them is different than that of the chip card equivalents. For now, I am
ignoring all of the special function cards, concentrating on cards that are
blank or that have one or more purses.

At the highest level, I want to write an app that can use any of the card
readers and create, read and modify any of the purses on any of the cards.
Later I want to expand this to create, read and modify the special function
cards.

Some of the objects I believe I will need are as follows:

TSerialChipCardReader
TPcscChipCardReader
TChipCardReader
TSerialMagCardReader
TChipCard
TChipCardPurseType1
TChipCardPurseType2
TChipCardPurseType3
TMagCard
TMagCardPurseType1
TMagCardPurseType2

This is where things get hard. At the very first run of the application, I
want to have the software figure out which card reader to use (I only want
one at any time - a Singleton TCardReader). Enumerating the attached PCSC
readers is quick. Enumerating the COM ports on the machine for the serial
readers is quick. Checking the serial port to see if there is a reader
attached, and which kind, is very slow. As a result, I would prefer on
first load to present a list that has the PCSC readers and COM ports, and
if they select a COM port, then I'll test to see which serial reader, if
any, is attached. I'll store the selection (if it is valid) so the next
time they load the app, I'll automatically try that. If it doesn't work,
I'll go back to the state from the first load and have the user select.
The problem with this, though, is the PCSC reader. You have to instantiate
an instance of the PCSCReader object to get the list of readers. So that
will be a temporary object, not the final object I will (may) use.

For the reader, I presume this will use the Factory pattern. I am not sure
how that will need to be coded, though, considering the fact that I need a
run time list to determine what readers are available (or potentially
available, for serial readers). Then, once I have a Reader, that reader
will determine what type of cards I can have. When a Reader gets a Card
(checked with the appropriate card present function), something (???) will
initiate a Read function. That Read function will then read the various
bits required to determine the type of the card (blank, card with purse, or
special function), and I presume pass that to a Card Factory to return a
Card object. Then this Card Object will be responsible for reading more
data and determining which purses (if any) are available, and use a Purse
Factory to create them, and then each Purse will read the data that
completes the process. Or at least that's what I thought, but I am running
into serious difficulties here, because how things are read are different
depending on the reader, and what is read is different depending on the
card, so I am having real trouble visualizing how all of this interacts.
One thing I do know is that a TChipCardPurseType2 must use a TChipCard
object, and a TChipCard object must use a TChipCardReader. I am not sure
if a TChipCardReader needs to be an abstract class that can be created with
a TSerialChipCardReader or TPcscChipCardReader, or if it needs to be a
Facade that hides one or the other, or if there is another pattern I am
missing.

Once I know the card type and purse types (if any), I can create UI objects
to interact with them. But here, I have another problem. For instance, if
I have a card with TChipCardPurseType2 in the second purse, I should be
able to change it to a TChipCardPurseType3. Or, if I have a blank card, I
should be able to add a TChipCardPurseType1 and then perhaps a
TChipCardPurseType2 (remember the rules don't allow a second purse unless
the first exists, and the first can only be a TChipCardPurseType1).

At any rate, I am not looking for someone to design the whole class
heiarchy for me. What I'm more interested in is if anyone can look at the
description and tell me where I am making the wrong choices, or if the
right choices, things I should look out for or take advantage of to make my
life easier. As I said, the rest of the apps, which all share this same
segment, are much more complicated, but if I can get this part covered, I
think I'll be ready to tackle the rest (well, the OPF might be another
issue, and this will eventually have an interaction, since one of the goals
is to be able to show the state of any Card at any time).

Jeff.
Back to top
Joanna Carter (TeamB)
Guest





PostPosted: Tue Feb 15, 2005 9:52 am    Post subject: Re: Structure Question Reply with quote



"Jeffrey A. Wormsley" <jwormsley (AT) nospam (DOT) debitek.com> a écrit dans le message
de news: Xns95FDB30F6221jwormsleyatdebitekdo (AT) 207 (DOT) 105.83.66...

Quote:
I need a bit of advice on how to structure a piece of code making use of
Design Patterns. I've read the GoF book and many papers available on the
web, but am having trouble assimilating all of this into a real world
application. Right now, I am trying to start small (the description won't
seem small, I suppose, but compared to the apps this is a common component
of, it is tiny), so I'm not looking into persistence issues, or even
business rules.

Jeff, I will make some comments and suggest some classes as I meander
through your post :-)

Quote:
Here's the background:

All of my apps deal with stored value payment cards.

TPaymentCard

Quote:
These cards can be rewritable magnetic stripes, or microprocessor based
chip cards.


TPaymentCard
--TMagStripeCard
--TChipCard

Quote:
There are three classes of devices that can read these cards. One is a
serial device
that can only handle magnetic stripe cards, one is a serial device that
can
only handle chip cards, and the other is a PCSC device for chip cards.

Separate out the protocol from the reading...

TProtocol
--TSerialProtocol
--TPcscProtocol

Use a delegate Protocol object inside whichever of your Reader classes needs
it...

TCardReader
--TMagStripeReader
--TChipReader

Quote:
The serial mag card device has a small set of functions (read whole card,
format whole card, add value to card, deduct value from card, check for
card present, eject card from reader). The other two, while very
different
internally, can map to the same interface at a fairly low level. The
functions include check for card present, check for card powered up, send
data to the card, read data from the card, verify card security codes,
power up the card, power down the card.

Is the function set common enough to make it virtual in the base
TCardReader?

Quote:
The cards themselves can have zero to two purses (and future cards may
have
more). Each purse can be of a different type, with different fields. The
magnetic stripe card can only have zero or one purse, and if it has a
purse, it can only be one of two types, and this will never change, as
these cards are being depricated.

The current chip cards can have zero to
two purses, and the first if present can only be of one type, and the
second if present can only be one of two types (so far). The second purse
cannot exist independent of the first. Cards with no purses can be either
unused ("blank") or special purpose cards, of which there are about 45,
which only share a couple of fields (a flag that identifies them as a
special purpose card and a field to define which one). Only about half of
the special purpose cards can be magnetic stripe cards, and the data for
them is different than that of the chip card equivalents. For now, I am
ignoring all of the special function cards, concentrating on cards that
are
blank or that have one or more purses.

Possibly separate out the 'field' concept as it is variable in ordinality...

TPurseField

Then include a list of TPurseFields in the appropriate Purse classes

TPurse
--TChipPurse
--TMagStripePurse

You client code should check for the existence of Purses on the Card and can
iterate through them, doing whatever operations are necessary.

If you envisage adding future operations to Purses, then the Visitor pattern
may help as it allows you to add common functionality to all the Purse
subclasses without altering the Purse classes themselves.

The same Visitor pattern may also help with dealing with different Card
functionality; although inappropriate use of the Visitor pattern can lead to
problems in itself.

Quote:
This is where things get hard. At the very first run of the application,
I
want to have the software figure out which card reader to use (I only want
one at any time - a Singleton TCardReader).

<snip>

Quote:
Or at least that's what I thought, but I am running
into serious difficulties here, because how things are read are different
depending on the reader, and what is read is different depending on the
card, so I am having real trouble visualizing how all of this interacts.
One thing I do know is that a TChipCardPurseType2 must use a TChipCard
object, and a TChipCard object must use a TChipCardReader. I am not sure
if a TChipCardReader needs to be an abstract class that can be created
with
a TSerialChipCardReader or TPcscChipCardReader, or if it needs to be a
Facade that hides one or the other, or if there is another pattern I am
missing.

This all sounds more and more like a Visitor would be useful...

TCardVisitor
Operation1
Operation2
Operation_n
...

TPurseVisitor
Operation1
Operation2
Operation_n
...

Quote:
Once I know the card type and purse types (if any), I can create UI
objects
to interact with them. But here, I have another problem. For instance,
if
I have a card with TChipCardPurseType2 in the second purse, I should be
able to change it to a TChipCardPurseType3. Or, if I have a blank card, I
should be able to add a TChipCardPurseType1 and then perhaps a
TChipCardPurseType2 (remember the rules don't allow a second purse unless
the first exists, and the first can only be a TChipCardPurseType1).

You should not be using inheritance; instead use Composition to contain as
many Purses of whatever type you want in any Card.

Please feel free to tear these ideas apart, a good (reasoned) argument
really is the best way to find the right answer :-)

Joanna

--
Joanna Carter (TeamB)

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



Back to top
Jeffrey A. Wormsley
Guest





PostPosted: Tue Feb 15, 2005 3:38 pm    Post subject: Re: Structure Question Reply with quote



"Joanna Carter (TeamB)" <joanna (AT) nospam (DOT) co.uk> wrote in
news:4211c67a$1 (AT) newsgroups (DOT) borland.com:

Quote:
Jeff, I will make some comments and suggest some classes as I meander
through your post Smile

Thanks, Joanna! I need a little time to digest things a bit. I'm not sure
exactly where I am going with this, but I am at one of those rare points
that I have time to think rather than do.

Jeff.

Back to top
Martin James
Guest





PostPosted: Tue Feb 15, 2005 5:47 pm    Post subject: Re: Structure Question Reply with quote


Quote:
This is where things get hard. At the very first run of the application,
I
want to have the software figure out which card reader to use (I only want
one at any time - a Singleton TCardReader). Enumerating the attached PCSC
readers is quick. Enumerating the COM ports on the machine for the serial
readers is quick. Checking the serial port to see if there is a reader
attached, and which kind, is very slow. As a result, I would prefer on
first load to present a list that has the PCSC readers and COM ports, and
if they select a COM port, then I'll test to see which serial reader, if
any, is attached. I'll store the selection (if it is valid) so the next
time they load the app, I'll automatically try that. If it doesn't work,
I'll go back to the state from the first load and have the user select.
The problem with this, though, is the PCSC reader. You have to
instantiate
an instance of the PCSCReader object to get the list of readers. So that
will be a temporary object, not the final object I will (may) use.

When I see apps like this, I start thinking 'layers' :)

Can you perform all this checking-for-readers in parallel? This is
certainly possible for the COM ports. There has to be a sensible max. no of
COM ports - if it was me, I would create tihs number of COM port
checkers/drivers & just leave them running, repeating the check every 10 sec
or so, for ever until they find one.

Perhaps you can do something similar with the PCSC reader. I am not
familiar with this protocol/interface, so I don't know. Maybee you can
instantiate one thread with a PCSCReader that does the interation &
checking, creating a list of those readers, then create an seperate 'driver'
for each PCSCReader.

If any of the reader-checkers finds a valid card reader attached to its
serial port, or has auccessfully opened its own PCSCReader, it can assemble
a TcardReader of the appropriate class, together with an interface to the
driver & post it to the next layer up. There you can keep your list of card
readers.

This cuts config time down to that of the slowest serial port at worst, with
next-to-no slowdown of detecting/checking the fastest reader/s.

The 'drivers' can themselves do stuff like occasionally polling their card
readers to check they are still there.

layer 2 would have this list of valid TcardReaders, each containig an
interface to its own driver. If you want to select one of these for use,
you can copy its reference into a 'currentReader' field/variable & discard
any messages from level 1 that are not from this readers driver.

Quote:
For the reader, I presume this will use the Factory pattern. I am not
sure
how that will need to be coded, though, considering the fact that I need a
run time list to determine what readers are available (or potentially
available, for serial readers). Then, once I have a Reader, that reader
will determine what type of cards I can have. When a Reader gets a Card
(checked with the appropriate card present function), something (???) will
initiate a Read function.

Level 1 driver thread should get a 'card inserted mnessage from its
port/PCSCReader

Quote:
That Read function will then read the various
bits required to determine the type of the card (blank, card with purse,
or
special function), and I presume pass that to a Card Factory to return a
Card object. Then this Card Object will be responsible for reading more
data and determining which purses (if any) are available, and use a Purse
Factory to create them, and then each Purse will read the data that
completes the process. Or at least that's what I thought, but I am
running
into serious difficulties here, because how things are read are different
depending on the reader

Do all the possible reader classes provide a byte stream? The serial reader
certainly will - it's like reading a file.

, and what is read is different depending on the
Quote:
card, so I am having real trouble visualizing how all of this interacts.

If a byte stream is coming in, I would be tempted to create a Tcard instance
that has a 'processChar' function & have the driver push
one-byte-afer-another into it until the functioin returns 'true'. The Tcard
could then have its TcardReader instance loaded into it & be posted off to
layer 2, where it can be delivered to ...whatever.


Quote:
One thing I do know is that a TChipCardPurseType2 must use a TChipCard
object, and a TChipCard object must use a TChipCardReader. I am not sure
if a TChipCardReader needs to be an abstract class that can be created
with
a TSerialChipCardReader or TPcscChipCardReader, or if it needs to be a
Facade that hides one or the other, or if there is another pattern I am
missing.

Hmm.. I'll leave that to an expert - I see that Joanna has already replied
:)

Quote:
Once I know the card type and purse types (if any), I can create UI
objects
to interact with them. But here, I have another problem. For instance,
if
I have a card with TChipCardPurseType2 in the second purse, I should be
able to change it to a TChipCardPurseType3. Or, if I have a blank card, I
should be able to add a TChipCardPurseType1 and then perhaps a
TChipCardPurseType2 (remember the rules don't allow a second purse unless
the first exists, and the first can only be a TChipCardPurseType1).

Joanna!

Quote:
At any rate, I am not looking for someone to design the whole class
heiarchy for me. What I'm more interested in is if anyone can look at the
description and tell me where I am making the wrong choices, or if the
right choices, things I should look out for or take advantage of to make
my
life easier.

Well, if you wnat flexibility & performance, you need to perform some tasks
in parallel. I sounds like that at least checking/reading/writing to the
readers can be separated out into an automomous, asynchronous lower layer.

Quote:
As I said, the rest of the apps, which all share this same
segment, are much more complicated, but if I can get this part covered, I
think I'll be ready to tackle the rest (well, the OPF might be another
issue, and this will eventually have an interaction, since one of the
goals
is to be able to show the state of any Card at any time).

Heh! This is a good reason for going for flexibility. Layer 2 could be
visual. Pernaps a stringGrid showing all readers, their currently inserted
cards, their purses and contents.and ongoing transactions. This would be
easily updated as messages come in from level 1 and level 3. Level 3 would
be where transactions with cards are initiated & handle the results returned
later from L2. Sound like layer 2 could best be done in th emain thread,
since it's mainly displaying data. Joanna will probably recommend detaching
the data from the display - that's fine.by me :)

Rgds,
Martin









Back to top
Bryan Crotaz
Guest





PostPosted: Wed Feb 16, 2005 5:09 pm    Post subject: Re: Structure Question Reply with quote

Quote:
TPaymentCard
--TMagStripeCard
--TChipCard

I disagree.
Payment cards are all equivalent:

TPaymentCard ----- * TPurse

The access to the physical card is different depending on the type of card,
so have a TCardReader and TCardWriter class which is instantiated when you
need to read or write the card. This can in turn delegate to a TProtocol
class for different manufacturers' cards.

I agree with the rest though. Composition is much better than inheritance
here, especially as you know the real world will change continuously.

I would recommend a factory class rather than hard coded compositions, so
you can easily register new forms of card, reader or protocol.

Bryan

Quote:

There are three classes of devices that can read these cards. One is a
serial device
that can only handle magnetic stripe cards, one is a serial device that
can
only handle chip cards, and the other is a PCSC device for chip cards.

Separate out the protocol from the reading...

TProtocol
--TSerialProtocol
--TPcscProtocol

Use a delegate Protocol object inside whichever of your Reader classes
needs
it...

TCardReader
--TMagStripeReader
--TChipReader

The serial mag card device has a small set of functions (read whole
card,
format whole card, add value to card, deduct value from card, check for
card present, eject card from reader). The other two, while very
different
internally, can map to the same interface at a fairly low level. The
functions include check for card present, check for card powered up,
send
data to the card, read data from the card, verify card security codes,
power up the card, power down the card.

Is the function set common enough to make it virtual in the base
TCardReader?

The cards themselves can have zero to two purses (and future cards may
have
more). Each purse can be of a different type, with different fields.
The
magnetic stripe card can only have zero or one purse, and if it has a
purse, it can only be one of two types, and this will never change, as
these cards are being depricated.

The current chip cards can have zero to
two purses, and the first if present can only be of one type, and the
second if present can only be one of two types (so far). The second
purse
cannot exist independent of the first. Cards with no purses can be
either
unused ("blank") or special purpose cards, of which there are about 45,
which only share a couple of fields (a flag that identifies them as a
special purpose card and a field to define which one). Only about half
of
the special purpose cards can be magnetic stripe cards, and the data for
them is different than that of the chip card equivalents. For now, I am
ignoring all of the special function cards, concentrating on cards that
are
blank or that have one or more purses.

Possibly separate out the 'field' concept as it is variable in
ordinality...

TPurseField

Then include a list of TPurseFields in the appropriate Purse classes

TPurse
--TChipPurse
--TMagStripePurse

You client code should check for the existence of Purses on the Card and
can
iterate through them, doing whatever operations are necessary.

If you envisage adding future operations to Purses, then the Visitor
pattern
may help as it allows you to add common functionality to all the Purse
subclasses without altering the Purse classes themselves.

The same Visitor pattern may also help with dealing with different Card
functionality; although inappropriate use of the Visitor pattern can lead
to
problems in itself.

This is where things get hard. At the very first run of the
application,
I
want to have the software figure out which card reader to use (I only
want
one at any time - a Singleton TCardReader).

snip

Or at least that's what I thought, but I am running
into serious difficulties here, because how things are read are
different
depending on the reader, and what is read is different depending on the
card, so I am having real trouble visualizing how all of this interacts.
One thing I do know is that a TChipCardPurseType2 must use a TChipCard
object, and a TChipCard object must use a TChipCardReader. I am not
sure
if a TChipCardReader needs to be an abstract class that can be created
with
a TSerialChipCardReader or TPcscChipCardReader, or if it needs to be a
Facade that hides one or the other, or if there is another pattern I am
missing.

This all sounds more and more like a Visitor would be useful...

TCardVisitor
Operation1
Operation2
Operation_n
...

TPurseVisitor
Operation1
Operation2
Operation_n
...

Once I know the card type and purse types (if any), I can create UI
objects
to interact with them. But here, I have another problem. For instance,
if
I have a card with TChipCardPurseType2 in the second purse, I should be
able to change it to a TChipCardPurseType3. Or, if I have a blank card,
I
should be able to add a TChipCardPurseType1 and then perhaps a
TChipCardPurseType2 (remember the rules don't allow a second purse
unless
the first exists, and the first can only be a TChipCardPurseType1).

You should not be using inheritance; instead use Composition to contain as
many Purses of whatever type you want in any Card.

Please feel free to tear these ideas apart, a good (reasoned) argument
really is the best way to find the right answer :-)

Joanna

--
Joanna Carter (TeamB)

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





Back to top
Joanna Carter (TeamB)
Guest





PostPosted: Wed Feb 16, 2005 5:21 pm    Post subject: Re: Structure Question Reply with quote

"Bryan Crotaz" <bryan (AT) no (DOT) spam.for.me.please.inspirationmatters.com> a écrit
dans le message de news: 42137e4b$1 (AT) newsgroups (DOT) borland.com...

Quote:
I disagree.
Payment cards are all equivalent:

TPaymentCard ----- * TPurse

Just as feasible, add it to the pot and stir well Smile)

Quote:
The access to the physical card is different depending on the type of
card,
so have a TCardReader and TCardWriter class which is instantiated when
you
need to read or write the card. This can in turn delegate to a TProtocol
class for different manufacturers' cards.

I agree with the rest though. Composition is much better than inheritance
here, especially as you know the real world will change continuously.

I would recommend a factory class rather than hard coded compositions, so
you can easily register new forms of card, reader or protocol.

Interesting and good ideas

Joanna

--
Joanna Carter (TeamB)

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



Back to top
Bryan Crotaz
Guest





PostPosted: Wed Feb 16, 2005 6:06 pm    Post subject: Re: Structure Question Reply with quote

Quote:
I would recommend a factory class rather than hard coded compositions,
so
you can easily register new forms of card, reader or protocol.

Mind you this can get complex very quickly if you want to get abstract about
it. My serial controller code has 39 base classes! Though it now only
takes about 20 minutes to implement a new protocol.

Bryan



Back to top
Bryan Crotaz
Guest





PostPosted: Wed Feb 16, 2005 6:12 pm    Post subject: Re: Structure Question Reply with quote

Quote:
I would recommend a factory class rather than hard coded compositions, so
you can easily register new forms of card, reader or protocol.

Use the same factory to register forms for each data object so that you can
call

View(ParentWinControl, Purse);

or

View(ParentWinControl, Card); // which internally calls View(purse) to
build a tabbed list of the purses?

Now your factory startup can be as simple as

Factory.Register('Tesco Clubcard', TMagStripeReader, TMagStripeWriter,
[PurseType1, PurseType4]);
Factory.RegisterViewer('Tesco Clubcard', TescoClubcardForm);
Factory.RegisterViewer(PurseType1, Purse1Form);
Factory.RegisterViewer(PurseType2, Purse2Form);
Factory.RegisterViewer(PurseType3, Purse3Form);
Factory.RegisterViewer(PurseType4, Purse4Form);

Bryan



Back to top
Jeffrey A. Wormsley
Guest





PostPosted: Thu Feb 17, 2005 5:09 pm    Post subject: Re: Structure Question Reply with quote

"Bryan Crotaz" <bryan (AT) no (DOT) spam.for.me.please.inspirationmatters.com>
wrote in news:42138d19 (AT) newsgroups (DOT) borland.com:

Quote:
Use the same factory to register forms for each data object so that
you can call

View(ParentWinControl, Purse);

or

View(ParentWinControl, Card); // which internally calls View(purse)
to build a tabbed list of the purses?

Now your factory startup can be as simple as

Factory.Register('Tesco Clubcard', TMagStripeReader, TMagStripeWriter,
[PurseType1, PurseType4]);
Factory.RegisterViewer('Tesco Clubcard', TescoClubcardForm);
Factory.RegisterViewer(PurseType1, Purse1Form);
Factory.RegisterViewer(PurseType2, Purse2Form);
Factory.RegisterViewer(PurseType3, Purse3Form);
Factory.RegisterViewer(PurseType4, Purse4Form);

Now this is where I will need a lot of study. Having a generic factory
class such as this is something I have never attempted, and frankly all of
the examples/white papers/tutorials I have seen on the subject leave me
quite confused. Couple that with the fact that my "veiwers" are also
"editors", at least for some of the fields (there are some fixed fields, at
least in the chipcard types), and I am really lost. I believe some form of
MVC or MVP would be used, but going from concept to implementation is a
very large gap, much like saying "I will write a book" versus actually
writing one.

At any rate, I have a working application that I am modifying piece by
piece to implement these concepts. While it might not be advisable to mix
approaches in general, at least for this application (an internal utility
that will never leave my PC, much less the building), it helps to identify
a concrete subsection that can be split off and worked on independently of
the rest. So far, I am sticking to the smaller items, such as (simple)
persistence of user settings. For example, the reader selection has an
observer that is notified of a changed selection, and stores the selection
in an INI (for now). Not sure how that is supposed to work in reverse,
though. Should the INI (or whatever persistence is used in the future) also
have an observer so the control will know when its data changes (and this
is really only relevant at startup so the control will know the initial
value to select)?

I assume the factory described above would be responsible for making these
relationships? If so, I don't see how that would work. If not, how are
these things hooked up? Ideally, I think I need Purse objects observed by
GUI controls to display the data, commands from the GUI to update the Purse
objects, and some mechanism (most likely another GUI element and associated
command) to commit those changes (ie. write the Purse to the card) or
abandon them. If I can extrapolate the XML/CSV editor example I read last
week, this would involve Mementos to store the chain of actions, would it
not? So here I have many layers and interactions, each in and of itself
simple enough, but managing this looks to be a huge problem (in my
unaccustomed eyes). I can't see how to make these connections without lots
of tedious and mistake prone code. How can I ensure each command is
registered to do its thing, each observer is observing its data, etc?

Thanks for letting me sound out my ideas and questions. I appreciate all
the (excellent) advice.

Jeff.

Back to top
Bryan Crotaz
Guest





PostPosted: Fri Feb 18, 2005 5:27 pm    Post subject: Re: Structure Question Reply with quote


"Jeffrey A. Wormsley" <jwormsley (AT) nospam (DOT) debitek.com> wrote

Quote:
"Bryan Crotaz" wrote in news:42138d19 (AT) newsgroups (DOT) borland.com:

Use the same factory to register forms for each data object so that
you can call

View(ParentWinControl, Purse);

or

View(ParentWinControl, Card); // which internally calls View(purse)
to build a tabbed list of the purses?

Now your factory startup can be as simple as

Factory.Register('Tesco Clubcard', TMagStripeReader, TMagStripeWriter,
[PurseType1, PurseType4]);
Factory.RegisterViewer('Tesco Clubcard', TescoClubcardForm);
Factory.RegisterViewer(PurseType1, Purse1Form);
Factory.RegisterViewer(PurseType2, Purse2Form);
Factory.RegisterViewer(PurseType3, Purse3Form);
Factory.RegisterViewer(PurseType4, Purse4Form);

Now this is where I will need a lot of study. Having a generic factory
class such as this is something I have never attempted

Do it the easy way:

TEditFormRegRecord = class
ObjectClass: TClass;
FormClass: TClass;
public
CreateForm: TForm;
end;

TFactory
FRegForms: TObjectList; // contains TEditFormRegRecords
public
RegisterForm(ObjectClass, FormClass: TClass); // creates a new
TEditFormRegRecord
CreateForm(ObjectClass: TClass): TForm; // iterate FRegForms to find the
right one then call record.CreateForm
ShowForm(Parent: TWinControl; ObjectClass: TClass): TForm; // call
CreateForm then set its parent
end;


Now your form can descend form a base form with a pointer to the edited
object:

TPurseForm = class(TForm)
public
property Purse: TPurse read FPurse write FPurse;
end;

So when you show a purse you can do

procedure EditPurse(Purse: TPurse);
var
PurseForm: TPurseForm;
begin
PurseForm := Factory.ShowForm(PursePanel, Purse.ClassType) as TPurseForm;
PurseForm.Purse := Purse;
end;

Now your purse form can do whatever it likes to the purse.
Different registered purse forms can make assumptions about the type of the
purse as they'd been registered for that type and will only get shown if the
purse is the right sort. So they can have the right edit controls etc.

Does that help?

Bryan






Back to top
Jeffrey A. Wormsley
Guest





PostPosted: Fri Feb 18, 2005 9:52 pm    Post subject: Re: Structure Question Reply with quote

"Bryan Crotaz" <bryan (AT) no (DOT) spam.for.me.please.inspirationmatters.com>
wrote in news:42162572 (AT) newsgroups (DOT) borland.com:

Quote:
Now your purse form can do whatever it likes to the purse.
Different registered purse forms can make assumptions about the type
of the purse as they'd been registered for that type and will only get
shown if the purse is the right sort. So they can have the right edit
controls etc.

Does that help?

Not exactly, but I think I get the picture. I wouldn't make a full form
for each purse (one card may have two purses, possibly more in the future),
as it would completely clutter the UI, but this method would be the same
for TPanels or some other control. I take it, though, if I needed to
create some other type of object or UI element, I'd have another factory
just for that type?

Still, this is beyond where I am now. I'm archiving these suggestions,
though, and hopefully in a few weeks will be able to come back and see
where my understanding and your explanation meets.

Jeff.

Back to top
Bryan Crotaz
Guest





PostPosted: Mon Feb 21, 2005 11:00 pm    Post subject: Re: Structure Question Reply with quote

Quote:
Not exactly, but I think I get the picture. I wouldn't make a full form
for each purse (one card may have two purses, possibly more in the
future),
as it would completely clutter the UI, but this method would be the same
for TPanels or some other control. I take it, though, if I needed to
create some other type of object or UI element, I'd have another factory
just for that type?

Use a form as you might use a frame (but much easier to use a form).

ie

Form := TPurseForm.Create(Panel);
Form.Parent := Panel;
Form.Align := alClient;
// set the form borders however you want here

Bryan



Back to top
Rolf van der Toorn
Guest





PostPosted: Tue Feb 22, 2005 8:44 am    Post subject: Re: Structure Question Reply with quote

Bryan Crotaz wrote:


Quote:
Use a form as you might use a frame (but much easier to use a form).

ie

Form := TPurseForm.Create(Panel);
Form.Parent := Panel;
Form.Align := alClient;
// set the form borders however you want here

Bryan

What is the reason you think forms are easier to use then Frames?
The form has some unused overhead when used like this.
We use the frames pretty much as described here (from a factory with
registration, etc). We have found no limiting restrictions in using
frames.

regards Rolf van der Toorn

Back to top
Bryan Crotaz
Guest





PostPosted: Tue Feb 22, 2005 1:11 pm    Post subject: Re: Structure Question Reply with quote


"Rolf van der Toorn" <rolfvandertoorn (AT) hotmail (DOT) com> wrote

Quote:
Bryan Crotaz wrote:


Use a form as you might use a frame (but much easier to use a form).

ie

Form := TPurseForm.Create(Panel);
Form.Parent := Panel;
Form.Align := alClient;
// set the form borders however you want here

Bryan

What is the reason you think forms are easier to use then Frames?
The form has some unused overhead when used like this.
We use the frames pretty much as described here (from a factory with
registration, etc). We have found no limiting restrictions in using
frames.

A lot of components don't like being on frames.
Resize doesn't work well on frames - especially parenting at runtime, you'll
see a lot of misalignment.

Bryan



Back to top
Jeffrey A. Wormsley
Guest





PostPosted: Tue Feb 22, 2005 6:46 pm    Post subject: Re: Structure Question Reply with quote

"Bryan Crotaz" <bryan (AT) no (DOT) spam.for.me.please.inspirationmatters.com> wrote
in news:421a67f0 (AT) newsgroups (DOT) borland.com:

Quote:
Use a form as you might use a frame (but much easier to use a form).

Cosidering I have never used a frame, I'm not sure that helps much.

However, I have enough to chew on for another few days, I believe, before
"the next thing" crops up.

Jeff.

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

 
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.