lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Preliminary emit_ledger code refactoring


From: Greg Chicares
Subject: Re: [lmi] Preliminary emit_ledger code refactoring
Date: Wed, 29 Jul 2015 17:37:18 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Icedove/31.3.0

On 2015-07-29 14:14, Vadim Zeitlin wrote:
> On Wed, 29 Jul 2015 10:14:23 +0000 Greg Chicares <address@hidden> wrote:
> 
> GC> On 2015-07-16 20:41, Vadim Zeitlin wrote:
> GC> [...]
> GC> >         Use ledger_emitter class instead of [pre_]emit_ledger() 
> functions.
> GC> 
> GC> I'm studying this patchset now, and I'm stuck on this particular patch.
> GC> 
> GC> Previously the ledger-emitter implementation was just two functions:
> GC>   double LMI_SO pre_emit_ledger(...);
> GC>   double LMI_SO     emit_ledger(...);
> GC> 
> GC> It might seem sensible enough to combine those into one single class
> GC>   class LMI_SO ledger_emitter
> GC> because, after all, some of the arguments of those two functions were
> GC> the same and may as well be stored as members.
> 
>  The real impetus behind this change is the need to store as members
> something that is _not_ passed as arguments to these functions

I'm not sure I understand. Are we really talking about the state of the
PDF generator? Or is there some required argument beyond those used today,
which will need to be added in the future?

> GC> OTOH, this patch adds
[...numerous classes...]
> GC> all of which makes it much more complex.
> 
>  I think it depends on the point of view.

Thank you for the detailed rationale. While I'm pondering it, let me ask
some questions about fine points.

>  Next, ledger_emitter_single_output_base is really just a way to reuse code
> and avoid duplicating these 2-3 lines which are the same for the 3 classes
> (2 existing ones and a new one).

You have
  ledger_emitter::start()
for the old pre-emission step (PrintRosterHeaders(), e.g.), and
  ledger_emitter::end()
for a post-emission step that hasn't been required in the past. Let me
refer to those things here as "headers" and "footers", which are both
optional and surround a non-optional "body".

Premium quotes require both a header and a footer. Would that necessitate
a new intermediate class? Would we wind up with a hierarchy like...
  class body              // body only, no header or footer possible
  class body_with_header // but no footer
  class body_with_footer // but no header
  class body_with_header_and_footer
which would grow exponentially if we ever add another optional component
or find a case where the "body" is actually optional?

Or is class ledger_emitter_single_output_base instead to be understood as
a ledger_single_format_emitter that actually makes use of a tsv_filepath,
as distinguished from those that ignore it?

> GC> > They are needed because the
> GC> > PDF generation can't be done in a single pass, if only because of the 
> page
> GC> > numbers (but also for a few other reasons), and so the code needs to 
> keep
> GC> > its state between the calls to emit_ledger().
[...]
>  There is the number of pages and also the totals which can only be
> computed at the end, so the generation just can't be done in a single pass.
> Because of this, all the data is just stored initially and then everything
> is generated at once when end() is called.

It's too bad I got pulled away for other tasks, so I can't remember whether
I've mentioned this before...but the 'composite' is a summary whose purpose
is to provide totals of all data.

There's one more detail I wanted to ask about. In this code:

        if(emission & mce_emit_pdf_to_printer)
            {
            emitters_.push_back(new ledger_emitter_pdf_to_printer());
            }
        if(emission & mce_emit_pdf_to_viewer)
            {
            emitters_.push_back(new ledger_emitter_pdf_to_viewer());
            }
        ...

is there a reason to manage dynamic allocation ourselves with new() and
delete() and a vector of pointers:
  std::vector<ledger_single_format_emitter*> emitters_;
? Could we instead do
  std::vector<ledger_single_format_emitter> emitters_;  // no pointers
  emitters_.push_back(ledger_emitter_pdf_to_printer()); // no new()
and let the vector delete its contents when it goes out of scope?

> while I know of people who use C++ without
> exceptions, templates or deep object hierarchies, I've never heard about
> any rules against using _simple_ objects.

Think of it this way--imagine that you have written some well-tested
code that uses the printf() family extensively, and I propose replacing
it with iostreams. My version is twice as long, but I can certainly say
that it's typesafe. Do you apply my changes with no hesitation at all?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]