Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php  | 
            ||
| 17 | class AuthenticatorService implements ServiceInterface  | 
            ||
| 18 | { | 
            ||
| 19 | |||
| 20 | /** @var AbstractController */  | 
            ||
| 21 | protected $controller;  | 
            ||
| 22 | |||
| 23 | /** @var DbService */  | 
            ||
| 24 | protected $orm;  | 
            ||
| 25 | |||
| 26 | /** @var Config */  | 
            ||
| 27 | protected $config;  | 
            ||
| 28 | |||
| 29 | /** @var string */  | 
            ||
| 30 | protected $redirectAfterAuth;  | 
            ||
| 31 | |||
| 32 | /**  | 
            ||
| 33 | * Authenticator constructor.  | 
            ||
| 34 | * @param AbstractController $controller  | 
            ||
| 35 | * @param Config $config  | 
            ||
| 36 | */  | 
            ||
| 37 | public function __construct(AbstractController $controller, Config $config)  | 
            ||
| 42 | |||
| 43 | /**  | 
            ||
| 44 | * @param Entity $user  | 
            ||
| 45 | * @param bool $shouldBeActive  | 
            ||
| 46 | * @return bool  | 
            ||
| 47 | * @codeCoverageIgnore  | 
            ||
| 48 | */  | 
            ||
| 49 | public function loginUser(Entity $user, $shouldBeActive)  | 
            ||
| 87 | |||
| 88 | /**  | 
            ||
| 89 | * @return bool  | 
            ||
| 90 | */  | 
            ||
| 91 | View Code Duplication | public function redirectToAccessDeniedPage()  | 
            |
| 99 | |||
| 100 | /**  | 
            ||
| 101 | * @return bool  | 
            ||
| 102 | */  | 
            ||
| 103 | View Code Duplication | public function redirectToAuthentication()  | 
            |
| 111 | |||
| 112 | /**  | 
            ||
| 113 | * @param array $roles  | 
            ||
| 114 | * @return bool  | 
            ||
| 115 | */  | 
            ||
| 116 | public function isPermitted(array $roles)  | 
            ||
| 135 | |||
| 136 | /**  | 
            ||
| 137 | * @param Entity $user  | 
            ||
| 138 | * @codeCoverageIgnore  | 
            ||
| 139 | */  | 
            ||
| 140 | public function saveUserInSession(Entity $user)  | 
            ||
| 144 | |||
| 145 | /**  | 
            ||
| 146 | * @return Entity  | 
            ||
| 147 | * @codeCoverageIgnore  | 
            ||
| 148 | */  | 
            ||
| 149 | public function getUserFromSession()  | 
            ||
| 161 | |||
| 162 | }  | 
            
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the interface: