Quando comecei a usar uma linguagem orientada a objetos (Java), eu simplesmente fui "Legal" e comecei a codificar. Eu realmente nunca pensei nisso até recentemente, depois de ter lido muitas perguntas sobre OOP. A impressão geral que tenho é que as pessoas lutam com isso. Como não achei isso tão difícil, e não diria que sou um gênio, estou pensando que devo ter perdido algo ou entendido mal.
Por que OOP é difícil de entender? É difícil de entender?
object-oriented
gablin
fonte
fonte
Respostas:
Pessoalmente, achei a mecânica do POO bastante fácil de entender. A parte mais difícil para mim foi o "porquê" disso. Quando fui exposto a ele pela primeira vez, parecia uma solução em busca de um problema. Aqui estão algumas razões pelas quais acho que a maioria das pessoas acha difícil:
IMHO ensinar OO desde o início é uma péssima idéia. A codificação processual não é um "mau hábito" e é a ferramenta certa para alguns trabalhos. Métodos individuais em um programa OO tendem a parecer bastante processuais de qualquer maneira. Além disso, antes de aprender a programação procedural o suficiente para que suas limitações se tornem visíveis, o OO não parece muito útil para o aluno.
Antes de realmente entender o OO, você precisa conhecer o básico de estruturas de dados e funções de ligação tardia / ordem superior. É difícil entender o polimorfismo (que basicamente passa um ponteiro para dados e várias funções que operam nos dados) se você nem entende os conceitos de estruturar dados, em vez de apenas usar primitivos e passar funções de ordem superior / ponteiros para funções.
Os padrões de design devem ser ensinados como algo fundamental para o OO, não como algo mais avançado. Os padrões de design ajudam a ver a floresta através das árvores e fornecem exemplos relativamente concretos de onde o OO pode simplificar problemas reais, e você vai querer aprendê-los eventualmente. Além disso, quando você realmente obtém OO, a maioria dos padrões de design se torna óbvia em retrospectiva.
fonte
Cat
classe que herdaMammal
, use um exemplo real de um programa real que teríamos escrito processualmente. Como uma estrutura de dados simples.Eu acho que existem alguns fatores que ainda não foram mencionados.
Primeiro de tudo, pelo menos em "OOP puro" (por exemplo, Smalltalk), onde tudo é um objeto, você precisa mudar sua mente para uma configuração pouco natural para pensar em um número (por apenas um exemplo) como um objeto inteligente em vez de apenas um valor - já que, na realidade,
21
(por exemplo) é realmente apenas um valor. Isso se torna especialmente problemático quando, por um lado, você diz que uma grande vantagem do OOP é modelar a realidade mais de perto, mas você começa adotando o que parece muito com uma visão inspirada em LSD, mesmo das partes mais básicas e óbvias de realidade.Segundo, a herança no POO também não segue muito de perto os modelos mentais das pessoas. Para a maioria das pessoas, classificar as coisas de maneira mais específica não tem nada perto das regras absolutas necessárias para criar uma hierarquia de classes que funcione. Em particular, criar um
class D
que herda de outroclass B
significa que os objetosclass D
compartilham absolutamente, positivamente todas as características declass B
.class D
pode adicionar novas e diferentes características próprias, mas todas as características declass B
devem permanecer intactas.Por outro lado, quando as pessoas classificam as coisas mentalmente, elas geralmente seguem um modelo muito mais flexível. Por exemplo, se uma pessoa faz algumas regras sobre o que constitui uma classe de objetos, é bastante típico que quase qualquer regra possa ser quebrada desde que outras regras sejam seguidas. Mesmo as poucas regras que realmente não podem ser violadas quase sempre podem ser "esticadas" um pouco.
Apenas por exemplo, considere "carro" como uma classe. É muito fácil perceber que a grande maioria do que a maioria das pessoas considera "carros" tem quatro rodas. A maioria das pessoas, no entanto, já viu (pelo menos uma foto) um carro com apenas três rodas. Alguns de nós da idade certa também se lembram de um ou dois carros de corrida do início dos anos 80 (mais ou menos) que tinham seis rodas - e assim por diante. Isso nos deixa basicamente com três opções:
Ensinar sobre POO geralmente se concentra na construção de enormes taxonomias - por exemplo, partes do que seria uma hierarquia gigante de toda a vida conhecida na Terra, ou algo nessa ordem. Isso levanta dois problemas: em primeiro lugar, tende a levar muitas pessoas a se concentrarem em grandes quantidades de informações que são absolutamente irrelevantes para a questão em questão. Em um ponto, vi uma discussão bastante longa sobre como modelar raças de cães e se (por exemplo) o "poodle miniatura" deve herdar do "poodle de tamanho completo", ou vice-versa, ou se deve haver uma base abstrata "Poodle "class, com" caniche em tamanho normal "e" caniche em miniatura "ambos herdados dela. O que todos pareciam ignorar era que o aplicativo deveria lidar com o controle de licenças para cães,
Segundo, e quase importante, leva a focar nas características dos itens, em vez de focar nas características importantes para a tarefa em questão. Isso leva a modelar as coisas como estão, onde (na maioria das vezes) o que é realmente necessário é construir o modelo mais simples que atenda às nossas necessidades e usar a abstração para atender às subclasses necessárias para atender à abstração que construímos.
Por fim, direi mais uma vez: estamos lentamente seguindo o mesmo caminho adotado pelos bancos de dados ao longo dos anos. Os primeiros bancos de dados seguiram o modelo hierárquico. Além de se concentrar exclusivamente em dados, essa é uma herança única. Por um curto período de tempo, alguns bancos de dados seguiram o modelo de rede - essencialmente idêntico à herança múltipla (e vistos desse ângulo, várias interfaces não são diferentes o suficiente de várias classes base para perceber ou se preocupar).
Há muito tempo, no entanto, os bancos de dados convergiam amplamente para o modelo relacional (e, embora não sejam SQL, nesse nível de abstração os bancos de dados "NoSQL" atuais também são relacionais). As vantagens do modelo relacional são suficientemente conhecidas que não vou me incomodar em repeti-las aqui. Vou apenas observar que o análogo mais próximo do modelo relacional que temos na programação é a programação genérica (e desculpe, mas, apesar do nome, os genéricos Java, por exemplo, não se qualificam realmente, embora sejam um pequeno passo no direção correta).
fonte
OOP requer a capacidade de pensar abstratamente; um presente / maldição que poucas pessoas, mesmo programadores profissionais, realmente têm.
fonte
Eu acho que você pode resumir a dificuldade básica desta maneira:
Claro, as pessoas podem se acostumar com o mapeamento de "left" como 270, e sim, dizer "Car.Turn" em vez de "turn the car" não é um salto tão grande. MAS, para lidar bem com esses objetos e criá-los, você deve inverter a maneira como pensa normalmente.
Em vez de manipular um objeto, estamos dizendo ao objeto para realmente fazer as coisas por conta própria. Pode não parecer mais difícil, mas dizer a uma janela para se abrir parece estranho. As pessoas que não estão acostumadas a esse modo de pensar precisam lutar repetidamente com essa estranheza até que finalmente se torne natural.
fonte
Qualquer paradigma exige um certo empurrão "além do limite" para entender, para a maioria das pessoas. Por definição, é um novo modo de pensamento e, portanto, requer uma certa quantidade de abandono de noções antigas e uma certa quantidade de compreensão completa do motivo pelo qual as novas noções são úteis.
Eu acho que grande parte do problema é que os métodos usados para ensinar programação de computadores são muito ruins em geral. OOP é tão comum agora que não é tão perceptível, mas você ainda o vê com frequência na programação funcional:
conceitos importantes estão ocultos atrás de nomes ímpares (FP: O que é uma mônada? OOP: Por que eles as chamam de funções e métodos outras vezes?)
conceitos estranhos são explicados em metáfora, em vez de em termos do que eles realmente fazem, ou por que você os usaria ou por que alguém pensou em usá-los (FP: Uma mônada é um traje espacial, envolve algum código. objeto é como um pato, pode fazer barulho, andar e herdar de Animal)
as coisas boas variam de pessoa para pessoa; portanto, não está claro qual será o ponto de inflexão para qualquer aluno e, muitas vezes, o professor nem se lembra. (FP: Ah, as mônadas permitem que você esconda algo no próprio tipo e continue sem escrever explicitamente o que está acontecendo a cada vez. OOP: Ah, objetos permitem manter as funções de um tipo de dados com esses dados.)
O pior de tudo é que, como a pergunta indica, algumas pessoas imediatamente começam a entender por que o conceito é bom e outras não. Realmente depende de qual é o ponto de inflexão. Para mim, compreender que objetos armazenam dados e métodos para esses dados era a chave, depois disso tudo se encaixava como uma extensão natural. Depois, saltei mais tarde, ao perceber que uma chamada de método de um objeto é muito semelhante a fazer uma chamada estática com esse objeto como o primeiro parâmetro.
Os pequenos saltos mais tarde ajudam a refinar a compreensão, mas é o inicial que tira uma pessoa de "OOP não faz sentido, por que as pessoas fazem isso?" to "OOP é o melhor, por que as pessoas fazem mais alguma coisa?"
fonte
Porque a explicação básica do OOP tem muito, muito pouco a ver com a forma como é usada no campo. A maioria dos programas para ensiná-lo tenta usar um modelo físico, como "Pense em um carro como um objeto, e as rodas como objetos e as portas e a transmissão ...", mas fora de alguns casos obscuros de programação de simulação, os objetos são muito mais frequentemente usados para representar conceitos não físicos ou para introduzir indiretos. O efeito é que isso faz as pessoas entenderem intuitivamente da maneira errada.
Ensinar a partir de padrões de design é uma maneira muito melhor de descrever o POO, pois mostra aos programadores como alguns problemas reais de modelagem podem ser efetivamente atacados com objetos, em vez de descrevê-lo em abstrato.
fonte
Discordo em grande parte da resposta de dsimcha:
Ensinar OO desde o início não é realmente uma má idéia em si, nem ensinar linguagens processuais. O importante é ensinar as pessoas a escrever um código claro, conciso e coeso, independentemente de OO ou processual.
Métodos individuais em bons programas de OO NÃO tendem a ser processuais. Isso está se tornando cada vez mais verdadeiro com a evolução das linguagens OO (leia C # porque, além de C ++, essa é a única outra linguagem OO que eu conheço) e sua sintaxe que fica cada vez mais complexa a cada dia (lambdas, LINQ para objetos etc.). A única semelhança entre métodos e procedimentos OO em linguagens procedurais é a natureza linear de cada uma, que duvido que mudaria tão cedo.
Você também não pode dominar uma linguagem processual sem entender as estruturas de dados. O conceito de ponteiro é tão importante para linguagens procedurais quanto para linguagens OO. A passagem de parâmetros por referência, por exemplo, que é bastante comum em linguagens procedurais, requer que você compreenda os ponteiros o quanto for necessário para aprender qualquer linguagem OO.
Eu não acho que os padrões de design devam ser ensinados no início da programação OO, porque eles não são fundamentais para a programação OO. Definitivamente, pode-se ser um bom programador de OO sem saber nada sobre padrões de design. De fato, uma pessoa pode até estar usando padrões de design conhecidos, mesmo sem saber que eles estão documentados como tal com nomes próprios e que livros são escritos sobre eles. O que deve ser ensinado fundamentalmente são princípios de design, como Responsabilidade Única, Fechamento Aberto e Segregação de Interface. Infelizmente, muitas pessoas que se consideram programadores de OO atualmente não estão familiarizadas com esse conceito fundamental ou apenas optam por ignorá-lo e é por isso que temos tanto código OO de lixo por aí.
Para responder à pergunta do pôster original, sim, OO é um conceito mais difícil de entender do que a programação procedural. Isso ocorre porque não pensamos em termos de propriedades e métodos de objetos da vida real. Por exemplo, o cérebro humano não pensa prontamente em "TurnOn" como um método de TV, mas o vê como uma função do ser humano ligar a TV. Da mesma forma, o polimorfismo é um conceito estranho para o cérebro humano que geralmente vê cada objeto da vida real por apenas uma "face". Herança novamente não é natural para nossos cérebros. Só porque eu sou um desenvolvedor, não significa que meu filho seria um. De um modo geral, o cérebro humano precisa ser treinado para aprender OO, enquanto as linguagens processuais são mais naturais para ele.
fonte
Eu acho que muitos programadores têm dificuldade com o design e o planejamento inicial, para começar. Mesmo que alguém faça todo o design para você, ainda é possível romper com os princípios de POO. Se eu pegar um monte de código de espaguete e colocá-lo em uma classe, isso é realmente OOP? Alguém que não entende OOP ainda pode programar em Java. Além disso, não confunda a dificuldade de entender com a falta de vontade de seguir uma determinada metodologia ou discordar dela.
fonte
Você deve ler Objetos Nunca? Bem, quase nunca. (Associação ACM exigida) por Mordechai Ben-Ari, que sugere que a OOP é tão difícil, porque não é um paradigma que é realmente natural para modelar qualquer coisa. (Embora eu tenha reservas sobre o artigo, porque não está claro quais critérios ele sente que um programa precisa satisfazer para dizer que está escrito no paradigma OOP, em oposição a um paradigma processual usando uma linguagem OO.)
fonte
A programação orientada a objetos em si não é difícil.
A parte mais difícil é fazê-lo bem. Onde colocar o corte entre o código para que você possa mover facilmente as coisas para o objeto base comum e estendê-las mais tarde? Como tornar seu código utilizável por outras pessoas (estender classes, agrupar proxies, substituir método) sem passar por aros para fazer isso.
Essa é a parte mais difícil e, se bem feita, pode ser muito elegante e se mal feita pode ser muito desajeitada. Minha experiência pessoal é que exige muita prática em todas as situações em que você gostaria que o fizesse de maneira diferente, a fim de fazê-lo bem o suficiente desta vez.
fonte
Eu estava apenas assistindo um vídeo de Richard Feynman discutindo como as pessoas podem realmente ter metodologias completamente diferentes na cabeça quando pensam - quero dizer, completamente diferentes.
Quando faço projetos de alto nível, visualizo objetos, posso vê-los, ver suas interfaces e ver quais caminhos as informações precisam percorrer.
Também tenho problemas para lembrar detalhes e achei o OO uma grande ajuda organizacional - muito mais fácil encontrar funcionalidade do que digitalizar uma lista pouco organizada de sub-rotinas.
Para mim, o OO foi um grande benefício, mas se você não visualiza da mesma maneira ou não faz arquitetura de alto nível, provavelmente é inútil e irritante.
fonte
INSTR
) - porque o nome está ligado ao tipo (comostring::find
)Eu já tinha feito bastante a programação GW-Basic e Turbo Pascal antes de ser apresentado ao OO, então, inicialmente, ele fez minha cabeça.
Não faço ideia se é isso que acontece com os outros, mas para mim foi assim: meu processo de pensamento sobre programação era puramente processual. Como em: "tal e tal acontece, então tal e tal acontece a seguir", etc. Eu nunca considerei as variáveis e os dados nada mais que atores fugazes no fluxo do programa. A programação era "o fluxo de ações".
Suponho que o que não foi fácil de entender (por mais estúpido que pareça para mim agora), foi a idéia de que os dados / variáveis realmente importam , em um sentido mais profundo do que apenas ser atores fugazes no "fluxo" do programa. Ou, em outras palavras: continuei tentando compreendê-lo pelo que acontece , e não pelo que é , que é a verdadeira chave para entender isso.
fonte
Não acho difícil entender, mas pode ser que muitos dos programadores consultados sejam novos no conceito, vindos de linguagens procedurais.
Pelo que tenho visto / lido muitas pessoas (pelo menos nos fóruns) procuram um 'resultado' do OOP. Se você é um programador de procedimentos que não volta e modifica estender seu código, provavelmente pode ser difícil entender os benefícios.
Além disso, há muita POO ruim por aí, se as pessoas estão lendo / vendo isso, é fácil ver por que elas podem achar isso difícil.
OMI, você precisa esperar até ouvir um clique ou ser ensinado por alguém com conhecimento real, não acho que você possa se apressar.
fonte
Eu acho que a razão pela qual o POO é difícil para muitos é porque as ferramentas realmente não o facilitam.
Hoje, as linguagens de computador são uma abstração do que está acontecendo no computador.
OOP é uma maneira abstraída de representar abstrações.
Então, estamos usando uma abstração para criar abstrações com uma abstração. Acrescente a isso que o que estamos abstraindo são geralmente interações físicas / sociais muito complexas e, bem, não é de admirar.
fonte
Na verdade, eu tenho um blog chamado "Lutas na programação orientada a objetos", que nasceu de algumas das minhas lutas com o aprendizado. Eu acho que foi particularmente difícil para mim entender porque eu gastei muito tempo usando programação procedural, e tive dificuldade em entender a idéia de que um objeto poderia ser representado por uma coleção de atributos e comportamentos (eu estava acostumado a simplesmente uma coleção de variáveis e métodos).
Além disso, existem muitos conceitos que orientam um objeto de linguagem - herança, interfaces, polimorfismo, composição, etc. Há muito o que aprender sobre a teoria dele antes que você possa realmente escrever código de maneira eficaz e de uma maneira orientada a objetos. maneira, enquanto na programação procedural, é simplesmente uma questão de entender coisas como alocação de memória para variáveis e chamadas de ponto de entrada para outros métodos.
fonte
Motivação. É mais difícil aprender alguma coisa quando você não vê o porquê e também quando não consegue ver o que fez e descobrir se fez certo ou não.
O que é necessário são pequenos projetos que usam OO para fazer coisas úteis. Sugiro que você leia um livro sobre padrões de design e crie um que é obviamente útil e funciona bem com o OO. (Usei o Strategy da vez em que tentei. Algo como Flyweight ou Singleton seria uma má escolha, pois são maneiras de usar objetos em geral, não de objetos para realizar alguma coisa.)
fonte
Eu acho que depende da idade (idade como proxy da experiência) e, mais importante, do interesse. Se você é "jovem" (ou seja, verde, talvez) e nunca pensou em outra maneira, parece bastante direto. Por outro lado, se você acha que é a coisa mais legal que você já viu - aconteceu comigo aos 28 anos ou algo assim - é fácil gritar.
Por outro lado, se você pensa, como muitos de meus alunos de Java, "por que estamos aprendendo isso, é apenas uma moda passageira", é praticamente impossível aprender. Isso é verdade com a maioria das tecnologias.
fonte
Independentemente de qual paradigma (OOP, funcional etc.) você escolher, para escrever um programa de computador, você precisa saber quais etapas o seu programa fará.
A maneira natural de definir um processo é anotar suas etapas, para tarefas maiores, você as divide em etapas menores. Esta é a maneira processual, é assim que o computador funciona, é assim que você percorre sua lista de verificação passo a passo.
OOP é uma maneira diferente de pensar. Em vez de pensar em uma lista de tarefas que precisam ser realizadas passo a passo, você pensa nos objetos, suas habilidades e relacionamentos. Então você escreverá muitos objetos, métodos pequenos e seu programa funcionará magicamente. Para conseguir isso, você precisa torcer sua mente ...
E é por isso que OOP é difícil. Como tudo é um objeto, tudo o que eles fazem é pedir a outros objetos que façam alguma coisa, e esses outros objetos basicamente fazem alguns. Portanto, o controle em um programa OOP pode ir muito além entre os objetos.
fonte
Como alguém que atualmente está aprendendo programação e tendo alguns problemas nessa área, não acho que seja tão difícil entender o conceito quanto as implementações específicas desse conceito. Digo isso porque tenho a idéia do OOP e o uso no PHP há cerca de um ano, mas conforme passo para o C # e observo o uso de objetos por outros programadores, percebo que muitas pessoas o fazem da mesma maneira. que eu simplesmente não entendo. É isso especificamente que me levou a encontrar uma melhor compreensão dos princípios da OOP.
Obviamente, percebo que o problema é provavelmente a minha falta de experiência com uma linguagem nativamente OOP, e que, com o passar do tempo, encontrarei novas maneiras de utilizar objetos que não são tão claros para um novo programador quanto o que sou. atualmente experimentando. Jerry Coffin aborda isso algumas vezes, particularmente em seu comentário:
Acho que isso é muito preciso, pois é a impressão que muitas vezes tenho quando vejo alguém criando classes para coisas que não são realmente coisas - um exemplo específico me escapa, mas o mais próximo que posso chegar em tempo real é tratar a distância como um objeto (vou editar na próxima vez que vir algo que causa essa mesma confusão). Às vezes, o OOP parece desconsiderar temporariamente suas próprias regras e se torna menos intuitivo. Isso ocorre com mais frequência quando objetos estão produzindo objetos, herdados de uma classe que os está encapsulando, etc.
Penso que para alguém como eu, ajuda pensar no conceito de objetos como tendo múltiplas facetas, uma das quais inclui tratar algo como um objeto quando, de outra forma, não seria. Algo como a distância, com apenas uma pequena mudança de paradigma, poderia parecer um objeto teórico, mas não um que pudesse ser segurado em sua mão. Eu tenho que pensar nisso como tendo um conjunto de propriedades, mas um conjunto mais abstrato de comportamentos, como acessar suas propriedades. Não tenho certeza de que essa seja a chave do meu entendimento, mas parece ser para onde meus estudos atuais estão levando.
fonte
As terminologias foram o meu obstáculo ao aprender os princípios da programação orientada a objetos (POOP). É quando você compreende os fundamentos que as peças começam a se encaixar. Assim como todas as coisas que aprendem novos conceitos são um pouco difíceis.
Concordou que os padrões de design devem ser trabalhados pelo menos paralelamente ao OOP.
fonte
O salto principal para mim foi apenas entender o conceito abstrato de OOP. Agora, sou muito novo em programação em geral. Estou programando há um ano a um ano e meio, então minha introdução ao OOP foi com Actionscript and Processing. Quando aprendi a codificação Actionscript, ela não estava no OOP. Aprendi a codificar diretamente no painel Actions e foi assim que aprendi os fundamentos básicos da programação (variáveis, funções, loops etc.). Aprendi como fazer algo diretamente no palco do Flash ou Processing.
Quando a OOP surgiu, perceber que eu poderia criar métodos e propriedades dentro de um objeto para poder usar e reutilizar foi um pouco difícil de entender no começo. Tudo era muito abstrato e difícil de processar, mas as linguagens de programação eram muito melhores, mas foi preciso um pouco de fé para estabelecer essas conexões no início.
fonte
Receita
Boa compreensão de POO = bom mentor ou bons livros ou ambos + interesse pessoal + prática.
Interesse pessoal
Da minha experiência pessoal, o interesse pessoal percorre um longo caminho para atravessar a ponte da programação processual para a OOP, com as informações corretas de mentores, bons livros ou ambos combinados .
Prática, Prática e Prática
Meu melhor amigo para entender melhor o POO não passou de prática. Isso definitivamente promoverá suas habilidades de OOP.
Como diz o ditado: "Não há substituto para o trabalho duro nem atalho para o sucesso".
Boa sorte!
fonte