Move Operation

Updated: Published: EuroPLoP 2025

Context and Motivation

One or more API endpoints (for instance, HTTP resources) have been developed, tested, and deployed. One endpoint contains multiple operations (for instance, HTTP PUT and POST methods). The externally exposed responsibilities of these operations differ with regards to stakeholder groups and their concerns; some of them work with different domain concept(s) in the underlying API implementation. For instance, some operations are process-oriented activities while others are data-oriented and have information management responsibilities; the quality characteristics, including data protection needs, of these operations differ. As a consequence, the endpoint serves multiple roles in the API architecture. There is a risk that these roles drift further apart during API evolution.

As an API provider, I want to focus and consolidate the operations of an existing endpoint on a single role and purpose so that API client developers serving a particular stakeholder group understand the API design intuitively and the provider has a single reason to change that endpoint. To achieve this goal, I want to move one or more operations to a different, already existing endpoint.

Stakeholder Concerns

#maintainability
There are many drivers for changing an API [Stocker and Zimmermann 2021]. APIs should be changed as much as required and as little as possible, and ripple effects be avoided. One of the first steps in maintenance tasks is to determine which parts of a system have to be changed. Separation of concerns tends to make changes smaller, but also adds to the amount of dependencies between system parts.
#scalability and #reliability
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.
#single-responsibility-principle and #independent-deployability
Principles such as single responsibility and independent deployability can guide the selection of refactorings. Some principles are affected positively, others negatively. With respect to the POINT principles for API design (purposeful, style-oriented, isolated, channel-neutral, and T-shaped), 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). Note that some principles might be defining an architectural style; for instance, statelessness of interactions in REST. Such prominent role makes it even more important to adhere to a principle during design, and stick to its evolution.
#understandability (a.k.a. explainability)
Endpoints with clearly stated, properly separated concerns and distinguished roles help developers to quickly understand and navigate the API. More documentation has to be studied, but its parts are easier to grasp.

Initial Position Sketch

The following platform- and technology-independent API design, specified in MDSL, serves as the starting point for this refactoring:

endpoint type SourceEndpoint
exposes 
  operation operation1 
    expecting payload "RequestMessage1" 
    delivering payload "ResponseMessage1"
  operation operation2 
    expecting payload "RequestMessage2" 
    delivering payload "ResponseMessage2"

endpoint type TargetEndpoint
    // zero or more already existing operations

See Figure 1 for a graphical representation of this initial position sketch. Note that the sketch does not show any particular application/domain semantics or desired qualities that are violated at present; see the following example for such design smells.

Move Operation: Initial Position Sketch. A client uses two different operations (message exchanges 1-2 and 3-4) in an API endpoint.

Figure 1: Move Operation: Initial Position Sketch. A client uses two different operations (message exchanges 1-2 and 3-4) in an API endpoint.

This refactoring targets API endpoints that have several operations, one of which will be moved to an already existing second endpoint (if no such endpoint exists, a new one can be created; this design change is described in the Extract Operation refactoring).

Design Smells

Data lifetime mismatches
Two operations in an endpoint deal with data that changes differently, both on the data definition and on the data manipulation level. For instance, one operation may expose master data and the other one may expose operational data, also known as transaction data. This causes undesired constraints on endpoint evolution. Different lifetimes make caching, especially cache invalidation, harder to manage.
Endpoint implementation spaghetti
There are several n to m relations between API endpoints and their implementation parts. At least one endpoint works with many implementation parts that evolve independently.
God endpoint
One endpoint contains a large number of operations that do not serve related purposes. Derived from the term “god class” [Riel 1996] in object-oriented design, the term describes a class or object that controls many other parts of a system. Many such dependencies on external systems and data make the API implementation difficult to operate and evolve.
Role and/or responsibility diffusion
The endpoint is both an Information Holder Resource and a Processing Resource. It is hard to explain what it does coherently. For instance, some of the exposed data lives long and changes rarely; other data goes through many create, update, delete operations in a short time span.
Too coarse-grained security or data privacy rules
Some operations in an endpoint have more advanced quality requirements than others. For instance, some of them may work with sensitive personal information that has to be protected while others merely operate on public data. Access control policies for operations and shared data may vary as well. Other quality requirements mismatches might exist, for instance regarding availability and scalability.

Instructions

Follow these steps to apply this refactoring:

  1. Remove the operation from the API Description of the endpoint that currently exposes it, or mark it as deprecated and soon to be retired.
  2. Refactor at the code level (for instance, Spring REST controllers when implementing the API in Java). Optionally, implement a new stub that merely redirects clients to the new endpoint operation (in HTTP, this can be achieved with URL redirection and status code 301 [Fielding and Reschke 2014]).
  3. Review the required and provided security policies including the access rights management (both in source and in target endpoint) and adjust as needed.
  4. Add the operation to the target API Description. Update all documentation accordingly.
  5. Test whether the source and the target endpoint still meet their contracts (both functional and non-functional characteristics).
  6. Evaluate whether smells are removed (or at least some desired qualities have improved); record any remaining or new technical debt and identify additional follow-on refactorings.
  7. Inform all API clients about the completed change (in which version will it be introduced?) and provide migration information (or support the transition on a technical level, for instance with an HTTP redirect).

Depending on the backwards-compatibility measures taken by the provider, clients may need to update their request URLs. Alternatively, if URL redirection is used, clients may automatically pick up the new location. See the Rename Endpoint refactoring example for details on how to implement this using the Spring Boot Web framework.

Target Solution Sketch (Evolution Outline)

The following simple and abstract MDSL sketch shows the API design after the Move Operation steps have been performed:

endpoint type SourceEndpoint
exposes 
  operation operation1 
    expecting payload "RequestMessage1" 
    delivering payload "ResponseMessage1"

endpoint type TargetEndpoint    
exposes
  // already existing operations (if any) still there
  operation operation2
    expecting payload "RequestMessage2" 
    delivering payload "ResponseMessage2"

A visual target solution sketch is shown in Figure 2.

Move Operation: Target Position Sketch. The client's API conversations (message exchanges 1-2 and 3-4) now go to two different API endpoints.

Figure 2: Move Operation: Target Position Sketch. The client’s API conversations (message exchanges 1-2 and 3-4) now go to two different API endpoints.

Example(s)

In a publication management system such as JabRef, the remote service layer exposing a Solution-Internal API for Frontend Integration in a Web application might look like Figure 3. There are two endpoints that offer operations to query and manage publications, represented by the PublicationManagementCommands and the PublicationManagementQueries services. The PublicationManagementQueries service suffers from role and/or responsibility diffusion: The bulkImportFromBibtex operation is not a query method and should be moved to PublicationManagementCommands. Applying the refactoring, we can clean up this mismatch.

Example of Refactoring Move Operation

Figure 3: Example of Refactoring Move Operation

Hints and Pitfalls to Avoid

It is worth checking the following concerns:

  • Is the operation name still adequate in the new endpoint? If not, Rename Operation can be applied.
  • Is the technology mapping of the request and response messages still ok? For instance, the MIME types in RESTful HTTP as well as the platform-specific authentication and authorization settings might have to be changed because the target endpoint receives an additional (sub-)responsibility.
  • Are additional test cases and test data required in the API endpoint that the operation is moved to?
  • Has the deprecation been communicated to the API clients? If the operation is not deprecated, has the API client been informed about the change?

The effect of the new API design on the compatibility with the original one should be communicated. If needed, migration instructions and simple migration tools (such as scripts) may be provided.

The refactoring Move Operation reverts itself; it can be undone by applying it again (and move the operation in the reverse direction). In code refactoring, Move Method [Fowler 2018] accomplishes a similar goal.

Consider Split Operation if the operation has several responsibilities and only some of them should be moved. Rename Operation is related. Extract Operation is eligible when an operation should be moved but no suitable target endpoint exists.

The Design Practice Reference/Repository (DPR) [Zimmermann and Stocker 2021] has a stepwise service design activity, which works with Candidate Endpoint Lists and Refined Endpoint Lists.

The API evolution patterns [Zimmermann et al. 2022] (also available as “Interface Evolution Patterns: Balancing Compatibility and Extensibility across Service Life Cycles” [Lübke et al. 2019] cover versioning. For instance, the patterns Semantic Versioning and Two in Production might be applicable.

References

Fielding, Roy T., and Julian Reschke. 2014. “Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content.” Request for Comments. RFC 7231; RFC Editor. https://doi.org/10.17487/RFC7231.

Fowler, Martin. 2018. Refactoring: Improving the Design of Existing Code. 2nd ed. Addison-Wesley Signature Series (Fowler). Boston, MA: Addison-Wesley.

Lübke, Daniel, Olaf Zimmermann, Cesare Pautasso, Uwe Zdun, and Mirko Stocker. 2019. “Interface Evolution Patterns: Balancing Compatibility and Extensibility Across Service Life Cycles.” In Proceedings of the 24th European Conference on Pattern Languages of Programs. EuroPLop ’19. New York, NY, USA: Association for Computing Machinery. https://doi.org/10.1145/3361149.3361164.

Riel, Arthur J. 1996. Object-Oriented Design Heuristics. Reading, MA: Addison-Wesley.

Stocker, Mirko, and Olaf Zimmermann. 2021. “From Code Refactoring to API Refactoring: Agile Service Design and Evolution.” In Service-Oriented Computing, edited by Johanna Barzen, 174–93. Cham: Springer International Publishing. https://doi.org/10.1007/978-3-030-87568-8_11.

Zimmermann, Olaf, and Mirko Stocker. 2021. Design Practice Reference - Guides and Templates to Craft Quality Software in Style. LeanPub. https://leanpub.com/dpr.

Zimmermann, Olaf, Mirko Stocker, Daniel Lübke, Uwe Zdun, and Cesare Pautasso. 2022. Patterns for API Design: Simplifying Integration with Loosely Coupled Message Exchanges. Addison-Wesley Signature Series (Vernon). Addison-Wesley Professional.