Esqueleto (programação de computador) - Skeleton (computer programming)

A programação de esqueleto é um estilo de programação de computador baseado em estruturas de programa simples de alto nível e o chamado código fictício . Os esqueletos do programa se parecem com o pseudocódigo , mas permitem análise , compilação e teste do código. O código fictício é inserido em um esqueleto de programa para simular o processamento e evitar mensagens de erro de compilação . Pode envolver declarações de funções vazias ou funções que retornam um resultado correto apenas para um caso de teste simples em que a resposta esperada do código é conhecida.

A programação de esqueleto facilita uma abordagem de design de cima para baixo , onde um sistema parcialmente funcional com estruturas completas de alto nível é projetado e codificado, e esse sistema é então progressivamente expandido para atender aos requisitos do projeto. Os esqueletos do programa também são algumas vezes usados ​​para descrições de algoritmos de alto nível . Um esqueleto de programa também pode ser utilizado como um modelo que reflete a sintaxe e as estruturas comumente usadas em uma ampla classe de problemas.

Os programas esqueleto são utilizados no padrão de design do método de modelo usado na programação orientada a objetos . Na programação orientada a objetos , o código fictício corresponde a um método abstrato , um esboço de método ou um objeto fictício . Na nomenclatura Java remote method invocation (Java RMI), um stub se comunica no lado do cliente com um esqueleto no lado do servidor.

Um esqueleto de classe é um esboço de uma classe usada em engenharia de software . Ele contém uma descrição das funções da classe e descreve os propósitos das variáveis e métodos , mas não os implementa. A classe é posteriormente implementada a partir do esqueleto. O esqueleto também pode ser conhecido como uma interface ou uma classe abstrata , com linguagens que seguem um paradigma polimórfico.

Fundo

Código normalmente encontrado em Python, seguindo uma estrutura baseada em esqueleto

O software usado em computadores hoje em dia costuma ser complicado por uma série de razões. Isso pode significar que não apenas um único programador pode desenvolvê-lo, ou que outros módulos ou partes devem ser importados separadamente. Os programas também podem ser muito complexos por si próprios, alguns com vários métodos acessando uma única variável ao mesmo tempo ou até mesmo gerando pixels para telas. O código de esqueleto é usado para ajudar os programadores a desenvolver seu código com o mínimo de erros durante o tempo de compilação .

O código-esqueleto é mais comumente encontrado na programação paralela , mas também é aplicado em outras situações, como documentação em linguagens de programação . Isso ajuda a simplificar a funcionalidade central de um método potencialmente confuso. Também pode ser usado para permitir que uma pequena função dentro de um programa maior opere temporariamente sem funcionalidade total. Esse método de programação é mais fácil do que escrever uma função completa, pois essas funções esqueleto não precisam incluir as funcionalidades principais e podem ser codificadas para uso durante o desenvolvimento. Eles geralmente envolvem código sintaticamente correto para apresentar o método, bem como comentários para indicar a operação do programa. Nem sempre é necessário chamar um fragmento de código de esqueleto de texto.


Relação com Pseudocódigo

Um exemplo genérico de pseudocódigo

O pseudocódigo é mais comumente encontrado ao desenvolver a estrutura de um novo software . É um retrato simples em inglês de uma função particular dentro de um sistema maior, ou pode até mesmo ser a representação de um programa inteiro. O pseudocódigo é semelhante à programação de esqueleto, porém se desvia no fato de que o pseudocódigo é principalmente um método informal de programação. O código fictício também é muito semelhante a este, onde o código é usado simplesmente como um espaço reservado ou para indicar a existência pretendida de um método em uma classe ou interface.

Os programadores de computador são extremamente dependentes do pseudocódigo, tanto que ele tem um impacto mensurável em sua psique . Um programador típico está tão condicionado à ideia de escrever código simplificado de alguma maneira, seja escrevendo pseudocódigo ou código esqueleto, ou mesmo apenas desenhando um diagrama, que isso tem um impacto mensurável em quão bem eles podem escrever sua implementação final. Isso foi encontrado em uma série de aplicativos, com diferentes programadores trabalhando em diferentes linguagens e variados paradigmas de programação .

Esse método de design de programa também é mais frequentemente feito em papel e caneta, afastando ainda mais o texto do que realmente deve ser implementado. A programação de esqueleto imita isso, mas difere na maneira como é comumente escrita em um ambiente de desenvolvimento integrado ou editores de texto . Isso auxilia no desenvolvimento do programa após o estágio inicial de design . Os programas esqueleto também permitem a operação de funções simplistas, se executadas.

Implementação

A programação de esqueleto pode ser implementada em uma variedade de aplicativos de programação diferentes.

Documentação de linguagem de programação

Todas, senão a maioria das linguagens de programação, possuem um esqueleto de código usado para auxiliar na definição de todas as funções e métodos integrados . Isso fornece um meio simples para os programadores mais novos entenderem a sintaxe e a implementação pretendida dos métodos escritos.

Java , uma linguagem orientada a objetos , concentra-se fortemente em uma página de documentação estruturada com métodos completamente separados para cada parte de objeto dos pacotes Java. Linguagens orientadas a objetos focam em uma estrutura baseada em hierarquia para suas implementações, ao invés de uma abordagem simples de cima para baixo encontrada em outras linguagens. 'Objetos' armazenam dados e variáveis ​​neles, permitindo que um programa tipicamente mais eficiente seja escrito. Esses objetos possuem funções individuais que podem acessar variáveis ​​internas, conhecidas como métodos.

Cada método é definido no mesmo formato, com o nome do método, bem como a sintaxe a ser usada em um ambiente de desenvolvimento integrado, claramente visível no topo de um bloco. Com o foco do Java no escopo , tipos de dados e herança , essa sintaxe é extremamente útil para novos, senão para todos os programadores. Isso é seguido por uma explicação detalhada da operação do método, com os erros abaixo.

Python tem uma abordagem semelhante para documentar seus métodos embutidos, no entanto, imita a falta de fixação da linguagem no escopo e nos tipos de dados. Esta documentação contém a sintaxe de cada método, junto com uma breve descrição e um exemplo do uso típico do método ou função. O esqueleto do código fornecido no exemplo fornece aos programadores uma boa compreensão da função em uma rápida olhada.

Definição de classe

As aulas escritas por desenvolvedores terceirizados, principalmente como parte de bibliotecas, também exibem sua programação na forma de um esqueleto de código. Isso ajuda a informar qualquer um que seja novo na biblioteca sobre como as funções e métodos operam. P5.Js usa este formato em sua página de documentação para explicar o uso pretendido de certas funções incluídas. Isso é diferente para a documentação da linguagem de programação, no entanto, usando o código de esqueleto para exibir parâmetros em vez de todos os usos possíveis do método.

As interfaces de linguagem natural (NLIs) são mais comumente encontradas em situações em que os programadores tentam pegar uma entrada , normalmente denominada coloquialmente (sem o uso de jargão específico da linguagem de programação ) e usar isso para criar um programa ou método. Uma implementação disso usa um pequeno conjunto de código de esqueleto para implicar a função em execução em segundo plano.

Outras formas de NLIs usam diferentes formas de entrada, variando de outros usuários que falam idiomas diferentes, a entrada baseada em gestos para produzir um resultado muito semelhante. Com as linguagens de programação sendo desenvolvidas e escritas principalmente em inglês, as pessoas que falam outras línguas têm dificuldade para desenvolver um novo software. Os NLIs têm sido usados ​​em alguns estudos para ajudar as pessoas nessas situações. O estudo mostrou classes escritas em Java por meio do uso de NLIs. Isso removeu a necessidade de aprender regras sintáticas; no entanto, significava que a classe foi escrita usando um conjunto básico de código de esqueleto.

Definições baseadas em polimorfismo

Polimorfismo é uma ideologia que segue o paradigma de programação orientada a objetos , onde os métodos podem ser sobrescritos ou sobrecarregados (métodos com o mesmo nome em uma classe filha que terá prioridade sobre um método escrito em uma classe pai). A definição de métodos é baseada em uma estrutura de esqueleto definida pela sintaxe da linguagem.

Muito semelhante à implementação de classe, o código de esqueleto pode ser usado para definir os métodos que fazem parte de uma interface . Uma interface é essencialmente um blueprint de uma classe, que permite que linguagens estritas orientadas a objetos (como Java ) usem classes de diferentes pacotes sem a necessidade de entender completamente as funções internas. As interfaces simplesmente definem os métodos que devem estar presentes na classe, permitindo que qualquer outra pessoa use os métodos ou implemente a classe para suas necessidades pessoais.

public skeletonExample();

Uma classe abstrata é quase igual a uma implementação de classe, entretanto, dependendo da linguagem, pelo menos um método é definido como abstrato. Isso implica que todos os filhos desta classe (quaisquer classes que estendem ou implementam) precisam ter um método definido para isso. As classes abstratas têm um estilo de definição muito semelhante às interfaces, no entanto, uma palavra-chave 'abstrato' é normalmente usada para identificar o fato de que ela precisa ser implementada em classes filhas.

public abstract skeletonExample();

Esses exemplos usam a sintaxe Java.

Programação paralela

A programação paralela é a operação de várias funções simultaneamente, mais comumente usadas para aumentar a eficiência. Esses são normalmente os tipos de programas mais difíceis de desenvolver, devido à sua complexidade e interconexão com o hardware em questão. Muitos desenvolvedores tentaram escrever programas com essa funcionalidade central, mas os resultados encontrados foram variados.

Estruturas de esqueleto de algoritmo são usadas em programação paralela para descrever abstratamente os métodos em questão para desenvolvimento posterior. As estruturas não se limitam a um único tipo e cada um desses tipos tem diferentes propósitos para aumentar a eficiência do programa do desenvolvedor. Estes podem ser classificados em três tipos principais: dados paralelas , tarefa-paralelas e resolução.

Data-Parallel

Esses algoritmos de esqueleto são usados ​​para desenvolver programas que funcionam em grandes softwares baseados em dados, geralmente identificando as conexões entre os dados para uso posterior. Algoritmos paralelos de dados incluem 'mapas', 'bifurcações' e 'reduz' ou 'varreduras'.

  • 'Mapas' são os algoritmos paralelos de dados mais comumente usados ​​e geralmente envolvem uma única operação concluída em um grande conjunto de dados. Para aumentar a eficiência, vários conjuntos de dados têm essa operação aplicada a eles simultaneamente, antes que os dados sejam estruturados juntos novamente no final.
  • 'Forks' são semelhantes a 'mapas', mas usam uma operação diferente para certos tipos de dados. Isso é conhecido como paralelismo de dados múltiplos .
  • 'Reduz' ou 'varredura' são usados ​​para aplicar prefixos a um conjunto de dados, antes de aplicar uma operação sobre os dados. Eles são diferentes dos 'mapas', pois têm um conjunto de resultados parciais durante o tempo de execução do próprio método.

Tarefa-Paralela

Essas operações, como o nome sugere, funcionam em tarefas. Cada tipo de algoritmo é diferente devido a uma mudança no comportamento entre as tarefas. Algoritmos paralelos de tarefas incluem 'sequenciais', 'farms', 'pipes', 'if', 'for' e 'while'.

  • 'Sequencial' fecha e termina um conjunto aninhado de algoritmos de esqueleto. Os métodos e programas que fazem parte dos esqueletos são incluídos como aspectos de encerramento do programa, antes do fechamento.
  • 'Fazendas' são conhecidas como um grupo de tarefas, um trabalhador, ou um mestre ou escravo de outra função. Ele completa as tarefas fornecidas replicando as tarefas em vários threads e executando-as simultaneamente. Isso divide a carga de um thread específico, criando efetivamente um relacionamento mestre / escravo entre os threads.
  • 'Pipes' são as formas mais tradicionais de algoritmos, onde cada método ou função é executado em uma sequência. Isso segue a ordem em que o programador escreveu seu código. Isso é feito em paralelo computando tarefas variadas em um conjunto de dados, normalmente de entrada, simultaneamente para melhorar o desempenho e a velocidade. Cada computação simultânea é conhecida como um estágio. O algoritmo do tubo pode ser aninhado, onde um está dentro do outro, cada um dividindo responsabilidades para aumentar a velocidade e também o número de estágios.
  • 'If' dá ao programa uma divisão condicional de tarefas, onde um conjunto de código de esqueleto é dividido em duas seções principais. Uma declaração condicional é fornecida ao programa, fornecendo, portanto, um algoritmo especificado a ser seguido.
  • 'For' opera uma tarefa várias vezes, ambas especificadas pelo programador, permitindo um conjunto de código mais eficiente. O número de vezes que o código é executado é um valor predefinido, indicando que em tempo de execução , isso não pode ser alterado. Ele deve completar a tarefa o número de vezes fornecido.
  • 'Enquanto' é um algoritmo muito semelhante à operação de um algoritmo 'para', em que uma tarefa é concluída várias vezes. No entanto, em algoritmos 'while', o programa calcula a tarefa várias vezes antes que uma instrução condicional seja satisfeita. Isso significa que o algoritmo 'while' pode executar sua tarefa um número diferente de vezes para cada vez que é executado.

Esqueletos de Resolução

Esses esqueletos são muito diferentes dos esqueletos típicos encontrados acima. Os algoritmos de 'resolução' usam uma combinação de métodos para resolver um problema específico. O problema fornecido pelo algoritmo pode ser uma “família de problemas”. Existem dois tipos principais desses esqueletos, 'dividir e conquistar' ou 'marcar e amarrar'.

  • 'Divide and conquer' usa um esqueleto de mapa como base, combinando-o com um esqueleto de tempo para resolver o problema. Em algoritmos de mapa, funções em dados são aplicadas simultaneamente. Em 'dividir para conquistar' o conjunto de dados fornecido tem uma função aplicada a ele usando o esqueleto do mapa, no entanto, isso pode ser aplicado recursivamente usando o algoritmo 'while'. O 'enquanto' só é quebrado quando todo o problema é resolvido.
  • 'Branch and bound' é um algoritmo que também usa algoritmos de mapa, no entanto, em vez de aplicar o algoritmo 'while' para executar as tarefas simultaneamente, esse algoritmo divide as tarefas em ramificações. Cada branch tem um propósito específico, ou 'limite', onde a instrução condicional fará com que ele pare.

Referências