fungsi
Fungsi
1. Parameter fungsi (sebaik-baiknya kurang daripada 2)
2. Hanya perlu ada satu lapisan abstraksi dalam fungsi
5. Jangan gunakan bendera sebagai parameter fungsi
8. Jangan gunakan corak Singleton9. Kemasukan pernyataan bersyarat10. Elakkan menggunakan pertimbangan bersyarat yang bersinonim11. Elakkan pemeriksaan jenis (bahagian 1)
13. Elakkan menyemak jenis (bahagian 2)
1 Parameter fungsi (sebaik-baiknya kurang daripada 🜎) bilangan parameter fungsi, jadi uji Fungsi anda lebih mudah. Mempunyai lebih daripada 3 parameter pilihan menghasilkan gabungan gabungan dan anda akan mempunyai banyak senario parameter bebas untuk diuji.
Tiada parameter adalah situasi yang ideal. 1 atau 2 adalah baik, 3 sebaiknya dielakkan. Apa-apa lagi dan ia akan memerlukan pengukuhan. Biasanya jika fungsi anda mempunyai lebih daripada dua parameter, ini bermakna ia mempunyai terlalu banyak untuk dikendalikan. Jika banyak data mesti dihantar, adalah disyorkan untuk merangkum objek peringkat tinggi sebagai parameter.
Buruk:Baik: 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
{
// ...
}
2. Apabila fungsi melakukan lebih daripada satu perkara, ia sukar untuk dilaksanakan, diuji dan difahami. Apabila anda membahagikan fungsi kepada hanya satu fungsi, ia lebih mudah untuk difaktorkan semula dan kod anda berbunyi lebih bersih. Jika anda hanya mengikut peraturan ini, anda akan mendahului kebanyakan pembangun. . re ee 4. Hanya ada satu lapisan abstraksi dalam fungsiApabila anda mempunyai terlalu banyak tahap abstraksi, fungsi mengendalikan terlalu banyak perkara. Fungsi pemisahan diperlukan untuk meningkatkan kebolehgunaan semula dan kemudahan penggunaan untuk memudahkan ujian. (Nota penterjemah: Berdasarkan kod sampel di sini, ia sepatutnya merujuk kepada terlalu banyak bersarang)
Bad:
function emailClients(array $clients): void { foreach ($clients as $client) { $clientRecord = $db->find($client); if ($clientRecord->isActive()) { email($client); } } }
Bad:Kami mengekstrak beberapa kaedah daripada gelung, tetapi parseBetterJSAlternative() /code>Kaedahnya masih sangat rumit dan tidak sesuai untuk ujian.
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(); }Baik:
Penyelesaian terbaik ialah mengalih keluar kebergantungan kaedah parseBetterJSAlternative()
.
class Email { //... public function handle(): void { mail($this->to, $this->subject, $this->body); } } $message = new Email(...); // 啥?handle处理一个消息干嘛了?是往一个文件里写吗? $message->handle();
Dengan cara ini kita boleh mengejek
kebergantungan dan menguji sama ada BetterJSAlternative::parse()
beroperasi seperti yang diharapkan. mock
,并测试BetterJSAlternative::parse()
运行是否符合预期。
5. 不要用flag作为函数的参数
flag就是在告诉大家,这个方法里处理很多事。前面刚说过,一个函数应当只做一件事。 把不同flag的代码拆分到多个函数里。
坏:
class Email { //... public function send(): void { mail($this->to, $this->subject, $this->body); } } $message = new Email(...); // 简单明了 $message->send();
避免副作用
一个函数做了比获取一个值然后返回另外一个值或值们会产生副作用如果。副作用可能是写入一个文件,修改某些全局变量或者偶然的把你全部的钱给了陌生人。
现在,你的确需要在一个程序或者场合里要有副作用,像之前的例子,你也许需要写一个文件。你想要做的是把你做这些的地方集中起来。不要用几个函数和类来写入一个特定的文件。用一个服务来做它,一个只有一个。
重点是避免常见陷阱比如对象间共享无结构的数据,使用可以写入任何的可变数据类型,不集中处理副作用发生的地方。如果你做了这些你就会比大多数程序员快乐。
坏:
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... } }
好:
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) { // 解析逻辑... } }
6. 不要写全局函数
在大多数语言中污染全局变量是一个坏的实践,因为你可能和其他类库冲突 并且调用你api的人直到他们捕获异常才知道踩坑了。让我们思考一种场景: 如果你想配置一个数组,你可能会写一个全局函数config()
,但是他可能 和试着做同样事的其他类库冲突。
坏:
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) { // 解析逻辑... } } }
好:
function createFile(string $name, bool $temp = false): void { if ($temp) { touch('./temp/'.$name); } else { touch($name); } } 好: function createFile(string $name): void { touch($name); } function createTempFile(string $name): void { touch('./temp/'.$name); }
现在你必须在程序中用 Configuration
5. Jangan gunakan bendera sebagai parameter fungsibendera memberitahu semua orang bahawa kaedah ini mengendalikan banyak perkara. Seperti yang dinyatakan sebelum ini, fungsi hanya perlu melakukan satu perkara. Pisahkan kod untuk bendera yang berbeza kepada berbilang fungsi.
Bad:// Global variable referenced by following function. // If we had another function that used this name, now it'd be an array and it could break it. $name = 'Ryan McDermott'; function splitIntoFirstAndLastName(): void { global $name; $name = explode(' ', $name); } splitIntoFirstAndLastName(); var_dump($name); // ['Ryan', 'McDermott'];
Elak kesan sampinganFungsi yang melakukan lebih daripada mendapat nilai dan mengembalikan nilai atau nilai lain akan mempunyai kesan sampingan jika. Kesan sampingan mungkin menulis pada fail, mengubah suai beberapa pembolehubah global atau secara tidak sengaja memberikan semua wang anda kepada orang yang tidak dikenali.
Kini, anda perlu mempunyai kesan sampingan dalam program atau situasi Seperti contoh sebelumnya, anda mungkin perlu menulis fail. Perkara yang anda mahu lakukan ialah memusatkan tempat di mana anda melakukan ini. Jangan gunakan beberapa fungsi dan kelas untuk menulis ke fail tertentu. Lakukan dengan perkhidmatan dan hanya satu.
Tumpuan adalah untuk mengelakkan perangkap biasa seperti berkongsi data tidak berstruktur antara objek, menggunakan jenis data boleh ubah yang boleh ditulis kepada apa-apa dan tidak memfokuskan pada tempat kesan sampingan berlaku. Jika anda melakukan ini, anda akan lebih gembira daripada kebanyakan pengaturcara.
🎜🎜Buruk:🎜🎜function splitIntoFirstAndLastName(string $name): array { return explode(' ', $name); } $name = 'Ryan McDermott'; $newName = splitIntoFirstAndLastName($name); var_dump($name); // 'Ryan McDermott'; var_dump($newName); // ['Ryan', 'McDermott'];
🎜🎜Baik:🎜🎜function config(): array { return [ 'foo' => 'bar', ] }
🎜🎜🎜6 Jangan tulis fungsi global🎜🎜🎜Mencemarkan amalan global dalam kebanyakan bahasa. Anda mungkin bercanggah dengan perpustakaan lain dan orang yang memanggil API anda tidak akan tahu mereka menghadapi masalah sehingga mereka mendapat pengecualian. Mari kita pertimbangkan senario: Jika anda ingin mengkonfigurasi tatasusunan, anda mungkin menulis fungsi globalconfig()
, tetapi ia mungkin bercanggah dengan perpustakaan lain yang cuba melakukan perkara yang sama. 🎜🎜Buruk:🎜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; } } 加载配置并创建 Configuration 类的实例 $configuration = new Configuration([ 'foo' => 'bar', ]);
🎜Baik:🎜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();
🎜Kini anda mesti menggunakan contohKonfigurasi dalam program anda🎜🎜🎜🎜🎜7 Jangan gunakan corak tunggal🎜🎜🎜🎜 a Anti-corak. Berikut ialah penjelasannya: Diparafrasa daripada Butang Brian: 🎜🎜🎜🎜 sentiasa digunakan sebagai contoh global. Ia biasanya digunakan sebagai contoh global, mengapa begitu teruk kerana anda menyembunyikan kebergantungan aplikasi anda dalam kod anda, dan bukannya mendedahkannya melalui antara muka Membuat sesuatu yang global untuk mengelak daripada menyebarkannya adalah bau kod.🎜🎜 🎜🎜 mereka melanggar prinsip tanggungjawab tunggal: berdasarkan fakta bahawa mereka mengawal ciptaan dan kitaran hayat mereka sendiri. Mereka sememangnya menyebabkan kod ditambah dengan ketat 🎜🎜🎜Sentiasa bawa negeri sepanjang hayat program. Mereka membawa keadaan sepanjang hayat aplikasi Satu lagi ujian kerana anda boleh berakhir dengan situasi di mana ujian perlu dipesan yang merupakan tidak besar untuk ujian unit Kerana setiap ujian unit harus bebas daripada yang lain .🎜 Berikut ialah artikel yang sangat bagus membincangkan punca utama pola singleton ((http://misko.hevery.com/2008/08/25/root-cause-of-singleton/) oleh Misko Hevery Written.
Bad:
class DBConnection { public function __construct(string $dsn) { // ... } // ... }
Baik:
if ($article->state === 'published') { // ... }
Buat contoh kelas DBConnection
dan konfigurasikannya melalui DSN.DBConnection
类的实例并通过 DSN 配置.
$connection = new DBConnection($dsn);
现在你必须在程序中 使用 DBConnection
$connection = new DBConnection ;
Sekarang anda mesti menggunakan contoh DBConnection
dalam program anda
8 Merangkumkan penyataan bersyarat
Bad:
Baik.
if ($article->isPublished()) { // ... }
9. Elakkan penghakiman bersyarat
Buruk:
function isDOMNodeNotPresent(\DOMNode $node): bool { // ... } if (!isDOMNodeNotPresent($node)) { // ... }Baik:
function isDOMNodePresent(\DOMNode $node): bool
{
// ...
}
if (isDOMNodePresent($node)) {
// ...
}
kelihatan seperti impos1. kebolehan Tugasan Apabila orang mula-mula mendengar ayat ini , mereka berkata, "Apa yang boleh saya lakukan tanpa pernyataan if Jawapannya ialah anda boleh menggunakan polimorfisme untuk mencapai tugas yang sama dalam berbilang senario , "Tidak mengapa untuk melakukan ini, tetapi mengapa saya perlu melakukannya?" ialah prinsip Kod Bersih yang kami pelajari sebelum ini: fungsi hanya perlu melakukan satu perkara Apabila anda mempunyai banyak kelas dan fungsi yang mengandungi penyataan jika, Fungsi anda melakukan lebih daripada satu perkara
Buruk: class Airplane
{
// ...
public function getCruisingAltitude(): int
{
switch ($this->type) {
case '777':
return $this->getMaxAltitude() - $this->getPassengerCount();
case 'Air Force One':
return $this->getMaxAltitude();
case 'Cessna':
return $this->getMaxAltitude() - $this->getFuelExpenditure();
}
}
}
Baik: 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(); } }
11 Mengelakkan penyemakan jenis (bahagian 1)
PHP ditaip dengan lemah, yang bermaksud fungsi anda boleh menerima apa-apa jenis parameter ini taip-periksa fungsi anda. Yang pertama adalah untuk menyatukan API
Buruk: function travelToTexas($vehicle): void
{
if ($vehicle instanceof Bicycle) {
$vehicle->pedalTo(new Location('texas'));
} elseif ($vehicle instanceof Car) {
$vehicle->driveTo(new Location('texas'));
}
}
Baik:function travelToTexas(Vehicle $vehicle): void { $vehicle->travelTo(new Location('texas')); }
12. nilai primitif seperti rentetan, integer dan tatasusunan, versi yang diperlukan ialah PHP 7+, yang tidak memerlukan polimorfisme dan memerlukan pengesanan jenis, maka anda harus mempertimbangkan pengisytiharan jenis atau mod ketat Masalah dengan menyediakan jenis statik berdasarkan PHP standard sintaks adalah bahawa ia memerlukan banyak karut untuk melakukannya dengan betul, yang nampaknya hanya untuk keselamatan Tanpa mengira kehilangan kebolehbacaan Pastikan PHP anda bersih, tulis ujian yang baik, dan lakukan ulasan kod Pengisytiharan jenis ketat PHP dan mod ketat untuk memastikan keselamatan
function combine($val1, $val2): int { if (!is_numeric($val1) || !is_numeric($val2)) { throw new \Exception('Must be of type Number'); } return $val1 + $val2; }
Baik: function combine(int $val1, int $val2): int
{
return $val1 + $val2;
}
13 Alih keluar kod zombi kod pendua tidak sama buruknya ia! , jadi ia selamat.
Teruk:
function oldRequestModule(string $url): void { // ... } function newRequestModule(string $url): void { // ... } $request = newRequestModule($requestUrl); inventoryTracker('apples', $request, 'www.inventory-awesome.io');🎜🎜Baik:🎜🎜
function requestModule(string $url): void { // ... } $request = requestModule($requestUrl); inventoryTracker('apples', $request, 'www.inventory-awesome.io');