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: Vadim Zeitlin
Subject: Re: [lmi] Preliminary emit_ledger code refactoring
Date: Tue, 4 Aug 2015 21:47:11 +0200

On Tue, 04 Aug 2015 19:23:59 +0000 Greg Chicares <address@hidden> wrote:

GC> I don't want to inconvenience you. Tell you what. Don't merge my changes
GC> yet. Just finish (once specifications stabilize) the work you're doing
GC> elsewhere to generate PDF files, and hand it to me with the class derived
GC> from ledger_emitter_single_output_base that you would have added to
GC> 'emit_ledger.cpp'...and I'll glue it all together.

 I really think it would be better if I glued it all. I have no doubt that
you can do it, but without using git merge capabilities it's bound to be
more difficult for you. It doesn't bother me to wait as, first, I still
have the other project (table utilities) to finish and, second, to the best
of my knowledge I already did everything I could with the current
specifications, so I'm also waiting for their final form to do the rest.

GC> >  In particular I wonder about
GC> > 
GC> >   /// Each member function (except the lightweight ctor and dtor)
GC> >   /// returns time spent, which is almost always wanted.
GC> > 
GC> > comment. Does it really mean that you are not going to apply the patch
GC> > refactoring the timers neither? For me this one seemed to be even more
GC> > obviously the right thing to do as the existing code could be used as a
GC> > nice example of why separation of concerns is a good thing to have, so I'd
GC> > be rather surprised if you didn't agree with it. But then, of course, I'm
GC> > already surprised, so this is not a good argument neither...
GC> 
GC> Here I guess we'll have to agree to disagree. Suppose I have a function
GC>   void calculate();
GC> (that does exactly one job), and I always want that calculation to be
GC> instrumented...so I write
GC> 
GC>   double calculate_with_instrumentation()
GC>     {
GC>     start-timer
GC>     call calculate() [which becomes non-public]
GC>     stop-timer
GC>     return timing
GC>     }
GC> 
GC> and use that instead of calculate() everywhere.
GC> 
GC> Pros:
GC>   less code to write everywhere the function is called
GC>   can't forget to write instrumentation for each call
GC>   unifies two concerns that are intimately linked
GC> Cons:
GC>   combines two concerns that might conceivably be separated
GC> 
GC> For me, the "Pros" win, hands down.

 I don't know if it makes sense to argue, but for me this is not the case
at all as I see:

Pros:
 - A tiny bit (a single simple statement) code less to write.

Not pros:
 - Can't forget to write instrumentation: you can still forget to use the
   returned value and I'd actually argue that it's much simpler to forget
   to output (or otherwise use) the time than if you have a timer right in
   front of you.
 - Unifies two concerns that are linked: no, they're really not, timing can
   be applied to just about any operation, and saying that it's linked to
   everything is exactly equivalent to saying that it's not linked to
   anything.

Cons:
 - Either mixing unrelated things in a single function or duplicating the
   number of functions (which was just deemed to be a big problem in
   another context!) if you split them in a public and private halves.
 - Lack of clarity in the code using the function: it's absolutely not
   obvious that a function frobnicate_widget() returns the time taken while
   it's blinding obviously that starting a timer before calling it and
   getting its time afterwards does the obvious thing.
 - Extra burden on the maintainer: whenever a new function is added you
   need to think about whether it should return the time taken by it or
   not.
 - Somewhat related: this can't be generalized to non-void functions,
   unless you're ready to return pairs or tuples or do something even more
   horrible to accommodate both the natural function return value and the
   time taken by it.
 - Lack of flexibility: if you need to compute the total time taken by two
   function calls you need to sum them up together manually instead of just
   creating the timer before calling the first one and getting its value
   after calling the second one.

 I think it's the combination of the first two cons that bothers me so
much. The code really becomes confusing to read, when looking at the
function itself you have no idea why does it need to measure the time taken
by it when it seems to have nothing to do with the function job (and,
indeed, it doesn't!) and when calling it you have no idea what does it
return because this is so unexpected from the function semantics.

 Honestly, I think you're not seeing it only because you're used to it by
now, but this is very confusing to the first time reader of this code.

 Regards,
VZ

reply via email to

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