Я немного программировал на C, и, хотя ООП отлично подходит для упрощения задач путем построения иерархий классов, я все же считаю простой подход на C самым простым и лучшим во многих случаях. В C мы имеем структуры только с открытыми членами, и программист передает такие структуры функциям (в Java такими функциями могут быть, например, статические функции в некотором служебном классе), которые управляют членами. Данные и алгоритм разделены, так как функции не являются членами структур. У меня всегда было ощущение, что VO объекты похожи на структуры в C.
Есть много случаев, когда язык C не самый лучший, потому что, например, нет никакой иерархии, нет полиморфизма, вещи, которые приличные программисты ООП находят полезными. Однако в целом мне нравится этот простой C-подход, и я предпочитаю использовать его, если не знаю, что ООП-метод будет действительно полезным. Например. когда мне нужно использовать иерархию классов для моделирования чего-либо или мне нужно убедиться, что члены одного или нескольких классов (в иерархии) всегда согласуются друг с другом, тогда я не могу использовать подход структуры C. Но в этих случаях у меня были бы не только сеттеры и геттеры.
Я бы также сослался на эту статью, посвященную C ++, но мне нравится, как этот парень объясняет такие вещи:
http://www.gotw.ca/gotw/084.htm
В этой статье 2 правила о том, когда делать функцию членом класса:
(из цитаты ниже я пропускаю некоторые вещи, прочитайте оригинал, если хотите все)
Всегда делайте его членом, если он должен быть одним: какие операции должны быть членами, потому что язык C ++ просто говорит об этом (например, конструкторы) или по функциональным причинам (например, они должны быть виртуальными)? Если они должны быть, тогда да, они просто должны быть; дело закрыто.
Предпочитают сделать его участником, если ему нужен доступ к внутренним компонентам: каким операциям нужен доступ к внутренним данным, которые мы бы иначе предоставили через дружбу? Обычно они должны быть членами.
Во всех других случаях предпочитайте делать его не-членом: какие операции могут работать так же хорошо, как и не-друзья? Они могут и, следовательно, обычно должны быть не членами. Это должен быть случай по умолчанию, к которому нужно стремиться.
У меня такое ощущение, что если вы сомневаетесь, добавлять ли функции в эти классы, у вас нет реальной необходимости делать это. То, что я написал здесь, является лишь частью всех причин, по которым я не буду добавлять методы в такие классы, однако, возможно, это и есть отец всех моих других причин. Но это все субъективно, так что YMMV. Кстати, метод статических функций утилит делает модульное тестирование простым в большинстве случаев.