3
unclesam
24d

No one can answer why classes over functions.

Comments
  • 4
    I use class when I wanted to easily extend it (inheritance) and when I wanted to prevent other from using dangerous thing by using private and protected access modifier.

    class Foo

    {

    public int add(int a,int b)

    {

    return internalAdd(a,b);

    }

    private int internalAdd(int a,int b)

    {

    return a+b;

    }

    }

    I found one benefit of class is that it let me provide an interface to the user. In the example above the user of the class only need to deal with "add" method (since it a public interface) and I am allow to change the implementation (internalAdd method) however I wanted as long as I follow the contract that it will provide a sum.

    Otherwise I use free function.Below link is the argument for free function.

    https://drdobbs.com/cpp/...
  • 4
    Classes can encapsulate a set of functions. Functions can't encapsulate functions. At least in C
  • 4
    @Bybit260
    Turns out, you don't need to, bc functional composition, lifting and higher order functions

    “Higher Order Functions (Composing Software)” by Eric Elliott https://link.medium.com/YtRmdJSmb8
  • 3
    @Bybit260 even python and js can have functions inside other functions, lambdas, and so on. C is very primitive in that regard (but understandably so).
  • 4
    @Bybit260

    You can use functional pointer.
  • 0
    @SortOfTested @RememberMe @mr-user I agree with you all. Also don't forget I specified C as my reference. Also @SortOfTested Thanks for the link.
  • 2
    Because it's easier 😛

    Object oriented is easier for humans to understand than complex functions. Literally the main reason the thing came to life. No one said you couldn't do it in functions, but everyone said if it's getting stupidly complex, simplify it by using OOP.
  • 0
    @NoMad FP solves the complexity problem too. OOP isn't the only kid in the block.
  • 1
    @RememberMe complexity of understanding???? I'd argue against that.

    It is much easier to understand an architectural design in OOP than in FP.
  • 1
    @RememberMe don't get me wrong, I'm not saying FP is not usable. It does have its use cases, but it's not the lazy easy solution.
  • 0
    @NoMad not really, depends on the design. Some things map to FP better, some things map to OOP better. OOP can become nightmarish if used in a place where it doesn't fit, similarly with typical FP patterns like monads.

    Composing functions is really nice usually, almost always makes the code more pleasant to reason about and work with.
  • 3
    @RememberMe

    I also like FP but OOP seem a lot easier to teach because it is more "natural" to explain. FP seem more abstract to the beginner than OOP.

    I think the reason FP is not popular as it should is due to it over complicated term. Monad, Bind , Functor, Pattern Matching,---etc. When you search what the term mean you are hit 9 out of 10 times with math or math-like explanation. People don't like math very much therefore the FP which is closely linked to math is not very popular.

    We need more book like "Functional Programming, Simplified - Alvin Alexander" (https://alvinalexander.com/scala/...) which explain FP in non math like manner.
  • 1
    As for the actual topic: you want classes if you have a very close coupling between state and behaviour. Typically for GUI objects and simulation of things, the latter including many games.

    On the other hand, for a input-processing-output kind of software, objects don't make much sense and tend to get in the way. Procedural is fine here.

    Glorified structs with data and functions, btw, were not what OOP was meant to be when Alan Key invented it. It was about actors passing messages to each other, which is an architectural pattern and can be implemented with both Java/C++ style OOP and procedural programming.
  • 1
    @mr-user I agree, FP is too tied to its mathematical background and needs better terminology (on the other hand the precision of mathematical terminology is a bonus). But if you're experienced enough, you can judge pretty effectively when to use what.

    @Fast-Nop hilariously enough, the most OOP language I've ever seen, in terms of Kay's definition, is Erlang - and it's traditionally counted as FP. It's built around actor model programming.

    FP and OOP start to intertwine quite a bit as you go deeper. It's easy to express certain classic OOP features like dynamic dispatch using Rank N Types, for example.
  • 2
    @RememberMe I once had a small AVR controller where no RTOS would fit, and I ended up with Kay style OOP, implemented procedurally.

    The main loop would call each pseudo-task entry function sequentially. Blocking wait was not possible of course, that went via dedicated waiting states in the task state machines. So it was like cooperative sequential multitasking.

    The kicker was that these tasks were isolated logically by putting them into separate C files and making everything file static except what was needed for public interfacing.

    Each task had an inbox for messages, and it knew the central postmaster box where it would write outgoing messages to. One of the tasks was the postmaster function which, depending on the message destination, copied it to the corresponding inbox.

    Since each message had IDs for origin and destination, a task could even answer to a message without caring about the sender, just by using the origin of the received message as destination for the answer.
  • 0
    You clearly forgot that functional programming is always better than any other approach no matter the task. Anyone who think it isn’t is just a moron. Reeeeeeeee!
  • 6
    @uyouthe While functional programming hasn't taken off that much, dysfunctional programming is totally mainstream.
  • 0
    @NoMad funny, I've always thought FP is easier than OOP: to write, to architect and to understand. OOP just doesn't make much sense to me as in context with the real world. Then again, real world doesn't make sense...
  • 2
    for me, class is to encapsulate data that can be dealt with directly or indirectly with methods. the class own the data-set and the procedure that affects it. it also have a lifecycle.

    function is a simple procedure that have no restriction on lifecycle, ownership. by definition it’s only purpose is to transform an input to an output, or do side effects.
  • 0
    I use class ( in JS ) when importing fuctions and variables from a file seems too tedious. Example:

    // instead of this:

    import {function1, function2, function3} from 'file1'

    function1(blahblah, blahblah)

    function2(blahblah)

    // I like this:

    import {SomethingHelper} from 'file'

    SomethingHelper.doThisOrThat(blahblah)
  • 0
    @uyouthe

    FP is not good for real time application or game where the state change a lot. It is much better to update a single pixel rather than creating new state for single pixel changes.
  • 0
    @mr-user reading your explanation makes me sad that we didn't properly cover modifiers like protected in my CS course.
  • 1
    @mr-user please tell me you know that reconciliators and persistent data structures exist. Please tell me you know this.
  • 1
    @uyouthe I know persistent data structure exist. By asking that question , I know what you are getting at.

    By reconcilliators do you mean wrapping the impure operation into a monad which lazy load when the operation is called to "kind-of" make it pure.

    They may solve the performance problem but even persistent data structure cannot avoid from copying data in some case (Please correct me if I am wrong)

    There is no reason why we cannot mix OOP and FP in the same project. I always make my function pure so it can be swap out with the constant value and work without problem (What the term called again in FP? )
  • 0
    @mr-user you mentioned creating a whole new state to change just one pixel. I was taking it literally when I was a junior and I honestly created a whole new state. Needless to say, the performance was awful. I even ranted about it here. But later I discovered persistent data structures and how they work, and what even though the changed state appears as a whole new entity, the allocated memory is in fact the same and the only differences are the changed bits themselves.

    So either I misunderstood you or you trying to blame fp for a problem that literally doesn’t exist.
  • 1
    @uyouthe

    I think we have miscommunication here. I am not trying to blame FP for anything.I like FP more than OOP by the way.

    Please correct me if I am wrong but I am making an argument that for an application which do a lot of graphic processing it is better to do mutable change than the immutable one,right?.

    Personally I never encounter the performance problem with FP so maybe it a myth. My main argument is that we don't need to stick with "Our project will be OOP or our project will be in FP". We can use mix style in the project.
  • 0
    @uyouthe

    Do you have any advise to write Lens easier to solve writing a lot of code?

    For example

    Person

    {

    Address;

    }

    Address

    {

    Primary;

    Secondary;

    }

    Primary

    {

    Street,

    Township,

    Country,

    HouseNumber

    }

    Seconday

    {

    Street,

    Country

    }

    I mean if I want to change the country in Primary.

    Country Change --> New Primary --> New Address --> New Person

    The more layer the data structure I have the more difficult it is to write the code which change data in underlying layer.
  • 1
    @mr-user changing data in a well-implemented persistent data structure has no or almost no overhead over mutating the data directly. My friend implemented a 3D graphics engine with physics, all in F# and it’s running pretty smooth
  • 0
    @mr-user no I can’t, there’s no universal advice here. You can either implement some kind of tiny ORM with according methods for this or pick a language or library with more syntax sugar
  • 0
    @uyouthe persistent data structures are at least around O(log n) to mutable ones in most cases. And space complexity is a thing too. It's much easier to express some computations via mutation.

    Sure you can do most things via a persistent structure, but it might be much more natural to use a ye olde mutable. They also don't scale nearly as well and usually have garbage cache performance.

    It's possible to do optimizations where you can prove that older values aren't used so you discard them, but it's still not as easy as a ye olde mutable and doesn't always work.
  • 0
    @RememberMe what about persistent queue or Brodal-Okasaki heap? Both are O(1) in terms of inserting data.

    My point wasn’t that persistent ds are always better, it was that you can successfully use them and still have great performance
  • 0
    @uyouthe right, the log n overhead is in terms of implementing a mutability like pattern on top of a persistent data structure.

    Sure you can get fairly okayish performance out of a well implemented PDS, I've built at least one game in Haskell that was decently complex. But it stresses the GC and despite having good theoretical time bounds, it's nowhere near the best mutable implementation I could come up with. DS replacement optimizations and partial persistence help somewhat but eh. Also it's much easier to cache optimize the mutable version. I used Okasaki's Purely Functional Data Structures as a reference when doing so.

    I would still only use a PDS when data structure performance is not the bottleneck of the program (and performance is a requirement). As much as I like pure FP and the ease of reasoning that go along with it, computer hardware is fundamentally very very good at mutation so not taking advantage of that is kinda pointless. Expressing your logic in terms of persistent data structures is really nice for compilers though, I've seen work on automatically replacing them with mutable versions (still research) and the speedup is legit. (that's the compilers pipe dream right, express logic in a safe way and have the compiler lower it to computer hardware efficiently).

    But yeah, you can get decent performance out of them so I agree with you there.
  • 1
    @RememberMe yeah no shit just changing a dword by a pointer is faster, but do we need this at a cost of a project turning into a complete leaky spaghetti disaster as it grow? I think not. Anyway, nice discussion 👍
  • 1
    @uyouthe it's always shades of grey heh. Well managed, well abstracted mutability is nice enough to work with.

    Yeah, good talk.
  • 1
    @NoMad and don't forget the reusability myth
Add Comment