27 Tips for making your code read like beautifully written prose
Tags: cleancode, programming, beginners
Published: 2023-02-10 12:46:11

Why is it important how you name software entities like functions, variables and classes? The reason is to make the code understandable for other developers and your future self. How many times have you read some code written by yourself a couple of years ago and thought what the heck is this code doing? We should remember that code is more often read than written, so it is crucial to ensure that code reads well. Don’t try to make your code too concise using too short names. Use the shortest most descriptive names. When code is written using great names, it makes the code read like beautifully written prose. Back in the days when I was a junior programmer, I did not care much about names in code. But nowadays I care about names in code a lot. I am always asking myself, is this name good enough or how could I improve some names. When you use great names in code, you don’t need to write so many comments. In the next sections, I am going to present some useful naming conventions for functions, variables, interfaces and classes. The naming conventions described below are not something I just quickly came up with but they are a product of practicing programming for almost 30 years. You can also find the below information in my book 📕[Clean Code Principles And Patterns: A Software Practitioner’s Handbook](https://www.amazon.com/dp/B0BSDJKYQJ) 📕.

## Naming Functions

> Functions should do one thing, and the name of a function should describe what the function does. The function name should contain a verb that indicates what the function does. The function name should usually start with a verb, but exceptions exist. If a function returns a value, and if possible, try to name the function so that the function name describes what it returns.

### Tip #1: Name the function on correct abstraction level

Let’s have an example with the following code:

```java
void deletePageAndAllReferences(Page page) {
  deletePage(page);
  registry.deleteReference(page.name);
  configKeys.deleteKey(page.name.makeKey());
}
```

In the above example, the function seems to do two things: deleting a page and removing all the references to that page. But if we look at the code inside the function, we can realize that it is doing a third thing also: deleting a page key from configuration keys. So should the function be named `deletePageAndAllReferencesAndConfigKey`? It does not sound reasonable. The problem with the function name is that it is at the same level of abstraction as the function statements. The function name should be at a higher level of abstraction than the statements inside the function.

How should we then name the function? We could name the function just `delete`. This would tell the function caller that a page will be deleted. The caller does not need to know all the actions related to deleting a page. The caller just wants a page to be deleted. The function implementation should fulfill that request and do the needed housekeeping actions, like removing all the references to the page being deleted and so on.

So, if you spot a function name containing and word, your function is either doing multiple things or is not named at the correct level of abstraction. You should have your functions doing a single thing only.

### Tip #2: Don’t repeat the interface/class name in the function name

Below is an example of an interface containing two methods named with simple verbs only. It is not necessary to name the methods as `startThread` and `stopThread` because the methods are already part of the Thread interface, and it is self-evident what the start method starts and what the end method ends.

```java
public interface Thread {
  void start();
  void stop();
}
```

### Tip #3: Don’t lie in the function name

Many languages offer streams that can be written to, like the standard output stream. Streams are usually buffered, and the actual writing to the stream does not happen immediately. For example, the below statement does not necessarily write to the standard output stream immediately. It buffers the text to be written later when the buffer is flushed to the stream. This can happen when the buffer is full, when some time has elapsed since the last flush or when the stream is closed.

```java
stdOutStream.write(...);
```

The above statement is misleading and could be corrected by renaming the function to describe what it actually does:

```java
stdOutStream.writeOnFlush(...);
```

Let’s have another example:

```java
grpcChannel.shutdown().awaitTermination(30, TimeUnit.SECONDS);
```

In the above code, the `shutdown` method does not shut the channel down. It actually only requests a shutdown. We should also use a single term _shutdown_ instead of using two terms for the same thing: _shutdown_ and _termination_. Below is the above code refactored:

```java
grpcChannel.requestShutdown().awaitShutdown(30, TimeUnit.SECONDS);
```

### Tip #4: Name a throwing function with a try prefix

It is easier not to forget handling thrown errors when a throwing function is named so that it clearly indicates it can throw:

```java
public interface ConfigParser {
  // Nothing in the function signature tells it can throw
  Configuration parseConfig(final String configJson);
}

public interface ConfigParser {
  // Try-prefix tells that the function can throw
  Configuration tryParseConfig(final String configJson);
}
```

### Tip #5: Don’t repeat the function target in the function name

The below example is repeating the function target in the function name:

```java
public interface ConfigParser {
  // Not optimal naming
  Configuration tryParseConfig(final String configJson);
}
```

We can remove the function target `Config` from the function name:

```java
public interface ConfigParser {
  // Better naming
  Configuration tryParse(final String configJson);
}
```

When we use the latter function name somewhere in code, it makes the code read better:

```java
// Word "config" repeated, not optimal
final var config = configParser.tryParseConfig(configJson);

// Shorter and reads better
final var config = configParser.tryParse(configJson);
```

### Tip #6: Use a preposition in the function name only when necessary

You don’t need to add a preposition to a function name if the preposition can be assumed (i.e., the preposition is implicit). In many cases, only one preposition can be assumed. If you have a function named `wait`, the preposition `for` can be assumed, and if you have a function named `subscribe`, the preposition `to` can be assumed. You don't need to use function names `waitFor` and `subscribeTo`.

Suppose a function is named `laugh(person: Person)`. Now we have to add a preposition because none can be assumed. We should name the function either `laughWith(person: Person)` or `laughAt(person: Person)`.

### Tip #7: Name method pairs logically

Methods in a class can come in pairs. A typical example is a pair of getter and setter methods. When you define a method pair in a class, name the methods logically. The methods in a method pair often do two opposite things, like getting or setting a value. If you are unsure how to name one of the methods, try to find an antonym for a word. For example, if you have a method whose name starts with “create” and are unsure how to name the method for the opposite action, try a Google search: “create antonym”.

Examples of method pairs:

- add/remove
- insert/delete
- start/stop

### Tip #8: Name predicate functions to read as boolean statements

> The naming of boolean functions (predicates) should be such that when reading the function call statement, it reads as a boolean statement that can be true or false.

The naming of boolean functions should be such that when reading the function call statement, it makes a statement that can be true or false. Below are some examples:

```java
public class String {
  public boolean isEmpty() { 
    //... 
  }
  
  public boolean startsWith(final String anotherString) { 
    //...
  }
}

final String line = fileReader.readLine();

// Here we have a statement: line is empty? True or false?
if (line.isEmpty()) {
  // ...  
}

// Here we have statement: line starts with a space [character]?
// true or false?
if (line.startsWith(" ")) { 
    // ...
}

public class Thread {
  public boolean shouldTerminate() {
    // ...
  }

  public boolean isPaused() {
    // ...
  }

  public boolean canResumeExecution() {
    // ...
  }

  public void run() {
    // ...

    // Here we have statement: if [this] should terminate?
    // True or false?
    if (shouldTerminate()) { 
      return;
    }

    // Here we have statement: if [this] is paused and
    // [this] can resume execution? True or false? 
    if (isPaused() && canResumeExecution()) { 
      // ...
    }
    
    // ...
  }
}
```

A boolean returning function is correctly named when you call the function in code and can read that function call statement in plain English. Below is an example of incorrect and correct naming:

```java
public class Thread {
  public boolean stopped() { // Incorrect naming
    // ...
  } 
  
  public boolean isStopped() { // Correct naming
    // ...
  }
}

if (thread.stopped()) { 
  // Here we have: if thread stopped
  // This is not a statement with a true or false answer
  // It is the second conditional form, 
  // asking what would happen if the thread stopped.
  // ...
}

if (thread.isStopped()) { 
  // Here we have statement: if thread is stopped
  // True or false?
  // ...   
}
```

### Tip #9: Sometimes a function can be named with an implicit verb

Factory method names usually start with the verb _create_. Factory methods can be named so that the _create_ verb is implicit, for example:

```java
Optional.of(final T value)
Optional.empty() // Not optimal, 'empty' can be confused as a verb
Either.withLeft(final L value)
Either.withRight(final R value)
SalesItem.from(final SalesItemArg salesItemArg)
```

Similarly, conversion methods can be named so that the _convert_ verb is implicit. Conversion methods without a verb usually start with the to preposition, for example:

```java
value.toString();
object.toJson();
```

### Tip #10: Naming a getter function without the respective setter function

Property getter functions are usually named `get + <property-name>`. It is also possible to name a property getter that does not have a respective setter using just the property name. This is acceptable in cases where the property name cannot be confused with a verb. Below is an example of property getters:

```java
final var list = new MyList();

list.size(); // OK
list.length(); // OK
list.empty(); // NOT OK, empty can be a verb. 
list.isEmpty(); // OK
```

### Tip #11: Naming lifecycle functions

Lifecycle methods are called on certain occasions only. Lifecycle method names should answer the question: When or “on what occasion” will this method be called? Examples of good names for lifecycle methods are: `onInit`, `onError`, `onSuccess`, `afterMount`, `beforeUnmount`. In React, there are lifecycle methods in class components called `componentDidMount`, `componentDidUpdate` and `componentWillUnmount`. There is no reason to repeat the class name (`component`) in the lifecycle method names. Better names would be: `afterMount`, `afterUpdate`, and `beforeUnmount`.

## Naming Variables

> A good variable name should describe the variable’s purpose and its type.

Naming variables with names that also convey information about the variable’s type is crucial in untyped languages and beneficial in typed languages, too, because modern typed languages use automatic type deduction, and you won’t always see the actual type of a variable. But when the variable name tells its type, it does not matter if the type name is not visible.

### Tip #12: Naming integer variables

Some variables are intrinsically integers, like `age` or `year`. Everybody understands immediately that the type of an age or year variable is a number and, to be more specific, an integer. So you don’t have to add anything to the variable’s name to indicate its type. It already tells you its type.

One of the most used categories of integer variables is a count or number of something. You see those kinds of variables in every piece of code. I recommend using the following convention for naming those variables: `numberOf<something>` or alternatively `<something>Count`. For example, `numberOfFailures` or `failureCount`. You should not use a variable name `failures` to designate a failure count. The problem with that variable name is it does not clearly specify the type of the variable and thus can cause some confusion. This is because a variable named `failures` can be misunderstood as a collection variable (e.g., a list of failures).

If the unit of a variable is not self-evident, always add information about the unit to the end of the variable name. For example, instead of naming a variable `tooltipShowDelay`, you should name it `tooltipShowDelayInMillis` or `tooltipShowDelayInMillisecs`. If you have a variable whose unit is self-evident, unit information is not needed. So, there is no need to name an `age` variable as `ageInYears`. But if you are measuring age in months, you must name the respective variable as `ageInMonths` so that people don’t assume that age is measured in years.

### Tip #13: Naming floating-point number variables

If you need to store an amount of something that is not an integer, use a variable named `<something>Amount`, like `rainfallAmount`. When you see “amount of something” in code, you can automatically think it is a floating-point number. If you need to use a number in arithmetic, depending on the application, you might want to use either floating-point or integer arithmetic. In the case of money, you should use integer arithmetic to avoid rounding errors. Instead of a floating-point `moneyAmount` variable, you should have an integer variable, like `moneyInCents`, for example.

If the unit of a variable is not self-evident, add information about the unit to the end of the variable name, like `rainfallAmountInMillimeters`, `widthInInches`, `angleInDegrees` (values 0–360), `failurePercent` (values 0–100), or `failureRatio` (values 0–1).

### Tip #14: Naming boolean variables

Boolean variables can have only one of two values: true or false. The name of a boolean variable should form a statement where the answer is true or false, or yes or no. Typical boolean variable naming patterns are: `is<something>`, `has<something>`, `did<something>`, `should<something>`, `can<something>`, or `will<something>`. Some examples of variable names following the above patterns are `isDisabled`, `hasErrors`, `didUpdate`, `shouldUpdate`, and `willUpdate`.

The verb in the boolean variable name does not have to be at the beginning. It can and should be in the middle if it makes the code read better. Boolean variables are often used in if-statements where changing the word order in the variable name can make the code read better.

Below is a code snippet where we have a boolean variable named `isPoolFull`:

```cpp
if (const bool isPoolFull = m_pooledMessages.size() >= 200U;
      isPoolFull)
{
  // ...
```

We can change the variable name to `poolIsFull` to make the if-statement read more fluently. In the below example, the if-statements reads `if poolIsFull` instead of `if isPoolFull`:

```cpp
if (const bool poolIsFull = m_pooledMessages.size() >= 200U;
      poolIsFull)
{
  // ...
```

Don’t use boolean variable names in the form of `<passive-verb>Something`, like `insertedField`, because this can confuse the reader. It is unclear if the variable name is a noun that names an object or a boolean statement. Instead, use either `didInsertField` or `fieldWasInserted`.

Below is a Go language example of the incorrect naming of a variable used to store a function return value. Someone might think that `tablesDropped` means a list of dropped table names. So, the name of the variable is obscure and should be changed.

```golang
tablesDropped := dropRedundantTables(prefix,
                                     vmsdata,
                                     cfg.HiveDatabase,
                                     hiveClient,
                                     logger)
if tablesDropped {
  // ...
}
```

Below is the above example modified so that the variable name is changed to indicate a boolean statement:

```golang
tablesWereDropped := dropRedundantTables(prefix,
                                         vmsdata,
                                         cfg.HiveDatabase,
                                         hiveClient,
                                         logger)
if tablesWereDropped {
  // ...
}
```

### Tip #15: Naming strings containing a number

When you need to store numerical data in a string variable, tell the code reader clearly that it is a question about a number in string format, and use a variable name in the following format: `<someValue>String` or `<someValue>AsString`. It makes the code more prominent and easier to understand. For example:

```js
const year = parseInt(yearAsString, 10);
```

### Tip #16: Naming collection (array, list, and set) variables

When naming arrays, lists, and sets, you should use the plural form of a noun, like `customers`, `errors`, or `tasks`. In most cases, this is enough because you don’t necessarily need to know the underlying collection implementation. Using this naming convention allows you to change the type of a collection variable without needing to change the variable name. If you are iterating over a collection, it does not matter if it is an array, list, or set. Thus, it does not bring any benefit if you add the collection type name to the variable name, for example, `customerList` or `taskSet`. Those names are just longer. You might want to specify the collection type in some special cases only. Then, you can use the following kind of variable names: `queueOfTasks`, `stackOfCards`, or `orderedSetOfTimestamps`.

Below is an example in Go language, where the function is named correctly to return a collection (of categories), but the variable receiving the return value is not named according to the collection variable naming convention:

```golang
vmsdata, error = vmsClient.GetCategories(vmsUrl, logger)
```

Correct naming would be:

```
vmsCategories, error = vmsClient.GetCategories(vmsUrl, logger)
```

### Tip #17: Naming map variables

Maps are accessed by requesting a _value_ for a certain _key_. This is why I recommend naming maps using the pattern `keyToValueMap`. Let’s say we have a map containing order counts for customer ids. This map should be named `customerIdToOrderCountMap`. Or if we have a list of suppliers for product names, the map variable should be named `productNameToSuppliersMap`. Below is an example of accessing maps in Java:

```java
final var orderCount = customerIdToOrderCountMap.get(customerId);
final var suppliers = productNameToSuppliersMap.get(productName);
```

Below is an example of iterating over a map in JavaScript:

```js
Object.entries(customerIdToOrderCountMap)
      .map(([customerId, orderCount]) => ...);
```

### Tip #18: Naming pair and tuple variables

A variable containing a pair should be named using the pattern `variable1AndVariable2`. For example: `heightAndWidth`. And for tuples, the recommended naming pattern is `variable1Variable2...andVariableN`. For instance: `heightWidthAndDepth`.

Below is an example of using pairs and tuples in JavaScript:

```js
const heightAndWidth = [100, 200];
const heightWidthAndDepth = [100, 200, 40];
const [height, , depth] = heightWidthAndDepth;
```

### Tip #19: Naming object variables

Object variables refer to an instance of a class. Class names are nouns written with the first letter capitalized, like `Person`, `Account`, or `Task`. Object variable names should contain the respective class name: a `person` object of the `Person` class, an `account` object of the `Account` class, etc. You can freely decorate the object’s name, for example, with an adjective: `completedTask`. It is important to include the class name or at least some significant part of it at the end of the variable name. Then looking at the end of the variable name tells what kind of object is in question.

### Tip #20: Naming function variables (callbacks)

Callback functions are functions supplied to other functions to be called at some point. If a callback function returns a value, it can be named according to the returned value, but it should still contain a verb. If the callback function does not return a value, you should name the callback function like any other function: Indicating what the function does. Below are some examples of naming callbacks:

```js
const doubledValue = value => 2 * value;
const squaredValue = value => value * value;
const valueIsEven = nbr => (nbr % 2) === 0;
const values = [1, 2, 3, 4, 5]
const doubledValues = values.map(doubledValue);
const squaredValues = values.map(squaredValue);
const evenValues = values.filter(valueIsEven);

const strings = [" string1", "string2 "];
const trimmedString = str => str.trim();
const trimmedStrings = strings.map(trimmedString);

const sumOfValues = (sum, value) => sum + value;
values.reduce(sumOfValues, 0);
```

### Tip #21: Naming class properties

Class properties (i.e., class attributes, fields, or member variables) should be named so that the class name is not repeated in the property names. Below is an example of incorrect naming:

```java
public class Order {
  private long orderId;
  private OrderState orderState;
}
```

Below is the above code with corrected names:

```java
public class Order {
  private long id;
  private OrderState state;
}
```

### Tip #22: Use Short, Common Names

When picking a name for something, use the most common shortest name. If you have a function named `relinquishSomething`, consider a shorter and more common name for the function. You could rename the function to `releaseSomething`, for example. The word “release” is shorter and more common than the “relinquish” word. Use Google to search for word synonyms, e.g., “relinquish synonym”, to find the shortest and most common similar term.

### Tip #23: Pick One Name And Use It Consistently

Let’s assume that you are building a data exporter microservice and you are currently using the following terms in the code: `message`, `report`, `record` and `data`. Instead of using four different terms to describe the same thing, you should pick just one term, like `message`, for example, and use it consistently throughout the microservice code.

### Tip #24: Avoid Obscure Abbreviations

Many abbreviations are commonly used, like `str` for a string, `num/nbr` for a number, `prop` for a property, or `val` for a value. Most programmers use these, and I use them to make long names shorter. If a variable name is short, the full name should be used instead, like `numberOfItems` instead of `nbrOfItems`. Use abbreviations in cases where the variable name otherwise becomes too long. What I especially try to avoid is using uncommon abbreviations. For example, I would never abbreviate amount to `amnt` or discount to `dscnt` because I haven’t seen those abbreviations used much in real life.

## Naming Interfaces, Classes and Subclasses

### Tip #25: Naming interfaces

> An interface represents a capability, abstract thing or abstract actor.

When an interface represents an abstract thing, name it according to that abstract thing. The name of an interface representing an abstract thing should be a noun, never a verb or adjective. For example, if you have a drawing application with various geometrical objects, name the geometrical object interface `Shape`. It is a simple abstract noun. The term `Shape` is abstract because we cannot create an instance of `Shape` because we don’t know what kind of shape it is. Names should always be the shortest, most descriptive ones. There is no reason to name the geometrical object interface as `GeometricalObject` or `GeometricalShape`, if we can simply use `Shape`. Other good examples of abstract names are `Chart` and `Widget`, for example.

When an interface represents an abstract actor, name it according to that abstract actor. The name of an interface representing an abstract actor should be a noun, never a verb or adjective. The name of an actor interface should be derived from the functionality it provides. For example, if there is a `parseConfig` method in the interface, the interface should be named `ConfigParser`, and if an interface has a `validateObject` method, the interface should be named `ObjectValidator`. Don’t use mismatching name combinations like a `ConfigReader` interface with a `parseConfig` method or an `ObjectValidator` interface with a `validateData` method. Mismatching name combinations confuse code readers.

When an interface represents a capability, name it according to that capability. Capability is something that objects of a concrete class implementing the interface are capable of doing. For example, objects of a class could be sortable, iterable, comparable, equitable, etc. Name the respective interfaces according to the capability: `Sortable`, `Iterable`, `Comparable`, and `Equitable`. The name of an interface representing a capability usually ends with `able` or `ing`.

Don’t name interfaces starting with an `I`. Instead, use an `Impl` postfix for the class name to distinguish the class from the implemented interface when needed. For example, name the class implementing the `ConfigParser` interface as `ConfigParserImpl`. Most of the time, you should be programming against interfaces (remember dependency inversion principle from SOLID principles), and if every interface has its name prefixed with an `I`, unnecessary noise is added to the code. Use the `I` prefix only if it is an established programming language convention.

### Tip #26: Naming Classes

> A class represents either an abstract or concrete thing or actor.

Some examples of class names representing a concrete thing are: `Account`, `Order`, `RectangleShape`, `CircleShape`, `TextWidget`, and `ColumnChart`.

An abstract class is a class you cannot create an instance of. When you have an abstract class, name it with an `Abstract` prefix, for example `AbstractChart` or `AbstractXAxisChart`.

If a class implements an interface, you should name the class so that the class name refines the implemented interface name. Suppose we have an `InputMessage` interface and we would like to introduce concrete input message types. We should name those concrete types using the following pattern: `<class-purpose> + <interface-name>`. For example, we could create a `Kafka + InputMessage = KafkaInputMessage` class that represents an input message consumed from a Kafka data source. Or for the `Shape` interface, we can introduce various concrete shape classes, like `CircleShape`, `RectangleShape`, etc. When using this naming convention, you can always see the implemented interface when looking at the end of the class name.

If you are using a design pattern, don’t add the design pattern name to the class name if it does not bring any real benefit. For example, suppose we have a `DataStore` interface, a `DataStoreImpl` class, and a class that is wrapping a `DataStore `instance and uses the proxy pattern to add caching functionality to the wrapped data store. We should not name the caching class `CachingProxyDataStore` or `CachingDataStoreProxy`. The word proxy does not add significant value, so the class can be named just `CachingDataStore`. The name `CachingDataStore` tells everything we need to know: a data store with caching functionality. Similarly, if we had a `SqlStatementExecutor` class in a 3rd party library and we would like to add logging functionality to the class’s `executeSqlStatement` method, we should use the decorator pattern. We should not name the decorated class `DecoratedLoggingSqlStatementExecutor` but just `LoggingSqlStatementExecutor`.

### Tip #27: Naming Subclasses

The subclass name should refine the base class name. The following naming pattern should be used: `<subclass-purpose> + <base-class-name>`. Suppose we have the `KafkaInputMessage` class and we would like to introduce new input message types for different input message data formats, like Avro and JSON. We should name those new classes in the following way: `Avro + KafkaInputMessage = AvroKafkaInputMessage` and `Json + KafkaInputMessage = JsonKafkaInputMessage`. When this naming convention is used for a subclass, the whole inheritance hierarchy can be seen in the subclass name, for example: `Avro + Kafka + InputMessage = AvroKafkaInputMessage` reveals the following inheritance hierarchy:

```java
public interface InputMessage {
  // ...
}

public class KafkaInputMessage implements InputMessage {
  // ...
}
public class AvroKafkaInputMessage extends KafkaInputMessage {
  // ...
}
```

The above-presented naming convention does not always work optimally, especially when the inheritance hierarchy is deep. Sometimes you can drop intermediate subclass names. For example, we should probably use the name `ColumnChart` instead of `ColumnXAxisChart` because everyone knows that a column chart is an x-axis chart.

```java
public interface Chart {
  // ...
}

public abstract class AbstractChart implements Chart {
  // ...
}

public abstract class AbstractXAxisChart extends AbstractChart {
  // ...
}

public class ColumnChart extends AbstractXAxisChart {
  // ...
}

public class LineChart extends AbstractXAxisChart {
  // ...
}
```

Let’s have one more example. Suppose we have the following class hierarchy:

```java
public interface Car {
  void drive(
    Location start,
    Location destination
 );
}

public class CombustionEngineCar implements Car {
  public void drive(
    final Location start,
    final Location destination
  ) {
    // ...
  }
}

public class ElectricEngineCar implements Car {
  public void drive(
    final Location start,
    final Location destination
  ) {
    // ...
  }
}

public class ManualTransmissionCombustionEngineCar 
         extends CombustionEngineCar {
  public void drive(
    final Location start,
    final Location destination
  ) {
    // ...
  }
}

public class AutomaticTransmissionCombustionEngineCar
         extends CombustionEngineCar {
  public void drive(
    final Location start,
    final Location destination
  ) {
    // ...
  }
}
```

If we wanted to add more car properties like two or four-wheel drive, the above class hierarchy would grow deeper and the class names would become ridiculously long, like `FourWheelDriveAutomaticTransmissionCombustionEngineCar`. Fortunately, the above example has the wrong object-oriented design. We are using class inheritance in a situation where we should use class composition instead because an engine and transmission are properties of a car, i.e., there is a _has-a_ relationship between a car and an engine and transmission. The above code should be corrected to use composition instead of inheritance. In the below example, we have the correct object-oriented design and reasonable class names.

```java
public interface Drivable {
  void drive(
    Location start, 
    Location destination
  );
}

public interface Engine {
  // Methods like start, stop ...
}

public class CombustionEngine implements Engine {
  // Methods like start, stop ...
}

public class ElectricEngine implements Engine {
  // Methods like start, stop ...
}

public interface Transmission {
  // Methods like changeGear ...
}

public class AutomaticTransmission implements Transmission {
  // Methods like changeGear ...
}

public class ManualTransmission implements Transmission {
  // Methods like changeGear ...
}

public class Car implements Drivable {
  private final Engine engine;
  private final Transmission transmission;
  
  public Car(
    final Engine engine,
    final Transmission transmission
  ) {
    this.engine = engine;
    this.transmission = transmission;
  }
    
  public void drive(
    final Location start,
    final Location destination
  ) {
    // To implement functionality, delegate to 
    // component classes, for example:
    
    // engine.start();
    // transmission.shiftGear(...);
    // ...
    // engine.stop();
  }
}
```

## Conclusion

> There are only two hard things in Computer Science: cache invalidation and naming things.
> — Phil Carlton

If you haven’t established good naming conventions for your functions, variables and classes yet, feel free to use the above-given tips. Having naming conventions makes your code read better and look more uniform and professional.

Connect with me on [Twitter](https://twitter.com/silen_petri) or [Medium](https://medium.com/@pksilen2). You can also find the above information in my book 📕 [Clean Code Principles And Patterns: A Software Practitioner’s Handbook](https://www.amazon.com/dp/B0BSDJKYQJ) 📕.