8 ms·
A few years ago, I quit organizing my code in terms of classes altogether. Everything got so much simpler that for me that whole way of looking at programming i
by gruseom 15y ago
A few years ago, I quit organizing my code in terms of classes altogether. Everything got so much simpler that for me that whole way of looking at programming is now a gigantic mistake. It's true that you have to have a powerful enough language to get away with writing only functions, or at least one that doesn't impose classes on you, but that's true of lots of languages nowadays.
Freud said sometimes a cigar is only a cigar. I say sometimes a function is only a function.
Classes get in the way between the programmer and the problem. They force you to reify your thinking into "things" (classes) that demand names and citizenship rights, so to speak, in the system. These "things" don't really exist, but we act like they do, and so increasingly see the problem in terms of the classes we've defined. This is a distorting filter that we can ill afford when the problem is complex (if it's not complex, who cares - anything will work ok). The solution is not to define such pseudo-things in the first place, but rather to focus at all times on the problem at hand. Functions, for me, are the right level of abstraction to do this. They don't get in the way.
Once a bunch of classes have taken residence in your system and your brain, it's hard to remember that they aren't real, and thus the pain threshold is quite high before you realize that they're causing problems. At that point they're hard to change: you have to replace the old class hierarchy with a new class hierarchy. The difference between that and reworking a few functions is the difference between working in concrete and clay.
There's also the cognitive tax of having to think about what classes to create and what to name them. This too is overhead we can ill afford given our limited mental resources. If you've ever found yourself putting some code in a new class (perhaps because the old one got too big, or because you need to use it from two places) and gotten stopped in your tracks by the question, "What should I name it? What is this thing?" you are experiencing the overhead I'm talking about. It's the programming equivalent of Mr. Heavyfoot: http://www.youtube.com/watch?v=R9d2Y1We-d0 http://www.youtube.com/watch?v=R9d2Y1We-d0. There is no such thing; you're just working in a way that forces you to pretend that there is and fulfill a bunch of duties towards it.
These two issues together are a double-whammy: you pay up front for what you pay for later.
It is shocking to see how much simpler systems become when we stop doing the things that make them complicated.
- pnathan 15y agoI have a similar approach. I only use classes when I find myself passing around an object that is starting looking suspiciously class-like. While this adds a refactoring burden, it turns out most of the time, OO is a waste of time, and a few arguments is all you need. Some things are objects, in and of their nature. So it turns out that they transform into classes very nicely. But most of the time, you have data, and you have things that work on that data, and it really does you no good to nounize the world too far. You wind up going off into this ontological modelling foolishness, and as a rule of thumb, you wasted your time.
- gruseom 15y agoIn what language do you find it easiest to make classes only when you feel like it? most of the time, OO is a waste of time, and a few arguments is all you need That reminds me of another key point. I try not to let function signatures have more than a few arguments, and I try to keep those arguments primitive. (A good litmus test is how easy it is to call from the REPL.) When my code starts to break these guidelines, that's a sign of design weakness, and I do what it takes to break up the complexity. It still amazes me how far you can get in terms of simple, decoupled design just by doing this. The widespread OO practice of factoring some of those arguments into a new class, so that now you need pass only one thing (the new composite object) instead of several old ones, does nothing to solve the problem, but instead makes it worse: you've both added complexity and lost transparency. It's like a kid saying yes when mother asks "did you clean your room", having shoved all the mess under the bed.
- tptacek 15y agoI'm reminded of 100 horrible C APIs that take a "struct foo_opts" instead of just conceding that they need 7 or 8 silly arguments. Or of "sockaddr_in".
- barrkel 15y agoThe sockets API would be much more future proof if C better supported polymorphism. That's usually the reason for using structs instead of arguments; in Windows, most API structs start with the size of the struct, effectively indicating the version. Makes binary compatibility easier when you add arguments in version n+1. sockaddr_in is the way it is because of sockaddr, sockaddr_in6 etc. Judicious polymorphism could have led to fewer headaches converting IPv4 apps to IPv6.