├── .gitignore ├── .scrutinizer.yml ├── .travis.yml ├── composer.json ├── composer.lock ├── phpunit.xml.dist ├── readme.md ├── src ├── InterfaceSegregationPrinciple │ ├── Correct │ │ ├── BasketballPlayer.php │ │ └── Interfaces │ │ │ ├── Coach.php │ │ │ ├── Defense.php │ │ │ └── Offense.php │ ├── Violation │ │ ├── BasketballPlayer.php │ │ └── Interfaces │ │ │ └── Basketball.php │ └── readme.md ├── LiskovSubstitutionPrinciple │ ├── Correct │ │ └── BazFilter.php │ ├── Interfaces │ │ └── Filter.php │ ├── README.md │ └── Violation │ │ └── BarFilter.php ├── OpenClosedPrinciple │ ├── README.md │ ├── correct │ │ ├── StringModifier.php │ │ └── filters │ │ │ ├── BazFilter.php │ │ │ ├── Filter.php │ │ │ └── FooFilter.php │ └── violation │ │ └── StringModifier.php └── SingleResonsibilityPrinciple │ ├── README.md │ ├── correct │ ├── BasketballCoach.php │ └── BasketballPlayer.php │ ├── interfaces │ ├── Coach.php │ └── Player.php │ └── violation │ └── BasketballPlayerAndCoach.php └── tests ├── InterfaceSegregationPrinciple ├── Correct │ └── BasketballPlayerTest.php └── Violation │ └── BasketballPlayerTest.php ├── LiskovSubstitutionPrinciple ├── Correct │ └── BazFilterTest.php └── Violation │ └── BarFilterTest.php ├── OpenClosedPrinciple ├── correct │ └── StringModifierTest.php └── violation │ └── StringModifierTest.php └── SingleResponsibilityPrinciple ├── correct ├── BasketballCoachTest.php └── BasketballPlayerTest.php └── violation └── BasketballPlayerAndCoachTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor/ 3 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | filter: 2 | excluded_paths: 3 | - tests/* 4 | 5 | checks: 6 | php: 7 | code_rating: true 8 | 9 | tools: 10 | external_code_coverage: true 11 | php_analyzer: true 12 | php_changetracking: true 13 | php_code_sniffer: 14 | config: 15 | standard: "PSR2" 16 | php_cpd: true 17 | php_mess_detector: true 18 | php_pdepend: true 19 | sensiolabs_security_checker: true 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: php 4 | 5 | php: 6 | - 5.5 7 | - 5.6 8 | - hhvm 9 | - hhvm-nightly 10 | 11 | cache: 12 | directories: 13 | - vendor 14 | before_script: 15 | - composer install --dev --no-interaction --prefer-source 16 | 17 | script: 18 | - vendor/bin/phpunit --configuration phpunit.xml.dist --colors --coverage-clover=coverage.clover 19 | 20 | after_script: 21 | - wget https://scrutinizer-ci.com/ocular.phar 22 | - php ocular.phar code-coverage:upload --format=php-clover coverage.clover 23 | 24 | matrix: 25 | allow_failures: 26 | - php: hhvm-nightly 27 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "andywendt/solid_php_examples", 3 | "description": "Tested examples of SOLID PHP code", 4 | "minimum-stability": "stable", 5 | "license": "proprietary", 6 | "authors": [ 7 | { 8 | "name": "Andy Wendt", 9 | "email": "andy@awendt.com" 10 | } 11 | ], 12 | "require": { 13 | "phpunit/phpunit": "4.5.*", 14 | "mockery/mockery": "0.9.*" 15 | }, 16 | "autoload": { 17 | "psr-4": { 18 | "SolidPhp\\": "src/" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "52eaaafe22127598fac6e3157c1118bd", 8 | "packages": [ 9 | { 10 | "name": "doctrine/instantiator", 11 | "version": "1.0.4", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/doctrine/instantiator.git", 15 | "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", 20 | "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3,<8.0-DEV" 25 | }, 26 | "require-dev": { 27 | "athletic/athletic": "~0.1.8", 28 | "ext-pdo": "*", 29 | "ext-phar": "*", 30 | "phpunit/phpunit": "~4.0", 31 | "squizlabs/php_codesniffer": "2.0.*@ALPHA" 32 | }, 33 | "type": "library", 34 | "extra": { 35 | "branch-alias": { 36 | "dev-master": "1.0.x-dev" 37 | } 38 | }, 39 | "autoload": { 40 | "psr-0": { 41 | "Doctrine\\Instantiator\\": "src" 42 | } 43 | }, 44 | "notification-url": "https://packagist.org/downloads/", 45 | "license": [ 46 | "MIT" 47 | ], 48 | "authors": [ 49 | { 50 | "name": "Marco Pivetta", 51 | "email": "ocramius@gmail.com", 52 | "homepage": "http://ocramius.github.com/" 53 | } 54 | ], 55 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 56 | "homepage": "https://github.com/doctrine/instantiator", 57 | "keywords": [ 58 | "constructor", 59 | "instantiate" 60 | ], 61 | "time": "2014-10-13 12:58:55" 62 | }, 63 | { 64 | "name": "mockery/mockery", 65 | "version": "0.9.3", 66 | "source": { 67 | "type": "git", 68 | "url": "https://github.com/padraic/mockery.git", 69 | "reference": "686f85fa5b3b079cc0157d7cd3e9adb97f0b41e1" 70 | }, 71 | "dist": { 72 | "type": "zip", 73 | "url": "https://api.github.com/repos/padraic/mockery/zipball/686f85fa5b3b079cc0157d7cd3e9adb97f0b41e1", 74 | "reference": "686f85fa5b3b079cc0157d7cd3e9adb97f0b41e1", 75 | "shasum": "" 76 | }, 77 | "require": { 78 | "lib-pcre": ">=7.0", 79 | "php": ">=5.3.2" 80 | }, 81 | "require-dev": { 82 | "hamcrest/hamcrest-php": "~1.1", 83 | "phpunit/phpunit": "~4.0", 84 | "satooshi/php-coveralls": "~0.7@dev" 85 | }, 86 | "type": "library", 87 | "extra": { 88 | "branch-alias": { 89 | "dev-master": "0.9.x-dev" 90 | } 91 | }, 92 | "autoload": { 93 | "psr-0": { 94 | "Mockery": "library/" 95 | } 96 | }, 97 | "notification-url": "https://packagist.org/downloads/", 98 | "license": [ 99 | "BSD-3-Clause" 100 | ], 101 | "authors": [ 102 | { 103 | "name": "Pádraic Brady", 104 | "email": "padraic.brady@gmail.com", 105 | "homepage": "http://blog.astrumfutura.com" 106 | }, 107 | { 108 | "name": "Dave Marshall", 109 | "email": "dave.marshall@atstsolutions.co.uk", 110 | "homepage": "http://davedevelopment.co.uk" 111 | } 112 | ], 113 | "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succint API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", 114 | "homepage": "http://github.com/padraic/mockery", 115 | "keywords": [ 116 | "BDD", 117 | "TDD", 118 | "library", 119 | "mock", 120 | "mock objects", 121 | "mockery", 122 | "stub", 123 | "test", 124 | "test double", 125 | "testing" 126 | ], 127 | "time": "2014-12-22 10:06:19" 128 | }, 129 | { 130 | "name": "phpdocumentor/reflection-docblock", 131 | "version": "2.0.4", 132 | "source": { 133 | "type": "git", 134 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 135 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" 136 | }, 137 | "dist": { 138 | "type": "zip", 139 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", 140 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", 141 | "shasum": "" 142 | }, 143 | "require": { 144 | "php": ">=5.3.3" 145 | }, 146 | "require-dev": { 147 | "phpunit/phpunit": "~4.0" 148 | }, 149 | "suggest": { 150 | "dflydev/markdown": "~1.0", 151 | "erusev/parsedown": "~1.0" 152 | }, 153 | "type": "library", 154 | "extra": { 155 | "branch-alias": { 156 | "dev-master": "2.0.x-dev" 157 | } 158 | }, 159 | "autoload": { 160 | "psr-0": { 161 | "phpDocumentor": [ 162 | "src/" 163 | ] 164 | } 165 | }, 166 | "notification-url": "https://packagist.org/downloads/", 167 | "license": [ 168 | "MIT" 169 | ], 170 | "authors": [ 171 | { 172 | "name": "Mike van Riel", 173 | "email": "mike.vanriel@naenius.com" 174 | } 175 | ], 176 | "time": "2015-02-03 12:10:50" 177 | }, 178 | { 179 | "name": "phpspec/prophecy", 180 | "version": "v1.3.1", 181 | "source": { 182 | "type": "git", 183 | "url": "https://github.com/phpspec/prophecy.git", 184 | "reference": "9ca52329bcdd1500de24427542577ebf3fc2f1c9" 185 | }, 186 | "dist": { 187 | "type": "zip", 188 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/9ca52329bcdd1500de24427542577ebf3fc2f1c9", 189 | "reference": "9ca52329bcdd1500de24427542577ebf3fc2f1c9", 190 | "shasum": "" 191 | }, 192 | "require": { 193 | "doctrine/instantiator": "~1.0,>=1.0.2", 194 | "phpdocumentor/reflection-docblock": "~2.0" 195 | }, 196 | "require-dev": { 197 | "phpspec/phpspec": "~2.0" 198 | }, 199 | "type": "library", 200 | "extra": { 201 | "branch-alias": { 202 | "dev-master": "1.2.x-dev" 203 | } 204 | }, 205 | "autoload": { 206 | "psr-0": { 207 | "Prophecy\\": "src/" 208 | } 209 | }, 210 | "notification-url": "https://packagist.org/downloads/", 211 | "license": [ 212 | "MIT" 213 | ], 214 | "authors": [ 215 | { 216 | "name": "Konstantin Kudryashov", 217 | "email": "ever.zet@gmail.com", 218 | "homepage": "http://everzet.com" 219 | }, 220 | { 221 | "name": "Marcello Duarte", 222 | "email": "marcello.duarte@gmail.com" 223 | } 224 | ], 225 | "description": "Highly opinionated mocking framework for PHP 5.3+", 226 | "homepage": "http://phpspec.org", 227 | "keywords": [ 228 | "Double", 229 | "Dummy", 230 | "fake", 231 | "mock", 232 | "spy", 233 | "stub" 234 | ], 235 | "time": "2014-11-17 16:23:49" 236 | }, 237 | { 238 | "name": "phpunit/php-code-coverage", 239 | "version": "2.0.15", 240 | "source": { 241 | "type": "git", 242 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 243 | "reference": "34cc484af1ca149188d0d9e91412191e398e0b67" 244 | }, 245 | "dist": { 246 | "type": "zip", 247 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/34cc484af1ca149188d0d9e91412191e398e0b67", 248 | "reference": "34cc484af1ca149188d0d9e91412191e398e0b67", 249 | "shasum": "" 250 | }, 251 | "require": { 252 | "php": ">=5.3.3", 253 | "phpunit/php-file-iterator": "~1.3", 254 | "phpunit/php-text-template": "~1.2", 255 | "phpunit/php-token-stream": "~1.3", 256 | "sebastian/environment": "~1.0", 257 | "sebastian/version": "~1.0" 258 | }, 259 | "require-dev": { 260 | "ext-xdebug": ">=2.1.4", 261 | "phpunit/phpunit": "~4" 262 | }, 263 | "suggest": { 264 | "ext-dom": "*", 265 | "ext-xdebug": ">=2.2.1", 266 | "ext-xmlwriter": "*" 267 | }, 268 | "type": "library", 269 | "extra": { 270 | "branch-alias": { 271 | "dev-master": "2.0.x-dev" 272 | } 273 | }, 274 | "autoload": { 275 | "classmap": [ 276 | "src/" 277 | ] 278 | }, 279 | "notification-url": "https://packagist.org/downloads/", 280 | "license": [ 281 | "BSD-3-Clause" 282 | ], 283 | "authors": [ 284 | { 285 | "name": "Sebastian Bergmann", 286 | "email": "sb@sebastian-bergmann.de", 287 | "role": "lead" 288 | } 289 | ], 290 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 291 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 292 | "keywords": [ 293 | "coverage", 294 | "testing", 295 | "xunit" 296 | ], 297 | "time": "2015-01-24 10:06:35" 298 | }, 299 | { 300 | "name": "phpunit/php-file-iterator", 301 | "version": "1.3.4", 302 | "source": { 303 | "type": "git", 304 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 305 | "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" 306 | }, 307 | "dist": { 308 | "type": "zip", 309 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", 310 | "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", 311 | "shasum": "" 312 | }, 313 | "require": { 314 | "php": ">=5.3.3" 315 | }, 316 | "type": "library", 317 | "autoload": { 318 | "classmap": [ 319 | "File/" 320 | ] 321 | }, 322 | "notification-url": "https://packagist.org/downloads/", 323 | "include-path": [ 324 | "" 325 | ], 326 | "license": [ 327 | "BSD-3-Clause" 328 | ], 329 | "authors": [ 330 | { 331 | "name": "Sebastian Bergmann", 332 | "email": "sb@sebastian-bergmann.de", 333 | "role": "lead" 334 | } 335 | ], 336 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 337 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 338 | "keywords": [ 339 | "filesystem", 340 | "iterator" 341 | ], 342 | "time": "2013-10-10 15:34:57" 343 | }, 344 | { 345 | "name": "phpunit/php-text-template", 346 | "version": "1.2.0", 347 | "source": { 348 | "type": "git", 349 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 350 | "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" 351 | }, 352 | "dist": { 353 | "type": "zip", 354 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", 355 | "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", 356 | "shasum": "" 357 | }, 358 | "require": { 359 | "php": ">=5.3.3" 360 | }, 361 | "type": "library", 362 | "autoload": { 363 | "classmap": [ 364 | "Text/" 365 | ] 366 | }, 367 | "notification-url": "https://packagist.org/downloads/", 368 | "include-path": [ 369 | "" 370 | ], 371 | "license": [ 372 | "BSD-3-Clause" 373 | ], 374 | "authors": [ 375 | { 376 | "name": "Sebastian Bergmann", 377 | "email": "sb@sebastian-bergmann.de", 378 | "role": "lead" 379 | } 380 | ], 381 | "description": "Simple template engine.", 382 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 383 | "keywords": [ 384 | "template" 385 | ], 386 | "time": "2014-01-30 17:20:04" 387 | }, 388 | { 389 | "name": "phpunit/php-timer", 390 | "version": "1.0.5", 391 | "source": { 392 | "type": "git", 393 | "url": "https://github.com/sebastianbergmann/php-timer.git", 394 | "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" 395 | }, 396 | "dist": { 397 | "type": "zip", 398 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", 399 | "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", 400 | "shasum": "" 401 | }, 402 | "require": { 403 | "php": ">=5.3.3" 404 | }, 405 | "type": "library", 406 | "autoload": { 407 | "classmap": [ 408 | "PHP/" 409 | ] 410 | }, 411 | "notification-url": "https://packagist.org/downloads/", 412 | "include-path": [ 413 | "" 414 | ], 415 | "license": [ 416 | "BSD-3-Clause" 417 | ], 418 | "authors": [ 419 | { 420 | "name": "Sebastian Bergmann", 421 | "email": "sb@sebastian-bergmann.de", 422 | "role": "lead" 423 | } 424 | ], 425 | "description": "Utility class for timing", 426 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 427 | "keywords": [ 428 | "timer" 429 | ], 430 | "time": "2013-08-02 07:42:54" 431 | }, 432 | { 433 | "name": "phpunit/php-token-stream", 434 | "version": "1.4.0", 435 | "source": { 436 | "type": "git", 437 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 438 | "reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74" 439 | }, 440 | "dist": { 441 | "type": "zip", 442 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/db32c18eba00b121c145575fcbcd4d4d24e6db74", 443 | "reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74", 444 | "shasum": "" 445 | }, 446 | "require": { 447 | "ext-tokenizer": "*", 448 | "php": ">=5.3.3" 449 | }, 450 | "require-dev": { 451 | "phpunit/phpunit": "~4.2" 452 | }, 453 | "type": "library", 454 | "extra": { 455 | "branch-alias": { 456 | "dev-master": "1.4-dev" 457 | } 458 | }, 459 | "autoload": { 460 | "classmap": [ 461 | "src/" 462 | ] 463 | }, 464 | "notification-url": "https://packagist.org/downloads/", 465 | "license": [ 466 | "BSD-3-Clause" 467 | ], 468 | "authors": [ 469 | { 470 | "name": "Sebastian Bergmann", 471 | "email": "sebastian@phpunit.de" 472 | } 473 | ], 474 | "description": "Wrapper around PHP's tokenizer extension.", 475 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 476 | "keywords": [ 477 | "tokenizer" 478 | ], 479 | "time": "2015-01-17 09:51:32" 480 | }, 481 | { 482 | "name": "phpunit/phpunit", 483 | "version": "4.5.0", 484 | "source": { 485 | "type": "git", 486 | "url": "https://github.com/sebastianbergmann/phpunit.git", 487 | "reference": "5b578d3865a9128b9c209b011fda6539ec06e7a5" 488 | }, 489 | "dist": { 490 | "type": "zip", 491 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5b578d3865a9128b9c209b011fda6539ec06e7a5", 492 | "reference": "5b578d3865a9128b9c209b011fda6539ec06e7a5", 493 | "shasum": "" 494 | }, 495 | "require": { 496 | "ext-dom": "*", 497 | "ext-json": "*", 498 | "ext-pcre": "*", 499 | "ext-reflection": "*", 500 | "ext-spl": "*", 501 | "php": ">=5.3.3", 502 | "phpspec/prophecy": "~1.3.1", 503 | "phpunit/php-code-coverage": "~2.0", 504 | "phpunit/php-file-iterator": "~1.3.2", 505 | "phpunit/php-text-template": "~1.2", 506 | "phpunit/php-timer": "~1.0.2", 507 | "phpunit/phpunit-mock-objects": "~2.3", 508 | "sebastian/comparator": "~1.1", 509 | "sebastian/diff": "~1.1", 510 | "sebastian/environment": "~1.2", 511 | "sebastian/exporter": "~1.2", 512 | "sebastian/global-state": "~1.0", 513 | "sebastian/version": "~1.0", 514 | "symfony/yaml": "~2.0" 515 | }, 516 | "suggest": { 517 | "phpunit/php-invoker": "~1.1" 518 | }, 519 | "bin": [ 520 | "phpunit" 521 | ], 522 | "type": "library", 523 | "extra": { 524 | "branch-alias": { 525 | "dev-master": "4.5.x-dev" 526 | } 527 | }, 528 | "autoload": { 529 | "classmap": [ 530 | "src/" 531 | ] 532 | }, 533 | "notification-url": "https://packagist.org/downloads/", 534 | "license": [ 535 | "BSD-3-Clause" 536 | ], 537 | "authors": [ 538 | { 539 | "name": "Sebastian Bergmann", 540 | "email": "sebastian@phpunit.de", 541 | "role": "lead" 542 | } 543 | ], 544 | "description": "The PHP Unit Testing framework.", 545 | "homepage": "https://phpunit.de/", 546 | "keywords": [ 547 | "phpunit", 548 | "testing", 549 | "xunit" 550 | ], 551 | "time": "2015-02-05 15:51:19" 552 | }, 553 | { 554 | "name": "phpunit/phpunit-mock-objects", 555 | "version": "2.3.0", 556 | "source": { 557 | "type": "git", 558 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 559 | "reference": "c63d2367247365f688544f0d500af90a11a44c65" 560 | }, 561 | "dist": { 562 | "type": "zip", 563 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c63d2367247365f688544f0d500af90a11a44c65", 564 | "reference": "c63d2367247365f688544f0d500af90a11a44c65", 565 | "shasum": "" 566 | }, 567 | "require": { 568 | "doctrine/instantiator": "~1.0,>=1.0.1", 569 | "php": ">=5.3.3", 570 | "phpunit/php-text-template": "~1.2" 571 | }, 572 | "require-dev": { 573 | "phpunit/phpunit": "~4.3" 574 | }, 575 | "suggest": { 576 | "ext-soap": "*" 577 | }, 578 | "type": "library", 579 | "extra": { 580 | "branch-alias": { 581 | "dev-master": "2.3.x-dev" 582 | } 583 | }, 584 | "autoload": { 585 | "classmap": [ 586 | "src/" 587 | ] 588 | }, 589 | "notification-url": "https://packagist.org/downloads/", 590 | "license": [ 591 | "BSD-3-Clause" 592 | ], 593 | "authors": [ 594 | { 595 | "name": "Sebastian Bergmann", 596 | "email": "sb@sebastian-bergmann.de", 597 | "role": "lead" 598 | } 599 | ], 600 | "description": "Mock Object library for PHPUnit", 601 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 602 | "keywords": [ 603 | "mock", 604 | "xunit" 605 | ], 606 | "time": "2014-10-03 05:12:11" 607 | }, 608 | { 609 | "name": "sebastian/comparator", 610 | "version": "1.1.1", 611 | "source": { 612 | "type": "git", 613 | "url": "https://github.com/sebastianbergmann/comparator.git", 614 | "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" 615 | }, 616 | "dist": { 617 | "type": "zip", 618 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", 619 | "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", 620 | "shasum": "" 621 | }, 622 | "require": { 623 | "php": ">=5.3.3", 624 | "sebastian/diff": "~1.2", 625 | "sebastian/exporter": "~1.2" 626 | }, 627 | "require-dev": { 628 | "phpunit/phpunit": "~4.4" 629 | }, 630 | "type": "library", 631 | "extra": { 632 | "branch-alias": { 633 | "dev-master": "1.1.x-dev" 634 | } 635 | }, 636 | "autoload": { 637 | "classmap": [ 638 | "src/" 639 | ] 640 | }, 641 | "notification-url": "https://packagist.org/downloads/", 642 | "license": [ 643 | "BSD-3-Clause" 644 | ], 645 | "authors": [ 646 | { 647 | "name": "Jeff Welch", 648 | "email": "whatthejeff@gmail.com" 649 | }, 650 | { 651 | "name": "Volker Dusch", 652 | "email": "github@wallbash.com" 653 | }, 654 | { 655 | "name": "Bernhard Schussek", 656 | "email": "bschussek@2bepublished.at" 657 | }, 658 | { 659 | "name": "Sebastian Bergmann", 660 | "email": "sebastian@phpunit.de" 661 | } 662 | ], 663 | "description": "Provides the functionality to compare PHP values for equality", 664 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 665 | "keywords": [ 666 | "comparator", 667 | "compare", 668 | "equality" 669 | ], 670 | "time": "2015-01-29 16:28:08" 671 | }, 672 | { 673 | "name": "sebastian/diff", 674 | "version": "1.2.0", 675 | "source": { 676 | "type": "git", 677 | "url": "https://github.com/sebastianbergmann/diff.git", 678 | "reference": "5843509fed39dee4b356a306401e9dd1a931fec7" 679 | }, 680 | "dist": { 681 | "type": "zip", 682 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/5843509fed39dee4b356a306401e9dd1a931fec7", 683 | "reference": "5843509fed39dee4b356a306401e9dd1a931fec7", 684 | "shasum": "" 685 | }, 686 | "require": { 687 | "php": ">=5.3.3" 688 | }, 689 | "require-dev": { 690 | "phpunit/phpunit": "~4.2" 691 | }, 692 | "type": "library", 693 | "extra": { 694 | "branch-alias": { 695 | "dev-master": "1.2-dev" 696 | } 697 | }, 698 | "autoload": { 699 | "classmap": [ 700 | "src/" 701 | ] 702 | }, 703 | "notification-url": "https://packagist.org/downloads/", 704 | "license": [ 705 | "BSD-3-Clause" 706 | ], 707 | "authors": [ 708 | { 709 | "name": "Kore Nordmann", 710 | "email": "mail@kore-nordmann.de" 711 | }, 712 | { 713 | "name": "Sebastian Bergmann", 714 | "email": "sebastian@phpunit.de" 715 | } 716 | ], 717 | "description": "Diff implementation", 718 | "homepage": "http://www.github.com/sebastianbergmann/diff", 719 | "keywords": [ 720 | "diff" 721 | ], 722 | "time": "2014-08-15 10:29:00" 723 | }, 724 | { 725 | "name": "sebastian/environment", 726 | "version": "1.2.1", 727 | "source": { 728 | "type": "git", 729 | "url": "https://github.com/sebastianbergmann/environment.git", 730 | "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7" 731 | }, 732 | "dist": { 733 | "type": "zip", 734 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e6c71d918088c251b181ba8b3088af4ac336dd7", 735 | "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7", 736 | "shasum": "" 737 | }, 738 | "require": { 739 | "php": ">=5.3.3" 740 | }, 741 | "require-dev": { 742 | "phpunit/phpunit": "~4.3" 743 | }, 744 | "type": "library", 745 | "extra": { 746 | "branch-alias": { 747 | "dev-master": "1.2.x-dev" 748 | } 749 | }, 750 | "autoload": { 751 | "classmap": [ 752 | "src/" 753 | ] 754 | }, 755 | "notification-url": "https://packagist.org/downloads/", 756 | "license": [ 757 | "BSD-3-Clause" 758 | ], 759 | "authors": [ 760 | { 761 | "name": "Sebastian Bergmann", 762 | "email": "sebastian@phpunit.de" 763 | } 764 | ], 765 | "description": "Provides functionality to handle HHVM/PHP environments", 766 | "homepage": "http://www.github.com/sebastianbergmann/environment", 767 | "keywords": [ 768 | "Xdebug", 769 | "environment", 770 | "hhvm" 771 | ], 772 | "time": "2014-10-25 08:00:45" 773 | }, 774 | { 775 | "name": "sebastian/exporter", 776 | "version": "1.2.0", 777 | "source": { 778 | "type": "git", 779 | "url": "https://github.com/sebastianbergmann/exporter.git", 780 | "reference": "84839970d05254c73cde183a721c7af13aede943" 781 | }, 782 | "dist": { 783 | "type": "zip", 784 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", 785 | "reference": "84839970d05254c73cde183a721c7af13aede943", 786 | "shasum": "" 787 | }, 788 | "require": { 789 | "php": ">=5.3.3", 790 | "sebastian/recursion-context": "~1.0" 791 | }, 792 | "require-dev": { 793 | "phpunit/phpunit": "~4.4" 794 | }, 795 | "type": "library", 796 | "extra": { 797 | "branch-alias": { 798 | "dev-master": "1.2.x-dev" 799 | } 800 | }, 801 | "autoload": { 802 | "classmap": [ 803 | "src/" 804 | ] 805 | }, 806 | "notification-url": "https://packagist.org/downloads/", 807 | "license": [ 808 | "BSD-3-Clause" 809 | ], 810 | "authors": [ 811 | { 812 | "name": "Jeff Welch", 813 | "email": "whatthejeff@gmail.com" 814 | }, 815 | { 816 | "name": "Volker Dusch", 817 | "email": "github@wallbash.com" 818 | }, 819 | { 820 | "name": "Bernhard Schussek", 821 | "email": "bschussek@2bepublished.at" 822 | }, 823 | { 824 | "name": "Sebastian Bergmann", 825 | "email": "sebastian@phpunit.de" 826 | }, 827 | { 828 | "name": "Adam Harvey", 829 | "email": "aharvey@php.net" 830 | } 831 | ], 832 | "description": "Provides the functionality to export PHP variables for visualization", 833 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 834 | "keywords": [ 835 | "export", 836 | "exporter" 837 | ], 838 | "time": "2015-01-27 07:23:06" 839 | }, 840 | { 841 | "name": "sebastian/global-state", 842 | "version": "1.0.0", 843 | "source": { 844 | "type": "git", 845 | "url": "https://github.com/sebastianbergmann/global-state.git", 846 | "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01" 847 | }, 848 | "dist": { 849 | "type": "zip", 850 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01", 851 | "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01", 852 | "shasum": "" 853 | }, 854 | "require": { 855 | "php": ">=5.3.3" 856 | }, 857 | "require-dev": { 858 | "phpunit/phpunit": "~4.2" 859 | }, 860 | "suggest": { 861 | "ext-uopz": "*" 862 | }, 863 | "type": "library", 864 | "extra": { 865 | "branch-alias": { 866 | "dev-master": "1.0-dev" 867 | } 868 | }, 869 | "autoload": { 870 | "classmap": [ 871 | "src/" 872 | ] 873 | }, 874 | "notification-url": "https://packagist.org/downloads/", 875 | "license": [ 876 | "BSD-3-Clause" 877 | ], 878 | "authors": [ 879 | { 880 | "name": "Sebastian Bergmann", 881 | "email": "sebastian@phpunit.de" 882 | } 883 | ], 884 | "description": "Snapshotting of global state", 885 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 886 | "keywords": [ 887 | "global state" 888 | ], 889 | "time": "2014-10-06 09:23:50" 890 | }, 891 | { 892 | "name": "sebastian/recursion-context", 893 | "version": "1.0.0", 894 | "source": { 895 | "type": "git", 896 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 897 | "reference": "3989662bbb30a29d20d9faa04a846af79b276252" 898 | }, 899 | "dist": { 900 | "type": "zip", 901 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", 902 | "reference": "3989662bbb30a29d20d9faa04a846af79b276252", 903 | "shasum": "" 904 | }, 905 | "require": { 906 | "php": ">=5.3.3" 907 | }, 908 | "require-dev": { 909 | "phpunit/phpunit": "~4.4" 910 | }, 911 | "type": "library", 912 | "extra": { 913 | "branch-alias": { 914 | "dev-master": "1.0.x-dev" 915 | } 916 | }, 917 | "autoload": { 918 | "classmap": [ 919 | "src/" 920 | ] 921 | }, 922 | "notification-url": "https://packagist.org/downloads/", 923 | "license": [ 924 | "BSD-3-Clause" 925 | ], 926 | "authors": [ 927 | { 928 | "name": "Jeff Welch", 929 | "email": "whatthejeff@gmail.com" 930 | }, 931 | { 932 | "name": "Sebastian Bergmann", 933 | "email": "sebastian@phpunit.de" 934 | }, 935 | { 936 | "name": "Adam Harvey", 937 | "email": "aharvey@php.net" 938 | } 939 | ], 940 | "description": "Provides functionality to recursively process PHP variables", 941 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 942 | "time": "2015-01-24 09:48:32" 943 | }, 944 | { 945 | "name": "sebastian/version", 946 | "version": "1.0.4", 947 | "source": { 948 | "type": "git", 949 | "url": "https://github.com/sebastianbergmann/version.git", 950 | "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b" 951 | }, 952 | "dist": { 953 | "type": "zip", 954 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b", 955 | "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b", 956 | "shasum": "" 957 | }, 958 | "type": "library", 959 | "autoload": { 960 | "classmap": [ 961 | "src/" 962 | ] 963 | }, 964 | "notification-url": "https://packagist.org/downloads/", 965 | "license": [ 966 | "BSD-3-Clause" 967 | ], 968 | "authors": [ 969 | { 970 | "name": "Sebastian Bergmann", 971 | "email": "sebastian@phpunit.de", 972 | "role": "lead" 973 | } 974 | ], 975 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 976 | "homepage": "https://github.com/sebastianbergmann/version", 977 | "time": "2014-12-15 14:25:24" 978 | }, 979 | { 980 | "name": "symfony/yaml", 981 | "version": "v2.6.5", 982 | "target-dir": "Symfony/Component/Yaml", 983 | "source": { 984 | "type": "git", 985 | "url": "https://github.com/symfony/Yaml.git", 986 | "reference": "0cd8e72071e46e15fc072270ae39ea1b66b10a9d" 987 | }, 988 | "dist": { 989 | "type": "zip", 990 | "url": "https://api.github.com/repos/symfony/Yaml/zipball/0cd8e72071e46e15fc072270ae39ea1b66b10a9d", 991 | "reference": "0cd8e72071e46e15fc072270ae39ea1b66b10a9d", 992 | "shasum": "" 993 | }, 994 | "require": { 995 | "php": ">=5.3.3" 996 | }, 997 | "require-dev": { 998 | "symfony/phpunit-bridge": "~2.7" 999 | }, 1000 | "type": "library", 1001 | "extra": { 1002 | "branch-alias": { 1003 | "dev-master": "2.6-dev" 1004 | } 1005 | }, 1006 | "autoload": { 1007 | "psr-0": { 1008 | "Symfony\\Component\\Yaml\\": "" 1009 | } 1010 | }, 1011 | "notification-url": "https://packagist.org/downloads/", 1012 | "license": [ 1013 | "MIT" 1014 | ], 1015 | "authors": [ 1016 | { 1017 | "name": "Symfony Community", 1018 | "homepage": "http://symfony.com/contributors" 1019 | }, 1020 | { 1021 | "name": "Fabien Potencier", 1022 | "email": "fabien@symfony.com" 1023 | } 1024 | ], 1025 | "description": "Symfony Yaml Component", 1026 | "homepage": "http://symfony.com", 1027 | "time": "2015-03-12 10:28:44" 1028 | } 1029 | ], 1030 | "packages-dev": [], 1031 | "aliases": [], 1032 | "minimum-stability": "stable", 1033 | "stability-flags": [], 1034 | "prefer-stable": false, 1035 | "prefer-lowest": false, 1036 | "platform": [], 1037 | "platform-dev": [] 1038 | } 1039 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/* 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # SOLID PHP Examples 2 | 3 | [![Build Status](https://travis-ci.org/AndyWendt/solid_php_examples.svg?branch=master)](https://travis-ci.org/AndyWendt/solid_php_examples) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/AndyWendt/solid_php_examples/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/AndyWendt/solid_php_examples/?branch=master) [![Code Coverage](https://scrutinizer-ci.com/g/AndyWendt/solid_php_examples/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/AndyWendt/solid_php_examples/?branch=master) 4 | 5 | ## Single Responsibility Principle 6 | 7 | >A class should only have one reason to change. 8 | 9 | Entities should do one thing only and do it well. 10 | 11 | ## Open/Closed Principle 12 | 13 | >Software entities (classes, modules, functions, etc.) should be **open for extension**, but **closed for modification.** 14 | 15 | Entities should be open for extension but closed to modification. 16 | 17 | 18 | ## Liskov Substitution Principle 19 | 20 | >Subtypes must be substitutable for their base types. 21 | 22 | Derived classes must be substitutable for their base types. 23 | 24 | A class that implements an interface should be able to be used anywhere that interface is type hinted. 25 | 26 | The preconditions cannot be greater! (i.e. if a subtype one throws an exception but not the main then its preconditions are greater) 27 | 28 | Really your @returns, @throws, input parameters, etc should be consistent throughout. 29 | 30 | If it looks like a duck, quacks like a duck and needs batteries, you probably have the wrong abstraction. 31 | 32 | 33 | ## Interface Segregation Principle 34 | 35 | >Clients should not be forced to depend on methods that they do not use. 36 | 37 | If clients are forced to depend on methods that they do not use, it results in inadvertent coupling. 38 | 39 | 40 | ## Dependency Inversion Principle 41 | 42 | >a. High-level modules should not depend on low-level modules. Both should depend on abstractions. 43 | >b. Abstractions should not depend on details. Details should depend on abstractions. 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/InterfaceSegregationPrinciple/Correct/BasketballPlayer.php: -------------------------------------------------------------------------------- 1 | randomBool(); 18 | } 19 | 20 | /** 21 | * Try to score by shooting the ball while on offense 22 | * 23 | * @return bool 24 | */ 25 | public function shoot() 26 | { 27 | return $this->randomBool(); 28 | } 29 | 30 | protected function randomBool() 31 | { 32 | return (bool) rand(0,1); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/InterfaceSegregationPrinciple/Correct/Interfaces/Coach.php: -------------------------------------------------------------------------------- 1 | randomBool(); 16 | } 17 | 18 | /** 19 | * Try to score by shooting the ball while on offense 20 | * 21 | * @return bool 22 | */ 23 | public function shoot() 24 | { 25 | return $this->randomBool(); 26 | } 27 | 28 | protected function randomBool() 29 | { 30 | return (bool) rand(0,1); 31 | } 32 | 33 | /** 34 | * Echos out some string of profanities 35 | * 36 | * @return string 37 | */ 38 | public function yellAtPlayersLikeBobbyKnight() 39 | { 40 | return 'This has been censored because of inappropriate content'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/InterfaceSegregationPrinciple/Violation/Interfaces/Basketball.php: -------------------------------------------------------------------------------- 1 | run($string); 19 | } 20 | 21 | return $string; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/OpenClosedPrinciple/correct/filters/BazFilter.php: -------------------------------------------------------------------------------- 1 | basketballPlayer = new BasketballPlayer(); 20 | } 21 | 22 | /** 23 | * @test 24 | */ 25 | public function it_implements_multiple_interfaces_because_the_responsibilities_are_different_for_each() 26 | { 27 | /* 28 | * The player can play offense and defense 29 | */ 30 | $this->assertInstanceOf(Offense::class, $this->basketballPlayer); 31 | $this->assertInstanceOf(Defense::class, $this->basketballPlayer); 32 | 33 | /* 34 | * The player does not have the responsibilities of a coach. 35 | */ 36 | $this->assertNotInstanceOf(Coach::class, $this->basketballPlayer); 37 | } 38 | 39 | /** 40 | * @test 41 | */ 42 | public function it_fulfills_all_of_its_contracts() 43 | { 44 | $this->assertTrue(is_bool($this->basketballPlayer->block()), 'The player can block'); 45 | $this->assertTrue(is_bool($this->basketballPlayer->shoot()), 'The player can shoot'); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/InterfaceSegregationPrinciple/Violation/BasketballPlayerTest.php: -------------------------------------------------------------------------------- 1 | basketballPlayer = new BasketballPlayer(); 19 | } 20 | 21 | 22 | /** 23 | * @test 24 | */ 25 | public function it_uses_one_interface_for_multiple_responsibilities() 26 | { 27 | $this->assertInstanceOf(Basketball::class, $this->basketballPlayer); 28 | } 29 | 30 | /** 31 | * @test 32 | */ 33 | public function it_fulfills_all_of_its_contracts() 34 | { 35 | $this->assertTrue(is_bool($this->basketballPlayer->block()), 'The player can block'); 36 | $this->assertTrue(is_bool($this->basketballPlayer->shoot()), 'The player can shoot'); 37 | $this->assertTrue(is_string($this->basketballPlayer->yellAtPlayersLikeBobbyKnight()), 'The player is also a coach evidently'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/LiskovSubstitutionPrinciple/Correct/BazFilterTest.php: -------------------------------------------------------------------------------- 1 | run(['a', 'baz', 'filter']); 13 | 14 | // Return type should be array 15 | $this->assertTrue(is_array($actual)); 16 | $this->assertContains('yikes', $actual); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/LiskovSubstitutionPrinciple/Violation/BarFilterTest.php: -------------------------------------------------------------------------------- 1 | barFilter = new BarFilter(); 16 | } 17 | 18 | 19 | /** 20 | * @test 21 | */ 22 | public function it_throws_an_exception_so_its_preconditions_are_greater() 23 | { 24 | /* 25 | * Because we are expecting an exception to be thrown, 26 | * and the parent class does not have an @throws, 27 | * the preconditions are greater for the sub class 28 | * than for the parent. 29 | * 30 | * We can theoretically say that the exception is being 31 | * thrown because the array is empty and should raise an exceptional case. 32 | * But we read in the doc block for the interface that the consumer is expecting 33 | * an empty array to be returned regardless. 34 | */ 35 | $this->setExpectedException(\Exception::class); 36 | 37 | $this->barFilter->run([]); 38 | } 39 | 40 | /** 41 | * @test 42 | */ 43 | public function it_sometimes_returns_a_string_so_it_cannot_be_substituted_for_the_base_type() 44 | { 45 | $actual = $this->barFilter->run(['bar']); 46 | 47 | /* 48 | * The consumer of the Filter interface is going to be freaking out 49 | * if they have a string returned rather than an array in an implementing class. 50 | * 51 | * The Filter interface explicitly says @return array *not* @return array|string. 52 | * 53 | * This would absolutely blow up in the face of whomever used it. It would 54 | * force them to hack in order to get it to work, eliminating the benefit of using 55 | * an interface. 56 | */ 57 | $this->assertTrue(is_string($actual)); 58 | } 59 | 60 | /** 61 | * @test 62 | */ 63 | public function it_sometimes_returns_an_array() 64 | { 65 | $actual = $this->barFilter->run(['test']); 66 | 67 | /* 68 | * This would drive you certifiably nuts receiving an array 69 | * sometimes and string others and then other times being greeted 70 | * by an exception you could not see coming. 71 | */ 72 | $this->assertContains('test', $actual); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/OpenClosedPrinciple/correct/StringModifierTest.php: -------------------------------------------------------------------------------- 1 | modify( 21 | $string, 22 | [ 23 | new BazFilter(), 24 | new FooFilter(), 25 | ] 26 | ); 27 | 28 | $this->assertSame($expected, $actual); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/OpenClosedPrinciple/violation/StringModifierTest.php: -------------------------------------------------------------------------------- 1 | modify($string); 17 | 18 | $this->assertSame($expected, $actual); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/SingleResponsibilityPrinciple/correct/BasketballCoachTest.php: -------------------------------------------------------------------------------- 1 | basketballCoach = new BasketballCoach(); 20 | } 21 | 22 | /** 23 | * @test 24 | */ 25 | public function is_only_a_coach() 26 | { 27 | $this->assertInstanceOf(Coach::class, $this->basketballCoach); 28 | $this->assertNotInstanceOf(Player::class, $this->basketballCoach); 29 | } 30 | 31 | /** 32 | * @test 33 | */ 34 | public function it_fulfills_all_interface_contracts() 35 | { 36 | $this->assertTrue(is_string($this->basketballCoach->leadTeam())); 37 | $this->assertTrue(is_string($this->basketballCoach->leadPractice())); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/SingleResponsibilityPrinciple/correct/BasketballPlayerTest.php: -------------------------------------------------------------------------------- 1 | basketballPlayer = new BasketballPlayer(); 20 | } 21 | 22 | 23 | /** 24 | * @test 25 | */ 26 | public function is_only_a_player() 27 | { 28 | $this->assertInstanceOf(Player::class, $this->basketballPlayer); 29 | $this->assertNotInstanceOf(Coach::class, $this->basketballPlayer); 30 | } 31 | 32 | /** 33 | * @test 34 | */ 35 | public function it_fullfills_its_interface_contracts() 36 | { 37 | $this->assertTrue(is_string($this->basketballPlayer->play())); 38 | $this->assertTrue(is_string($this->basketballPlayer->practice())); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/SingleResponsibilityPrinciple/violation/BasketballPlayerAndCoachTest.php: -------------------------------------------------------------------------------- 1 | basketballPlayerAndCoach = new BasketballPlayerAndCoach(); 20 | } 21 | 22 | 23 | /** 24 | * @test 25 | */ 26 | public function is_both_a_player_and_a_coach_violating_srp() 27 | { 28 | $this->assertInstanceOf(Player::class, $this->basketballPlayerAndCoach); 29 | $this->assertInstanceOf(Coach::class, $this->basketballPlayerAndCoach); 30 | } 31 | 32 | /** 33 | * @test 34 | */ 35 | public function it_fullfills_its_interface_contracts() 36 | { 37 | $this->assertString($this->basketballPlayerAndCoach->leadTeam()); 38 | $this->assertString($this->basketballPlayerAndCoach->leadPractice()); 39 | $this->assertString($this->basketballPlayerAndCoach->play()); 40 | $this->assertString($this->basketballPlayerAndCoach->practice()); 41 | } 42 | 43 | /** 44 | * @param mixed $result 45 | */ 46 | protected function assertString($result) 47 | { 48 | $this->assertTrue(is_string($result)); 49 | } 50 | } 51 | --------------------------------------------------------------------------------