|
1411 | 1411 | ] |
1412 | 1412 | } |
1413 | 1413 | }, |
| 1414 | + "ADA95_5.4.8": { |
| 1415 | + "checked": false, |
| 1416 | + "language": "Ada", |
| 1417 | + "tags": [ "Language: Ada", "Standard: Ada 95", "Data Structures" ], |
| 1418 | + "name": "Published Standards/Ada 95/5.4.8 Modular Types", |
| 1419 | + "desc": { |
| 1420 | + "html": [ |
| 1421 | + "<b>", |
| 1422 | + "<span style=\"color:red\">This check cannot be automated</span>", |
| 1423 | + "</b>", |
| 1424 | + "", |
| 1425 | + "<p><b>Guideline</b></p>", |
| 1426 | + "<p>• Use modular types rather than Boolean arrays when you create data structures that need bit-wise operations, such as <code>and</code> and <code>or</code>.</p>", |
| 1427 | + "", |
| 1428 | + "<p><b>Example</b></p>", |
| 1429 | + "<pre><code language=\"Ada\">with Interfaces;", |
| 1430 | + "procedure Main is", |
| 1431 | + " type Unsigned_Byte is mod 255;", |
| 1432 | + " X : Unsigned_Byte;", |
| 1433 | + " Y : Unsigned_Byte;", |
| 1434 | + " Z : Unsigned_Byte;", |
| 1435 | + " X1 : Interfaces.Unsigned_16;", |
| 1436 | + "begin -- Main", |
| 1437 | + " Z := X or Y; -- does not cause overflow", |
| 1438 | + " -- Show example of left shift", |
| 1439 | + " X1 := 16#FFFF#;", |
| 1440 | + " for Counter in 1 .. 16 loop", |
| 1441 | + " X1 := Interfaces.Shift_Left (Value => X1, Amount => 1);", |
| 1442 | + " end loop;", |
| 1443 | + "end Main;", |
| 1444 | + "</code></pre>", |
| 1445 | + "", |
| 1446 | + "<p><b>Rationale</b></p>", |
| 1447 | + "<p>Modular types are preferred when the number of bits is known to be fewer than the number of bits in a word and/or performance is a serious concern. Boolean arrays are appropriate when the number of bits is not particularly known in advance and performance is not a serious issue. See also Guideline 10.6.3.</p>" |
| 1448 | + ] |
| 1449 | + } |
| 1450 | + }, |
| 1451 | + "ADA95_5.4.7": { |
| 1452 | + "checked": false, |
| 1453 | + "language": "Ada", |
| 1454 | + "tags": [ "Language: Ada", "Standard: Ada 95", "Data Structures" ], |
| 1455 | + "name": "Published Standards/Ada 95/5.4.7 Access Discriminants", |
| 1456 | + "desc": { |
| 1457 | + "html": [ |
| 1458 | + "<b>", |
| 1459 | + "<span style=\"color:red\">This check cannot be automated</span>", |
| 1460 | + "</b>", |
| 1461 | + "", |
| 1462 | + "<p><b>Guideline</b></p>", |
| 1463 | + "<p>• Use access discriminants to create self-referential data structures, i.e., a data structure one of whose components points to the enclosing structure.</p>", |
| 1464 | + "", |
| 1465 | + "<p><b>Example</b></p>", |
| 1466 | + "<p>See the examples in Guidelines 8.3.6 (using access discriminants to build an iterator) and 9.5.1 (using access discriminants in multiple inheritance).</p>", |
| 1467 | + "", |
| 1468 | + "<p><b>Rationale</b></p>", |
| 1469 | + "<p>The access discriminant is essentially a pointer of an anonymous type being used as a discriminant. Because the access discriminant is of an anonymous access type, you cannot declare other objects of the type. Thus, once you initialize the discriminant, you create a \"permanent\" (for the lifetime of the object) association between the discriminant and the object it accesses. When you create a self-referential structure, that is, a component of the structure is initialized to point to the enclosing object, the <i>\"constant\"</i> behavior of the access discriminant provides the right behavior to help you maintain the integrity of the structure.</p>", |
| 1470 | + "<p>See also Rationale (1995, §4.6.3) for a discussion of access discriminants to achieve multiple views of an object.</p>", |
| 1471 | + "<p>See also Guideline 6.1.3 for an example of an access discriminant for a task type.</p>" |
| 1472 | + ] |
| 1473 | + } |
| 1474 | + }, |
| 1475 | + "ADA95_5.4.4": { |
| 1476 | + "checked": false, |
| 1477 | + "language": "Ada", |
| 1478 | + "tags": [ "Language: Ada", "Standard: Ada 95", "Data Structures" ], |
| 1479 | + "name": "Published Standards/Ada 95/5.4.4 Nested Records", |
| 1480 | + "desc": { |
| 1481 | + "html": [ |
| 1482 | + "<b>", |
| 1483 | + "<span style=\"color:red\">This check cannot be automated</span>", |
| 1484 | + "</b>", |
| 1485 | + "", |
| 1486 | + "<p><b>Guideline</b></p>", |
| 1487 | + "<p>• Record structures should not always be flat. Factor out common parts.</p>", |
| 1488 | + "<p>• For a large record structure, group related components into smaller subrecords.</p>", |
| 1489 | + "<p>• For nested records, pick element names that read well when inner elements are referenced.</p>", |
| 1490 | + "<p>• Consider using type extension to organize large data structures.</p>", |
| 1491 | + "", |
| 1492 | + "<p><b>Example</b></p>", |
| 1493 | + "<pre><code language=\"Ada\">type Coordinate is", |
| 1494 | + " record", |
| 1495 | + " Row : Local_Float;", |
| 1496 | + " Column : Local_Float;", |
| 1497 | + " end record;", |
| 1498 | + "type Window is", |
| 1499 | + " record", |
| 1500 | + " Top_Left : Coordinate;", |
| 1501 | + " Bottom_Right : Coordinate;", |
| 1502 | + " end record;", |
| 1503 | + "</code></pre>", |
| 1504 | + "", |
| 1505 | + "<p><b>Rationale</b></p>", |
| 1506 | + "<p>You can make complex data structures understandable and comprehensible by composing them of familiar building blocks. This technique works especially well for large record types with parts that fall into natural groupings. The components factored into separately declared records, based on a common quality or purpose, correspond to a lower level of abstraction than that represented by the larger record.</p>", |
| 1507 | + "<p>When designing a complex data structure, you must consider whether type composition or type extension is the best suited technique. Type composition refers to creating a record component whose type is itself a record. You will often need a hybrid of these techniques, that is, some components you include through type composition and others you create through type extension. Type extension may provide a cleaner design if the \"intermediate\" records are all instances of the same abstraction family. See also Guidelines 5.4.2 and 9.2.1.</p>", |
| 1508 | + "", |
| 1509 | + "<p><b>Notes</b></p>", |
| 1510 | + "<p>A carefully chosen name for the component of the larger record that is used to select the smaller enhances readability, for example:</p>", |
| 1511 | + "<pre><code language=\"Ada\">if Window1.Bottom_Right.Row > Window2.Top_Left.Row then . . .", |
| 1512 | + "</code></pre>" |
| 1513 | + ] |
| 1514 | + } |
| 1515 | + }, |
| 1516 | + "ADA95_5.4.3": { |
| 1517 | + "checked": false, |
| 1518 | + "language": "Ada", |
| 1519 | + "tags": [ "Language: Ada", "Standard: Ada 95", "Data Structures" ], |
| 1520 | + "name": "Published Standards/Ada 95/5.4.3 Heterogeneous Polymorphic Data", |
| 1521 | + "desc": { |
| 1522 | + "html": [ |
| 1523 | + "<b>", |
| 1524 | + "<span style=\"color:red\">This check cannot be automated</span>", |
| 1525 | + "</b>", |
| 1526 | + "", |
| 1527 | + "<p><b>Guideline</b></p>", |
| 1528 | + "<p>• Use access types to class-wide types to implement heterogeneous polymorphic data structures.</p>", |
| 1529 | + "<p>• Use tagged types and type extension rather than variant records (in combination with enumeration types and case statements).</p>", |
| 1530 | + "", |
| 1531 | + "<p><b>Example</b></p>", |
| 1532 | + "<p>An array of type <code>Employee_List</code> can contain pointers to part-time and full-time employees (and possibly other kinds of employees in the future):</p>", |
| 1533 | + "<pre><code language=\"Ada\">-----------------------------------------------------------------------------------", |
| 1534 | + "package Personnel is", |
| 1535 | + " type Employee is tagged limited private;", |
| 1536 | + " type Reference is access all Employee'Class;", |
| 1537 | + " ...", |
| 1538 | + "private", |
| 1539 | + " ...", |
| 1540 | + "end Personnel;", |
| 1541 | + "-----------------------------------------------------------------------------------", |
| 1542 | + "with Personnel;", |
| 1543 | + "package Part_Time_Staff is", |
| 1544 | + " type Part_Time_Employee is new Personnel.Employee with", |
| 1545 | + " record", |
| 1546 | + " ...", |
| 1547 | + " end record;", |
| 1548 | + " ...", |
| 1549 | + "end Part_Time_Staff;", |
| 1550 | + "-----------------------------------------------------------------------------------", |
| 1551 | + "with Personnel;", |
| 1552 | + "package Full_Time_Staff is", |
| 1553 | + " type Full_Time_Employee is new Personnel.Employee with", |
| 1554 | + " record", |
| 1555 | + " ...", |
| 1556 | + " end record;", |
| 1557 | + " ...", |
| 1558 | + "end Full_Time_Staff;", |
| 1559 | + "-----------------------------------------------------------------------------------", |
| 1560 | + "...", |
| 1561 | + "type Employee_List is array (Positive range <>) of Personnel.Reference;", |
| 1562 | + "Current_Employees : Employee_List (1..10);", |
| 1563 | + "...", |
| 1564 | + "Current_Employees(1) := new Full_Time_Staff.Full_Time_Employee;", |
| 1565 | + "Current_Employees(2) := new Part_Time_Staff.Part_Time_Employee;", |
| 1566 | + "...", |
| 1567 | + "</code></pre>", |
| 1568 | + "", |
| 1569 | + "<p><b>Rationale</b></p>", |
| 1570 | + "<p>Polymorphism is a means of factoring out the differences among a collection of abstractions so that programs may be written in terms of the common properties. Polymorphism allows the different objects in a heterogeneous data structure to be treated the same way, based on dispatching operations defined on the root tagged type. This eliminates the need for <code>case</code> statements to select the processing required for each specific type. Guideline 5.6.3 discusses the maintenance impact of using <code>case</code> statements.</p>", |
| 1571 | + "<p>Enumeration types, variant records, and case statements are hard to maintain because the expertise on a given variant of the data type tends to be spread all over the program. When you create a tagged type hierarchy (tagged types and type extension), you can avoid the variant records, case statement, and single enumeration type that only supports the variant record discriminant. Moreover, you localize the <i>\"expertise\"</i> about the variant within the data structure by having all the corresponding primitives for a single operation call common <i>\"operation-specific\"</i> code.</p>", |
| 1572 | + "<p>See also Guideline 9.2.1 for a more detailed discussion of tagged types.</p>", |
| 1573 | + "", |
| 1574 | + "<p><b>Exceptions</b></p>", |
| 1575 | + "<p>In some instances, you may want to use a variant record approach to organize modularity around operations. For graphic output, for example, you may find it more maintainable to use variant records. You must make the tradeoff of whether adding a new operation will be less work than adding a new variant.</p>" |
| 1576 | + ] |
| 1577 | + } |
| 1578 | + }, |
| 1579 | + "ADA95_5.4.2": { |
| 1580 | + "checked": false, |
| 1581 | + "language": "Ada", |
| 1582 | + "tags": [ "Language: Ada", "Standard: Ada 95", "Data Structures" ], |
| 1583 | + "name": "Published Standards/Ada 95/5.4.2 Heterogeneous Related Data", |
| 1584 | + "desc": { |
| 1585 | + "html": [ |
| 1586 | + "<b>", |
| 1587 | + "<span style=\"color:red\">This check cannot be automated</span>", |
| 1588 | + "</b>", |
| 1589 | + "", |
| 1590 | + "<p><b>Guideline</b></p>", |
| 1591 | + "<p>• Use records to group heterogeneous but related data.</p>", |
| 1592 | + "<p>• Consider records to map to I/O device data.</p>", |
| 1593 | + "", |
| 1594 | + "<p><b>Example</b></p>", |
| 1595 | + "<pre><code language=\"Ada\">type Propulsion_Method is (Sail, Diesel, Nuclear);", |
| 1596 | + "type Craft is", |
| 1597 | + " record", |
| 1598 | + " Name : Common_Name;", |
| 1599 | + " Plant : Propulsion_Method;", |
| 1600 | + " Length : Feet;", |
| 1601 | + " Beam : Feet;", |
| 1602 | + " Draft : Feet;", |
| 1603 | + " end record;", |
| 1604 | + "type Fleet is array (1 .. Fleet_Size) of Craft;", |
| 1605 | + "</code></pre>", |
| 1606 | + "", |
| 1607 | + "<p><b>Rationale</b></p>", |
| 1608 | + "<p>You help the maintainer find all of the related data by gathering it into the same construct, simplifying any modifications that apply to all rather than part. This, in turn, increases reliability. Neither you nor an unknown maintainer is liable to forget to deal with all the pieces of information in the executable statements, especially if updates are done with aggregate assignments whenever possible.</p>", |
| 1609 | + "<p>The idea is to put the information a maintainer needs to know where it can be found with the minimum of effort. For example, if all information relating to a given <code>Craft</code> is in the same place, the relationship is clear both in the declarations and especially in the code accessing and updating that information. But, if it is scattered among several data structures, it is less obvious that this is an intended relationship as opposed to a coincidental one. In the latter case, the declarations may be grouped together to imply intent, but it may not be possible to group the accessing and updating code that way. Ensuring the use of the same index to access the corresponding element in each of several parallel arrays is difficult if the accesses are at all scattered.</p>", |
| 1610 | + "<p>If the application must interface directly to hardware, the use of records, especially in conjunction with record representation clauses, could be useful to map onto the layout of the hardware in question.</p>", |
| 1611 | + "", |
| 1612 | + "<p><b>Notes</b></p>", |
| 1613 | + "<p>It may seem desirable to store heterogeneous data in parallel arrays in what amounts to a FORTRAN-like style. This style is an artifact of FORTRAN's data structuring limitations. FORTRAN only has facilities for constructing homogeneous arrays.</p>", |
| 1614 | + "", |
| 1615 | + "<p><b>Exceptions</b></p>", |
| 1616 | + "<p>If the application must interface directly to hardware, and the hardware requires that information be distributed among various locations, then it may not be possible to use records.</p>" |
| 1617 | + ] |
| 1618 | + } |
| 1619 | + }, |
1414 | 1620 | "ADA95_5.3.4": { |
1415 | 1621 | "checked": false, |
1416 | 1622 | "language": "Ada", |
|
0 commit comments