DO FOR <tablenames> TRANSACTION:

Posted by ojfoggin on 14-Apr-2010 03:18

Hi All,

Can anyone explain what this does please?

The block is...

(for example)

DO FOR order, customer, item TRANSACTION:

/* stuff */

END.

Thanks

Oliver

All Replies

Posted by ksv on 14-Apr-2010 05:20

It's a strong scope block which prevents you from using order, customer, item tables out of it. Well, actually it doesn't make much sense for me, I can't think up any use case in which this block will be really useful.

Posted by ojfoggin on 14-Apr-2010 05:31

Thanks!

It does make sense for this particular use I think.

It is in an include file that is used in a lot of places and accesses various settings/parameter tables.

Without the block I suppose it could be altering the currently selected records in the file it is included into.

Thanks again

Posted by ksv on 14-Apr-2010 07:30

It is in an include file that is used in a lot of places and accesses various settings/parameter tables


That's a bad practice I'm affraid and I'd do my best to eliminate such an include. But, yes, I agree it might indicate some problems at compile-time.

Posted by rbf on 14-Apr-2010 10:11

DO FOR order, customer, item TRANSACTION:

/* stuff */

END.

Like Sergey said it strongly scopes the DO block to the named buffers. If the code is only limited to the snippet above that can certainly create problems at compile time and is not very useful.

However, if the actual code is something like this:

PROCEDURE foo:

  DEF BUFFER order FOR order.
  DEF BUFFER customer FOR customer.
  DEF BUFFER item FOR item.

  DO FOR order, customer, item TRANSACTION:

  /* stuff */

  END.

END PROCEDURE.

This code is *very* useful since it limits the recod scope to the internal procedure and becomes completely independent of any other code in the same compilation unit. Therefore it will not create any problems at compile time.It is a matter of taste if you prefer to write the code like this:

PROCEDURE foo:

  DEF BUFFER b-order FOR order.
  DEF BUFFER b-customer FOR customer.
  DEF BUFFER b-item FOR item.

  DO FOR b-order, b-customer, b-item TRANSACTION:

  /* stuff */

  END.

END PROCEDURE.

Posted by Admin on 14-Apr-2010 10:31

I agree with Peter - strong scoping Buffers to blocks is usually very helpful. It makes sure the TRANSACTION block is not accidentally widened because a record has not been released before.

When the DO FOR

is the outermost block in a procedure (internal) it's very similar to

DEFINE BUFFER Customer FOR Customer. /* same name by purpose */

Posted by rbf on 14-Apr-2010 11:06

mikefe wrote:

I agree with Peter - strong scoping Buffers to blocks is usually very helpful. It makes sure the TRANSACTION block is not accidentally widened because a record has not been released before.

That is a common misconception. It is not the TRANSACTON scope that matters here (that can always be widened) but the record scope.

 

When the DO FOR

is the outermost block in a procedure (internal) it's very similar to

DEFINE BUFFER Customer FOR Customer. /* same name by purpose */

That is true. Buffers are already scoped to the internal prcedure, so using DO FOR inside an internal procedure only adds value if there are multiple blocks that must not have bleeding records scopes.

Posted by Admin on 14-Apr-2010 11:11

That is a common misconception. It is not the TRANSACTON scope that matters here (that can always be widened) but the record scope.

And that's the purporse of the DO FOR Block.

Posted by Thomas Mercer-Hursh on 14-Apr-2010 12:12

Peter is pointing you in the right direction here. One is always wanting to limit scope.  Bodies of action get encapsulated into procedures or classes so that you know everything that is going to happen about that area of responsibility is in that package.  Database transactions get scoped to the smallest possible block, no user input, nothing open ended, in order minimize the length of any locks and to have a small tight block of code where everything that happens to the DB is in that one place.  Strong scoping a buffer to a block like this has the same kind of purpose.  It is telling you that everything that happens to those buffers happens within that block (there may be another such block in the same program, but no "loose" references or the compiler will complain).   Loosely scoped references are a classic way of unintentionally extending the scope of a transaction or lock.

Posted by Admin on 13-May-2010 09:14

DEFINE BUFFER Customer FOR Customer. /* same name by purpose */

----------

YUK!!! A personal hate of mine. I'd have to beat you with a large stick!

Posted by ChUIMonster on 13-May-2010 09:40

It is a technique that you either love or hate.  There is no middle ground on that one.

You may want to beat hime with a big stick but I'll be pinning a medal on him.

That's one of my personal favorites

Posted by Peter Judge on 13-May-2010 09:48

You may want to beat hime with a big stick but I'll be pinning a

medal on him.

Me too. Easy way to keep readability (no need for any flavour of Eastern European notation) and to ensure buffer scope.

-- peter

Posted by Admin on 13-May-2010 09:53

YUK!!! A personal hate of mine. I'd have to beat you with a large stick!

 

Any argument or just dislike?

Posted by jmls on 13-May-2010 10:03

Heh. I want a medal too, then.

Julian

Posted by Admin on 13-May-2010 10:08

Heh. I want a medal too, then.

 

Where do I get mine from?

Posted by Admin on 13-May-2010 10:09

Its just lazy programming imho. I'd like to think that a buffer falls under the same umbrella as a parameter or variable where naming convensions are concerned particularly where multiple buffers on the same table are referenced in the same block.

Posted by jmls on 13-May-2010 10:13

Tom's going to have to have a ceremony soon, I guess ..

Posted by Admin on 13-May-2010 10:13

Its just lazy programming imho.

It's a safety net. And therefor it shouldn't be banned. Basically like a garbage collector in OO ...

Posted by Admin on 13-May-2010 10:18

It's a safety net

Surely only if you don't define a buffer in the first place?

Posted by ChUIMonster on 13-May-2010 10:28

I'm very much in favor of properly applied laziness and very much

opposed to naming conventions. I prefer to call things what they are

rather than obfuscating them with a bunch of gobbledygook. You would

think that the Western World would have learned its lesson after Roman

Numerals but apparently we are doomed to repeat that particular lesson.

Posted by Admin on 13-May-2010 10:28

Surely only if you don't define a buffer in the first place?

That explains why you believe you don't have to use it. It does not explain why you'd wanna hurt other developers that do this...

Posted by ChUIMonster on 13-May-2010 10:28

That is exactly the point!

Posted by Peter Judge on 13-May-2010 10:33

It's a safety net

Surely only if you don't define a buffer in the first place?

If you don't define a buffer explicitly*, it'll be scoped to the outermost block that references it. So if you do a FIND in method/function/procedure A on the default buffer, and reference the same buffer in m/f/p B, it'll point at the same record. You may not want that, and you may spend a lot of time trying to figure out why your code isn't doing what you expect.

Of course, you may want that behaviour, in which case defining a named buffer will cause the buffer to be scoped to method/function/procedure A or B and the other m/f/p won't have access to it. But I personally don't like this because it introduces all sorts of implicit interdependencies; passing a buffer as a parameter (or handle) makes it clear where the m/f/p gets its buffer from in cases where it's "shared". If there's no buffer passed, then I can assume that the intent of the code is to have the buffer scoped to that m/f/p. And clearly, the preceding paragraph has nothing in particular to do with whether the buffer is named "customer" or "bufCustomer" or "roger".

-- peter

  • explicitly since there's always a buffer

Posted by Admin on 13-May-2010 10:44

I guess we'll agree to disagree on the "safety net" issue.

Posted by Admin on 13-May-2010 10:50

Don't get me wrong here. I'm not saying the use of strongly scoped buffers is bad practive. On the contrary, I think its a must. I just don't like to see BUFFER customer FOR customer. However, it seems I am in a minority of 1.

Posted by Thomas Mercer-Hursh on 13-May-2010 11:26

At least two.  Explicit buffers are a must, but why obscure the scope of the buffer by giving it a name which means that you can't tell what its scope is?

This thread is closed