Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I\'m regularly facing following pattern: public abstract class BaseItem { BaseIt

ID: 644460 • Letter: I

Question

I'm regularly facing following pattern:

public abstract class BaseItem
{
    BaseItem[] children;

    // ...

    public void DoSomethingWithStuff()
    {
        StuffCollection collection = new StuffCollection();
        foreach(child c : children) c.AddRequiredStuff(collection);
        // do something with the collection ...
    }

    public abstract void AddRequiredStuff(StuffCollection collection);
}

public class ConcreteItem : BaseItem
{
    // ...

    public override void AddRequiredStuff(StuffCollection collection)
    {
        Stuff stuff;
        // ...
        collection.Add(stuff);
    }
}
Where I would prefer something like this, for better information hiding:

public abstract class BaseItem
{
    BaseItem[] children;

    // ...

    public void DoSomethingWithStuff()
    {
        StuffCollection collection = new StuffCollection();
        foreach(child c : children) collection.AddRange(c.RequiredStuff());
        // do something with the collection ...
    }

    public abstract StuffCollection RequiredStuff();
}

public class ConcreteItem : BaseItem
{
    // ...

    public override StuffCollection RequiredStuff()
    {
        StuffCollection stuffCollection;

        Stuff stuff;
        // ...
        stuffCollection.Add(stuff);

        return stuffCollection;
    }
}
What are pros and cons of each solution?

For me, giving the implementation access to parent's information is some how disconcerting. On the other hand, initializing a new list, just to collect the items is a useless overhead ...

What is the better design? How would it change, if DoSomethingWithStuff wouldn't be part of BaseItem but a third class?

PS: there might be missing semicolons, or typos; sorry for that! The above code is not meant to be executed, but just for illustration.

Explanation / Answer

initializing a new list, just to collect the items is a useless overhead

instantiate 2 class-level collections, once. The first is for the cumulative AddStuff() and the other is to pass to the child - and is reused.

public abstract class BaseItem
{
BaseItem[] children;
StuffCollection masterCollection;
StuffCollection transferCollection;

// ...

public void DoSomethingWithStuff()
{
masterCollection = masterCollection?? new StuffCollection();
transferCollection = transferCollection?? new StuffCollection();

transferCollection.Clear();

foreach(child c : children) {
c.RequiredStuff(transferCollection);
masterCollection.AddRange(transferCollection);
transferCollection.Clear();
}

// do something with the collection ...
}

public abstract void RequiredStuff(StuffCollection aTransferCollection);
}

public class ConcreteItem : BaseItem
{
// ...

public override void RequiredStuff(StuffCollection collector )
{
Stuff stuff;
// ...
collector.Add(stuff);
}
}