HACKER Q&A
📣 parpfish

Is "Stop Writing Classes” still good advice in modern Python?


I've just saw Jack Diederich's "Stop Writing Classes" talk (2012) for the first time (https://www.youtube.com/watch?v=o9pEzgHorH0). This talk has shown up on HN a few times, but only elicited a big conversation in one thread back in 2012 (https://news.ycombinator.com/item?id=3717715).

One of the main takes is "Don't write classes that could just be a function" (stated in the video as "If a class has two methods and one of them is __init__, it doesn't need to be a class"). But given the addition of dataclasses and typing to python in the last 10 years, is this still good advice for code style?

For a more specific example, I'd prefer to defining a "useless" class for the purpose of typing like this:

  @dataclass
  class FooFuncParams:
      bar: str
      baz: int
      ...

  def foofunc(params: FooFuncParams):
      ...

Rather than having to use overly-permissive typing like this:

  def foofunc(params: Dict[str, Any]):
      ...


  👤 zach_garwood Accepted Answer ✓
I think maybe you're overextrapolating here. Classes are meant to hold state. If you have a bunch of related state, wrapping it up in a class has been a common use of classes even before `dataclass` existed.

What the talk is discussing is the creation of classes for wrapping related _functionality_, sans state. The class isn't really necessary at that point, so you should just create a module with functions instead of a class.

Even if you do need your related functionality to reference some common state, you still might not need a class, because modules themselves are objects and can hold state.

The point of the talk is not to dissuade you from _ever_ using classes, it's to make you think more judiciouly about adding new classes you probably don't need. Python isn't Java, and you dont need everything to be a class.


👤 PaulHoule
There has been a lot of commentary along the lines that "OO sucks" since OO became mainstream in the early 1990s and there will be for a long time.

I think your example of a dataclass replacing a dict is just fine.

I'd grant though that the single-method class is a special case, even in Java it is tempting to use a Function as opposed to define a specific class or interface for a particular use. Such a "class" can even be defined as a lambda message in Java and capture state from the environment as opposed to writing a class with fields spelled out.

I've found, however, that the "functional class" often adds more methods and attributes over time. In the case of Python, however, you can write something like

def fn(): ...

fn.someAttribute = ...

so you can occasionally tack some extra functionality (say metadata) onto a function that way.


👤 hitpointdrew
I have never seen that talk, I might check it out later though.

>If a class has two methods and one of them is __init__ it doesn't need to be a class.

That seems like dumb advice to me. I don't use classes often in Python, but when I do it is typically because I have a more complex data set to work with and I don't really need database. Usually this is a class that ONLY has an __init__ function in it. Having data set that is a dictionary with nested dictionaries, with nested arrays ,etc. gets ugly and often you end up with a mess of loops trying to parse the data. I find classes super helpful here and would just instance a bunch of class objects with attributes I need, then put all those objects in a list. You can then iterate over a nice, simple, clean, list of you objects and access any attribute you wish. Without having to do nested loops trying to dig down the the value you want.


👤 meltyness
Another meaningful consideration is whether or not you intend for the project to remain python for it's full lifecycle.

If you're looking forward to porting to a more performant language, dict has parity with struct, and vtable dereferencing and polymorphism has performance penalties in say, C++. rust and golang don't really have a robust object implementation so flatter structuring is preferred.