Torne as coisas o mais simples possível, mas não mais simples. Essa é a regra pela qual tento seguir. Às vezes, faz sentido que uma classe faça o que, estritamente falando, equivale a mais de uma coisa, se essas coisas estiverem relacionadas a algum tema comum . Veja o .NET; existem inúmeras classes que implementam um grande número de interfaces, cada uma com sua própria lista de membros necessários. Um método pode acabar precisando se tornar um pouco longo se fizer algo complexo com várias etapas intermediárias, todas interconectadas e, portanto, não se prestam muito bem a refatoração adicional. (A refatoração para manter os métodos curtos deve, em última análise, ter a legibilidade e a capacidade de manutenção; se o método longo for mais legível e / ou sustentável do que o curto, todo o resto será igual, aceitarei o longo a qualquer dia.)
Apenas "tornar as classes e métodos o menor possível" é, na minha opinião, equivocado. O verdadeiro desafio é, como aponta o @c_maker, fornecer boas abstrações. Seu exemplo de agrupamento de dois números é excelente, por exemplo, se você estiver trabalhando em uma implementação aritmética de números complexos, ou se em um sistema Unix, precisará se referir a um contexto de usuário / grupo. Faz muito pouco sentido se os números representam, por exemplo, um ID da fatura e um ID do produto a serem adicionados a essa fatura.
"As small as possible, but no smaller."