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  | 
            ||
| 9 | class LDAPAuthenticator extends Authenticator  | 
            ||
| 10 | { | 
            ||
| 11 | /**  | 
            ||
| 12 | * @var string  | 
            ||
| 13 | */  | 
            ||
| 14 | private $name = 'LDAP';  | 
            ||
| 15 | |||
| 16 | /**  | 
            ||
| 17 | * Set to 'yes' to indicate if this module should look up usernames in LDAP by matching the email addresses.  | 
            ||
| 18 | *  | 
            ||
| 19 | * CAVEAT #1: only set to 'yes' for systems that enforce email uniqueness.  | 
            ||
| 20 | * Otherwise only the first LDAP user with matching email will be accessible.  | 
            ||
| 21 | *  | 
            ||
| 22 | * CAVEAT #2: this is untested for systems that use LDAP with principal style usernames (i.e. [email protected]).  | 
            ||
| 23 | * The system will misunderstand emails for usernames with uncertain outcome.  | 
            ||
| 24 | *  | 
            ||
| 25 | * @var string 'no' or 'yes'  | 
            ||
| 26 | */  | 
            ||
| 27 | private static $allow_email_login = 'no';  | 
            ||
| 28 | |||
| 29 | /**  | 
            ||
| 30 |      * Set to 'yes' to fallback login attempts to {@link $fallback_authenticator}. | 
            ||
| 31 | * This will occur if LDAP fails to authenticate the user.  | 
            ||
| 32 | *  | 
            ||
| 33 | * @var string 'no' or 'yes'  | 
            ||
| 34 | */  | 
            ||
| 35 | private static $fallback_authenticator = 'no';  | 
            ||
| 36 | |||
| 37 | /**  | 
            ||
| 38 |      * The class of {@link Authenticator} to use as the fallback authenticator. | 
            ||
| 39 | *  | 
            ||
| 40 | * @var string  | 
            ||
| 41 | */  | 
            ||
| 42 | private static $fallback_authenticator_class = 'MemberAuthenticator';  | 
            ||
| 43 | |||
| 44 | /**  | 
            ||
| 45 | * @return string  | 
            ||
| 46 | */  | 
            ||
| 47 | public static function get_name()  | 
            ||
| 51 | |||
| 52 | /**  | 
            ||
| 53 | * @param Controller $controller  | 
            ||
| 54 | *  | 
            ||
| 55 | * @return LDAPLoginForm  | 
            ||
| 56 | */  | 
            ||
| 57 | public static function get_login_form(Controller $controller)  | 
            ||
| 61 | |||
| 62 | /**  | 
            ||
| 63 | * Performs the login, but will also create and sync the Member record on-the-fly, if not found.  | 
            ||
| 64 | *  | 
            ||
| 65 | * @param array $data  | 
            ||
| 66 | * @param Form $form  | 
            ||
| 67 | *  | 
            ||
| 68 | * @throws SS_HTTPResponse_Exception  | 
            ||
| 69 | *  | 
            ||
| 70 | * @return bool|Member|void  | 
            ||
| 71 | */  | 
            ||
| 72 | public static function authenticate($data, Form $form = null)  | 
            ||
| 122 | |||
| 123 | /**  | 
            ||
| 124 | * Try to authenticate using the fallback authenticator if enabled via config fallback_authenticator.  | 
            ||
| 125 | *  | 
            ||
| 126 | * @param array $data  | 
            ||
| 127 | * @param Form|null $form  | 
            ||
| 128 | *  | 
            ||
| 129 | * @return Member|null  | 
            ||
| 130 | */  | 
            ||
| 131 | protected static function fallback_authenticate($data, Form $form = null)  | 
            ||
| 147 | |||
| 148 | private static function form_error_msg($form, $message)  | 
            ||
| 156 | |||
| 157 | /**  | 
            ||
| 158 | * @return bool  | 
            ||
| 159 | */  | 
            ||
| 160 | private static function allow_email_logins()  | 
            ||
| 164 | |||
| 165 | /**  | 
            ||
| 166 | * @param string $identity  | 
            ||
| 167 | * @return Member|null  | 
            ||
| 168 | */  | 
            ||
| 169 | private static function get_member($identity)  | 
            ||
| 193 | }  | 
            ||
| 194 | 
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.