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=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: a07f3367d7,c7c302806c75a91b X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,UTF8 Received: by 10.68.197.201 with SMTP id iw9mr2704298pbc.6.1352353190410; Wed, 07 Nov 2012 21:39:50 -0800 (PST) From: =?utf-8?Q?Yannick_Duch=C3=AAne_=28Hibou57?= =?utf-8?Q?=29?= Newsgroups: comp.lang.ada Subject: Re: Design by contract and control inversion Date: Fri, 02 Nov 2012 09:59:53 +0100 Organization: Ada @ Home Message-ID: References: <13ce31f3-34c8-4e08-b45f-cbed9e4ffefe@googlegroups.com> NNTP-Posting-Host: kkBNy2WMHv5wPgXyHzithg.user.speranza.aioe.org Mime-Version: 1.0 X-Complaints-To: abuse@aioe.org User-Agent: Opera Mail/12.02 (Linux) X-Notice: Filtered by postfilter v. 0.8.2 Path: 6ni68208pbd.1!nntp.google.com!npeer01.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!border3.nntp.dca.giganews.com!border1.nntp.dca.giganews.com!border4.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!news.mccarragher.com!news.grnet.gr!de-l.enfer-du-nord.net!feeder2.enfer-du-nord.net!weretis.net!feeder1.news.weretis.net!usenet.pasdenom.info!aioe.org!.POSTED!not-for-mail X-Received-Bytes: 14912 Content-Type: text/plain; charset=utf-8; format=flowed; delsp=yes Content-Transfer-Encoding: Quoted-Printable Date: 2012-11-02T09:59:53+01:00 List-Id: Le Fri, 02 Nov 2012 04:40:44 +0100, Yannick Duch=C3=AAne (Hibou57) = a =C3=A9crit: > I may post part of the specification in this thread, to request people= = > for comments. Will be useful to know if whether or not it's clear enou= gh = > and understandable (just don't expect anything wonderful, that's a = > stupidly simple thing apart of the question raised here). Here is=E2=80=A6 reading Adam, I get the idea to post an excerpt to ensu= re it's = intelligible enough. That does not really stand for the real thing, I'm = = just posting an intermediate thing, which is enough to looks useful, but= = lacks many things. Hope that's not too long for a Usenet post. Although I decided to use a fa=C3=A7ade type, I still could not avoid to= put = some preconditions at multiple place. Comment explains why (in short, = that's due to the remaining ability to access the object via other paths= = than the one provided to the handler sub-program). -- abc.ads package ABC is pragma Pure; end ABC; -- abc-sets.ads package ABC.Sets is pragma Pure; end ABC.Sets; -- abc-sets-base.ads generic type Element_Type is private; type Cardinal_Type is (<>); package ABC.Sets.Base is type Instance_Type is limited interface; Read_Unassigned : exception; Update_Unassigned : exception; -- An implementation may raise the above exceptions, even -- when pre/post assertions are not enabled. -- = ------------------------------------------------------------------------= function Is_Assigned (Instance : Instance_Type) return Boolean is abstract; -- For pre/post assertions and defensive design. -- = ------------------------------------------------------------------------= procedure Add (Instance : in out Instance_Type; Element : in Element_Type) is abstract with Pre'Class =3D> Is_Assigned (Instance); procedure Add (Instance : in out Instance_Type; Other : in Instance_Type) is abstract with Pre'Class =3D> Is_Assigned (Instance) and Is_Assigned (Other); procedure Assign (Instance : in out Instance_Type; Element : in Element_Type) is abstract with Post'Class =3D> Is_Assigned (Instance); procedure Assign (Instance : in out Instance_Type; Other : in Instance_Type) is abstract with Pre'Class =3D> Is_Assigned (Other), Post'Class =3D> Is_Assigned (Instance); function Cardinal (Instance : in Instance_Type) return Cardinal_Type is abstract with Pre'Class =3D> Is_Assigned (Instance); function Create return Instance_Type is abstract; -- `Is_Assigned` may or may not be `True`, depending -- on concrete implementation's choice. function Equal (Instance : in Instance_Type; Other : in Instance_Type) return Boolean is abstract with Pre'Class =3D> Is_Assigned (Instance) and Is_Assigned (Other); function Has (Instance : in Instance_Type; Element : in Element_Type) return Boolean is abstract with Pre'Class =3D> Is_Assigned (Instance); function Has (Instance : in Instance_Type; Other : in Instance_Type) return Boolean is abstract with Pre'Class =3D> Is_Assigned (Instance) and Is_Assigned (Other); procedure Remove (Instance : in out Instance_Type; Element : in Element_Type) is abstract with Pre'Class =3D> Is_Assigned (Instance); procedure Remove (Instance : in out Instance_Type; Other : in Instance_Type) is abstract with Pre'Class =3D> Is_Assigned (Instance) and Is_Assigned (Other); -- Concrete implementations must consider the case -- where `Instance` and `Other` refers (directly or indirectl= y) -- to the same object, whether what "object" is for the -- implementation. end ABC.Sets.Base; -- abc-sets-functional.ads -- Functional set. -- -- The functional behaviour, its absence of dependencies to side -- effects during evaluation, provides optimization opportunities -- for concrete implementations. -- -- A classic interface would leave, to create complex expressions, -- no other choices than using regular functions each returning -- a sub-expression. An alternative is to directly write to -- a target result object instead, avoiding returns from function -- and passing to functions parameters. A simple and safe = implementation -- may still go this way, and use an result object per sub-expressi= on. -- A optimized implementation may benefits from the enforced no-sid= e -- effect behaviour (whether or not an element is set, does not dep= ends -- on whether or not another element is set). with ABC.Sets.Base; generic with package Base is new ABC.Sets.Base (<>); package ABC.Sets.Functional is type Expression_Type is limited interface; subtype Expression_Class is Expression_Type'Class; -- Instead of a function returning a set, an expression, -- is a subprogram writing to a result target object. The -- concrete implementation is responsible for the object -- passed to be written to. The sub-program then write -- its sub-expression to it, using basic methods such as -- `Add`, `Remove` and so on. subtype Element_Type is Base.Element_Type; subtype Cardinal_Type is Base.Cardinal_Type; type Instance_Type is limited interface and Base.Instance_Type; subtype Instance_Class is Instance_Type'Class; type Instance_Write_Only_Type is limited interface; subtype Instance_Write_Only_Class is Instance_Write_Only_Type'Cl= ass; -- A restricted fa=C3=A7ade to an `Instance_Type`: no read metho= ds, = intended -- to be written to only, as a target result object. It enforce = the -- functional semantic, via type safety. If an expression = sub-program -- attempts to modify or read the target set (ex. using an objec= t in -- its scope), then an error is raised. This case cannot avoided= by -- type safety mechanisms, and runtime checks are still required= to -- prevent it (see `Is_Being_Assigned`). Illegal_Assignment : exception; Illegal_Operation : exception; Illegal_Read : exception; Nesting_Limit : exception; Self_Dependency : exception; -- The above exceptions may be raised by an implementation, even= -- when pre/post assertions are disabled. -- = ------------------------------------------------------------------------= function Is_Being_Assigned (Instance : Instance_Type) return Boolean is abstract; -- Property used for runtime checks of the functional semantic (= for = the -- part of it which cannot be ensured by type safety). -- = ------------------------------------------------------------------------= procedure Add (Instance : in out Instance_Write_Only_Type; Element : in Element_Type) is abstract; procedure Add (Instance : in out Instance_Write_Only_Type; Expression : in Expression_Class) is abstract; procedure Add (Instance : in out Instance_Write_Only_Type; Other : in Instance_Class) is abstract with Pre'Class =3D> Is_Assigned (Instance_Type (Other)) and not Is_Being_Assigned (Instance_Type (Other)); procedure Remove (Instance : in out Instance_Write_Only_Type; Element : in Element_Type) is abstract; procedure Remove (Instance : in out Instance_Write_Only_Type; Expression : in Expression_Class) is abstract; procedure Remove (Instance : in out Instance_Write_Only_Type; Other : in Instance_Class) is abstract with Pre'Class =3D> Is_Assigned (Instance_Type (Other)) and not Is_Being_Assigned (Instance_Type (Other)); -- = ------------------------------------------------------------------------= procedure Evaluate (Expression : in Expression_Type; Result : in out Instance_Write_Only_Type'Class) is abstract; -- `Expression` has `in` mode, so that it can be the one -- returned by a function. -- -- The `in` mode `Result` holds, does not mean it is readable= -- (see some of the comments above). That's just required for= any -- implementation to get a chance to be feasible. -- = ------------------------------------------------------------------------= -- `Expression`'s `Evaluate` methods, will receive `Instance` -- behind an `Instance_Write_Only_Type` fa=C3=A7ade. -- -- During `Evaluate`, `Is_Being_Assigned (Instance)` is `True`. procedure Assign (Instance : in out Instance_Type; Expression : in Expression_Class) is abstract with Post'Class =3D> Is_Assigned (Instance); -- The old status of the instance, may or may not be = `Is_Assigned`. -- An implementation must support both cases. -- = ------------------------------------------------------------------------= -- Only root level modification allowed. No modification, nor re= ad -- access allowed, while it is being evaluated by an expression -- sub-program (which may be nesting). overriding procedure Add (Instance : in out Instance_Type; Element : in Element_Type) is abstract with Pre'Class =3D> not Is_Being_Assigned (Instance); overriding procedure Add (Instance : in out Instance_Type; Other : in Instance_Type) is abstract with Pre'Class =3D> not Is_Being_Assigned (Instance) and not Is_Being_Assigned (Other); overriding procedure Assign (Instance : in out Instance_Type; Element : in Element_Type) is abstract with Pre'Class =3D> not Is_Being_Assigned (Instance); overriding procedure Assign (Instance : in out Instance_Type; Other : in Instance_Type) is abstract with Pre'Class =3D> not Is_Being_Assigned (Instance) and not Is_Being_Assigned (Other); overriding function Cardinal (Instance : in Instance_Type) return Cardinal_Type is abstract with Pre'Class =3D> not Is_Being_Assigned (Instance); overriding function Equal (Instance : in Instance_Type; Other : in Instance_Type) return Boolean is abstract with Pre'Class =3D> not Is_Being_Assigned (Instance) and not Is_Being_Assigned (Other); overriding function Has (Instance : in Instance_Type; Element : in Element_Type) return Boolean is abstract with Pre'Class =3D> not Is_Being_Assigned (Instance); overriding function Has (Instance : in Instance_Type; Other : in Instance_Type) return Boolean is abstract with Pre'Class =3D> not Is_Being_Assigned (Instance) and not Is_Being_Assigned (Other); overriding procedure Remove (Instance : in out Instance_Type; Element : in Element_Type) is abstract with Pre'Class =3D> not Is_Being_Assigned (Instance); overriding procedure Remove (Instance : in out Instance_Type; Other : in Instance_Type) is abstract with Pre'Class =3D> not Is_Being_Assigned (Instance) and not Is_Being_Assigned (Other); end ABC.Sets.Functional; (you were warned, that's nothing wonderful) -- = =E2=80=9CSyntactic sugar causes cancer of the semi-colons.=E2=80=9D [1] =E2=80=9CStructured Programming supports the law of the excluded muddle.= =E2=80=9D [1] [1]: Epigrams on Programming =E2=80=94 Alan J. =E2=80=94 P. Yale Univers= ity