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

Best way to implement class printing

96 views
Skip to first unread message

JiiPee

unread,
Nov 6, 2016, 8:13:42 PM11/6/16
to
They say, especially in game programming, that drawing/printing should
not be done inside the class but some other class should do it (by
asking the data from the object). Is this the way also with cout? Say we
have:

class Person
{
public:
Person(const string& name, int age, int id) :
m_name{ name }, m_age{ age }, m_id{ id } {}
private:
string m_name;
int m_age;
int m_id;
};

If I want to create a print function which prints all persons details
what is the best way to do it?
First idea/try is obviously somethin like:

class Person
{
public:
Person(const string& name, int age, int id) :
m_name{ name }, m_age{ age }, m_id{ id } {}
void print(ostream& os) { os<<m_name<<", " << ....};
private:
string m_name;
int m_age;
int m_id;
};

But now the class is doing two things... printing and holding the data.
they should be separated, isnt it? Second idea is to create a non-class
function which a friend of Person. but any other ideas? Is it best to do
like in game programming: no printing done in Person class, some other
function/class asks the values and prints. Obviously we dont want to
have getters for Person necessary (because it would break OO-idea.).

bitrex

unread,
Nov 6, 2016, 8:51:54 PM11/6/16
to
On 11/06/2016 08:13 PM, JiiPee wrote:
> They say, especially in game programming, that drawing/printing should
> not be done inside the class but some other class should do it (by
> asking the data from the object).

I thought the notion of OOP was exactly the opposite: the caller tells
the object in question to do something, not asks for the data and does
the thing itself.

Daniel

unread,
Nov 6, 2016, 9:12:42 PM11/6/16
to
Strict OO people believed that, yes. But I thought that'd all died off.

The first problem with objects that display themselves, print themselves, etc.
is that the object doesn't know how the user wants to present it: an object
should be viewable in multiple ways, as the user wishes. The second problem is
that it leads to very heavy objects, and single responsibility principle
demurs. In general, the code for displaying, printing, etc should be kept
outside the object. The object should expose enough of itself to make that
possible.

Daniel



Öö Tiib

unread,
Nov 7, 2016, 12:59:14 AM11/7/16
to
On Monday, 7 November 2016 03:13:42 UTC+2, JiiPee wrote:
> They say, especially in game programming, that drawing/printing should
> not be done inside the class but some other class should do it (by
> asking the data from the object). Is this the way also with cout?

Maybe. It is up to you. You are designer of your software.

> Say we have:
>
> class Person
> {
> public:
> Person(const string& name, int age, int id) :
> m_name{ name }, m_age{ age }, m_id{ id } {}
> private:
> string m_name;
> int m_age;
> int m_id;
> };
>
> If I want to create a print function which prints all persons details
> what is the best way to do it?

There are no best ways. I can suggest to consider two. Both are Ok
but you may want to use something else.

1) A free 'operator<<' is likely least noise:

std::ostream& operator<<(std::ostream& o, Person const& p);


2) Visitor pattern is most fancy and clever. The Wikipedia
https://en.wikipedia.org/wiki/Visitor_pattern has a C++ example how
different "files" are "dispatched" by "dispatchers" using visitor
pattern. You can use same to "output" your "outputtables" with
"outputters".

Then you can have number of different and separate ways how your 'Person'
and other types are printed, drawn or stored on different media or views.
My experience is that visitor pattern works greatly but is bordering
on confusing for some people.

Jerry Stuckle

unread,
Nov 7, 2016, 9:45:17 AM11/7/16
to
Yes, to a point. But the display can also be a class, as in Microsoft's
Document-View architecture, or the Model-View-Controller (MVC)
architecture common to many projects.

The class holding the data is still responsible for some formatting of
the data. And for a text-mode console or flat file mode I/O, that is
often sufficient. But when you have a GUI there is much more involved
and more interaction between the various objects. In cases like this,
it is often more efficient (and cleaner) to have a class representing
the view (or multiple classes for multiple views).

Like anything else, there are few firm design rules. You need to become
familiar with different architectures so you can adapt to the needs.

--
==================
Remove the "x" from my email address
Jerry Stuckle
jstu...@attglobal.net
==================

JiiPee

unread,
Nov 7, 2016, 1:25:38 PM11/7/16
to
On 07/11/2016 02:12, Daniel wrote:
> On Sunday, November 6, 2016 at 8:51:54 PM UTC-5, bitrex wrote:
>> On 11/06/2016 08:13 PM, JiiPee wrote:
>>> They say, especially in game programming, that drawing/printing should
>>> not be done inside the class but some other class should do it (by
>>> asking the data from the object).
>> I thought the notion of OOP was exactly the opposite: the caller tells
>> the object in question to do something, not asks for the data and does
>> the thing itself.
> Strict OO people believed that, yes. But I thought that'd all died off.
>
> The first problem with objects that display themselves, print themselves, etc.
> is that the object doesn't know how the user wants to present it:

yes , exactly. And also... the format of printing can be changed easier
outside. Maybe today we want to pring on to screen but tomorrow into the
file etc. maybe next day using OpenGL....

> an object
> should be viewable in multiple ways, as the user wishes. The second problem is
> that it leads to very heavy objects, and single responsibility principle
> demurs. In general, the code for displaying, printing, etc should be kept
> outside the object. The object should expose enough of itself to make that
> possible.

you propose: string getName();
? so getters for those data memember?

>
> Daniel
>
>
>

JiiPee

unread,
Nov 7, 2016, 1:29:22 PM11/7/16
to
On 07/11/2016 05:59, Öö Tiib wrote:
> My experience is that visitor pattern works greatly but is bordering
> on confusing for some people.


good suggestion. I ll think about this. Although it makes things a bit
complicated, isnt it? a simple textout functionality needs a complex
stucture behind it...

Öö Tiib

unread,
Nov 7, 2016, 3:55:05 PM11/7/16
to
I said that there are no "best" silver bullets for all situations.
It is likely clean and simple when you have more than one different
outputter outputting same set of classes.
It is likely pointless complexity when you need only simple textout
for couple classes.

Note that code can be edited! If you are unsure then pick simplest
that can solve your issue right now and when you later see that it
can't actually pull the weight then rearrange it into next solution.

Daniel

unread,
Nov 7, 2016, 4:45:13 PM11/7/16
to
I think getters are beautiful things :-) (setters not so much.) But let me digress.

I used to participate on comp.object, and one of the difficulties I had with the OO people was what exactly did they mean by objects saving themselves and displaying themselves and printing themselves, etc.? To me they seemed infuriatingly vague on the specifics. So I was happy to find an article by Alan Holub in JavaWorld, http://www.javaworld.com/article/2072302/core-java/more-on-getters-and-setters.html, who explained exactly what he meant by these things, with code.

So I read Holub's article carefully, hoping to be enlightened, but instead I found myself asking, did anyone else besides Holub think that

class EmployeeUI extends JPanel implements Employee.Exporter
{ private JLabel nameWidget = new JLabel("");
private JLabel idWidget = new JLabel("");
private JLabel salaryWidget = new JLabel("");

public void addName ( String name ) { nameWidget.setText(name);
}
public void addID ( String id ) { idWidget.setText(id); }
public void addSalary( String salary ) {
salaryWidget.setText(salary); }

public EmployeeUI()
{ setLayout( new GridLayout(3,2) );
add( new JLabel("Name: ") );
add( nameWidget );
add( new JLabel("Employee ID: ") );
add( idWidget );
add( new JLabel("Salary: ") );
add( salaryWidget );
}
}

was anything other than a widget class with setters?

Holub introduced Exporter and Importer interfaces, which he identified as
interfaces for GOF style builder patterns, but the analogy escaped me;
to me they looked like plain old data objects with setters and getters, except reborn as add/produce.

Anyway, it seems to me that one of the most widely accepted and successful practices over the last couple of decades is to expose the properties of objects, particularly in the Java and C# worlds. Much to the horror I'm sure of the OO people, typical Java and C# objects expose lots of properties. There are different levels of sophistication when it comes to accessing them, whether through reflection or getters, but in principle it's the same.

If you have to lay out fields on a GUI, which would you rather work with, somebody's incredibly complicated concoction of "interfaces for GOF style builder patterns", or simple data objects with getters?

Best regards,
Daniel

Christopher J. Pisz

unread,
Nov 7, 2016, 7:42:14 PM11/7/16
to
Who is "they" and what are "thier" reasons for making such assertions?
I am reading alot about Domain Driven Design recently, and it, afaik,
argues the exact opposite.

Christopher J. Pisz

unread,
Nov 7, 2016, 7:51:43 PM11/7/16
to
I take it back/clarify. Something like printing its values in a string
for logging might belong to the class...possibly... However, something
like generating a webpage that displays the values of the class would be
surely be somewhere else, like a view.

In the case that you are providing an ostream operation, it is most
likely for logging, in the real world. Even if your application was
command line only, I'd imagine there is some other component somewhere
for the "UI"

Also consider though, that if the data is private, it most likely isn't
meant to be displayed on a webpage and viewed. In your example there is
no method exposing the data for such a purpose. Making a friend and
exposing the private data is surely bad design. If Person wants
something to be seen, it will expose it, in its public methods, although
it might not expose it in such a manner that it is meant to generate
HTML and show a webpage or application tab.





Alf P. Steinbach

unread,
Nov 7, 2016, 9:38:56 PM11/7/16
to
On 07.11.2016 02:13, JiiPee wrote:
> They say, especially in game programming, that drawing/printing should
> not be done inside the class but some other class should do it (by
> asking the data from the object). Is this the way also with cout?

Yes.


> Say we have:
>
> class Person
> {
> public:
> Person(const string& name, int age, int id) :
> m_name{ name }, m_age{ age }, m_id{ id } {}
> private:
> string m_name;
> int m_age;
> int m_id;
> };
>
> If I want to create a print function which prints all persons details
> what is the best way to do it?

As a non-member.

E.g. this ensures that all the needed information is accessible to
calling code in general.


> First idea/try is obviously somethin like:
>
> class Person
> {
> public:
> Person(const string& name, int age, int id) :
> m_name{ name }, m_age{ age }, m_id{ id } {}
> void print(ostream& os) { os<<m_name<<", " << ....};

In spite of the name this is not a printing function: it's a function
that converts to string.

I think a far better design for this member would be

auto to_string() const
-> string
{ ...

In particular, when the class is used in a GUI the `<string>` header
will likely be included anyway, but not so `<iosfwd>` or `<iostram>`.

Also, standard iostreams are extremely inefficient, possibly due to the
locale stuff that is forced on you, and the modes, both of which makes
robust client code extremely complex in addition to inefficient.


> private:
> string m_name;
> int m_age;
> int m_id;
> };
>
> But now the class is doing two things... printing and holding the data.
> they should be separated, isnt it?

No, it's not printing; it's just converting to string.

This is the #1 litmus test: can you use the class in various GUI frameworks?

If so then it's portable, OK in that respect.

But then, there is the #2 test, can you use the class in different
environments in general?

For example, since you're involving a stream it may be that the code
will depend on an UTF-8 locale having been imbued in that stream. Then
use the code in Windows and there's no such. Uh oh.


> Second idea is to create a non-class
> function which a friend of Person. but any other ideas? Is it best to do
> like in game programming: no printing done in Person class, some other
> function/class asks the values and prints. Obviously we dont want to
> have getters for Person necessary (because it would break OO-idea.).

For conversion to string, try to express that more directly. This is
akin to generally using `++x` instead of `x++`. Don't ask for and
require way more than you actually need for the job.

Well, unless it's money, and the person paying is Donald Trump.


Cheers & hth.,

- Alf

Jerry Stuckle

unread,
Nov 7, 2016, 10:20:00 PM11/7/16
to
The problem with this that to_string() generally is considered to
convert the entire object to a string. That's often desired for things
like debugging or even serialization, but not necessarily printing. You
might, for instance, want to print just the name and address, not the
birth date or phone number.

> Also, standard iostreams are extremely inefficient, possibly due to the
> locale stuff that is forced on you, and the modes, both of which makes
> robust client code extremely complex in addition to inefficient.
>

No arguments that they are inefficient. Part of that may be the locale
stuff, but they've always been inefficient, even before locales were
added. I think it's more due to the flexibility of the iostreams -
especially formatting options. The code is significantly more complex
than printf() formatting.
<snip>

Richard

unread,
Nov 8, 2016, 5:45:58 PM11/8/16
to
[Please do not mail me a copy of your followup]

som...@somewhere.net spake the secret code
<nvr6vt$q2g$1...@dont-email.me> thusly:

>I am reading alot about Domain Driven Design recently, and it, afaik,
>argues the exact opposite.

DDD by Eric Evans and "Implementing Domain-Driven Design" by Vaughn
Vernon are both excellent books. So much great stuff in there, it
can't be overstated.

Domain-Driven Design
<http://amzn.to/2fYwJGv>

Implementing Domain-Driven Design
<http://amzn.to/2flkaBo>
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

woodb...@gmail.com

unread,
Nov 9, 2016, 2:19:59 PM11/9/16
to
I hope he will be a humble and friendly person.

http://www.dailywire.com/news/10639/president-elect-trump-proved-me-wrong-about-ben-shapiro


Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net

Tim Rentsch

unread,
Nov 12, 2016, 10:18:22 AM11/12/16
to
I would like to offer a different viewpoint. Both of the above
positions are shortsighted, for the same underlying reason: they
insist that one approach is better than the other in all cases.

Questions like this one should be seen as offering design choices,
and a good choice in one case may very well be a poor choice in
other circumstances. Generically here we have three agents: a
requester, something to be displayed, and a display medium.
Which one is better positioned to decide how the display action
should take place? In different circumstances, it could be the
requester, the display medium, or the object to be displayed. In
some cases no single agent has all the knowledge needed to carry
out the assignment, in which case there needs to be a negotiation
between two (or less often, more) agents to accomplish the task
at hand. Of course we try to minimize the set of cases where the
more complicated interactions are needed, but it isn't always
possible to avoid them entirely, and it is foolish to pretend
otherwise.

As regards the single responsibility principle, and other similar
principles - what we want is good design. Principles offer
guidelines, or heuristics, for how to discover a good design,
but they are means to an end, not an end in itself. As with
geometry, there is no royal road to making good design choices.
Different architectural choices will lead to different designs,
and consequently different answers to questions like the one
under consideration here.

woodb...@gmail.com

unread,
Nov 12, 2016, 8:09:52 PM11/12/16
to
There's "A Royal Road to Algebraic Geometry" by Holme, Audun.
http://www.springer.com/us/book/9783642192241


Perhaps the royal road is doing the right thing given the context.

Tim Rentsch

unread,
Nov 15, 2016, 11:51:51 AM11/15/16
to
An amusing title, presumably deliberately so. But thank you for
the reference.

> Perhaps the royal road is doing the right thing given the context.

I think the whole point of the "no royal road" comment is that
there is no surefire way to know what the right thing is in
any given context.

woodb...@gmail.com

unread,
Nov 15, 2016, 1:56:02 PM11/15/16
to
If you give up, you are not on the royal road.

Brian
Ebenezer Enterprises - If you can't join 'em, beat 'em.
http://webEbenezer.net

bitrex

unread,
Nov 17, 2016, 9:29:27 AM11/17/16
to
The natural progression of any Internet argument on a point of
"technical disagreement":

Guy #1: "There is only the one true path!"

Guy #2: "That's not true anymore. An outmoded way of thinking from
another era. Do what you want!"

Guy #3: "I think neither of you can see the forest for the trees. You
should really be asking - what's appropriate given a particular situation?"

Guy #4: "I guess <technical thing> is just a tough problem, these days."

http://www.ericberne.com/games-people-play/why-dont-you-yes-but/

0 new messages