Sign up on the Revelation Software website to have access to the most current content, and to be able to ask questions and get answers from the Revelation community

At 15 AUG 2005 06:10:47AM Graeme McGillivray wrote:

I am hoping someone has knowledge of how to implement OI's contract block, pre and post conditions.

It appears to follow the model set by Meyer's Eiffel, which allows assertions inserted into the code as pre/post and invariants. The eiffel syntax is:

assertion_label: statement

for example:

ensure {the equivalent post condition block}

product_price: price ]= 0

meaning that the class method will throw an error if this post condition fails.

I did try an OI contract block post condition with similar logic, and it did throw an error, but the documentation gives no clue as to how to handle the error, or even if my assumption of the syntax is correct.

Is anyone able to offer any clues?


At 15 AUG 2005 03:29PM [email protected] wrote:

The problem you are seeing is that this is a partial implementation which should either be removed from the documentation or fixed. To provide some historical context. When the original developers decided to create OI2 they naively assumed that they had carte blanche and could happily break existing apps in the name of progress. So taking tips from Eiffel et al they extended the language to insist on prototyping of variables in subroutine/function headers and to include an (optional) contract block.

Not surprisingly the existing developer base balked at having to change all of their existing code and the whole thing became optional and withered away into obscurity.

Consider the following code section

<code>

Function DeleteMe(A, B)

Begin Condition
	Pre:
		Assigned(A)
		Assigned(B)
		A ] 0
		B ] 0
	Post:
		C The Sprezzatura Group Web Site

World Leaders in all things RevSoft


At 16 AUG 2005 12:19AM Graeme McGillivray wrote:

Many thanks for the response, its pleasing to see someone is interested. First, a little background information.

Bertrand Meyer is the author of Eiffel, probably the most thought out language that handles this concept. His logic is based on what he calls Design by Contract.

His “Design by Contract” concept helps us build software in which reliability is built in rather than achieved after the fact through debugging. We will derive tremendous benefits from writing the assertions at the same time as we write the software, or indeed before we write the software."

Many people think that these assertions should only be used up to the debugging stage (as is the case at present in OI), and when the system goes operational (the live version) then the assertion checking is turned off, or ignored.

Meyers view is that they can be used in an operational system, and has two views on how this can be handled.

The first, and most extreme is:

“One approach is to say, this problem simply shouldn't happen. If it ever does happen, the best you can do is shut your system down, fix the bug, and restart it. (again as OI does now by drooping into the debugger)”

The Least extreme view is:

“The first thing to do if you have a problem is obviously to log it. Typically when you have an assertion violation during operation, not during debugging, but during operation, it's an indication that something needs to be fixed in the software. The defect cannot be left to stand in the long term. What you do in the short term is try to recover as reasonably as you can. And indeed, that's where exception handling comes in.”

The Eiffel mechanisms for exception handling are defined at the routine level. The Eiffel approach to exception handling may be summarised as follows:

• a routine either fails or succeeds

• if a routine fails it must not pretend that it has succeeded

• it should either try again or report failure to the client

• if it tries again and still fails then it should as far as possible leave the environment stable

• failure is reported upwards through the chain of routine calls until either the error is dealt with or - if it gets to the root - it causes system failure.

The exception is executed only if an exception occurs in the body of the routine. It cannot therefore be used to deal with violations of preconditions. Its main purpose is to return the current object to a stable state so that invariants are satisfied. It may also attempt to re-execute the body of the routine. This may be accomplished by a retry instruction. This instruction, which consists simply of the reserved word retry, may be used only in a rescue clause.

Meyer has an interesting concept with “preconditions”, and that is:

There are two ways of handling “preconditions”, Meyer’s logic is that the preconditions is documentation for any caller routine and in no way should you, as the programmer, actually check the preconditions in your reoutine. His logic is:

“If you take the viewpoint of the client, what happens typically is this: You are writing some software and you instantiate a class. Assuming you are programming in a context in which the only way to use the class is through it's specification, which includes the contract, you'll see the pre-condition. If you are a reasonable client programmer, if you know what you are doing, you'll know to program against the precondition. Of course, you may not like the precondition. You may find it's too demanding, but that's life. It's part of the contract. I think that style works pretty well.”

This means that if the client routine is not going to stick to the contract and meet the preconditions before calling your routine, then; you don't want to have the same condition being tested in multiple places, both the client and the supplier. "If the client's part of the contract is not fulfilled, that is to say if the class does not satisfy precondition, then the class is not bound by the post condition." So the supplier class can either throw an exception or return a wrong result. It should always be simple to return the system to a useful state. If it's not simple to recover, you're probably not recovering at the right place.

In summary:

Each routine may have a precondition and a postcondition. These are boolean expressions which are compiled and may be checked at run- time. Preconditions and postconditions derive directly from a view of software development as a contract between the client and the provider of services. A precondition defines the client's responsibility: it stipulates those conditions that must be met at the point when a routine is called. The postcondition is the supplier's part of the contract: it stipulates what will be true on exit from a routine, provided the pre-conditions were met on entry. It says nothing about what will happen if preconditions are not met. The supplier is not required to take action to deal with a client's failure to meet preconditions, and indeed is discouraged from doing so. At first sight this may seem odd, but it is a deliberate attempt to break away from 'defensive programming' which can lead to duplication of checking by users and suppliers of routines, to consequent inefficiency, and more importantly perhaps, to confusion as to who is responsible for what.

Two other issues of interest from Eiffel:

The debug instruction is an instruction designed, as the name suggests, for tracing errors. It allows us to insert instructions in a piece of code during debugging, and to switch them off when they are no longer required. It is possible to switch all debugging on or off, or to switch individual debug statements or sets of statements on or off. This is done either by specifying at run time which classes in a system are to be switched on, or by appending a key or keys to the keyword debug, which allows the system to execute selectively a specified debug or set of debug instructions.

A trace facility is provided as part of the run-time support for Eiffel. This may be used during debugging to trace the flow of control in a system; it will help a programmer to ensure that routines are being called in the order expected. The trace facility may be switched on for individual classes, for all classes, and for none. If switched on it generates information about calls to, and returns from, routines of specified classes. Like the debug instruction this can be very useful in tracing the causes of error. Readers who wish to use this facility are advised to switch it on only for a limited number of classes.

So, Rev also needs to consider:

• Whether the contract block should check the preconditions

• Provide an exception technique which contains "your error requirements"

• Provide a system switch to enable/disable assertion testing – when enabled it should provide the contract block in the template for the routine.

• Also provide an enhance debug on/off switch system wide

• Also provide a trace on/off facility


At 16 AUG 2005 02:15AM [email protected] wrote:

Thank you - that explains some things already present in the system.

There is a GET_CONTRACT routine that permits the extraction of pre or post contracts. This could theoretically be used by the client to ensure compliance.

The new debugger extensions permit the calling of your own routine to deal with the error. This too could check the contract block.

The debugger can (theoretically) be toggled on the fly using SET_ENV (we've had mixed results with this).

The existence of the OEPROFILE.LOG provides a sledgehammer to crack the nut of tracing. The RetStack() function is more granular.

As is usually the case with OI you can achieve specific ends in slightly non specific ways. ;)

In a non-typed language such assertion checking is sometimes more onerous than useful - but I'd hasten to point out that that is an individual design philosophy and that other members of the Sprezz gestalt might not share my POV :].

[email protected]

The Sprezzatura Group Web Site

World Leaders in all things RevSoft


At 16 AUG 2005 05:39PM Graeme McGillivray wrote:

Thanks for the explanation.

As I am new to the OI environment, I could not find any details on your second point, about the new debugger extensions allowing me to call my own routine to deal with errors. Do you have any explanation on how this can be achieved please.

I hope that the REV designers are watching this post and provide some future hooks so that the Contract Block could be used in a useful manner.

As a general last comment.

As a programmer I like the concept of assertions in the actual code, even if its only inline documentation. At least the rules are available for review when anyone revisted the code for any reason at a later date.

The next step is the Eiffel concept (and hopefully where OI is heading, even if its only optional) which is to allow the runtime to enable the assertion testing and throw exceptions which can be managed by the programmer.

The newest perspective on this is allow routines to call an external "business rules engine" where the users sets the rules and our routines simply handle the true/false decision and provide the explanation in the exception handling.

I personally would like to have all options available, and decide on a case by case decision whether I actually use them.


At 17 AUG 2005 03:48AM [email protected] wrote:

See the routine Debugger_Replacement and the Database Manager, Environment, General, Debuggger - Disable/Enable/Intercept.

This is discussed in more depth on the Works Forum - as it is a 7.1.1 feature it is only available to Works members.

[email protected]

The Sprezzatura Group Web Site

World Leaders in all things RevSoft

View this thread on the forum...

  • third_party_content/community/commentary/forums_nonworks/f36a4df886f15c398525705e0037eb5d.txt
  • Last modified: 2024/01/04 21:00
  • by 127.0.0.1