Rename Endpoint

Updated: Published: EuroPLoP 2025

Context and Motivation

An API endpoint runs in production and is used by clients. Its name does not match its domain semantics well; this name is a build-time concept that might also be visible at runtime, for instance in the address of the endpoint on the protocol level.

As an API developer, I want to express the domain concepts exposed by an endpoint and the architectural role that the endpoint plays as accurately as possible in the published language that the API exposes, in the API contract in particular.

Stakeholder Concerns

#learnability (#readability in particular)
Using expressive and meaningful names makes navigating a code base easier, for instance when searching for endpoints while fixing bugs and adding features. The Move Operation refactoring has more explanations of such learnability and readability qualities.
#understandability (a.k.a. #explainability)
A good name expresses what an endpoint has to offer, which helps clients decide whether and how to use it. The Rename Operation refactoring provides additional explanations of the understandability and explainability qualities.

Initial Position Sketch

Let’s assume that an API endpoint type called OldCrypticName exists (note that this name is deliberately poor, to make the change and the need for it clear):

endpoint type OldCrypticName
exposes 
  operation operation1 
    expecting payload "SomeRequestMessage"

The refactoring targets a single endpoint that contains one or more operations (here: just one).

Design Smells

Cryptic, misleading or disrespectful name
The given endpoint name is not straightforward to understand and/or is not part of the domain terminology. It may raise wrong, unexpected or undesired associations or simply be outdated. It might even be unethical/irresponsible and offend or insult certain parts of the API community. For example, terms like “Blacklist/Whitelist” (alternative: “Blocklist/Allowlist”) or “Master/Slave” (alternative: “Primary/Secondary” or “Leader/Follower”) have been replaced in favor of more neutral and often also more accurate alternatives. Similarly, pattern names such as the “Strangler” have evolved to “Strangler Fig” to reduce negative connotations [Yoder and Merson 2022], though even these may still be problematic. When selecting names, consider ethical implications and inclusivity. See “Nonviolent Communication” by Rosenberg [2003] and papers on ethics in technology [Kapferer, Stocker, and Zimmermann 2024; Kapferer, Zimmermann, and Stocker 2024].
REST principle(s) violated
Abstract API endpoints correspond to resources identified by URIs in RESTful HTTP APIs. Their names should convey the meaning and role of the resources. For instance, using verbs as relative paths might be considered an antipattern; resources should be named with nouns that can be traced back to domain entities (note that these entities and their resource representations can be Processing Resources and/or data-oriented Information Holder Resources both in RESTful HTTP APIs and in APIs leveraging other integration styles and protocols).

Instructions

This refactoring is rather straightforward to apply.1 The main task is to find a suited name that balances the desired qualities and stakeholder concerns:

  1. Discuss alternative new names and decide for one. Have this decision reviewed and agreed upon.
  2. Apply code-level rename refactorings, for instance for the controller class realizing the endpoint. If the code is generated from a specification, update the specification and regenerate the code.
  3. For backward compatibility, consider implementing a redirect, either at the protocol level (for instance with an HTTP redirect [Fielding and Reschke 2014]) or at the code level by keeping the old method and calling the new one from it. If the name change is noticeable to API clients, mark the old endpoint name as deprecated in the API Description (for instance, its OpenAPI Specification, OAS) and announce that it will be removed in future versions of the API. Plan this cleanup work for later.
  4. Update security rules, tests and documentation as well as any address resolution services (gateways, portals, registries, repositories, service meshes). Check that the old name has been updated everywhere, e.g., OAS and examples; use a global search in editor or command line for that.
  5. Notify all known API clients of the change, ideally with detailed migration instructions.

Target Solution Sketch (Evolution Outline)

The endpoint type is called NewExpressiveNameFromDomainVocabulary now (for demonstration purposes; when applying the refactoring, an actual domain term would be used):

endpoint type NewExpressiveNameFromDomainVocabulary
exposes 
  operation operation1 
    expecting payload "SomeRequestMessage" 

Example(s)

In a publication management example, an application of the refactoring might change the following interface (notation: CML):

Aggregate APIEndpoint {
    Service JabRefDatabaseFacade {
        Set<@PublicationEntryDTO>
          lookupPublicationsFromAuthor(String writer);
        ...
    }
}

to this one:

Aggregate PublicationManagementEndpoint {
    Service PublicationManagementFacade {
        Set<@PublicationEntryDTO>
          lookupPublicationsFromAuthor(String writer);
        ...
    }
}

The specific name of an open source tool, JabRef, was replaced by a more general, domain-specific name. This reduces the prerequisite knowledge that stakeholders of the name (such as API client developers, but also API implementation maintainers and API product managers and testers) must have.

In this second example, we will look at a concrete implementation in Java Web framework Spring Boot. Endpoints are defined as classes, with Java methods implementing the API operations. Annotations, such as @GetMapping and @PathVariable are used to instruct Spring how to map the URL paths and query parameters to Java code. The CustomerInformationHolder class has two methods, one for retrieving and another one for updating a customer (note that the code is simplified, the full implementation can be found on GitHub).

@RestController
@RequestMapping("/getCustomers")
public class CustomerInformationHolder {
  ...
  @GetMapping(value = "/{ids}")
  public ResponseEntity getCustomer(@PathVariable String ids) {
    ...
  }
  @PutMapping(value = "/{id}")
  public ResponseEntity updateCustomer(
    ...

API clients can then retrieve the details of a customer by their id bunlo9vk5f:

curl  http://localhost:8110/getCustomers/bunlo9vk5f
{
  "customers" : [ {
    "customerId" : "bunlo9vk5f",
    "firstname" : "Ado",
    "lastname" : "Kinnett",
    "birthday" : "1975-06-13T23:00:00.000+00:00",
    "streetAddress" : "2 Autumn Leaf Lane",
    "postalCode" : "6500",
...

If we look closely at the path (getCustomers), we see that it violates the principle that no verbs should be used. Also, the endpoint offers operations to update customers, so the ‘get’ is also misleading and makes it difficult to understand. So let us rename it to simply customers by changing the request mapping:

@RestController
--- @RequestMapping("/getCustomers")
+++ @RequestMapping("/customers")

Unfortunately, this will break existing clients, which will now get an Error Report:

{
  "timestamp" : "2025-02-14T09:01:47.779+00:00",
  "status" : 404,
  "error" : "Not Found",
  "path" : "/getCustomers/bunlo9vk5f"
}

To inform clients about the new name, we can implement another controller class, which informs clients about the new location using HTTP status 301 (HttpStatus.MOVED_PERMANENTLY) and the Location header:

@RestController
@RequestMapping(path = "getCustomers")
public class OldCustomerInformationHolder {
  ...
  @GetMapping(value = "/{ids}")
  @ResponseBody
  public ResponseEntity getCustomer(@PathVariable String ids) {
    URI movedTo = linkTo(
      methodOn(CustomerInformationHolder.class).getCustomer(ids))
      .toUri();
    return ResponseEntity
      .status(HttpStatus.MOVED_PERMANENTLY)
      .location(movedTo)
      .build();
    }
}

Clients will then be redirected to the new location. We can see this by enabling the --verbose option. The --location instructs curl to follow redirects (greater-than > signs indicate requests, less-than < show responses).

curl --verbose --location http://localhost:8110/getCustomers/bunlo9vk5f
> GET /getCustomers/bunlo9vk5f HTTP/1.1
< HTTP/1.1 301 
< Location: http://localhost:8110/customers/bunlo9vk5f
> GET /customers/bunlo9vk5f HTTP/1.1
< HTTP/1.1 200 
{
  "customers" : [ {
    "customerId" : "bunlo9vk5f",
    "firstname" : "Ado",
    "lastname" : "Kinnett",
    "birthday" : "1975-06-13T23:00:00.000+00:00",
    "streetAddress" : "2 Autumn Leaf Lane",
    "postalCode" : "6500",
...

This approach is fully backwards compatible for clients that implemented the HTTP location header. To support clients that do not, we can also include the response in the redirect response:

    return ResponseEntity
      .status(HttpStatus.MOVED_PERMANENTLY)
      .location(movedTo)
      .body(customerInformationHolder.getCustomer(ids).getBody());

As a next step, not shown here, we will update security rules to cover the old and new endpoint, tests and documentation.

Hints and Pitfalls to Avoid

Here is some advice regarding naming:

  • Organization-, unit-, or project-wide naming conventions should be considered. It often makes sense to A/B test naming options with members of the target audience (here: API client developers).
  • Domain-Driven Design with its concepts of Ubiquitous Language and Published Language is well-suited to contribute naming suggestions. Singjai et al. [2022] recommend “that names and abstractions in the API follow the terms defined in the ubiquitous language which is formally specified by the domain model.”
  • Naming collisions with other endpoints should be avoided (even if they are technically possible and permitted, which depends on the chosen protocol technology).
  • URI templates {id} in HTTP resource APIs also require attention (and these names may appear in multiple places in API specifications and implementations).
  • Consistency of name across an API and/or multiple related APIs maintained by the same organization is an important meta-quality; it contributes to conceptual integrity [Brooks 1978].

More hints can be found in the Rename Operation and Rename Representation Element refactorings.

Rename Operation and Rename Representation Element also address readability, but have other parts of an API as targets.

The Rename refactoring, as described by Fowler [2018], can be applied to any named program element, not just endpoints. It is also often implemented in integrated development environments for various programming languages [Roberts, Brant, and Johnson 1997; Corbat, Felber, and Stocker 2007; Stocker 2010].

Refactoring.Guru calls for Clean Code and emphasizes that poor names make code difficult to grasp.

“The Art of Readable Code” [Dustin Boswell 2011] contains many helpful hints on naming program elements that also apply to APIs.

The book “Clean Code” [Martin 2008] by Robert C. Martin devotes an entire chapter to meaningful names, for instance recommending that we should use intention-revealing names, avoid disinformation, use pronounceable names. The advice given applies not only to code, but also to many other artifacts such as APIs and their parts.

References

Brooks, Frederick P. 1978. The Mythical Man-Month: Essays on Software-Engineering. 1st ed. USA: Addison-Wesley Longman Publishing Co., Inc.

Corbat, Thomas, Lukas Felber, and Mirko Stocker. 2007. “Refactoring Support for the Ruby Development Tools.” In Software Engineering (Workshops), edited by Wolf-Gideon Bleek, Henning Schwentner, and Heinz Züllighoven, P-106:313–15. LNI. GI. http://dblp.uni-trier.de/db/conf/se/se2007w.html#CorbatFS07.

Dustin Boswell, Trevor Foucher. 2011. The Art of Readable Code. O’Reilly Media, Inc.

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.

Kapferer, Stefan, Mirko Stocker, and Olaf Zimmermann. 2024. “[Towards responsible software engineering: combining value-based processes, agile practices, and green metering]{.nocase}.” In [2024 IEEE International Symposium on Technology and Society (ISTAS)]{.nocase}, 1–4. https://doi.org/10.1109/ISTAS61960.2024.10732097.

Kapferer, Stefan, Olaf Zimmermann, and Mirko Stocker. 2024. “[Value-Driven Analysis and Design: Applying Domain-Driven Practices in Ethical Software Engineering]{.nocase}.” In Proceedings of the 29th European Conference on Pattern Languages of Programs, People, and Practices. EuroPLoP ’24. New York, NY, USA: Association for Computing Machinery. https://doi.org/10.1145/3698322.3698332.

Martin, R. C. 2008. [Clean Code: A Handbook of Agile Software Craftsmanship]{.nocase}. Robert c. Martin Series. Pearson Education.

Roberts, Don, John Brant, and Ralph E. Johnson. 1997. “A Refactoring Tool for Smalltalk.” Theory Pract. Object Syst. 3: 253–63.

Rosenberg, M. B. 2003. Nonviolent Communication: A Language of Life. BusinessPro Collection. Independent Publishers Group.

Singjai, Apitchaka, Uwe Zdun, Olaf Zimmermann, and Cesare Pautasso. 2022. “[Patterns on Deriving APIs and their Endpoints from Domain Models]{.nocase}.” In Proceedings of the 26th European Conference on Pattern Languages of Programs. EuroPLoP ’21. New York, NY, USA: Association for Computing Machinery. https://doi.org/10.1145/3489449.3489976.

Stocker, Mirko. 2010. “Scala Refactoring.” Master’s thesis, http://eprints.ost.ch/id/eprint/286: HSR Hochschule für Technik Rapperswil.

Yoder, Joseph W., and Paulo Merson. 2022. “Strangler Patterns.” In Proceedings of the 27th Conference on Pattern Languages of Programs. PLoP ’20. USA: The Hillside Group.

  1. assuming that the used tools (including IDEs, API contract editors, and test tools) support consistent find-and-replace across files, and do so conveniently and reliably