Rename Operation

Updated:

 Note: This is a preview release and subject to change. Feedback welcome! Contact Information and Background (PDF)

Context and Motivation

An API endpoint, for instance an HTTP resource, has been developed, tested, and deployed. The name of one of the operations of the endpoint does not represent its semantics well; there is a mismatch between operation name and performed operation. It is difficult to comprehend.

As an API provider, I want to express the responsibilities of an operation in its name so that client developers, API developers, and non-technical stakeholders (end users, product managers) understand the API — and each other in conversations about the API.

Stakeholder Concerns (including Quality Attributes and Design Forces)

#maintainability
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.
#understandability (including #explainability and #learnability)
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.

Initial Position Sketch

The initial design before the refactotring, specified in the Microservice Domain-Specific Language (MDSL) notation, is as follows:

endpoint type GenericEndpointOfUnknownRole
exposes 
  operation hardToGraspName 
    expecting payload "SomeRequestMessage" 

It is unlikely that GenericEndpointOfUnknownRole, hardToGraspName, and SomeRequestMessage are part of the vocabulary of the application domain (such as finance, e-commerce, or distributed control system) that the API deals with.

This refactoring deals with a single operation.

Design Smells

Curse of knowledge
The operation name is easy to comprehend — but only for the developers of the API implementation on the provider side. On the contrary, client developers miss required context information.1

 

Role and/or responsibility diffusion
The operation does something, but the effects of the operation execution are not clear. For instance, it is not specified whether it reads and/or writes provider-side data and application state. The domain model abstractions/concepts that it works with remain fuzzy. Precision might be harmed and ambiguities introduced.
Sloppy or ill-motivated naming conventions
Knowing something that nobody else knows might be seen as a pragmatic approach to achieving job security; obscuring operation names might be part of such a strategy. However, the attitude driving such naming decisions can be considered unprofessional (or even unethical); API design and documentation should be seen as a service provided to the client community (and other stakeholders). Another example of good intentions gone wrong is trying to be funny when naming program(ming) artifacts; endpoint and operation names are not the most suited places for humor or irony because they distract from the facts.

Instructions (Steps)

  1. Rename the operation in the abstract API contract and any technical API Description (for instance, its OpenAPI specification).
  2. Refactor on code level; for instance, apply Rename Element/Method in a Java IDE. 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).
  3. Adjust the test cases and run them (to achieve/stay with a “green build”).
  4. Update all supporting documentation such as API reference and guides, examples, and tutorials. Check and update security rules if necessary.
  5. Inform all known API clients about the change, ideally with detailed instructions how to migrate. Code snippets that can be copy-pasted easily will be appreciated by the client maintainers.

Target Solution Sketch (Evolution Outline)

The following abstract, domain-independent MDSL sketch outlines how to improve the naming (DomainNounAndRDDRoleStereotype, verbFromDomainLanguage, DomainLevelTransferObject1) on an abstract, conceptual level:

endpoint type DomainNounAndRDDRoleStereotype
exposes 
  operation verbFromDomainLanguage 
    expecting payload "DomainLevelTransferObject1" 
    delivering payload "DomainLevelTransferObject2"

Note that two similar refactorings were applied as well, Rename Endpoint and Rename Representation Element.

Example

In a publication management system, the remote service layer of a Web application might expose a Community API for Backend Integration, two foundation patterns in the Microservice API Patterns language. It might look like as follows:2

Service JabrefAPI {
    @PaperId add(@PublicationEntryDTO newEntry);

Renaming the rather generic names yields this API design:

Service PublicationManagementFacade {
    // a state creation/state transition operation (DTO = Data Transfer Object)
    @PaperId addPublicationToArchive(@PublicationEntryDTO publicationInformation);

Endpoint name, operation name, and parameter name are now free of technical jargon (except for the pattern names Facade and DTO, with the acronym being explained in the comment).

Hints and Pitfalls to Avoid

Consider consulting the following artifacts (before and after the refactoring):

  • Naming conventions on organization, unit, project level3
  • Glossaries and the ubiquitous language established by a domain model (for instance, some community members advise that BankAccountAggregate is a bad choice of name while others recommend this domain-pattern pairing convention)
  • Coding guidelines, both general and language-specific

Avoid special characters such as underscore _ in operation names because middleware and tools might not handle them correctly. The same holds for natural language-specific characters such as German “Umlaute”.4

Be careful with metaphors when naming things. Some might not be understood by parts of the target audience, others might cause unwanted reactions.5 Apply the ones that you do choose consistently and do not mix them wildly.6 Ask yourself: Would the current name also work in another domain? In how many projects/APIs can this name be found?

Note that this refactoring is not straightforward to apply in HTTP resource APIs due to the REST principle “uniform interface”: One cannot rename PUT to something that has domain semantics.7 Rename Endpoint might be more suited in such cases because it deals with URIs.

This refactoring reverts itself. In code refactoring, there is Rename Method [Fowler 2018].

Move Operation is another operation-level refactoring.

The hints in “The Art of Readable Code” [Dustin Boswell 2011] also apply to API naming.

References

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

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

  1. The term “curse of knowledge” originates from technical writing (see for instance hint 5 in “Technical Writing Tips and Tricks” and the video lecture by Steven Pinker referenced in that post). 

  2. The notation in this example is CML, the tactic domain-driven design language supported by Context Mapper

  3. If you cannot locate such conventions, use this opportunity to establish them. Rename consistently and document the rationale for your naming decisions. For instance, start operation names with verbs and then let a noun from the domain vocabulary follow. 

  4. As a test, do ä, ö, ü render properly when you read this? 

  5. Baseball fans, for example, know what a “curveball” and a “pitcher” are, but this sport is not as global as others. 

  6. What happens if an elephant enters a room as a visitor or crosses a bridge? Should the flyweight pattern be applied then? Or does it make sense to build a factory in this case? What will observers think about this strategy? 

  7. This is inherent and one reason the Web works: You do not want to recompile your browser when there is a breaking change in a website.