Live data from Hacker News

The use of `class` for things that should be simple free functions

quuxplusone.github.io

341–350 of 406 posts

Re: The use of `class` for things that should be simple free functions

#341

Earlier quoted context omitted.

> Good modern practice (c.f. Rust, etc) is to ship LTO'ed mostly-static binaries. What Go and Rust do (by default) is only useful for internal software that you have full control of (both in source and in updates), but it is definitely not "good practice" for general software distribution. Going fully static (Go) or mostly static (Rust) means your users/clients cannot update dependencies easily. Users will suffer whe…

> Users will suffer when the vendor is not replying as quickly as they would hope for (which is not a pleasant experience at all, specially if you run server software) or when they simply discontinue the software (cf thousands of games). My experience as a Linux user is that I suffer even more from some minor update in /usr/lib/libwhatever.so suddenly breaking some feature in software that I use to do my job / have f…

Being self-contained does not imply statically linked, though.

The benefit of dynamically linking is that you (as a user) or upstream (most likely) can fix those issues you point out, including future ones.

Being self-contained simply means updates aren’t forced into it, which is a good thing and I agree with it.

I didn’t downvote you, by the way, since the point you make is valid.

Re: The use of `class` for things that should be simple free functions

#342
post #258

Earlier quoted context omitted.

Sure, you can build your own object and pass the 'this' pointer around manually. You could use C for everything, and tediously do everything again that objects do for free. But why? There's a lot of object-hating going around. Its silly. Use objects to encapsulate functionality, they are good at that and everybody understands what it means.

But you _are_ passing `this` around with OO code too. It just ends up being before the dot (or arrow), instead of being an argument. All you did is loose some flexibility. OO couples behavior with state. Sometimes that's exactly what you want (e.g. containers). And sometimes you just need data, functions and namespaces and all 3 are available in C++ outside classes.

Ok mostly true. It can also be part of a function pointer.

Re: The use of `class` for things that should be simple free functions

#343

I know that there's arguments for and against classes and functions. In recent years, I've come to love functions. But they are both tools that have cases of appropriateness. However, I think a lot of people are looking at classes the wrong way. In this thread, I'm hearing that classes should encapsulate functionality. While this is an aspect of classes, I don't think it's the main use case of a class. A class should…

The problem is many popular languages place a heavy emphasis on object oriented programming. Primarily functional or procedural programming, with the ability to fallback to OOP when necessary, seems to better align with the software design sensibilities you lay out here. You can of course write FP-like code in Java, or OOP-like code in Clojure (or Golang), but I find I get more done when working in ecosystems I swim…

That's totally fair. I'm not against OOP per se. OO and FP are both tools that, if they fit the task, should be used in a way that's not dogmatic. But obviously you wouldn't try to turn a flat-head screw with a Philips head screwdriver!

Re: The use of `class` for things that should be simple free functions

#344

Earlier quoted context omitted.

If you do use a class for this, of course you can provide a wrapper function that constructs the object, calls the "run" method on it, and returns the result. This can be in addition to the processing class, or it can be the entirety of the public API while the processing class is defined privately in an implementation file. I've done this before for Munkres, also called The Hungarian Algorithm, which assigns jobs to…

Isn’t this all just different approaches to currying? It’s often convenient to have some function that you can call without passing the same subset of parameters to each invocation. Whether to curry depends on how much repetition is involved and how “expensive” it is for the programmer to curry. In the case of “curry by creating a whole named class”, the expense is relatively large, while a functional currying approa…

I'm not that familiar with functional programming but I think the answer is no. In the situation I'm describing, most of the arguments to the private methods are completely different except for the implicit this/self argument that contains the progress of the algorithm. Currying is about turning a function of multiple arguments into a function of one argument which itself is a function (which in turn takes a function as an argument, and so on). I don't see the connection. Maybe you could clarify?

Re: The use of `class` for things that should be simple free functions

#345
post #220

Earlier quoted context omitted.

Classes usually have a more complex state than the state passed to utility functions, which is a reason I'd be incline to use e.g. a struct as a state vs a C++ class. Makes it harder to write bad code.

So, let's say what you actually mean here: overly complex state is a problem, regardless of the syntactic sugar around passing it. I've seen monstrous state variables passed around to "pure functions" at least as much as I've seen monstrous god objects; the problem is around complexity and data flow design and has very little to do with function vs object.

Yes that's my thinking. Everything can be done both ways, but in my experience structs have a better track record. Also different languages implement objects differently which adds mental overhead. Copying structs or marking them read-only is also usually easier vs an object which manipulates its own state.

Re: The use of `class` for things that should be simple free functions

#346
post #179

Earlier quoted context omitted.

I think that depends on what we understand by 'state'. Do we count immutable data? Consider faking a 'bind' with something like: var quadrupler = new ConstantMultiplier(4); var output = quadrupler.applyTo(42); The 'quadrupler' instance is stateless in that it's immutable, but it presumably has a (constant) member to store the value 4.

After ES6, I jumped at the opportunity to write classes in javascript, but lately I've realised I barely write classes anymore, but I write a lot of functions that return functions. And this example is perfect for that. For example, I recently wrote this: const labelizeElement = ((element) => element.type.replace(/\s+/g, '')); const labelizeRelation = ((relation) => relation.type.toUpperCase().replace(/\s+/g, '_'));…

Personally I'd avoid currying and go with a function with three params, like:

    const labelizeElement = ...
    const labelizeRelation = ...
    
    const groupByLabels = (labelizer, set, element) => ....
    
    const groupByElement = (set, element) => groupByLabels(labelizeElement, set, element);
    const groupByRelation = (set, element) => groupByLabels(labelizeRelation, set, element);
This makes it slightly simpler to create a binding function around groupByLabels which fixes, say, the middle argument. I also think that avoiding the chained use of the => operator makes the code more readable to the average JavaScript dev.

C++ has (strange looking) support for the bind pattern in its standard-library now [0], and Python3 has functools.partial but it only supports left-to-right binding [1] (not that there's any particular reason to avoid lambdas).

[0] https://en.cppreference.com/w/cpp/utility/functional/bind

[1] https://docs.python.org/3/library/functools.html

Re: The use of `class` for things that should be simple free functions

#347

Earlier quoted context omitted.

Let's use C and C++ as an example. What does the code look like? myobj.cool_func(1,2,3); // C++ cool_func(myobj, 1, 2, 3); // C Is this better? If you use a vanilla C++ style class then the class definition is in the header. All changes to the class require a recompilation and break the ABI of the class. This means you basically cannot release patch versions of your library because consumers cannot link against it if…

> If you use a vanilla C++ style class then the class definition is in the header. All changes to the class require a recompilation and break the ABI of the class. definitely not all, only things that change the layout. adding a non-virtual method does not break ABI at all for instance. > Contrast with C where you would forward declare a struct in the header and pass that around while the definition is hidden in a .c…

> adding a non-virtual method does not break ABI at all for instance.

Ctors/dtors can break ABI as well: https://gcc.godbolt.org/z/XAx00v

Re: The use of `class` for things that should be simple free functions

#348

This antipattern is taken to the extreme with the `DOMParser` [1] class in the Browser. The constructor takes no arguments and it has a single instance method that takes produces a result without mutating any internal state. What's worse, the method returns a newly created object of another class, which in my head is an indication that maybe, just MAYBE it should have been a constructor of said other class instead. […

As it says in the HTML Standard[0]: >The design of `DOMParser`, as a class that needs to be constructed and then have its `parseFromString()` method called, is an unfortunate historical artifact. If we were designing this functionality today it would be a standalone function. [0]: https://html.spec.whatwg.org/multipage/dynamic-markup-insert...

> The design of `DOMParser` ... is an unfortunate historical artifact

My prediction is that in 20-30 years the same will be said about today's mainstream OOP.

Re: The use of `class` for things that should be simple free functions

#349

Author makes some valid points, but jumps to conclusions too quickly. Most importantly, code in examples that actually solves problem is omitted (`[...recursive solution omitted...]`) - and that code can be potentially very long. If you have very long function, you should break it into smaller functions. But, those functions need to operate on shared state. In some languages (Python) you can have nested functions tha…

What's wrong with having the functions stateless and just passing the state in as a parameter? OOP does exactly this behind the scenes.

> foo.do(bla)

is syntactic sugar for

> do(foo, bla)

Re: The use of `class` for things that should be simple free functions

#350
post #258

Earlier quoted context omitted.

Sure, you can build your own object and pass the 'this' pointer around manually. You could use C for everything, and tediously do everything again that objects do for free. But why? There's a lot of object-hating going around. Its silly. Use objects to encapsulate functionality, they are good at that and everybody understands what it means.

But you _are_ passing `this` around with OO code too. It just ends up being before the dot (or arrow), instead of being an argument. All you did is loose some flexibility. OO couples behavior with state. Sometimes that's exactly what you want (e.g. containers). And sometimes you just need data, functions and namespaces and all 3 are available in C++ outside classes.

But I don't want that flexibility!

If my state has some invariant, I want to be sure that I can trust it. I don't want to worry that someone will mess with it, breaking the invariant, or accidentally pass in stale state.

If that's all handled automagically by the object, it's out of sight, out of mind. Add in a get_state() and set_state() method if you need it as an escape hatch or for testing.

Post reply on HN