A colleague of mine used to reference the following when talking about naming:
In my career so far, I have come to realize that there is some truth in this statement. Naming conventions have never been as important on the Lightning Platform as it is currently without a means to group or structure code files, using a directory structure, for example. Instead, all classes are effectively in one root folder called /classes.
Thus, it comes down to the use of naming conventions to help clarify purpose (for developers, both new and old, working on the code base) and to which layer in your architecture a class belongs. Naming does not, however, stop at the class name level; the enums, methods, and even parameter names all matter.
The following points break down some specific guidelines for the Service layer, though some are also applicable throughout your application code:
- Avoid acronyms: In general, try to avoid using acronyms (as far as possible); while these might be meaningful to those experienced in working on the application, newcomers will find it harder to navigate the code as they learn the application functionality and code base. This applies more so if you're using your Service layer as an API. Though it can be tempting from a typing perspective, a good editor with autocompletion should resolve this concern pretty well. Widely used and understood acronyms such as ID are reasonable.
- Class names: Ending your class name with the Service suffix allows developers to filter easily in order to find these critical classes in your application code base. The actual name of the service can be pretty much anything you like, typically a major module or a significant object in your application. Make sure, however, that it is something from your application's vocabulary. If you've structured your application design well, your service class names should roughly fall into the groupings of your application's modules; that is, the naming of your Service layer should be a by-product of your application's architecture and not a thing you think up when creating the class:
- Some bad examples are UtilService, RaceHelper, BatchApexService, and CalcRacePointsService. These examples either use acronyms that are platform feature bias or potentially to contextualized. Classes with the name Helper in them are often an indication that there is a lack of true understanding of where the code should be located; watch out for such classes.
- Some good examples are CommonService, RaceService, and SeasonService. These examples clearly outline some major aspects of the application and are general enough to permit future encapsulation of related operations as the application grows.
- Method names: The public or global method names are essentially the business operations exposed by the service. These should also ideally relate or use terms expressed in your application's end user vocabulary, giving the same thought to these as you would give to a label or button for the end user, for example. Avoid naming them in a way that ties them to their caller; remember that the Service layer doesn't know or care about the caller type:
- Some bad examples are RaceService.recalcPointsOnSave, SeasonService.handleScheduler, and SeasonService.issueWarnings. These examples are biased either toward the initial caller use case or toward the calling context; nor does the handleScheduler method name really express enough about what the method is actually going to perform.
- Some good examples are RaceService.awardChampionshipPoints, SeasonService.issueNewsLetter, and DriverService.issueWarnings. These examples are named according to what they do, correctly located, and unbiased to the caller.
- Parameter names and types: As with method and class names, keep them focused on the data they represent, and ideally use consistent terms. Keep in mind that the type of your parameter can also form a part of the meaning of the parameter, and may help in some cases with the implementation of the Service method. For example, if the parameter is intended to receive a list of IDs, consider using Set instead of List, as typically, duplicate IDs in the list are unwanted. For the Map parameters, I always try to use the somethingABySomethingB convention in my naming so it's at least clear what the map is keyed by. In general, I actually try to apply these conventions to all variables, regardless of them being method parameters:
- Some bad examples are List<String>driverList and Map<String, DriverPerformance>mapOfPerformance. These examples are either not using the correct data type and/or are using unclear data types as to the list or map contents; there is also some naming redundancy.
- Some good examples are Set<Id>driverIds and Map<String,DrivePerformance>drivePerformanceByName. These examples use the correct types and help in documenting how to use the Map parameter correctly; the reader now knows that the String key is a name. Another naming approach is somethingsToName, for example. Also, the Map parameter name no longer refers to the fact that it is a map because the type of parameter communicates this well enough.
- Inner class names: While there is no formal structure to Apex classes in the form of a typical directory facility (or package structure, in Java terms), Apex does support the concept of inner classes to one level. These can sometimes be used to define classes that represent parameter data that is only relevant to the service methods. Because inner classes are always qualified by the name of the parent class, you do not need to repeat it:
- Some bad examples are SeasonService.SeasonSummary and DriverService.DriverRaceData. These examples repeat the parent class name.
- Some good examples are SeasonService.Summary and DriverService.RaceDetails. These examples are shorter as they are qualified by the outer class.
These guidelines should not only help to ensure whether your Service layer remains more neutral to its callers and thus more consumable now and in the future, but also follow some best practices around the platform. Finally, as we will discuss in Chapter 10, Providing Integration and Extensibility, following these guidelines leaves things in good shape to expose as an actual API, if desired.