Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a public method on a non-final class is to be considered a BC break #111

Open
Ocramius opened this issue Oct 21, 2018 · 10 comments
Open
Assignees

Comments

@Ocramius
Copy link
Member

Ocramius commented Oct 21, 2018

Take following example:

class Counter
{
    private $count = 0;
    public function increment() : void {
        $this->count += 1;
    }
    public function count() : int {
        return $this->count;
    }
}

class LoggingCounter extends Counter
{
    private $logger;
    private $originalCounter;
    public function __construct(Logger $logger, Counter $originalCounter)
    {
         $this->logger = $logger;
         $this->originalCounter = $originalCounter;
    }
    public function increment() : void {
        $this->logger->log('increment');
        $this->originalCounter->increment();
    }
}

If Counter is modified to add an increment2 method, LoggingCounter fails (this is partly described in my article "When to declare Classes Final" ).

class Counter
{
    private $count = 0;
    public function increment() : void {
        $this->count += 1;
    }
    public function increment2() : void {
        $this->count += 2;
    }
    public function count() : int {
        return $this->count;
    }
}

Here's a test to show that:

class LoggingCounterTest extends TestCase
{
    public function incrementAndIncrement2() : void
    {
        $counter = new LoggingCounter($this->createMock(Logger::class), new Counter());
        
        $counter->increment();
        $counter->increment2();

        self::assertSame(3, $counter->count());
    }
}

This is because decorators require an update for each parent class public API change. Therefore, we should mark any addition of methods to an open class as a BC break.

@Ocramius Ocramius self-assigned this Oct 21, 2018
@Majkl578
Copy link
Contributor

It's technically correct, but IMO way too pedantic. 🤔

@Ocramius Ocramius added this to the 3.0.0 milestone Oct 21, 2018
@Ocramius
Copy link
Member Author

Still gonna add it to the default set with a new major: I'll tackle #52 as well.

It is true that these are pedantic, but I'm really just trying to categorise the BC breaks here, not saying this will fit for everyone 👍

@Ocramius
Copy link
Member Author

Hmm, previous comment got lost due to timeouts.

Wanted to clarify that I'm just categorising and enabling BC breaks as they are discovered/remembered (this one was long known, just forgotten), even if they are extremely strict, so this will appear in the defaults for the next major.

I'll try to tackle #52 before implementing this.

@cebe
Copy link

cebe commented Oct 24, 2018

It's technically correct, but IMO way too pedantic. thinking

In case you need a real world example that crashed a lot of things: yiisoft/yii2#14441 (comment) ;)

@Majkl578
Copy link
Contributor

We also have one in Doctrine: EntityRepository::count() with different signature than the one that comes from Countable, broke a lot of stuff in userland for people who implemented Countable (which doesn't make much sense, but anyway).

@goetas
Copy link

goetas commented Nov 16, 2018

as @Majkl578 said, adding bc breaks in this case is correct but a bit pedantic.
What abound introducing "optional" rules where the user can opt-in? (based on their BC promise)

@Ocramius
Copy link
Member Author

@goetas the library will provide a mathematical set of what is right/wrong, and release a new major version each time a new rule is added to that set: configuring a subset of BC breaks will be up to consumers (see #52)

@goetas
Copy link

goetas commented Nov 16, 2018

(see #52)

great

@Ocramius
Copy link
Member Author

Moving out of 3.0.0: won't get to it for now.

@Ocramius Ocramius removed this from the 3.0.0 milestone Apr 23, 2019
@Ocramius Ocramius added this to the 4.0.0 milestone Jun 9, 2019
@Ocramius Ocramius modified the milestones: 4.0.0, 5.0.0 Jul 17, 2019
@Ocramius Ocramius modified the milestones: 5.0.0, 4.3.0 Feb 8, 2020
@Ocramius Ocramius modified the milestones: 5.0.0, 5.1.0, 6.0.0 Jun 22, 2020
@Ocramius Ocramius removed this from the 6.0.0 milestone Nov 5, 2021
@Ocramius
Copy link
Member Author

Ocramius commented Nov 5, 2021

Not going to be able to drag this into 6.0 - removing milestone for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants