Como as linguagens de programação inicialmente usavam apenas linhas de código executadas seqüencialmente e evoluíram para incluir funções que eram um dos primeiros níveis de abstração, e então classes e objetos foram criados para abstraí-lo ainda mais; qual é o próximo nível de abstração?
O que é ainda mais abstrato do que aulas ou já existe?
programming-languages
object-oriented
language-agnostic
abstraction
Jordan Medlock
fonte
fonte
Respostas:
Eu acho que você tem alguns conceitos errados sobre a história da computação.
A primeira abstração (em 1936) foi, de fato, o Lambda Calculus de Alonzo Church, que é a base para o conceito de funções de alta ordem e todas as linguagens funcionais que se seguiram. Ele inspirou diretamente o Lisp (a segunda linguagem de programação de alto nível mais antiga, criada em 1959), que por sua vez inspirou tudo, de ML a Haskell e Clojure.
A segunda abstração foi a programação procedural. Ele surgiu das arquiteturas de computadores de von Neumann, onde programas sequenciais eram escritos, uma instrução de cada vez. FORTRAN (a mais antiga linguagem de programação de alto nível, 1958) foi a primeira linguagem de alto nível a sair do paradigma processual.
A terceira abstração provavelmente foi na verdade programação declarativa, primeiro exemplificada por Absys (1967) e, posteriormente, Prolog (1972). É a base da programação lógica, onde as expressões são avaliadas combinando uma série de declarações ou regras, em vez de executar uma série de instruções.
A quarta abstração era então a programação orientada a objetos, que apareceu pela primeira vez nos programas Lisp nos anos 60, mas depois foi exemplificada por Smalltalk em 1972. (Embora pareça haver algum debate sobre se o estilo de transmissão de mensagens do Smalltalk é a abstração One True orientada a objeto. Não vou tocar nisso.)
Todas as outras abstrações, especialmente na arquitetura tradicional de computadores von Neumann, são variações desses quatro temas. Não estou convencido de que exista outra abstração além dessas quatro que não seja apenas uma variação ou uma combinação delas.
Mas uma abstração é, em essência, apenas uma maneira de modelar e descrever um algoritmo. Você pode descrever algoritmos como uma série de etapas distintas, como um conjunto de regras que devem ser obedecidas, como um conjunto de funções matemáticas ou como objetos em interação. É muito difícil conceber outra maneira de descrever ou modelar algoritmos e, mesmo que exista, não estou convencido de sua utilidade.
Existe, no entanto, o modelo de computação quântica. Na computação quântica, novas abstrações são necessárias para modelar algoritmos quânticos. Sendo um neófito nesta área, não posso comentar sobre isso.
fonte
Para muitos, a forma mais pura de abstração de código na era atual da programação binária é a "função de ordem superior". Basicamente, a própria função é tratada como dados e as funções das funções são definidas, da mesma forma que você as veria em equações matemáticas, com operadores definindo o resultado de seus operandos e uma ordem predeterminada de operações que define o "aninhamento" dessas operações. A matemática possui muito poucos "comandos imperativos" em sua estrutura; os dois exemplos em que consigo pensar são "deixe x ter algum valor ou seja qualquer valor conforme alguma restrição" e "funções por partes" nas quais a entrada determina a expressão necessária para produzir a saída. Essas construções são facilmente representáveis como suas próprias funções; a "função" x sempre retorna 1 e "sobrecarga" de funções são definidas em termos do que é passado a elas (que, diferentemente das sobrecargas orientadas a objetos, podem ser definidas com base na entrada de valores), permitindo a avaliação "por partes" de um grupo nomeado de funções, mesmo em termos de si mesmos. Como tal, o programa elimina a noção de imperativos no nível baixo e, em vez disso, se concentra em "avaliar a si próprio", dados de entrada.
Essas funções de ordem superior formam a espinha dorsal das "linguagens funcionais"; o que um programa faz é definido em termos de "funções puras" (uma ou mais entradas, uma ou mais saídas, sem efeitos colaterais ou "estado oculto"), que são aninhadas umas às outras e avaliadas conforme necessário. Nesses casos, a maioria das "lógicas imperativas" é abstraída; o tempo de execução lida com a chamada real de funções e quaisquer condições nas quais uma ou outra sobrecarga de uma função possa precisar ser chamada. Nesse programa, o código não é pensado como "fazendo" alguma coisa, é pensado como "sendo" algo, e o que exatamente é determinado é determinado à medida que o programa é executado com a entrada inicial.
Agora, as funções de ordem superior também são um grampo de muitas linguagens imperativas; As instruções lambda do .NET permitem basicamente entradas funcionais "anônimas" em outra "função" (implementada imperativamente, mas teoricamente não precisa ser), permitindo assim um encadeamento altamente personalizável de "funções" de uso geral o resultado desejado.
Outra abstração comumente vista na última rodada de linguagens de programação é a digitação dinâmica de variáveis com base no conceito de "digitação de pato"; se parece um pato, nada como um pato, voa como um pato e grasna como um pato, você pode chamá-lo de pato. Não importa se é realmente um pato-real ou um canvasback. Pode importar se é realmente um ganso ou um cisne, mas, novamente, pode não interessar se tudo o que importa é que nada e voe, e meio que parece um pato. Isso é considerado o máximo em herança de objetos; você não se importa com o que é , exceto para dar um nome; o que é mais importante é o que faz. Em tais idiomas, existem basicamente apenas dois tipos; o "átomo", um único elemento de informação (um "valor"; um número, caractere, função, qualquer que seja) e a "tupla", composta por um átomo e um "ponteiro" para tudo o mais na tupla. Exatamente como esses tipos são implementados em binário pelo tempo de execução é irrelevante; Com essas opções, você pode obter a funcionalidade de praticamente todos os tipos possíveis, de tipos simples de valor a seqüências de caracteres e coleções (que, como os valores podem ser de "tipos" diferentes, permite "tipos complexos", também conhecidos como "objetos").
fonte
Pode-se considerar linguagens específicas do domínio, como SQL, como uma ordem mais alta de abstração. O SQL é uma linguagem muito direcionada que abstrai operações como armazenamento e fornece funções de nível superior com base na teoria de conjuntos. Considere também quantas linguagens mainstream atualmente não têm como alvo uma arquitetura específica, mas uma Máquina Virtual (como a JVM ou o .NET CLR). Por exemplo, o C # é compilado para IL, o qual é interpretado (ou mais frequentemente JIT'd - Just In Time Compiled-- para uma implementação nativa) pelo mecanismo de tempo de execução nativo.
Houve muita discussão sobre o conceito de DSLs sendo usado para criar linguagens de nível muito alto que podem ser usadas sem muita experiência técnica para criar um programa de trabalho. Pense se alguém foi capaz de descrever suas entidades e interações em inglês simples e o ambiente operacional lidou com tudo, desde a apresentação de uma interface simples até o armazenamento de dados em algum tipo de banco de dados. Depois que essas operações se tornam abstratas, você pode imaginar como a programação sem esforço pode se tornar.
Atualmente existem alguns como o JetBrains MPS (que é um kit de ferramentas para descrever DSLs ou um gerador de linguagem). A Microsoft teve uma breve incursão (e muito promissora, devo acrescentar) neste espaço com sua linguagem M (a linguagem M era tão completa que a linguagem foi definida em M).
Os críticos do conceito apontam para tentativas anteriores fracassadas de remover programadores da tarefa de desenvolver programas; a diferença com as bancadas de trabalho DSL (como Fowler chama) é que os desenvolvedores ainda se envolveriam na codificação de conceitos que os Especialistas em Domínio poderiam usar para expressar as necessidades de seu domínio. Assim como os fornecedores de sistemas operacionais e idiomas criam ferramentas que usamos para programação, usamos DSLs para fornecer ferramentas para usuários corporativos. Poderíamos imaginar DSLs que descrevem os dados e a lógica, enquanto os desenvolvedores criam intérpretes que armazenam e recuperam dados e aplicam a lógica expressa na DSL.
fonte
Eu argumentaria que as meta-estruturas, módulos, estruturas, plataformas e serviços são todos grupos de recursos de nível superior ao das classes. Minha hierarquia de abstrações do sistema de programação:
Metaestruturas como metaclasses , funções de ordem superior e genéricos claramente adicionam abstração a classes básicas, funções, tipos de dados e instâncias de dados. Traços, aspectos e decoradores são mecanismos mais novos para combinar recursos de código e, da mesma forma, "acelerar" outras classes e funções.
Até as linguagens pré-objeto tinham módulos e pacotes, portanto, colocá-los acima das classes pode ser discutível. Mas eles contêm essas classes e meta-estruturas, então eu as classifico mais alto.
As estruturas são a resposta mais abrangente - elas orquestram várias classes, meta-estruturas, módulos, funções e outras para fornecer abstrações sofisticadas de alto nível. E, no entanto, estruturas ainda operam quase inteiramente no campo da programação.
As pilhas ou plataformas de solução geralmente combinam várias estruturas, subsistemas ou componentes em um ambiente para solucionar vários problemas.
Por fim, existem serviços - geralmente implantados como serviços da Web ou de rede. São arquiteturas, estruturas, pilhas de soluções ou recursos de aplicativos entregues como pacotes completos. Seus internos geralmente são opacos, expondo principalmente as interfaces de administrador, programação e usuário. PaaS e SaaS são exemplos comuns.
Agora, essa progressão pode não ser totalmente satisfatória, por alguns motivos. Primeiro, ele cria uma progressão ou hierarquia linear pura de coisas que não são perfeitamente lineares ou hierárquicas. Abrange algumas abstrações, como "pilhas" e serviços que não estão totalmente sob controle do desenvolvedor. E isso não representa nenhuma nova poeira mágica de duende. (Spoiler: Não há pó mágico de duende. )
Eu acho que é um erro procurar apenas novos níveis de abstração . Todos os que listei acima existem há anos , mesmo que nem todos tenham sido tão importantes ou populares como agora. E, ao longo desses anos, as abstrações possíveis em todos os níveis de codificação melhoraram. Agora temos coleções genéricas de uso geral, não apenas matrizes. Repetimos as coleções, não apenas os intervalos de índice. Temos compreensões de lista e operações de filtro e mapa de lista. Muitas funções da linguagem podem ter um número variável de argumentos e / ou argumentos padrão. E assim por diante. Estamos aumentando a abstração em todos os níveis, portanto, adicionar mais níveis não é um requisito para aumentar o nível geral de abstração.
fonte
A próxima abstração após as aulas são meta classes . É simples assim ;)
fonte
Type
que dá capacidades reflexivas, mas não mutação (você não pode adicionar um novo método paraMyType
dizendotypeof(MyType).Methods += new Method ( "Foo", (int x)=>x*x )
como você pode em CLOS)Estou surpreso que ninguém tenha mencionado a teoria das categorias.
A unidade mais fundamental da programação é a função que é baseada em tipos. As funções são geralmente indicadas como f: A -> B, onde A e B são tipos. Se você colocar essas coisas, que eu estou chamando de tipos e funções, juntas, da maneira correta, você obtém algo chamado categoria. Você não precisa parar neste momento.
Pegue essas coisas, categorias e pergunte a si mesmo qual seria a maneira correta de relacioná-las. Se você fizer isso corretamente, obtém algo chamado functor, que varia entre duas categorias e geralmente é indicado como F: C -> B. Mais uma vez, você não precisa parar.
Você pode pegar todos os functores e montá-los da maneira certa e, se fizer as coisas corretamente, começa a pensar em como relacionar dois functores entre si. Nesse ponto, você obtém algo chamado transformação natural, mu: F -> G, onde F e G são functores.
Meu conhecimento neste momento fica confuso, mas você pode continuar fazendo isso e continuar subindo a escada da abstração. Objetos e classes nem sequer chegam perto de descrever o quão alto você pode subir a escada de abstração. Existem muitas linguagens que podem expressar os conceitos acima computacionalmente e a mais proeminente dessas linguagens é Haskell. Então, se você realmente quer saber o que é realmente abstração, aprenda Haskell, Agda, HOL ou ML.
fonte
Eu acho que o modelo do ator está faltando na lista de candidatos.
Aqui está o que quero dizer com Atores:
Esse modelo está além das máquinas determinísticas de Turing e, na verdade, está mais próximo do nosso hardware do mundo real quando se olha para programas concorrentes. A menos que você use etapas de sincronização extras (caras), hoje em dia, quando seu código recebe dados, esse valor já pode ter sido alterado do outro lado da mesma matriz, talvez até dentro do mesmo núcleo.
Breve discussão / introdução: http://youtube.com/watch?v=7erJ1DV_Tlo
fonte
Se eu entendi direito, suas "abstrações ascendentes" podem ser consideradas encapsulações cada vez maiores da lógica, principalmente relacionadas à reutilização de código.
A partir de instruções específicas executadas uma após a outra, passamos para funções / sub-rotinas , que encapsulam, ou abstraem, um agrupamento lógico de instruções em um único elemento. Em seguida, temos objetos ou módulos que encapsulam sub-rotinas relacionadas a uma determinada entidade ou categoria lógica, para que eu possa agrupar todas as operações de cadeia de caracteres da
String
classe ou todas as operações matemáticas comuns doMath
módulo (ou classe estática, em idiomas como C #) .Então, se essa é a nossa progressão, o que vem a seguir? Bem, eu não acho que você tenha um próximo passo claro. Como outros responderam, sua progressão se aplica apenas a estilos de programação imperativos / procedimentais, e outros paradigmas não compartilham seus conceitos de abstração. Mas se há algo que pode estender logicamente sua metáfora, são os serviços .
Um serviço é semelhante a uma classe no sentido de que é uma entidade que expõe a funcionalidade, mas implica uma separação de preocupações muito mais rigorosa do que o ir e vir com objetos que você instancia. Eles expõem um conjunto limitado de operações, ocultam a lógica interna e nem estão necessariamente em execução na mesma máquina.
Novamente, há uma boa distinção. Na maioria dos casos, você usará um objeto que atua como um proxy para um serviço , e os dois serão muito semelhantes, mas como uma arquitetura, os dois são distintos.
fonte
Novas formas de abstração ocultam o trabalho de baixo nível de você. Os procedimentos e funções nomeados ocultam seus endereços de programa. Os objetos ocultam o gerenciamento dinâmico de memória e algumas instruções "if" dependentes do tipo.
Eu sugeriria que o próximo nível de abstrações práticas que ocultem a labuta de baixo nível são as da programação reativa funcional . Veja os "sinais" em algo como http://elm-lang.org/ que oculta os retornos de chamada e atualiza as dependências que você precisaria gerenciar explicitamente em javascript. O FRP pode ocultar muita complexidade de comunicação entre processos e entre máquinas, necessária em aplicativos de Internet em larga escala e em paralelismo de alto desempenho.
Tenho certeza de que é sobre isso que todos nós vamos ficar animados nos próximos 5 anos.
fonte
A teoria dos conjuntos - como parcialmente implementada em bancos de dados relacionais, mas também em linguagens estatísticas como SAS e R, fornece um nível de abstração diferente, mas sem dúvida mais alto que o OO.
fonte