The BEST Naming Strategy for Any Programming Language
In this article, I write about a best practice naming strategy for functions that I find amazing to work with. It encapsulates responsibilities among different kinds of functions and sets guidelines that will save you a lot of debugging time down the road.
The naming strategy is suitable for any programming language, but I will focus on JavaScript (using ReactJS) and use the example of function implementations in Readily, a reading enhancement Chrome Extension for dyslexic readers.
Following this, the criteria for the best naming convention would be:
- Shortest names possible
- Easy to understand
Naming Conventions != Naming Strategy
Firstly, while I won’t get into too much detail into case convention, but here are the most recognized ones for completeness.
- camelCase : all words except the first are capitalized at the first letter (JavaScript)
- PascalCase : all words capitalized at the first letter (C#)
- snake_case : all lowercase, words separated by underscores (python)
High-Level Overview
Now, the key concept in this naming strategy is adding prefixes to functions to indicate to declare what will happen when it is called. This allows future developers to quickly identify where in the code any business logic was implemented incorrectly given a set of debug logs.
Note that this article does not discuss a naming strategy for variables. That will be in an article for another time.
Prefixes, Why?
Using prefixes encapsulates what occurs in functions using the single responsibility principles, meaning that functions should ever only do one thing, or make one kind of decision.
This method is used in the Unity game engine’s networking module, which requires functions that will be run on the server to start with Cmd while functions that can only be called in the clients start with Rpc (short for remote procedure call. More on this here.
The kinds of prefixes you will use can depend on your use case. For the example below, I will be discussing general functions with regards to using the Command and Memento Design Pattern .
The COMMAND pattern is applied to the SentenceMenuItem, which is the row rendered in the example image containing the “Sentence” title and toggle switch.
Following the MEMENTO pattern for ReactJS, all STATE must be in the top level renderer object (SentenceMenuItem). In MEMENTO, functions must update the state, and changes in the state must be analyzed to reflect visual updates. This is done via the virtual componentDidUpdate(prevProps,prevState,snapshot) in the React.Component class where this.state can be called in the function to get the current state.
In the example, there are a few states to be kept for each webpage visisted:
- current (integer), indicates the sentence number the user is on
- highlights (map), indicates which sentences should be highlighed
- commands (array-like), stores the command history
Functions are prefixed with the following keys:
[1] The commands object most closely resembles a stack. A command is pushed to the object to be at the top. However, when undoing, the top command is just popped and discarded. The undone commands are kept until a redo is executed or the user applied a new command to overwrite the popped commands. The popped commands could be stored in another stack.
Further Notes on Prefixes
- doIter
May contain filtration logic. Execute functions should not be called here as it will trigger multiple state updates.
Instead, the final state should be calculated using calc then applied using execute, the differences in state should then calculated by calc, and then be iterated by the doIter function.
- user
The compoennt’s enabled & active state is checked before the command functions are allowed to run. Execute functions may be directly called if undo functionality is not intended.
- calc & get
All variables should be declared in the function parameters (this should not read any state variables). Constants may be declared outside the function.
Additional Functions
For ReactJS, the following function is also used:
- componentDidUpdate: compare previous state and new state, then apply do functions
Example Flow
Here is an example of how these functions are used. In it, you can see how the encapsulation makes it clear what would happen in the functions.
/**
* The following chain will increment the this.state.current
* value to indicate that the next sentence should be
* highlighted.
*/userMoveNextSentence() // Calls the command function to
// record the action
- commandMoveNext() // Calls the execute to apply state change
= executeMove(commandProps) // Causes the re-render
- (state-change re-render)
- componentDidUpdate() // Calls the do functions to
// remove the previous
// highlight and add the next one
- doRemoveHighlight(prevN), doAddHighlight(nextN)
Conclusion
In this article I have discussed the best naming strategy for encapsulating several types of functions. Using this naming strategy, developers can significantly enhance the maintainability and understandability of their code.
If you have any thoughts or knowledge of the enforcement of this prefixing (e.g. in a Linter), do comment and let me know below!