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:
Complex classes like ObjectCache often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ObjectCache, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 80 | class ObjectCache { | 
            ||
| 81 | /** @var BagOStuff[] Map of (id => BagOStuff) */  | 
            ||
| 82 | public static $instances = [];  | 
            ||
| 83 | /** @var WANObjectCache[] Map of (id => WANObjectCache) */  | 
            ||
| 84 | public static $wanInstances = [];  | 
            ||
| 85 | |||
| 86 | /**  | 
            ||
| 87 | * Get a cached instance of the specified type of cache object.  | 
            ||
| 88 | *  | 
            ||
| 89 | * @param string $id A key in $wgObjectCaches.  | 
            ||
| 90 | * @return BagOStuff  | 
            ||
| 91 | */  | 
            ||
| 92 | 	public static function getInstance( $id ) { | 
            ||
| 99 | |||
| 100 | /**  | 
            ||
| 101 | * Get a cached instance of the specified type of WAN cache object.  | 
            ||
| 102 | *  | 
            ||
| 103 | * @since 1.26  | 
            ||
| 104 | * @param string $id A key in $wgWANObjectCaches.  | 
            ||
| 105 | * @return WANObjectCache  | 
            ||
| 106 | */  | 
            ||
| 107 | 	public static function getWANInstance( $id ) { | 
            ||
| 114 | |||
| 115 | /**  | 
            ||
| 116 | * Create a new cache object of the specified type.  | 
            ||
| 117 | *  | 
            ||
| 118 | * @param string $id A key in $wgObjectCaches.  | 
            ||
| 119 | * @return BagOStuff  | 
            ||
| 120 | * @throws MWException  | 
            ||
| 121 | */  | 
            ||
| 122 | 	public static function newFromId( $id ) { | 
            ||
| 132 | |||
| 133 | /**  | 
            ||
| 134 | * Get the default keyspace for this wiki.  | 
            ||
| 135 | *  | 
            ||
| 136 | * This is either the value of the `CachePrefix` configuration variable,  | 
            ||
| 137 | * or (if the former is unset) the `DBname` configuration variable, with  | 
            ||
| 138 | * `DBprefix` (if defined).  | 
            ||
| 139 | *  | 
            ||
| 140 | * @return string  | 
            ||
| 141 | */  | 
            ||
| 142 | 	public static function getDefaultKeyspace() { | 
            ||
| 152 | |||
| 153 | /**  | 
            ||
| 154 | * Create a new cache object from parameters.  | 
            ||
| 155 | *  | 
            ||
| 156 | * @param array $params Must have 'factory' or 'class' property.  | 
            ||
| 157 | * - factory: Callback passed $params that returns BagOStuff.  | 
            ||
| 158 | * - class: BagOStuff subclass constructed with $params.  | 
            ||
| 159 | * - loggroup: Alias to set 'logger' key with LoggerFactory group.  | 
            ||
| 160 | * - .. Other parameters passed to factory or class.  | 
            ||
| 161 | * @return BagOStuff  | 
            ||
| 162 | * @throws MWException  | 
            ||
| 163 | */  | 
            ||
| 164 | 	public static function newFromParams( $params ) { | 
            ||
| 207 | |||
| 208 | /**  | 
            ||
| 209 | * Factory function for CACHE_ANYTHING (referenced from DefaultSettings.php)  | 
            ||
| 210 | *  | 
            ||
| 211 | * CACHE_ANYTHING means that stuff has to be cached, not caching is not an option.  | 
            ||
| 212 | * If a caching method is configured for any of the main caches ($wgMainCacheType,  | 
            ||
| 213 | * $wgMessageCacheType, $wgParserCacheType), then CACHE_ANYTHING will effectively  | 
            ||
| 214 | * be an alias to the configured cache choice for that.  | 
            ||
| 215 | * If no cache choice is configured (by default $wgMainCacheType is CACHE_NONE),  | 
            ||
| 216 | * then CACHE_ANYTHING will forward to CACHE_DB.  | 
            ||
| 217 | *  | 
            ||
| 218 | * @param array $params  | 
            ||
| 219 | * @return BagOStuff  | 
            ||
| 220 | */  | 
            ||
| 221 | 	public static function newAnything( $params ) { | 
            ||
| 231 | |||
| 232 | /**  | 
            ||
| 233 | * Factory function for CACHE_ACCEL (referenced from DefaultSettings.php)  | 
            ||
| 234 | *  | 
            ||
| 235 | * This will look for any APC style server-local cache.  | 
            ||
| 236 | * A fallback cache can be specified if none is found.  | 
            ||
| 237 | *  | 
            ||
| 238 | * // Direct calls  | 
            ||
| 239 | * ObjectCache::getLocalServerInstance( $fallbackType );  | 
            ||
| 240 | *  | 
            ||
| 241 | * // From $wgObjectCaches via newFromParams()  | 
            ||
| 242 | * ObjectCache::getLocalServerInstance( array( 'fallback' => $fallbackType ) );  | 
            ||
| 243 | *  | 
            ||
| 244 | * @param int|string|array $fallback Fallback cache or parameter map with 'fallback'  | 
            ||
| 245 | * @return BagOStuff  | 
            ||
| 246 | * @throws MWException  | 
            ||
| 247 | * @since 1.27  | 
            ||
| 248 | */  | 
            ||
| 249 | 	public static function getLocalServerInstance( $fallback = CACHE_NONE ) { | 
            ||
| 266 | |||
| 267 | /**  | 
            ||
| 268 | * @param array $params [optional] Array key 'fallback' for $fallback.  | 
            ||
| 269 | * @param int|string $fallback Fallback cache, e.g. (CACHE_NONE, "hash") (since 1.24)  | 
            ||
| 270 | * @return BagOStuff  | 
            ||
| 271 | * @deprecated 1.27  | 
            ||
| 272 | */  | 
            ||
| 273 | 	public static function newAccelerator( $params = [], $fallback = null ) { | 
            ||
| 284 | |||
| 285 | /**  | 
            ||
| 286 | * Create a new cache object of the specified type.  | 
            ||
| 287 | *  | 
            ||
| 288 | * @since 1.26  | 
            ||
| 289 | * @param string $id A key in $wgWANObjectCaches.  | 
            ||
| 290 | * @return WANObjectCache  | 
            ||
| 291 | * @throws MWException  | 
            ||
| 292 | */  | 
            ||
| 293 | 	public static function newWANCacheFromId( $id ) { | 
            ||
| 317 | |||
| 318 | /**  | 
            ||
| 319 | * Get the main cluster-local cache object.  | 
            ||
| 320 | *  | 
            ||
| 321 | * @since 1.27  | 
            ||
| 322 | * @return BagOStuff  | 
            ||
| 323 | */  | 
            ||
| 324 | 	public static function getLocalClusterInstance() { | 
            ||
| 329 | |||
| 330 | /**  | 
            ||
| 331 | * Get the main WAN cache object.  | 
            ||
| 332 | *  | 
            ||
| 333 | * @since 1.26  | 
            ||
| 334 | * @return WANObjectCache  | 
            ||
| 335 | */  | 
            ||
| 336 | 	public static function getMainWANInstance() { | 
            ||
| 341 | |||
| 342 | /**  | 
            ||
| 343 | * Get the cache object for the main stash.  | 
            ||
| 344 | *  | 
            ||
| 345 | * Stash objects are BagOStuff instances suitable for storing light  | 
            ||
| 346 | * weight data that is not canonically stored elsewhere (such as RDBMS).  | 
            ||
| 347 | * Stashes should be configured to propagate changes to all data-centers.  | 
            ||
| 348 | *  | 
            ||
| 349 | * Callers should be prepared for:  | 
            ||
| 350 | * - a) Writes to be slower in non-"primary" (e.g. HTTP GET/HEAD only) DCs  | 
            ||
| 351 | * - b) Reads to be eventually consistent, e.g. for get()/getMulti()  | 
            ||
| 352 | * In general, this means avoiding updates on idempotent HTTP requests and  | 
            ||
| 353 | * avoiding an assumption of perfect serializability (or accepting anomalies).  | 
            ||
| 354 | * Reads may be eventually consistent or data might rollback as nodes flap.  | 
            ||
| 355 | * Callers can use BagOStuff:READ_LATEST to see the latest available data.  | 
            ||
| 356 | *  | 
            ||
| 357 | * @return BagOStuff  | 
            ||
| 358 | * @since 1.26  | 
            ||
| 359 | */  | 
            ||
| 360 | 	public static function getMainStashInstance() { | 
            ||
| 365 | |||
| 366 | /**  | 
            ||
| 367 | * Clear all the cached instances.  | 
            ||
| 368 | */  | 
            ||
| 369 | 	public static function clear() { | 
            ||
| 373 | }  | 
            ||
| 374 | 
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: