Generic names

The terse naming technique is one of the principal technique for reducing character count complexity metric, but it offers positive implications on the horizontal complexity as well. The technique dictates a replacement of long variable names with short, often one or two characters long, names. This is possible mostly in the case that the identifier represents a generic member of its kind. The code will obfuscated if such short names are used for non-generic members.

Motivation

The following function takes a quadratic function, specified by the three coefficients of the polynomial, and draws the values of this function in several integral points.

void draw_Quadratic_function(
  double coefficient_X_squared,
  double coefficient_X,
  double free_coefficient,
  int points_count
) {
  double values_array[] = new double[points_count];
  for (int index = 0; index < points_count; index++)
    values_array[index] = coefficient_Xsquared * index * index + coefficient_X * index + free_coefficient;
  draw(values_array,points_count);
}

The parameters to this function are generic, that is, no special assumptions are made about any one of them. The first three parameters are arbitrary double values, while the fourth is a non-negative integers. The terse naming technique dictates using one letter names for all of these:

void draw_quad_func(double a, double b, double c, int n) {
  double f[] = new double[n];
  for (int i = 0; i < n; i++)
    f[i] = a * i * i + b * i + c;
  draw(f,n);
}

The choice of names relies on common mathematical conventions for the names of the coefficients of a quadratic polynomial, and the use of n as a generic name for a generic non-negative integer.

This shorter former should be just as clear as its longer version. Further, the shorter form reveals a quick optimization by using Newtwon's formula for the evaluation of polynomials

void draw_quad_func(double a, double b, double c, int n) {
  double f[] = new double[n];
  for (int i = 0; i < n; i++) 
    f[i]=(a * i + b ) * i + c; 
  draw(f,n); 
}

which incidentally reduces further the character count and the token count metrics.

As shown in the above example, trying to make up "good", in the sense of long, verbose and descriptive names for generic variables may yield somewhat awkward names such coefficient_X_squared. It may also lead to inconsistent naming. Consider for example functions compareTo and compareToIgnoreCase

/**
* Compares two strings lexicographically.
* The comparison is based on the...
* @param anotherString the String to be compared.
* @return ...
*/
public int compareTo(String anotherString) {
  // ...
}
/**
* Compares two strings lexicographically, ignoring case
* differences...
* @param str the String to be compared.
* @return ...
*/
public int compareToIgnoreCase(String str) {
  // ...
}

both of which are part of Java's standard implementation of the String data type, that is java.lang.String. In the first, the generic parameter is named anotherString while in the other, it is named str, even though the functions are similar, and both parameters serve the same role. Similarly, we find in the same class a function whose signature is

public boolean equals(Object anObject)

and another function with the signature

public boolean equalsIgnoreCase(String anotherString)

It seems as if the implementors of this class worked hard to find descriptive names for these generic parameters. But, almost by definition, generic entities have no descriptive names, and it is even more difficult to come up with consistent "descriptive" names for these.

The alternative offered by the generic names technique

public boolean equalsIgnoreCase(String anotherString) {
  // ...
}
public int compareTo(String s) {
  // ...
}
public int compareToIgnoreCase(String s) {
  // ...
}
public boolean equals(Object o) {
  // ...
}
public boolean equalsIgnoreCase(String s) {
  // ...
}

is more consistent. And, the choice of one letter names highlights the fact that the values with which the receiver String is compared are arbitrary.

Rules

In selecting generic names, apply the following rules:

Generic Variables Only

Generic names should never be used for non-generic. Do not apply the following rules to any of these.

Consider for example the signature of function sendAnEmail

private static void sendEmail(
  final String from, 
  final List<String> to, 
  final String subject, 
  final String body, 
  final List<File> attachments
) throws Throwable {

Parameter from is a String, but it is not a generic string. The function is not designed to work if an arbitrary string is passed as its first parameter. Parameter from is intended to be a string representing a valid email address and accordingly follow specific formatting rules, and the choice of name reflects this intention. A generic name for this parameter is absolutely inappropriate.

The same consideration applies to all other parameters of this function.

Small Scoped Variables Only

Terse names should never be used for variables defined in large scope

The generic identifiers technique is inspired by the observation that many of the identifiers are visible only at a very limited scope. The application of other spartan programming techniques may make this scope even shorter. But, if for some reason a variable is visible in a large scope, using a generic name for it may confuse readers, sending them in a long journey of examining the variable's definition and all its uses.

Primitive Arithmetical Types

Generic names of variables of the primitive arithmetical types should follow the mathematical conventions suitable for the context.

The primitive arithmetical types of Java are byte, short, int, long, float and double. C++ offers more such types, including unsigned short, long long int, long double. Generic variables of arithmetical types are often used in a mathematical context which suggests names for such variables.

Integral Primitive Types

Function positive in Class DBC uses the name n for a generic parameter of type int

/**
* A possibly non-returning method to be used for checking integers which must be positive.
*
* @param n
* a value which must be positive
* @throws Bug.Assertion.Value.Numerical.Positive
* in case n was nonpositive
*/
public static void positive(final int n) throws Bug.Assertion.Value.Numerical.Positive {
  if (n <= 0) 
    throw new Bug.Assertion.Value.Numerical.Positive(n); 
}

Floating Point Type Example

The standard Java library, java.lang.Math includes a function to compute an angle from rectangular coordinates. This function reads

/** ...
* @param y the ordinate coordinate
* @param x the abscissa coordinate
* @return ...
*/
public static double atan2(double y, double x) {
// ...
}

Non Arithmetical Primitive Types

There are only two non-arithmetical primitive types in Java: char and boolean.

Character Primitive Type

A generic variable of type char is usually denoted by c as in the following two functions, both drawn from the Java standard library implementation of the type Character:

/**
* Returns a <tt>Character</tt> instance representing the specified
* <tt>char</tt> value. ...
* @param c a char value.
* @return a <tt>Character</tt> instance representing <tt>c</tt>. ...
*/
public static Character valueOf(char c) {
...
}
/**
* Returns a <tt>String</tt> object representing the
* specified <tt>char</tt>. ...
* @param c the <tt>char</tt> to be converted...
*/
public static String toString(char c) {
    return String.valueOf(c);
}

Boolean Primitive Type

Generic parameters of type boolean are not common. When they do show up, the generic names technique says that they should be named b as in the following example, drawn from the Java standard library implementation of the type Boolean:


  /**
  * Returns a <tt>Boolean</tt> instance representing the specified
  * <tt>boolean</tt> value. ....
  *
  * @param b a boolean value.
  * @return a <tt>Boolean</tt> instance representing <tt>b</tt>. ...
  */
  public static Boolean valueOf(boolean b) {
  ...
  }

One-Word Reference Types

The name of an instance of a non-primitive type is the first letter of the type name, if the type name is a single word.

Good type names consist of a single word. A generic instance of an instance of such a type is the first letter of the type name.

For example, function sendMessage uses the generic name t for the generic variable of type Transport

private static void sendMessage(final Message m, final Session s) {
  final Transport t = s.getTransport("smtp");
  t.connect(smtpServer, port, userName, password);
  t.sendMessage(m, m.getAllRecipients());
  t.close();
}

Multiple-Word Reference Types

The generic name of an instance of a non-primitive type whose name is comprised by several words is the lower cased acronym of the type name

Java String Example

The following function is offered by Java's standard implementation of the String datatype, that is java.lang.String. Notice that the generic parameter of type StringBuffer is named sb.

/**
* Compares this string to the specified {@code StringBuffer}...
*
* @param sb
* The {@code StringBuffer} to compare this {@code String} against
*
* @return ...
*/
  public boolean contentEquals(StringBuffer sb) {
    synchronized(sb) {
    return contentEquals((CharSequence)sb);
  }
}

Arrays and other Collections