fundo
Eu não sou um grande fã de abstração. Admito que alguém possa se beneficiar da adaptabilidade, portabilidade e reutilização de interfaces, etc. Há um benefício real lá, e eu não quero questionar isso, então vamos ignorá-lo.
Há o outro "benefício" principal da abstração, que é ocultar a lógica de implementação e os detalhes dos usuários dessa abstração. O argumento é que você não precisa conhecer os detalhes e, nesse momento, deve-se concentrar em sua própria lógica. Faz sentido na teoria.
No entanto, sempre que tenho mantido grandes aplicativos corporativos, sempre preciso saber mais detalhes. Torna-se um enorme aborrecimento, aprofundando cada vez mais a abstração para descobrir exatamente o que algo faz; ou seja, ter que fazer "declaração aberta" cerca de 12 vezes antes de encontrar o procedimento armazenado usado.
Essa mentalidade de "ocultar os detalhes" parece apenas atrapalhar. Estou sempre desejando interfaces mais transparentes e menos abstração. Eu posso ler código fonte de alto nível e saber o que ele faz, mas nunca vou saber como ele faz, quando ele faz, é o que eu realmente preciso saber.
Oque esta acontecendo aqui? Todos os sistemas em que trabalhei foram mal projetados (pelo menos dessa perspectiva)?
Minha filosofia
Quando desenvolvo software, sinto que tento seguir uma filosofia que sinto estar intimamente relacionada à filosofia do ArchLinux :
O Arch Linux mantém as complexidades inerentes a um sistema GNU / Linux, mantendo-as bem organizadas e transparentes. Os desenvolvedores e usuários do Arch Linux acreditam que tentar ocultar as complexidades de um sistema realmente resulta em um sistema ainda mais complexo e, portanto, deve ser evitado.
E, portanto, nunca tento ocultar a complexidade do meu software atrás das camadas de abstração. Eu tento abusar da abstração, não me tornar escravo dela.
Pergunta no coração
- Existe um valor real em ocultar os detalhes?
- Não estamos sacrificando a transparência?
- Essa transparência não é valiosa?
fonte
Respostas:
O motivo para ocultar os detalhes não é mantê-los ocultos; é possibilitar a modificação da implementação sem quebrar o código dependente.
Imagine que você tenha uma lista de objetos e cada objeto tenha uma
Name
propriedade e outros dados. E muitas vezes, você precisa encontrar um item na lista queName
corresponda a uma determinada string.A maneira óbvia é fazer um loop sobre cada item, um por um, e verificar se
Name
corresponde à sequência. Mas se você achar que isso está demorando muito (como faria se tivesse vários milhares de itens na lista), convém substituí-lo por uma pesquisa no dicionário de objetos de string.Agora, se todas as suas pesquisas foram feitas recuperando a lista e fazendo um loop sobre ela, você tem uma enorme quantidade de trabalho a fazer para corrigir isso. É ainda mais difícil se você estiver em uma biblioteca e se forem usados por terceiros; você não pode sair e consertar o código deles !
Mas se você tivesse um
FindByName
método para encapsular o processo de pesquisa de nome, você pode simplesmente mudar a maneira como ele é implementado e todo o código que o chama continuará funcionando, e ficará muito mais rápido gratuitamente. Esse é o valor real da abstração e encapsulamento.fonte
Acabei de ler a seção no Código completo sobre abstração, e é aí que a maioria dessas fontes.
O objetivo da abstração é remover a necessidade de perguntar "como isso é implementado?". Quando você liga
user.get_id()
, você sabe queid
é isso que você receberá de volta. Se você precisar perguntar "como isso obtém a identificação do usuário?" então você provavelmente não precisa de umid
, ouget_id()
retorna algo inesperado e mal projetado.Você usa abstração para permitir que você crie:
não projetar
fonte
Sim. Ao apresentar abstrações, podemos pensar e programar em um nível superior.
Imagine modelar sistemas físicos sem cálculo ou álgebra matricial. É completamente impraticável. Da mesma forma, se pudermos apenas programar em nível escalar, não conseguiremos resolver problemas interessantes. Mesmo aplicativos da Web relativamente simples podem se beneficiar muito de abstrações como bibliotecas de tags. É muito mais fácil inserir uma tag que significa "campos de entrada de endereço" do que criar repetidamente quatro campos de texto e uma caixa de seleção. E se você decidir expandir para o exterior, poderá apenas modificar a definição de tag, em vez de corrigir todos os formulários para lidar com endereços internacionais. O uso eficaz da abstração é o que torna alguns programadores dez vezes mais eficazes que outros.
Os seres humanos têm uma memória de trabalho limitada. A abstração nos permite raciocinar sobre sistemas grandes.
Não. Se abstrações não forem usadas, o objetivo de um componente de software será oculto em detalhes repetidos. Os desenvolvedores passam seus dias vasculhando códigos como este:
e pensando "oh sim, outro loop de quatro níveis sobre os kits", em vez de ver
Como você apontou, há um custo para a indireção. Não faz sentido criar camadas "apenas por precaução". Use a abstração para reduzir a duplicação e esclarecer o código.
fonte
Quando as pessoas dizem que as abstrações ocultam os detalhes da implementação, na verdade não significam "ocultar" no sentido de dificultar a localização. O que eles querem dizer é separar os detalhes da implementação da interface pública, para manter a interface simples, concisa e gerenciável. Assim como um carro "esconde" a maior parte de suas partes vitais e oferece apenas um conjunto de controles bastante rudimentar para operá-los, um módulo de software "oculta" a maior parte de sua funcionalidade nas profundezas do intestino e expõe apenas um número limitado de métodos de acesso a eles. Dirija. Imagine um carro em que você tivesse que operar manualmente todos os componentes internos do motor (e há muitos deles), seria muito difícil manter um olho no tráfego e encontrar o caminho.
Mas manter a interface simples não é apenas uma coisa estética; pode fazer a diferença entre um projeto bem-sucedido e uma Marcha da Morte. Vamos bancar o advogado do diabo por um minuto; imagine um projeto de software sem abstrações. Se você precisar manter um valor, use uma variável global. Se você precisar usar a funcionalidade mais de uma vez, copie e cole. Se você precisar de duas versões diferentes de uma determinada seção de código, copie e cole, envolva-a em uma
if
instrução e modifique os dois ramos. Tecnicamente falando, funciona, mas alguns meses depois, você estará enfrentando alguns problemas realmente desagradáveis:Em uma base de código mal abstraída, o impacto geralmente aumenta exponencialmente com o tamanho da base de código, ou seja, adicionar uma quantidade constante de código aumenta o esforço de manutenção por um fator constante. Para piorar a situação, adicionar mais programadores a um projeto não aumenta a produtividade linearmente, mas logaritmicamente na melhor das hipóteses (porque quanto maior sua equipe, mais sobrecarga é necessária para a comunicação).
fonte
Eu acho que você deve entender como funciona, se necessário. Depois de determinar que ele faz o que você pensou que faria, então você fica tranquilo. Eu nunca pensei que o objetivo era escondê-lo para todo o sempre.
Depois de definir um alarme em um relógio que você acredita que funcionará, você pode dormir um pouco sabendo que ele disparará no horário correto. Acordar uma hora mais cedo só para ver os segundos passarem é um desperdício.
fonte
Para responder às suas perguntas especificamente:
Sim. Como você reconhece na primeira linha da sua pergunta.
Na verdade não. Uma abstração bem escrita facilitará a compreensão dos detalhes, se necessário.
Sim. As abstrações devem ser projetadas e implementadas para facilitar a compreensão dos detalhes quando necessário / desejado.
fonte
Eu diria que esconder os detalhes é ótimo quando as coisas ocultas funcionam.
Por exemplo, digamos que desenvolvamos uma interface que define comportamentos (por exemplo, GetListItems, SendListItem), que são dois recursos iniciados pelo usuário com um clique de botão ou algo assim. AGORA, cada usuário pode ter seu próprio "ListItemStore". está no facebook, no myspace .. (por exemplo) .. e diz que é salvo como uma propriedade / configuração do usuário em algum lugar no aplicativo por meio de preferências do usuário. e diz que é possível para os desenvolvedores do aplicativo adicionar ListItemStore adicionais ao longo de time (mybook, facespace, etc.)
agora há muitos detalhes na conexão com o facebook e na obtenção de itens ... e há tantos detalhes ao se conectar ao myspace ... e assim por diante ...
agora, depois que o código inicial de "acesso à loja" é gravado, ele pode não precisar ser modificado (no caso dos facebooks, provavelmente precisamos de um desenvolvedor em tempo integral para acompanhar as alterações, zing ..),
então, quando você usa o código, é algo como:
e agora você tem os dados do usuário de onde quer que eles estejam armazenados, e como tudo o que me preocupa é obter a lista de itens e fazer alguma coisa com ele, e já que foram necessárias apenas duas linhas, que funcionam, não importa como muitas outras lojas são adicionadas, posso voltar a responder / publicar perguntas na pilha ... lol ..
Então, todo o encanamento para que isso aconteça é "oculto" e quem realmente se importa com o que faz, desde que eu receba a lista correta de itens. Se você tiver testes de unidade, pode ficar ainda mais fácil porque os resultados devem " já foi quantificado ..
fonte
O que você chama de "Ocultar", muitos vêem como uma separação de preocupações (por exemplo, Implementação vs. Interface).
Na minha opinião, um grande benefício da abstração é reduzir a confusão de detalhes desnecessários do espaço limitado do cérebro do desenvolvedor.
Se o código de implementação fosse ofuscado, eu poderia ver que isso dificulta a transparência, mas a abstração como a vejo é apenas uma boa organização.
fonte
Primeiro, qualquer coisa além de uma única instrução de código de máquina é essencialmente abstração - um
while...do
loop é uma maneira simbólica consistente de representar as comparações e chamadas de endereço necessárias para repetir um conjunto de instruções até que uma condição seja atendida. Da mesma forma, o tipo int é uma abstração para o número X de bits (dependendo do seu sistema). A programação tem tudo a ver com abstração.Você provavelmente concordaria que essas abstrações primitivas são muito úteis. Bem, assim é ser capaz de construir o seu próprio. OOAD e OOP têm tudo a ver.
Suponha que você tenha um requisito no qual os usuários possam exportar os dados de uma tela em vários formatos: texto delimitado, excel e pdf. Não é prático criar uma interface chamada "Exportador" com um método de exportação (dados), com base no qual você pode criar um DelimitedTextExporter, um ExcelExporter e um PDFExporter, cada um dos quais sabe como criar sua saída específica? Tudo o que o programa de chamada precisa saber é que ele pode chamar o método de exportação (dados) e qualquer implementação usada fará seu trabalho. Além disso, se as regras de texto delimitado forem alteradas, você poderá alterar o DelimitedTextExporter sem precisar mexer no ExcelExporter, possivelmente quebrando-o.
Praticamente todos os padrões de design conhecidos usados na programação OO dependem da abstração. Eu recomendo a leitura de Freeman e Freeman's Head First Design Patterns para ter uma idéia melhor de por que a abstração é uma coisa boa
fonte
Acho que entendo sua opinião sobre isso e acho que tenho uma opinião semelhante.
Trabalhei com desenvolvedores Java que transformam 50 classes de linhas de código em 3 classes e 3 interfaces, porque é fácil de entender. E eu não aguentava.
A coisa era muito difícil de entender, quase impossível de depurar e nunca precisava "mudar a implementação".
Por outro lado, também vi código em que vários objetos compartilham comportamento semelhante e são usados em um só lugar, e poderiam realmente usar loops comuns de classificação / processamento se os métodos tivessem sido expostos por meio da interface comum.
Assim, IMHO, objetos principais que provavelmente serão usados em cenários semelhantes geralmente se beneficiam de comportamentos comuns que devem ser acessíveis através da interface. Mas é basicamente isso: abstrair coisas simples porque é certo ou possibilitar a troca de implementações é apenas uma maneira de tornar o código confuso.
Por outro lado, prefiro aulas mais inteligentes e longas do que uma quantidade explosiva de turmas pequenas com todos os problemas de gerenciamento da vida, relacionamentos difíceis de ver e gráficos de chamadas de espaguete. Então, algumas pessoas vão discordar de mim.
fonte
O objetivo norteador de ocultar e abstração deve ser dissociar o usuário da implementação para que ele possa ser alterado de forma independente. Se o consumidor estiver acoplado aos detalhes da implementação, devido à brincadeira com os internos, ambos são lançados na pedra e fica mais difícil introduzir novos recursos. ou algoritmos melhores no futuro.
Ao escrever um módulo, partes ocultas da implementação oferecem a você a capacidade de alterá-las sem o risco de quebrar outro código que você não consegue imaginar.
Outra vantagem de fornecer interfaces opacas é que elas reduzem significativamente a área de superfície entre os subsistemas. Ao reduzir a quantidade de maneiras pelas quais eles podem interagir, eles podem se tornar mais previsíveis, mais fáceis de testar e ter menos erros. As interações entre os módulos também aumentam quadraticamente com o número de módulos, portanto, é importante tentar controlar esse crescimento da complexidade.
Dito isto, é claro que é possível ocultar demais e aninhar interfaces muito profundas. O trabalho do programador, como um ser humano inteligente, é projetar o sistema para que seja útil ao máximo, além de minimizar a complexidade e maximizar a manutenção.
fonte
Em muitos casos, você simplesmente não precisa saber como as coisas são implementadas. Eu quase posso garantir que você escreverá um código como esse
people.Where(p => p.Surname == "Smith")
tantas vezes por dia, mas dificilmente pensará "como esseWhere()
método realmente funciona?" Você simplesmente não se importa - você sabe que esse método existe e que obtém os resultados desejados. Por que você se importaria como isso funciona?É exatamente o mesmo para qualquer software interno; só porque não foi escrito pela Oracle, Microsoft, etc, não significa que você precise pesquisar sobre como ele é implementado. Você pode esperar razoavelmente que um método chamado
GetAllPeopleWithSurname(string name)
retorne uma lista de pessoas com esse sobrenome. Pode percorrer uma lista, pode usar um dicionário, pode fazer algo completamente louco, mas você não deve se importar .Há uma exceção a essa regra, é claro (não seria uma regra sem uma!) E isso ocorre se houver um erro no método. Portanto, no exemplo acima, se você possui uma lista com três pessoas e sabe que uma delas tem o sobrenome Smith e elas não são retornadas na lista , você se preocupa com a implementação desse método, porque está claramente quebrado .
A abstração, quando feita corretamente, é maravilhosa porque permite filtrar todas as coisas que não são úteis quando você precisa lê-las posteriormente. Não se esqueça que gasta muito mais tempo lendo o código do que o escrevendo; portanto, a ênfase deve estar em tornar essa tarefa o mais fácil possível. Você também pode estar pensando que abstração significa uma hierarquia de objetos contanto que seu braço, mas pode ser tão simples quanto refatorar um método de 100 linhas em 10 métodos, cada um com 10 linhas. Então, o que antes era 10 etapas agrupadas agora é 10 etapas separadas, permitindo que você vá direto para o local onde esse bug traquina está escondido.
fonte
PeopleFactory.People.Strategy.MakePeople.(CoutryLaw.NameRegistry.NameMaker.Make()) as People.Female
Abstrações resultam em ocultação de informações. Isso deve terminar no acoplamento inferior. Isso deve levar a menos riscos na mudança. Isso deve levar os programadores felizes, não ficando nervosos ao tocar no código.
Essas idéias são expressas através de três leis essenciais na arquitetura de software:
Lei de Simon: "Hierarquias reduzem a complexidade". (Hierarquias introduzem abstração)
Lei de Parna: "Somente o que está oculto pode ser alterado sem risco".
Lei de Constantin: programas robustos precisam de baixo acoplamento e alta coesão
fonte
Também estou no negócio de aplicativos corporativos e essa pergunta chamou minha atenção porque eu mesma tenho a mesma pergunta. Eu tive algumas idéias sobre a questão da abstração ao longo da minha carreira até agora, mas minha visão não é de modo algum a resposta universal. Continuo aprendendo / ouvindo novas idéias e pensamentos, então o que acredito agora pode mudar.
Quando eu mantinha uma aplicação de saúde grande e complexa, gostava de você, odiava todas as abstrações lá. Descobrir onde todo o código vai foi uma dor no pescoço. Pular em diferentes classes me deixou tonto. Então eu disse a mim mesmo "abstração é uma porcaria, vou minimizar a abstração quando criar coisas".
Então chegou a hora de projetar um aplicativo (pequeno componente de serviço da Web) a partir do zero. Lembrando de toda a dor, eu tinha um design bastante plano do componente. O problema era que, quando os requisitos foram alterados, tive que fazer alterações em muitos lugares diferentes (os requisitos eram bastante fluidos e não pude fazer nada sobre isso). Foi tão ruim que eu basicamente joguei fora meu design inicial e o redesenhei com abstração, e as coisas melhoraram - eu não precisei fazer alterações em muitos lugares quando os requisitos mudaram mais.
Entreguei o aplicativo, fiquei sentado por algumas semanas e fui orientado a começar a manter o aplicativo. Fazia um tempo, não me lembrava de tudo, então lutei um pouco para entender meu próprio código, e a abstração não estava ajudando.
Fui colocado em muitos outros projetos depois e tive a chance de brincar um pouco mais com os níveis de abstração. O que realmente acho é que, e essa é apenas minha opinião pessoal, a abstração ajuda muito no desenvolvimento, mas tem um impacto negativo quando você não escreve o código e está tentando entender tudo no nível mais profundo de um aplicativo; você passará mais tempo pulando em diferentes classes e tentando fazer as conexões.
Meu sentimento é que a abstração é tão valiosa durante o tempo de desenvolvimento que vale a pena o problema que enfrentamos como mantenedor ao tentar entender o código. Existem softwares para resolver problemas de negócios, os problemas de negócios evoluem com o tempo; portanto, o software precisa evoluir com o tempo. Sem abstração, evoluir o software é muito difícil. Pode-se projetar abstração de uma maneira que o mantenedor possa navegar facilmente pela base de código depois de ver o padrão da estrutura do código, de modo que apenas a curva de aprendizado inicial seja frustrante.
fonte
Como outros já disseram, "ocultar detalhes" por trás de uma abstração permite que eles sejam alterados sem afetar os usuários. Esta idéia vem dos critérios de Parnas para serem usados na decomposição de sistemas em módulos (1972) , , e está relacionada à idéia de tipos de dados abstratos (ADT) e programação orientada a objetos.
Ao mesmo tempo, o modelo relacional de dados do Codd para grandes bancos de dados compartilhados (1970) foi motivado (veja o resumo e a introdução) ao querer alterar a representação de armazenamento interno dos bancos de dados, sem afetar os usuários do banco de dados. Ele viu programadores regularmente levando dias, modificando páginas de código, para lidar com pequenas alterações de armazenamento.
Dito isto, uma abstração não é muito útil se você precisar ver o que está dentro dela para poder usá-la. Pode ser muito difícil projetá-lo bem. Um exemplo de uma boa abstração é a adição - quando foi a última vez que você teve que pensar no que acontece lá dentro? (mas às vezes você faz, por exemplo, para transbordamento).
O problema essencial (IMHO) é que, para projetar bem os módulos (no sentido de Parnas), você precisa prever o que vai mudar e o que não vai mudar. Prever o futuro é difícil - mas se você tiver muita experiência com algo e entender claramente, poderá fazer um bom trabalho de previsão. E, portanto, você pode criar um módulo (abstração) que funcione bem.
No entanto, parece o destino de todas as abstrações - mesmo as melhores - que eventualmente haverá mudanças imprevisíveis (e sem dúvida imprevisíveis) que exigem a quebra da abstração. Para resolver isso, algumas abstrações têm um escape, onde você pode obter acesso a um nível mais profundo, se realmente precisar.
Tudo isso parece muito negativo. Mas acho que a verdade é que estamos cercados por abstrações que funcionam tão bem que não as notamos ou percebemos o que estão escondendo. Observamos apenas as más abstrações, por isso temos uma visão icônica delas.
fonte
As abstrações são principalmente para o benefício de seus consumidores (por exemplo, programadores de aplicativos). Os programadores do sistema (designer) têm mais trabalho a fazer para torná-los bonitos e úteis, e é por isso que o bom design geralmente não é feito pelos iniciantes.
Talvez você não goste de abstrações porque elas sempre adicionam complexidade? Talvez os sistemas nos quais você trabalhou tenham abstração (uso excessivo de abstrações)? Eles não são uma panacéia.
O trabalho extra e a complexidade de uma abstração útil devem valer a pena, mas é difícil saber com certeza. Se você pensa em uma abstração como um ponto de articulação, o design do software pode ser flexível de ambos os lados: as implementações da abstração podem ser modificadas sem quebrar o código do cliente e / ou novos clientes podem reutilizar facilmente a abstração para criar coisas novas.
Você quase pode medir o retorno do investimento das abstrações, mostrando que elas foram "flexionadas" ao longo do tempo em uma ou em ambas as direções: mudanças relativamente simples na implementação e novos clientes adicionais.
Por exemplo: Usando a abstração da classe Socket em Java, tenho certeza de que meu código de aplicativo do Java 1.2 ainda funciona bem no Java 7 (embora possam haver algumas alterações no desempenho). Desde o Java 1.2, definitivamente existem muitos novos clientes que também usam essa abstração.
Quanto à infelicidade com abstrações, se eu conversasse com os desenvolvedores que mantiveram o código por trás da classe Socket, então talvez suas vidas não sejam tão pessimistas quanto os clientes que usaram o Socket para escrever aplicativos divertidos. Trabalhar na implementação de uma abstração certamente é mais trabalho do que usá-la. Mas isso não torna as coisas ruins.
Quanto à transparência, em uma estratégia de design de cima para baixo, a transparência total contribui para o mau design. Programadores inteligentes tendem a tirar o máximo proveito das informações que têm à sua disposição, e o sistema fica fortemente acoplado. A menor alteração de detalhe (por exemplo, alterar a ordem dos bytes em uma estrutura de dados) em um módulo pode quebrar algum código em outro lugar, porque um programador inteligente usa essas informações para fazer algo útil.David Parnas apontou esse problema em artigos tão antigos quanto 1971, onde ele propôs ocultar informações em projetos.
Sua referência ao ArchLinux faz sentido para mim se você considerar o "interior" do sistema operacional como a implementação complexa da abstração que é o sistema operacional para os aplicativos executados nele. Mantenha-o simples nas entranhas da abstração.
fonte
Eu responderei sua pergunta com uma pergunta; quando você dirigiu para o trabalho hoje de manhã (presumo que o fez de fato), você se importou exatamente como o motor abriu as válvulas para permitir a entrada de misturas de combustível e ar e as acendeu? Não. Você não se importa com o funcionamento do motor do seu carro quando está dirigindo pela estrada. Você se importa que ele faz o trabalho.
Suponha que um dia seu carro não funcione. Não começa, joga uma vara, quebra um cinto, inexplicavelmente entra nessa barreira de concreto sem culpa sua enquanto você estava ocupado, enviando mensagens de texto. Agora, você precisa de um carro novo (pelo menos temporariamente). Você se importa exatamente como esse novo carro funciona? Não. O que mais lhe interessa é que ele funcione, e depois que você pode usar o mesmo conhecimento e habilidades que usou para dirigir seu carro antigo para dirigir o novo. Idealmente, deve parecer que não houve alteração no carro que você está dirigindo. Realisticamente, a maneira como este novo carro funciona deve lhe dar o mínimo de "surpresas" possível.
Esses princípios básicos são o princípio básico por trás do encapsulamento e da abstração. O conhecimento de como um objeto faz o que faz não deve ser um requisito para usá-lo para fazer o que faz. Mesmo na programação de computadores, os detalhes dos caminhos elétricos na CPU executando o programa são abstraídos por pelo menos meia dúzia de camadas de instruções de E / S, drivers, software do SO e tempo de execução. Muitos engenheiros de software bem-sucedidos escrevem um código perfeitamente bom sem se preocupar com a arquitetura exata de hardware ou com a compilação do sistema operacional que o executará. Incluindo eu.
O encapsulamento / ocultação de informações permite a mentalidade "não se importa com o que acontece, apenas se preocupa com isso". Seu objeto deve expor o que é útil para o consumidor, de uma maneira que ele possa consumir facilmente. Agora, de volta ao mundo real, isso não significa que um carro não deva fornecer ao usuário informações sobre o funcionamento interno ou que ele só deve permitir ao usuário as funcionalidades mais básicas, como ignição, volante, e pedais. Todos os carros têm velocímetros e indicadores de combustível, tacômetros, luzes idiotas e outros comentários. Praticamente todos os carros também possuem interruptores para vários subsistemas independentes, como faróis, piscas, rádio, ajuste de assentos, etc. Alguns carros permitem uma entrada bastante esotérica do usuário, como a sensibilidade do diferencial central de escorregamento limitado. Em todos os casos, se você souber o suficiente, você pode abri-lo e mudar as coisas para que funcione de uma maneira um pouco diferente. Mas, na maioria dos casos, talvez, apenas talvez, o usuário não consiga controlar direta e independentemente as bombas de combustível de dentro da cabine? Talvez, apenas talvez, o usuário não consiga ativar as luzes de freio sem pressionar o pedal do freio?
A abstração permite que "isso não é o mesmo que isso, mas, porque ambos são XI, podem usá-los como faria com qualquer X". Se seu objeto herda ou implementa uma abstração, seus consumidores devem esperar que sua implementação produza o mesmo resultado ou semelhante a outras implementações conhecidas da abstração. Um Toyota Camry e um Ford Fusion são "carros". Como tal, eles têm um conjunto comum de funcionalidades esperadas, como um volante. Gire no sentido anti-horário, o carro vai para a esquerda. Gire no sentido horário, o carro vai para a direita. Você pode entrar em qualquer carro nos Estados Unidos e esperar que o carro tenha um volante e pelo menos dois pedais, o da direita sendo o pedal "carro vai" e o do centro o pedal "carro pára" .
Um corolário da abstração é a "teoria do mínimo espanto". Se você pegasse o volante de um carro novo para um test drive, girasse o volante no sentido horário e o carro virasse para a esquerda, você ficaria surpreso em dizer o mínimo. Você acusaria o revendedor de vender um PDV e provavelmente não ouviria nenhuma das razões pelas quais o novo comportamento é "melhor" do que você está acostumado, ou quão bem esse comportamento é "documentado" ou como " transparente "o sistema de controle é. Apesar deste carro novo e de todos os outros que você dirigiu ainda serem "carros", ao dirigir esse carro, você precisa alterar alguns conceitos fundamentais de como um carro deve ser dirigido para dirigir com sucesso o novo carro. Isso normalmente é uma coisa ruim, e isso só acontece quando há uma vantagem intuitiva para o novo paradigma. Talvez a adição de cintos de segurança seja um bom exemplo; Há 50 anos, você entrou e foi embora, mas agora precisa apertar o cinto, a vantagem intuitiva é que você não entra no pára-brisa ou no banco do passageiro se sofrer um acidente. Mesmo assim, os motoristas resistiram; muitos proprietários de automóveis cortam os cintos de segurança do carro até que sejam aprovadas leis exigindo seu uso.
fonte