On Sat, Aug 27, 2011 at 4:05 AM, rantingrick <rantingr...@gmail.com> wrote:
> Now take a look at MY simple ONE module solution. It has JUST enough
> methods and NOT a single more!

I disagree - create_widgets() is completely unnecessary in the
presence of show(), unless it's possible to show the dialog, hide it,
and then re-show it without recreating the widgets.


On Sat, Aug 27, 2011 at 4:16 AM, Steven D'Aprano
<steve+comp.lang.pyt...@pearwood.info> wrote:
> I can think of at least five reasons apart from re-use why it might be
> appropriate to pull out code into its own function or method even if it is
> used in one place only:

I'm glad you say "might be", because your five reasons aren't always
reasons for refactoring. I'll play devil's advocate for a moment,
because discussion is both fun and informative: :)

> (1) Extensibility. Just earlier today I turned one method into three:
> I did this so that subclasses could override the behaviour of each component
> individually, even though the caller is not expected to call raw_select or
> choose directly. (I may even consider making them private.)

Definitely, but it's no value if you make every tiny thing into your
own function. Sometimes the best way to code is to use lower-level
functionality directly (not wrapping input() inside raw_select() for
instance), and letting someone monkey-patch if they want to change
your code. A judgment call.

> (2) Testing. It is very difficult to reach into the middle of a function and
> test part of it. ... By splitting it
> into functions, you can test each part in isolation, which requires much
> less work.

Yes, but 100% coverage isn't that big a deal. If the function does
precisely one logical thing, then you don't _need_ to test parts in
isolation - you can treat it as a black box and just ensure that it's
doing the right thing under various circumstances. However, this ties
in nicely with your next point...

> (3) Fault isolation. If you have a 100 line function that fails on line 73,
> that failure may have been introduced way back in line 16. By splitting the
> function up into smaller functions, you can more easily isolate where the
> failure comes from, by checking for violated pre- and post-conditions.

... and here's where #2 really shines. If you break your function in
two, the natural thing to do is to test each half separately, with the
correct preconditions, and examine its output. If your fault was on
line 16, your test for that half of the function has a chance of
detecting it. I don't have a Devil's Advocate put-down for this one,
save the rather weak comment that it's possible to check pre- and
post-conditions without refactoring. :)

> (4) Maintainability. It's just easier to document and reason about a
> function that does one thing, than one that tries to do everything. Which
> would you rather work with, individual functions for:
> ... omnomnom ...
> Even if each function is only called once, maintenance is simpler if the
> code is broken up into more easily understood pieces.

Yes, as long as you do the job intelligently. Goes back to what I said
about naming functions - in your kitchen example, every function has a
self-documenting name, which means you've broken it out more-or-less
correctly. (I'd still want to have
prepare_and_serve_five_course_meal() of course, but it would be
calling on all the others.) Breaking something out illogically doesn't
help maintainability at all - in fact, it'll make it worse. "So this
function does what, exactly? And if I need to add a line of code,
ought I to do it here, or over there? Does anyone else actually call
this function? MIGHT someone be reaching into my module and calling
this function directly? I'd better keep it... ugh."

> (5) Machine efficiency. This can go either way.

And that's the very best thing to say about efficiency. Ever. In C, I
can write static functions and let the compiler inline them; in Java,
I tried to do the same thing, and found ridiculous overheads. Ended up
making a monolith rather than go through Java's overhead. But if I'd
changed what VM I was running it on, that might well have changed.
Profile, profile, profile.

> So that's four really good reasons for splitting code into functions, and
> one borderline one, other than code re-use. There may be others.

I'm sure there are. But let's face it: We're programming in PYTHON.
Not C, not Erlang, not Pike, not PHP. Python. If this has been the
right choice, then we should assume that efficiency isn't king, but
readability and maintainability probably are; so the important
considerations are not "will it take two extra nanoseconds to execute"
but "can my successor understand what the code's doing" and "will he,
if he edits my code, have a reasonable expectation that he's not
breaking stuff". These are always important.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to