No seu blog, parece que você está familiarizado com a programação imperativa e funcional e com os conceitos básicos envolvidos na programação orientada a objetos, mas você nunca teve realmente um "clique" sobre o que torna útil. Vou tentar explicar em termos desse conhecimento e espero que seja útil para você.
Na sua essência, a OOP é uma maneira de usar o paradigma imperativo para gerenciar melhor os altos graus de complexidade, criando estruturas de dados "inteligentes" que modelam o domínio do problema. Em um programa (procedimento padrão não orientado a objetos), você tem duas coisas básicas: variáveis e código que sabe o que fazer com elas. O código recebe a entrada do usuário e de várias outras fontes, armazena-a em variáveis, opera nele e produz dados de saída que vão para o usuário ou para vários outros locais.
A programação orientada a objetos é uma maneira de simplificar seu programa, pegando esse padrão básico e repetindo-o em uma escala menor. Assim como um programa é uma grande coleção de dados com código que sabe o que fazer com ele, cada objeto é um pequeno pedaço de dados vinculado ao código que sabe o que fazer com ele.
Ao dividir o domínio do problema em partes menores e garantir que o máximo de dados possível seja vinculado diretamente ao código que sabe o que fazer com ele, você facilita muito o raciocínio sobre o processo como um todo e também sobre os sub- questões que compõem o processo.
Ao agrupar dados em classes de objetos, você pode centralizar o código relacionado a esses dados, facilitando o código relevante para localizar e depurar. E, encapsulando os dados por trás dos especificadores de acesso e acessando-os apenas por métodos (ou propriedades, se o seu idioma os suportar), você reduz bastante o potencial de corrupção de dados ou violação de invariantes.
E usando herança e polimorfismo, você pode reutilizar classes preexistentes, personalizando-as para atender às suas necessidades específicas, sem ter que modificar os originais ou reescrever tudo desde o início. (O que é algo que você nunca deve fazer , se puder evitá-lo.) Apenas tome cuidado para entender seu objeto base ou poderá acabar com cangurus assassinos .
Para mim, esses são os princípios fundamentais da programação orientada a objetos: gerenciamento de complexidade, centralização de código e modelagem aprimorada de domínios de problemas através da criação de classes de objetos, herança e polimorfismo e segurança aumentada sem sacrificar o poder ou controle através do uso de encapsulamento e propriedades. Espero que isso ajude você a entender por que muitos programadores acham útil.
EDIT: Em resposta à pergunta de Joel nos comentários,
Você pode explicar o que um "programa orientado a objetos" contém (além dessas definições sofisticadas que você descreveu) que são fundamentalmente diferentes de um programa imperativo? Como você "faz a bola rolar?"
Um pequeno aviso aqui. Meu modelo de "um programa orientado a objetos" é basicamente o modelo Delphi, que é muito semelhante ao modelo C # /. NET desde que eles foram criados por ex-membros da equipe Delphi. O que estou dizendo aqui pode não se aplicar, ou não se aplica tanto, em outros idiomas OO.
Um programa orientado a objetos é aquele em que toda a lógica é estruturada em torno de objetos. Claro que isso precisa ser iniciado em algum lugar. Seu programa Delphi típico contém código de inicialização que cria um objeto singleton chamado Application. No início do programa, ele chama Application.Initialize, depois uma chamada Application.CreateFormpara todos os formulários que você deseja carregar na memória desde o início e, em seguida, Application.Run,exibe o formulário principal na tela e inicia o loop de entrada / evento que forma o núcleo de qualquer programas de computador interativos.
O aplicativo e seus formulários pesquisam os eventos recebidos do sistema operacional e os convertem em chamadas de método no seu objeto. Uma coisa que é muito comum é o uso de manipuladores de eventos, ou "delegados" no .NET-speak. Um objeto possui um método que diz "faça X e Y, mas também verifique se esse manipulador de eventos específico está atribuído e chame-o se for". Um manipulador de eventos é um ponteiro de método - um fechamento muito simples que contém uma referência ao método e uma referência à instância do objeto - usado para estender o comportamento dos objetos. Por exemplo, se eu tiver um objeto de botão no meu formulário, personalizo seu comportamento anexando um manipulador de eventos OnClick, que faz com que outro objeto execute um método quando o botão é clicado.
Portanto, em um programa orientado a objetos, a maior parte do trabalho é realizada definindo objetos com certas responsabilidades e vinculando-os, por meio de ponteiros de método ou por um objeto que chama diretamente um método definido na interface pública de outro objeto. (E agora estamos de volta ao encapsulamento.) Essa é uma ideia que eu não tinha noção de voltar antes de ter aulas de OOP na faculdade.