comp.lang.ada
 help / color / mirror / Atom feed
From: nickroberts@blueyonder.co.uk (Nick Roberts)
Subject: Re: Aspect-Oriented Programming
Date: Sun, 29 Sep 2002 22:56:50 GMT
Date: 2002-09-29T22:56:50+00:00	[thread overview]
Message-ID: <3d977d7e.65439093@news.cis.dfn.de> (raw)
In-Reply-To: 3D975896.CDB6CA2E@adaworks.com

On Sun, 29 Sep 2002 12:46:30 -0700, Richard Riehle <richard@adaworks.com>
strongly typed:

>I was having a conversation last week with a colleague
>and the topic turned to aspect-oriented programming.  This
>rather interesting approach to software design seems, at first,
>to break encapsulation, but close inspection, offers some
>powerful capabilities for reuse and corresponds to the reality
>of a physical world architectures.
>
>As we talked, I realized that there was an opportunity to
>consider the role of private child packages in the design of
>aspect-oriented architectures.    So I am wondering if anyone
>in this forum has investigated the unique properties of Ada
>that contribute to aspect-oriented software architectures.

Forgive me for reposting an article I posted here in February, in a thread
about refactoring, complete with brain-damage warning (which still
applies).

==========

[ *** WARNING: mind-numbing esoterica follows; no liability for brain
damage can be accepted. *** ]

If you would like me to throw in my own ideas, one fairly elaborate one
occurs to me, to do with providing support for Aspect-Oriented Programming
in Ada. It would work something like as follows.

First, the user specifies a list A of aspects, each having a name N (which
is a valid Ada name). One of these aspects is designated the default Nd.
Each name would either be simple (an identifier) or compound (having a
prefix). The operation is applied to a library package P, and does the
following:

(1) for each (N) of all the aspects in A, write a new private package
specification named P.N, containing an inlined declaration for each
subprogram S declared in the specification of P, each such declaration
being a copy of the declaration of S but excluding out-mode parameters in
the case of the default aspect, and a procedure in all other cases with the
same parameters but excluding the out-mode (and return) parameters;

(2) rewrite the existing body of P with the name P.Nd (but otherwise
unchanged);

(3) for each (N) of the other aspects in A, write a new body named P.N,
which contains a null completion for each subprogram in the specification
of P;

(4) write a new body of P, with a completion for each subprogram in the
specification of P, each such completion containing (only) a call to each
member (N) of A (in the order given) in the form "P.N(parameters)" where
the parameters are a repetition of the formal parameters of the subprogram,
and the result of a function is held in a temporary and returned at the
end, if necessary.

In addition, for each member of the set formed by the closure of the
ancestors of the (compound) names of A, write out an empty private package
specification.

An example might illuminate the idea. Suppose we have a package:

   with Customers;
   package Ice_Cream is
      type Cone is private;
      function Make return Cone;
      procedure Eat (Item:   in out Cone;
                     Person: in out Customers.Human);
   private
      ... private stuff
   end Ice_Cream;

   package body Ice_Cream is

      function Make return Cone is
      begin
         ... make a cone
      end;

      procedure Eat (Item:   in out Cone;
                     Person: in out Customers.Human) is
      begin
         ... eat a cone
      end;

   end Ice_Cream;

Now, suppose we wished to divide this into the aspects: Debug.Before; Main;
Debug.After. The refactoring would generate the following compilation
units:

   private package Ice_Cream.Debug is end;

   private package Ice_Cream.Debug.Before is
      procedure Make;
      procedure Eat (Item:   in out Cone;
                     Person: in out Customers.Human);
      pragma Inline(Make,Eat);
   end Ice_Cream.Debug.Before;

   private package Ice_Cream.Main is
      function Make return Cone;
      procedure Eat (Item:   in out Cone;
                     Person: in out Customers.Human);
      pragma Inline(Make,Eat);
   end Ice_Cream.Main;

   private package body Ice_Cream.Debug.After is
      procedure Make;
      procedure Eat (Item:   in out Cone;
                     Person: in out Customers.Human);
      pragma Inline(Make,Eat);
   end Ice_Cream.Debug.After;

   package body Ice_Cream.Debug.Before is

      procedure Make is
      begin
         null;
      end;

      procedure Eat (Item:   in out Cone;
                     Person: in out Customers.Human) is
      begin
         null;
      end;

   end Ice_Cream.Debug.Before;

   package body Ice_Cream.Main is

      function Make return Cone is
      begin
         ... make a cone
      end;

      procedure Eat (Item:   in out Cone;
                     Person: in out Customers.Human) is
      begin
         ... eat a cone
      end;

   end Ice_Cream.Main;

   package body Ice_Cream.Debug.After is

      procedure Make is
      begin
         null;
      end;

      procedure Eat (Item:   in out Cone;
                     Person: in out Customers.Human) is
      begin
         null;
      end;

   end Ice_Cream.Debug.After;

The following replacement compilation unit would be generated:

   package body Ice_Cream is

      function Make return Cone is
         Temp: Cone;
      begin
         Ice_Cream.Debug.Before.Make;
         Temp := Ice_Cream.Main.Make;
         Ice_Cream.Debug.After.Make;
         return Temp;
      end;

      procedure Eat (Item:   in out Cone;
                     Person: in out Customers.Human) is
      begin
         Ice_Cream.Debug.Before.Eat(Item,Person);
         Ice_Cream.Main.Eat(Item,Person);
         Ice_Cream.Debug.After.Eat(Item,Person);
      end;

   end Ice_Cream.Main;

For any other compilation unit written, if the unit already exists, it is
not replaced.

Obviously, the idea is to automatically generate a skeleton that provides
for the separation of the implementation of a library package into a set of
different aspects.

It also would be good to have operations that: added aspects to an
implementation already divided; coalesced several aspects back into one;
coalesced all the aspects back into one body.

I'm sure that any number of similarly specialised and elaborate
refactorings could be useful to some people. I'm also sure that useful
manipulations would not be limited to those which preserve (external)
semantics.

==========

The thread got a bit sidetracked (it included some comments by Richard on a
different topic). Hope you don't mind. As you get older you start repeating
yourself.

Never mind, as they say: as you get older you start ... um, did I just say
that?

-- 
Nick Roberts
Per Ardua ad Disastra




  reply	other threads:[~2002-09-29 22:56 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-09-29 19:46 Aspect-Oriented Programming Richard Riehle
2002-09-29 22:56 ` Nick Roberts [this message]
2002-09-29 23:27   ` Pat Rogers
2002-10-01 23:45   ` Richard Riehle
2002-10-03  0:11     ` Nick Roberts
2002-10-10 20:38   ` Programmer Dude
2002-10-10 21:09     ` Jim Rogers
2002-10-15 16:13       ` Programmer Dude
2002-09-30  6:02 ` Caffeine Junky
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox