From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC,T_FILL_THIS_FORM_SHORT autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: fac41,2c6139ce13be9980 X-Google-Attributes: gidfac41,public X-Google-Thread: f43e6,2c6139ce13be9980 X-Google-Attributes: gidf43e6,public X-Google-Thread: 1108a1,2c6139ce13be9980 X-Google-Attributes: gid1108a1,public X-Google-Thread: 103376,3d3f20d31be1c33a X-Google-Attributes: gid103376,public From: donh@syd.csa.com.au (Don Harrison) Subject: Re: Safety-critical development in Ada and Eiffel Date: 1997/07/11 Message-ID: X-Deja-AN: 256151588 Sender: news@syd.csa.com.au X-Nntp-Posting-Host: dev50 References: Organization: CSC Australia, Sydney Reply-To: donh@syd.csa.com.au Newsgroups: comp.object,comp.software-eng,comp.lang.ada,comp.lang.eiffel Date: 1997-07-11T00:00:00+00:00 List-Id: [C/C++ groups removed] Tucker Taft wrote: ::It is not so easy to take a language like Eiffel that is fundamentally ::oriented toward dynamic storage allocation (and pervasive dynamic binding), ... I responded: :Eiffel implementations optimise a high percentage of dynamic calls to static :ones - 80-90%? Also, since the overhead of the calling mechanism is just part :of the cost of making the call (the total cost includes execution of the body), :the resultant penalty for default dynamic binding is reduced to 5-10% - :obviously not worth getting excited over, even for HRT systems. If even this small overhead is unacceptable, you can force static binding where necessary by freezing routines. Although you forgo the flexibility of polymorphism, you can still take advantage of inheritance by virtue of Eiffel synonyms - these allow you to declare a routine under different names. For an HRT application, you can use a redefinable version for specialisation but in your system, call only the frozen version to force static binding. Mike Stark wrote: :Don Harrison wrote: [...] :> Both of these issues can be dealt with in Eiffel: :> :> 1) Dynamic storage allocation - The solution here (as in Ada) is to use :> a pre-allocated memory pool for HRT parts of the system so eliminating :> the need for dynamic allocation under HRT conditions. : :Does this "pre-allocated memory pool" mean that you will know exactly :what address :each object's data will reside at, or merely that you dynamically :allocate memory :at initialization and do not dynamically allocate after initialization :is complete? The latter. You don't actually need to know *where* objects are allocated, merely that there is sufficient memory to allocate them. :My experience with flight software people here at Goddard (and it is :admittedly :limited) is that they are very conservative about knowing *exactly* :where :everything is located in memory -- they want the equivalent of a FORTRAN :common :block, which can be achieved in Ada (or C++, to be fair) by [using aliases]... : :(the aliased keyword in Ada allows pointers to statically declared :objects) I suspect that you can also make an Eiffel reference access a statically allocated object (expanded type) using a standard class (MEMORY? someone may wish to confirm this). There would certainly be no technical obstacle to providing this capability if it doesn't already exist enabling you to statically allocate whatever memory you require if that's what you want (as in your application domain). :I am interested in any contrary opinions, though, especially from people who :actually :have used Eiffel for safety critical systems. Your probably unlikely to hear of any because most (including even the Eiffel community, unfortunately) seem to overlook its potential for RT systems. Ken Garlington wrote: :> 2) Eiffel's contracts are stronger, more general, more flexible and more :powerful :> than in standard Ada. This doesn't mean Ada's contracting is useless :by :> any means. It's a tribute to the designers of Ada83 that support for :> predefined contracts was included at the time it was designed. I'm :> disappointed, of course, that they were omitted from Ada95. ^^^^ :I'm not sure what was in Ada83 that was omitted in Ada95; Sorry, this should have been "Eiffel-like assertions". :however, I have noticed :that Eiffel examples posted in various places tend to have assertions that :are :fairly simple in nature (range checks), etc that are directly representable :in Ada. Maybe general assertions are more common than you imagine. However, I agree that range constraints are roughly covered by Ada subtypes. I use them liberally for just that purpose. :Those that aren't tend to be easy to do with good Ada design using :exceptions ... Can you clarify what you mean here? If you mean that you can emulate general assertions in Ada by testing assumptions and raising exceptions when violated, I agree. In fact that's exactly the style of Ada coding I write these days and it works great! I routinely apply preconditions, postconditions and check instructions to all my code now. Here's an example from some code for managing analysis of Sonar tracks (Please excuse the capitals - it's the convention here :( ): -- ================================================================== -- -- PROCEDURE NAME : REMOVE_TRACK_FROM_ANALYSIS -- -- DESCRIPTION : Remove track from analysis. -- -- Precondition : The specified track is under analysis. -- Postcondition : The track is not under analysis and an empty -- position exists. -- -- ================================================================== procedure REMOVE_TRACK_FROM_ANALYSIS (TRACK_INDEX : SAT.TRACK_INDEX_TYPE) is POSITION : POSITION_TYPE; ANALYSIS_POSITION : POSITION_DATA_TYPE; begin if SA.ASSERTIONS_ON and then not UNDER_ANALYSIS (TRACK_INDEX) then raise SA.PRECONDITION_ERROR; end if; -- Get it's position. POSITION := POSITION_OF_TRACK (TRACK_INDEX); -- Set data to defaults. ANALYSIS_POSITION := DEFAULT_POSITION_DATA; -- Update the tote position data. POSITION_DATA(POSITION) := ANALYSIS_POSITION; if SA.ASSERTIONS_ON and then (UNDER_ANALYSIS (TRACK_INDEX) or else not ANY_POSITION_VACANT) then raise SA.POSTCONDITION_ERROR; end if; exception when others => SEL.LOG_ERROR( EXCEPT_STRING => CE.EXCEPTION_NAME, PACKAGE_NAME => PACKAGE_NAME, SUBPROG_NAME => "REMOVE_TRACK_FROM_ANALYSIS" ); raise; end REMOVE_TRACK_FROM_ANALYSIS; It's not quite as good though because you miss out on inheriting contracts and it's a little messy to read because there are no distinct assertion clauses to syntactically separate them from the routine body as in Eiffel. :I think I'd like to see more cases where Eiffel is used in "hard" real-time :safety-critical :systems, and in particular some years of experience where Eiffel accurately :detects - :AND CORRECTS - for faults that are not routinely handled in equivalent Ada :systems :developed by the same vendor. Correct me I misunderstand you.. Are you wondering whether contracting helps you to identify more bugs? I can offer my own experience which has firmly convinced me of this. As an example, in our simulation, we have a vehicles object. This is implemented as an array of records (they should be variant records discriminated on validity, however..). Vehicles are activated and deactivated during the course of a "game" by setting a validity flag. I added preconditions to ensure that other attributes (such as heading) were not queried unless the vehicle was active. These simple checks caught a whole bunch of errors that may otherwise have gone unnoticed. In the absence of such a check, the problem may only have come to our attention if spurious behaviour was observed. In contrast, the exceptions raised were hard to overlook and ignore and identified these problems closer to their source. Consequently, when we (a team of 5) recently reached the end of a 5 month long development effort of incremental coding and integration testing, the parts of the system that used contracting work flawlessly apart from problems resulting from misinterpretation of requirements. The success was due not only to contracting (other factors such as good design and some good developers also played a part), but contracting definitely contributed significantly. :I think that experience is already starting :to emerge with :respect to Ada vs. older languages in this domain, particularly for Ada's :static checks. I agree. Static typing is great for reliability. Complementing it with inheritable contracts is even better. :> 3) Named parameter association is not necessary with systematic, sensible :naming. :> I confess to still using them in Ada (through force of habit) but :usually :> find that my formal and actual names are identical. : :Not our experience at all, particularly for commonly-used routines within a :system. Named :parameter association is extremely useful, in my experience. Yes, I guess it's quite handy in many cases. I'm not averse to using it under some circumstances. :> Using named association :> under such circumstances only serves to clutter the software text. : :Fortunately, in Ada, you can only use named notation where you want. Yes, making it optional is a good idea. Don. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Don Harrison donh@syd.csa.com.au