Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Why would I use a class over a module for stateless computation?
6 points by DATACOMMANDER on Feb 24, 2019 | hide | past | favorite | 3 comments
I’m a fledgling programmer, experienced enough to write code that works and solves real business problems but by no means a seasoned software engineer. I mainly code in Python, and as I gain experience I find myself reading code written by other programmers more and more frequently. I’m usually reading the code of mature, highly regarded tools (e.g., Requests, Ansible, some lesser-known but clearly high-quality tools), and I can’t help but notice that the people who write this code tend to take a much more object-oriented approach than I do. In particular, they use classes in situations where I would use modules, and objects in situations where I would use dicts or tuples (or named tuples, which I’m fond of). The style I’ve developed so far is to use a module when I’m trying to bundle related functions that don’t manage state, and to use classes when state-management is inherent to the problem and I want to shield clients from it (or “encapsulate” it).

On the one hand, I don’t want to blindly imitate programmers who are dealing with problems of a different type (or scale) than those I’m dealing with and end up making my own code unnecessarily complex. I sometimes have an imaginary conversation with a composite “seasoned Python programmer” in which I proudly show him code that I’ve written as a collection of classes, and he looks at me quizzically and says, “Why did you write all these classes to solve this problem? I would have just used modules.”

On the other hand, as I’ve matured as a programmer I’ve noticed that my code has started to look more like the code I read, not due to conscious imitation, but because I’ve improved and those improvements have naturally made my code look more like the code of more experienced programmers. If I’m inevitably going to rediscover the reason for using objects when state isn’t an issue, I might as well just be told what I’m missing and save myself some time (and spare my employer the inferior code that I’ll be writing in the interim).




You wouldn't, and good for you having recognized that. :) There are always exceptions to rules though. Perhaps your code is stateless consumer of an api, but you want to store your username and api key somewhere, so why not in a class? Perhaps you want to create a large number of namespaces and it is more convenient to use static stateless classes than create one new file for each namespace? Some programmers also shy away from module-level variables because to set them in the same module that they are defined requires using the global keyword.

Classes also has some extra trickery over modules which you can use and abuse. Such as __getattr__ and __getitem__.


Worst part of python seems to be that there are no truly global variables. So those seasoned pythoners make spaghetti code where the global data is inherited and modified most complex of ways.

Is this a matter of professional pride? I do not know. I just make a module for truly global variables: class G: a=1; b=2; which can be easily accessed everywhere G.a=G.b+4 .


Can you give an example of a truly global variable? I do try to avoid those. If we’re talking about global parameters, I usually put those in all-caps near the beginning of whatever module has to use them, and have them default to values that live in a top-level text file that the user can edit between invocations. But for global(ish) variables I do use classes, so other parts of the code can instantiate objects that are responsible for their values and call methods on those objects rather than mutate global state arbitrarily. I hope I’m not writing spaghetti code by doing this. The objects that manage these variables definitely never pass them to other objects (which in my mind would defeat the purpose). For example, if I need to use an external RESTful API, then things like token expiration are unavoidable state that must be dealt with, but I’ll write a paper-thin wrapper around a Requests session that shields consumers of the API from that sort of bookkeeping. If Python had private members I’d use them, but I at least use the “_” prefix to signal to clients that if they’re accessing the member directly they should stop and think about what they’re trying to accomplish.

It sounds like maybe you’re talking about what I’ve heard referred to as “cross-cutting concerns” that happen to be stateful. I haven’t developed anything large or complex enough to run into that, but I can imagine (in a fuzzy sort of way) code that contorts itself to avoid globals when a far simpler solution would be, “Use this small number of globals, but be careful.”

I could be way off here. I’m eager to hear your response.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: