Each potential reuser should also estimate the effort needed to develop the functionality he needs from scratch, and the probability that he will reuse the component.
Based on this input, we can decide if we will develop the component for reuse. All the estimates made during the analysis of requirements and solutions should be saved to enable comparison with actual data (see Chapter 4). Note that this step is taken before we start the bulk of the development effort.
2. Capture all requirements as parts of the analysis models. [p300]
3. Use a notation that is easy to understand.
4. Present the models in a clearly visible way to all project members.
5. Refine and formalize the analysis models. [p301]
6. Conduct a formal review of the outputs from the analysis phase.
9. Generalize in such a way that future alterations of the component are supported (i.e. introduce high level abstractions).
10. Pinpoint variants among existing and future systems within the domain.
12. Distribute system intelligence evenly.
14. Factor common responsibilities as high as possible up the inheritance hierarchy.
15. State responsibilities as generally as possible. [p309]
16. Minimize the number of collaborations a class has with other classes or subsystems
17. Minimize the number of subsystems.
18. Make subsystems out of classes which are likely to be affected by the same minor change in requirements.
20. Introduce subsystems late in the architectural design phase.
22. Use multiple inheritance rarely.
23. If an operation X of a class is implemented by performing a similar operation on another class, then that operation should also be named X (recursion introduction). [p312]
24. One task - one method. Each method should perform only one task to keep it simple. For example, decompose a method called "put_and_print" into two methods.
25. Subclasses should be specializations.
26. The top of a class hierarchy should be abstract. [p313]
27. Keep a small total protocol for a class.
28. Keep classes small - avoid introducing too many methods.
30. Class hierarchies should be fairly deep and narrow. [p314]
31. Factor implementation differences into new abstractions.
32. Favor uniformity over specificity in naming conventions.
33. Keep method signatures consistent. [p315]
35. All methods intended to be overloaded or redefined in subclasses must be declared as virtual.
36. Do not cast down the inheritance hierarchy unnecessarily.
36. Try to avoid inheritance with cancellation.
38. Do not use private inheritance. [p331]
39. Keep classes small - avoid large total protocols.
40. Keep classes small - avoid the introduction of too many methods.
41. Keep the number of method arguments small.
42. Keep methods small.
43. Declare member methods "const" when possible. [p332]
44. Declare parameters "const" when possible.
45. Always make destructors virtual in the base class.
46. Eliminate "switch" statements on object types.
47. Specify attributes as "private". [p333]
48. Use "protected" methods instead of protected attributes in the base class, for interfacing the subclasses.
49. Avoid using "friends" if possible.
50. Avoid implicit "inline", that is, implementation and code in header files.
52. Implement implicitly generated class methods: constructor, destructor, copy constructor, and assignment operator.
53. When copying or assignment makes no sense, hide the copy constructor and the assignment operator in the "private" part of the class specification.
56. Couple specific test cases and test beds to the component, components, or users they are intended to represent.
58. Record the test beds used for a component.
These components can be of several types:
Note that in some cases (e.g. in a mature domain), guidelines, standards and application generators may be of benefit, but here we mainly deal with components which will compose the application.
60. Enlarge the scope of the search for reusable components as widely as possible within the company, and do not ignore external sources of reusable components. [p347]
61. Use the taxonomy put forward by the company. [p348]
62. Use the appropriate view of a component to understand it.
63. Use domain analysis results, if available, to understand the characteristics of the component.
64. Consult experienced people. [p349]
65. Carry out a study of a high-level component so that you fully understand it and can make an appropriate selection if time allows.
66. Study the technical solutions for implementing adaptations based on your chosen mode of reuse. [p350]
67. Determine the appropriate level of investigation of components depending on the component type and the types of requirements to be fulfilled. [p351]
68. Evaluate the distance between candidate components and the requirements.
69. When using evaluation models based on metrics, consider the different evaluation levels of FCM (factor-criteria-metrics). [p352]
70. Do not forget to study the adaptations you need to integrate the component into the application development.
71. When selecting components, you should choose standardized ones in the absence of any other criteria. [p354]
72. Use a project-wide or module-wide prefix for each outstanding global name.
73. Define a standard communication protocol.
74. When making adaptations of a component in a given phase, do not forget to carry this information forward to the following phases.
75. Identify reuse opportunities during the specification phase, and identify specific reuse requirements that support them. [p359]
76. Do not over-specify requirements.
77. Use the domain analysis and validate new application requirements.
78. Use the products from domain analysis to understand the context in which the application takes place, and its dynamics.
79. Use available documentation as much as possible when learning about a reuse repository. [p360]
81. Consider downstream detailed design for framework evaluation.
82. Preserve the strategy implemented in the framework when adapting it.
83. Keep the life cycle sequencing for framework adaptation.
84. Use inheritance to customize reused frameworks. [p363]
86. Establish implementation standards that facilitate the ease and safety of code reuse.
87. Control and document each modification performed on the component.
88. Rename programming entities when necessary.
89. Keep the naming coherent. [p366]
90. Keep coherence when manipulating programming entities.