В идеале каждый модуль программы:
1) Должен делать всего одну вещь
2) Не должен открывать наружу внутренности реализации
3) Быть гибким, не привязанным к каким-то условностям (это самое сложное)
4) Быть самодостаточным (если это не мешает пункту 1, надо искать баланс самому)
5) Не модифицировать наружности (правда иногда без этого никак, но лучше это обойти если можно)