Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the advantages of PHP code

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "what are the advantages of PHP code". The content of the article is simple and clear, and it is easy to learn and understand. Please follow the editor's ideas to study and learn "what are the advantages of PHP code".

Introduction

Robert C.Martin's 's software engineer guidelines, Clean Code, also apply to PHP. It is not a coding style guide, it guides us to write readable, reusable and decomposable code in PHP.

Not all guidelines must be strictly observed, and even some have become common conventions. This serves only as a guideline, many of which are years of experience by Clean Code authors.

Inspired by clean-code-javascript

Although many developers still use PHP 5, most of the examples in this article can only be run under PHP 7.1 +.

Variable

Use meaningful and readable variable names

Unfriendly:

$ymdstr = $moment- > format ('ymuri mmurd')

Friendly:

$currentDate = $moment- > format ('ymuri mmurd')

Use the same vocabulary for variables of the same type

Unfriendly:

GetUserInfo (); getUserData (); getUserRecord (); getUserProfile ()

Friendly:

GetUser ()

Use a searchable name (part I)

We read more code than we write. So it is very important that the code we write needs to be readable and searchable. It is very troublesome for us to understand unnamed variables in the program. Make your variables searchable!

Code that is not readable:

/ / what the hell does 448 mean? $result = $serializer- > serialize ($data, 448)

Having readability:

$json = $serializer- > serialize ($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)

Use searchable names (part II)

Bad:

/ / what the hell does 4 mean? If ($user- > access & 4) {/ /...}

A good way:

Class User {const ACCESS_READ = 1; const ACCESS_CREATE = 2; const ACCESS_UPDATE = 4; const ACCESS_DELETE = 8;} if ($user- > access & User::ACCESS_UPDATE) {/ / do edit.}

Use interpretive variables

Bad:

$address = 'One Infinite Loop, Cupertino 95014); saveCityZipCode ($matches [1], $matches [2])

General:

This is better, but we still rely heavily on regular expressions.

$address = 'One Infinite Loop, Cupertino 95014) / / ^ [^,] +,\ s * (. +?)\ s * (\ d {5}) $/'; preg_match ($cityZipCodeRegex, $address, $matches); [, $city, $zipCode] = $matches;saveCityZipCode ($city, $zipCode)

It's great:

Reduce dependence on regular expressions by naming subpatterns.

$address = 'One Infinite Loop, Cupertino 95014 matches city' =' / ^ [^,] +,\ s * (?. +?)\ s * (?\ d {5}) $/'; preg_match ($ZipCodeRegex, $matches ['city'], $matches [' zipCode'])

Avoid too deep nesting and early return (part I)

Using too many if else expressions can make the code difficult to understand.

Explicit is better than implicit.

Bad:

Function isShopOpen ($day): bool {if ($day) {if (is_string ($day)) {$day = strtolower ($day); if ($day = 'friday') {return true;} elseif ($day =' saturday') {return true;} elseif ($day = 'sunday') {return true;} else {return false;}} else {return false;} else {return false;}}

It's great:

Function isShopOpen (string $day): bool {if (empty ($day)) {return false;} $openingDays = ['friday',' saturday', 'sunday']; return in_array (strtolower ($day), $openingDays, true);}

Avoid too deep nesting and early return (part II)

Bad:

Function fibonacci (int $n) {if ($n)

< 50) { if ($n !== 0) { if ($n !== 1) { return fibonacci($n - 1) + fibonacci($n - 2); } else { return 1; } } else { return 0; } } else { return 'Not supported'; }} 很棒: function fibonacci(int $n): int{ if ($n === 0 || $n === 1) { return $n; } if ($n >

50) {throw new\ Exception ('Not supported');} return fibonacci ($n-1) + fibonacci ($n-2);}

Avoid psychological mapping

Don't force your code reader to translate the meaning of variables.

Explicit is better than implicit.

Bad:

$l = ['Austin',' New York', 'San Francisco']; for ($I = 0; $I

< count($l); $i++) { $li = $l[$i]; doStuff(); doSomeOtherStuff(); // ... // ... // ... // Wait, what is `$li` for again? dispatch($li);} 很棒: $locations = ['Austin', 'New York', 'San Francisco'];foreach ($locations as $location) { doStuff(); doSomeOtherStuff(); // ... // ... // ... dispatch($location);} 不要增加不需要的上下文 如果类名或对象名告诉你某些东西后,请不要在变量名中重复。 小坏坏: class Car{ public $carMake; public $carModel; public $carColor; //...} 好的方式: class Car{ public $make; public $model; public $color; //...} 使用默认参数而不是使用短路运算或者是条件判断 不好的做法: 这是不太好的因为 $breweryName 可以是 NULL. function createMicrobrewery($breweryName = 'Hipster Brew Co.'): void{ // ...} 还算可以的做法: 这个做法比上面的更加容易理解,但是它需要很好的去控制变量的值. function createMicrobrewery($name = null): void{ $breweryName = $name ?: 'Hipster Brew Co.'; // ...} 好的做法: 你可以使用 类型提示 而且可以保证 $breweryName 不会为空 NULL. function createMicrobrewery(string $breweryName = 'Hipster Brew Co.'): void{ // ...}对比 使用 相等运算符 不好的做法: $a = '42';$b = 42; 使用简单的相等运算符会把字符串类型转换成数字类型 if( $a != $b ) { //这个条件表达式总是会通过} 表达式 $a != $b 会返回 false 但实际上它应该是 true ! 字符串类型 '42' 是不同于数字类型的 42 好的做法: 使用全等运算符会对比类型和值 if( $a !== $b ) { //这个条件是通过的} 表达式 $a !== $b 会返回 true。 函数 函数参数(2 个或更少) 限制函数参数个数极其重要 这样测试你的函数容易点。有超过 3 个可选参数会导致一个爆炸式组合增长,你会有成吨独立参数情形要测试。 无参数是理想情况。1 个或 2 个都可以,最好避免 3 个。 再多就需要加固了。通常如果你的函数有超过两个参数,说明他要处理的事太多了。 如果必须要传入很多数据,建议封装一个高级别对象作为参数。 不友好的: function createMenu(string $title, string $body, string $buttonText, bool $cancellable): void{ // ...} 友好的: 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 only do 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 the function does only one thing, the refactoring is very simple, and the code is very clear to read. By mastering this principle, you will be ahead of many other developers.

Bad:

Function emailClients (array $clients): void {foreach ($clients as $client) {$clientRecord = $db- > find ($client); if ($clientRecord- > isActive ()) {email ($client);}

All right:

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 what it does.

Bad examples:

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 ()

A function can only be at one level of abstraction

When you have multiple levels of abstraction, your functions usually do too much. The split function function makes reusability and testing easier. .

Bad:

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... }}

It's not very good either:

We have done some functionality, but the parseBetterJSAlternative () function is still very complex and cumbersome 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 parseBetterJSAlternative () 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 ($foreach $ast as) {/ / ast as }}}

Do not use marking as an argument to a function

The sign is to tell you that there are a lot of things to do in this method. As I just said, a function should only do one thing. Split the code with different tags into multiple functions.

Unfriendly:

Function createFile (string $name, bool $temp = false): void {if ($temp) {touch ('. / temp/'.$name);} else {touch ($name);}}

Friendly:

Function createFile (string $name): void {touch ($name);} function createTempFile (string $name): void {touch ('. / temp/'.$name);}

Avoid side effects

A function should only take a numerical value and return another numerical value, which is called a side effect if something else is done in the process. The side effects may be writing to a file, modifying some global variables, or accidentally giving all your money to strangers.

Now, you do need to have side effects in a program or situation, like the previous example, you may need to write a file. What you need to do is to put together the places where you do this. Don't write to a specific file with several functions and classes. Only one service is allowed to be implemented separately.

The point is to avoid common pitfalls such as sharing unstructured data between objects, using any variable data type that can be written, and not focusing on dealing with these side effects. If you do this, you will be happier than most programmers.

Bad:

/ / this global variable is used in the function / / if we use this global variable in another method, it is possible that we will accidentally change it to the array type $name = 'Ryan McDermott';function splitIntoFirstAndLastName (): void {global $name; $name = explode (', $name);} splitIntoFirstAndLastName (); var_dump ($name); / / ['Ryan',' McDermott']

Recommended:

Function splitIntoFirstAndLastName (string $name): array {return explode ('', $name);} $name = 'Ryan McDermott';$newName = splitIntoFirstAndLastName ($name); var_dump ($name); / /' Ryan McDermott';var_dump ($newName); / / ['Ryan',' McDermott']

Do not define global functions

Defining global functions in many languages is a bad habit because the global functions you define may conflict with other people's libraries, and unless you encounter an exception in practice, your API users will not be aware of this. Let's take a look at an example: when you want to have a configuration array, you may write a global function of config (), but this will conflict with libraries defined by others.

Bad:

Function config (): array {return ['foo' = >' bar',]}

All right:

Class Configuration {private $configuration = []; public function _ construct (array $configuration) {$this- > configuration = $configuration;} public function get (string $key):? string {return isset ($this- > configuration [$key])? $this- > configuration [$key]: null;}}

To obtain the configuration, you need to create an instance of the Configuration class, as follows:

$configuration = new Configuration (['foo' = >' bar',])

Now, you must use an instance of Configuration in your application.

Do not use singleton mode

The singleton pattern is an anti-pattern. The following paraphrase Brian Button's point of view:

The singleton pattern is often used for global instances. Why is it not good to do so? Because you hide the application dependencies in your code instead of exposing them through the interface. Avoiding the spread of global things is a kind of code smell.

The singleton model violates the principle of single responsibility: it is based on the fact that the singleton model controls its own creation and life cycle.

Singleton patterns naturally lead to code tight coupling. This makes it difficult to test with fake data in many cases.

The state of the singleton pattern remains throughout the lifecycle of the application. This will have a second blow to the test, you can only make it impossible to run the code that needs to be tested, and you can't do unit testing at all. What for? Because each unit test should be independent of each other.

There is also some deep thinking from Misko Hevery about the root causes of the singleton pattern.

A bad demonstration:

Class DBConnection {private static $instance; private function _ construct (string $dsn) {/ /...} public static function getInstance (): DBConnection {if (self::$instance = null) {self::$instance = new self ();} return self::$instance;} / /.} $singleton = DBConnection::getInstance ()

A good demonstration:

Class DBConnection {public function _ construct (string $dsn) {/ /...} / /.}

Configure the created instance of the DBConnection class with DSN.

$connection = new DBConnection ($dsn)

Now you have to use an instance of DBConnection in your application.

Encapsulate conditional statement

Unfriendly:

If ($article- > state = = 'published') {/ /.}

Friendly:

If ($article- > isPublished ()) {/ /...}

Avoid judging by antonym conditions

Unfriendly:

Function isDOMNodeNotPresent (\ DOMNode $node): bool {/ /...} if (! isDOMNodeNotPresent ($node)) {/ /.}

Friendly:

Function isDOMNodePresent (\ DOMNode $node): bool {/ /...} if (isDOMNodePresent ($node)) {/ /.}

Avoid using conditional statements

It sounds like an impossible task. When you hear this for the first time, most people say, "what am I going to do without an if statement?" The answer is that in many cases you can use polymorphism to accomplish the same task. Then came the second question, "sounds good, but why do I need to do that?" The answer is the clean code concept we learned before: a function should only do one thing. If your class or function has an if statement, this tells the user that your class or function has done more than one thing. Remember, just do one thing.

Bad:

Class Airplane {/ /... Public function getCruisingAltitude (): int {switch ($this- > type) {case '777customers: return $this- > getMaxAltitude ()-$this- > getPassengerCount (); case' Air Force One': return $this- > getMaxAltitude (); case 'Cessna': return $this- > getMaxAltitude ()-$this- > getFuelExpenditure ();}

All right:

Interface Airplane {/ /... Public function getCruisingAltitude (): int;} class Boeing777 implements Airplane {/ /... Public function getCruisingAltitude (): int {return $this- > getMaxAltitude ()-$this- > getPassengerCount ();} class AirForceOne implements Airplane {/ /. Public function getCruisingAltitude (): int {return $this- > getMaxAltitude ();} class Cessna implements Airplane {/ /. Public function getCruisingAltitude (): int {return $this- > getMaxAltitude ()-$this- > getFuelExpenditure ();}}

Avoid type detection (part 1)

PHP is untyped, which means that your function can accept any type of argument.

Sometimes this freedom bothers you, and it makes you naturally use type checking in functions. There are many ways to avoid doing this.

Consider the consistency of API first.

Bad:

Function travelToTexas ($vehicle): void {if ($vehicle instanceof Bicycle) {$vehicle- > pedalTo (new Location ('texas'));} elseif ($vehicle instanceof Car) {$vehicle- > driveTo (new Location (' texas'));}}

All right:

Function travelToTexas (Traveler $vehicle): void {$vehicle- > travelTo (new Location ('texas'));}

Avoid type checking (part 2)

If you are using a basic type such as a string, numeric, or array, you are using the PHP version of PHP 7 numbers, and you cannot use polymorphism, but still feel the need to use type checking, you should consider type definition or strict schema. It provides you with static types based on the standard PHP syntax.

The problem with manual type checking is that it takes so much extra language to do it, and the fake "type safety" you get doesn't make up for lost readability. Keep your code concise, write good tests, and have good code review.

Otherwise, use PHP's strict type declaration or strict schema to do all this work.

Bad:

Function combine ($val1, $val2): int {if (! is_numeric ($val1) | |! is_numeric ($val2)) {throw new\ Exception ('Must be of type Number');} return $val1 + $val2;}

All right:

Function combine (int $val1, int $val2): int {return $val1 + $val2;}

Remove useless code

Useless code is as bad as repeating code. If it is not called, it should be deleted, there is no need to keep it in your code base! When you need it, you can find it in your historical version.

Bad:

Function oldRequestModule (string $url): void {/ /...} function newRequestModule (string $url): void {/ /...} $request = newRequestModule ($requestUrl); inventoryTracker ('apples', $request,' www.inventory-awesome.io')

Good:

Function requestModule (string $url): void {/ /...} $request = requestModule ($requestUrl); inventoryTracker ('apples', $request,' www.inventory-awesome.io'); objects and data structures

Use object encapsulation

In PHP, you can use keywords such as public, protected and private in methods.

With them, you can control and modify the properties of the object at will.

When you want to do more than get object properties, you don't need to modify your code

When the set property is used, it is easy to add parameter validation.

The internal representation of the package.

It is easy to add logging and error handling when getting and setting properties.

Inheriting this class, you can override the default information.

You can delay loading the properties of the object, such as getting data from the server.

In addition, this method is also in line with the [opening and closing principle] (# opening and closing principle (OCP)) in OOP development.

Bad:

Class BankAccount {public $balance = 1000;} $bankAccount = new BankAccount (); / / Buy shoes...$bankAccount- > balance-= 100

All right:

Class BankAccount {private $balance; public function _ construct (int $balance = 1000) {$this- > balance = $balance;} public function withdraw (int $amount): void {if ($amount > $this- > balance) {throw new\ Exception ('Amount greater than available balance.');} $this- > balance-= $amount;} public function deposit (int $amount): void {$this- > balance + = $amount;} public function getBalance (): int {return $this- > balance;}} $bankAccount = bankAccount () / / Buy shoes...$bankAccount- > withdraw ($shoesPrice); / / Get balance$balance = $bankAccount- > getBalance ()

Let the object have a member of the private/protected property

Public public methods and properties are the most dangerous for change, because some external code may easily rely on them, but you can't control the code that depends on them. Class changes are dangerous for all users of the class.

Protected protected attribute changes are as dangerous as public public ones, because they are available within the subclass scope. In other words, the difference between public and protected lies only in the access mechanism, and only encapsulation can ensure that the properties are consistent. Any change within a class is dangerous for all inherited subclasses.

Changes to the private properties of private guarantee that the code is only dangerous within the scope of a single class (you are safe to modify, and you will not have other similar building block effects Jenga effect).

Therefore, use the private property by default, and use the public/protected property only when you need to provide access properties to external classes.

For more information, please refer to Fabien Potencier's article on this column, blog post.

Bad:

Class Employee {public $name; public function _ construct (string $name) {$this- > name = $name;}} $employee = new Employee ('John Doe'); echo' Employee name:'. $employee- > name; / / Employee name: John Doe

Good:

Class Employee {private $name; public function _ construct (string $name) {$this- > name = $name;} public function getName (): string {return $this- > name;}} $employee = new Employee ('John Doe'); echo' Employee name:'. $employee- > getName (); / / Employee name: John Doe class

Combination is better than inheritance

As stated in the design pattern written by the Gang of Four

We should try our best to choose combination rather than inheritance. There are many benefits to using inheritance and combination.

The main significance of this rule is that when you instinctively use inheritance, try to think about whether the combination can better model your requirements.

In some cases, this is the case.

Then you might think, "so when should I use inheritance?"

The answer depends on your question, and of course here are some instructions on when inheritance is better than combination:

Your inheritance expresses a relationship that is "one" rather than "has one" (for example, humans are "animals, while users" have "user details").

You can reuse the code of the base class (humans can move like animals).

You want to make global changes to all derived classes by modifying the base class (change the energy consumption of animals as they move).

Bad:

Class Employee {private $name; private $email; public function _ construct (string $name, string $email) {$this- > name = $name; $this- > email = $email;} / not good, because Employees "has" taxdata// and EmployeeTaxData is not an Employee type class EmployeeTaxData extends Employee {private $ssn; private $salary; public function _ construct (string $name, string $email, string $ssn, string $salary) {parent::__construct ($name, $email); $this- > this- = $this- $ssn > ssn; = $ssn } / /...}

Very good:

Class EmployeeTaxData {private $ssn; private $salary; public function _ _ construct (string $ssn, string $salary) {$this- > ssn = $ssn; $this- > salary = $salary;} / /.} class Employee {private $name; private $email; private $taxData; public function _ construct (string $name, string $email) {$this- > name = $name; $this- > email = $email;} public function setTaxData (string $ssn, string $salary) {$salary > this- = this- ($this-, $this-) } / /...}

Avoid streaming interfaces

Streaming interface is an object-oriented API method, which aims to improve the readability of source code through method chain Method chaining.

Although streaming interfaces require some context and often build objects, this pattern reduces code redundancy (for example: PHPUnit Mock Builder

Or Doctrine Query Builder)

But it also brings a lot of trouble:

Broke the encapsulated Encapsulation

Destroyed the prototype Decorators

It is difficult to simulate and test mock

Makes code that has been submitted many times difficult to understand

For more information, please refer to Marco Pivetta's article on this topic, blog post.

Bad:

Class Car {private $make = 'Honda'; private $model =' Accord'; private $color = 'white'; public function setMake (string $make): self {$this- > make = $make; / / NOTE: Returning this for chaining return $this;} public function setModel (string $model): self {$this- > model = $model; / / NOTE: Returning this for chaining return $this;} public function setColor (string $color): self {$this- > color = $color / / NOTE: Returning this for chaining return $this;} public function dump (): void {var_dump ($this- > make, $this- > model, $this- > color);}} $car = (new Car ())-> setColor ('pink')-> setMake (' Ford')-> setModel ('Fmur150')-> dump ()

Good:

Class Car {private $make = 'Honda'; private $model =' Accord'; private $color = 'white'; public function setMake (string $make): void {$this- > make = $make;} public function setModel (string $model): void {$this- > model = $model;} public function setColor (string $color): void {$this- > color = $color;} public function dump (): void {var_dump ($this- > make, $this- > model, $this- > this-);} $color = color () $car- > setColor ('pink'); $car- > setMake (' Ford'); $car- > setModel ('Fmuri 150'); $car- > dump ()

SOLID

SOLID is a memorable acronym recommended by Michael Feathers and represents the five most important object-oriented programming principles of Robert Martin naming:

S: single responsibility principle (SRP)

O: open-close principle (OCP)

L: Richter substitution principle (LSP)

I: interface isolation principle (ISP)

D: dependency inversion principle (DIP)

Principle of single responsibility Single Responsibility Principle (SRP)

As stated in the Clean Code book, "there should be only one reason to modify a class." It is always easy for people to "fill" a class with a bunch of methods, just like when we can only carry one suitcase on a plane, we stuff everything into it. The consequence of this is that logically, such a class is not highly cohesive and leaves a lot of reasons to modify it later.

It is important to minimize the number of times you need to modify a class, because when there are many methods in the class, it is difficult to know which dependent modules in the entire code base will be affected.

It's bad:

Class UserSettings {private $user; public function _ construct (User $user) {$this- > user = $user;} public function changeSettings (array $settings): void {if ($this- > verifyCredentials ()) {/ /...} private function verifyCredentials (): bool {/ /...}}

Very good:

Class UserAuth {private $user; public function _ construct (User $user) {$this- > user = $user;} public function verifyCredentials (): bool {/ /...}} class UserSettings {private $user; private $auth; public function _ construct (User $user) {$this- > user = $user; $this- > auth = new UserAuth ($user) } public function changeSettings (array $settings): void {if ($this- > auth- > verifyCredentials ()) {/ /...}

Opening and closing principle (OCP)

As Bertrand Meyer said, "Software entities (classes, modules, functions, etc.) should be open to extensions, but closed to modifications." What does that mean? This principle generally means that you should allow users to add functionality without modifying existing code.

Bad:

Abstract class Adapter {protected $name; public function getName (): string {return $this- > name;}} class AjaxAdapter extends Adapter {public function _ construct () {parent::__construct (); $this- > name = 'ajaxAdapter';}} class NodeAdapter extends Adapter {public function _ construct () {parent::__construct (); $this- > name =' nodeAdapter';} class HttpRequester {private $adapter Public function _ construct (Adapter $adapter) {$this- > adapter = $adapter;} public function fetch (string $url): Promise {$adapterName = $this- > adapter- > getName (); if ($adapterName = 'ajaxAdapter') {return $this- > makeAjaxCall ($url);} elseif ($adapterName =' httpNodeAdapter') {return $this- > makeHttpCall ($url) } private function makeAjaxCall (string $url): Promise {/ / request and return promise} private function makeHttpCall (string $url): Promise {/ / request and return promise}}

All right:

Interface Adapter {public function request (string $url): Promise;} class AjaxAdapter implements Adapter {public function request (string $url): Promise {/ / request and return promise}} class NodeAdapter implements Adapter {public function request (string $url): Promise {/ / request and return promise}} class HttpRequester {private $adapter; public function _ construct (Adapter $adapter) {$this- > adapter = $adapter;} public function fetch (string $url): Promise {return $this- > adapter- > request ($url);}}

Richter substitution principle (LSP)

This is a terrible term for a simple concept. It is usually defined as "if S is a subtype of T, T-type objects can be replaced with S-type objects."

(I.E., S-type objects can replace T-type objects) without changing any ideal properties of the program (correctness, task completion, etc.). This is an even more frightening definition.

The best explanation for this is that if you have a parent class and a subclass, then the parent and subclasses can be used interchangeably without getting incorrect results. This may still be confusing, so let's take a look at the classic square-rectangle example. Geometrically, a square is a rectangle, but if you model a "IS-a" relationship through inheritance, you will soon get into trouble. .

Bad:

Class Rectangle {protected $width = 0; protected $height = 0; public function render (int $area): void {/...} public function setWidth (int $width): void {$this- > width = $width;} public function setHeight (int $height): void {$this- > height = $height;} public function getArea (): int {return $this- > width * $this- > height }} class Square extends Rectangle {public function setWidth (int $width): void {$this- > width = $this- > height = $width;} public function setHeight (int $height): void {$this- > width = $this- > height = $height;}} / * * @ param Rectangle [] $rectangles * / function renderLargeRectangles (array $rectangles): void {foreach ($rectangles as $rectangle) {$rectangle- > setWidth (4); $rectangle- > setHeight (5); $area = $rectangle- > getArea (); / / BAD: Will return 25 Will return. Should be 20. $rectangle- > render ($area);}} $rectangles = [new Rectangle (), new Rectangle (), new Square ()]; renderLargeRectangles ($rectangles)

Excellent:

Abstract class Shape {abstract public function getArea (): int; public function render (int $area): void {/ /...}} class Rectangle extends Shape {private $width; private $height; public function _ construct (int $width, int $height) {$this- > width = $width; $this- > height = $height;} public function getArea (): int {return $this- > width * $this- > height;} class Square extends Shape {private $length Public function _ construct (int $length) {$this- > length = $length;} public function getArea (): int {return pow ($this- > length, 2);}} / * * @ param Rectangle [] $rectangles * / function renderLargeRectangles (array $rectangles): void {foreach ($rectangles as $rectangle) {$area = $rectangle- > getArea (); $rectangle- > render ($area);} $shapes = [new Rectangle (4,5), new Rectangle (4,5), new Square (5)]; renderLargeRectangles ($shapes)

Interface isolation principle (ISP)

ISP pointed out that "customers should not be forced to rely on interfaces they do not need."

A good example to observe and confirm this principle is for classes that need to set a large number of objects, and it is beneficial not to require clients to set a large number of options, because in most cases they do not need all the settings. Make them optional to avoid creating a "bloated interface."

Bad:

Interface Employee {public function work (): void; public function eat (): void;} class Human implements Employee {public function work (): void {/ /.... working} public function eat (): void {/ /. Eating in lunch break} class Robot implements Employee {public function work (): void {/ /.... Working much more} public function eat (): void {/ /.... Robot can't eat, but it must implement this method}}

All right:

Not every worker is an employee, but every employee is a worker.

Interface Workable {public function work (): void;} interface Feedable {public function eat (): void;} interface Employee extends Feedable, Workable {} class Human implements Employee {public function work (): void {/.... working} public function eat (): void {/ /.... Eating in lunch break}} / / robot can only workclass Robot implements Workable {public function work (): void {/ /.... working}}

Dependency inversion principle (DIP)

This principle provides for two basic contents:

High-level modules should not rely on lower-level modules. Both should rely on abstraction.

Abstract classes should not depend on instances. Instances should rely on abstraction.

It may be difficult to understand at first, but if you have used php frameworks (such as Symfony) in your work, you should have seen this principle implemented in the form of dependency

Dependency injection (DI). Although they are not the same concept, DIP allows advanced modules to install them without knowing the details of their low-level modules.

This can be done through dependency injection. One of the great benefits of this is that it reduces coupling between modules. Coupling is a very bad development model because it makes your code difficult to ReFactor.

Bad:

Class Employee {public function work (): void {/ /.... working}} class Robot extends Employee {public function work (): void {/ /.... Working much more}} class Manager {private $employee; public function _ construct (Employee $employee) {$this- > employee = $employee;} public function manage (): void {$this- > employee- > work ();}}

Excellent:

Interface Employee {public function work (): void;} class Human implements Employee {public function work (): void {/.... working}} class Robot implements Employee {public function work (): void {/ /.... Working much more}} class Manager {private $employee; public function _ construct (Employee $employee) {$this- > employee = $employee;} public function manage (): void {$this- > employee- > work ();}} Don't write duplicate code (DRY)

Try to follow the DRY principle.

Try your best to avoid copying code, which is a very bad behavior, and copying code usually means that you need to change more than one place when you need to change some logic.

Imagine if you are running a restaurant and you need to record the purchases and sales of your warehouse: including all potatoes, onions, garlic, chili peppers, and so on. If you use multiple forms to manage purchase and sales records, when you cook with some of these potatoes, you need to update all the tables. If you only have one list, you only need to update one place.

Usually the reason you copy the code is that most of them are the same, except that there are two or more slightly different logic, but because of these differences, you end up writing two or more isolated but mostly the same methods, removing duplicate code means creating an abstraction that handles differences with a function/module/class.

Correct abstraction is critical, which is why you must learn to follow the SOLID principles discussed in the Classes chapter. Unreasonable abstraction is worse than copying code, so be careful! Having said so much, if you can design a reasonable abstraction, implement it! For the last time, don't write repetitive code, or you will find that when you want to change a logic, you have to modify multiple places!

Bad:

Function showDeveloperList (array $developers): void {foreach ($developers as $developer) {$expectedSalary = $developer- > calculateExpectedSalary (); $experience = $developer- > getExperience (); $githubLink = $developer- > getGithubLink (); $data = [$expectedSalary, $experience, $githubLink]; render ($data);} function showManagerList (array $managers): void {foreach ($managers as $manager) {$expectedSalary = $manager- > calculateExpectedSalary (); $experience = $manager- > getExperience (); $githubLink = $githubLink > githubLink (); $manager- = [$manager-, $getGithubLink, $getGithubLink] Render ($data);}}

All right:

Function showList (array $employees): void {foreach ($employees as $employee) {$expectedSalary = $employee- > calculateExpectedSalary (); $experience = $employee- > getExperience (); $githubLink = $employee- > getGithubLink (); $data = [$expectedSalary, $experience, $githubLink]; render ($data);}}

Very good:

It's best to keep your code compact.

Function showList (array $employees): void {foreach ($employees as $employee) {render ([$employee- > calculateExpectedSalary (), $employee- > getExperience (), $employee- > getGithubLink ()]);}} Thank you for reading, the above is the content of "what are the advantages of PHP code". After the study of this article, I believe you have a deeper understanding of the advantages of PHP code, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report