Stevan -

    If I understand you correctly, the main difference between
preconditions and ensures are the way they are handled if they fail.

If a precondition fails, raise an exception.
If an ensure block fails the first time, run the using block.
If an ensure block fails the second time, raise an exception.

In the case of deleting a file, that's the perfect situation for an
ensure/using pair. You're attempting to make sure that a file is
deleted. So, you're trying to ensure that, once this step is
completed, the file doesn't exist.

step DeleteFile =>
    ensure { !-f $filename }
    using { unlink $filename }
;

I'm still trying to find a place where you need an assertion around a
using block. The only thing I can think of is if you want to make sure
you avoid catastrophic failures that are outside your control.
Something like databases are down or NFS mounts are unavailable. But,
I would think you'd want to attempt to reconnect, so you'd do
something like:

step MakeSureDbhConnected =>
    ensure { $dbh->is_connected }
    using { $dbh->reconnect( @vars ) }
;

Or something similar for NFS mounts and other network resources.

What am I missing?

Rob

On Tue, 23 Nov 2004 14:03:35 -0500, Stevan Little
<[EMAIL PROTECTED]> wrote:
> Rob,
> 
> On Nov 23, 2004, at 12:50 PM, Rob Kinyon wrote:
> > I'm a little confused as to why one would need pre- and
> > post-conditions at all. The "ensure" block would seem to handle the
> > whole thing as it is both the pre- and post-condition to the "using"
> > block. (What about aliasing "doing" to "using"?)
> 
> There may be preconditions which need to be true prior to running the
> code, but which are false after the code is run. For instance, deleting
> a file. I want to be sure its there first, then delete it, and
> afterwards the file is gone so the pre-condition would fail.
> 
> Also the ensure works by being false before the using block and then
> true afterwards, so using it as a pre-condition would be difficult IMO
> since you would have to define the negative rather than the positive.
> 
> Steve
> 
> 
> 
> 
> > The only thing I can see being useful is allowing for more than one
> > "ensure" and more than one "using" block. This would allow me to write
> > something like:
> >
> > step Foo =>
> >     ensure { -f '/net' }
> >     ensure { -f '/net/foo' }
> >     ensure { The actual thing I care about }
> >     using { Do something here }
> >     using { Do something else here}
> > ;
> >
> > The benefit is that you can do things like:
> >
> > sub foo { blahblah }
> > sub bar { blahblah }
> >
> > step Foo =>
> >     ensure \&foo
> >     ensure \&bar
> >     using { Do something }
> > ;
> >
> > And have reusable ensure clauses. Sure, you could do:
> > step Foo =>
> >     ensure { foo() && bar() }
> >     using { Do something }
> > ;
> >
> > But, there's no reason not to allow it, that I can think of. This is
> > especially true when treating them as assertions.
> >
> > *thinks a little bit*
> >
> >>> I've been thinking about what to do if either the C<ensure> or the
> >>> <using>
> >>> blocks are missing.  Currently the module throws an exception, but I
> >>> don't
> >>> think that's right.  In an earlier draft of the module, I had an
> >>> "ALWAYS"
> >>> variant that ran the C<using> clause whether or not the C<ensure> was
> >>> present.  Surely
> >>>
> >>>   step withoutUsing =>
> >>>     ensure { -f '/boot/vmunix' }
> >>>   ;
> >>>
> >>> should be treated as an assertion: if it's true, go on, if false,
> >>> throw an
> >>> exception.  But
> >>>
> >>>   step withoutEnsure =>
> >>>     using { mkdir "/net" }
> >>>     ;
> >>>
> >>> seems somewhat useless to me.  Considering the fact that other blocks
> >>> may
> >>> exist (sanity/rollback/etc.), perhaps a missing C<ensure> should be
> >>> treated specially so it fails before C<using> and succeeds after.
> >>
> >> IMO lack of them is programmer error, and should throw an exeption.
> >> What is the use of using your framework but to use the ensure and
> >> using
> >> directives and get those benefits? Otherwise are you not just adding
> >> several levels of indirection for a subroutine call?
> >
> > I agree that ensure should always be there. using not being there ...
> > *shrugs* - not so big a deal.
> >
> >> I also have a feature suggestion for you, as this is something I
> >> recently ran into. How about the ability to have a timeout on the
> >> block? I recently had a problem where a cron job was hanging for about
> >> 8 hours because a very odd condition occurred which caused a
> >> subprocess
> >> to require user input. The result was that everything seemed to report
> >> success, but the process was not yet complete (and so couldn't fail
> >> and
> >> tell me what was wrong). Not until I checked the output of top did I
> >> see what was wrong. No granted it was my own stupid fault (I am mostly
> >> a programmer, and I am a mediocre sys-admin at best), but a timeout on
> >> that particular block of code would have been nice.
> >
> > I like the idea of a "no_longer_than" with a prototype of ($@) that
> > takes a number of seconds to run. Alternatively, you could use a
> > format of /\d+[A-Za-z]?/ and allow things like 30m, 2d, 12h, 3600s,
> > etc.
> >
> > ********
> >
> > NOTE: One thing that you need to be aware of is the potential for
> > memory leaks and other problems using the & prototype. See
> > http://www.perlmonks.org/?node_id=278900 for more info.
> >
> > ********
> >
> > _______________________________________________
> > sw-design mailing list
> > [EMAIL PROTECTED]
> > http://metaperl.com/cgi-bin/mailman/listinfo/sw-design
> >
> 
>

_______________________________________________
sw-design mailing list
[EMAIL PROTECTED]
http://metaperl.com/cgi-bin/mailman/listinfo/sw-design

Reply via email to