Brett Romero wrote:
If Person objects have an address collection (since a person can have
multiple addresses) in them, should I have a FillAddresses() method on
the collection that lazy loads all of its Person.FillAddress()'s? Or
should I instead loop through the collection and access FillAddresses()
off of each Person object. For example:
for(int i; i < mycollection.count; i++)
mycollection[i].FillAddress();
A problem with this approach is that it transferres control back and
forth between the looping code and the collection. This is undesireable
if mycollection is a remote object or FillAddresses does lookups with
high expense on indvidual actions, compared to grouped ones -- as
database lookups.
instead of mycollection.FillAddresses();
This is chunky, and resolves the problem above, it does however
introduce the problem that you have to fill all addresses, and it binds
the code that fill the address to the collection, which probably
shouldn't have any idea of to lookup address'es in it's constituent objects.
This problem crops up again and again, and the best solution i've seen
is to introduce a separate protocol, for example:
public delegate void PersonCallback(Person p);
public interface IAddressFiller {
// If address isn't found
// if notfound == null
// throw
// else
// invoke notfound(p).
// to abort filling programatically in notfound, throw
void FillAddress(Person p, PersonCallback notfound);
void FillAddresses(ICollection<Person> persons,
PersonCallback notfound);
}
And have an implementation of that protocol that fits the situations,
for example if addresses are to be filled from a database:
public class DataBaseAddressFiller {
public readonly DatabaseReferenceOrWhatnot Data;
...
public void FillAddress(Person p, AddressFillError error) {
// lookup person p
Address a = lookup_single_address(p);
if ( address_not_found )
if ( error == null )
throw new AddressNotFoundException(p);
else
error(p);
}
public void FillAddress(ICollection<Person> persons,
AddressFillError error) {
ICollection<Result> results;
if ( persons.Count < Data.PersonsCount() * factor )
results = parametrised_select_addresses(persons);
else
results = select_addrdesses();
// set addresses,
// You can utilize ORDER_BY and sorting, or a dictionary
// to pair up persons and results
// if a person is missing an address:
if ( address_not_found )
if ( error == null )
throw new AddressNotFoundException(p);
else
error(p);
}
}
If you need to indicate progress, you can let the IAddressFiller
functions accept a callback for each success as well as failure.
You may also wish to extend the PersonCallback with some EventArgs, if
specific failure info needs to be passed up.
--
Helge Jensen
mailto:he**********@slog.dk
sip:he**********@slog.dk
-=> Sebastian cover-music:
http://ungdomshus.nu <=-