Alternative ways of writing code to improve code readability, clarity, brevity & performance
C# | C# in Unity | C++ | C++ in Unreal Engine | Java | Dart | Python | R | JS/TS | Go |
---|
Type annotation (explicit type)=> type inference (implicit type) for initializer expression and local variable [C++11auto
, C#var
, TSlet
, Dartvar
]
Pros: shorthand especially for long type init, focus more attention on local variable name and value
- Remove redundant member initializer (with default value)
// π non-compliant
private int _level = 0;
private bool _isGameOver = false;
// π preference
private int _level;
private bool _isGameOver;
Initializer expression:
// π longhand
AReallyReallyLooooongClass instance = new AReallyReallyLooooongClass();
// π shorthand
var instance = new AReallyReallyLooooongClass();
For local variable:
// π given
List<User> users = {User1, User2...};
// π non-compliant
foreach(User user in users)
// π preference
foreach(var user in users)
- Assign w/ nullable variable
// π longhand
const result = (nullableVar !== null && nullableVar !== undefined) ? nullableVar : fallbackVar
Using nullish coalescing operator ??
[C#, PHP, ES11]
// π shorthand
const result = nullableVar ?? fallbackVar
Using short circuit evaluation &&, ||
// π shorthand
const result = nullableVar || fallbackVar
- Assign default value for nullable variable using logical nullish assigment operator
??=
[TS/JS, C#8]
// π longhand
nullableVar = (nullableVar !== null && nullableVar !== undefined) ? nullableVar : defaultVal
// π longhand
nullableVar ?? (nullableVar = defaultVal)
// π shorthand
nullableVar ??= defaultVal
- Multiple variable declaration for related variables (and usually same type) [JS/TS, C#, Java, Go]
// π longhand
private string _firstName;
private string _lastName;
private float _height;
private float _weight;
// π shorthand
private string _firstName, _lastName;
private float _height, _weight;
- Assign multiple variables using object destructuring/tuple [ES6, C#, Python]
// π longhand
let a = 1;
let b = 2;
let c = 3;
// π shorthand
[a, b, c] = [1, 2, 3]
- Swap two variables using XOR
^
βοΈ Pros: avoid using third temporary variable
β Cons: purpose may not seem straightforward
// π longhand
temp = a;
a = b;
b = temp;
// π shorthand
a ^= b ^= a ^= b;
- Guard clause/assert/precondition: early return for special case; multiple return statements
βοΈ Pros: avoid nested statements, improve readability
β οΈ Cautions: too many return statements (esp. void) will make code unobvious and harder to debug
// π non-compliant
function getInsuranceDeductible(insurance){
if (insurance.covered) {
if (insurance.majorRepair) {
return 500
} else if (insurance.mediumRepair){
return 300
} else {
return 100
}
} else {
return 0
}
}
// π preference (use daisy chaining ternary operator to shorten furthermore)
function getInsuranceDeductible(insurance){
if (!insurance.covered) return 0
if (insurance.majorRepair) return 500
if (insurance.mediumRepair) return 300
return 100
}
- Ternary operator
? :
To assign value:
// π longhand
if (a > b) {
result = x;
}
else {
result = y;
}
// π shorthand
result = a > b ? x : y;
To return:
// π longhand
if (a > b) {
return x;
}
else {
return y;
}
// π shorthand
return a > b ? x : y;
To invoke function:
// π longhand
if (target is not null) {
print("Target found.");
}
else {
print("Target not found.");
}
// π shorthand
print(target is not null ? "Target found." : "Target not found.");
To shorten switch w/ multiple return statements using daisy chaining:
// π longhand
function getInsuranceDeductible(insurance) {
if (!insurance.covered) return 0
if (insurance.majorRepair) return 500
if (insurance.mediumRepair) return 300
return 100
}
// π shorthand
function getInsuranceDeductible(insurance) {
return insurance.covered ? 0
: insurance.majorRepair ? 500
: insurance.mediumRepair ? 300
: 100
}
- Conditional w/ falsy/truthy values [TS/JS, Groovy, Perl, PHP, Python, Ruby, C++
0, false
]
// π longhand
if(typeof a !== "undefined" && typeof b !== "null" && typeof c !== "NaN" && d !== "" && array.length !== 0)
// π shorthand
if(a && b && c && d && array.length)
- One-statement in conditional w/ short circuit evaluation
&&, ||
// π longhand
if(isHungry && isSleepy) {
code()
}
// π shorthand
isHungry && isSleepy && code()
- Spaceship/three-way comparison operator
<=>
[C++, Groovy, Kotlin, Perl, PHP, Ruby]
// π given
$users = ['branko', 'ivana', 'luka', 'ivano'];
// π longhand
usort($users, function ($a, $b) {
return ($a < $b) ? -1 : (($a > $b) ? 1 : 0);
});
// π shorthand
usort($users, function ($a, $b) {
return $a <=> $b;
});
- Constructor shorthand [TS, PHP8 (property promotion), Dart]
// π longhand
class User {
private name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
// π shorthand
class User {
constructor(
private name: string,
private age: number
) {}
}
- Explicitly declare access modifiers for class members
Reason: clarify purpose of the member
class User {
// π non-compliant
name: string;
// π preference
public name: string;
}
- Use lambda expression/arrow function
=>
to declare single statement functions [Java8, JS/TS (fat arrow), Dart, C# (expression-bodied members), Pythonlambda
]
Pros: bind this to the invoker
// π longhand
function getSum(a: number, b: number) {
return a + b
}
// π shorthand
const getSum = (a: number, b: number) => (a + b)
- Pass a single-use callback function as an argument w/ anonymous function
Pros: no need to declare a separate disposable function -> reduce coding overheating, often used along w/ collection operation such as map(), where(), and reduce(), etc
- Return
null=> empty collection
Reason: less error prone, reduce null checking on function usage
- Named argument [PHP8, Kotlin, C#, Python (keyword argument)]
Reason: for clarity, order of params could be changed, convenient to leave default arguments
// π given
public void doSomething(string foo, int bar) {...}
// π non-compliant
doSomething("someString", 1);
// π preference
doSomething(foo: "someString", bar: 1);
Overloading functionsthat differ only in trailing parameters => optional parameters
// π non-compliant
interface Example {
diff(one: string): number;
diff(one: string, two: string): number;
diff(one: string, two: string, three: boolean): number;
}
// π preference
interface Example {
diff(one: string, two?: string, three?: boolean): number;
}
Promise/callback chaining=>async-await
[ES6, C#, Dart]
=>String
StringBuffer
for string manipulations [Java, C#]
Reason: do not create new String instances on manipulations -> save memory
String concatenation operator=> String interpolation/template literals+
`${}`
[ES, C#, Kotlin, PHP]
// π non-compliant
console.log("Sum of " + a + " and " + b + " is " + (a + b))
// π preference
console.log(`Sum of ${a} and ${b} is ${a + b}`)