############# # Initial state we have an extension Thing with a method draw ############# ///////////// // Core ///////////// /** * Thing that can draw */ interface Thing { /** * @param int $x */ public function draw( $x ); } /** * Trait used to ease evolution of the Thing interface */ trait ThingBCTrait { } /** * Base class for Thing */ abstract class BaseThing implements Thing { use ThingBCTrait; } ///////////// // Extension ///////////// class SimpleThing extends BaseThing { /** * @param int $x */ public function draw( $x ) { print( $x ); } } class ThingAndThat extends That implements Thing { use ThingBCTrait; /** * @param int $x */ public function draw( $x ) { print( $x ); } } #################### # Goal 1: warn extensions that they need to implement draw2 # Goal 2: gently tell call sites to move to draw2 # We introduce draw2 as a replacement of draw # We soft deprecate draw to gently warn call sites # We add draw2 with a warning to our BCTrait to not break existing extensions #################### ///////////// // Core ///////////// /** * Thing that can draw */ interface Thing { /** * @param int $x * @deprecated use draw2d */ public function draw( $x ); /** * @param int $x * @param int $y */ public function draw2d( $x, $y ); } /** * Trait used to ease evolution of the Thing interface */ trait ThingBCTrait { public function draw2d( $x, $y ) { wfDeprecated( __CLASS__ . " must implement draw2d" ); $this->draw( $x ); } } /** * Base class for Thing */ abstract class BaseThing implements Thing { use ThingBCTrait; } ///////////// // Extension ///////////// class SimpleThing extends BaseThing { /** * @param int $x */ public function draw( $x ) { print( $x ); } } class ThingAndThat extends That implements Thing { use ThingBCTrait; /** * @param int $x * @deprecated */ public function draw( $x ) { // We can implement our own BC strategy $this->draw2d( $x, 12 ); } public function draw2d( $x, $y ) { print( "$x:$y" ); } } ####################### # We finally remove draw from Thing # We keep a hard deprecation warning for draw in ThingBCTrait in case some old call sites are still using it # The Thing interface is now what we expect # Extensions that want to be compatible with a old MW core version can keep their old draw method. ####################### ///////////// // Core ///////////// /** * Thing that can draw */ interface Thing { /** * @param int $x * @param int $y */ public function draw2d( $x, $y ); } /** * Trait used to ease evolution of the Thing interface */ trait ThingBCTrait { public function draw( $x ) { wfDeprecated( __METHOD__ . " is deprecated" ); $this->draw2d( $x, 0 ); } } /** * Base class for Thing */ abstract class BaseThing implements Thing { use ThingBCTrait; } ///////////// // Extension ///////////// class SimpleThing extends BaseThing { /** * @param int $x * @param int $y */ public function draw2d( $x, $y ) { print( "$x:$y" ); } } class ThingAndThat extends That implements Thing { use ThingBCTrait; /** * @param int $x * @deprecated */ public function draw( $x ) { // We can implement our own BC strategy $this->draw2d( $x, 12 ); } public function draw2d( $x, $y ) { print( "$x:$y" ); } }