Why I use final

Поделиться
HTML-код
  • Опубликовано: 24 окт 2024

Комментарии • 50

  • @phpannotated
    @phpannotated  2 месяца назад +5

    🔥

  • @alpat1735
    @alpat1735 2 месяца назад +16

    Final classes promote composition. The problem is that most PHP developers don't know when to use them or otherwise prefer class inheritance.
    With that said, final classes only work effectively under following assumptions:
    - There is an abstraction (interface) that the final class implements
    - All of the public API of the final class is part of that interface

    • @Yogarine
      @Yogarine 2 месяца назад

      @@alpat1735 Exactly this.
      Proper use of `final` requires matching interfaces, and for those interfaces to be used as type hints instead of the actual final class. This allows devs to extend functionality through encapsulation, while implementing the interface.
      This whole concept breaks down the moment someone uses a final class as type hint.
      Never. 👏🏻 Use. 👏🏻 Final. 👏🏻 Classes. 👏🏻 As. 👏🏻 Argument. 👏🏻 Types.

  • @gssj-o8p
    @gssj-o8p 2 месяца назад +3

    Finally!

  • @razvbir
    @razvbir 2 месяца назад +6

    my opinion on final is final

  • @krzysztofkubacki8609
    @krzysztofkubacki8609 2 месяца назад +1

    Good stuff

  • @TheKennyWorld
    @TheKennyWorld Месяц назад

    I wish final could be used for functions parameters

  • @dkroed
    @dkroed 2 месяца назад +1

    I think you miss an argument. When writing a package you ‘agree’ on a specific interface (not necessarily being a literal interface) with the user of that package. Next (minor) versions must be backwards compatible and still comply to that interface. If the user of the package is not forced to use the interface you can’t know how the package is used and never garante backwards compatibility for next versions. Users of packages that have problems just file an issue or suggest a change. If they only want to use your code, fine. They can just copy/clone it change it and maintain it themselves.

  • @JordanHumbertodeSouza
    @JordanHumbertodeSouza 2 месяца назад

    mind sharing your pint.json or similar, i believe you're using PER preset with some other preferences.

  • @DavidSmith-ef4eh
    @DavidSmith-ef4eh Месяц назад

    tdd forces me already to prefer composition... the problem with final is you need to type 5 extra letters before the class declaration.

    • @phpannotated
      @phpannotated  Месяц назад +2

      That's a good argument for making final the default 😁

  • @markuszeller_official
    @markuszeller_official 2 месяца назад

    I like the abstraction to interfaces. That looks like more work, but it really is not.

  • @Chemaclass
    @Chemaclass 2 месяца назад

    final FTW

  • @badasukerubin
    @badasukerubin 2 месяца назад

    everything is final

  • @krycekaiolfi
    @krycekaiolfi 10 дней назад

    Man, what are we doing? We've designed the whole language around inheritance and now we are limiting it? As soon your framework/library expect that final class in any argument, the user are stuck. Every wrong decision the author made will be forced into the user.
    Without final, at least the user can workaround those limitations.
    You dont run into problems with final, because you are writing the code at both end.

  • @KingSvenDeluxe
    @KingSvenDeluxe Месяц назад +1

    Don't use final unless you absolutely know what you're doing. Funnily enough, the examples you have given highlight that final should _almost never_ be used.

    • @phpannotated
      @phpannotated  Месяц назад

      Wat? 😅

    • @KingSvenDeluxe
      @KingSvenDeluxe Месяц назад +2

      ​@@phpannotated Indeed, your code example highlighted the fact that you're having to write more code to achieve (arguably) less. It's as if you have had to implement some sort of work-around for an arbitrary restriction that you have set for yourself. I'm not saying that your code was "bad", it's fine to design things in such a manner, it's just that needlessly declaring classes as `final` is not something that should be encouraged.
      The `final` keyword does not exist for the intent of forcing a particular coding style, there are actual legitimate uses for it that you have either completely neglected to mention or you simply aren't aware of.
      Over the years, I have observed similar issues with the use of `private` and it's clear that a number of people don't actually understand what the intent is or how/when to correctly utilise it.

    • @phpannotated
      @phpannotated  Месяц назад

      ​@@KingSvenDeluxe Gotcha :)

  • @bohdan.vorona
    @bohdan.vorona 2 месяца назад +4

    Forget Laravel and Symfony - Slim!

  • @vudaltsov
    @vudaltsov 2 месяца назад +1

    I always use final by default and enforce it with PHP-CS-Fixer rules 'final_class' and 'final_public_method_for_abstract_class'.

    • @Yogarine
      @Yogarine 2 месяца назад +1

      Do you also enforce that every class has an accompanying interface, and that final classes are not allowed as argument types?

    • @vudaltsov
      @vudaltsov 2 месяца назад

      @@Yogarine , no, why would I do that? If you are talking about testing, than I mostly use classic approach to testing, not mockist (see Fowler's Mocks aren't Stubs article). I only need interfaces for polymorphism, so I don't abuse them.

    • @Yogarine
      @Yogarine 2 месяца назад

      @@vudaltsovNothing to do with tests.
      It’s because to encapsulate final classes properly, you need to have accompanying interfaces you can implement and use as argument types.
      The biggest mistake people make when using final classes to enforce encapsulation, is not consistently providing and using accompanying interface. Behat is a good example of it. Every time I tried to write an extension for Behat I’ve run into issues because they decided to use final classes as argument types, making it impossible to encapsulate the appropriate classes.

    • @vudaltsov
      @vudaltsov 2 месяца назад

      @@Yogarine in my libraries I give users only the extension points I want them to have and I make sure they are easy to use. The rest is marked @internal and is not meant to be accessed. Concerning library's API I don't see a problem with, for example, a value object parameter Color that is a final class and has static constructors like fromHex() or fromRGB($red, $green $blue).

    • @Yogarine
      @Yogarine 2 месяца назад

      @@vudaltsov And why wouldn’t you want to allow people to provide their own implementation for Color?

  • @SaiyanJin85
    @SaiyanJin85 2 месяца назад +1

    But obviously if I extend a class from a package the responsibility of correctness is mine, not the package's maintainer. I get your point that it makes the package maintenance harder but you can always enforce rules when someone makes an issue like providing code samples and stuff like that

    • @phpannotated
      @phpannotated  2 месяца назад

      Still, it's an additional burden for maintainers :)

    • @SaiyanJin85
      @SaiyanJin85 2 месяца назад

      @@phpannotated Thanks for the reply!

    • @phpannotated
      @phpannotated  2 месяца назад +1

      @@SaiyanJin85 Thanks for the reply about the reply!

  • @CottonInDerTube
    @CottonInDerTube 2 месяца назад +1

    The problem with final is that it causes problems at the user side.
    The maintainer can later change the class so the final is no more a problem.
    But the user needs the solution NOW ... which leads to NOT better code, or not using the class/repo.
    =)

    • @phpannotated
      @phpannotated  2 месяца назад +1

      From my point of view, I answered that question in the video: this comes down to the package not having a proper design that takes final into account. For me that's not an argument against final, it's an argument against suboptimal package design. Do you think I should have made that point more clear in the video?

    • @CottonInDerTube
      @CottonInDerTube 2 месяца назад

      @@phpannotated No, i understood your arguments. And i agree witih you on the maintainer side.
      Im just bringing my argument from the user side =)

  • @StrangerWolf-x6z
    @StrangerWolf-x6z 2 месяца назад +1

    It looks like the final may violate O from SOILD

    • @phpannotated
      @phpannotated  2 месяца назад +7

      "O" stands for "open for extension, but closed for modification", most of the "bad" examples (ab)use inheritance to modify behaviour. This is exactly why final helps with SOLID :)

    • @StrangerWolf-x6z
      @StrangerWolf-x6z 2 месяца назад +1

      @@phpannotated Objects or entities should be open for extension but closed for modification. != If the class itself is being defined final then it cannot be extended.(this is from PHP doc)

    • @dkroed
      @dkroed 2 месяца назад

      @@StrangerWolf-x6zgood point. So then you should make all public and protected methods final and keep the class open.

    • @remiarbousset476
      @remiarbousset476 Месяц назад

      o from solid does not talk about inheritance ...
      "open to extension, closed to modification" should be read as "open to behavioral extension, closed to modification", some pretty pattern as observer or decorator let us easily extends the behavior of a class, which cannot be modified because it"s final
      final is not an issue for the o from solid , it's the solution

  • @krzysiej--9229
    @krzysiej--9229 2 месяца назад

    fżnaZ cZass :D

  • @spicynoodle7419
    @spicynoodle7419 2 месяца назад +4

    Before watching the video, *final* sucks because I can't mock the class

    • @spicynoodle7419
      @spicynoodle7419 2 месяца назад

      Final is ok for stuff like classes for the state pattern, but not for action or service classes

    • @spicynoodle7419
      @spicynoodle7419 2 месяца назад

      Alright, I've finished the video. Interfaces solve the mocking issue, though you can't make an interface for every class. So, while *final* can be used in a lot of places, it's not something you can spam everywhere like *readonly* in properties

    • @phpannotated
      @phpannotated  2 месяца назад +1

      @@spicynoodle7419 I really don't agree. In my experience, all classes that need to be mocked can have a fitting interface

    • @ovidiu_nl
      @ovidiu_nl 21 день назад

      They "can" have an interface, but it's not a given that the library author will actually do it. It happened to me a lot that I had to work with (closed source) libraries that other team in the company provided where all the classes were marked "final" just because someone's linter liked it that way, and there was no reasonable way to get a mock object.

  • @SebastianFischer
    @SebastianFischer 2 месяца назад +2

    Why is it your concern that following developers inherit your class and do stuff with it? You don't have to support other changes.
    And yes. I'm totally against final unless there is a reason, like security concerns.
    Inheritance in it self is not bad.

  • @adaliszk
    @adaliszk 2 месяца назад +3

    Recently ran into final, quickly come to the opinion that no library should use final for their published classes, though they can freely use it internally.
    Its great for application scope, but horrible for sharing.