
Stop writing classes... - andybak
http://pyvideo.org/video/880/stop-writing-classes
======
scott_s
I almost never write classes in Python. That may be a result of the fact that
I never use Python for anything other than system automation and data post
processing; I don't use Python to build complicated systems. What I have made
use of are named tuples:

    
    
      3DPoint = collections.namedtuple('3DPoint', ['x', 'y', 'z'])
      p1 = 3DPoint(3, 2, 4)
      p2 = 3DPoint(10, 1, 10)
    
      dist = math.sqrt((p2.x - p1.x)**2 + 
                       (p2.y - p1.y)**2 + 
                       (p2.z - p1.z)**2)
    

I don't mean to say that classes aren't useful in Python, just that I've
gotten a lot done in the language just depending on hashes, lists, tuples,
named tuples, functions, comprehensions and generators. I've never felt the
need to define a a class - the closest I came, I realized I wanted a named
tuple. It certainly would make sense in the above example to define "dist" as
a member function of a 3DPoint class, but it's just not how I write code in
Python.

Contrast this with C++, where I define classes all the time. I think the
reason for this discrepancy is that if you want to do anything interesting in
C++, you almost have to define a struct or a class; that's where most of the
abstractions happen. In fact, if I want functional style code in C++, I have
to define my functions as classes. I think that Python's native tuple types,
first-class functions and comprehensions make the difference.

~~~
gruseom
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>. 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.

~~~
haberman
I couldn't disagree more.

Classes are nothing but:

    
    
      1. a group of data attributes, and
      2. a defined set of operations that can happen on instances
         of those data attributes.
    

If you are opposed to classes, which of these characteristics are you opposed
to? Since I think it would be pretty much impossible to be a programmer and be
opposed to structs or tuples, it must be the latter that you don't like:
giving structs an associated set of methods that operate on them.

But having a set of methods that define the state transitions that are
possible on an object is incredibly useful, for so many reasons. It helps
organize your code. It provides nicer, more intuitive syntax. But most
importantly, it reduces program complexity by narrowing down the set of code
that can directly modify the attributes of an object.

Without this encapsulation, any piece of code anywhere in the program could be
modifying data attributes in any way, and it is extremely difficult to reason
about the state transitions that any particular struct could be taking.

There is no rule that says classes have to be in any kind of hierarchy at all,
and in fact "prefer composition over inheritance" has been common wisdom for
years now.

I recently rewrote a very useful but hard to follow JavaScript library in a
more object-oriented style. The old code has a bunch of maps everywhere that
can be read or written by any part of the code, and it's very difficult to
follow. In a more object-oriented style the structure of the code is far more
obvious, and the state transitions that each object can take are far more
clear.

~~~
telemachos
To follow up on gruseom's comment that YMMV, I would point you to Joe
Armstrong's (Erlang creator) "Why OO Sucks"[1]. The title isn't great, and you
may hate the content, but the interesting thing (to me) is that he makes a lot
of the same basic points as you and then he draws all the opposite
conclusions.

Maybe a reasonable conclusion is that there is no silver bullet for managing
complexity and making things easier to reason about.

[1]: <http://www.sics.se/~joe/bluetail/vol1/v1_oo.html>

~~~
loup-vaillant
No silver bullet? Check this out: <http://vpri.org/html/work/ifnct.htm>

They already have some results:
<http://www.vpri.org/pdf/tr2011004_steps11.pdf>

To sum it up, they do "personal computing" in about 4 orders of magnitude less
code than current mainstream systems (from more than 200 millions lines to
about 20,000). That includes the self-implementing compilers. The only thing
they left out was the device drivers (which by the way takes less than 0.5%
the size of current systems).

Now the Complexity Werewolf just went from "Unspeakably Awful Indescribable
Horror" to "Cute puppy".

------
lrobb
Are java programmers the most egregious abusers of the Gang of Four?

Twice now, I've been faced with a metric crap-ton of Java source files for
reading / writing to a device.

Anything you could possibly imagine, gets defined as a class. There's dozens
of classes, and more SLOC than I can count.. Meanwhile, an equivalent C
program comes in at 2k SLOC, and 4 files.

You().Can('not').Do(any(thing)).Concise().In(java())!

When I was primarily doing C++, I gradually switched to generic programming
once visual studio supported STL... And then when I started using Perl I found
I didn't need to write classes at all.

Reminds me of this Paul Graham quote: "This practice is not only common, but
institutionalized. For example, in the OO world you hear a good deal about
"patterns". I wonder if these patterns are not sometimes evidence of case (c),
the human compiler, at work. When I see patterns in my programs, I consider it
a sign of trouble. The shape of a program should reflect only the problem it
needs to solve. Any other regularity in the code is a sign, to me at least,
that I'm using abstractions that aren't powerful enough-- often that I'm
generating by hand the expansions of some macro that I need to write."

<http://www.paulgraham.com/icad.html>

~~~
omaranto
You might enjoy Steve Yegge making fun of this aspect of Java culture, if you
haven't this particular post before: [http://steve-
yegge.blogspot.com/2006/03/execution-in-kingdom...](http://steve-
yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html)

~~~
lrobb
I had not seen that! Explains so much...

 _In the neighboring programming-language kingdoms, taking out the trash is a
straightforward affair, very similar to the way we described it in English up
above. As is the case in Java, data objects are nouns, and functions are
verbs. But unlike in Javaland, citizens of other kingdoms may mix and match
nouns and verbs however they please, in whatever way makes sense for
conducting their business.

For instance, in the neighboring realms of C-land, JavaScript-land, Perl-land
and Ruby-land, someone might model taking out the garbage as a series of
actions — that is to say, verbs, or functions. Then if they apply the actions
to the appropriate objects, in the appropriate order (get the trash, carry it
outside, dump it in the can, etc.), the garbage-disposal task will complete
successfully, with no superfluous escorts or chaperones required for any of
the steps.

There's rarely any need in these kingdoms to create wrapper nouns to swaddle
the verbs. They don't have GarbageDisposalStrategy nouns, nor
GarbageDisposalDestinationLocator nouns for finding your way to the garage,
nor PostGarbageActionCallback nouns for putting you back on your couch. They
just write the verbs to operate on the nouns lying around, and then have a
master verb, take_out_garbage(), that springs the subtasks to action in just
the right order._

------
lrobb
"I find OOP technically unsound. It attempts to decompose the world in terms
of interfaces that vary on a single type. To deal with the real problems you
need multisorted algebras - families of interfaces that span multiple types. I
find OOP philosophically unsound. It claims that everything is an object. Even
if it is true it is not very interesting - saying that everything is an object
is saying nothing at all. I find OOP methodologically wrong. It starts with
classes. It is as if mathematicians would start with axioms. You do not start
with axioms - you start with proofs. Only when you have found a bunch of
related proofs, can you come up with axioms. You end with axioms. The same
thing is true in programming: you have to start with interesting algorithms.
Only when you understand them well, can you come up with an interface that
will let them work." - Alexander Stepanov.

~~~
Drbble
The part about proofs and axioms is completely non-logical. for the past
several centuries, proofs have relied on axioms. Euclid introduced axioms
(postulates) in order to provide proofs (and precise formulations) for
informal statements. So the math part is really more an argument in favor of
classes as a sort of axiomitization of computing.

~~~
pavpanchekha
The majority of the proofs Euclid produced existed, both as theorem and proof,
before his time. Similarly, few recent mathematical advances have started with
formalizations and axioms. Calculus wasn't put on a rigorous basis until
Lebesgue's time, hundreds of years after Newton and Leibniz. Category theory
needed quite some work before it was formalizable. Differential geometry
wasn't that rigorous until the twenties or so. Complex analysis was developed
using many, many unnecessary assumptions because the formalities weren't
there. I'm not picking-and-choosing math fields here; these are just the ones
I'm familiar ones. It turns out, axiomatization and theory-building are two
separate jobs rarely performed by the same mathematician. Usually, the theory-
building makes the mathematician famous, and the axiomatization does not, but
this is in many ways a tragedy. In any case, to the outsider of mathematics,
it seems that axioms come first. This is false -- axioms come much later,
because the work of axiomatizing isn't worth it before the theory proves
itself useful. Axioms come first in a formal way, in the same way classes come
first in a formal way. But the interesting thing isn't the class -- it's the
instance. And in the same way, the axioms aren't interesting -- it's the
resulting theories. I found the analogy very insightful.

------
petercooper
I notice no mentions of Ruby yet, and I wonder if this discussion is pretty
much impossible to have in the Ruby world, given Ruby is _solely_ an object
oriented language, even if you try to use it procedurally. Not writing classes
would be against so many Ruby conventions and accepted style that it's a non-
topic?

Or is it that classes in Python _specifically_ aren't that much of a win over
the language's implementation of other paradigms? I sure haven't hit into any
problems using classes or objects in Ruby, even when sometimes the use feels a
little contrived to begin with, but.. I also have no choice :-) (maybe
Rubyists have a Stockholm Syndrome with OO ;-))

~~~
ryanf
I think part of the reason this doesn't come up in Ruby is that Ruby doesn't
have Python's powerful namespacing system.

In Python, it's reasonable to have a package with just functions in it,
whereas in Ruby, writing a top-level method means polluting every object in
the system. You can write modules that have singleton methods on them, but you
still don't have anything as flexible as Python's "from pkg import foo,
bar"—the caller needs to either write "ModuleName.my_function" at every call
site, or use "include" and end up with the module's methods as part of the
consuming class's interface.

~~~
judofyr
Implicit self and late binding in Ruby makes it hard to implement a proper
namespacing system without breaking other semantics :(

After working with Perl (which has a similar namespacing), I must it's
something I really miss when I come back to Ruby.

------
johnkchow
One concern I have with Jack Diederich's video is that he never addressed one
benefit of classes: better testability. In his Muffin example, he took out the
instance variable that stored the API URL and created a constant out of it. If
I had an URL for my staging environment, and another for my production
environment, I'd like to programatically set that instead of going back into
the code, modifying the constant value, run the test, and then change the
value back to the original. That's just a bug waiting to happen.

This isn't to say his underlying message is wrong (I 100% agree with Jack's
message, too much classes create unnecessary complexity in your library/app),
but I don't want people destroying their classes without fully understanding
the consequences.

~~~
quotemstr
You can create a variable, set that, and pass that variable as the first
parameter to greeting. I don't see why having a class makes testing any
easier.

~~~
radicalbyte
Decoupling. For example if your code requires access to an outside resource
(database, message queue, email service) you can mock said resource in order
to test the code in isolation.

~~~
quotemstr
Down that road lies the hell of dependency injection frameworks. A simpler
approach is to use something like detours[1] to mock bare functions directly.

[1] <https://research.microsoft.com/en-us/projects/detours/>

~~~
Drbble
Google Guice is not hell.

------
fuzzythinker
Disagree with "Decoupling" never used or "if used, they are pulling a fast one
on you". It not only will help make his point of decreasing line-count, but
more importantly, it is one of the main principles in achieving DRY-ness (both
code-level and more importantly, architectural level DRY-ness). I'll even go
further and say that if you're not thinking about it all the time, you're most
likely doing it wrong.

~~~
Maro
I think he didn't mean that it's never used, just that it's never actually
said in the real world.

My experience confirms this.

~~~
fuzzythinker
Yup, my bad, he actually said "people never say". But the way he presented it,
seemed like he's opposed of it. But I still think it should be mentioned more
in the industry so more developers are aware of it and think about it more
often than not.

EDIT: Can't reply to Tommabeeng's comment (probably too deep). Yup, and I
agree with the presenter's main point - that classes are not necessary in many
situations, even for decoupling.

~~~
Tommabeeng
He does say about coupling & cohesion that "if used, they are pulling a fast
one on you".

That's wrong. I like the key to his talk but the plague of large complicated
systems is exactly coupling and incoherence. Classes are NOT necessarily the
way to achieve these.

~~~
drucken
As others have implied already, he could just as easily have been referring to
the words.

I think his intention was to explain that these are the same words (mostly
from academia and taken up with reckless abandon via language architectures
like Java) that may be thrown around by some to create the code mess (anti-
pythonic) in the first place.

------
jakejake
Over-engineered code is frustrating to read and work with. If your project
doesn't require classes then it's fine to not create a bunch of complexity
with OO style and design patterns. But if you just dismiss the techniques
because they're difficult or you don't want to spend time learning, then
you're likely to re-invent the wheel over and over.

~~~
aroberge
That's not what the video was about at all. The speaker never implied to use
an approach that would lead to reinvent the wheel over and over ... quite the
contrary in fact.

~~~
jakejake
Well, his message I think is easily translated into "classes suck - never use
them" by those who may choose read into it that way. He also dismisses a few
rather basic design patters as basically jokes (literally with laughs from the
audience as if these ideas are idiotic rather than foundations of software
design) without making the distinction that these concepts are actually really
important.

It's easy for people who are very smart and experienced to dismiss the rules -
that applies for all things, not just programming. But if you never learn the
basics then you'll stumble over silly things that have be solved by much
smarter people.

~~~
aroberge
Standard design patterns are important ... if you program in Java and similar
languages. But many of these are completely unnecessary when using a dynamic
language like Python - and many others.

~~~
jakejake
To me it's just simply a way to organize code, there's nothing inherently good
or bad about classes. You can use or abuse them like anything else. It never
hurts to know the basic GoF patterns and when to use them to simplify your
code or solve a common problem. You can use them with or without classes. Most
Javascript libraries that I look at today use closures, prototypes and
anonymous objects that might as well be classes. Patterns seem to be making a
huge appearance in client-side code in the last year. I'll admit that I don't
know anything about Python, though.

------
daviddaviddavid
I dislike classes but I like bundling data along with methods which operate on
that data. I often find that JavaScript's classless objects are a great
solution. It's just so natural to be able to create an object with object
literal syntax without first creating an ad hoc class and then instantiating
it:

    
    
      var o = {
          name: 'David',
          greet: function () {
              console.log('Hi, I am ' + this.name);
          }
      };

~~~
njharman
> bundling data along with methods which operate on that data

What can you possibly believe a class is other than exactly that?

~~~
daviddaviddavid
I realize that is one thing that classes offer. My point is that you can
achieve exactly the same thing with objects rather than classes.

Very often when writing Python (or whatever) you'll create a class which is
only ever instantiated once and the instantiation is done simply for the
benefit of calling one method.

In such cases I find classes to be overkill. What I really want is the object.
I don't need to factor the object's behavior out into a class.

Many of my sympathies are expressed much more thoroughly and eloquently in the
many papers you can find online by Walter Smith outlining the motivations
behind NewtonScript.

------
gruseom
It may interest people to know that Alan Kay has said that they got
granularity wrong with classes. Functions are a good granularity, and so are
systems, but classes don't work. To get true encapsulation as he originally
envisioned it, you need to think in terms of interoperating systems. The
example he gave of getting it right is the internet (but not the web). This
was all from Kay's talk last year in Germany.

~~~
Alexandervn
Do you have a source (video, transcript) to that talk of Alan Kay in Germany?

~~~
gg_
I believe he is referring to this talk: <http://tele-
task.de/archive/video/flash/14029/>

~~~
gruseom
Yes thanks - and if anyone watches it, be sure also to check out the stuff on
Bob Barton. I learned about a magnificent part of computing history thanks to
that talk.

Edit: here you go:

<http://news.ycombinator.com/item?id=2855500>

<http://news.ycombinator.com/item?id=2928672>

<http://news.ycombinator.com/item?id=2856567>

<http://news.ycombinator.com/item?id=2855508>

The first two are teaser comments. The second two are the important pieces.
Also the paper Kay praises at the start of the talk is short and very worth
reading.

------
sukuriant
I think he missed one of my favorite uses of classes: a collection of
implementations of defined methods, especially if you can't pass around
function pointers. For example, you're working with a Reader and the Reader is
something that needs to be able to read( _) and flush(_ ) and open( _) and
close(_ ). You use that Reader everywhere with those abilities. You don't care
how they work, you just need for it to be able to do those four things. If
you're expecting different Readers, it's useful to have a Reader interface and
then classes that implement it.

Unfortunately, this is the only way to perform this activity in Java. Also, I
adore Go's style of pseudo-OO programming.

.. or, from reading the HN threads, is that decoupling?

If so, I'm using decoupling right now!

~~~
ibejoeb
I think he addressed that (or a very similar circumstance) while talking about
the stdlib heap, and again in response to the question on "bag of related
functions." I don't think he'd take issue with your position.

Alternatively, if you are working with things that you expect to follow a
certain interface, Python does not really require a formal definition. Duck
typing should suffice.

------
kjlef
I'm not much of a python programmer, but in Java I use classes all the time.
The main reason is that small classes make writing unit tests easy. I can use
a mocking library like <http://www.easymock.org/> to mock out whatever
dependencies the code I'm trying to test depends on.

I agree on some of the presenters philosophical ideas, mainly that adding
complexities into the codebase before they're needed is almost always a
terrible idea, but saying that classes lead to complex code is simply not
true, at least in my experience.

~~~
aroberge
Of course you use classes all the time in Java: it forces you to do so by
design. I have significantly more experience with Python than with Java and I
find that writing unit tests on functions is as easy if not easier than
writing tests for (small) classes. And Diederich's point about small classes
being a code smell (my words - not his) is hard to refute.

------
martininmelb
As an 'end-user' of Python, I rarely find myself writing my own classes, but I
am really pleased that the authors of many of the libraries that I use decided
to write classes.

I think the distinction between 'end-users' and people who make libraries is
an important one and one that Jack seemed to overlook.

------
lbolla
What surprises me is that no-one mentioned inheritance when speaking about
classes. I am not a fan of classes and I prefer the functional approach,
whenever possible. In my experience, I found that classes make sense as part
of a hierarchy, that is, when subclassed to override/specialize methods or to
describe interfaces, like type-classes in Haskell.

------
phzbOx
Look, there is nothing _wrong_ with classes and OO in general. What is _wrong_
is using OO when it is unnecessary and only adds layers of complexity.

~~~
gruseom
_What is wrong is using OO when it is unnecessary_

That's a platitude which everybody can and does say about everything.

But I think one can make a case that there _is_ something wrong with OO in
general. The original arguments for OO were: it's better for managing
complexity, and it creates programs that are easier to change. Both of these
turned out not to be true in general. So we need to ask, when _is_ OO a win?
But for simpler problems it doesn't matter, because anything would work. So we
need to ask: what are the hard problems that OO makes significantly easier? I
don't think anyone has answered that.

I suspect it's that OO is good when the problem involves some well-defined
system that exists objectively outside the program - for example, a physical
system. One can look at that outside thing and ask, "what are its components?"
and represent each with a class. The objective reality takes care of the
hardest part of OO, which is knowing what the classes should be. (Whereas most
of the time that just takes our first hard problem - what should the system
do? - and makes it even harder.) As you make mistakes and have to change your
classes, you can interrogate the outside system to find out what the mistakes
are, and the new classes are likely to be refinements of the old ones rather
than wholly incompatible.

This answer boils down to saying that OO's sweet spot is right where it
originated: simulation. But that's something of a niche, not the general-
purpose complexity-tackling paradigm it was sold as. (There's an interview on
Youtube of Steve Jobs in 1995 or so saying that OO means programmers can build
software out of pre-existing components and that this makes for _at least one_
order of magnitude more productivity - that "at least" being a marvelous
Jobsian touch.)

The reason OO endures as a general-purpose paradigm is inertia. Several
generations of programmers have been taught it as _the_ way to program --
which it is not, except that thinking makes it so. How did it get to become so
standard? Story of the software industry to date: software is hard, so we come
up with a theory of how we would like it to work, do that, and filter out the
conflicting evidence.

~~~
Jare
> The original arguments for OO were: it's better for managing complexity, and
> it creates programs that are easier to change. Both of these turned out not
> to be true in general.

Wrong. Even the worst Enterprisey mess of Java classes and interfaces that you
can find today, is probably better than most of the spaghetti, global state
ridden, wild west that existed in the golden days of "procedural" programming.

If you consider that software is composed of Code and Data, then OOP was the
first programming model that offered a solid, practical and efficient approach
to the organization of data, code and the relationship between the two. That
resulted in programs that, given their size and amount of features, were
generally easier to understand and change.

That doesn't mean OOP was perfect, or that it couldn't be misused; it was
never a silver bullet. With the last generation of software developers trained
from the ground up with at least some idea that code and data and need to be
organized and structured properly, it's time to leave many of the practices
and patterns of "pure" OOP and evolve into something better. In particular,
Functional has finally become practical in the mainstream, with most languages
offering efficient methods for developing with functional patterns.

~~~
gruseom
You believe this, but you've given no reason to believe it other than the
dogma you favor. The old-fashioned procedural systems I've seen with global
state and the like were actually easier to understand than the convoluted
object systems with which they were often replaced. Your comment is exactly
the kind of thing that people who are enthralled with a paradigm say. But the
"worst Enterprisey mess of Java" that you blithely invoke is... really bad,
actually, as bad as anything out there. You're assuming that paradigm shifts
constitute progress. I offer an alternate explanation for why paradigms may
shift: because the new generation wants to feel smarter than the old one.

~~~
hackinthebochs
OO enterprisey mess is strictly better than global state ridden spaghetti
code. The hard part with enterprisey code is that the code performing the
action is hidden under layers of abstraction. The bootstrapping cost is much
higher here because you have to put more abstractions in your head before you
can understand a particular bit of functionality. This is a different sort of
complexity than the global state spaghetti.

With the global state code you have to understand the entire codebase to be
sure who exactly is modifying a particular bit of state. This is far more
fragile because the "interaction space" of a bit of code is much greater. The
dangerous part is that while you must understand the whole codebase, the code
itself doesn't enforce this. You're free to cowboy-edit a particular function
and feel smug that this was much easier than the enterprisey code. But you
can't be sure you didn't introduce a subtle bug in doing so.

The enterprisey code is better because it forces you to understand exactly
what you need to before you can modify the program. Plus the layered
abstractions provide strong type safety to help against introducing bugs.
Enterprisey code has its flaws, but I think its a flaw of organization of the
code rather than the abstractions themselves. It should be clear how to get to
the code that is actually performing the action. The language itself or the
IDE should provide a mechanism for this. Barring that you need strong
conventions in your project to make implementations clear from the naming
scheme.

~~~
gruseom
This sounds like ideology to me. You can _never_ be sure you didn't introduce
a subtle bug, you can never _force_ someone to understand what they need to,
and interactions between objects can be _just_ as hard to understand as any
other interactions.

I agree that a project needs strong conventions, consistently practiced. See
Eric Evans on ubiquitous language for the logical extension of that thinking.
But this is as true of OO as anywhere else.

~~~
hackinthebochs
First off, apologies for seemingly badgering you in various threads in this
post. I don't usually look at usernames when replying so it was completely by
accident.

>interactions between objects can be just as hard to understand as any other
interactions.

While this is true, there are strictly fewer possible interactions compared to
the same functionality written only using primitives. To put it simply, one
must understand all code that has a bit of data in its scope to fully
understand how that bit of data changes. The smaller the scopes your program
operates in, the smaller the "interaction space", and the easier it is to
reason about. Class hierarchies do add complexity, but its usually well
contained. It adds to the startup cost of comprehending a codebase which is
why people tend to hate it.

~~~
gruseom
That's hilarious. Well, you're welcome to "badger" (i.e., discuss) anytime.
It's I who should apologize for producing every other damn comment in this
thread.

In my experience, classes don't give the kind of scope protection you're
talking about. They pretend to, but then you end up having to understand them
anyway. True scope protection exists as (1) local variables inside functions,
and (2) API calls between truly independent systems. (If the systems aren't
truly independent, but just pretending to be, then you need to understand them
anyway.)

~~~
hackinthebochs
You're right that the scope protection I'm talking about isn't as clear cut
when it comes to classes. Design by contract is an attempt to address this.
Client code can _only_ refer to another object through a well-defined
interface. Thus your limited scope is enforced by the type system itself.
Furthermore, much of this discussion is about _perception_ of complexity
rather than actual complexity.

In python you can access any classes internals if you're persistent enough.
However, the difficulty in doing so and the convention that says that's bad
practice gives the perception of a separation, thus one does not need to be
concerned about its implementation. It lowers the cognitive burden in using a
piece of functionality.

Haven't you noticed this yourself? A simpler interface is much easier to use
than a more complicated one. If you're familiar with python, perhaps you've
used the library called requests, its a pythonic API for http reqeusts.
Compare this to the core library API using urllib2. The mental load to perform
the same action is about an order of magnitude smaller with requests than
urllib2, and its because there are far more moving parts with the latter.

My contention is that if bits of data and code are exposed to you, it is
essentially a part of the API, even if you never actually use it. You still
must comprehend it on some level to ensure you're using data it can access
correctly, aka interaction space (I feel like I'm selling a book here).

------
cageface
Defining abstract datatypes and legal operations on those datatypes is useful
whether you do it with objects or Haskell type classes or C++ generics. It's
easy to go overboard with objects but explicit interface definitions are a lot
easier to reason about then big grab bags of functions.

------
malkia
Wish someone asked his opinion on "singletons". I've been fan of them in the
past, and now I totally despise them... But then it came to me, that I don't
despise the semantics of he singleton - I just write that as a bunch of
functions, rather than class with methods that is "singleton-ized".

There were also some revelations - like printer().getSingleton() (or instead
of printer, put keyboard, mouse, memory, etc.) - at some point some of these
"singletons" might be become "multi-tons" - for example
gamepad().getSingleton() already is a trouble...

~~~
Ingaz
The best "singleton" for me is python module. Import is the constructor of
singleton. Python itself controls single initialization of object.

------
TeeWEE
Some arguments from this guy are:

1) Do not use a class if it doesnt have state

Agreed

2) Keep it simple and do not think about the future, fix it later if needed

He probably never wrote API code in libraries needed for other people. Once
you choose something you are bound to it. In this case classes and interfaces
are very helpfull. For example the API class example in the beginning (no
state) is a good example. In the future the api might be extended with more
functionality. The last thing you want is have 3rd parties rewrite their code
cause you changed the API. So a class is good to provide a Facade (yes Facade
Pattern).

3) package names are not for taxonomy but for preventing nameclashes

True. However in Java the editor is so powerfull that you never ever have to
lookup package names. This goes automatically (IDE parses the code on the
fly). Java package names also use URI patterns like:
com.google.android.hardware.vibrator. Which can only be used by somebody who
has the google.com domain name. This prevents name clashes ALL the time. In
python you sometimes have to rename a whole project. And the taxonomy gives
you an indication what the code actually does.

4) Dont overuse exceptions and keep shorts names.

Agreed. However i am not sure what the best granularity is. In a public
Library API, i would be very carefull about this.

Otherwise I agree with him.

------
swah
This discussion would be much more constructive if we have an actual problem
to code a solution for... then we could see the merits of each approach...

------
njharman
Stop writing class __hierarchies __.

Classes are fine. Over-engineering classes, like over-engineering anything is
bad, m'kay?

------
darylteo
For awhile I did not really know how to take this whole thing. Upon
reflecting, I realise I probably do lean away from Classes in general... it
was strange to come upon that realisation, as I come from a strong Java/OOP
background.

The benefits of Classes are still related to data abstraction. But it is
pointless if you are still accessing the data directly anyway (getters and
setters be damned). So, I would only legitimately prescribe a class only when
you are building a data structure.

Nowadays, my classes are either \- composition of primitive data (as I don't
have tuples(python)/structs or dynamic objects (javascript)) \- or function
groups (like a business logic layer of some sort, which could have just as
easily have been just bags of functions in modules).

I'm going to be teaching my students Classes in a couple of weeks... food for
thought before then.

------
dragonbonheur
I don't understand. I started to program computers when I was 12. I used
BASIC. And now they have conferences because they don't know how to write data
structures and subroutines? No wonder software gets bloated...

~~~
dragonbonheur
And just last week I read about a post where some guys were amazed that one
coud write loops without for {;;} while {} or do { } while

Facepalm.

------
ufo
One thing that I still wonder about is, in cases where I need for some object
to hold some state, whether it is better to use a class or a closure. Both
approaches are similar in many ways but still subtly different. Is there a
good rule of thumb, kind of like the one for classes vs tagged unions?
(classes let you add new classes but don't like if you add a new method,
tagged unions let you add new methods but make it hard to add a new type).

------
eliben
I think most of the comments here are taking it too far. Not using classes in
some cases is not equivalent to stopping using classes altogether. Classes are
yet another tool in the programmer's toolbox. Sometimes the tool makes sense,
sometimes it doesn't. The trick is to know when. But jumping to absolutes is
surely not the right way to go about it.

------
mclin
I agree with most of this issues, but it sounds like his editor doesn't have
auto import and jump to definition like Eclipse.

eg complaint about nested packages. (not that I agree that this is a necessary
class): instead of MuffinMail.MuffinHash.MuffinHash, type MuffinHash and have
your editor add: from MuffinMail.MuffinHash import MuffinHash.

~~~
timruffles
Tools to reduce the burden of tautology are workarounds. You can rely on tools
to make the worst design/language less painful, but it's not an argument
against avoiding tautology.

------
rurounijones
"Stop writing classes... "

No

Ooooh, you wanted to make a case for not using classes in certain situations?
Then enough with the linkbait title.

------
danbmil99
The best use of Python Classes is as a stand-in for Javascript-style object
syntax, ala:

    
    
      class foo:
        pass
    
      f = foo()
        f.bar = "yes"
    

which is easier to type and more readable than:

    
    
      f = {}
        f['bar'] = "yes"
    

(credit where due: learned this trick from TB)

~~~
stock_toaster
You can simplify it a bit by building the container class on the fly, if
desired.

    
    
      >>> x = type('Foo', (object,), {})
      >>> x.bar = 1
      >>> x.bar
      1

------
ObnoxiousJul
OOP obfuscate our programs by blurring the frontier between data and
treatment. I can't agree more, since I made the mistake quite a few times
myself.

------
donald_draper
I wish they told me that when I took inline lessons on class-class.org

