• ZILtoid1991@lemmy.world
    link
    fedilink
    arrow-up
    14
    ·
    1 day ago

    Entity Component System all the things!

    I might write an XML ECS parser, as a joke. Practical? No! Probably even slower than the XML DOM? Yes! Funny? Yes!

  • tiramichu@sh.itjust.works
    link
    fedilink
    arrow-up
    173
    arrow-down
    3
    ·
    3 days ago

    I’ll say this now.

    Inheritance is the most misused capability of OOP which programmers think makes their code look smart, but most of the time just makes a giant fucking mess.

    • VibeSurgeon@piefed.social
      link
      fedilink
      English
      arrow-up
      1
      ·
      2 hours ago

      In all honesty, the protocols and structs-thing they talk about in Swift-land is the way to go. Interfaces and data classes in JVM-land

    • Wirlocke@lemmy.blahaj.zone
      link
      fedilink
      arrow-up
      6
      arrow-down
      1
      ·
      edit-2
      1 day ago

      I’ve moved away from Classes in general unless it truly makes code more streamlined. The main language I was taught in highschool was Java and it’s just so liberating not needing to turn everything into an object.

      But recently I’ve used a Class specifically for Inheritance. I’m making an extension to Pytorch and almost everything in Pytorch uses Tensors as a medium. I made a new kind of tensor that inherits the Tensor class to add specific restrictions on how it behaves. Because of this, this new tensor object can be used with any of the preexisting pytorch functions while also validating the results, reverting to a Tensor if it becomes invalid.

      Even in this situation though, all my programming logic rests in it’s own static functions, and the class contains functions that call the static version. The only actual logic the inherited object handles is validating the data.

      Because of this, I feel like inheritance is most useful when you’re inheriting someone else’s code to make it compatible with their library. I don’t think I’ll ever inherit my own objects because that’s how you end up with Java.

    • mesa@piefed.social
      link
      fedilink
      English
      arrow-up
      46
      arrow-down
      1
      ·
      2 days ago

      Its the best/worst thing about OOP no matter what language.

      We had a rule at work that if you are 3 levels or more down an inheritance tree, then you are too far. The cognitive load is just too much, plus everything stops making sense.

      One level can be great (MVC all have great conventions, MCP as well). Two can be pushing it (Strategy pattern when you have physical devices and cant be connected all the time, Certain kinds of business logic that repeat hundreds of times, etc…) But even there you are kinda pushing it.

      I need code that I can look at a month from now and know WTF is happening. And sometimes its better to have less DRY and more comprehension. Or maybe im just a forever mediocre dev and dont see the “light”. I dunno.

      • sip@programming.dev
        link
        fedilink
        arrow-up
        3
        ·
        1 day ago

        composition can help with all of that. factories, strategies, injections are all composition patterns that work fine.

        business logic that repeats? extract it to it’s own thing (class, function, etc) and pass it as a param to the supposed childs.

        mvc? controllers don’t need to extend anything, just have them accept the framework through the constructor and request and response as args. views? same. models? perhaps only if doing an active record, but a repo pattern with plain objects is a good pattern too.

        I never seen a clean inheritance implementation for a decently sized problem. it mostly works for tiny ones.

      • Ethan@programming.dev
        link
        fedilink
        English
        arrow-up
        7
        arrow-down
        1
        ·
        2 days ago

        When I first started using Go I bemoaned the lack of true inheritance and classes. Now I love it.

          • Ethan@programming.dev
            link
            fedilink
            English
            arrow-up
            3
            ·
            22 hours ago

            Depends on what you mean by “basically a class”. If you mean inheritance, overriding, and more generally class/inheritance based polymorphism, no, it does not. Those require dynamic dispatch, which Go does not have (for concrete types, which is what we’re talking about here).

      • tiramichu@sh.itjust.works
        link
        fedilink
        arrow-up
        20
        ·
        2 days ago

        This is exactly how I feel too. A little bit of repetition is totally worth it, versus having inappropriate coupling, or code that jumps in and out of parent/child classes everywhere so you can hardly keep it in your head what’s going on.

        I freely accept that I AM a mediocre dev, but if that lends me to prefer code that is comprehensible and maintainable then I think being mediocre is doing my team a favour, honestly.

          • jason@discuss.online
            link
            fedilink
            English
            arrow-up
            3
            arrow-down
            1
            ·
            1 day ago

            Yup. They made it to the other side of the bell curve meme. Most developers have an OOP phase until they learn that it’s utter bullshit.

            • Grendel@tiny.tilde.website
              link
              fedilink
              arrow-up
              2
              ·
              1 day ago

              @jason

              I do like being able to easily bundle properties and functions together. I think objects are useful if kept in their simplest form.

              Though I think some would argue that not using inheritance and interfaces and such precludes it from really counting as OOP

              • jason@discuss.online
                link
                fedilink
                English
                arrow-up
                2
                ·
                edit-2
                17 hours ago

                I can definitely respect a limited approach. I personally don’t find any benefit from it. Anecdotally, I’ve become much more productive since switching from OOP style C++, to just straight C. I think a lot of that comes from the boilerplate and ceremony required to make it do the thing, but in C, you just do the thing.

                I also think even using objects tends to encourage poorer design choices by thinking in terms of individual items (and their lifetimes) which is enforced by the constructor/destructor model. As opposed to thinking in terms of groups of items which leads to simpler and safer code.

      • fibojoly@sh.itjust.works
        link
        fedilink
        arrow-up
        9
        ·
        edit-2
        2 days ago

        PTSD flashbacks to the codebase I started on in 2008 which had… I don’t even remember. Like six or seven levels. Fucking nightmare. I did a printout of the analysis Doxygen gave me and it ended up as a 4x3 meters poster ;_;

      • calcopiritus@lemmy.world
        link
        fedilink
        arrow-up
        6
        ·
        2 days ago

        But if I have to make an Array I have to inherit from Indexable which inherits from Collection which inherits from Object! How else am I supposed to implement an Array?

        • SparroHawc@lemmy.zip
          link
          fedilink
          arrow-up
          4
          ·
          edit-2
          24 hours ago

          Admittedly this is why I like C#'s ‘implements’ paradigm. Doesn’t have to inherit, it just has to fulfill the contract, and then you can pass it to anything that expects the interface it implements. Keeps you from building giant trees.

          • calcopiritus@lemmy.world
            link
            fedilink
            arrow-up
            3
            ·
            18 hours ago

            As a rust developer I feel obligated by religion to make this comment:

            Then you’d love rust! Rust only has “interfaces” (called traits) but doesn’t have inheritance. You just have traits that don’t inherit from anything and structs (that don’t inherit from other structs) that implement X amount of traits.

            So you can have the good things about OOP without the bad ones.

            And these traits allow you to make trait objects, which would be like regular objects in C# (with vtables for the methods). If 2 different structs implement the same trait, you can “downcast” them to a trait object and store them in the same array. Or pass it is an argument to a function that wants something that implements that trait but doesn’t care about the specific struct. You can of course cast it back later to the original struct.

            • SparroHawc@lemmy.zip
              link
              fedilink
              arrow-up
              2
              ·
              6 hours ago

              I like interfaces as a supplement to inheritance. The strength of inheritance is getting all of the internal functionality of the parent class, while still allowing you to differentiate between children.

              Interfaces are useful for disparate classes which don’t have much in common besides fitting within a specific use case, rather than classes that are very similar to each other but need specific distinguishing features.

        • mesa@piefed.social
          link
          fedilink
          English
          arrow-up
          2
          ·
          2 days ago

          I remember some crazy stuff back when I had to work with a Java + ember.js project. Everything was like that.

      • Grendel@tiny.tilde.website
        link
        fedilink
        arrow-up
        3
        ·
        2 days ago

        @mesamunefire
        @tiramichu

        I totally agree on this. I found that often things that appeared to need inheritance at first glance often didn’t if I gave deeper thought to it.

        Granted I was working on much smaller projects rather than crazy huge multi team enterprise apps, but I’d guess that even then this is a good “rule of thumb”.

        • mesa@piefed.social
          link
          fedilink
          English
          arrow-up
          2
          ·
          2 days ago

          Cool, good to know someone else has the same experience.

          Ive been on a couple of multi-year projects and they are NOT fun with OOP + developer went crazy with patterns they were experimenting at the time. Its what made the “rule” pop up to begin with.

    • red_tomato@lemmy.world
      link
      fedilink
      arrow-up
      103
      ·
      edit-2
      3 days ago

      Hold on, I’m in the middle of drawing an inheritance graph so I know how Dog is related to AircraftCarrier.

      • blackn1ght@feddit.uk
        link
        fedilink
        English
        arrow-up
        78
        ·
        edit-2
        3 days ago
        public interface ICanTravelThroughTheAir
        {
        
        }
        
        public class Flea : ICanTravelThroughTheAir
        {
        
        }
        
        public class AircraftCarrier
        {
          private readonly List<ICanTravelThroughTheAir> _aircraft = new();
        
          public void AddAircraft(ICanTravelThroughTheAir flyingThing)
          {
            _aircraft.Add(flyingThing);
          }
        }
        
        public class Dog : AircraftCarrier
        {
            public void Woof()
            {
                Console.WriteLine("Bitch I'm an aircraft carrier!");
            }
        }
        
        public static class Program
        {
          public int Main(string[] args)
          {
            var dog = new Dog();
            
            for (var i = 0; i < 10000; i++)
            {
                dog.AddAircraft(new Flea());
            }
        
            dog.Woof();
          }
        }
        
          • VibeSurgeon@piefed.social
            link
            fedilink
            English
            arrow-up
            2
            ·
            2 hours ago

            I managed to organically create a StrategyFactory at work once.

            It was a good design, but it felt extremely wrong

          • Supercrunchy@programming.dev
            link
            fedilink
            arrow-up
            24
            ·
            2 days ago

            And dependency injection!

            Every class needs to use DI for calling other classes, even though we’ll have anyway just a single implementation for all of them, and we won’t be using this flexibility at all (not even for tests where it might be useful for mocking dependencies).

        • ZILtoid1991@lemmy.world
          link
          fedilink
          arrow-up
          3
          ·
          edit-2
          1 day ago

          Now someone needs to make it an entity component system!

          Attempt 1:

          public struct Entity {
            bool isDog : 1;
            bool isAircraftCarrier : 1;
            bool isFlea : 1;
            bool canFlyInAir : 1;
            ubyte opt_numOfAircrafts : 4;
            int entityID;
            int opt_parentID;
            static Entity createDog(int entityID) {
              Entity result;
              result.isDog = true;
              result.entityID = entityID;
              return result;
            }
            static Entity createFlea(int entityID) {
              Entity result;
              result.isFlea = true;
              result.canFlyInAir = true;
              result.entityID = entityID;
              return result;
            }
            void addAirCraft(ref Entity aircraft) {
              if (aircraft.canFlyInAir && this.isAircraftCarrier) {
                aircraft.opt_parentID = this.entityID;
                this.opt_numOfAircrafts++;
              }
            }
            void woof() {
              if (isDog) {
                if (isAircraftCarrier) writeln("I'm a motherfucking aircraft carrier");
                else writeln("Woof!");
              }
            }
          }
          
          void main() {
            Entity dog = Entity.createDog(1);
            Entity flea = Entity.createFlea(2);
            dog.woof();
            dog.isAircraftCarrier = true;
            dog.addAirCraft(flea);
            dog.woof();
          }
          
      • criss_cross@lemmy.world
        link
        fedilink
        arrow-up
        2
        ·
        1 day ago

        Was gonna say just this. Inheritance is powerful but something to reach for sparingly. 80% of the time aggregation and composition can solve the problems.

        I’ve cleaned up too many inheritance nightmares in my day from people who insisted inheritance was the way to go.

    • FunkyCheese@lemmy.dbzer0.com
      link
      fedilink
      English
      arrow-up
      11
      arrow-down
      1
      ·
      2 days ago

      I learned about it in school and we didna few assignments for it

      But… never seen or heard anyone mention it outside of that

      I guess we can make up some nische vases

      I did hear it can be useful for video games though. But then again im sure people can manage fint without, as well

      • Valmond@lemmy.dbzer0.com
        link
        fedilink
        arrow-up
        14
        ·
        2 days ago

        It’s wildly useful, when you store a lot of similar stuff, or treat a lot of similar stuff etc.

        Like a GUI, a rendering engine or a scientific soft. Video games, any soft with users, and so on.

        I get that people misuse it but for me it’s wild that people think you should like program without it, like at all cost.

      • Railcar8095@lemmy.world
        link
        fedilink
        arrow-up
        6
        ·
        2 days ago

        We use it a lot when we have a solution that works for 95% of customers and a few need random things.

        Else we will have multiple markets changing the same function with a thousand if else

        Main issue is that makes it so that some functions are never generalized, like when customer A wanted to use an equal filter, customer B wanted a IN filter, and the rest have no filtering capability at all.

    • vapeloki@lemmy.world
      link
      fedilink
      arrow-up
      6
      arrow-down
      2
      ·
      2 days ago

      And polymorphism is the only way you could expose those composite Interfaces as bindings on C API based languages. And polymorphism is part of OOP.

      If we take the text book definition of OOP, then the kernel is OOP …

  • kibiz0r@midwest.social
    link
    fedilink
    English
    arrow-up
    48
    ·
    2 days ago

    The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said “Master, I have heard that objects are a very good thing - is this true?” Qc Na looked pityingly at his student and replied, “Foolish pupil - objects are merely a poor man’s closures.”

    Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire “Lambda: The Ultimate…” series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress.

    On his next walk with Qc Na, Anton attempted to impress his master by saying “Master, I have diligently studied the matter, and now understand that objects are truly a poor man’s closures.” Qc Na responded by hitting Anton with his stick, saying “When will you learn? Closures are a poor man’s object.” At that moment, Anton became enlightened.

  • RustyNova@lemmy.world
    link
    fedilink
    arrow-up
    60
    ·
    edit-2
    2 days ago

    I LOVE TRAITS. YOU’LL HAVE TO TAKE THEM FROM MY COLD DEAD HANDS

    [Insert SpongeBob screaming meme]

    • PlexSheep@infosec.pub
      link
      fedilink
      arrow-up
      8
      ·
      2 days ago

      TRAITS ARE SO USEFUL AND STRUCTS ARE EASILY REPRESENTED IN MEMORY AND WORKED WITH, COMBINED THEY WILL TAKE OVER THE LINUX KERNEL AND THE WORLD

    • wewbull@feddit.uk
      link
      fedilink
      English
      arrow-up
      2
      ·
      1 day ago

      Do you include “traits” and “interfaces” under the title “inheritance”?

    • Supercrunchy@programming.dev
      link
      fedilink
      English
      arrow-up
      6
      ·
      2 days ago

      It might be nice to use in some very specific cases (e.g. addition-operation is a binary-operation AST node which is an AST node).

      In most of the cases it just creates noise though, and you can usually do something different anyway to implement the same feature. For example in rust, just use enums and list all the possible cases and it’s even nicer to use than inheritance.

      • tatterdemalion@programming.dev
        link
        fedilink
        arrow-up
        2
        ·
        1 day ago

        Some legacy Python code that already used inheritance. I had to extend it, and it was pretty infeasible to refactor the whole thing to not use inheritance. Not sure if I technically regretted that decision, but it was definitely painful, since Python inheritance makes it really hard to follow program control flow.

        • Valmond@lemmy.dbzer0.com
          link
          fedilink
          arrow-up
          1
          ·
          9 hours ago

          Non typed inheritance, what could go wrong eh. You can just ‘add’ a function to a class dynamically in python, that is so bad.

          Done any C++ classes & inheritance?

          • tatterdemalion@programming.dev
            link
            fedilink
            arrow-up
            1
            ·
            4 hours ago

            It was actually typed. Python had type annotations at the time.

            I only wrote C++ very early in my career so I don’t remember much, but I’m sure I at least tried some inheritance in toy games I would write. All of that code was trash though by my standards today.

  • NigelFrobisher@aussie.zone
    link
    fedilink
    arrow-up
    16
    arrow-down
    1
    ·
    edit-2
    2 days ago

    Examples of inheritance hierarchies are always totally useless shit like this - what if a cow is an animal; What if a cow is a mammal, all mammals are animals and all mammals have a lactate() method?

    • ulterno@programming.dev
      link
      fedilink
      English
      arrow-up
      10
      ·
      1 day ago

      Because any real life use that might come to mind would probably be related to some NDA protected database in a company.
      And it is otherwise hard to think of anything at the spot, so just go with what the first example on the web-search came up with.

  • Hirom@beehaw.org
    link
    fedilink
    arrow-up
    4
    arrow-down
    1
    ·
    2 days ago

    Separating data structure from implementation has benefits.

    In languages with classic OOP classes and objects, it’s often necessary to write wrappers or adapters to allow new operations on existing objects. This adds overhead and require more code.

  • panda_abyss@lemmy.ca
    link
    fedilink
    arrow-up
    2
    ·
    2 days ago

    I wish I could take go’s interfaces and drop them into zig, and that’s all the object oriented concepts I need.