Hidden Implementation

I

Immortal Nephi

I want to create one simple interface. One class has one private
data member and more than 10 public member functions. It does not
have private member functions.
The client includes a header. He only needs to see simple interface,
but he does not know hidden implantation. He uses class A to invoke
doit() function and/or other public member functions.
doit() function may have small or big algorithm, but client does not
know what algorithm is doing.
I need to create another class or global function. Another class or
global function is defined in source code. The global function like
doSomething_1(…) and doSomething_2(…) may have more than 8
parameters. It is located inside doit() function.

// Interface.h
class A {
public:
A();
~A();

int getValue();
void setValue( int value );

void doit();

private:
int m_data;
};


// interface.cpp
void doSomething_1( int &a, int &b, int &c, int &d, int &e, int &f,
int &g, int &h );

void doSomething_2( int &a, int &b, int &c, int &d, int &e, int &f,
int &g, int &h );

void doSomething_1( int &a, int &b, int &c, int &d, int &e, int &f,
int &g, int &h ) {
// do something…
doSomething_2( a, b, c, d, e, f, g, h );
}

void doSomething_2( int &a, int &b, int &c, int &d, int &e, int &f,
int &g, int &h ) {
// do something…
}


A::A() : m_data( 0 ) {
}

A::~A() {
}

int A::getValue() {
return m_data;
}

void A::setValue( int value ) {
if ( value > 10 )
value = 10;

else if ( value < 0 )
value = 0;

m_data = value;
}

void A::doit() {
int a = 0;
int b = 1;
int c = 2;
int d = 3;
int e = 4;
int f = 5;
int g = 6;
int h = 7;

doSomething_1( a, b, c, d, e, f ,g, h );

// after 8 local variables are complete, it modifies the final value
back to private data member – m_data
}

int main() {
A a;
a.doit();

return 0;
}

doit() has 8 local variables. It invokes doSomething_1(…) function
and doSomething_2(…) function. doSomething_1(…) does calculation to
modify 8 local variables before it calls doSomething_2(…) function to
finish more local variables.

I think 8 parameters are too many. I should decide to design another
class to hold 8 data members and replace 8 parameters to one class
reference.

// interface.cpp
class Data {
public:

int a;
int b;
int c;
int d;
int e;
int f;
int g;
int h;
};

void doSomething_1( Data &data );
void doSomething_2( Data &data );

void doSomething_1( Data &data ) {
// do something
doSomething_2( data );
}

void A::doit() {
Data data;

data.a = 0;
data.b = 1;
data.c = 2;
data.d = 3;
data.e = 4;
data.f = 5;
data.g = 6;
data.h = 7;

doSomething_1( data );
}

Class Data has 8 public data members. It does not need to use getter
and setter function because it does not need to validate inbound range
on all 8 data members. doit() function takes care to modify public
data members and invokes global function doSomething_1(…) function and
doSomething_2(…) function.
If I want to create more than 5 small global functions, I will want
to move them to class Data body and treat them as public member
functions, but 8 data members are still public.
It is possible to say that public member functions may do validate
inbound range on all 8 public data members if necessary.

// interface.cpp
class Data {
public:
void continueToDoSomething();

void doSomething_1(); // do validate ranges
void doSomething_2(); // do calculation
void doSomething_3(); // do final result before return back to A.

int a;
int b;
int c;
int d;
int e;
int f;
int g;
int h;
};

void Data::continueToDoSomething() {
doSomething_1();
}

void Data::doSomething_1() {
// work data member -- a and b
doSomething_2();
}

void Data::doSomething_2() {
// work data member -- c and d
doSomething_3();
}

void Data::doSomething_3() {
// work data member -- e, f, g, and h
}


void A::doit() {
Data data;

data.a = 0;
data.b = 1;
data.c = 2;
data.d = 3;
data.e = 4;
data.f = 5;
data.g = 6;
data.h = 7;

data.continueToDoSomething();

// after 8 local variables are complete, it modifies the final value
back to private data member – m_data
}


class Data with 8 public data members and some public member
functions are hidden inside A’s doit() function.
Please let me know if you think that I should treat class Data’s data
members and member functions to private because I might want to reduce
bugs if I make easy mistakes to write my code.
 
F

Francesco S. Carta

I want to create one simple interface. One class has one private
data member and more than 10 public member functions. It does not
have private member functions.
The client includes a header. He only needs to see simple interface,
but he does not know hidden implantation. He uses class A to invoke
doit() function and/or other public member functions.
doit() function may have small or big algorithm, but client does not
know what algorithm is doing.
I need to create another class or global function. Another class or
global function is defined in source code. The global function like
doSomething_1(…) and doSomething_2(…) may have more than 8
parameters. It is located inside doit() function.

It's hard to decide whether those data members should be kept separated
or put together since your code example is too abstract.

If their names aren't meaningful, and if they're all of the same type as
it seems they are, I would put them into a vector or into a wrapped raw
array as the one I've posted lately in this group.

I definitely wouldn't create a function with 8 or 10 parameters, in any
case.

doit() has 8 local variables. It invokes doSomething_1(…) function
and doSomething_2(…) function. doSomething_1(…) does calculation to
modify 8 local variables before it calls doSomething_2(…) function to
finish more local variables.

I think 8 parameters are too many. I should decide to design another
class to hold 8 data members and replace 8 parameters to one class
reference.

Definitely, put them together in some class.

Class Data has 8 public data members. It does not need to use getter
and setter function because it does not need to validate inbound range
on all 8 data members. doit() function takes care to modify public
data members and invokes global function doSomething_1(…) function and
doSomething_2(…) function.

I would validate the data upon creation of the data class, if possible.

Please let me know if you think that I should treat class Data’s data
members and member functions to private because I might want to reduce
bugs if I make easy mistakes to write my code.

As above, it's hard to give you sensible advice. Please post a more
concise example and less abstract example of what you're doing: you want
to get advice about how to do something, but you need to tell us what
you're wanting to do.

I am accustomed to see experienced people posting sensible advice
"seeing through" examples like this, but I haven't reached such level of
clairvoyance ;-)
 
I

Immortal Nephi

It's hard to decide whether those data members should be kept separated
or put together since your code example is too abstract.

If their names aren't meaningful, and if they're all of the same type as
it seems they are, I would put them into a vector or into a wrapped raw
array as the one I've posted lately in this group.

I definitely wouldn't create a function with 8 or 10 parameters, in any
case.




Definitely, put them together in some class.



I would validate the data upon creation of the data class, if possible.



As above, it's hard to give you sensible advice. Please post a more
concise example and less abstract example of what you're doing: you want
to get advice about how to do something, but you need to tell us what
you're wanting to do.

I am accustomed to see experienced people posting sensible advice
"seeing through" examples like this, but I haven't reached such level of
clairvoyance ;-)

I can see one problem. If class Data has 8 private data members,
then you prefer to create one constructor with 8 parameters. You put
8 local variables from doit() function to Data’s constructor.
The constructor takes care to do validity checking.
If class Data has 20 private data members, you want to split 20
private data members into two or three classes and put local variables
into two or three classes’ constructor.

class subData1 {
public:
subData1( int a, int b, int c ) { /*…*/ }
~subData1() { /*…*/ }

private:
int m_a;
int m_b;
int m_c;
}

class subData2 {
public:
subData2( int d, int e, int f ) { /*…*/ }
~subData2() { /*…*/ }

private:
int m_d;
int m_e;
int m_f;
}

class subData3 {
public:
subData3( int g, int h ) { /*…*/ }
~subData3() { /*…*/ }

private:
int m_g;
int m_h;
}

class Data {
public:
Data() { /*…*/ }
~Data() { }

private:
subData1 m_subData1;
subData2 m_subData2;
subData3 m_subData3;
}

void doit() {
Data data;

// do something….
}

How can you describe you want to define Data’s constructor? subData1
… subData3 can’t have default constructors because you want to put
local variables into constructor’s parameter. You will move subData1
… subData3 into doit() function.

void doit() {
int a = 0;
int b = 1;
int c = 2;
int d = 3;
int e = 4;
int f = 5;
int g = 6;
int h = 7;

subData1 m_subData1( a, b, c );
subData2 m_subData2( d, e, f );
subData3 m_subData3( g, h );

// do something….
}


I clarify you have 8 local variables in doit() function. You want to
divide one problem into three problems. Design two or three classes
and allow constructor to do validity checking if necessary before the
class processes algorithms.
Yes, you state that class is very abstract. Unfortunately, I can’t
think how to give good name to any class, data member and member
function. Always make sure to keep small class body if necessary.
I can write names in the list. I separate names into 2 or 3 diagrams
and draw a line connection between classes. I can think how I can
design better class.
 
Ö

Öö Tiib

        Yes, you state that class is very abstract.  Unfortunately, I can’t
think how to give good name to any class, data member and member
function.  Always make sure to keep small class body if necessary.

You should always try to solve actual problems with software. Actual
data, actual subdata. There are no solutions for nonexistent problems
between 8 ints. 8 ints of data are perhaps best like:

int data[8];
 
F

Francesco S. Carta

I can see one problem. If class Data has 8 private data members,
then you prefer to create one constructor with 8 parameters. You put
8 local variables from doit() function to Data’s constructor.
The constructor takes care to do validity checking.
If class Data has 20 private data members, you want to split 20
private data members into two or three classes and put local variables
into two or three classes’ constructor.

class subData1 {
public:
subData1( int a, int b, int c ) { /*…*/ }
~subData1() { /*…*/ }

private:
int m_a;
int m_b;
int m_c;
}

class subData2 {
public:
subData2( int d, int e, int f ) { /*…*/ }
~subData2() { /*…*/ }

private:
int m_d;
int m_e;
int m_f;
}

class subData3 {
public:
subData3( int g, int h ) { /*…*/ }
~subData3() { /*…*/ }

private:
int m_g;
int m_h;
}

class Data {
public:
Data() { /*…*/ }
~Data() { }

private:
subData1 m_subData1;
subData2 m_subData2;
subData3 m_subData3;
}

void doit() {
Data data;

// do something….
}

How can you describe you want to define Data’s constructor? subData1
… subData3 can’t have default constructors because you want to put
local variables into constructor’s parameter. You will move subData1
… subData3 into doit() function.

void doit() {
int a = 0;
int b = 1;
int c = 2;
int d = 3;
int e = 4;
int f = 5;
int g = 6;
int h = 7;

subData1 m_subData1( a, b, c );
subData2 m_subData2( d, e, f );
subData3 m_subData3( g, h );

// do something….
}


I clarify you have 8 local variables in doit() function. You want to
divide one problem into three problems. Design two or three classes
and allow constructor to do validity checking if necessary before the
class processes algorithms.
Yes, you state that class is very abstract. Unfortunately, I can’t
think how to give good name to any class, data member and member
function. Always make sure to keep small class body if necessary.
I can write names in the list. I separate names into 2 or 3 diagrams
and draw a line connection between classes. I can think how I can
design better class.

Yes, please, describe at least the idea you're implementing, at the
present level of specificity everything and nothing is possible/advisable.

If you have trouble finding the appropriate names for the various parts
of your program you probably need to focus a bit more on the idea before
starting to translate it in lines of code.

I've once read a comic strip where the marketing guy was fiddling with
some code, then he got stuck somehow and went to the developers' team to
ask them whether they could implement a "DoWhatIMean()" function for him
- IIRC that was a guy called Stef, in a UserFriendly strip of some years
ago.

I'm not making fun of your problem with choosing names. It's something
that can happen (and very likely has happened or will happen) to every
programmer, at some point in time.

Personally, I'd love to have a "DoWhatIMean()" function somewhere in my
libraries ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top