[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] Inversion of control
From: |
Greg Chicares |
Subject: |
Re: [lmi] Inversion of control |
Date: |
Thu, 13 Sep 2018 00:31:24 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 |
On 2018-09-08 15:32, Vadim Zeitlin wrote:
> On Sat, 8 Sep 2018 15:19:41 +0000 Greg Chicares <address@hidden> wrote:
[...]
> GC> Right now, I'm just asking you to tell me whether I'm on the right
> GC> track.
>
> Yes, I think so. I.e. the most complicated is usually determining the "Fn"
> parts of code and you've already done it.
I've written something that does appear to work:
http://git.savannah.nongnu.org/cgit/lmi.git/commit/?h=odd/pagination
but it seems too ugly.
> GC> C++ member-function pointers can be unwieldy, so my first
> GC> thought would be to use this as a mixin class: make the paginate()
> GC> demonstration a member function that calls some new virtuals, then
> GC>
> GC> class page_with_tabular_report
> GC> :public numbered_page
> GC> ,protected using_illustration_table
> GC> + ,private paginator
> GC>
> GC> and reimplement that class's render() function. And I guess I'll
> GC> want a default ctor for class paginator, and an init() function
> GC> that I can call from render(). Or does another approach seem
> GC> clearly better?
>
> No, this is a perfectly good implementation of this pattern in what I
> called OO style. The main advantage of the functional style is that you do
> not have to create a new class, deriving from paginator, to use it. But in
> this case we already have a class, so this advantage is not very important.
That's where I think I went down the proverbial rabbit hole.
I didn't actually do this...
> GC> class page_with_tabular_report
> GC> :public numbered_page
> GC> ,protected using_illustration_table
> GC> + ,private paginator
...because I don't see how I can implement the pagination class's virtuals
as members of class page_with_tabular_report. The reason is that the
tabular-report class has only member functions--it doesn't have data members,
so AFAICT an instance has no state. Rather, "state" is imbued by passing
arguments, and most of the member functions take similar arguments:
(Ledger const& ledger
,pdf_writer_wx& writer
,html_interpolator const& interpolate_html
)
But arguments can't be added to pagination-class virtuals. For example,
consider (left-aligned '#' comments added for this discussion only):
void print_a_data_row () override
{
# The derived pagination class isn't a mixin, so it can't call the
# tabular-report class's members directly--so I pass an instance of that
# class into the paginator by reference. (It's called 'outer_' because
# I originally thought the paginator wanted to be a nested class.)
# Similarly, arguments to render() like 'ledger_' are passed into this
# pagination class by reference.
auto const v = outer_.visible_values(ledger_, interpolate_html_,
year_);
# 'pos_y' was a local variable in render(), which wasn't a reference to
# anything external to that function, so I made it a pagination member.
table_gen_.output_row(pos_y_, v);
# 'year' is a pure local; no problem here.
++year_;
}
> Another advantage of functional style is that you can easily mix and match
> parts of different implementations, which is impossible or at least very
> inconvenient with the OO style, i.e. if you have classes FooBar and BazQuux
> deriving from paginator, you typically can't easily define a class FooQuux
> which takes half of FooBar implementation and half of BazQuux. But again,
> in this particular case, I don't think we're going to need this.
In my 'odd/pagination' branch, I guess that, fundamentally, I was struggling
to invent a closure; and that made me wonder whether a functional style would
be better. But I'm not at all sure that it would be much different: lambdas
can capture state, but class page_with_tabular_report doesn't have any state
to capture--or, alternatively, the required state isn't the state of a class
instance, but rather the arguments passed to all the member functions. But I
don't see how I can write a conjectured virtual member like
void page_with_tabular_report::print_a_data_row() override
that captures the state of a different member function, namely
void page_with_tabular_report::render() override
Now that I have something that does have the virtue of actually working, can
you say how it might be reimplemented cleanly?
I have only one question about the original implementation: concerning
its next_page() function, did I guess correctly here...
void open_page () override
{
// "if": guesswork--next_page() seems to have been called already.
if(0 != year_) outer_.next_page(writer_);
...and in the following?
void close_page () override
{
// See open_page() above. This causes an assertion to fail:
// This function may only be called if we had reserved enough physical
// pages for these logical pages by overriding get_extra_pages_needed().
// LMI_ASSERT(0 < extra_pages_); <-- fails
// Conjecture: once the last page has been printed, asking for
// the "next" page fails because there is no next page.
// outer_.next_page(writer_);
}
- [lmi] Inversion of control [Was: Another large census error with group quotes], Greg Chicares, 2018/09/07
- Re: [lmi] Inversion of control, Vadim Zeitlin, 2018/09/08
- Re: [lmi] Inversion of control, Greg Chicares, 2018/09/08
- Re: [lmi] Inversion of control, Vadim Zeitlin, 2018/09/08
- Re: [lmi] Inversion of control,
Greg Chicares <=
- Re: [lmi] Inversion of control, Vadim Zeitlin, 2018/09/17
- Re: [lmi] Inversion of control, Greg Chicares, 2018/09/17
- Re: [lmi] Inversion of control, Vadim Zeitlin, 2018/09/17
- Re: [lmi] Inversion of control, Greg Chicares, 2018/09/17
- Re: [lmi] Inversion of control, Vadim Zeitlin, 2018/09/18
- Re: [lmi] Inversion of control, Greg Chicares, 2018/09/18
- Re: [lmi] Inversion of control, Vadim Zeitlin, 2018/09/18
- [lmi] Header pagination PR (was: Inversion of control), Vadim Zeitlin, 2018/09/18
- Re: [lmi] Header pagination PR, Greg Chicares, 2018/09/18
- Re: [lmi] Header pagination PR, Vadim Zeitlin, 2018/09/18