0% acharam este documento útil (0 voto)
120 visualizações14 páginas

Paradigmas de Programação: Estrutural e Orientado a Objetos

O documento discute diferentes paradigmas de programação, incluindo imperativo, declarativo, estrutural e orientado a objetos. Ele explica as diferenças entre esses paradigmas e como eles influenciaram o desenvolvimento de linguagens de programação ao longo do tempo.
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
120 visualizações14 páginas

Paradigmas de Programação: Estrutural e Orientado a Objetos

O documento discute diferentes paradigmas de programação, incluindo imperativo, declarativo, estrutural e orientado a objetos. Ele explica as diferenças entre esses paradigmas e como eles influenciaram o desenvolvimento de linguagens de programação ao longo do tempo.
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 14

Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

Paradigmas de Programação

Uma linguagem de programação é a forma na qual o computador e o programador se


comunicam, fazendo uma analogia simples é a mesma forma como os seres humanos
comunicam-se, através de linguagens, sendo essas de gestos, escritas, faladas, ou seja, uma
codificação na qual duas partes conseguem interpretar. Para cada linguagem ou forma de
comunicação existe uma metodologia, essas metodologias para as linguagens de programação
são os chamados paradigmas.

O Paradigma de programação oferece a visão que o programador possui da estrutura de


execução do programa, por exemplo uma programação estruturada os programadores irão
produzir a abstração do código como uma sequência de funções executadas de modo empilhado.

Diferentes linguagens irão possuir diferentes paradigmas de programação, esses paradigmas


definirão o que a linguagem permite ou não realizar. Por exemplo a linguagem C em seu modo
puro, é uma linguagem estruturada, e por isso não permite a criação de objetos que é uma
característica de linguagens com paradigmas de Orientação a Objetos.

Paradigma Declarativo X Paradigma Imperativo


Existem 2 paradigmas dos quais todos os outros são derivados, o paradigma declarativo e o
imperativo, algumas vezes também citados como estilos.

O paradigma imperativo é o mais antigo em programação, está diretamente ligado a


linguagem Assembly que é conhecida como linguagem de máquina.

Paradigma imperativo: descreve-se todas as operações a serem realizadas para solucionar o


problema. O resultado é uma consequência da realização destas operações. O Foco do
paradigma imperativo é em como o programa deve conseguir o resultado.

Paradigma declarativo: é feita a descrição do problema. Cada sentença tem significado por si
mesma e adiciona algumas informações diretamente associadas ao resultado. Elas podem ser
apresentadas em qualquer ordem. O foco do paradigma declarativo é, o que o programa deve
realizar.

p. 1 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

Figure 1: Imperativo Vs Declarativo - https://pt.slideshare.net/skosta/paradigmas-de-programacao

Figure 2:Derivação dos Paradigmas de Programação -https://www.differencebetween.com/difference-between-


declarative-and-vs-imperative-programming/

Paradigma Estrutural

O paradigma imperativo foca em definir “como” o programa deve ser computado, e


derivado dele foram criados os paradigmas procedimental e orientado a objetos. Contudo,
parte da forma em como explicitamos o fluxo de controle do programa nestes dois
paradigmas foi influenciada pelo paradigma estrutural.

Quando o paradigma imperativo era o único conhecido e se programava apenas em


linguagens puramente imperativas, como Assembly, FORTRAN e COBOL, havia um recurso

p. 2 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

implementado pelo comando goto, que permitia saltos transferir a execução para qualquer
linha específica dos programas. Fazendo uso deste recurso, era possível quebrar a linearidade
do código, ou seja, a execução das linhas de código na ordem que foram escritas, o que
tornava o software incrivelmente difícil de manter e compreender, porém criava recursos
importantes como executar novamente uma ação sem a necessidade de escrever de novo a
mesma linha ou pulando uma ação desnecessária, economizando linhas de código e tempo
de processamento. Este estilo de programação era conhecido como código espaguete, uma
vez que toda estrutura estava toda entrelaçada.

Em 1968 e 1987, Edsger W. Dijkstra e Niklaus Wirth respectivamente, publicaram artigos nos
quais defendiam a abolição do goto nas linguagens de programação de alto nível, alegando
que o comando induzia a vários erros de programação e promovia práticas ruins, além de
tornar extremamente difícil a leitura de programas.

Este movimento deu origem à programação estruturada, que se fundamenta em três


estruturas de controle de fluxo de código:

• Estrutura de sequência: na qual um comando é executado após o outro, de


forma linear, e, portanto, sem o uso de goto;
• Estrutura de decisão: na qual trechos do programa podem ser executados
dependendo do resultado de um teste lógico;
• Estrutura de iteração: na qual determinado trecho de código é repetido por
um número finito de vezes, enquanto um teste lógico for verdadeiro.

Exemplo de programação imperativa não-estrutural:

Figure 3: Exemplo de Programação Imperativa não-estrutural usando Basic

Programação Procedural/Procedimental (Paradigma Estruturado)

Também conhecida como programação estruturada, nesse tipo de programação, os programas


são criados baseados em quais funções, procedimentos e variáveis são necessárias para resolver
um problema.

p. 3 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

O nome de programação estruturada é dado pela forma que os programas são escritos,
possuindo uma estrutura básica formada por três etapas, que são: sequência, decisão e
interação (Paradigma Estrutural). Em particular eu prefiro chamar esse tipo programação de
programação orientada ao procedimento, que aliás era a matéria na qual aprendi esse
paradigma, pelo simples fato de que realmente tudo é orientado ao procedimento a ser
executado para conseguir o resultado esperado.

Na sequência, temos a ordem em que as coisas devem acontecer, como por exemplo, antes de
atribuir um valor a uma variável é necessário que ela esteja declarada. Na decisão podemos usar
desvios condicionais como IF ou SWITCH para tomar decisões baseadas em valores de variáveis,
e na Interação há a possibilidade de o usuário interagir com o programa enviando informações
e tomando decisões.

A programação estruturada pode também ser modularizada usando subprogramas ou sub-


rotinas, mais conhecidos como procedimentos e funções. A modularização ou divisão do
programa permite que vários programadores trabalhem em conjunto, cada um fazendo uma
parte, uma sub-rotina, que depois será incluída ao programa principal, além de permitir a
reutilização de código, assim não é necessário escrever os códigos do procedimentos e/ou
funções todas as vezes que for necessário, bastando apenas chama-los para serem executados
novamente, obedecendo a ordem sequencial lógica do programa. Todo programa possui sub-
rotinas que realizam tarefas, sendo o correto fazer com que cada uma realize apenas tarefas
coerentes com sua responsabilidade. Excesso de tarefas dentro e uma sub-rotina torna-se difícil
a localização de falhas e manutenção do código, por isso a divisão de sub-rotinas e tarefas deve
ser feita com muita cautela.

Existem muitas linguagens de programação que seguem a forma estruturada. Dentre as mais
conhecidas estão as linguagens C e Pascal. A linguagem C foi criada por Ken Thompson na década
de 60, originalmente desenvolvida para a implementação do sistema Unix. O nome C foi dado
pelo fato de a linguagem ter sido desenvolvida com características semelhantes à outra
linguagem de nome B, uma simplificação da linguagem BCPL.

Vale aqui nos lembrar que as linguagens de programação para CLP (Controlador Lógico
Programável), são por definições da IEC 6113-3, todas linguagens estruturadas e procedimentais,
a última atualização da IEC 6113-3 datada de Fevereiro de 2013, adiciona algumas características
para a Orientação a Objetos, mas veja bem, apenas algumas características, porém não as torna
Orientadas a Objeto. Um dos motivos é a própria característica do CLP quando foi editada pela
primeira vez a norma (em 1993), de trabalhar através de ciclos por varredura (Scan), em um
único sentido (de cima para baixo), o que torna a linguagem sequencial ideal para essa aplicação
de hardware. Os hardwares de CLP atuais, apesar de manterem suas características de varredura,
em virtude do aumento de capacidade computacional, atualmente podem executar rotinas
através de interrupções, múltiplos threads, rotinas principais em paralelo (múltiplos runtimes
em diferentes tempo de ciclo e execução), sendo assim, possuindo capacidade de sobra para
orientação a objetos, dependendo apenas de atualização da normal e das características das
linguagens e editores pelos fabricantes.

Vale lembrar as 3 principais linguagens utilizadas em CLP como Texto Estruturado, Diagrama de
Blocos, Ladder e Gráfico Sequencial (não necessariamente nessa ordem).

p. 4 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

Programação Orientada a Objetos

O paradigma orientado a objetos tem suas raízes nas linguagens de programação Simula e
Smalltalk nas décadas de 1960 e 1970, respectivamente. Contudo, este paradigma só veio a
ser aceito realmente para uso comercial por volta dos anos 1990, quando surgiu a linguagem
de programação Java, que ficou popularizada pelo fato de se poder programar para todas as
plataformas da mesma maneira, o que até então não era possível.

A orientação a objetos também se apresentou com a esperança de suprir algumas das


preocupações da indústria do software: a necessidade de criar software comercial mais
rapidamente, mais confiável e a um custo baixo

A programação Orientada a Objetos ou OO difere da linguagem estruturada inicialmente e


principalmente pela forma de pensar. Em OO o programador deve conseguir abstrair do
problema coisas que podem ser representadas como objetos, literalmente esse paradigma
busca trazer o mundo real para dentro do computador através da abstração, como por exemplo,
se deseja criar um programa para saber se um aluno está ou não aprovado em uma disciplina, o
programa deverá criar objetos para representar o aluno e a disciplina. Os objetos são definidos
em classes, onde cada objeto criado é denominado instância.

Uma classe define as características dos objetos, denominadas atributos e suas ações,
denominadas métodos. A classe Aluno, por exemplo, possui atributos
como nome, endereco, idade, serie e turma. Os métodos nos dizem o que pode ser feito com o
objeto, e no caso do objeto aluno, podemos armazenar, alterar, excluir e buscar. A quantidade
de atributos e métodos varia em cada programa e devem ser criados de acordo com a
necessidade especificada durante a fase de abstração do problema. As classes também
descrevem relacionamentos entre objetos (da mesma classe, ou de classes distintas). Ou seja,
o software é representado por um conjunto de estruturas de dados que interagem entre si,
cada uma delas contendo uma coleção de dados específicos e um conjunto de rotinas
(métodos) para manipular esses dados (ações sobre dados).

Uma forma de representar um programa orientado a objetos é o Diagrama de Classes. Nele é


possível especificar classes, atributos, métodos, herança e a associação existente entre as
classes, comumente modelo em UML (Unified Modeling Language),

Figure 4: Diagrama de Classes

p. 5 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

Para uma linguagem de programação fazer parte inteiramente do paradigma orientado a


objetos, deve implementar seus três mecanismos básicos, ou pilares da orientação a objeto,
que são: herança, polimorfismo e encapsulamento.

Classe

Uma classe é uma estrutura que abstrai um conjunto de objetos do mesmo tipo . É nela que
são definidas as características (estrutura) dos objetos daquele tipo, ou seja, que dados
(atributos) são armazenados pelo objeto e que operações (métodos) podem ser efetuadas
com estes dados.

É importante que cada classe tenha apenas uma ou um pequeno número de


responsabilidades. Se uma classe possui excesso de responsabilidades, sua implementação
se tornará muito confusa e difícil de manter e entender. Pois, nesse caso, ao alterar uma
responsabilidade, você correrá o risco de alterar outro comportamento inadvertidamente.
Ela também centralizará muito conhecimento, que seria melhor gerenciado se fosse
espalhado. Quando uma classe fica grande demais, ela quase se torna um programa completo
e pode cair nos problemas da programação procedimental.

• Atributo

Os dados contidos em uma classe são conhecidos como atributos daquela classe e
representam características presentes nos objetos do tipo da classe. Cada atributo
deve ter um escopo de acessibilidade, um nome e ser de um tipo, que será ou um
tipo de dado nativo da linguagem (geralmente tipos: inteiro, real, caractere, string,
booleano), ou outra classe já existente na linguagem ou definida pelo programador.

Por exemplo, para a classe Pessoa, que representa uma abstração de uma pessoa,
seus atributos poderiam ser os seguintes: nome (cadeia), idade (inteiro), peso (real)
e rg (cadeia). Consequentemente cada objeto do tipo Pessoa teria estes atributos,
cada um deles com um valor específico.

Vale ressaltar que um atributo de uma classe também pode ser declarado como
sendo um objeto de outra classe. Por exemplo, na classe Pessoa, o atributo rg
poderia ser da classe Rg e esta, por sua vez, teria os atributos nome, nome do pai,
nome da mãe, data de nascimento, naturalidade, número do RG, etc.

• Método

Métodos definem os comportamentos dos objetos da classe, sendo equivalentes


às funções e/ou procedimentos do paradigma procedimental, mas diretamente
ligados a um objeto ou uma classe. Ou seja, são trechos de código modularizados
que executam uma ação com os atributos acessíveis ao seu contexto.

Assim como no paradigma procedimental, além dos métodos poderem ter suas
próprias variáveis locais, estes também podem acessar as variáveis globais, que no
caso da orientação a objetos são os atributos da classe ou da sua instância em
questão. Estes também podem receber ou não parâmetros, e podem retornar um
valor a quem o chamou (similar a uma função) ou apenas executar alguma ação com
os atributos acessíveis a ele (similar a um procedimento).

Vale ressaltar que quando uma função ou procedimento do paradigma


procedimental acessa uma variável global aquela variável é uma variável do

p. 6 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

programa e é visível a todo o programa, enquanto que quando um método acessa


uma “variável global” (atributo definido na classe), ele acessa apenas os atributos
do objeto em questão ou atributos próprios da classe, chamados estes de atributos
estáticos (i.e., são atributos que não pertencem aos objetos, sendo acessáveis
somente pela classe). Ou seja, quando invocamos algum método de um objeto da
classe Pessoa, esse método só terá acesso aos atributos do seu objeto, não
“enxergando” quaisquer atributos de outros objetos do tipo Pessoa.

Como vimos, métodos são extremamente necessários na manipulação dos atributos


dos objetos e são utilizados para definir o comportamento destes.
Consequentemente são o principal meio de comunicação pelo qual o ambiente
externo interage com o ambiente interno do objeto.

• Construtores e Destrutores

Construtores de instâncias, ou simplesmente construtores, são métodos chamados


automaticamente quando ocorre uma instanciação de uma classe, ou seja, quando
um objeto é criado. Estes realizam as ações necessárias para a inicialização correta
do objeto, como por exemplo, atribuir valores aos atributos de controle interno do
objeto, para que então este possa ser usado corretamente.

Em contraste com os métodos construtores, temos os métodos destrutores, que


são executados automaticamente quando o escopo em que os objetos estão
definidos é finalizado (i.e., quando uma instância de uma classe não pode ser mais
referenciada, ela é removida da memória pelo mecanismo de coleta automática de
lixo, também denominado Garbage Collector. Contudo, quando seu objeto utiliza
recursos não gerenciáveis automaticamente, como arquivos, conexões de rede, etc.
é necessário usar o destrutor para liberar esses recursos). Seu principal objetivo é a
liberação de recursos alocados pelo objeto que será destruído (liberar arquivos,
sockets, conexões com banco de dados, etc).

Objeto

Um objeto ou instância é uma materialização da classe, e pode ser usado para


armazenar dados e realizar as operações definidas na classe. Na grande maioria
das linguagens orientadas a objetos mais recentes, como Java e C# , a instanciação
de um objeto é feita quando o operador new é seguido da chamada de algum
método construtor. Para que os objetos ou instâncias possam ser manipulados, é
necessária a criar uma instância da classe, que é basicamente criar variáveis do
tipo da classe. Após alterar o valor de algum dos atributos do objeto é dito que o
estado do objeto foi alterado.

Encapsulamento

Encapsulamento permite que detalhes complicados da implementação da classe (regras de


negócio, atributos para controle interno, métodos, etc.) sejam escondidos de quem os usa,
sendo que estes apenas interagem com o que precisam através de interfaces, permitindo
assim ocultar do usuário toda a parte que é irrelevante para este.

Dessa maneira, podemos pensar em uma classe como uma caixa preta, pois sabemos o que
ela faz, conhecemos e interagimos com sua interface externa, mas não nos preocupamos
como o processo é feito lá dentro.

p. 7 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

A ideia do encapsulamento é tornar o software mais flexível, fácil de modificar e de criar


novas implementações, uma vez, que cada parte possui sua implementação e realiza seu
trabalho independentemente das outras partes (i.e., pacotes, bibliotecas, componentes,
classes, métodos, etc.).

Modificadores de Acesso

Nas linguagens de programação orientada a objetos (e.g., C++, Java, C#), em geral, os
níveis de encapsulamento são indicados através das seguintes palavras-chaves:

• public: é o modificador menos restritivo; ele permite que o membro da


classe pode ser acessado externamente a ela, assim como das classes
derivadas desta;
• protected: esse modificador permite que o membro seja acessado apenas
pela própria classe ou pelas classes que derivam desta;
• private: é o modificador mais restritivo; ele permite que o membro da classe
seja acessado somente de dentro desta, não podendo ser acessado nem
mesmo por classes derivadas.

Essas palavras chaves são chamadas de “modificadores de acesso” e são utilizadas para
definir quem terá acesso à classe e a seus membros (atributos e métodos), sendo assim,
essenciais para o encapsulamento.

Geralmente atributos encapsulados são atributos que não podem ser alterados
livremente, por estarem intimamente relacionado a outros atributos e a integridade do
objeto, de tal forma que se forem alterados de forma indevida, podem tornar o estado
do objeto inconsistente.

Para lidar com atributos encapsulados com o uso dos modificadores protected ou private,
é preciso implementar métodos públicos que acessam e alteram esses atributos, fazendo
todo tratamento para que a integridade do objeto seja mantida.

Herança

Herança Simples

O conceito de herança é construído sobre a ideia de que algumas classes estão intimamente
ligadas a outras classes, e que por conta disso, compartilham características em comum (i.e.,
atributos, métodos, comportamentos, etc.).

Partindo dessa ideia, podemos estabelecer um relacionamento hierárquico entre classes,


em que a classe no topo da árvore é a classe mais genérica (geralmente chamada de classe
base, ou classe mãe) e à medida que descemos de nível na hierarquia, temos uma nova
classe (classe derivada, ou classe filha), que é uma especialização da classe acima. Por conta
disso, geralmente nos referimos à relação que vincula uma classe derivada a sua classe base
pela frase "Y é um tipo de X" ou "Y é uma especialização da classe X", sendo X a classe base
e Y a classe derivada.

Abaixo tem uma figura que torna simples o entendimento, a classe mãe Animal, contém o
nível mais genérico, as classes filhas ou derivadas Mamífero e Ave, possuem um novo grau
de especialização, porém não deixar ser uma classe animal, o mesmo acontecendo com os
níveis subsequentes.

p. 8 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

Figure 5:Classe Mãe Anima e Suas Filhas -


http://www.dsc.ufcg.edu.br/~pet/jornal/junho2011/materias/recapitulando.html

O mecanismo de herança permite que uma classe seja definida a partir de uma outra classe
já existente, com isso a definição da classe derivada herda automaticamente atributos,
métodos e comportamentos da classe base. Por conta disso, herança é considerada uma
técnica poderosa, uma vez que encoraja a reusabilidade durante o desenvolvimento e provê
uma grande economia de tempo, sem perda de qualidade no desenvolvimento (pois você
não precisa reescrever, testar, depurar e manter o código herdado).

Herança múltipla

Algumas linguagens orientadas a objetos como C++, Scala e Python também oferecem o
mecanismo de herança múltipla, que permite que uma classe herde de mais de uma classe
ao mesmo tempo.

Contudo herança múltipla tem sido uma questão sensível por muitos anos, pois pode
aumentar a complexidade na programação e gerar ambiguidade em situações onde mais de
uma classe base possui atributos ou métodos como mesmo nome, embora hoje já haja
abordagens que resolvem essa ambigüidade (i.e., em C++ por exemplo, é usado
classePai::AtributoAmbiguo para explicitar de qual classe o atributo ambíguo será acessado).

Polimorfismo

A palavra polimorfismo vem do grego, πολύς (poli) que significa muitas e μορφή (morphos)
que significa formas, ou seja, muitas formas. Em programação, é dito que um objeto é
polimórfico quando o sistema de tipo da linguagem atribui mais de um tipo a este.

Linguagens tipadas convencionais, como Pascal, baseiam-se na ideia de que funções e


procedimentos e, consequentemente, seus parâmetros, têm um tipo único. Tais linguagens
são ditas monomórficas, no sentido de que cada variável pode ser interpretada como sendo
de um tipo. Linguagens de programação monomórficas contrastam com as linguagens
polimórficas em que algumas variáveis podem ter mais de um tipo.

Contudo, mesmo nas linguagens de programação mais convencionais há um certo grau de


polimorfismo. Em muitas linguagens, por exemplo, o operador de soma (+), aceita tanto soma
entre números inteiros (int x int -> int), quanto soma entre números reais (float x float ->

p. 9 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

float), e em algumas linguagens ainda, age como concatenador de strings (string x string ->
string). Sendo assim, podemos dizer que operador de soma é polimórfico, pois possui mais
de um tipo, e assume um deles de acordo com o contexto. Outro exemplo, seria a função
length(), que retorna o número de elementos em um vetor de tipo T (T[] -> int), sendo T
qualquer tipo.

Existem quatro tipos de polimorfismo que uma linguagem pode ter (note que nem toda
linguagem orientada a objetos implementa todos os tipos de polimorfismo).

• Sobrecarga

Sobrecarga ocorre quando definimos numa mesma classe métodos com o mesmo nome,
mas com assinaturas diferentes, ou seja, que recebem e/ou retornam parâmetros de
tipos diferentes. Esse tipo de polimorfismo ocorre em tempo de compilação, pois
conseguimos saber qual definição do método será invocada para um dado grupo de
parâmetros antes mesmo de o código ser executado.

• Coerção

Coerção permite ao programador converter de maneira implícita alguns tipos para


outros tipos, omitindo assim algumas conversões de tipo semanticamente necessárias.

Em C# por exemplo, é possível converter implicitamente um tipo int para double, como
ilustrado abaixo:

int a = 2;

double b = a;

Esse tipo de polimorfismo nos permite, por exemplo, definir uma função de soma, para
o tipo double, e usá-la para somar inteiros, bem como somar variáveis dos dois tipos.

Paramétrico

Polimorfismo paramétrico permite que uma função ou um tipo de dado seja escrito de forma
genérica, de modo que ele possa lidar com valores uniformemente, sem dependendo do seu
tipo.

O polimorfismo paramétrico é extremamente útil quando precisamos criar estruturas de


dados genéricas, como listas, árvores, filas, pilhas, etc. Utilizando o polimorfismo
paramétrico, podemos definir a estrutura de forma genérica, e especificar o tipo no momento
da criação do objeto ou do uso da função.

Inclusão

Objetos de um subtipo (classe derivada) podem ser manipulados como sendo objetos de
algum de seus supertipos (classe base).

Classe Abstrata

Classe abstrata é uma classe que não pode ser instanciada diretamente, mas que pode ser
herdada por outras classes. Nela, definimos atributos, métodos e métodos abstratos, que
são métodos com apenas a assinatura definida, sem implementação.

p. 10 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

As classes derivadas (através de override) é que definirão a funcionalidade de cada atributo


ou método abstrato. A ideia de uma classe abstrata é forçar que todas as suas classes
derivadas implementem os atributos e métodos definidos nela.

Classes abstratas também podem herdar de outras classes abstratas e uma classe abstrata
pode ser herdada por uma classe concreta (i.e., classes instanciáveis, como Pessoa,
Trabalhador, Estudante, Pilha<T>, etc.).

Um bom exemplo de classe abstrata é a classe Animal, uma vez que esta classe em si é uma
abstração de todas as espécies de animais, e consequentemente, não existe no mundo real
um animal que seja apenas do tipo Animal, e sim “animais concretos” que são de alguma raça
e espécie específica (e.g., pastor alemão, harpia, pônei, etc., note que esses animais também
pertencem a outras classes abstratas, sendo estas cachorro, ave e cavalo, respectivamente,
que também herdam de Animal), ou seja, que pertencem a alguma classe concreta derivada
de Animal.

Interface

Na interface definimos atributos e métodos sem implementar nada do seu código (apenas
assinaturas) e a classe que implementa a interface é obrigada a fornecer (implementar) os
códigos definidos na interface. Vale também evidenciar que uma classe pode implementar
mais de uma interface, sendo esta uma alternativa para compartilhamento de características
entre classes em linguagens que não suportam herança múltipla.

Por exemplo, podemos pensar no código de barras de um produto como uma interface, uma
vez que são estabelecidos padrões de código de barra, e é necessário que todo produto
implemente esses padrões para poder ser identificado.

Comparação: Procedural VS Orientada a Objetos

Legibilidade

Uma vez que os paradigmas procedimental e orientado a objetos são imperativos, nestes o
programador precisa definir exatamente como quer que o programa seja computado,
explicitando, além da lógica do algoritmo, todo o fluxo de controle e manipulação dos dados.
Por sua vez, nas abordagens dos paradigmas funcional e lógico, que são declarativos, o
programador delega ao sistema todo o fluxo de controle da execução do programa,
permitindo o mesmo apenas declarar as estruturas e funções necessárias para a solução do
problema.

Baseado nesse fato podemos argumentar que a abordagem imperativa faz com que um
programa seja mais difícil de ler se comparado a declarativa, pois uma vez que é necessário
explicitar sobre qual fluxo de controle o programa deve ser computado, parte do código
passar a ser mais para a máquina do que para o ser humano, o que pode inclusive dificultar
a compreensão deste quanto a ideia do algoritmo em si, uma vez que para o ser humano
compreender o processo de resolução de um problema, nem sempre é preciso explicitar
todo o fluxo, bastando uma abstração adequada.

Vale ressaltar também que, como na programação declarativa os dados são imutáveis, o
programa é livre de efeitos colaterais e possui transparência referencial, uma vez que você
entende como algo funciona, você não precisa mais se preocupar se em algum momento
especifico pode acontecer um erro naquele código caso o programa seja executado de
alguma forma não planejada. Essa característica torna a leitura do código muito mais simples,

p. 11 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

uma vez que o resultado de todas as partes do programa não compartilham estados em
comum e são independentes das demais partes (e de sua ordem de execução), permitindo o
programador se concentrar em entender apenas a parte desejada, abstraindo as demais
partes, sem receio de que o não conhecimento delas possa facilitar um erro.

Capacidade de Escrita

Podemos também analisar a expressividade dos paradigmas quanto à quantidade de esforço


necessário para se escrever um programa nele, ou seja, por quão fácil é usar um determinado
paradigma para representar um problema e sua solução.

Cada paradigma foi feito para expressar de forma simples e natural um tipo de problema,
consequentemente um programa relativamente simples pode se tornar complexo num
paradigma inapropriado.

Confiabilidade

Pelo fato de programas desenvolvidos no paradigma imperativo terem seu estado


representado por variáveis, e essas poderem ser compartilhadas entre diferentes partes do
programa (ou seja, podem ter efeitos colaterais) é possível que um método altere o estado
do programa e, de forma não planejada, acabe corrompendo a integridade do sistema, o que
muito provavelmente pode levar a um erro em tempo de execução. Esse é comum problema
comum no paradigma imperativo, e pode ser contornado com o uso dos tratadores de
exceção try-catch, presentes em linguagens imperativas mais recentes como C++, Java, C#,
JavaScript, Python, etc.

No paradigma orientado a objetos, ainda pode ser usado o conceito de encapsulamento para
tornar o programa mais modular, como uma caixa preta. Assim, é fácil desenvolver um
módulo, testá-lo, e uma vez testado, usá-lo em outras partes do projeto com total
confiabilidade, bem como em outros projetos. Dessa forma, é possível aumentar a
produtividade sem perder confiabilidade.

Já no paradigma funcional o problema citado não existe, uma vez que o programa não tem
estados, e todos os dados definidos são imutáveis. Propriedades como transparência
referencial e ausência de efeitos colaterais tornam a programação funcional muito mais
modular e fácil do seu código ser analisado e testado de forma isolada, sendo um enorme
trunfo quanto à confiabilidade do programa. O mesmo também vale para programas
desenvolvidos no paradigma lógico, que assim como o funcional, também tem transparência
referencial e ausência de efeitos colaterais.

Eficiência

O paradigma imperativo é baseado na máquina de Turing e na arquitetura von Neumann de


computadores, consequentemente esses programas são naturalmente eficientes quando
executados nessa arquitetura; enquanto o paradigma declarativo é totalmente diferente
deste modelo, sendo programas escritos neste geralmente menos eficientes no uso de CPU
e memória que programas imperativos, como C, Pascal e Java.

Reusabilidade

Como vimos ao longo deste trabalho, nos paradigmas procedimental, funcional e orientado
a objetos podemos escrever funções e / ou subrotinas, e por meio dessas encapsular uma
determinada ação ou processo do sistema, bastando apenas chamá-la quando necessário; o
que nos evita ter de reescrever o código em todos os lugares onde aquela ação se faz

p. 12 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

presente, aumentando assim altamente a reusabilidade em um projeto de software. Uma vez


que já temos várias funções escritas, ainda podemos, a partir dessas criar bibliotecas de
funções, possibilitando assim a reusabilidade de código não apenas em várias partes de um
mesmo sistema, mas também entre vários sistemas.

O conceito de polimorfismo paramétrico adotado pelos paradigmas funcional e orientado a


objeto também colaboram consideravelmente para uma maior reusabilidade durante o
desenvolvimento de um projeto, pois é possível definir funções que aceitam mais de um tipo
como parâmetro, o que nos permite escrever uma função genérica e usá-la para diversos
tipos, ao invés de termos que reescrever o código para todos os tipos necessários.

No paradigma orientado a objetos, além do polimorfismo, podemos destacar o conceito de


herança, que tem como objetivo justamente definir novas classes a partir de outras já
implementadas, herdando todas as características (atributos, métodos, formas de
construção, etc.) da classe mãe, evitando assim que o programador tenha reescrever toda a
estrutura mais genérica para cada nova especialização.

Manutenabilidade

Manutenção em programas imperativos tende a ser uma tarefa mais difícil já que esses
possuem estados mutáveis com dependências implícitas e, possivelmente, subrotinas pouco
expressivas. Uma forma de minimizar essa dificuldade é fazer uso do conceito de
encapsulamento, ocultando assim toda parte “sensível” do programa (e.g., controle interno
de um objeto, validações da regra de negócio, etc.), tornando assim o programa mais modular
e por tanto, mais fácil de testar e manter. No paradigma procedimental, que não possui
explicitamente um conceito de encapsulamento, podemos modularizar o código por
subrotinas e bibliotecas.

Para simplificar o código em programas imperativos e minimizar a dificuldade de manutenção,


existe uma série de recomendações/boas práticas a seguir durante o desenvolvimento, como
por exemplo: usar nomes significativos para variáveis, cada função ou subrotina deve realizar
apenas uma tarefa, comentar o código quando for necessário evidenciar alguma regra do
negócio, etc.

Bibliografia:

https://leandromoh.gitbooks.io/tcc-paradigmas-de-programacao

https://fit.faccat.br/~guto/artigos/Artigo_Paradigmas_de_Programacao.pdf

https://www.devmedia.com.br/paradigmas-de-programacao-estruturado-e-orientado-a-
objetos/27335

Programação de computadores em Java, Rui Rossi dos Santos, Nova Terrra, 2011

https://www.devmedia.com.br/programacao-orientada-a-objetos-versus-programacao-
estruturada/32813

https://www.differencebetween.com/difference-between-declarative-and-vs-imperative-
programming/

https://bar8.com.br/abap-oo-versus-procedural-50474ff371a5

http://www.dsc.ufcg.edu.br/~pet/jornal/junho2011/materias/recapitulando.html

p. 13 Paulo Ricardo Siqueira Soares


Desenvolvimento de Software, Treinamentos e Consultoria em Gestão de Projetos

p. 14 Paulo Ricardo Siqueira Soares

Você também pode gostar