User Interface and Domain object design question
Hi,
I always get stuck when I need to design a domain class and the corresponding user interface class because of following reasons:
1. Most of the details of the domain class need to be visible to the user interface class. So, I think it violets the encapsulation of the domain class because the innards of this object need to be open to the user interface object.
2. Instead of providing a whole lot of get methods in the domain object (which being public can be accessed by other objects as well) for every member variable, I just declare the UI class as a friend of domain class. Moreover this has advantage that when domain class changes, say we add more member variables, we don't need to add in more Get methods.
I am aware of the difference between 'attribute' and 'member variable' of domain. But mostly they are both the same. So, I don't see any advantage of Get methods.
Code:
#include <iostream>
using namespace std;
class widget
{
};
class UserInterface;
class Domain
{
public:
static const int MAX_DATA_LEN = 10;
static const int MAX_DATA_VAL = 10;
static const int MAX_PERIOD = 4;
static const int MAX_AMP = 2;
private:
unsigned char data[MAX_DATA_LEN];
int amp;
int period;
friend class UserInterface;
public:
Domain();
~Domain();
};
class UserInterface
{
private:
static const int MAX_PIXEL_LEN = Domain::MAX_DATA_LEN * Domain::MAX_PERIOD;
static const int MAX_PIXEL_AMP = Domain::MAX_DATA_VAL * Domain::MAX_AMP;
unsigned char pixelData[MAX_PIXEL_AMP][MAX_PIXEL_LEN];
Domain & m_Domain;
public:
class RowExceeded {};
class ColumnExceeded {};
UserInterface( Domain & domain );
~UserInterface();
void PlotData();
};
Domain::Domain() : amp ( 2 ), period ( 4 )
{
for ( int i=0; i<MAX_DATA_LEN; i++)
{
data[i] = static_cast<unsigned char>(i%4);
}
}
Domain::~Domain()
{
}
UserInterface::UserInterface( Domain & domain ) : m_Domain ( domain )
{
}
UserInterface::~UserInterface()
{
}
void UserInterface::PlotData()
{
int pixelAmp;
if ( m_Domain.period > Domain::MAX_PERIOD )
throw ColumnExceeded();
memset(pixelData, ' ', MAX_PIXEL_AMP * MAX_PIXEL_LEN );
for ( int col=0; col < Domain::MAX_DATA_LEN; col++ )
{
pixelAmp = m_Domain.data [col] * m_Domain.amp;
if ( pixelAmp >= MAX_PIXEL_AMP )
throw RowExceeded();
pixelData[pixelAmp][col * m_Domain.period] = 'M';
}
for ( int row=0; row<MAX_PIXEL_AMP; row++ )
{
for ( int col=0; col<MAX_PIXEL_LEN; col++ )
{
cout << pixelData[row][col];
}
cout << endl;
}
}
int main(int argc, char *argv[])
{
Domain domain;
UserInterface userInterface ( domain );
try
{
userInterface.PlotData();
}
catch ( UserInterface::RowExceeded )
{
cout << "Invalid domain data value!" << endl;
}
catch ( UserInterface::ColumnExceeded )
{
cout << "Invalid period!" << endl;
}
catch ( ... )
{
cout << "Unknown exception!" << endl;
}
return 0;
}
What are the alternatives to designing domain and the corresponding user Interface classes other than friend classes and Get methods?
Re: User Interface and Domain object design question
Hello rohshall,
Recently, there was a good disucssion about abstraction and encapsulation,
you might want to search and read the thread.
In the mean time, one obvious reason is that friendship is not inherited. If you have two classes like in your example, it won't make a whole lot of difference. But using friendship in a multiple levels, polymorphism is difficult to achieve. So, I think the better question is rather inheritance vs composition modeling and whether we trully need an inheritance or not.
Re: User Interface and Domain object design question
Hi PotatoCode,
Thanks for your inputs. I did find some good points mentioned in these encapsulation and Abstraction debates. And thanks for pointing out that friendship is not inherited.