Skip to content

Commit c3fd3a4

Browse files
authored
Merge pull request #1130 from gusthoff/content/ada_idioms/new_section/introduction/20241025
Adding chapter: "Introduction"
2 parents f8173a0 + 95e61e4 commit c3fd3a4

File tree

2 files changed

+232
-2
lines changed

2 files changed

+232
-2
lines changed
Lines changed: 230 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,234 @@
11
:prev_state: False
22

3-
.. include:: ../../global.txt
4-
53
Introduction
64
============
5+
6+
.. include:: ../../global.txt
7+
8+
This course describes how to implement selected programming idioms in the Ada
9+
language.
10+
11+
What is an idiom? Some would say that an idiom is a workaround for an
12+
expressive deficiency in a programming language. That is not what we mean.
13+
14+
For example, we have in mind solution techniques and designs that are widely
15+
recognized as most appropriate for certain programming situations, across
16+
multiple programming languages. For instance, *reference counting* is a
17+
well-known approach to tracking and managing the storage for objects and is
18+
conceptually independent of the programming language. The implementation varies
19+
with the language, of course, but the concept is the same. Other examples might
20+
include
21+
:wikipedia:`Resource Acquisition Is Allocation (RAII) <Resource_acquisition_is_initialization>`,
22+
as well as :wikipedia:`type punning <Type_punning>` and inheritance idioms such
23+
as
24+
:wikipedia:`interface inheritance <Subtyping>` and
25+
:wikipedia:`implementation inheritance <Implementation_inheritance>`.
26+
27+
We also have in mind the best way in Ada to express fundamental, commonly known
28+
concepts such as Abstract Data Types, something the Ada language directly
29+
supports but using *building blocks* instead of a single construct. These
30+
concepts are included because they are fundamental to good design and because
31+
the building blocks require some explanation.
32+
33+
In contrast, we also include idioms for programming situations specific to the
34+
Ada language. These are not deficiency workarounds, but rather,
35+
*best practices* in situations that arise given the capabilities and semantics
36+
in the language. For example, Ada directly supports tasks (threads). There is
37+
an idiom for how best to associate a task with an enclosing object so that the
38+
task has visibility to the object's other components.
39+
40+
Some would equate idioms with design patterns. That's not unreasonable but is
41+
more narrow than we intend. This is not a document dedicated to describing how
42+
to use Ada to implement various design patterns. But note that we may refer to
43+
a design pattern to illustrate an idiom's purpose and implementation. For
44+
example, in the idiom for controlling object creation and initialization, the
45+
implementation approach happens to be the same as for expressing a
46+
Singleton [1]_. Some idiom entries might even be dedicated to implementing
47+
design patterns, but the intent is beyond just that.
48+
49+
Perhaps instead of *idiom* we should have used the term *cookbook,* but
50+
although descriptive for some entries, that term didn't completely convey the
51+
intent either.
52+
53+
54+
Assumptions
55+
-----------
56+
57+
We assume the reader knows Ada to some degree, including some advanced topics.
58+
For those lacking significant familiarity, we hope these solutions will at
59+
least give a sense for how to apply the language. We direct such readers to the
60+
:ref:`online Learn courses dedicated to the Ada language itself <Advanced_Ada_Course_Index>`.
61+
62+
63+
Definitions
64+
-----------
65+
66+
For the sake of avoiding duplication in the idiom entries, the following terms
67+
are defined here. Note that the Ada Language Manual includes a glossary in
68+
:arm22:`Section 1.3 <1-3>` (located in Annex N prior to Ada 2022). Some of the
69+
following expand on the definitions found there.
70+
71+
Suppliers and Clients
72+
~~~~~~~~~~~~~~~~~~~~~
73+
74+
*Suppliers* are software units that provide programming entities to other
75+
software units, the users. These users are the *clients* of the supplied units.
76+
The concept is simple and intuitive, but by defining these terms we can convey
77+
these roles quickly in the idioms' discussions.
78+
79+
For example, a unit that defines a type and associated operations would be a
80+
supplier. Client units could use that type to declare objects, and/or apply the
81+
operations to such objects. The language-defined package :ada:`Ada.Text_IO` is
82+
an example of a supplier. Similarly, the unit that defines a library, such as a
83+
math library, is a supplier. Callers to the math library routines are the
84+
clients. The generic package
85+
:ada:`Ada.Numerics.Generic_Complex_Elementary_Functions`, once instantiated,
86+
would be an example supplier. (Arguably, the generic package itself would be a
87+
supplier to the client that instantiates it, but instantiation is the only
88+
possibility in that narrow case. Only the routines in the instances can be
89+
called.)
90+
91+
Betrand Meyer's book on OOP [2]_ limits these terms specifically to the case of
92+
a type used in an object declaration. Our definitions cover that case but
93+
others as well.
94+
95+
Units can be both suppliers and clients, because a given supplier's facility,
96+
i.e., the interface and/or implementation, may be built upon the facilities
97+
defined by other suppliers.
98+
99+
Compile-time Visibility
100+
~~~~~~~~~~~~~~~~~~~~~~~
101+
102+
In the definitions of supplier and client above, we gave an example in which a
103+
supplier's type was used by clients to declare objects of the type. For the
104+
client to legally do so |mdash| that is, for the compiler to accept this usage
105+
and process the code |mdash| the use of the supplier's type has to satisfy the
106+
scope and visibility rules of the programming language.
107+
108+
Good implementations harness these visibility rules to adhere to the software
109+
engineering principles of information hiding and abstraction, both of which
110+
require that nothing of the implementation be made visible to clients unless
111+
necessary. Compiler enforcement ensures rigorous adherence to those principles.
112+
113+
Therefore, modern languages provide some way to express this control. For
114+
example, in Ada, a package can have both a *public* part and a *private* part.
115+
Clients have no compile-time visibility to the private part, nor to the package
116+
body, as both parts contain implementation artifacts. In class-oriented
117+
languages, parts of the class can be marked as *public,* *private*, and
118+
*protected* (the details depend on the specific language).
119+
120+
The idioms explored in
121+
:ref:`Fundamental Packages <Ada_Idioms_Essential_Design_Idioms_For_Packages>`
122+
are largely variations on expressing this control in Ada. More details on the
123+
topic are provided in those idioms.
124+
125+
Views
126+
~~~~~
127+
128+
In Ada, a *view* of an entity defines what the developer can legally do with
129+
that entity. For example, the declaration of an object defines a view of that
130+
object. The operations allowed by that view are determined by the type used to
131+
declare the object: a signed integer type would allow signed integer numeric
132+
operations, but not, say, bit-level operations, nor array indexing, and so on.
133+
Furthermore, the view includes whether the object is a constant.
134+
135+
An entity can have more than one view, depending on where in the text of the
136+
source code a view of that entity is considered. For example, let's say that
137+
the integer object introduced above is in fact a variable. Within the scope of
138+
that variable, we can refer to it by that name and update the value using
139+
assignment statements. However, if we pass that variable as the argument to a
140+
procedure call, within that subprogram (for that call) the view specifies a
141+
different name for the argument, i.e., the formal parameter name. Moreover, if
142+
that formal parameter is a mode-in parameter, within that procedure body the
143+
view of the actual parameter is as if it is a constant rather than a variable.
144+
No assignments via the formal parameter name are allowed because the view at
145+
that point in the text |mdash| within that procedure body |mdash| doesn't allow
146+
them, unlike the view outside the body.
147+
148+
As another example, consider a tagged type named :ada:`Parent`, and a type
149+
derived from it via type extension, named :ada:`Child`. It is common for a
150+
derived type to have either additional components, or additional operations, or
151+
both. For a given object of the :ada:`Child` type, the view via type
152+
:ada:`Child` allows the developer to refer to the extended components and/or
153+
operations. But we can convert the :ada:`Child` object to a value of the
154+
:ada:`Parent` type using what is known as a *view conversion*. With that
155+
:ada:`Parent` view of the :ada:`Child` object, we can only refer to those
156+
components and operations defined for the :ada:`Parent` type. The compiler
157+
enforces this temporary view.
158+
159+
For further details about view conversions, please refer to that
160+
:ref:`specific section of the Advanced Ada course <Adv_Ada_View_Conversion>`.
161+
162+
Views are a fundamental concept in Ada. Understanding them will greatly
163+
facilitate understanding the rules of the language in general.
164+
165+
166+
Partial and Full Views
167+
~~~~~~~~~~~~~~~~~~~~~~
168+
169+
Like objects, types also can have more than one view, again determined by the
170+
place in the program text that a view is considered. These views can be used to
171+
apply information hiding and abstraction.
172+
173+
The declaration of a private type defines a *partial view* of a type that
174+
reveals only some of its properties: the type name, primarily, but in
175+
particular not the type's representation. For example:
176+
177+
.. code-block:: ada
178+
179+
type Rotary_Encoder is private;
180+
181+
Private type declarations must occur in the *public part* of a package
182+
declaration. Anything declared there is compile-time visible to clients of the
183+
package so the type's name is visible, and potentially some other properties as
184+
well. Clients can therefore declare objects of the type name, for example, but
185+
must adhere to their partial view's affect on what is compile-time visible.
186+
187+
The private type's full representation must be specified within the
188+
*private part* of that same package declaration. For example:
189+
190+
.. code-block:: ada
191+
192+
type Rotary_Encoder is record ... end record;
193+
194+
Therefore, within that package private part and within the package body the
195+
*full view* is available because full representation information is
196+
compile-time visible in those regions. (Parts of child units have the full view
197+
as well.) This view is necessary in those two regions of the package because
198+
the representation details are required in order to implement the corresponding
199+
operations, among other possibilities.
200+
201+
Because the clients only have the partial view they do not have compile-time
202+
visibility to the type's internal representation. Consequently, the compiler
203+
will not allow representation-specific references or operations in client code.
204+
The resulting benefit is that clients are independent of the type's
205+
representation and, therefore, it can be changed without requiring coding
206+
changes in the clients. Clients need only be recompiled in that case.
207+
208+
This application of information hiding has real-world cost benefits because
209+
changing client code can be prohibitively expensive. That's one reason why the
210+
maintenance phase of a project is by far the most expensive phase. Another
211+
reason is that *maintenance* is often a euphemism for new development. Either
212+
way, change is involved.
213+
214+
As a result, when defining types, developers should use private types by
215+
default, only avoiding them when they are not appropriate. Not using them
216+
should be an explicit design choice, a line item in code reviews. Not defining
217+
a major abstraction as a private type should be suspect, just as using a
218+
:c:`struct` rather than a :c:`class` in C++ should be suspect in that case. (In
219+
C++ anything a :c:`struct` contains is compile-time visible to clients by
220+
default.)
221+
222+
For further details about type views, please refer to that
223+
:ref:`specific section of the Advanced Ada course <Adv_Ada_Type_View>`.
224+
225+
226+
Bibliography
227+
------------
228+
229+
.. [1] Gamma, E., R. Helm, et al. (1995), pp. 127. Design Patterns: Elements of
230+
Reusable Object-Oriented Software. Reading, MA, Addison-Wesley
231+
Publishing Company.
232+
233+
.. [2] Meyer, B. (1997), pp. 182. Object-Oriented Software Construction,
234+
Prentice-Hall.

content/courses/advanced-ada/parts/data_types/types.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2080,6 +2080,8 @@ types. However, we can still convert between them in the same way as we did in
20802080
the previous code examples.
20812081

20822082

2083+
.. _Adv_Ada_View_Conversion:
2084+
20832085
View conversion
20842086
~~~~~~~~~~~~~~~
20852087

0 commit comments

Comments
 (0)