Раньше программа могла быть написана одним сплошным листингом. Но при попытке сделать изменения, оказалось что очень сложно понять все зависимости внутри программы, как только ее размер превышает некоторый критический уровень.
Появилась мода на модульность.
Но программы стали сложнее, и уже модуль перестал помещаться в мозг одного человека, чтобы можно было его быстро править.
В процессе различных подходов, был придуман ООП-подход, суть которого заключается в следующем:
Раз все программы оперируют некоторыми данными, то нужно взять эти данные, взять функции (методы), которые работают с этими данными и поместить в один объект.
Если нужно будет изменить тип данных, добавить/отнять/поделить функционал, то программист будет работать с одним этим объектом. При этом, если разные объекты запрашивают что-либо друг у друга, то в ООП довольно легко сделать версионность и обратную совместимость.
Ну а все остальное (наследование, полиморфизм и так далее) это уже возникло как следствие того, что ООП не решает все проблемы. Другой, более удобной глобальной парадигмы для сложных программ пока нет, вот ООП и занял свою нишу.
Программы поменьше, особенно те, которые могут быть написаны одним человеком, могут писаться как угодно, но чем больше программа, тем сложнее ее поддерживать, а ООП - один из самых доступных методов "поделить" программу на независимые инкапсулированные кусочки.