Use default parameters instead of short circuit operation or condition judgment
Bad practice:
This is not good because $breweryName can be NULL
function createMicrobrewery($breweryName = 'Hipster Brew Co.'): void { // ... }
It's OK:
This approach is easier to understand than the above, but it needs to control the value of variables well
function createMicrobrewery($name = null): void { $breweryName = $name ?: 'Hipster Brew Co.'; // ... }
Good practice:
You can use Type hint And you can guarantee that $breweryName will not be NULL
function createMicrobrewery(string $breweryName = 'Hipster Brew Co.'): void { // ... } }
Contrast
Use Equality operator
Bad practice:
$a = '42'; $b = 42; Using a simple equality operator converts a string type to a number type if( $a != $b ) { //This conditional expression always passes }
The expression $a! = $B returns false, but it should be true!
String type '42' is different from number type 42
Good practice:
Use the full operator to compare types and values
if( $a !== $b ) { //This condition is passed }
The expression $a! = = $B returns true.
function
Function arguments (2 or less)
It is very important to limit the number of function parameters
It's easier to test your functions. There are more than three optional parameters that will lead to an explosive combination growth, and you will have tons of independent parameters to test.
No parameter is ideal. One or two can be used. It's better to avoid three.
More needs to be reinforced. Usually if your function has more than two arguments, it has too much to deal with. If you have to pass in a lot of data, it is recommended to encapsulate a high-level object as a parameter.
unamiable:
function createMenu(string $title, string $body, string $buttonText, bool $cancellable): void { // ... }
Amicable:
class MenuConfig { public $title; public $body; public $buttonText; public $cancellable = false; } $config = new MenuConfig(); $config->title = 'Foo'; $config->body = 'Bar'; $config->buttonText = 'Baz'; $config->cancellable = true; function createMenu(MenuConfig $config): void { // ... }
Function should do only one thing
This is by far the most important principle of software engineering. When functions do more than one thing, they become difficult to write, test, and derive. When a function does only one thing, it's very simple to refactor, and the code is very clear to read. With this principle in hand, you will be ahead of many other developers.
It is bad:
function emailClients(array $clients): void { foreach ($clients as $client) { $clientRecord = $db->find($client); if ($clientRecord->isActive()) { email($client); } } }
Well:
function emailClients(array $clients): void { $activeClients = activeClients($clients); array_walk($activeClients, 'email'); } function activeClients(array $clients): array { return array_filter($clients, 'isClientActive'); } function isClientActive(int $client): bool { $clientRecord = $db->find($client); return $clientRecord->isActive(); }
The name of the function should be clear about the example of what it does not do well:
class Email { //... public function handle(): void { mail($this->to, $this->subject, $this->body); } } $message = new Email(...); // What is this? A handle for the message? Are we writing to a file now? $message->handle()
;
A good example:
class Email { //... public function send(): void { mail($this->to, $this->subject, $this->body); } } $message = new Email(...); // Clear and obvious $message->send();
Function can only be an abstraction level
When you have multiple levels of abstraction, you usually do too much function. Partitioning functions makes reusability and testing easier. .
Not good:
function parseBetterJSAlternative(string $code): void { $regexes = [ // ... ]; $statements = explode(' ', $code); $tokens = []; foreach ($regexes as $regex) { foreach ($statements as $statement) { // ... } } $ast = []; foreach ($tokens as $token) { // lex... } foreach ($ast as $node) { // parse... } }
Also not very good:
We have completed some functions, but the parsebetterjscalternative() function is still very complex and troublesome to test.
function tokenize(string $code): array { $regexes = [ // ... ]; $statements = explode(' ', $code); $tokens = []; foreach ($regexes as $regex) { foreach ($statements as $statement) { $tokens[] = /* ... */; } } return $tokens; } function lexer(array $tokens): array { $ast = []; foreach ($tokens as $token) { $ast[] = /* ... */; } return $ast; } function parseBetterJSAlternative(string $code): void { $tokens = tokenize($code); $ast = lexer($tokens); foreach ($ast as $node) { // parse... } }
Very good:
The best solution is to extract the dependency of the parsebetterjalternative() function
class Tokenizer { public function tokenize(string $code): array { $regexes = [ // ... ]; $statements = explode(' ', $code); $tokens = []; foreach ($regexes as $regex) { foreach ($statements as $statement) { $tokens[] = /* ... */; } } return $tokens; } } class Lexer { public function lexify(array $tokens): array { $ast = []; foreach ($tokens as $token) { $ast[] = /* ... */; } return $ast; } } class BetterJSAlternative { private $tokenizer; private $lexer; public function __construct(Tokenizer $tokenizer, Lexer $lexer) { $this->tokenizer = $tokenizer; $this->lexer = $lexer; } public function parse(string $code): void { $tokens = $this->tokenizer->tokenize($code); $ast = $this->lexer->lexify($tokens); foreach ($ast as $node) { // parse... } } }
For more information, please visit: