Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Best way to access methods of Objects and its sub-Objects

75 views
Skip to first unread message

dotnet...@googlemail.com

unread,
Apr 26, 2013, 11:47:45 AM4/26/13
to
Hi All,
I was always unsure as how to deal with cases where one has to access methods of objects contained with in the class. Basically, if we have a complex system as a car, where things can be abstracted in several classes, what is the ideal way to access one/several methods of an object contained in the class, which inturn contain additional classes ?

To explain what I mean, i wrote some pseudo code below. For example, I like to check the health of the car. While coding, I would normally prefer method-1 where the task of checking is delegated to each individual method. Where as some of my collegues argue this leads to several methods which do nothing but delegating the task further down. And suggest something like in method-2.

I am grateful for your time and suggestions. Thank you.



Pseudo code:
-----------

class Tyre;
class MovingParts
{
...
...
Tyre m_Tyre;
public:
Tyre* GetTyre() { return &m_Tyre; }
void CheckTyrePressure()
{
m_Tyre.CheckTyrePressure();
}
};

class Car
{
...
...
MovingParts m_movingParts;
public:
...
...
bool CheckCarHealth()
{
...
m_movingParts.CheckTyrePressure();
...
}

MovingParts* GetMovingPartsHandler()
{
return &m_MovingParts;
}
};



int main()
{
std::list<Car*> myCars;
...
...
// Check the health of all cars
for (std::list<Car*>::iterator carIdx=myCars.begin(); carIdx!=myCars.end(); ++carIdx)
{
// Method-1
carIdx->CheckCarHealth();
// Method-2
carIdx->GetMovingPartsHandler()->GetTyre()->CheckTyreProfile();
}
...
...
}


Victor Bazarov

unread,
Apr 26, 2013, 2:11:31 PM4/26/13
to
On 4/26/2013 11:47 AM, dotnet...@googlemail.com wrote:
> Hi All,
> I was always unsure as how to deal with cases where one has to
> access
methods of objects contained with in the class. Basically, if we have a
complex system as a car, where things can be abstracted in several
classes, what is the ideal way to access one/several methods of an
object contained in the class, which inturn contain additional classes ?
>
> To explain what I mean, i wrote some pseudo code below. For example,
> I
like to check the health of the car. While coding, I would normally
prefer method-1 where the task of checking is delegated to each
individual method. Where as some of my collegues argue this leads to
several methods which do nothing but delegating the task further down.
And suggest something like in method-2.
>
> I am grateful for your time and suggestions. Thank you.
>
>
>
> Pseudo code:
> -----------
>
> class Tyre;

??? No known interface in Tyre...

> class MovingParts
> {
> ...
> ...
> Tyre m_Tyre;
> public:
> Tyre* GetTyre() { return &m_Tyre; }
> void CheckTyrePressure()

Probably

void CheckTyrePressure() const

(or does checking pressure changes the state of 'MovingParts' object?)
and perhaps there is some kind of side effect since this function does
not seem to return any value, nor does it have any arguments beyond
'this'. Consider documenting that somehow.

> {
> m_Tyre.CheckTyrePressure();

The compiler is unlikely to accept this code without seeing the
definition of 'Tyre' type.

> }
> };
>
> class Car
> {
> ...
> ...
> MovingParts m_movingParts;
> public:
> ...
> ...
> bool CheckCarHealth()

bool CheckCar

> {
> ...
> m_movingParts.CheckTyrePressure();
> ...
> }
>
> MovingParts* GetMovingPartsHandler()
> {
> return &m_MovingParts;
> }
> };
>
>
>
> int main()
> {
> std::list<Car*> myCars;
> ...
> ...
> // Check the health of all cars
> for (std::list<Car*>::iterator carIdx=myCars.begin(); carIdx!=myCars.end(); ++carIdx)

In C++11 consider doing

for (Car* pCar : myCars)

> {
> // Method-1
> carIdx->CheckCarHealth();
> // Method-2
> carIdx->GetMovingPartsHandler()->GetTyre()->CheckTyreProfile();
> }
> ...
> ...
> }

If your question is purely about the differences I see between the two
ways of invoking the interface, then my answer is to hide it. Hidden
interface is the best abstraction, the ultimate black box. The code
that uses the results does not have to know even that the interface
actually exists. The the outside observer the car can check its health
and what it entails is of no consequence. Unless they actually know
what they are looking for, in which case you probably want to design a
special "mechanic" interface who would request all those part-by-part
interfaces and interrogate those individually...

To conclude: create those interfaces that your user is going to want to
use. If you can see both uses, create both interfaces.

V
--
I do not respond to top-posted replies, please don't ask

Christopher Pisz

unread,
Apr 26, 2013, 6:22:03 PM4/26/13
to
In my opinion this is why you start with requirements before coding.
Do you have a use case where the user would want to interact with tire
objects directly? Are they concerned with each individual tire? Perhaps
they'd like to modify tires? Or is your user only concerned with the car
as a whole?

In the former case, I'd provide get and set methods for tires in the car
interface and allow the user to interact with tires or references to
tires directly. In the latter case, I'd hide the details of tire
interactions withing the implementation of the car class.

If unsure, then go the second route, but make it easy to provide get and
set methods for tires later and a proper tire interface, such that
actions can be taken on the tire directly later if needed. There is no
problem having both IMO. You want to check car health, which in turn
checks tire pressure? fine. Later on the customer, wants to look at each
individual tire? Fine, get and set tire added to car, caller gets each
tire from car and calls check pressure, get serial number, get tread,
etc. on each tire individually.

In summary, Opt for the second choice, but let your requirements guide you.









Message has been deleted
Message has been deleted

dotnet...@googlemail.com

unread,
Apr 26, 2013, 8:44:43 PM4/26/13
to
Thank you all for your thoughtful answers.

@Stefan: You may find it hard to believe but I am an experienced programmer. Your comments clearly indicate that I should learn to *speak* in C++ rather than just *think* in it.

I am also sorry for the errors in the Pseudo code. I did not review it before posting. I rather concentrated on my question part only.

The Pseudo code I gave as example, comes no where near to the system we have at work. We offer wide range of interfaces, right from something as abstract as checking the Car's health, to something as detailed as the pressure of the tyre, its serial number, etc etc. Therefore, the requirements demands that we offer much detailed access to our system.

Using the method-2, it becomes much easier to handle every possible case. But it has the disadvantage that, error handling gets very difficult (Ex: What if there are no tyres ?)

Whereas in Method-1, I like the black box approach, where the User just invokes the interface without actually worrying what lies underneath.

From what I understand reading your comments, there is no *one* way, but rather both ways can/should be used simultaneously, given the wide range of interfaces we offer to the User ?

Victor Bazarov

unread,
Apr 27, 2013, 9:43:34 AM4/27/13
to
On 4/26/2013 8:44 PM, dotnet...@googlemail.com wrote:
>[..]
> From what I understand reading your comments, there is no *one* way,
> but rather both ways can/should be used simultaneously, given the
> wide range of interfaces we offer to the User ?

You misunderstand, or so it seems. The way is not dictated by *you*,
the implementor of the class/interface, but by the user of it. Provide
the interface that will be used. If both are needed, provide both. If
you provide both, they *can* be used simultaneously (that's the user's
prerogative), but AFA design is concerned, the word "should" has no
place, IMHO.

Now, how do you figure out which interface is *likely* to be used? You
need to put yourself in the shoes of the user and imagine the likely
application of your types. The rest of the story is to be written by
the market, so to speak. If you have unlimited resources, provide all
the interfaces you can think of. If your resources are of the real
world, then you will need to pick the most likely to be used, and
concentrate on making them convenient and robust.

Gerhard Fiedler

unread,
Apr 29, 2013, 1:20:53 PM4/29/13
to
Something that has been missing so far IMO is encapsulation.

Let's say you add the possibility to add a turbo charger to the motor
and now may have to check an optional turbo charger for health. If there
are a dozen places in the code that use method 2, they all have to be
kept up to date with this change. If they all use a single "black box"
interface like method 1, the change is restricted to (encapsulated in) a
single function.

So, going back to Victor's point, if there is a requirement to be able
to "check the (whole) car's health", this is a strong indicator that you
want a single function that encapsulates this, a la method 1. While
method 2 in principle provides the means to fulfill the requirement, it
makes it error-prone and awkward.

Gerhard

Jorgen Grahn

unread,
May 16, 2013, 4:14:58 AM5/16/13
to
On Fri, 2013-04-26, Christopher Pisz wrote:
> On 4/26/2013 10:47 AM, dotnet...@googlemail.com wrote:
>> Hi All,
>> I was always unsure as how to deal with cases where one has to
>> access methods of objects contained with in the class.
...

> In my opinion this is why you start with requirements before coding.
> Do you have a use case where the user would want to interact with tire
> objects directly? Are they concerned with each individual tire? Perhaps
> they'd like to modify tires? Or is your user only concerned with the car
> as a whole?

I'd put that differently, since IME it's rare to have actual
requirements on this level.

If you start doubting what the class interface should look like, try
leaving it aside for a while and work on the code which /uses/ the
class. (Assuming you're responsible for that code too; if you aren't,
then you are a library designer and that's a much harder job.)

If I focus on just the Car class and its unit tests, I tend to come up
with a lot of interface which isn't needed or is too elaborate.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
0 new messages