should getInstance() be idempotent?

P

Patrick May

Alex Hunsley said:
I thought you might be thinking about the inner-class idea. I've
never heard it called envelope-letter but now I know!

It seems that my C++ background is showing.
Just so I can be clear I'm thinking along the same lines, is this
basic example what you mean by the envelope-letter:
[ good example elided -- pjm ]

That's a good way of using inner classes to accomplish the goal.
If the implementation can be used separately from the Singleton in
other contexts (not as common a situation), the same thing can be done
without the inner class.

Regards,

Patrick
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

jlowery05 schreef:
Seems it should be, at least if there's state involved. What about
pooled Singletons, though? In that case I wouldn't necessarily expect
the same object to come back with every call.

Seeking opinions...

How about getInstance(Symbol, List), which returns the unique instance
which contains that particular symbol and that particular list of whatever?

H.
--
Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFEFUyTe+7xMGD3itQRAjHxAJ4s5OX+EGnQeczvtqGxsdO0OPyrJACfXdjg
3pUSOKlwjYca90DdaqlAaMs=
=lmbb
-----END PGP SIGNATURE-----
 
O

Oliver Wong

jlowery05 said:
The reason for bringing up this topic was that I came across some code
where a class' getInstance() method was returning a static instance
variable that was set in its constructor... bad code, IMO, but it got
me thinking if one should expect getInstance() to return the same
object everytime.

So my thought now is "yes, it should", and if you want to do something
schmancy with multiple singleton instances, then you should be using a
factory to dole them out and manage them.

If the method has documentation, then you should read the documentation
as to whether it is intended to return the same object every time, intended
to return a different object every time, or doesn't define whether the
objected returned is the same one or a different one.

If there is no documentation, then with a name like "getInstance", I
wouldn't automatically assume it returns the same instance every time; I'd
treat it as "undefined."

If it were called "getNewInstance" (and had no documentation), then I'd
assume it returns a different object every time.

If it were called "getSingletonInstance" or "getSoleInstance" (and had
no documentation), then I'd assume it returns the same object every time.

- Oliver
 
O

Oliver Wong

Chris Uppal said:
A curious question relating to a recent thread: should a MonoState
instance be considered to be immutable ?

I think the whole point of MonoState was for it to be NOT immutable.
That is, somewhere, you modify the state of a MonoState, and every else, all
other instances of the same MonoState class are instantly, magically
updated.

- Oliver
 
K

Kent Paul Dolan

jlowery05 said:
So my thought now is "yes, it should", and if you
want to do something schmancy with multiple
singleton instances, then you should be using a
factory to dole them out and manage them.

For an instance I encounter where you might want to
do exactly that:

I run a Java version, from Sean Luke, of the
Mersenne Twister pseudo-random number generator
(PNG).

Normally I run it as a singleton, with synchronized
access from the dozens of places and several threads
where my application wants random numbers, to save
memory footprint; the Twister keeps a fairly huge
amount of state, and I cannot afford to have dozens
of instances' state cluttering RAM.

However, it is well known in the cryptography
community that in a sufficiently high-dimensional
space, the output of a congruential generator PNG
forms a very regular lattice in that space.

So, if I have two groups of places I need PNG
output, but I don't want to take the risk of them
being mutually correlated in lockstep, I'd want to
create _two_ singleton Twister instances,
initialized them by separate mechanisms, and use
them to parcel out independent streams of PNG
output. The two groups would be uncorrelated,
because how many calls to the Twister each makes is
data dependent, in two disparate data streams.

Each group of clients would then gain references to
its associated Twister instance, and the lockstep
would be broken.

FWIW

xanthian.
 
J

jlowery05

If you're going to store an instance id, you might as well store the
instance itself.
I suppose there could be an case where the instance is large and you
don't want to hold a direct reference to it for GC purposes, but why
not use WeakReference then?
 
A

Alex Hunsley

Chris said:
Wow! I couldn't have asked for a more striking demonstration of the
Dark Side of patterns.

Why bother with the word "demonstration"? Wouldn't the words "act of
showing or making evident" have done just as well? :)
Would it have killed anyone to say, for example:

"If there should only be one logical instance of the implementation,
the class should handle that by sharing some OO model of the shared
state while still giving each client its own object to hide that
implementation detail."

"Suppose, though, that it is important to prevent creating a copy of
an object per client, in a large application, for performance
reasons."

No, it wouldn't have hurt. It's a trade-off - if someone knows the
principle already, by a certain name, it can be simpler to be terse, if
you believe they are going to know what you mean.
Someone else was talking about MonoState, so I presumed they'd
understand the 'Flyweight' reference, and I think they did. It's my
fault that I wasn't clear enough about why MonoState would reduce the
effectiveness of Flyweight. This doesn't automatically mean referring to
design patterns is evil, though.
And we'd be in a much better place, without anyone assuming some intent
in some pattern name that was never really there. Why, oh why, do
design patterns have to block the natural ability to communicate?

Step 1: Read about a design pattern.
Step 2: Understand a design pattern.
Step 3: Practice a design pattern.
Step 4: Internalize a design pattern.
Step 5: Communicate clearly without using Capitalized Name.

IME, failure in step five follows directly from a weak or incomplete
step four (or occasionally, two).

I think you're jumping the gun a little here.

If someone else is comfortable with using a pattern name to refer to a
concept or idea, it seems a little long winded for me to not use a
pattern name, if it is appropriate, in my reply to them. Yes, I should
have been clearer in the exact aspect I was referring to, however.

Out of interest, do you ever use words with complex meanings? If yes,
then why? Isn't it easier for everyone if you just use a longer
collection of simpler words? Does you using a complex word mean that
you've failed to internalise or understand their meaning? Does this mean
that you have to think about everything you see and do in terms of the
complex words? (Hmm, we're straying into Chomsky land here, perhaps.)
Instead of continuing to actually
design, the developer attempts to compensate by carrying around a
dictionary of patterns in his/her head, and more or less applying them
wholesale. The result is a rather rigid entity that's unable to adapt
to the situation at hand. This is accompanied by (and largely caused
by) an inability to even talk about the design in language that admits
to adaptation, if there's no Capitalized Name for the adaptation.

Some people certainly use design patterns as a proverbial golden hammer
and view the world through rose-tinted design glasses, yes.
 
C

Chris Smith

Alex Hunsley said:
Why bother with the word "demonstration"? Wouldn't the words "act of
showing or making evident" have done just as well? :)

Indeed, but no one misunderstood me because I said "demonstration".

The problem here is not with definitions, but rather with taking a set
of several design decisions that are demonstrated together in some book,
and using a single word to refer to all of them. To be fair, there's
often (though not always) some degree of synergy between the various
design decisions demonstrated in a pattern. Nevertheless, their primary
benefit is that you've now seen each of those design decisions being
made, and what implications they had, at least in a very limited
context.
No, it wouldn't have hurt. It's a trade-off - if someone knows the
principle already, by a certain name, it can be simpler to be terse, if
you believe they are going to know what you mean.

And I am disputing that there is "a" principle here. My copy of the GoF
book defines Flyweight using an inheritance tree for the flyweight class
and a separate factory class which are in no way related to the idea of
sharing objects, as well as implying some kind of hierarchical
composition which certainly isn't relevant to your point, but is
nevertheless very often associated with this pattern name in people I've
talked to. Though I've often used shared objects, I can't recall ever
using the whole set of classes in this book.

And that's the point. Your comment was not about Flyweight, but about
the performance cost of creating a large number of objects. The term
"Flyweight" is, in my experience, pretty much useless in terms of real
design discussions because of all this conceptual baggage that quite
rarely comes together in exactly that way. Flyweight is a bit extreme
in that sense, but the general idea applies to most patterns (and, when
it doesn't, the "pattern" name was generally in wide use prior to anyone
writing a patterns book anyway).
I think you're jumping the gun a little here.

And I figured you would probably think so. If you didn't disagree with
me, it would have been a little silly for you to have written that prior
message.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Uppal

Oliver Wong wrote:

[me:]
I think the whole point of MonoState was for it to be NOT immutable.
That is, somewhere, you modify the state of a MonoState, and every else,
all other instances of the same MonoState class are instantly, magically
updated.

The point I was hinting at was that it depends on how you see "mutability". In
one very definite, if rather literal-minded, sense the instances are clearly
immutable. They don't have any local state, so they cannot have any local
state that changes. OTOH, they certainly behave as if they change, so they
behave as if they have state (somewhere). IIRC you recently distinguished
between internal and external mutability -- these things are internally
immutable, externally mutable. In my terms the /location/ of the state is
unimportant, they behave as if they are mutable, so they are.

(Which is why I have doubts about the mutable/immutable distinction when
applied to OO. It's fine and dandy for informal discourse, but if it were
added to the language as a keyword, then there would be considerable potential
for confusion and/or misuse.)

Which makes these things rather strange from an OO perspective. If we take the
objects' behaviour as the most (or only) important knowledge we have about
them, then the fact that they all behave in the same way (in lockstep) is
extremely unusual. Not wrong, but also not something that is "just an
implementation detail". So the design is exposing itself just as clearly as it
did if we used an explicit Singleton.

-- chris
 
O

Oliver Wong

Chris Uppal said:
Oliver Wong wrote:

[me:]
I think the whole point of MonoState was for it to be NOT immutable.
That is, somewhere, you modify the state of a MonoState, and every else,
all other instances of the same MonoState class are instantly, magically
updated.

The point I was hinting at was that it depends on how you see
"mutability". In
one very definite, if rather literal-minded, sense the instances are
clearly
immutable. They don't have any local state, so they cannot have any local
state that changes.

Ah, I see your point now. The implementation for MonoState I saw was to
just declare every field in the object as static. So my brain registered the
following facts: {"object has fields", "no 'final' keyword in sight"} and
came to conclusion: {"object is imutable"}. But now that you've reminded me
that the state is "somewhere else", I can see the case being made for
considering the object to be immutable.
OTOH, they certainly behave as if they change, so they
behave as if they have state (somewhere). IIRC you recently distinguished
between internal and external mutability -- these things are internally
immutable, externally mutable. In my terms the /location/ of the state is
unimportant, they behave as if they are mutable, so they are.

I'm in agreement with you. I didn't use the terms "internally mutable"
and "externally" mutable though (not sure what those terms would mean);
rather I was spoke of "immutable from the compiler's perspective" and
"immutable from the (client) programmer's perspective". I suggested, like
you it seems, that the (client) programmer's perspective is more important.
(Which is why I have doubts about the mutable/immutable distinction when
applied to OO. It's fine and dandy for informal discourse, but if it were
added to the language as a keyword, then there would be considerable
potential
for confusion and/or misuse.)

I have a "favorite" definition of "immutable", but I know that not
everyone uses this definition, so I often don't assume that the person I'm
speaking to shares this definition. It says that an immutable object is an
object for which there does not exist a sequence of method calls which would
change the apparent state of the object.
Which makes these things rather strange from an OO perspective. If we
take the
objects' behaviour as the most (or only) important knowledge we have about
them, then the fact that they all behave in the same way (in lockstep) is
extremely unusual. Not wrong, but also not something that is "just an
implementation detail". So the design is exposing itself just as clearly
as it
did if we used an explicit Singleton.

I think to say that an object is a "Singleton" is also a description of
its behaviour (or at least, it says something about the behaviour of its
constructors and factory methods). And the JavaDocs should document the
behaviour of the objects. So as long as the author clearly writes that the
object is a "singleton" or is a "monostate", I'm personally fine with it.

If there is no documentation, I figure singleton would be easier to
"detect", as it tends to have an obvious signature (all constructors are
private), whereas monostate doesn't seem to have such an obvious signature
(a bunch of static fields, might lead to a lot of false positives if that's
the criterion used to detect monostates).

- Oliver
 
C

Chris Uppal

Oliver said:
I'm in agreement with you. I didn't use the terms "internally mutable"
and "externally" mutable though (not sure what those terms would mean);
rather I was spoke of "immutable from the compiler's perspective" and
"immutable from the (client) programmer's perspective". I suggested, like
you it seems, that the (client) programmer's perspective is more
important.

I'd misremembered. Pity really since I rather liked the terms ;-)

By internal mutability (or immutability) I meant that the observer is looking
at it from the point of view of the object itself -- i.e. focussing on what's
inside it, it's own fields. External (im)mutability is how it looks from
outside the object -- the POV of every other object and every programmer except
someone writing the code for that class.

I have a "favorite" definition of "immutable", but I know that not
everyone uses this definition, so I often don't assume that the person I'm
speaking to shares this definition. It says that an immutable object is an
object for which there does not exist a sequence of method calls which
would change the apparent state of the object.

From outside the object (which, IMO, is the only POV that should matter to any
programmer, not just to "client" programmers), state (and hence mutability) is
not really a property of an object, but of a /system/ of objects. Individual
object's behaviour will typically change in response to the events "seen" by
the system, but you have no reason to know or care exactly /which/ object holds
onto which parts of the state. You do care and should care what effects
sending, say, close() to a stream object will have on its subsequent behaviour,
but you have no reason to care where (or even whether) there's a
boolean isClosed;
flag. Maybe "openness" is implemented as a list of currently open instances
held in a class field.

-- chris
 

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,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top