[
  {
    "path": ".gitattributes",
    "content": "*.md linguist-documentation=false\n*.md linguist-language=PHP\n"
  },
  {
    "path": ".github/workflows/coding_standard.yaml",
    "content": "name: Coding Standard\n\non:\n    pull_request: null\n    push: null\n\njobs:\n    coding_standard:\n        runs-on: ubuntu-latest\n\n        steps:\n            -   uses: actions/checkout@v2\n            # see https://github.com/shivammathur/setup-php\n            -   uses: shivammathur/setup-php@v2\n                with:\n                    php-version: 8.0\n                    coverage: none\n\n            -   run: composer install --no-progress --ansi\n\n            -   run: vendor/bin/ecs check-markdown README.md --ansi\n"
  },
  {
    "path": ".gitignore",
    "content": "composer.lock\n/vendor"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 Ryan McDermott\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE\n"
  },
  {
    "path": "README.md",
    "content": "# Clean Code PHP\n\n## Table of Contents\n\n  1. [Introduction](#introduction)\n  2. [Variables](#variables)\n     * [Use meaningful and pronounceable variable names](#use-meaningful-and-pronounceable-variable-names)\n     * [Use the same vocabulary for the same type of variable](#use-the-same-vocabulary-for-the-same-type-of-variable)\n     * [Use searchable names (part 1)](#use-searchable-names-part-1)\n     * [Use searchable names (part 2)](#use-searchable-names-part-2)\n     * [Use explanatory variables](#use-explanatory-variables)\n     * [Avoid nesting too deeply and return early (part 1)](#avoid-nesting-too-deeply-and-return-early-part-1)\n     * [Avoid nesting too deeply and return early (part 2)](#avoid-nesting-too-deeply-and-return-early-part-2)\n     * [Avoid Mental Mapping](#avoid-mental-mapping)\n     * [Don't add unneeded context](#dont-add-unneeded-context)\n  3. [Comparison](#comparison)\n     * [Use identical comparison](#use-identical-comparison)\n     * [Null coalescing operator](#null-coalescing-operator)\n  4. [Functions](#functions)\n     * [Use default arguments instead of short circuiting or conditionals](#use-default-arguments-instead-of-short-circuiting-or-conditionals)\n     * [Function arguments (2 or fewer ideally)](#function-arguments-2-or-fewer-ideally)\n     * [Function names should say what they do](#function-names-should-say-what-they-do)\n     * [Functions should only be one level of abstraction](#functions-should-only-be-one-level-of-abstraction)\n     * [Don't use flags as function parameters](#dont-use-flags-as-function-parameters)\n     * [Avoid Side Effects](#avoid-side-effects)\n     * [Don't write to global functions](#dont-write-to-global-functions)\n     * [Don't use a Singleton pattern](#dont-use-a-singleton-pattern)\n     * [Encapsulate conditionals](#encapsulate-conditionals)\n     * [Avoid negative conditionals](#avoid-negative-conditionals)\n     * [Avoid conditionals](#avoid-conditionals)\n     * [Avoid type-checking (part 1)](#avoid-type-checking-part-1)\n     * [Avoid type-checking (part 2)](#avoid-type-checking-part-2)\n     * [Remove dead code](#remove-dead-code)\n  5. [Objects and Data Structures](#objects-and-data-structures)\n     * [Use object encapsulation](#use-object-encapsulation)\n     * [Make objects have private/protected members](#make-objects-have-privateprotected-members)\n  6. [Classes](#classes)\n     * [Prefer composition over inheritance](#prefer-composition-over-inheritance)\n     * [Avoid fluent interfaces](#avoid-fluent-interfaces)\n     * [Prefer final classes](#prefer-final-classes)\n  7. [SOLID](#solid)\n     * [Single Responsibility Principle (SRP)](#single-responsibility-principle-srp)\n     * [Open/Closed Principle (OCP)](#openclosed-principle-ocp)\n     * [Liskov Substitution Principle (LSP)](#liskov-substitution-principle-lsp)\n     * [Interface Segregation Principle (ISP)](#interface-segregation-principle-isp)\n     * [Dependency Inversion Principle (DIP)](#dependency-inversion-principle-dip)\n  8. [Don’t repeat yourself (DRY)](#dont-repeat-yourself-dry)\n  9. [Translations](#translations)\n\n## Introduction\n\nSoftware engineering principles, from Robert C. Martin's book\n[*Clean Code*](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882),\nadapted for PHP. This is not a style guide. It's a guide to producing\nreadable, reusable, and refactorable software in PHP.\n\nNot every principle herein has to be strictly followed, and even fewer will be universally\nagreed upon. These are guidelines and nothing more, but they are ones codified over many\nyears of collective experience by the authors of *Clean Code*.\n\nInspired from [clean-code-javascript](https://github.com/ryanmcdermott/clean-code-javascript).\n\nAlthough many developers still use PHP 5, most of the examples in this article only work with PHP 7.1+.\n\n## Variables\n\n### Use meaningful and pronounceable variable names\n\n**Bad:**\n\n```php\n$ymdstr = $moment->format('y-m-d');\n```\n\n**Good:**\n\n```php\n$currentDate = $moment->format('y-m-d');\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Use the same vocabulary for the same type of variable\n\n**Bad:**\n\n```php\ngetUserInfo();\ngetUserData();\ngetUserRecord();\ngetUserProfile();\n```\n\n**Good:**\n\n```php\ngetUser();\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Use searchable names (part 1)\n\nWe will read more code than we will ever write. It's important that the code we do write is\nreadable and searchable. By *not* naming variables that end up being meaningful for\nunderstanding our program, we hurt our readers.\nMake your names searchable.\n\n**Bad:**\n\n```php\n// What the heck is 448 for?\n$result = $serializer->serialize($data, 448);\n```\n\n**Good:**\n\n```php\n$json = $serializer->serialize($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);\n```\n\n### Use searchable names (part 2)\n\n**Bad:**\n\n```php\nclass User\n{\n    // What the heck is 7 for?\n    public $access = 7;\n}\n\n// What the heck is 4 for?\nif ($user->access & 4) {\n    // ...\n}\n\n// What's going on here?\n$user->access ^= 2;\n```\n\n**Good:**\n\n```php\nclass User\n{\n    public const ACCESS_READ = 1;\n\n    public const ACCESS_CREATE = 2;\n\n    public const ACCESS_UPDATE = 4;\n\n    public const ACCESS_DELETE = 8;\n\n    // User as default can read, create and update something\n    public $access = self::ACCESS_READ | self::ACCESS_CREATE | self::ACCESS_UPDATE;\n}\n\nif ($user->access & User::ACCESS_UPDATE) {\n    // do edit ...\n}\n\n// Deny access rights to create something\n$user->access ^= User::ACCESS_CREATE;\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Use explanatory variables\n\n**Bad:**\n\n```php\n$address = 'One Infinite Loop, Cupertino 95014';\n$cityZipCodeRegex = '/^[^,]+,\\s*(.+?)\\s*(\\d{5})$/';\npreg_match($cityZipCodeRegex, $address, $matches);\n\nsaveCityZipCode($matches[1], $matches[2]);\n```\n\n**Not bad:**\n\nIt's better, but we are still heavily dependent on regex.\n\n```php\n$address = 'One Infinite Loop, Cupertino 95014';\n$cityZipCodeRegex = '/^[^,]+,\\s*(.+?)\\s*(\\d{5})$/';\npreg_match($cityZipCodeRegex, $address, $matches);\n\n[, $city, $zipCode] = $matches;\nsaveCityZipCode($city, $zipCode);\n```\n\n**Good:**\n\nDecrease dependence on regex by naming subpatterns.\n\n```php\n$address = 'One Infinite Loop, Cupertino 95014';\n$cityZipCodeRegex = '/^[^,]+,\\s*(?<city>.+?)\\s*(?<zipCode>\\d{5})$/';\npreg_match($cityZipCodeRegex, $address, $matches);\n\nsaveCityZipCode($matches['city'], $matches['zipCode']);\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Avoid nesting too deeply and return early (part 1)\n\nToo many if-else statements can make your code hard to follow. Explicit is better\nthan implicit.\n\n**Bad:**\n\n```php\nfunction isShopOpen($day): bool\n{\n    if ($day) {\n        if (is_string($day)) {\n            $day = strtolower($day);\n            if ($day === 'friday') {\n                return true;\n            } elseif ($day === 'saturday') {\n                return true;\n            } elseif ($day === 'sunday') {\n                return true;\n            }\n            return false;\n        }\n        return false;\n    }\n    return false;\n}\n```\n\n**Good:**\n\n```php\nfunction isShopOpen(string $day): bool\n{\n    if (empty($day)) {\n        return false;\n    }\n\n    $openingDays = ['friday', 'saturday', 'sunday'];\n\n    return in_array(strtolower($day), $openingDays, true);\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Avoid nesting too deeply and return early (part 2)\n\n**Bad:**\n\n```php\nfunction fibonacci(int $n)\n{\n    if ($n < 50) {\n        if ($n !== 0) {\n            if ($n !== 1) {\n                return fibonacci($n - 1) + fibonacci($n - 2);\n            }\n            return 1;\n        }\n        return 0;\n    }\n    return 'Not supported';\n}\n```\n\n**Good:**\n\n```php\nfunction fibonacci(int $n): int\n{\n    if ($n === 0 || $n === 1) {\n        return $n;\n    }\n\n    if ($n >= 50) {\n        throw new Exception('Not supported');\n    }\n\n    return fibonacci($n - 1) + fibonacci($n - 2);\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Avoid Mental Mapping\n\nDon’t force the reader of your code to translate what the variable means.\nExplicit is better than implicit.\n\n**Bad:**\n\n```php\n$l = ['Austin', 'New York', 'San Francisco'];\n\nfor ($i = 0; $i < count($l); $i++) {\n    $li = $l[$i];\n    doStuff();\n    doSomeOtherStuff();\n    // ...\n    // ...\n    // ...\n    // Wait, what is `$li` for again?\n    dispatch($li);\n}\n```\n\n**Good:**\n\n```php\n$locations = ['Austin', 'New York', 'San Francisco'];\n\nforeach ($locations as $location) {\n    doStuff();\n    doSomeOtherStuff();\n    // ...\n    // ...\n    // ...\n    dispatch($location);\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Don't add unneeded context\n\nIf your class/object name tells you something, don't repeat that in your\nvariable name.\n\n**Bad:**\n\n```php\nclass Car\n{\n    public $carMake;\n\n    public $carModel;\n\n    public $carColor;\n\n    //...\n}\n```\n\n**Good:**\n\n```php\nclass Car\n{\n    public $make;\n\n    public $model;\n\n    public $color;\n\n    //...\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Comparison\n\n### Use [identical comparison](http://php.net/manual/en/language.operators.comparison.php)\n\n**Not good:**\n\nThe simple comparison will convert the string into an integer.\n\n```php\n$a = '42';\n$b = 42;\n\nif ($a != $b) {\n    // The expression will always pass\n}\n```\n\nThe comparison `$a != $b` returns `FALSE` but in fact it's `TRUE`!\nThe string `42` is different than the integer `42`.\n\n**Good:**\n\nThe identical comparison will compare type and value.\n\n```php\n$a = '42';\n$b = 42;\n\nif ($a !== $b) {\n    // The expression is verified\n}\n```\n\nThe comparison `$a !== $b` returns `TRUE`.\n\n**[⬆ back to top](#table-of-contents)**\n\n### Null coalescing operator\n\nNull coalescing is a new operator [introduced in PHP 7](https://www.php.net/manual/en/migration70.new-features.php). The null coalescing operator `??` has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with `isset()`. It returns its first operand if it exists and is not `null`; otherwise it returns its second operand.\n\n**Bad:**\n\n```php\nif (isset($_GET['name'])) {\n    $name = $_GET['name'];\n} elseif (isset($_POST['name'])) {\n    $name = $_POST['name'];\n} else {\n    $name = 'nobody';\n}\n```\n\n**Good:**\n```php\n$name = $_GET['name'] ?? $_POST['name'] ?? 'nobody';\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Functions\n\n### Use default arguments instead of short circuiting or conditionals\n\n**Not good:**\n\nThis is not good because `$breweryName` can be `NULL`.\n\n```php\nfunction createMicrobrewery($breweryName = 'Hipster Brew Co.'): void\n{\n    // ...\n}\n```\n\n**Not bad:**\n\nThis opinion is more understandable than the previous version, but it better controls the value of the variable.\n\n```php\nfunction createMicrobrewery($name = null): void\n{\n    $breweryName = $name ?: 'Hipster Brew Co.';\n    // ...\n}\n```\n\n**Good:**\n\n You can use [type hinting](https://www.php.net/manual/en/language.types.declarations.php) and be sure that the `$breweryName` will not be `NULL`.\n\n```php\nfunction createMicrobrewery(string $breweryName = 'Hipster Brew Co.'): void\n{\n    // ...\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Function arguments (2 or fewer ideally)\n\nLimiting the amount of function parameters is incredibly important because it makes\ntesting your function easier. Having more than three leads to a combinatorial explosion\nwhere you have to test tons of different cases with each separate argument.\n\nZero arguments is the ideal case. One or two arguments is ok, and three should be avoided.\nAnything more than that should be consolidated. Usually, if you have more than two\narguments then your function is trying to do too much. In cases where it's not, most\nof the time a higher-level object will suffice as an argument.\n\n**Bad:**\n\n```php\nclass Questionnaire\n{\n    public function __construct(\n        string $firstname,\n        string $lastname,\n        string $patronymic,\n        string $region,\n        string $district,\n        string $city,\n        string $phone,\n        string $email\n    ) {\n        // ...\n    }\n}\n```\n\n**Good:**\n\n```php\nclass Name\n{\n    private $firstname;\n\n    private $lastname;\n\n    private $patronymic;\n\n    public function __construct(string $firstname, string $lastname, string $patronymic)\n    {\n        $this->firstname = $firstname;\n        $this->lastname = $lastname;\n        $this->patronymic = $patronymic;\n    }\n\n    // getters ...\n}\n\nclass City\n{\n    private $region;\n\n    private $district;\n\n    private $city;\n\n    public function __construct(string $region, string $district, string $city)\n    {\n        $this->region = $region;\n        $this->district = $district;\n        $this->city = $city;\n    }\n\n    // getters ...\n}\n\nclass Contact\n{\n    private $phone;\n\n    private $email;\n\n    public function __construct(string $phone, string $email)\n    {\n        $this->phone = $phone;\n        $this->email = $email;\n    }\n\n    // getters ...\n}\n\nclass Questionnaire\n{\n    public function __construct(Name $name, City $city, Contact $contact)\n    {\n        // ...\n    }\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Function names should say what they do\n\n**Bad:**\n\n```php\nclass Email\n{\n    //...\n\n    public function handle(): void\n    {\n        mail($this->to, $this->subject, $this->body);\n    }\n}\n\n$message = new Email(...);\n// What is this? A handle for the message? Are we writing to a file now?\n$message->handle();\n```\n\n**Good:**\n\n```php\nclass Email\n{\n    //...\n\n    public function send(): void\n    {\n        mail($this->to, $this->subject, $this->body);\n    }\n}\n\n$message = new Email(...);\n// Clear and obvious\n$message->send();\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Functions should only be one level of abstraction\n\nWhen you have more than one level of abstraction your function is usually\ndoing too much. Splitting up functions leads to reusability and easier\ntesting.\n\n**Bad:**\n\n```php\nfunction parseBetterPHPAlternative(string $code): void\n{\n    $regexes = [\n        // ...\n    ];\n\n    $statements = explode(' ', $code);\n    $tokens = [];\n    foreach ($regexes as $regex) {\n        foreach ($statements as $statement) {\n            // ...\n        }\n    }\n\n    $ast = [];\n    foreach ($tokens as $token) {\n        // lex...\n    }\n\n    foreach ($ast as $node) {\n        // parse...\n    }\n}\n```\n\n**Bad too:**\n\nWe have carried out some of the functionality, but the `parseBetterPHPAlternative()` function is still very complex and not testable.\n\n```php\nfunction tokenize(string $code): array\n{\n    $regexes = [\n        // ...\n    ];\n\n    $statements = explode(' ', $code);\n    $tokens = [];\n    foreach ($regexes as $regex) {\n        foreach ($statements as $statement) {\n            $tokens[] = /* ... */;\n        }\n    }\n\n    return $tokens;\n}\n\nfunction lexer(array $tokens): array\n{\n    $ast = [];\n    foreach ($tokens as $token) {\n        $ast[] = /* ... */;\n    }\n\n    return $ast;\n}\n\nfunction parseBetterPHPAlternative(string $code): void\n{\n    $tokens = tokenize($code);\n    $ast = lexer($tokens);\n    foreach ($ast as $node) {\n        // parse...\n    }\n}\n```\n\n**Good:**\n\nThe best solution is move out the dependencies of `parseBetterPHPAlternative()` function.\n\n```php\nclass Tokenizer\n{\n    public function tokenize(string $code): array\n    {\n        $regexes = [\n            // ...\n        ];\n\n        $statements = explode(' ', $code);\n        $tokens = [];\n        foreach ($regexes as $regex) {\n            foreach ($statements as $statement) {\n                $tokens[] = /* ... */;\n            }\n        }\n\n        return $tokens;\n    }\n}\n\nclass Lexer\n{\n    public function lexify(array $tokens): array\n    {\n        $ast = [];\n        foreach ($tokens as $token) {\n            $ast[] = /* ... */;\n        }\n\n        return $ast;\n    }\n}\n\nclass BetterPHPAlternative\n{\n    private $tokenizer;\n    private $lexer;\n\n    public function __construct(Tokenizer $tokenizer, Lexer $lexer)\n    {\n        $this->tokenizer = $tokenizer;\n        $this->lexer = $lexer;\n    }\n\n    public function parse(string $code): void\n    {\n        $tokens = $this->tokenizer->tokenize($code);\n        $ast = $this->lexer->lexify($tokens);\n        foreach ($ast as $node) {\n            // parse...\n        }\n    }\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Don't use flags as function parameters\n\nFlags tell your user that this function does more than one thing. Functions should\ndo one thing. Split out your functions if they are following different code paths\nbased on a boolean.\n\n**Bad:**\n\n```php\nfunction createFile(string $name, bool $temp = false): void\n{\n    if ($temp) {\n        touch('./temp/' . $name);\n    } else {\n        touch($name);\n    }\n}\n```\n\n**Good:**\n\n```php\nfunction createFile(string $name): void\n{\n    touch($name);\n}\n\nfunction createTempFile(string $name): void\n{\n    touch('./temp/' . $name);\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Avoid Side Effects\n\nA function produces a side effect if it does anything other than take a value in and\nreturn another value or values. A side effect could be writing to a file, modifying\nsome global variable, or accidentally wiring all your money to a stranger.\n\nNow, you do need to have side effects in a program on occasion. Like the previous\nexample, you might need to write to a file. What you want to do is to centralize where\nyou are doing this. Don't have several functions and classes that write to a particular\nfile. Have one service that does it. One and only one.\n\nThe main point is to avoid common pitfalls like sharing state between objects without\nany structure, using mutable data types that can be written to by anything, and not\ncentralizing where your side effects occur. If you can do this, you will be happier\nthan the vast majority of other programmers.\n\n**Bad:**\n\n```php\n// Global variable referenced by following function.\n// If we had another function that used this name, now it'd be an array and it could break it.\n$name = 'Ryan McDermott';\n\nfunction splitIntoFirstAndLastName(): void\n{\n    global $name;\n\n    $name = explode(' ', $name);\n}\n\nsplitIntoFirstAndLastName();\n\nvar_dump($name);\n// ['Ryan', 'McDermott'];\n```\n\n**Good:**\n\n```php\nfunction splitIntoFirstAndLastName(string $name): array\n{\n    return explode(' ', $name);\n}\n\n$name = 'Ryan McDermott';\n$newName = splitIntoFirstAndLastName($name);\n\nvar_dump($name);\n// 'Ryan McDermott';\n\nvar_dump($newName);\n// ['Ryan', 'McDermott'];\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Don't write to global functions\n\nPolluting globals is a bad practice in many languages because you could clash with another\nlibrary and the user of your API would be none-the-wiser until they get an exception in\nproduction. Let's think about an example: what if you wanted to have configuration array?\nYou could write global function like `config()`, but it could clash with another library\nthat tried to do the same thing.\n\n**Bad:**\n\n```php\nfunction config(): array\n{\n    return [\n        'foo' => 'bar',\n    ];\n}\n```\n\n**Good:**\n\n```php\nclass Configuration\n{\n    private $configuration = [];\n\n    public function __construct(array $configuration)\n    {\n        $this->configuration = $configuration;\n    }\n\n    public function get(string $key): ?string\n    {\n        // null coalescing operator\n        return $this->configuration[$key] ?? null;\n    }\n}\n```\n\nLoad configuration and create instance of `Configuration` class\n\n```php\n$configuration = new Configuration([\n    'foo' => 'bar',\n]);\n```\n\nAnd now you must use instance of `Configuration` in your application.\n\n**[⬆ back to top](#table-of-contents)**\n\n### Don't use a Singleton pattern\n\nSingleton is an [anti-pattern](https://en.wikipedia.org/wiki/Singleton_pattern). Paraphrased from Brian Button:\n 1. They are generally used as a **global instance**, why is that so bad? Because **you hide the dependencies** of your application in your code, instead of exposing them through the interfaces. Making something global to avoid passing it around is a [code smell](https://en.wikipedia.org/wiki/Code_smell).\n 2. They violate the [single responsibility principle](#single-responsibility-principle-srp): by virtue of the fact that **they control their own creation and lifecycle**.\n 3. They inherently cause code to be tightly [coupled](https://en.wikipedia.org/wiki/Coupling_%28computer_programming%29). This makes faking them out under **test rather difficult** in many cases.\n 4. They carry state around for the lifetime of the application. Another hit to testing since **you can end up with a situation where tests need to be ordered** which is a big no for unit tests. Why? Because each unit test should be independent from the other.\n\nThere is also very good thoughts by [Misko Hevery](http://misko.hevery.com/about/) about the [root of problem](http://misko.hevery.com/2008/08/25/root-cause-of-singletons/).\n\n**Bad:**\n\n```php\nclass DBConnection\n{\n    private static $instance;\n\n    private function __construct(string $dsn)\n    {\n        // ...\n    }\n\n    public static function getInstance(): self\n    {\n        if (self::$instance === null) {\n            self::$instance = new self();\n        }\n\n        return self::$instance;\n    }\n\n    // ...\n}\n\n$singleton = DBConnection::getInstance();\n```\n\n**Good:**\n\n```php\nclass DBConnection\n{\n    public function __construct(string $dsn)\n    {\n        // ...\n    }\n\n    // ...\n}\n```\n\nCreate instance of `DBConnection` class and configure it with [DSN](http://php.net/manual/en/pdo.construct.php#refsect1-pdo.construct-parameters).\n\n```php\n$connection = new DBConnection($dsn);\n```\n\nAnd now you must use instance of `DBConnection` in your application.\n\n**[⬆ back to top](#table-of-contents)**\n\n### Encapsulate conditionals\n\n**Bad:**\n\n```php\nif ($article->state === 'published') {\n    // ...\n}\n```\n\n**Good:**\n\n```php\nif ($article->isPublished()) {\n    // ...\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Avoid negative conditionals\n\n**Bad:**\n\n```php\nfunction isDOMNodeNotPresent(DOMNode $node): bool\n{\n    // ...\n}\n\nif (! isDOMNodeNotPresent($node)) {\n    // ...\n}\n```\n\n**Good:**\n\n```php\nfunction isDOMNodePresent(DOMNode $node): bool\n{\n    // ...\n}\n\nif (isDOMNodePresent($node)) {\n    // ...\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Avoid conditionals\n\nThis seems like an impossible task. Upon first hearing this, most people say,\n\"how am I supposed to do anything without an `if` statement?\" The answer is that\nyou can use polymorphism to achieve the same task in many cases. The second\nquestion is usually, \"well that's great but why would I want to do that?\" The\nanswer is a previous clean code concept we learned: a function should only do\none thing. When you have classes and functions that have `if` statements, you\nare telling your user that your function does more than one thing. Remember,\njust do one thing.\n\n**Bad:**\n\n```php\nclass Airplane\n{\n    // ...\n\n    public function getCruisingAltitude(): int\n    {\n        switch ($this->type) {\n            case '777':\n                return $this->getMaxAltitude() - $this->getPassengerCount();\n            case 'Air Force One':\n                return $this->getMaxAltitude();\n            case 'Cessna':\n                return $this->getMaxAltitude() - $this->getFuelExpenditure();\n        }\n    }\n}\n```\n\n**Good:**\n\n```php\ninterface Airplane\n{\n    // ...\n\n    public function getCruisingAltitude(): int;\n}\n\nclass Boeing777 implements Airplane\n{\n    // ...\n\n    public function getCruisingAltitude(): int\n    {\n        return $this->getMaxAltitude() - $this->getPassengerCount();\n    }\n}\n\nclass AirForceOne implements Airplane\n{\n    // ...\n\n    public function getCruisingAltitude(): int\n    {\n        return $this->getMaxAltitude();\n    }\n}\n\nclass Cessna implements Airplane\n{\n    // ...\n\n    public function getCruisingAltitude(): int\n    {\n        return $this->getMaxAltitude() - $this->getFuelExpenditure();\n    }\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Avoid type-checking (part 1)\n\nPHP is untyped, which means your functions can take any type of argument.\nSometimes you are bitten by this freedom and it becomes tempting to do\ntype-checking in your functions. There are many ways to avoid having to do this.\nThe first thing to consider is consistent APIs.\n\n**Bad:**\n\n```php\nfunction travelToTexas($vehicle): void\n{\n    if ($vehicle instanceof Bicycle) {\n        $vehicle->pedalTo(new Location('texas'));\n    } elseif ($vehicle instanceof Car) {\n        $vehicle->driveTo(new Location('texas'));\n    }\n}\n```\n\n**Good:**\n\n```php\nfunction travelToTexas(Vehicle $vehicle): void\n{\n    $vehicle->travelTo(new Location('texas'));\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Avoid type-checking (part 2)\n\nIf you are working with basic primitive values like strings, integers, and arrays,\nand you use PHP 7+ and you can't use polymorphism but you still feel the need to\ntype-check, you should consider\n[type declaration](https://www.php.net/manual/en/language.types.declarations.php)\nor strict mode. It provides you with static typing on top of standard PHP syntax.\nThe problem with manually type-checking is that doing it will require so much\nextra verbiage that the faux \"type-safety\" you get doesn't make up for the lost\nreadability. Keep your PHP clean, write good tests, and have good code reviews.\nOtherwise, do all of that but with PHP strict type declaration or strict mode.\n\n**Bad:**\n\n```php\nfunction combine($val1, $val2): int\n{\n    if (! is_numeric($val1) || ! is_numeric($val2)) {\n        throw new Exception('Must be of type Number');\n    }\n\n    return $val1 + $val2;\n}\n```\n\n**Good:**\n\n```php\nfunction combine(int $val1, int $val2): int\n{\n    return $val1 + $val2;\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Remove dead code\n\nDead code is just as bad as duplicate code. There's no reason to keep it in\nyour codebase. If it's not being called, get rid of it! It will still be safe\nin your version history if you still need it.\n\n**Bad:**\n\n```php\nfunction oldRequestModule(string $url): void\n{\n    // ...\n}\n\nfunction newRequestModule(string $url): void\n{\n    // ...\n}\n\n$request = newRequestModule($requestUrl);\ninventoryTracker('apples', $request, 'www.inventory-awesome.io');\n```\n\n**Good:**\n\n```php\nfunction requestModule(string $url): void\n{\n    // ...\n}\n\n$request = requestModule($requestUrl);\ninventoryTracker('apples', $request, 'www.inventory-awesome.io');\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n\n## Objects and Data Structures\n\n### Use object encapsulation\n\nIn PHP you can set `public`, `protected` and `private` keywords for methods.\nUsing it, you can control properties modification on an object.\n\n* When you want to do more beyond getting an object property, you don't have\nto look up and change every accessor in your codebase.\n* Makes adding validation simple when doing a `set`.\n* Encapsulates the internal representation.\n* Easy to add logging and error handling when getting and setting.\n* Inheriting this class, you can override default functionality.\n* You can lazy load your object's properties, let's say getting it from a\nserver.\n\nAdditionally, this is part of [Open/Closed](#openclosed-principle-ocp) principle.\n\n**Bad:**\n\n```php\nclass BankAccount\n{\n    public $balance = 1000;\n}\n\n$bankAccount = new BankAccount();\n\n// Buy shoes...\n$bankAccount->balance -= 100;\n```\n\n**Good:**\n\n```php\nclass BankAccount\n{\n    private $balance;\n\n    public function __construct(int $balance = 1000)\n    {\n      $this->balance = $balance;\n    }\n\n    public function withdraw(int $amount): void\n    {\n        if ($amount > $this->balance) {\n            throw new \\Exception('Amount greater than available balance.');\n        }\n\n        $this->balance -= $amount;\n    }\n\n    public function deposit(int $amount): void\n    {\n        $this->balance += $amount;\n    }\n\n    public function getBalance(): int\n    {\n        return $this->balance;\n    }\n}\n\n$bankAccount = new BankAccount();\n\n// Buy shoes...\n$bankAccount->withdraw($shoesPrice);\n\n// Get balance\n$balance = $bankAccount->getBalance();\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Make objects have private/protected members\n\n* `public` methods and properties are most dangerous for changes, because some outside code may easily rely on them and you can't control what code relies on them. **Modifications in class are dangerous for all users of class.**\n* `protected` modifier are as dangerous as public, because they are available in scope of any child class. This effectively means that difference between public and protected is only in access mechanism, but encapsulation guarantee remains the same. **Modifications in class are dangerous for all descendant classes.**\n* `private` modifier guarantees that code is **dangerous to modify only in boundaries of single class** (you are safe for modifications and you won't have [Jenga effect](http://www.urbandictionary.com/define.php?term=Jengaphobia&defid=2494196)).\n\nTherefore, use `private` by default and `public/protected` when you need to provide access for external classes.\n\nFor more information you can read the [blog post](http://fabien.potencier.org/pragmatism-over-theory-protected-vs-private.html) on this topic written by [Fabien Potencier](https://github.com/fabpot).\n\n**Bad:**\n\n```php\nclass Employee\n{\n    public $name;\n\n    public function __construct(string $name)\n    {\n        $this->name = $name;\n    }\n}\n\n$employee = new Employee('John Doe');\n// Employee name: John Doe\necho 'Employee name: ' . $employee->name;\n```\n\n**Good:**\n\n```php\nclass Employee\n{\n    private $name;\n\n    public function __construct(string $name)\n    {\n        $this->name = $name;\n    }\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n}\n\n$employee = new Employee('John Doe');\n// Employee name: John Doe\necho 'Employee name: ' . $employee->getName();\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Classes\n\n### Prefer composition over inheritance\n\nAs stated famously in [*Design Patterns*](https://en.wikipedia.org/wiki/Design_Patterns) by the Gang of Four,\nyou should prefer composition over inheritance where you can. There are lots of\ngood reasons to use inheritance and lots of good reasons to use composition.\nThe main point for this maxim is that if your mind instinctively goes for\ninheritance, try to think if composition could model your problem better. In some\ncases it can.\n\nYou might be wondering then, \"when should I use inheritance?\" It\ndepends on your problem at hand, but this is a decent list of when inheritance\nmakes more sense than composition:\n\n1. Your inheritance represents an \"is-a\" relationship and not a \"has-a\"\nrelationship (Human->Animal vs. User->UserDetails).\n2. You can reuse code from the base classes (Humans can move like all animals).\n3. You want to make global changes to derived classes by changing a base class.\n(Change the caloric expenditure of all animals when they move).\n\n**Bad:**\n\n```php\nclass Employee\n{\n    private $name;\n\n    private $email;\n\n    public function __construct(string $name, string $email)\n    {\n        $this->name = $name;\n        $this->email = $email;\n    }\n\n    // ...\n}\n\n// Bad because Employees \"have\" tax data.\n// EmployeeTaxData is not a type of Employee\n\nclass EmployeeTaxData extends Employee\n{\n    private $ssn;\n\n    private $salary;\n\n    public function __construct(string $name, string $email, string $ssn, string $salary)\n    {\n        parent::__construct($name, $email);\n\n        $this->ssn = $ssn;\n        $this->salary = $salary;\n    }\n\n    // ...\n}\n```\n\n**Good:**\n\n```php\nclass EmployeeTaxData\n{\n    private $ssn;\n\n    private $salary;\n\n    public function __construct(string $ssn, string $salary)\n    {\n        $this->ssn = $ssn;\n        $this->salary = $salary;\n    }\n\n    // ...\n}\n\nclass Employee\n{\n    private $name;\n\n    private $email;\n\n    private $taxData;\n\n    public function __construct(string $name, string $email)\n    {\n        $this->name = $name;\n        $this->email = $email;\n    }\n\n    public function setTaxData(EmployeeTaxData $taxData): void\n    {\n        $this->taxData = $taxData;\n    }\n\n    // ...\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Avoid fluent interfaces\n\nA [Fluent interface](https://en.wikipedia.org/wiki/Fluent_interface) is an object\noriented API that aims to improve the readability of the source code by using\n[Method chaining](https://en.wikipedia.org/wiki/Method_chaining).\n\nWhile there can be some contexts, frequently builder objects, where this\npattern reduces the verbosity of the code (for example the [PHPUnit Mock Builder](https://phpunit.de/manual/current/en/test-doubles.html)\nor the [Doctrine Query Builder](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/query-builder.html)),\nmore often it comes at some costs:\n\n1. Breaks [Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_%28object-oriented_programming%29).\n2. Breaks [Decorators](https://en.wikipedia.org/wiki/Decorator_pattern).\n3. Is harder to [mock](https://en.wikipedia.org/wiki/Mock_object) in a test suite.\n4. Makes diffs of commits harder to read.\n\nFor more information you can read the full [blog post](https://ocramius.github.io/blog/fluent-interfaces-are-evil/)\non this topic written by [Marco Pivetta](https://github.com/Ocramius).\n\n**Bad:**\n\n```php\nclass Car\n{\n    private $make = 'Honda';\n\n    private $model = 'Accord';\n\n    private $color = 'white';\n\n    public function setMake(string $make): self\n    {\n        $this->make = $make;\n\n        // NOTE: Returning this for chaining\n        return $this;\n    }\n\n    public function setModel(string $model): self\n    {\n        $this->model = $model;\n\n        // NOTE: Returning this for chaining\n        return $this;\n    }\n\n    public function setColor(string $color): self\n    {\n        $this->color = $color;\n\n        // NOTE: Returning this for chaining\n        return $this;\n    }\n\n    public function dump(): void\n    {\n        var_dump($this->make, $this->model, $this->color);\n    }\n}\n\n$car = (new Car())\n    ->setColor('pink')\n    ->setMake('Ford')\n    ->setModel('F-150')\n    ->dump();\n```\n\n**Good:**\n\n```php\nclass Car\n{\n    private $make = 'Honda';\n\n    private $model = 'Accord';\n\n    private $color = 'white';\n\n    public function setMake(string $make): void\n    {\n        $this->make = $make;\n    }\n\n    public function setModel(string $model): void\n    {\n        $this->model = $model;\n    }\n\n    public function setColor(string $color): void\n    {\n        $this->color = $color;\n    }\n\n    public function dump(): void\n    {\n        var_dump($this->make, $this->model, $this->color);\n    }\n}\n\n$car = new Car();\n$car->setColor('pink');\n$car->setMake('Ford');\n$car->setModel('F-150');\n$car->dump();\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Prefer final classes\n\nThe `final` keyword should be used whenever possible:\n\n1. It prevents an uncontrolled inheritance chain.\n2. It encourages [composition](#prefer-composition-over-inheritance).\n3. It encourages the [Single Responsibility Principle](#single-responsibility-principle-srp).\n4. It encourages developers to use your public methods instead of extending the class to get access to protected ones.\n5. It allows you to change your code without breaking applications that use your class.\n\nThe only condition is that your class should implement an interface and no other public methods are defined.\n\nFor more informations you can read [the blog post](https://ocramius.github.io/blog/when-to-declare-classes-final/) on this topic written by [Marco Pivetta (Ocramius)](https://ocramius.github.io/).\n\n**Bad:**\n\n```php\nfinal class Car\n{\n    private $color;\n\n    public function __construct($color)\n    {\n        $this->color = $color;\n    }\n\n    /**\n     * @return string The color of the vehicle\n     */\n    public function getColor()\n    {\n        return $this->color;\n    }\n}\n```\n\n**Good:**\n\n```php\ninterface Vehicle\n{\n    /**\n     * @return string The color of the vehicle\n     */\n    public function getColor();\n}\n\nfinal class Car implements Vehicle\n{\n    private $color;\n\n    public function __construct($color)\n    {\n        $this->color = $color;\n    }\n\n    public function getColor()\n    {\n        return $this->color;\n    }\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n## SOLID\n\n**SOLID** is the mnemonic acronym introduced by Michael Feathers for the first five principles named by Robert Martin, which meant five basic principles of object-oriented programming and design.\n\n * [S: Single Responsibility Principle (SRP)](#single-responsibility-principle-srp)\n * [O: Open/Closed Principle (OCP)](#openclosed-principle-ocp)\n * [L: Liskov Substitution Principle (LSP)](#liskov-substitution-principle-lsp)\n * [I: Interface Segregation Principle (ISP)](#interface-segregation-principle-isp)\n * [D: Dependency Inversion Principle (DIP)](#dependency-inversion-principle-dip)\n\n### Single Responsibility Principle (SRP)\n\nAs stated in Clean Code, \"There should never be more than one reason for a class\nto change\". It's tempting to jam-pack a class with a lot of functionality, like\nwhen you can only take one suitcase on your flight. The issue with this is\nthat your class won't be conceptually cohesive and it will give it many reasons\nto change. Minimizing the amount of times you need to change a class is important.\nIt's important because if too much functionality is in one class and you modify a piece of it,\nit can be difficult to understand how that will affect other dependent modules in\nyour codebase.\n\n**Bad:**\n\n```php\nclass UserSettings\n{\n    private $user;\n\n    public function __construct(User $user)\n    {\n        $this->user = $user;\n    }\n\n    public function changeSettings(array $settings): void\n    {\n        if ($this->verifyCredentials()) {\n            // ...\n        }\n    }\n\n    private function verifyCredentials(): bool\n    {\n        // ...\n    }\n}\n```\n\n**Good:**\n\n```php\nclass UserAuth\n{\n    private $user;\n\n    public function __construct(User $user)\n    {\n        $this->user = $user;\n    }\n\n    public function verifyCredentials(): bool\n    {\n        // ...\n    }\n}\n\nclass UserSettings\n{\n    private $user;\n\n    private $auth;\n\n    public function __construct(User $user)\n    {\n        $this->user = $user;\n        $this->auth = new UserAuth($user);\n    }\n\n    public function changeSettings(array $settings): void\n    {\n        if ($this->auth->verifyCredentials()) {\n            // ...\n        }\n    }\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Open/Closed Principle (OCP)\n\nAs stated by Bertrand Meyer, \"software entities (classes, modules, functions,\netc.) should be open for extension, but closed for modification.\" What does that\nmean though? This principle basically states that you should allow users to\nadd new functionalities without changing existing code.\n\n**Bad:**\n\n```php\nabstract class Adapter\n{\n    protected $name;\n\n    public function getName(): string\n    {\n        return $this->name;\n    }\n}\n\nclass AjaxAdapter extends Adapter\n{\n    public function __construct()\n    {\n        parent::__construct();\n\n        $this->name = 'ajaxAdapter';\n    }\n}\n\nclass NodeAdapter extends Adapter\n{\n    public function __construct()\n    {\n        parent::__construct();\n\n        $this->name = 'nodeAdapter';\n    }\n}\n\nclass HttpRequester\n{\n    private $adapter;\n\n    public function __construct(Adapter $adapter)\n    {\n        $this->adapter = $adapter;\n    }\n\n    public function fetch(string $url): Promise\n    {\n        $adapterName = $this->adapter->getName();\n\n        if ($adapterName === 'ajaxAdapter') {\n            return $this->makeAjaxCall($url);\n        } elseif ($adapterName === 'httpNodeAdapter') {\n            return $this->makeHttpCall($url);\n        }\n    }\n\n    private function makeAjaxCall(string $url): Promise\n    {\n        // request and return promise\n    }\n\n    private function makeHttpCall(string $url): Promise\n    {\n        // request and return promise\n    }\n}\n```\n\n**Good:**\n\n```php\ninterface Adapter\n{\n    public function request(string $url): Promise;\n}\n\nclass AjaxAdapter implements Adapter\n{\n    public function request(string $url): Promise\n    {\n        // request and return promise\n    }\n}\n\nclass NodeAdapter implements Adapter\n{\n    public function request(string $url): Promise\n    {\n        // request and return promise\n    }\n}\n\nclass HttpRequester\n{\n    private $adapter;\n\n    public function __construct(Adapter $adapter)\n    {\n        $this->adapter = $adapter;\n    }\n\n    public function fetch(string $url): Promise\n    {\n        return $this->adapter->request($url);\n    }\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Liskov Substitution Principle (LSP)\n\nThis is a scary term for a very simple concept. It's formally defined as \"If S\nis a subtype of T, then objects of type T may be replaced with objects of type S\n(i.e., objects of type S may substitute objects of type T) without altering any\nof the desirable properties of that program (correctness, task performed,\netc.).\" That's an even scarier definition.\n\nThe best explanation for this is if you have a parent class and a child class,\nthen the base class and child class can be used interchangeably without getting\nincorrect results. This might still be confusing, so let's take a look at the\nclassic Square-Rectangle example. Mathematically, a square is a rectangle, but\nif you model it using the \"is-a\" relationship via inheritance, you quickly\nget into trouble.\n\n**Bad:**\n\n```php\nclass Rectangle\n{\n    protected $width = 0;\n\n    protected $height = 0;\n\n    public function setWidth(int $width): void\n    {\n        $this->width = $width;\n    }\n\n    public function setHeight(int $height): void\n    {\n        $this->height = $height;\n    }\n\n    public function getArea(): int\n    {\n        return $this->width * $this->height;\n    }\n}\n\nclass Square extends Rectangle\n{\n    public function setWidth(int $width): void\n    {\n        $this->width = $this->height = $width;\n    }\n\n    public function setHeight(int $height): void\n    {\n        $this->width = $this->height = $height;\n    }\n}\n\nfunction printArea(Rectangle $rectangle): void\n{\n    $rectangle->setWidth(4);\n    $rectangle->setHeight(5);\n\n    // BAD: Will return 25 for Square. Should be 20.\n    echo sprintf('%s has area %d.', get_class($rectangle), $rectangle->getArea()) . PHP_EOL;\n}\n\n$rectangles = [new Rectangle(), new Square()];\n\nforeach ($rectangles as $rectangle) {\n    printArea($rectangle);\n}\n```\n\n**Good:**\n\nThe best way is separate the quadrangles and allocation of a more general subtype for both shapes.\n\nDespite the apparent similarity of the square and the rectangle, they are different.\nA square has much in common with a rhombus, and a rectangle with a parallelogram, but they are not subtypes.\nA square, a rectangle, a rhombus and a parallelogram are separate shapes with their own properties, albeit similar.\n\n```php\ninterface Shape\n{\n    public function getArea(): int;\n}\n\nclass Rectangle implements Shape\n{\n    private $width = 0;\n    private $height = 0;\n\n    public function __construct(int $width, int $height)\n    {\n        $this->width = $width;\n        $this->height = $height;\n    }\n\n    public function getArea(): int\n    {\n        return $this->width * $this->height;\n    }\n}\n\nclass Square implements Shape\n{\n    private $length = 0;\n\n    public function __construct(int $length)\n    {\n        $this->length = $length;\n    }\n\n    public function getArea(): int\n    {\n        return $this->length ** 2;\n    }\n}\n\nfunction printArea(Shape $shape): void\n{\n    echo sprintf('%s has area %d.', get_class($shape), $shape->getArea()).PHP_EOL;\n}\n\n$shapes = [new Rectangle(4, 5), new Square(5)];\n\nforeach ($shapes as $shape) {\n    printArea($shape);\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Interface Segregation Principle (ISP)\n\nISP states that \"Clients should not be forced to depend upon interfaces that\nthey do not use.\"\n\nA good example to look at that demonstrates this principle is for\nclasses that require large settings objects. Not requiring clients to set up\nhuge amounts of options is beneficial, because most of the time they won't need\nall of the settings. Making them optional helps prevent having a \"fat interface\".\n\n**Bad:**\n\n```php\ninterface Employee\n{\n    public function work(): void;\n\n    public function eat(): void;\n}\n\nclass HumanEmployee implements Employee\n{\n    public function work(): void\n    {\n        // ....working\n    }\n\n    public function eat(): void\n    {\n        // ...... eating in lunch break\n    }\n}\n\nclass RobotEmployee implements Employee\n{\n    public function work(): void\n    {\n        //.... working much more\n    }\n\n    public function eat(): void\n    {\n        //.... robot can't eat, but it must implement this method\n    }\n}\n```\n\n**Good:**\n\nNot every worker is an employee, but every employee is a worker.\n\n```php\ninterface Workable\n{\n    public function work(): void;\n}\n\ninterface Feedable\n{\n    public function eat(): void;\n}\n\ninterface Employee extends Feedable, Workable\n{\n}\n\nclass HumanEmployee implements Employee\n{\n    public function work(): void\n    {\n        // ....working\n    }\n\n    public function eat(): void\n    {\n        //.... eating in lunch break\n    }\n}\n\n// robot can only work\nclass RobotEmployee implements Workable\n{\n    public function work(): void\n    {\n        // ....working\n    }\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n### Dependency Inversion Principle (DIP)\n\nThis principle states two essential things:\n1. High-level modules should not depend on low-level modules. Both should\ndepend on abstractions.\n2. Abstractions should not depend upon details. Details should depend on\nabstractions.\n\nThis can be hard to understand at first, but if you've worked with PHP frameworks (like Symfony), you've seen an implementation of this principle in the form of Dependency\nInjection (DI). While they are not identical concepts, DIP keeps high-level\nmodules from knowing the details of its low-level modules and setting them up.\nIt can accomplish this through DI. A huge benefit of this is that it reduces\nthe coupling between modules. Coupling is a very bad development pattern because\nit makes your code hard to refactor.\n\n**Bad:**\n\n```php\nclass Employee\n{\n    public function work(): void\n    {\n        // ....working\n    }\n}\n\nclass Robot extends Employee\n{\n    public function work(): void\n    {\n        //.... working much more\n    }\n}\n\nclass Manager\n{\n    private $employee;\n\n    public function __construct(Employee $employee)\n    {\n        $this->employee = $employee;\n    }\n\n    public function manage(): void\n    {\n        $this->employee->work();\n    }\n}\n```\n\n**Good:**\n\n```php\ninterface Employee\n{\n    public function work(): void;\n}\n\nclass Human implements Employee\n{\n    public function work(): void\n    {\n        // ....working\n    }\n}\n\nclass Robot implements Employee\n{\n    public function work(): void\n    {\n        //.... working much more\n    }\n}\n\nclass Manager\n{\n    private $employee;\n\n    public function __construct(Employee $employee)\n    {\n        $this->employee = $employee;\n    }\n\n    public function manage(): void\n    {\n        $this->employee->work();\n    }\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Don’t repeat yourself (DRY)\n\nTry to observe the [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) principle.\n\nDo your absolute best to avoid duplicate code. Duplicate code is bad because\nit means that there's more than one place to alter something if you need to\nchange some logic.\n\nImagine if you run a restaurant and you keep track of your inventory: all your\ntomatoes, onions, garlic, spices, etc. If you have multiple lists that\nyou keep this on, then all have to be updated when you serve a dish with\ntomatoes in them. If you only have one list, there's only one place to update!\n\nOften you have duplicate code because you have two or more slightly\ndifferent things, that share a lot in common, but their differences force you\nto have two or more separate functions that do much of the same things. Removing\nduplicate code means creating an abstraction that can handle this set of different\nthings with just one function/module/class.\n\nGetting the abstraction right is critical, that's why you should follow the\nSOLID principles laid out in the [Classes](#classes) section. Bad abstractions can be\nworse than duplicate code, so be careful! Having said this, if you can make\na good abstraction, do it! Don't repeat yourself, otherwise you'll find yourself\nupdating multiple places any time you want to change one thing.\n\n**Bad:**\n\n```php\nfunction showDeveloperList(array $developers): void\n{\n    foreach ($developers as $developer) {\n        $expectedSalary = $developer->calculateExpectedSalary();\n        $experience = $developer->getExperience();\n        $githubLink = $developer->getGithubLink();\n        $data = [$expectedSalary, $experience, $githubLink];\n\n        render($data);\n    }\n}\n\nfunction showManagerList(array $managers): void\n{\n    foreach ($managers as $manager) {\n        $expectedSalary = $manager->calculateExpectedSalary();\n        $experience = $manager->getExperience();\n        $githubLink = $manager->getGithubLink();\n        $data = [$expectedSalary, $experience, $githubLink];\n\n        render($data);\n    }\n}\n```\n\n**Good:**\n\n```php\nfunction showList(array $employees): void\n{\n    foreach ($employees as $employee) {\n        $expectedSalary = $employee->calculateExpectedSalary();\n        $experience = $employee->getExperience();\n        $githubLink = $employee->getGithubLink();\n        $data = [$expectedSalary, $experience, $githubLink];\n\n        render($data);\n    }\n}\n```\n\n**Very good:**\n\nIt is better to use a compact version of the code.\n\n```php\nfunction showList(array $employees): void\n{\n    foreach ($employees as $employee) {\n        render([$employee->calculateExpectedSalary(), $employee->getExperience(), $employee->getGithubLink()]);\n    }\n}\n```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Translations\n\nThis is also available in other languages:\n\n* :cn: **Chinese:**\n   * [php-cpm/clean-code-php](https://github.com/php-cpm/clean-code-php)\n* :ru: **Russian:**\n   * [peter-gribanov/clean-code-php](https://github.com/peter-gribanov/clean-code-php)\n* :es: **Spanish:**\n   * [fikoborquez/clean-code-php](https://github.com/fikoborquez/clean-code-php)\n* :brazil: **Portuguese:**\n   * [fabioars/clean-code-php](https://github.com/fabioars/clean-code-php)\n   * [jeanjar/clean-code-php](https://github.com/jeanjar/clean-code-php/tree/pt-br)\n* :thailand: **Thai:**\n   * [panuwizzle/clean-code-php](https://github.com/panuwizzle/clean-code-php)\n* :fr: **French:**\n   * [errorname/clean-code-php](https://github.com/errorname/clean-code-php)\n* :vietnam: **Vietnamese:**\n   * [viethuongdev/clean-code-php](https://github.com/viethuongdev/clean-code-php)\n* :kr: **Korean:**\n   * [yujineeee/clean-code-php](https://github.com/yujineeee/clean-code-php)\n* :tr: **Turkish:**\n   * [anilozmen/clean-code-php](https://github.com/anilozmen/clean-code-php)\n* :iran: **Persian:**\n   * [amirshnll/clean-code-php](https://github.com/amirshnll/clean-code-php)\n* :bangladesh: **Bangla:**\n   * [nayeemdev/clean-code-php](https://github.com/nayeemdev/clean-code-php)\n* :egypt: **Arabic:**\n   * [ahmedalmory/clean-code-php](https://github.com/ahmedalmory/clean-code-php)\n* :jp: **Japanese:**\n   * [hayato07/clean-code-php](https://github.com/hayato07/clean-code-php)\n\n**[⬆ back to top](#table-of-contents)**\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"jupeter/clean-code-php\",\n    \"description\": \"Clean Code concepts adapted for PHP\",\n    \"require\": {\n        \"php\": \">=7.2\",\n        \"symplify/easy-coding-standard\": \"^9.3\"\n    },\n    \"scripts\": {\n        \"check-cs\": \"vendor/bin/ecs check-markdown README.md\",\n        \"fix-cs\": \"vendor/bin/ecs check-markdown README.md --fix\"\n    }\n}\n"
  },
  {
    "path": "ecs.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nuse PhpCsFixer\\Fixer\\PhpTag\\BlankLineAfterOpeningTagFixer;\nuse PhpCsFixer\\Fixer\\Strict\\DeclareStrictTypesFixer;\nuse PhpCsFixer\\Fixer\\Strict\\StrictComparisonFixer;\nuse Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ContainerConfigurator;\nuse Symplify\\EasyCodingStandard\\ValueObject\\Option;\nuse Symplify\\EasyCodingStandard\\ValueObject\\Set\\SetList;\n\nreturn static function (ContainerConfigurator $containerConfigurator): void\n{\n    $containerConfigurator->import(SetList::COMMON);\n    $containerConfigurator->import(SetList::CLEAN_CODE);\n    $containerConfigurator->import(SetList::PSR_12);\n    $containerConfigurator->import(SetList::SYMPLIFY);\n\n    $parameters = $containerConfigurator->parameters();\n    $parameters->set(Option::PATHS, [__DIR__ . '/src', __DIR__ . '/config', __DIR__ . '/ecs.php']);\n\n    $parameters->set(Option::SKIP, [\n        BlankLineAfterOpeningTagFixer::class => null,\n        StrictComparisonFixer::class => null,\n        DeclareStrictTypesFixer::class => null,\n    ]);\n};\n"
  }
]