Implicit initialization is EXCELLENT

  • Thread starter Steven D'Aprano
  • Start date
S

Steven D'Aprano

This is not strictly Python, although it is peripherally relevant.

Some month or three ago, I read an article or blog post about API design,
specifically the wrong-headedness of insisting that callers manually
initialise instances using a separate step after creation.

The argument goes, if your API looks something like this:

instance = Spaminator(extra_truffles=False)
instance.activate()
instance.nom_nom_nom()
=> prints "yummy spam, the food of the Gods!!!"

chances are that you are doing it wrong and your users will hate you. Why
force the user to manually "flip the switch" (so to speak)? It's not like
they can possibly avoid it:

another_instance = Spaminator(with_extra_cheese=True)
another_instance.nom_nom_nom()
=> raises InactiveInstanceError("you must activate the instance first")

What? No! Just activate yourself!

Exceptions to this rule are if the Spaminator has side-effects (e.g. files,
in which case the user may want finer control in when they are opened and
closed), or if there are meaningful operations you can perform on an
inactive Spaminator.

Python generally follows this design. Apart from files, I can't easily think
off the top of my head of any types that require a separate
open/start/activate call before they are usable. It's also relevant to
tkinter, which will implicitly create a root window for you when needed.
Since you can't do anything without a root window, I don't see the benefit
in forcing the user to do so. When they need to learn about root windows,
they will in their own good time.

Now, I have an ulterior motive in raising this issue... I can't find the
original article I read! My google-fu has failed me (again...). I don't
suppose anyone can recognise it and can point me at it?
 
M

Mel

Steven D'Aprano wrote:
[ ... ]
Python generally follows this design. Apart from files, I can't easily
think off the top of my head of any types that require a separate
open/start/activate call before they are usable. It's also relevant to
tkinter, which will implicitly create a root window for you when needed.
Since you can't do anything without a root window, I don't see the benefit
in forcing the user to do so. When they need to learn about root windows,
they will in their own good time.

In wx, many of the window classes have Create methods, for filling in
various attributes in "two-step construction". I'm not sure why, because it
works so well to just supply all the details when the class is called and an
instance is constructed. Maybe there's some C++ strategy that's being
supported there.

Mel.
 
S

Stefaan Himpe

Hello,

I agree with the contents of this post.

I see a similar problem with API's requiring to initialize all kinds of
data using setters/properties instead of receiving it in the initializer
(or constructor).
Python generally follows this design. Apart from files, I can't easily think
off the top of my head of any types that require a separate
open/start/activate call before they are usable.

database connections, network connections, spawning expensive
processes/threads, things that benefit from lazy evaluation...
Now, I have an ulterior motive in raising this issue... I can't find the
original article I read! My google-fu has failed me (again...). I don't
suppose anyone can recognise it and can point me at it?

My sarcasm detector warns me not to add a link, although perhaps it's
time for recalibration (after all, summer season started) :)

Best regards,
Stefaan.
 
J

John Gordon

My sarcasm detector warns me not to add a link, although perhaps it's
time for recalibration (after all, summer season started) :)

He's not asking for a link to the "Implicit initialization is EVIL"
thread; he's asking for a link to the original article he read elsewhere
which praised the bendfists of implicit initialization.
 
R

rantingrick

This is not strictly Python, although it is peripherally relevant.

Some month or three ago, I read an article or blog post about API design,
specifically the wrong-headedness of insisting that callers manually
initialise instances using a separate step after creation.

The argument goes, if your API looks something like this:

instance = Spaminator(extra_truffles=False)
instance.activate()
instance.nom_nom_nom()
=> prints "yummy spam, the food of the Gods!!!"

chances are that you are doing it wrong and your users will hate you. Why
force the user to manually "flip the switch" (so to speak)? It's not like
they can possibly avoid it:

I completely agree!
Exceptions to this rule are if the Spaminator has side-effects (e.g. files,
in which case the user may want finer control in when they are opened and
closed), or if there are meaningful operations you can perform on an
inactive Spaminator.

Agreed again!
It's also relevant to
tkinter, which will implicitly create a root window for you when needed.

WRONG.
Oh wait,
of course,
you are correct!
YES!
Maybe we should have library modules import only when needed! i mean,
who needs those pesky import statements anyways! Sure it will slow
down run time BUT WHO CARES! My gawd, you just opened my mind to so
many possibilities! Why stop at library modules, if it is not there
just download the source at run time! Guido really dropped the ball on
this one folks.
Since you can't do anything without a root window, I don't see the benefit
in forcing the user to do so.

The reason is simple. It's called order. It's called learning from day
one how the order of things exists. Widgets are part of windows, not
the other way around. Saving a few keystrokes is not acceptable if you
jumble the understanding of a new student. To understand and use
Tkinter properly you must understand the order of window->widget.
When they need to learn about root windows,
they will in their own good time.

So you would start drivers education class with road construction? Or
the history of the internal combustion engine? Who cares about
actually *driving* the car.
 
C

Chris Angelico

So you would start drivers education class with road construction? Or
the history of the internal combustion engine? Who cares about
actually *driving* the car.

I believe that starting driver ed with some basics of how an internal
combustion engine works would be a Good Thing. If you're going to be
in control of a ton of steel that's capable of moving at a hundred
kays, you ought to know at least a bit about what provides the kinetic
energy.

There's a difference between comprehension and jumping through hoops.
In your driver ed example, I don't believe that the accelerator pedal
should be replaced with a flexible fuel-line that the driver squeezes
to control flow to the engine; but on the other hand, I don't think
the brake pedal should be replaced by a single button saying "stop
car" either.

Arrogance is a normal part of designing programming languages (see
Larry Wall's comments regarding Perl, for instance). But arrogance to
the extent of forcing your views on programmers is generally resented,
and with good reason. If you force too much on people, they'll go
elsewhere.

ChrisA
 
R

rantingrick

I believe that starting driver ed with some basics of how an internal
combustion engine works would be a Good Thing. If you're going to be
in control of a ton of steel that's capable of moving at a hundred
kays, you ought to know at least a bit about what provides the kinetic
energy.

How about kinetic energy itself? If you know *what* produces power to
induce kinetic energy into the vehicle but not *how* the laws of
physics govern kinetic energy; what damn good is that going to do for
you? How about some basics of safe/defensive driving? How about
considering the good of the many instead of the you?
There's a difference between comprehension and jumping through hoops.

Likewise for priorities and acting aloof.
If you force too much on people, they'll go
elsewhere.

Why all this running away with tail between legs?
Do these these people have extremely small eggs?
I wish they would stand firm and put up a fight
instead they're just cowards spewing more endless tripe.
 
C

Chris Angelico

 Why all this running away with tail between legs?
 Do these these people have extremely small eggs?
 I wish they would stand firm and put up a fight
 instead they're just cowards spewing more endless tripe.

Standing up and fighting takes effort. It's a lot easier - and a lot
more time-efficient - to ignore idiots and trolls and just get some
work done. I think I'll do that, right now.

Chris Angelico
 
U

Ulrich Eckhardt

rantingrick said:
On Jul 5, 10:26 am, Steven D'Aprano <steve
Since you can't do anything without a root window, I don't see the
benefit in forcing the user to do so [create one explicitly].

The reason is simple. It's called order. It's called learning from day
one how the order of things exists. Widgets are part of windows, not
the other way around. Saving a few keystrokes is not acceptable if you
jumble the understanding of a new student. To understand and use
Tkinter properly you must understand the order of window->widget.
When they need to learn about root windows,
they will in their own good time.

So you would start drivers education class with road construction? Or
the history of the internal combustion engine? Who cares about
actually *driving* the car.

Ahem, you are the one that suggests that in order to drive a car you should
first build a road, not Steven!

That said, why should I care about the choices and steps I have for creating
main windows and the possibilities I get from doing this myself? A basic
default main window is enough for me! Further, choice implies I can make
wrong choices, too, so forcing someone to make a decision might cause
errors.

Uli
 
U

Ulrich Eckhardt

Mel said:
In wx, many of the window classes have Create methods, for filling in
various attributes in "two-step construction". I'm not sure why, because
it works so well to just supply all the details when the class is called
and an instance is constructed. Maybe there's some C++ strategy that's
being supported there.

Just guessing, is it legacy, C-with-classes code rather than C++ code
perhaps? Haven't looked at wx for a while. Such code typically lacks
understanding of exceptions, which are the only way to signal failure from
e.g. constructors.

Uli
 
S

Steven D'Aprano

Stefaan said:
My sarcasm detector warns me not to add a link, although perhaps it's
time for recalibration (after all, summer season started) :)

No! I was serious. I've spent *ages* trying to find the link to the
article... if you know it, please share.
 
I

Ian Kelly

Just guessing, is it legacy, C-with-classes code rather than C++ code
perhaps? Haven't looked at wx for a while. Such code typically lacks
understanding of exceptions, which are the only way to signal failure from
e.g. constructors.

No, wx is C++ through and through. For the why of it, see:

http://wiki.wxpython.org/TwoStageCreation

The "More Details" section is particularly illuminating.
 
S

Steven D'Aprano

Stefaan said:
Ok - I thought you were referring to some troll's rant with similar
title. I'm probably way off, but were you referring to the RAII technique?

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

Thanks Stefaan, but although it *sounds* like it should be from the title,
that's not the idea I'm talking about. Despite the name, RAII is more about
destructor/finalizer methods than initialisation. The blog post I'm looking
for is not about finalizers, but about API design: don't make the caller
give an explicit second activation call if you don't need to.
 
U

Ulrich Eckhardt

Ian said:
Mel said:
In wx, many of the window classes have Create methods, for filling in
various attributes in "two-step construction". [...]

Just guessing, is it legacy, C-with-classes code rather than C++ code
perhaps? Haven't looked at wx for a while. Such code typically lacks
understanding of exceptions, which are the only way to signal failure
from e.g. constructors.

No, wx is C++ through and through.

No namespaces. No templates but macros. No exceptions. No C++.

Sorry, I beg to differ. BTW, they say themselves that they tolerate but not
use exceptions, so they actually need two-stage construction if construction
can fail, and for exactly the guessed legacy reasons.


A C++ object is not a window, it is rather a proxy for managing the window.
As such, it can be attached or detached from the underlying window, just
like a std::fstream, so in this light it makes sense actually. Thanks for
the link!

Uli
 
I

Ian Kelly

No namespaces. No templates but macros. No exceptions. No C++.

Sorry, I beg to differ. BTW, they say themselves that they tolerate but not
use exceptions, so they actually need two-stage construction if construction
can fail, and for exactly the guessed legacy reasons.

Ah, I think I misunderstood your meaning. By "C-with-classes" I
thought you were referring to the practice of OOP in C, and my
response was to the effect that building wx requires a C++ compiler,
not just a C compiler.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top