object.enable() anti-pattern

Mark Janssen dreamingforward at gmail.com
Fri May 10 22:43:52 EDT 2013


>>>>>> There is no sensible use-case for creating a file OBJECT unless it
>>>>>> initially wraps an open file pointer.
>>
>>> So far the only counter-examples given aren't counter-examples ...
>>
>> Well, sure, if you discount operations like "create this file" and
>> queries like "could I delete this file if I wanted to?" [0] as methods
>> of the file system rather than of a hypothetical file object.
>>
>> What about a distributed system?  Suppose I want to create a file object
>> in one place, and send that object to the another place for the file to
>> be read from or written to [1]?  Suppose that for security reasons, I
>> have to do it that way, because the first place can only create the
>> objects, and the second place can only access the underly file contents
>> through an existing object?
>
> Unless you have re-implemented the file I/O system, it doesn't matter. If
> your file objects are based on C I/O, then even if the first server
> cannot read or write to the files it still creates file objects in an
> open state, because that is how C works.
>
> Or maybe the first server only creates some sort of proxy to the real
> underlying file object. Or maybe you're re-implemented the I/O system,
> and aren't following C's design. Since you're just making this up as a
> thought experiment, anything is possible.
>
> But either way, that's fine. You've found an object where it does make
> sense to have an explicit "make it go" method: first one entity has
> permission to construct the object, but not to open the underlying file.
> Another entity has permission to open the underlying file, but not to
> create the object. I have no idea whether this is a reasonable security
> design or not, it actually sounds a bit rubbish to me but what do I know?
> So let's treat it as a reasonable design.
>
> As I've said, repeatedly, that's not what I'm talking about.
>
> When you DON'T have useful things that can be done with the object before
> calling "enable", then it is an anti-pattern to require a separate call
> to "enable" method, and the enable functionality should be moved into the
> object constructor. If you DO have useful things that can be done, like
> pass the object to another entity, for security, then that's a whole
> 'nuther story.

You're missing one other case:  if there's useful things that can be
checked before calling enable().  Remember, on multi-user and/or
multi-processing systems, there could be contention for a slow
resource.  If you automatically open a file for write, you're
preventing everyone else from writing and potentially reading it.  So
there is something useful: did that file exist?  Is that resource
available for writing?

Prior to such hi-level languages like Python and reliable hardware,
such fine-grained control was important and vital.   Now it can
probably be relegated to special OS libraries.

Mark

> Really, what I'm describing is *normal* behaviour for most objects. We
> don't usually design APIs like this:
>
> n = int("42")
> n.enable()
> m = n + 1
> m.enable()
> x = m*2 + n*3
> print x - 1  # oops, raises because I forgot to call x.enable()

Again, you only do that for shared resources.  In this case, memory
would have to be a (protected) shared resources, but the OS manages
memory allocation, so it's not an issue.

Mark

> That's a rubbish API, and for simple data-like objects, we all agree it
> is a rubbish API. So why accept the same rubbish API just because the
> object is more complicated?

I think I just told you, but let me know ..... :)

> For my next controversial opinion, I'm going to argue that we should do
> arithmetic using numbers rather than by inserting lists inside other
> lists:

Try arguing that we should have a common message-passing syntax.

> # Do this:
>
> count = 0
> count += 1
>
> # Not this:
>
> count = []
> count.insert(0, [])

That's actually what they do in "set theory", believe it or not.

MarkJ
Tacoma, Washington



More information about the Python-list mailing list