From: Brad Moore <brad.moore@shaw.ca>
Subject: Re: Proper program structure
Date: Thu, 01 Oct 2009 23:44:20 -0600
Date: 2009-10-01T23:44:20-06:00 [thread overview]
Message-ID: <6rgxm.83139$u76.321@newsfe10.iad> (raw)
In-Reply-To: <35f850af-2aed-4fe8-be6d-473ab698c181@h13g2000yqk.googlegroups.com>
Maciej Sobczak wrote:
> On 1 Paz', 17:36, Brad Moore <brad.mo...@shaw.ca> wrote:
>
>> OK, but I can apply a similar technique to hide the routines from the
>> public interface of the car. In this case, I renamed the Cars.Vehicle
>> package to be Cars.Vehicle_Internal, then created a public Cars.Vehicle
>> package that wraps the internal one, but hides the interfaces that you
>> do not want to expose.
>>
>> Is this version acceptable?
>
> Well, it is acceptable in the same way as the other options that I
> have described. In other words, due to the fact that the right way
> does not work, I have to use some inferior solution that always has a
> price in the design that does not accurately reflect the original
> intent.
>
> Thank you very much for you complete examples, but I have finally
> settled on two-phase initialization of components (so each has an Init
> procedure that is used to wire them together and all Inits are called
> from the constructor of the whole). This solution allows to keep the
> reasonable package hierarchy (no artificial packages are needed) and
> avoids a number of forwarding subprograms.
You're welcome. It was an interesting challenge. Not sure I fully see
how you've structured things, but glad you found something that at least
works. I do have one more set of refinements to add to my example
though.
I can get rid of the artificial packages Cars, and Vehicle, by using an
incomplete type declaration. That is, I move the declarations in
Cars.Vehicle, to Cars, which is where you wanted to declare the type
in the first place. However Vehicle_Type is an access type to an
incomplete type that is completed in the body.
This allows me to delete the Cars.Vehicle package as it is no longer needed.
Since Construct now returns a heap allocated object, I make the type,
Vehicle_Internal_Type a controlled type in the package body, so that
clients of Cars would not be impacted by memory leakage by declaring a
Vehicle_Type on the stack.
Also, I made the Cars.Vehicle_Type inherit from
Cars.Vehicle_Internal.Vehicle_Internal_Type. That way, I eliminate
the forwarding programs. (If that is what you meant by forwarding
subprograms), since the primitive subprograms are inherited directly.
Well not entirely true. The primitive subprograms are available in
the body, but if they need to be exported from the spec, then you
still need forwarding subprograms, since Vehicle_Type is an access type.
Also, other than the Cars package, all the other child packages are
private packages, which cannot be withed by client code.
If the goal of this exercise is to be able to define a clean interface
that is not impacted by the Ada language restrictions, ie, no evidence
or artifacts in the spec resulting from issues that have been discussed,
then I think this might be a good approach. If we had to jump through
a hoop or two to get the implementations to work, at least we've hidden
those hurdles.
Of course, the approach you've chosen may still be a better approach for
you, since the requirements of your real system may be very much
different than this toy example.
For example, you may not like the fact that I used heap allocation here,
or that I still have a Cars.Vehicle_Internal package, though that is a
private package at least. Maybe it just needs a better name.
It is perhaps weird that the vehicle_type in Cars effectively inherits
from a private child package. Usually it is the other way around, the
child package type inherits from the root package type, but I think
this gives you the effect that the root package type contains all the
details hidden in the child package.
To show the refined approach though...
package Cars is
type Vehicle_Type (<>) is limited private;
function Construct return Vehicle_Type;
private
type Car_Type;
type Vehicle_Type is access all Car_Type;
end Cars;
------------------------------------------
with Cars.Vehicle_Internal;
use Cars.Vehicle_Internal;
package body Cars is
type Car_Type is new Vehicle_Internal_Type;
function Construct return Vehicle_Type is
begin
return new Car_Type'
(Car_Type (Vehicle_Internal_Type'(Construct)));
end Construct;
end Cars;
---------------------------------------------
with Cars.Types; use Cars.Types;
private with Cars.Wheels, Cars.Chassis, Cars.Engine, Cars.Gear_Box;
private with Ada.Finalization;
private package Cars.Vehicle_Internal is
type Vehicle_Internal_Type is private;
procedure Shift_Gears
(Car : in out Vehicle_Internal_Type;
Gear : Gear_Type);
function Construct return Vehicle_Internal_Type;
private
use Cars.Wheels, Cars.Chassis, Cars.Engine, Cars.Gear_Box;
use Ada.Finalization;
type Wheel_Array_Type is array (1 .. 4) of Wheel_Type;
type Force_Finalization is new Controlled with null record;
type Vehicle_Internal_Type is
record
Needs_Finalization : Force_Finalization;
Wheels : Wheel_Array_Type;
Chassis : Chassis_Type;
Engine : Engine_Type;
Gear_Box : Gear_Box_Type (Vehicle_Internal_Type'Access);
end record;
end Cars.Vehicle_Internal;
----------------------------------------
package body Cars.Vehicle_Internal is
function Construct return Vehicle_Internal_Type is
begin
return New_Vehicle : Vehicle_Internal_Type do
Gear_Box.Select_Gear (New_Vehicle.Gear_Box, Park);
return;
end return;
end Construct;
procedure Shift_Gears
(Car : in out Vehicle_Internal_Type;
Gear : Gear_Type) is
begin
Cars.Engine.Shift_Gears (Motor => Car.Engine, Gear => Gear);
end Shift_Gears;
end Cars.Vehicle_Internal;
----------------------------------------
-- Also, forgot to include this package last time.
private package Cars.Types is
type Gear_Type is (Park, Neutral, Forward, Backward);
end Cars.Types;
Brad
next prev parent reply other threads:[~2009-10-02 5:44 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-09-30 21:25 Proper program structure Maciej Sobczak
2009-09-30 22:16 ` Robert A Duff
2009-10-01 7:13 ` Maciej Sobczak
2009-09-30 23:43 ` Adam Beneschan
2009-10-01 7:35 ` Maciej Sobczak
2009-10-01 6:34 ` Brad Moore
2009-10-01 7:44 ` Maciej Sobczak
2009-10-01 9:39 ` Maciej Sobczak
2009-10-01 15:36 ` Brad Moore
2009-10-01 20:01 ` Maciej Sobczak
2009-10-02 5:44 ` Brad Moore [this message]
2009-10-02 13:10 ` Brad Moore
2009-10-01 8:08 ` Dmitry A. Kazakov
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox