I think the source of confusion is the word "possible". The principle becomes ridiculous if "possible" is referring only to the code, because the smallest possible class that does anything useful has only one method (and in some cases zero). The candidate very likely meant to take into account cohesion and coupling.
– KelvinFeb 13 '17 at 19:07

7 Answers
7

There is a grain of truth in that advice, but IMHO it is not very well expressed, thus easy to misunderstand and/or to take to a stupid extreme. At any rate, this should be a rule of thumb, rather than hard law. And you should always imply in such rules the clause "within reasonable limits", or "but don't forget to use your common sense" :-)

The grain of truth is that in practice, classes and methods always tend to grow by nature, not shrink. A bug fix here, a little feature extension there, handling a special case over there... and voila, your once neat and small class starts to bloat. Over time, your code almost inevitably tends to become a monstrous mess of spaghetti - unless you actively fight this tendency via refactoring. Refactoring almost always produces many smaller classes / methods from a few big ones. But of course, there is a sensible limit to miniaturizing. The point of refactoring is not to have smaller classes and methods per se, but to make your code cleaner, easier to understand and maintain. At a certain point, making your methods / classes smaller starts to decrease readability, rather than increasing it. Aim towards that optimum. It is a blurry and moving target area, so you don't need to hit it spot on. Just improve the code a little whenever you notice some problem with it.

definitely a rule to not follow blindly, too many tiny classes is so much worse than a few larger classes most of the time.
– RyathalDec 15 '11 at 13:24

4

My personal rule of thumb is: if you can't see a whole method implementation on the screen at once, refactor.
– Dan RayDec 15 '11 at 13:36

6

@DanRay, yeah, I used to have the same rule, until I read Clean Code. It was quite a shock, but gradually caused my optimum to go down to around 10 lines.
– Péter TörökDec 15 '11 at 13:45

2

IMO Clean Code is horrible in its extremity towards small methods. The problem is that when methods are made smaller, there will be more of them. Of course too long methods are too long, but Bob Martin seems to prefer 10 1-line methods over 1 10-line one (thus the effectively same code taking about 5x as much screen space). Maybe it's meant to be some sort of educational trick, I can't believe someone actually thinks the code in that book is any good.
– Joonas PulakkaDec 16 '11 at 10:00

5

@JoonasPulakka - Let's just say I've never read a method and thought, "I wish this method did more." By shortening methods you can write very descriptive method names that can often eliminate the need to read the method body entirely. I found the advice in Clean Code to be very sensible. We'll just have to agree to disagree. :)
– David HarknessJan 20 '12 at 8:06

The more important issue to stress here is creating good abstractions. Small classes that are loosely coupled and have high cohesion are the product of good abstractions.

Sometimes it makes perfect sense to encapsulate two integers in a class. Especially if you want to have methods 'attached' to this class to also encapsulate how one can manipulate these attributes and to make sure you protect them from other parts of the program changing them.

Another positive to create a class in this case is that the class can evolve a lot better/nicer than let's say a lower level data structure like a Map or List can.

Third, a good abstraction can improve readability a great deal. Classes that adhere to SRP are usually a lot easier to understand by a human than classes that do not.

And just as a final note... no matter how good of a student you are... to understand OOP and good abstractions and when to use them, you need experience. You need to write bad code and go through the pain to maintain it. You need to see others write good code to build up your knowledge about what is 'good' and what will be a problem down the line... So do not beat yourself up if you just do not get it right away.

In object-oriented programming, the single responsibility principle states that every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class. Usually you are doing more than one thing if your class gets too big.
In your case the class is just a data class which holds data which is totaly ok. You shouldn't name the class PairOfInteger. What does the integers describe?
Depending on your scenario a Tuple (like in C#) might be sufficient, too.
And you may want to think about a strut instead of a class.

Make things as simple as possible, but not simpler. That's the rule I try to go by. Sometimes, it actually makes sense for a class to do what strictly speaking amounts to more than one thing, if those things are related on some common theme. Look at .NET; there are tons of classes that implement a large number of interfaces, each with its own list of required members. A method might end up needing to become somewhat long if it does something complex with a number of intermediate steps which are all interconnected and thus don't lend themselves very well to further refactoring. (Refactoring to keep methods short should ultimately be about readability and maintainability; if the long method is more readable and/or maintainable than a short one, all else equal, I will take the long one any day.)

To only "make classes and methods as small as possible" is, in my opinion, misguided. The real challenge is, as @c_maker points out, to provide good abstractions. Your example of grouping two numbers together is great, for example, if you are working on an implementation of complex numbers arithmetic, or if on a Unix system you need to refer to a user/group context. It makes very little sense if the numbers represent, say, an invoice ID and a product ID to be added to that invoice.

The God Object anti-pattern is what she was probably alluding to. I do tend to think that if I have an "and" in my class description, I should have two classes. If I have more than ten lines of code in a method/function, then I should break it up. As the pirate code, those are more guidelines than rules.

Uncle Bob says you should refactor/split/extract your methods until it is impossible to make them smaller. This usually ends in having several methods with 3 or 4 lines each. When you get too many methods, you have to make more classes.

If you try to follow SRP and one level of abstraction per method, these rules serve you well. At least they serve me well. Aiming for "as small as possible" gives me reasonable small methods, as I usually fall short the aim.