3

I've been doing Progress 4GL for 8 years though it's not my main responsibility. I do C++ and Java a lot more. When programming in other language it's suggested to have the declaration close to the usage. With 4GL however I see people place the declaration on top of the file. It's even in the coding standard.

I think placing them on top of them file would lead to 'vertical separation' problem. In most other language it's even suggested to do the assignment at the same line as the declaration.

The question is why it's suggested to do so in 4GL ? What's the benefit ? I know that it's possible to place the declaration anywhere in the file, given that it's declared before it is used.

3 Answers3

3

I think the answer is to do with scoping, or the lack of it, within Progress 4GL.

If you are used to Java, say, and read a Progress 4GL program, that looks like

DO:
    DEFINE VARIABLE x AS INTEGER INITIAL 4.
    DISPLAY x.
END.

then you wouldn't expect to be able to use this value of x anywhere else in the program, and that any changes made in the block, wouldn't effect anything outside the block.

As I understand it, all progress variables declared within the body of a program are scoped to the whole program, unless they are declared are within an internal procedure or function, in which case they are scoped to the procedure or function.

(Incidentally any default buffers [i.e. undeclared] you use within an internal procedure/function are scoped to the whole program, not just the procedure or function, so you need to be very careful to explicity declare buffers in functions you intend ot use recursively).

I therefore think the convention of declaring variables at the beginning of a program is in order to reflect the fact that Progress will treat them has having been done so, regardless of where you put the declaration.

Screwtape
  • 1,337
  • 2
  • 12
  • 27
  • You are correct about the variable scoping, but wrong about the buffer scoping. Buffers can be defined within procedures AND the program main body with the same name, that said procedure can be stacked and Progress will not leak or confuse those records. I have an example, but it doesn't fit here and isn't pertinent to the original question anyway. – bupereira Dec 10 '15 at 16:00
  • I meant that if you don't explicitly declare a buffer but use a default buffer, it is scoped to the program even if you only use it in an internal function. – Screwtape Dec 10 '15 at 16:18
  • I apologize. I thought you meant default buffer as opposed to shared buffers, for instance. If you are talking about unnamed buffers (which coincide with the table name), then you are right. – bupereira Dec 10 '15 at 16:35
  • Unnamed buffer would have been a better description. I'll edit the main answer. – Screwtape Dec 10 '15 at 16:53
  • All buffers are named, even the default buffer which has the same name as the table. I think your initial answer was correct and the edit introduced terminology "unnamed buffer" that I've never seen before in ABL. – carl verbiest Dec 11 '15 at 06:43
  • "unnamed buffer" was the standard terminology at one point. Maybe not now ... some of us have been doing this a long time... – Andy Jones Dec 11 '15 at 10:49
  • I think your explanation makes sense. If there's no scoping then placing varible close to where it's used can be very confusing. Yet scrolling thousands lines of code just to find what is the type of variable is not fund at all especially in the terminal (we are just migrating to PDSOE recently though). Since there're needs to maintain compatibility with the existing codes, I don't think the Progress guy would do anything with it ever. – Wutipong Wongsakuldej Dec 18 '15 at 07:02
2

There is absolutely no benefit in scoping anything to the program as a whole when it could be scoped smaller.

Smaller scopes are easier to test, give less possibility of namespace conflict, and less opportunity for error.

Tightly scoped named buffers are especially useful when writing to the database because they eliminate the possibility of there ever being some other part of your code that uses the same buffer and causes a share-lock, i.e., this fails to compile:

do for b-customer transaction:
    find b-customer where .... exclusive...
    ...
end.
...
find b-customer...

On the other hand, procedures and functions (and include files...) that share scope with the main body of code are a major source of bugs, because when you pick up your variable or whatever, you can never be entirely certain where it has been...

All of this is just basic Structured Programming, of course. It's true for every language and has been accepted since the 70's.

Andy Jones
  • 1,074
  • 1
  • 10
  • 21
2

The "reason" that you usually see variables defined at the top is simple. Habit. That is just how things were done in the bad old days.

A lot of old code, or code written by old fossils, is written that way. No matter the language.

Some languages (COBOL springs to mind) even formalized it.

Is there any advantage to such an approach?

Not especially. I guess you could argue "they are all in one place and easy to find" but that isn't very compelling.

"Habit" is actually more compelling ;) If you are working with a team that expects a certain style or in an application where a particular style is prevalent then you should think twice before unilaterally throwing out a new way of doing things - the confusion could be a bigger problem than the advantages gained.

Tom Bascom
  • 13,405
  • 2
  • 27
  • 33