Refactorings by Stakeholder Concerns

We also have a Refactorings by Smells / Drivers index.

This index lists refactorings by the stakeholder concerns they address (Show / Hide all details):

Agility 

  • Segregate Commands from Queries  (Show Details ) (Hide Details )

    Read and write operations may evolve at different speeds. For example, data analytics queries may often change, driven by client demand and insights just gained.

Auditability 

  • Externalize Context Representation  (Show Details ) (Hide Details )

    In multi-protocol scenarios and long-running client-provider invocation sequences, end-to-end security guarantees can only be given and enforced when the information in protocol headers is aggregated and correlated somehow. System and process assurance audits appreciate if all relevant compliance information can be found in a single place (that is protected properly).

Client Information Needs 

  • Add Wish List  (Show Details ) (Hide Details )

    APIs are often used by multiple clients with differing information needs, which makes it difficult for their providers to offer one-size-fits-all solutions.

  • Add Wish Template  (Show Details ) (Hide Details )

    As motivated in Add Wish List, APIs are often used by multiple clients with differing information needs, which makes it difficult for providers to offer one-size-fits-all solutions. Some clients may require overviews of information elements, for instance list of identifiers, others may require a few or all of the data fields/attributes of these elements that the API is able to provide.

Cohesion 

Cost 

  • Relax Evolution Strategy  (Show Details ) (Hide Details )

    Less code to be maintained over time means less maintenance costs. Sometimes, a planned (or managed) obsolescence approach is followed. Tighten Evolution Strategy also discusses this concern.

  • Tighten Evolution Strategy  (Show Details ) (Hide Details )

    Effort comes with cost. Operational and capital expenditure, including budget for training, evolution (including documentation), and operations increase as lifetime guarantees are extended.

Coupling 

  • Merge Endpoints  (Show Details ) (Hide Details )

    See Wikipedia entry and pattern summary of Loose Coupling.

  • Merge Operations  (Show Details ) (Hide Details )

    In our context here, coupling is a measure of how closely connected and dependent on each other endpoints and their operations are. The coupling may concern the data exchanged and/or the operation call sequencing. See Wikipedia entry and summary of Loose Coupling in pattern form for general explanations.

Data Access Characteristics 

  • Introduce Pagination  (Show Details ) (Hide Details )

    In principle, the client wants to access all data elements, but not all of these have to be received at once or every time. For example, older posts to a social media site are less relevant than recent ones and can be retrieved separately.

  • Make Request Conditional  (Show Details ) (Hide Details )

    As an API client, I do not want to retrieve data repeatedly that I have obtained already.

Data Currentness 

  • Extract Information Holder  (Show Details ) (Hide Details )

    Data returned by an API might age at different rates. In the e-commerce shop scenario, for instance, the master data of customers (e.g., names, shipping addresses) will change less frequently than transactional data such as orders. API clients might want to cache some of the data retrieved, which is harder if faster-changing data is embedded in a slower-changing data.

Data Privacy 

Developer Experience 

  • Bundle Requests  (Show Details ) (Hide Details )

    Bulk/batch uploads might be prepared by iterating through a data set and then sending API operation calls for each entry in the set. It might be easier to prepare a single technical request message (for instance, a JSON array) that contains several business-, domain-, or application-level requests instead of having to manage the state (running, succeeded, failed) of all individual requests on the client side.

  • Externalize Context Representation  (Show Details ) (Hide Details )

    Accessing protocol headers is different from accessing payload; different local APIs and/or platform-specific libraries have to be used. Consolidating information in the payload reduces the learning effort.

  • Extract Information Holder  (Show Details ) (Hide Details )

    The implementation effort on the client side decreases if fewer requests and less client-side state management are required to fetch the desired data.

  • Inline Information Holder  (Show Details ) (Hide Details )

    An API that offers clients all the data they require with as few requests as possible is easier to use than an API where the client has to issue many requests and requires a complex state management.

  • Introduce Data Transfer Object  (Show Details ) (Hide Details )

    API clients want to navigate to the data they require with minimum effort. This should take as few coding steps (such as statements and expressions) as possible.

  • Introduce Version Identifier  (Show Details ) (Hide Details )

    Explicit versioning might appear to be costly and anti-agile or not RESTful at first glance. However, fixing bugs caused by not knowing about versioning mismatches often is expensive. As Version Identifiers can be placed in protocol headers (in most protocols) or in the message payload, additional learning and decision making is required. Accessing protocol headers differs from accessing payload in terms of code to be written, tool and library support, and portability.

  • Introduce Version Mediator  (Show Details ) (Hide Details )

    Breaking changes in APIs and pressure to upgrade may frustrate client developers, especially if they must migrate to a newer version on short notice. For instance, cloud application developers sometimes have to react rather quick to infrastructure changes introduced by their public cloud providers.

  • Make Request Conditional  (Show Details ) (Hide Details )

    Knowing when and how long to cache which data might be challenging for some API clients. Permanent or temporary storage is required. These valid concerns have to be balanced with the provider’s desire for performance.

Development Velocity 

  • Segregate Commands from Queries  (Show Details ) (Hide Details )

    Read and write operations may evolve at different speeds. For example, data analytics queries may often change, driven by client demand and insights just gained.

Evolvability 

  • Add Wish List  (Show Details ) (Hide Details )

    The information needs of clients change over time, and an API and its provider-side implementation should not have to be changed every time something changes in its clients. Maintaining several variations of the same operation for different clients is possible but increases the maintenance effort and coordination needs, which in turn might constrain the flexibility of the API provider.

  • Extract Information Holder  (Show Details ) (Hide Details )

    Systems and components evolve at different speeds. Hence, they should not depend on each other unless this is justified in the business requirements. Data dependencies often introduce undesired, hard-to-spot coupling.

  • Introduce Version Mediator  (Show Details ) (Hide Details )

    To evolve an API, providers must have the flexibility to refactor, redesign, and adapt an API over time. Ideally, this happens without breaking compatibility, but this is not always realistic.

  • Split Operation  (Show Details ) (Hide Details )

    Operations that follow the single responsibility principle are easier to maintain and evolve over time, for instance because their provider only has a single reason to change their request and response message structure and content during API evolution. Changing an operation that does many things is unnecessarily difficult if the change only affects certain aspects of the operation; unexpected side effects may occur. For example, the access control list has to include the superset of all stakeholders of the “many things”; changing it has a rather large impact. Deprecating the operation also is more complicated if an operation has multiple stakeholders. Test cases have to cover all – and all combinations of – the “many things” the operation is in charge of.

Explainability 

  • Merge Endpoints  (Show Details ) (Hide Details )

    Fewer endpoints might be easier to understand and maintain — if they are cohesive and do not contain too many operations. The refactorings Move Operation and Rename Operation explain the quality attributes #maintainability and #understandability further.

  • Merge Operations  (Show Details ) (Hide Details )

    Fewer operations might be easier to understand and maintain — if they still each have one and only one dedicated responsibility. Move Operation has more explanations.

  • Rename Endpoint  (Show Details ) (Hide Details )

    A good name expresses what an endpoint has to offer, which helps clients decide whether and how to use it. Rename Operation has more explanations of this quality.

  • Rename Operation  (Show Details ) (Hide Details )

    Both API client developers and API maintainers should be able to grasp what an API is supposed to do (and actually does) easily. It should be straightforward to teach API usage. Educated guesses and implicit assumptions are likely to cause misunderstandings that lead to technical risk and defects later on.

  • Rename Representation Element  (Show Details ) (Hide Details )

    A good name expresses what a representation element (such as a JSON object and its properties) has to offer, which helps clients decide whether and how to use it. It has a single meaning and purpose. Move Operation provides a deeper explanation of this quality.

Flexibility 

  • Add Wish List  (Show Details ) (Hide Details )

    The information needs of clients change over time, and an API and its provider-side implementation should not have to be changed every time something changes in its clients. Maintaining several variations of the same operation for different clients is possible but increases the maintenance effort and coordination needs, which in turn might constrain the flexibility of the API provider.

  • Add Wish Template  (Show Details ) (Hide Details )

    Client information needs change over time, but an API and its implementation should not have to be updated every time a client does. Maintaining multiple variants of the same operation for different clients is possible, but increases maintenance cost and coordination effort, which in turn can limit the flexibility of the API provider.

  • Introduce Version Mediator  (Show Details ) (Hide Details )

    To evolve an API, providers must have the flexibility to refactor, redesign, and adapt an API over time. Ideally, this happens without breaking compatibility, but this is not always realistic.

  • Relax Evolution Strategy  (Show Details ) (Hide Details )

    Not having to maintain different versions in parallel makes the provider team more flexible, but limits the options client developers have. Again, Tighten Evolution Strategy features this quality as well.

  • Segregate Commands from Queries  (Show Details ) (Hide Details )

    Keeping read and write operations together is easy to understand and brings functional endpoint #cohesion. Separating these types of operations increases the ability to change rapidly and flexibly.

  • Tighten Evolution Strategy  (Show Details ) (Hide Details )

    The more lifetime guarantees are given and the longer the committed time spans are, the less freedom remains with respect to changing product vision and corresponding API designs (for instance, the role of an API in the organization).

Independent Deployability 

  • Extract Endpoint  (Show Details ) (Hide Details )

    Architectural principles can guide the selection of refactoring. Some are affected positively, some are affected negatively. The Purposeful, style-Oriented, Isolated, channel-Neutral, and T-shaped (POINT) principles for API design fall in this category; extracting an endpoint can improve P, O, and I (but might harm T when looking at a single endpoint and not an entire API).

  • Move Operation  (Show Details ) (Hide Details )

    Architectural principles such as single responsibility and independent deployability can guide the selection of refactoring. Some are affected positively, others negatively. The POINT principles for API design (purposeful, style-oriented, isolated, channel-neutral, and T-shaped) belong to this category; moving an operation to another endpoint can improve P, O, and I (but might harm T when looking at a single endpoint and not an entire API). Some principles might be style-defining (for instance, statelessness of interactions in REST), which makes it even more important to adhere and stick to them during design and evolution.

Interoperability 

  • Externalize Context Representation  (Show Details ) (Hide Details )

    The less protocol-dependent functionality is used, the fewer misunderstandings between communicating parties can occur, and the fewer changes are required when a protocol is replaced by another.

Learnability 

  • Externalize Context Representation  (Show Details ) (Hide Details )

    Accessing protocol headers is different from accessing payload; different local APIs and/or platform-specific libraries have to be used. Consolidating information in the payload reduces the learning effort.

  • Merge Operations  (Show Details ) (Hide Details )

    Fewer operations might be easier to understand and maintain — if they still each have one and only one dedicated responsibility. Move Operation has more explanations.

  • Rename Endpoint  (Show Details ) (Hide Details )

    The more expressive and meaningful a name is, the easier it is to navigate through the code base, for instance when searching for them while fixing bugs and adding features. Move Operation has more explanations of this quality.

  • Rename Operation  (Show Details ) (Hide Details )

    Both API client developers and API maintainers should be able to grasp what an API is supposed to do (and actually does) easily. It should be straightforward to teach API usage. Educated guesses and implicit assumptions are likely to cause misunderstandings that lead to technical risk and defects later on.

  • Rename Representation Element  (Show Details ) (Hide Details )

    A good name expresses what a representation element (such as a JSON object and its properties) has to offer, which helps clients decide whether and how to use it. It has a single meaning and purpose. Move Operation provides a deeper explanation of this quality.

Maintainability 

  • Add Wish Template  (Show Details ) (Hide Details )

    Client information needs change over time, but an API and its implementation should not have to be updated every time a client does. Maintaining multiple variants of the same operation for different clients is possible, but increases maintenance cost and coordination effort, which in turn can limit the flexibility of the API provider.

  • Introduce Version Identifier  (Show Details ) (Hide Details )

    Move Operation explains this quality: “There are many reasons to change an API (in addition to quality refactorings) [@StockerZimmermann2021]. It should be changed as much as required and as little as possible, and ripple effects be avoided. One of the first steps in related maintenance tasks is to determine which parts of the system should be changed.” The impact of the changes on other parts should be kept minimal, but are worth communicating when they occur.

  • Introduce Version Mediator  (Show Details ) (Hide Details )

    Fewer components and/or code paths that handle deprecated behavior make an API and its implementation easier to maintain for the provider.

  • Move Operation  (Show Details ) (Hide Details )

    There are many reasons to change an API (not just refactorings) [@StockerZimmermann2021]. APIs should be changed as much as required and as little as possible, and ripple effects be avoided. One of the first steps in related maintenance tasks is to determine which parts of the system should be changed. An API whose endpoints have clearly separated concerns and distinguished roles helps developers to quickly understand the API.

  • Relax Evolution Strategy  (Show Details ) (Hide Details )

    Reducing the number of versions that run in production and reducing their lifetime guarantees reduces the maintenance effort. See Tighten Evolution Strategy for more explanations.

  • Rename Operation  (Show Details ) (Hide Details )

    APIs should be changed as much as required and as little as possible, and ripple effects be avoided. Expressive operation names help with orientation during API evolution. The source code and documentation on client and provider side using a particular name have to be updated if this name changes.

  • Rename Representation Element  (Show Details ) (Hide Details )

    The more expressive and meaningful a name (for instance, the key in a key-value pair) is, the easier it is to search and navigate the code base, for instance when fixing bugs and adding features during API evolution. Move Operation also covers this quality in more detail.

  • Split Operation  (Show Details ) (Hide Details )

    Operations that follow the single responsibility principle are easier to maintain and evolve over time, for instance because their provider only has a single reason to change their request and response message structure and content during API evolution. Changing an operation that does many things is unnecessarily difficult if the change only affects certain aspects of the operation; unexpected side effects may occur. For example, the access control list has to include the superset of all stakeholders of the “many things”; changing it has a rather large impact. Deprecating the operation also is more complicated if an operation has multiple stakeholders. Test cases have to cover all – and all combinations of – the “many things” the operation is in charge of.

  • Tighten Evolution Strategy  (Show Details ) (Hide Details )

    During their lifetimes, API versions have to be supported and evolved. Security patches are applied, bugs are fixed, and so on. The effort for such activities might not be proportional to the guaranteed lifetime but certainly is related and somewhat coupled to it. Related (sub-)concerns are compatibility and extensibility.

Modifyability 

  • Externalize Context Representation  (Show Details ) (Hide Details )

    The less protocol-dependent functionality is used, the fewer misunderstandings between communicating parties can occur, and the fewer changes are required when a protocol is replaced by another.

  • Introduce Data Transfer Object  (Show Details ) (Hide Details )

    API providers want the freedom to change API implementation details without revealing these changes to clients.

Performance 

  • Add Wish List  (Show Details ) (Hide Details )

    Response time, throughput, and processing time are qualities that concern both API clients and their providers. Unused data that is prepared, transported, and processed wastes resources and ought to be avoided.

  • Add Wish Template  (Show Details ) (Hide Details )

    Response time and throughput are qualities that concern both API clients serving end users and API providers (also explained in Add Wish List). Preparing, transporting, and processing data but not using it on the client side wastes resources and ought to be avoided.

  • Bundle Requests  (Show Details ) (Hide Details )

    Transferring many small requests may stress network and communication endpoints preparing requests and consuming them (for instance, on HTTP or TCP/IP level).

  • Extract Information Holder  (Show Details ) (Hide Details )

    Assembling, transferring, and processing a response utilizes resources both on the provider and on the client side. These resources should not be wasted but treated with care. Bandwidth and computing power are examples of precious (and sometimes costly) resources.

  • Inline Information Holder  (Show Details ) (Hide Details )

    Both API clients and providers are interested in keeping the latency and bandwidth usage low and using as few resources as possible.

  • Introduce Pagination  (Show Details ) (Hide Details )

    Transferring all data elements at once can lead to huge response messages that burden receiving clients and the underlying infrastructure (i.e., network and application frameworks as well as the database) with high workload. For instance, single page applications that receive several megabytes of JSON might freeze until the data has been decoded.

  • Make Request Conditional  (Show Details ) (Hide Details )

    Response time, throughput, and processing time are qualities that concern both API clients and providers. Unused data that is prepared, transported, and processed wastes resources and should be avoided.

  • Segregate Commands from Queries  (Show Details ) (Hide Details )

    Workload such as computation effort (for instance, loading data from data stores, filtering, and formatting it) and high data volumes may make certain operations expensive. Expensive operations (for instance, complex queries) should not slow down cheaper operations (for instance, single updates of single attribute values).

Reliability 

  • Extract Endpoint  (Show Details ) (Hide Details )

    When co-located in a single endpoint and deployed jointly, operations might influence each other. For instance, if one of them is long-running or causes a provider-internal error, its siblings might suffer from quality-of-service degradations too.

  • Move Operation  (Show Details ) (Hide Details )

    When co-located in a single endpoint and deployed jointly, operations might influence each other. For instance, if one of these operations is long-running or causes a provider-internal error, its siblings might suffer from quality-of-service degradation too.

Scalability 

  • Extract Endpoint  (Show Details ) (Hide Details )

    When co-located in a single endpoint and deployed jointly, operations might influence each other. For instance, if one of them is long-running or causes a provider-internal error, its siblings might suffer from quality-of-service degradations too.

  • Move Operation  (Show Details ) (Hide Details )

    When co-located in a single endpoint and deployed jointly, operations might influence each other. For instance, if one of these operations is long-running or causes a provider-internal error, its siblings might suffer from quality-of-service degradation too.

  • Segregate Commands from Queries  (Show Details ) (Hide Details )

    Workload such as computation effort (for instance, loading data from data stores, filtering, and formatting it) and high data volumes may make certain operations expensive. Expensive operations (for instance, complex queries) should not slow down cheaper operations (for instance, single updates of single attribute values).

Security 

  • Externalize Context Representation  (Show Details ) (Hide Details )

    In multi-protocol scenarios and long-running client-provider invocation sequences, end-to-end security guarantees can only be given and enforced when the information in protocol headers is aggregated and correlated somehow. System and process assurance audits appreciate if all relevant compliance information can be found in a single place (that is protected properly).

  • Extract Information Holder  (Show Details ) (Hide Details )

    Not all API clients have the same access privileges. More fine-grained data retrieval operations make it easier to enforce related controls and rules, avoiding the risk that restricted data “slips through” accidentally. To revisit the e-commerce scenario, what if the shop software also includes public ratings of products that show the name and picture of the rating customer? Here, only limited and carefully selected information about the customer should be returned.

  • Segregate Commands from Queries  (Show Details ) (Hide Details )

    Read and write operations might have different protection needs. Few user roles, for instance, are usually authorized to update master data; many or all user roles may read it. If there are two separate endpoints for read and write access, it might be easier to fine tune the Confidentiality, Integrity and Availability (CIA) rules and related compliance controls. See the OWASP API Security Top 10 for risks and related advice.

Simplicity 

  • Make Request Conditional  (Show Details ) (Hide Details )

    Knowing when and how long to cache which data might be challenging for some API clients. Permanent or temporary storage is required. These valid concerns have to be balanced with the provider’s desire for performance.

  • Segregate Commands from Queries  (Show Details ) (Hide Details )

    Keeping read and write operations together is easy to understand and brings functional endpoint #cohesion. Separating these types of operations increases the ability to change rapidly and flexibly.

Single Responsibility Principle 

  • Extract Endpoint  (Show Details ) (Hide Details )

    Architectural principles can guide the selection of refactoring. Some are affected positively, some are affected negatively. The Purposeful, style-Oriented, Isolated, channel-Neutral, and T-shaped (POINT) principles for API design fall in this category; extracting an endpoint can improve P, O, and I (but might harm T when looking at a single endpoint and not an entire API).

  • Move Operation  (Show Details ) (Hide Details )

    Architectural principles such as single responsibility and independent deployability can guide the selection of refactoring. Some are affected positively, others negatively. The POINT principles for API design (purposeful, style-oriented, isolated, channel-neutral, and T-shaped) belong to this category; moving an operation to another endpoint can improve P, O, and I (but might harm T when looking at a single endpoint and not an entire API). Some principles might be style-defining (for instance, statelessness of interactions in REST), which makes it even more important to adhere and stick to them during design and evolution.

  • Split Operation  (Show Details ) (Hide Details )

    An API that offers endpoints with operations that follow the single responsibility principle is easier to understand for clients (because operations are focussed and do not offer unwanted capabilities) and for the provider staff due to the lower complexity of the implementation.

Understandability 

  • Merge Endpoints  (Show Details ) (Hide Details )

    Fewer endpoints might be easier to understand and maintain — if they are cohesive and do not contain too many operations. The refactorings Move Operation and Rename Operation explain the quality attributes #maintainability and #understandability further.

  • Merge Operations  (Show Details ) (Hide Details )

    Fewer operations might be easier to understand and maintain — if they still each have one and only one dedicated responsibility. Move Operation has more explanations.

  • Move Operation  (Show Details ) (Hide Details )

    There are many reasons to change an API (not just refactorings) [@StockerZimmermann2021]. APIs should be changed as much as required and as little as possible, and ripple effects be avoided. One of the first steps in related maintenance tasks is to determine which parts of the system should be changed. An API whose endpoints have clearly separated concerns and distinguished roles helps developers to quickly understand the API.

  • Rename Endpoint  (Show Details ) (Hide Details )

    A good name expresses what an endpoint has to offer, which helps clients decide whether and how to use it. Rename Operation has more explanations of this quality.

  • Rename Operation  (Show Details ) (Hide Details )

    Both API client developers and API maintainers should be able to grasp what an API is supposed to do (and actually does) easily. It should be straightforward to teach API usage. Educated guesses and implicit assumptions are likely to cause misunderstandings that lead to technical risk and defects later on.

  • Rename Representation Element  (Show Details ) (Hide Details )

    A good name expresses what a representation element (such as a JSON object and its properties) has to offer, which helps clients decide whether and how to use it. It has a single meaning and purpose. Move Operation provides a deeper explanation of this quality.

  • Split Operation  (Show Details ) (Hide Details )

    An API that offers endpoints with operations that follow the single responsibility principle is easier to understand for clients (because operations are focussed and do not offer unwanted capabilities) and for the provider staff due to the lower complexity of the implementation.

Usability 

  • Extract Information Holder  (Show Details ) (Hide Details )

    The implementation effort on the client side decreases if fewer requests and less client-side state management are required to fetch the desired data.

  • Inline Information Holder  (Show Details ) (Hide Details )

    An API that offers clients all the data they require with as few requests as possible is easier to use than an API where the client has to issue many requests and requires a complex state management.