Concept

A good name indicates concept. A name's concept refers to the idea behind it, the intent in its creation, and how we should think about it. For example, a function named relocateDeviceAccurately not only tells us what it will do (its purpose) but informs us about the concept surrounding its behavior. From this name, we can see that devices are things that can be located and that locating such devices can be done at different levels of accuracy. A relatively simple name can arouse a rich concept within the minds of those who read it. This is part of the vital power of naming things: names are avenues to understanding.

A name's concept, like its purpose, is strongly tied to the context in which it exists. Context is the shared space that our names exist within. The other names that surround the name we're interested in are absolutely instrumental in helping us understand its concept. Imagine the following names together:

  • rejectedDeal
  • acceptedDeal
  • pendingDeal
  • stalledDeal

By these names, we immediately understand that a deal is something that can have at least four different states. It is implied that these states are mutually exclusive and cannot apply to a deal at the same time, although that is unclear at this time. We are likely to assume that there are specific conditions related to whether a deal is pending or stalled, although we're not sure what those conditions are. So, even though there is ambiguity here, we are already starting to build up a rich understanding of the problem domain. That's just by looking at names—without even reading the implementation. 

We have spoken about context as a kind of shared space for names. In programming vernacular, we usually say that things named together in one area occupy a single namespace. A namespace can be thought of as a place where things share a conceptual area with each other. Some languages have formalized the concept of a namespace into its own language construct (often called a package, or simply a namespace). Even without such formal language constructs, JavaScript still makes it possible to construct namespaces via hierarchical constructs such as objects like so:

const app = {};
app.transactions = {};
app.transactions.dealMaking = {};
app.transactions.dealMaking.states = [
'REJECTED_DEAL',
'ACCEPTED_DEAL',
'PENDING_DEAL',
'STALLED_DEAL'
];

Most programmers tend to think of namespaces as a very formal construct, but this isn't often the case. Often, without knowing it, we are composing implied namespaces when we write functions with functions within them. Instead of being delineated by a level of an object hierarchy, the namespaces, in this case, are delineated by the scopes of our functions, as follows: 

function makeFilteredRequest(endpoint, filterFn) {
return fetch(`/${endpoint}/`)
.then(response => response.json())
.then(data => data.filter(filterFn);
}

Here, we are making a request to an endpoint, via fetch, and before we return, we are gathering the required data via tapping into the promise returned by fetch. To do this, we use two then(...) handlers.

A promise is a natively provided class that provides a useful abstraction for handling asynchronous actions. You can usually identify a promise by its then method, like what we used in the preceding code. It's common practice to either use promises or callbacks when tapping into asynchronous actions. You can read more about this in Chapter 10, Control Flow, in the Asynchronous control flow section.

Our first then(...) handler names its argument response, while the second one names its argument data. Outside the context of makeFilteredRequest, these terms would be very ambiguous. However, because we are within the implied namespace of a function related to making a filtered request, the terms response and data are sufficient to communicate their concepts.

The concepts communicated by our names, much like their purposes, are heavily intertwined with the contexts in which they are specified, so it's important to consider not only the name itself but everything that surrounds it: the complex mesh of logic and behavior in which it resides. All code deals with some level of complexity, and a conceptual understanding of that complexity is crucial in being able to harness it. So, when naming something, it helps to ask yourself: How do I want them to understand this complexity? This is relevant if you're crafting a simple interface to be consumed by other programmers, writing a deeply embedded hardware driver, or creating a GUI for non-programmers to consume.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.238.70