Reusability risk control: quantitative management of software reuse costs

Reusability is a frequently used term in software engineering. It is generally promoted as a selling point of a product or appears in technical design documents. Most audiences who see this concept only understand it as a positive non-functional attribute of software, but ignore the risks hidden behind it. This article starts from another angle to analyze the risks and causes behind the concept of "reusability". With the author's experience in business security and basic security, it proposes a way to manage "reusability costs" in the software development process. risk management model. Starting from the model, we can recognize the various challenges faced when implementing reuse, development cognitive fallacies, formal definition methods of reuse costs, etc. We hope that these inputs can provide readers with some insights in subsequent technical decisions and software development processes. help.

This article is mainly divided into three parts: the first part introduces the definition of reusability and the main technical debt caused by unreasonable reuse; the second part analyzes the reasons for reusability failure; the third part is the construction method of reusable software assets. Provide a formal measurement tool with users, which will lay the foundation for quantitative analysis in the subsequent risk management model evaluation phase; the fourth part proposes a model for managing "reusability risk", covering the entire software development life cycle. The process minimizes the software development and maintenance costs caused by software reuse through the three links of pre-event evaluation, mid-event mitigation and post-event iteration.

1. The ideal and reality of reusability

1.1 Definition of reuse: from code to system

Software reuse is a method to solve software quality and productivity problems. It refers to the reuse of the same or similar software elements during the software development process. By rationally utilizing software reuse technology, we can improve development efficiency and reduce error rates during the development process. At the same time, software reuse can also promote team collaboration and knowledge sharing, allowing developers to better utilize each other's experience and resources. Therefore, in today's fast-paced development environment, software reuse has become one of the key strategies to improve productivity and quality. In the past few decades, the success of many programming languages ​​(Python, Java, etc.) and the vigorous development of open source culture are inseparable from reuse. Software reuse can occur at different granularities, including code and design copying, source code reuse, design and software architecture reuse, and domain-specific software architecture reuse. Early software reuse was mainly focused on the code level, such as shared methods, abstract classes, libraries, microservices, and Docker images. Over time, its extension has expanded to various software products generated at different stages such as domain knowledge, development experience, design documents, requirements analysis, test cases and data. In this article, unless otherwise specified, reusability mainly refers to the reuse of focused code. The "component reuse" below is not limited to the common libraries we usually think of, but also includes code methods, public classes, software Reusable elements in software development such as frameworks and integrable systems.

1.2 Reuse risk: complexity and cost

It is true that the efficiency and quality of software development can be improved through the reuse of components, but reuse is not a silver bullet, and reuse will also have some side effects:

1. Compatibility/security/performance;

2. Increased dependencies between systems;

3. Increased development and maintenance costs.

First of all, issues such as compatibility/security/performance are aimed at users of reusable components. Generally speaking, they can be evaluated before deciding whether to reuse them, and the indicators and processes are relatively clear. I won’t go into details here.

Secondly, reuse will increase system dependencies. Dependencies are a fundamental part of software and cannot be eliminated, but one of the goals of software design is to eliminate dependencies as much as possible and to make dependencies as simple and obvious as possible. When we introduce external components for reuse, the dependencies between software components will lead to an expansion of the scope of component changes and an increase in the cognitive load of the components. The former is for component maintainers, that is, seemingly simple changes need to be The code is modified in many different places, and as the number of consumers grows, it becomes increasingly difficult to balance the different needs; the latter is for the component consumer, that is, the developer needs to know a lot of component domain knowledge to Enable effective component reuse. For example, you need to understand the design intent of several input parameters in the interface to be used, whether there is implicit dependency transfer that leads to dependency conflicts, etc. The increase in dependencies will introduce more complexity into the system, and we know that the core challenge of building software systems is to manage complexity. Reusing components will only transfer complexity to a certain extent, but it does not eliminate complexity. Therefore, we need to strike a balance between "reusing components to reduce costs" and "reusing components to introduce dependencies (complexity)".

Finally, reuse increases costs. Including development costs, change costs, integration costs, and domain knowledge migration costs. For a component designed for reuse, the design and development cost of implementing the correct abstraction and common framework is much higher than a one-time solution. For subsequent maintainers of the component, such reusable frameworks and libraries There's often a steep learning curve (since documentation is often missing), components will gradually become corrupted, and you'll eventually have to tear them down and start over. In addition, for users of reusable components, the cost of understanding and integrating components is usually ignored. Some strongly promoted "pseudo-reuse frameworks" in the business layer have brought huge integration costs to front-end integration students. , learning and maintenance costs.

Some of the problems caused by the above reuse can be avoided, such as the matching of compatibility, performance, capacity, etc., while some are unavoidable, such as the development cost of designing universal components and code corruption caused by unreasonable abstraction. , maintenance costs caused by unreasonable reuse, etc. In fact, no matter how sophisticated our technical design is, technological innovation will always lag behind the rate of system corruption.

In order to minimize the risks caused by reuse, this article proposes a "reusability risk" response model that is analogous to security risk management, starting from the three stages of pre-assessment, mitigation during the event, and post-event iteration, to maximize To effectively reduce the various risks we encounter in developing and using reusable components. It should be noted that the "reusability risk" mentioned above and below is defined as the problem of "due to unreasonable reuse decisions, which leads to excessive expansion of dependencies and complexity, resulting in excessive software maintenance costs." In addition to cost In addition to risks, risks in compatibility, security, performance and other aspects caused by the unreasonable use or defects of reused components are more significant and easy to manage, so they are not the focus of this article. In addition, risks such as deviation in development goals, delays in iteration and release plans, and staff shortages during the reuse development process will not be discussed here due to space limitations.

The second part will first introduce several main reasons that lead to the failure of the principle of "reuse improves software development efficiency". The third part will focus on introducing several tools for evaluating reusability, so as to gain an understanding of the essence of reusability. Finally, in the fourth part we will briefly introduce the reusability risk management model.

2. Root cause analysis of reusability risks

2.1 Realistic Challenges: Right and Wrong Abstractions

One of our original intentions for reusing components is not only to improve research and development efficiency, but also to hope that reusable components can isolate the complexity of the domain in a place where we can never see it, thereby reducing the overall system complexity of the component user. . Therefore, the design process of a reusable component, regardless of its size, is a highly abstract process in a certain field. When designing components, facing current or potential needs requires us to do a certain forward universal design and shield the implementation details of the components as much as possible. The result of abstraction directly determines the subsequent reusability of the component. High or low (measures of reusability are detailed in the next section). But unfortunately, good abstraction ability is a scarce product for most developers. It requires clear definition, simplification and decomposition of problems, while identifying and utilizing common patterns to combine solutions to sub-problems to form A holistic solution that relies on long-term practice and thinking about design patterns, open source libraries and frameworks, data structures and algorithms, and mass production projects.

In daily code, we have many abstractions, but most of them are unreasonable abstractions. Wrong abstraction causes more harm than non-abstraction. For example, a common phenomenon is: knowing little about the scope of application of design patterns, and abusing design patterns just for the sake of showing off skills, resulting in reduced code readability and maintainability.

In addition to the requirements for abstract capabilities, many factors such as demand urgency, development resources, responsibility, and changes in the domain responsibilities of the components will cause reusable components to carry the original sin of "high cost" from birth, and their subsequent The use and maintenance costs will rise sharply, so I won’t go into them one by one here.

2.2 Cognitive fallacy: reuse is not a design goal

A cognitive fallacy about reusability is to equate "no duplication" with "reuse". There are similarities between the two concepts, but there are still some subtle differences. "Don't Repeat Yourself" is the well-known DRY principle (Don't Repeat Yourself). Its goal is to avoid the maintenance cost of inconsistent copies by reducing repeated construction, while Reusability is to find repeated parts from all codes, and then in complex Under the premise of controllability, we strive to abstract things that can be reused. A bunch of non-duplicated code does not mean there are reusable components.

Reuse is just a means to achieve the goal of non-duplication. "No duplication" is our goal when designing software systems. Simply pursuing "reusability" will often put the cart before the horse. For example, some automatic testing frameworks and business middle-end frameworks with very high access costs have emerged, blindly pursuing "(I) develop once, (you) use it anywhere", but little do they know that the user needs to spend a lot of energy to internalize the framework designer The original design intention is that it is at a loss when faced with more than a dozen access parameters or configuration files.

For example, we occasionally see that in the business layer code, some students abstract the simple addition and modification logic into a method, euphemistically called "providing it to the access layer for reuse", such as the insertOrUpdate method below At first glance, it seems that the code for domain object conversion and user object existence is reused, which conforms to the DRY principle, but in fact it mixes two different business semantics, which will bring higher costs to subsequent maintenance, such as When changing user information, more personalized user attribute processing is required. At this time, adjusting the code at the domain object conversion point will affect the new logic.

A more reasonable implementation is to split codes with obviously different semantics. Although there seems to be a certain degree of code duplication, its design will be more conducive to subsequent functional iterations and is more in line with the "single responsibility" design principle of the code.

2.3 Decision bias: Where is the decision-making power for reuse?

Code reuse is mostly done voluntarily by software developers, but one thing we cannot ignore is how to integrate, whether to reuse, how to reuse, whether it is the same function, and what granularity of reuse is used. Many times It is determined by the business structure, and "Conway's Law" cannot be avoided.

For example, in a new scenario, the product requires reusing "a function with the same name on the PPT" to quickly go online. Although they have the same name, their product forms, business processes, environmental dependencies, etc. are different. The final result of forced "reuse" is that a large number of branch judgments appear in the code logic, and the underlying technical architecture becomes bloated. Due to different understandings of the field, this situation is inevitable. Although in many cases the decision-making power for software reuse does not lie with the developer, but out of technical sentiments or sense of responsibility, developers have the obligation to make such corrections and eliminate such differences to the greatest extent. However, it is necessary to realize that the role of technology is not decisive here. Excellent technology is a necessary but not sufficient condition for successful reuse.

2.4 Missing Tools: How to Calculate Reuse Costs

Reusability measurement is mainly divided into two parts:

1. Reusability: What are the factors that determine the level of reusability of a component?

2. Reuse cost: How to calculate the ROI after the component integrator and the organization where the component is located decide to implement the reuse strategy?

Through the two indicators of reusability and reuse cost, we can conduct a quantitative analysis of reusability to a certain extent and make more long-term technical decisions. For example, you can learn about the characteristics of a highly reusable component. When introducing a new third-party component, besides the basic functional components, what else do I need to consider? Rather than using existing components, would you consider reinventing the wheel? How much is the cost between "reuse" and "wheel-making"? Regarding the measurement tools of reusability, the third part will focus on it.

3. Formal measurement of reusability

3.1 Component metrics: assessment of reusability level

When we design a reusable component such as a piece of code/a class/a module, some measurable software indicators jointly determine the level of reusability of the component. These indicators include: Reliability (Reliability), Readability (Understandability), Maintainability (Maintainability), Generality (Generality) and Portability (Portability), as shown in the figure below. Each indicator can be determined by various code measurement attributes. For example, the portability of a component is determined by the two attributes of "component independence" and "coupling". Most of the measurement attributes can be formally defined and calculated. The determinants and measurement values ​​(in brackets) of different indicators are as follows:

1. Reliability: performance (response time), fault tolerance (recovery time);

2. Universality: class generalization level (number of subclass instances or number of interface implementation classes);

3. Readability: cohesion (coupling between classes), complexity (cyclomatic complexity), scale (number of lines of code), document level (number + completeness);

4. Maintainability: easy to modify, single test and regression test (test coverage), independence of components (number of dependencies), coupling (degree of coupling between classes);

5. Portability: independence of components (number of dependencies) and coupling (degree of coupling between classes).

In order to measure the reusability of the entire component, it is necessary to define a reusability calculation model. This model is based on the reusability attribute model shown above. The relationships between the main reusability attributes, the factors that influence these attributes, and the metrics that measure these factors are shown in this model. In theory, the reusability of a software component (  expressed as Reusability  ) can be calculated using the expression:

Reusability = w1*M + w2*R + w3*P + w4*U + w5*G

Among them,  w1 ~ w5  are the weight values ​​of different indicators. After the indicator  M (Maintainability), R (Reliability), P (Portability), U (Understandability), and G (Generality)  values ​​are normalized (0...1), Multiply the different weight values ​​of each indicator to calculate the final reusability of the component.

In the above analysis process, there are cases where some measures cannot be quantitatively analyzed, but the calculation of different factor combinations is still meaningful. We can use these indicators to evaluate the severity of the problems in our current system. The next time someone asks us why we should reuse component A instead of component B, we can give a more convincing reason, not just "I think" or "A is much better than B" and other arguments.

3.2 Organizational measurement: input-output ratio of reuse

After having a perceptual understanding of the reusability of components, let us take a step further to think about the cost issue behind reusability from an economic perspective. First, we define several variables  RL, NUC, RCR, and RCWR .

  • RL (Reuse Level) : The proportion of reusable components in the application, that is, RL = the number of lines of code in the reused components/the total number of lines of code in the application;
  • NUC (Not Use Cost) : The cost of not using reusable components at all during the application development process. Note that subsequent maintenance costs are not included;
  • RCR (Relative Cost of Reuse) : The ratio of workload between reusing existing components and re-creating a similar wheel is generally between 0.03~0.4, and the empirical value is 20%, which means The cost of reuse is about 20% of the investment of writing a new component;
  • RCWR (Relative Cost of Writing for Reuse) : The ratio of workload between developing reusable components and developing one-time use modules is generally between 1.0 and 2.2, and the empirical value is 1.5, which means Writing reusable software requires approximately 50% additional cost.

For the integrator, the cost savings due to reuse (DCA, Development Cost Avoidance) and the cost savings ratio after reuse (DCAR, Development Cost Avoidance Ratio) can be calculated:

For example, if the reuse degree RL = 40% and RCR = 0.2, then the software integrator's cost saving ratio = 0.64, that is, 64% of the cost is saved. At the same time, we can draw a simple conclusion. For component integrators, if you want to increase the cost ratio, you need: the higher the reusability of reusable components in the project, the better. At the same time, the higher the reusability of reusable components, the better. RCR should be lower. This means that the scalability and readability of reusable components need to be maintained at a high level, so that the integrator's secondary development and adaptation costs during integration will be lower. This conclusion is also in line with our intuition during research and development. .

For an organization, if N scenarios of a reusable component are used, the organizational reuse income OROI can be calculated as follows:

For example: If the reusability RL = 40%, RCR = 0.2, RCWR = 1.5, and the number of reuses is 5 times, the organizational benefit OROI = 167%, which means developing a reusable component that can be used in multiple scenarios at the same time Reuse has excess returns. But won’t there be benefits as long as it is reused? In addition, OROI = (N*(1-RCR) - RCWR)/RCWR > 0, we can get N > RCWR/(1-RCR), and bring in the two preset values ​​of RCR = 0.2 and RCWR = 1.5 above to get N > 2, which means that two or more scenarios need to reuse this component before our R&D activities will achieve positive benefits. At the same time, we can draw the following conclusions from the above formula about improving organizational reuse ROI: the higher the reusability of reusable components in the project, the better. When developing reusable components, the lower the RCWR and RCR The better. Low RCWR means not to over-design, and the generalization of components needs to be controlled within the domain. Low RCR means that reusable components have good readability, high scalability, and low integration costs.

Martin Fowler proposed a code refactoring rule of thumb "Rule of Three" in his book "Refactoring", that is, we can copy and paste code once, but when the same code is copied three times, it should be It is extracted into a new process for abstraction to facilitate reuse. The minimum number of repetitions in the rule is 3, and its value is also consistent with the above conclusion of N > RCWR/(1-RCR).

3.3 Repeated Measurement: The Boundary of Reuse and Replication

Back to the question we mentioned in Section 2: Why is the DRY principle not equivalent to reuse? Assume the following scenario: 1. A global string constant class is designed in the project. All public constants are placed here. Classes in other modules all reference this constant. Is this a good practice? Is it defined in the module? Would it be better to have a constant class or a constant field in the class? 2. I need to perform string weight judgment logic. Should I rewrite a string tool class myself, or should I directly use the code in the commons-lang or guava package? There is no absolute answer to the above scenarios, but from what I have seen so far, in the coding habits of many developers, due to excessive pursuit of "reusability", some unnecessary dependency burdens have appeared, such as using Global constant classes, unnecessary class loading, and arbitrary use of third-party packages cause application package expansion or package conflicts during integration. Sometimes it's better to copy some similar code than to try to generalize and instantiate it. Overuse of abstractions only obscures the real key issues.

So when is copying allowed and when is it not recommended? In addition to the moderate copying (not reuse) when the semantics are inconsistent mentioned in 2.2, when the code we actually use accounts for a low proportion of the overall code logic of the reusable component (for example, only StringUitls in the commons-lang package is used) class), you can consider rewriting it and copying and pasting appropriately to achieve "autonomy" of the logic and integration side. Corresponding to the previous conclusion, this case means that RL is low and  RCR is high, for example, RL = 0.01, RCR = 0.8, then the software integrator’s cost saving ratio is only RL*(1-RCR) = 0.2%, which means Compared with the small benefits and potential risks (packet bloat and package conflicts) later, replication may be a better choice.

4. Reusability risk management model

With the previous two parts laying the groundwork, let's go back and examine the cost risks introduced by reuse. What measures should be taken to minimize the risks? In pan-information security businesses such as business risk control and data security, our abstraction of risk management will emphasize the risk control process before, during and after the event. Similarly, during the code development process, we can reduce the possibility of risks and their impact by establishing reusable risk management and control methods for pre-assessment, in-process mitigation and post-event iteration , and based on the business architecture and technical architecture The development trend adopts measures to avoid, reduce and transfer risks to control risks to a level that the team can bear, and to avoid or delay problems such as high maintenance costs and rapid system corruption caused by reuse to the greatest extent.

The full life cycle reusability risk management model formed by pre-event assessment, mid-event mitigation, and post-event iteration is shown in the figure below:

4.1 Ex ante evaluation: cost and heuristic decision-making

The pre-event stage of risk control (assessment + analysis) is generally based on certain black samples to unearth certain risk behavior characteristics or models suitable for the subsequent risk confrontation stage, and calculate the accuracy and recall rate based on historical samples. In the pre-event stage of reusability risks, we can also use qualitative and quantitative assessment methods to detect various "bad smells" in reuse as early as possible, correct or prevent them immediately, nip risks in the bud, and avoid mistakes due to wrong decisions. Reuse introduces too much technical debt. The evaluation process is mainly divided into three stages: evaluation of reusable components, measurement of reuse costs and benefits, and heuristic decision-making. Specifically:

1. If the component to be reused already exists, the reusability level of the reused component can be calculated or estimated. The indicators considered are the reliability, readability, maintainability, and versatility mentioned above. And transferability, the indicator weights in different scenarios are different, and judgments can be made based on specific scenarios;

2. If the components to be reused need to be newly built, the labor costs saved by subsequent integration can be calculated, as well as the overall benefits obtained by the organization through reusing the components in the medium and long term. By combining the reuse costs, reuse benefits, The current organizational manpower status and follow-up business make final decisions;

3. If steps 1 and 2 cannot reach a final conclusion, there are some heuristic experiences below to help us decide whether reuse is really needed.

Scenarios that may require reuse (abstract components or reuse existing components):

1. The business logic to be reused is very professional, such as Json serialization, encryption and decryption;

2. Code with the same or similar business semantics already exists in multiple (3) places and needs to be refactored;

3. The documentation for the reusable components to be selected is very comprehensive and easy to access, expand, replace or remove;

4. Business logic changes frequently, and each change requires changes to multiple systems or modules at the same time to maintain synchronization;

5. Some business logic units that need to be shared immediately and have low tolerance for inconsistency, such as table meta information.

Scenarios that may not need to be reused (then reinvent the wheel):

1. There is no documentation, or the quality of the documentation is poor;

2. It is not difficult to re-create one, and the maintenance cost is low;

3. Only a little logic from all the functions of the reusable component is used;

4. It takes a lot of time to understand the design ideas of reusable components;

5. When reusable components expand new functions, a lot of energy needs to be invested in collaborative advancement;

6. The adaptation or expansion code required when integrating reusable components is more than the code required to rewrite the component alone;

7. Reusable components are the core of the entire application, and the subsequent rapid business development requires more customization;

8. The product documentation or system design of reusable components promises too many functions (pie) and is too "ambitious";

9. The last point: If you think it is useful or not when making a decision, then there is a high probability that it does not need to be reused. Trust your first judgment.

Through cost and benefit estimation, as well as several heuristic decision-making experiences, we can evaluate most scenarios and get a clear answer to whether to reuse. Software reuse may increase productivity in the short term, but it can have long-term consequences, so this step needs to be taken with caution.

4.2 Mitigation in the event: HCLC&Testing&Documentation

The mid-event mitigation stage is the core link in controlling reusability risks. It mainly focuses on the development stage of reusable components and reduces reuse risks as much as possible before development or formal use through a series of key steps, which mainly include Here are some key points:

  • High cohesion and low coupling
  • Unit testing and regression testing
  • Complete and effective documentation

High Cohesion Low Coupling (HCLC). This is a commonplace thing. Cohesion and coupling will affect multiple indicators in the reusability level, such as whether cohesion will affect readability and portability, and coupling will affect maintainability, portability and readability. sex. There are already many design principles or patterns for us to choose from in software engineering, such as priority combination, dependency inversion, nested substitution, interface isolation, single responsibility, open and closed, 23 design patterns, etc. in the code development stage. In the architecture design stage , there are also several architectural design patterns or methodologies, such as layering, CQRS, asynchronous event-driven, domain-driven design, etc.

Complete and valid documentation. "Good code is self-explanatory" is not entirely true. First of all, whether it is our architecture design or code design, many things cannot be systemized in the code, such as the choice of domain abstractions, the thinking process of decision-making, etc. Even our interfaces, member variables, and implementations, among others, The naming and design process has reached a very high level, and the "hidden information" in the code will still be lost, and comments can make up for this loss as much as possible. Secondly, it is necessary to realize that human perception and communication are very slow and inefficient, and documents need to be used to fill this gap in communication between the two parties. Of course, what is discussed here is a general situation, and behavioral patterns that rely on "undocumentation" to build core "competitiveness" should not be classified into this category. Finally, in a normal organization, personnel will be lost, and most people will eventually leave the organization. If the key designers of reusable components are no longer in the organization, this loss of knowledge will be permanent, document ( Annotations, designs) serve as a backup of domain knowledge.

Unit testing and regression testing. The reason why the reuse theory is established is that we hope to use existing and mature software assets to improve R&D efficiency and reduce system defects. A comprehensive set of automated regression tests will not only benefit the integrator, but also allow subsequent and this Everyone benefits from reusable components. If the reusable components we develop do not have automated regression testing, then such components are unqualified and should not be released to the public repository. The lack of automated testing or components with low core process automated testing coverage is a disaster for the integrator and subsequent maintainers of the components. It introduces huge technical debt to the system, which is more reusable than the complete lack of supporting documentation. components.

4.3 Post-Iteration: Capturing Domain Changes & Organization

When developing reusable components, investing R&D resources aggressively at the outset may end up creating software assets that are irrelevant to immediate requirements and incur significant schedule risks due to increased design, development, and testing time. Conversely, by Multiple iterations of improving reusable components reduce these risks. A good component, framework, and software architecture takes time to design, implement, optimize, verify, apply, maintain, and enhance. At the same time, after the first phase of development and integration, continuous risk management during the iterative process can keep the risk of reusable components at a low level and extend the life of the components as much as possible. The main things that need to be done include: continuous capture of changes in the field and corresponding organizational support.

Capture domain changes. As mentioned above, there is some implicit knowledge in the code. In fact, a reusable component is the result of the developer's thinking about a certain field , whether it is presented in the form of a class file, module or system. All fields will change. Changes include: the boundaries of the field will expand, the connotation of some entities in the field will change, and the boundaries between different fields will overlap or merge, etc. After the domain changes, if the reusable components in it are not properly adjusted, there will be problems with technology and business pace failure. Reusable components not only encapsulate domain knowledge, but also shield complexity to a certain extent. When components are not enough to bear the domain's entities or functions deviate, the problem of "complexity leakage" will occur.

Two key actions to capture domain change: unify domain context and focus on upstream requirements pools. The importance of unifying the context of the field is self-evident. Many times, the fundamental reason for the deviation of opinions between parties is that everyone has not formed a unified communication language and cannot describe their respective demands simply, accurately and clearly. When I was conducting structural governance for a certain risk domain, the first thing I did was to bring together the industry, industry, and research parties to unify everyone’s understanding of the connotation and boundaries of the two concepts of “rules” and “strategy.” Second, developers and architects need to pay close attention to the requirements pool, starting from the requirements themselves, and distinguish the key sources of variability and commonality in the domain. It is unrealistic to identify all changes in the problem domain. We can focus on some key issues. For example, when facing a new requirement, we can consider:

1. Are the concepts we discuss consistent?

2. Which domain entities does this requirement involve?

3. Does this requirement require us to add a new entity?

4. Will the new entity be ambiguous with the existing entity?

5. Have similar needs existed before? what is the difference?

6. Can new requirements be isolated from existing logic?

7.......

Is there a guiding principle that allows us to make more reasonable designs and choices when tracking changes in these domains? The principle of entropy increase tells us: the entropy of an isolated thermodynamic system does not decrease. For reversible processes of the system, the entropy remains unchanged, while for irreversible processes, the entropy increases. Therefore, analogous to the field of software engineering, in the post-iteration stage of components, a design principle is to eliminate the entropy increase in code design/software architecture as much as possible: new functional points in existing components need to have a reverse deletion mechanism , so that Try to prevent reusable components from becoming chaotic and unmaintainable. The specific operations of reversible functions can be embodied as: SPI mechanism (Service Provider Interface), interface-oriented programming, isolation of random or one-time requirements through modules, etc.

Organization and supporting culture. First of all, the organization is a projection of the business architecture . When there is a deviation between the domain entities in the reused components and the domain entities that the organization is responsible for, technical debt will occur due to misalignment. The results are nothing more than two types: one is the previous repeatable Used components are directly discarded and left to fend for themselves; the other type lacks the courage and responsibility to rebuild from the bottom of the pot. Since it is not my responsibility, then change it and reuse it. The original unified and balanced structure will be broken quickly. Secondly, reusable components and frameworks are only as good as the people who build and use them . We need managers who can evaluate risks and opportunities, who can recognize the intrinsic and accidental complexity of the domain, and who have a good grasp of design patterns. Architects and architectural patterns, as well as developers experienced in development principles, patterns and practices. Whether components can be reused and how long they can be reused is largely a by-product of good design and experienced developers. . Furthermore, in the post-iteration phase, we need a dedicated team or person in charge to be responsible for this reusable asset , constantly monitor the health of the platform code base, track and fix errors, adhere to correct abstractions, and continuously improve documentation. Of course, the above is only an ideal situation. More often than not, such a person or team does not exist, or even if it exists, the corresponding organizational incentives are missing. In a cultural soil without reuse, it is only a matter of time before components become corrupted. Finally, with the right organization and good people, long-term confidence, enthusiasm, motivation, and management support and response are also essential conditions for successful reuse.

5. Some thoughts on reuse

This article wants to focus on several points: don’t pursue “reuse” too much, the level of reusability and the input-output ratio of reuse are quantifiable, reusable assets are implicit domain knowledge, moderate repetition It is also acceptable. Documentation can make up for the loss of domain knowledge. New functions in the evolution of the architecture must be reversible.

The original intention of writing this article stems from the fact that in recent years when guiding new students, I have discovered that there are more "pseudo-reuse" phenomena. For example, in order to reduce code, shared method signatures are placed in interfaces to form a "process "Interface". On the other hand, I have also written some components or modules designed "for reuse". There are about a dozen from middleware to business components. But recently, I have gradually begun to realize that in many cases, for the sake of subsequent portability, the forward defensive design of some architectures or code layers is not very effective, and excessive abstraction causes some understanding difficulties for users. After sorting out this article, which ones really need to be reused and which ones can be compromised, I have firmed up some ideas (such as documenting the entire process) and also corrected some existing concepts.

The point above has been conveyed that good software assets are a by-product of an excellent team. When we focus on reuse from software to people, ourselves, what can be reused, and what are given to us by the platform or organization? Get rid of those weird and illusory parts, and what are the immutable parts? A high-value patent after authorization is considered a type of patent and its validity period is twenty years. Precipitation in the thinking process may be another type. They summarize more or less and stage by stage what was thought at that time. Regardless of whether the content is comprehensive and correct, it is also smeared with the color of time. This is also the reason for this article. Another motivation.

Author|Qi Guang

Click to try the cloud product for free now to start your practical journey on the cloud!

Original link

This article is original content of Alibaba Cloud and may not be reproduced without permission.

Alibaba Cloud suffered a serious failure and all products were affected (restored). Tumblr cooled down the Russian operating system Aurora OS 5.0. New UI unveiled Delphi 12 & C++ Builder 12, RAD Studio 12. Many Internet companies urgently recruit Hongmeng programmers. UNIX time is about to enter the 1.7 billion era (already entered). Meituan recruits troops and plans to develop the Hongmeng system App. Amazon develops a Linux-based operating system to get rid of Android's dependence on .NET 8 on Linux. The independent size is reduced by 50%. FFmpeg 6.1 "Heaviside" is released
{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/yunqi/blog/10140476