Paradigmas de Programação
Fala, skillers! Hoje vamos falar sobre paradigmas de programação. "Paradigma" parece uma daquelas palavras que só aparecem em provas de filosofia, mas relaxa que vou te mostrar como isso é essencial para a nossa arte de codar.
Imperativo
No paradigma imperativo, você é o chefe e o computador é o estagiário que segue suas ordens à risca. Você diz o que fazer e como fazer. É como se você estivesse dando um passo a passo de como preparar um miojo gourmet.
Exemplos
- Linguagem C
No C, você tem que ser bem específico sobre o que quer fazer. Você declara variáveis, modifica seus valores e controla o fluxo do programa passo a passo.

#include <stdio.h>
int main() {
int num = 15; // Declara uma variável num e inicializa com 15
num = num + 10; // Soma 10 ao valor atual de num
printf("%d", num); // Imprime o valor de num, que agora é 25
return 0; // Encerra o programa com sucesso
}
- Python

Python é conhecido por ser super legível. Aqui, definimos uma função que faz o trabalho e a chamamos com o número 15. Python cuida de muitos detalhes para você, como gerenciamento de memória.
num = 15
soma = num + 10
print soma # mostrará 25
3. Javascript

JavaScript é a linguagem que domina os navegadores. Aqui, também estamos fazendo uma operação simples de adição e exibindo o resultado no console.
let num = 15; // Declara uma variável num e atribui 15 a ela
num += 10; // Usa o operador += para adicionar 10 ao valor atual de num
console.log(num); // Imprime o valor de num no console, que será 25
Em todas essas linguagens, estamos seguindo o paradigma imperativo: dizendo ao computador como fazer algo passo a passo. É como se estivéssemos dando uma receita de bolo para ele seguir. E aí, curtiu os exemplos? Qualquer coisa, só chamar que a gente descomplica mais! 🚀
Procedural
Aqui ainda é você quem manda, mas agora você organiza as tarefas em procedimentos ou funções. É tipo ter uma playlist para cada momento do seu dia.
O paradigma procedural é caracterizado pelo uso de procedimentos, também conhecidos como funções ou sub-rotinas, que contêm uma série de etapas computacionais a serem executadas. Vou fornecer exemplos em três linguagens de programação que suportam o paradigma procedural: C, Pascal e Python.

- C
C é uma linguagem de programação procedural clássica. Aqui está um exemplo simples de um procedimento em C que calcula a soma de dois números:
#include <stdio.h>
// Definição do procedimento
void soma(int a, int b) {
int resultado = a + b;
printf("A soma é: %d\n", resultado);
}
int main() {
// Chamada do procedimento
soma(5, 3);
return 0;
}
Neste exemplo, soma
é um procedimento que recebe dois inteiros, os soma e imprime o resultado.
- Pascal
Pascal é outra linguagem de programação procedural. Aqui está um exemplo de um procedimento em Pascal que realiza a mesma tarefa:

program Example;
uses crt;
// Definição do procedimento
procedure Soma(a, b: Integer);
var
resultado: Integer;
begin
resultado := a + b;
WriteLn('A soma é: ', resultado);
end;
begin
// Chamada do procedimento
Soma(5, 3);
ReadKey;
end.
Neste exemplo, Soma
é um procedimento que toma dois parâmetros, calcula a soma e exibe o resultado.

- Python
Embora Python seja uma linguagem de programação de alto nível com suporte a múltiplos paradigmas, incluindo programação orientada a objetos e funcional, ela também pode ser usada de forma procedural. Aqui está um exemplo de uma função em Python que age como um procedimento:
# Definição da função
def soma(a, b):
resultado = a + b
print(f"A soma é: {resultado}")
# Chamada da função
soma(5, 3)
Neste exemplo, soma
é uma função que recebe dois argumentos, calcula a soma e imprime o resultado. Em Python, as funções podem ser tratadas como procedimentos quando não retornam explicitamente um valor (ou seja, quando não há um return
ou quando o return
não tem um valor associado).
Esses exemplos demonstram o uso do paradigma procedural em diferentes linguagens de programação. Embora a sintaxe varie, o conceito fundamental de encapsular a lógica em blocos reutilizáveis é consistente entre elas.
Paradigma Imperativo
O paradigma imperativo é o mais básico dos paradigmas de programação e foca em como você faz as coisas, ou seja, como você chega a um resultado. Ele é caracterizado pelo uso de comandos para alterar o estado do programa. Você diz ao computador para realizar uma série de tarefas passo a passo. Este paradigma inclui conceitos como variáveis, loops e condicionais.
Exemplo em pseudocódigo imperativo:
inicialize total como 0
para cada número na lista:
adicione o número ao total
mostre o total
Paradigma Procedural
O paradigma procedural é uma extensão do imperativo. Ele ainda diz ao computador como fazer as coisas, mas introduz o conceito de procedimentos ou funções — blocos de código que podem ser reutilizados. Isso permite que você estruture melhor o seu código e o torne mais modular e fácil de manter. No procedural, você ainda está preocupado com o estado e como as coisas são feitas, mas você organiza seu código em procedimentos que podem ser chamados várias vezes.
Exemplo em pseudocódigo procedural:
procedimento calculeTotal(lista de números):
inicialize total como 0
para cada número na lista:
adicione o número ao total
retorne total
total = calculeTotal(lista de números)
mostre total
A principal diferença é que, enquanto o imperativo pode ser considerado a base, o procedural é uma construção sobre essa base que introduz a ideia de dividir o código em unidades reutilizáveis chamadas procedimentos ou funções. Isso ajuda a evitar repetições e torna o código mais organizado e fácil de entender.
Declarativo
O paradigma declarativo de programação é um estilo onde você escreve código que descreve o que você quer alcançar, em vez de como você quer alcançá-lo. Este paradigma contrasta com o estilo imperativo, onde o código precisa detalhar explicitamente os passos necessários para alcançar um resultado desejado.
Aqui estão três exemplos de uso do paradigma declarativo:

1. SQL para Bancos de Dados
SQL, ou Linguagem de Consulta Estruturada, é uma linguagem declarativa usada para gerenciar e recuperar informações de bancos de dados relacionais. Em vez de dizer ao computador como percorrer tabelas e dados, você declara o que deseja.
Exemplo:
SELECT nome, idade FROM usuarios WHERE pais = 'Brasil';
Este comando SQL declara que você deseja obter os nomes e idades dos usuários que estão no Brasil. O sistema de gerenciamento de banco de dados (SGBD) cuida de como essa operação será realizada.
2. HTML para Páginas Web

HTML, ou Linguagem de Marcação de Hipertexto, é uma linguagem declarativa usada para estruturar conteúdo na web. Você descreve a estrutura da página, e o navegador web cuida de renderizá-la.
Exemplo:
<p class="destaque">Bem-vindo ao meu site!</p>
Este trecho de HTML declara que há um parágrafo de texto que deve ser destacado (possivelmente com estilos definidos em CSS). O navegador interpreta essa marcação e exibe o conteúdo de acordo.
3. CSS para Estilização de Páginas Web
CSS, ou Cascading Style Sheets, é uma linguagem declarativa usada para definir a apresentação de um documento escrito em HTML ou XML. Você declara como os elementos devem ser exibidos, e o navegador aplica esses estilos.
Exemplo:
.destaque {
font-weight: bold;
color: red;
}
Este CSS declara que qualquer elemento com a classe destaque
deve ter o texto em negrito e colorido de vermelho. O navegador aplica esses estilos automaticamente onde a classe é usada.
Em todos esses exemplos, o foco está em descrever o resultado desejado, não em como o computador deve chegar a esse resultado. Isso pode tornar o código mais fácil de ler e manter, pois você está trabalhando em um nível mais abstrato de pensamento.
Funcional
Inspirado na matemática, você trabalha com funções que transformam dados sem alterar o estado do mundo. É como se cada função fosse uma receita que sempre dá certo se você seguir os passos.
A programação funcional é um subtipo do paradigma declarativo que trata a computação como a avaliação de funções matemáticas e evita mudanças de estado e dados mutáveis. É baseada em funções puras, imutabilidade e funções de primeira classe.
Quando usar a programação funcional:
- Cálculos Matemáticos Complexos: Devido à sua proximidade com a matemática, a programação funcional é adequada para sistemas que requerem uma alta confiabilidade em cálculos complexos.
- Programas Concorrentes ou Paralelos: A imutabilidade dos dados facilita a execução de programas em ambientes concorrentes ou paralelos, pois não há preocupações com condições de corrida.
- Sistemas com Fluxos de Dados Complexos: A capacidade de compor funções torna mais fácil gerenciar fluxos de dados complexos e operações de transformação de dados.
- Desenvolvimento de Software Reativo: Para aplicações que requerem um alto grau de reatividade a eventos, como interfaces de usuário ou sistemas em tempo real.
Por que usar a programação funcional:
- Código Mais Limpo e Expressivo: As funções puras e a composição de funções podem levar a um código mais conciso e fácil de entender.
- Facilidade de Teste e Depuração: Funções puras são mais fáceis de testar e depurar, pois não dependem nem alteram o estado externo.
- Menos Bugs: A imutabilidade e as funções puras reduzem os efeitos colaterais, o que pode levar a menos bugs.
- Reusabilidade de Código: As funções de alta ordem e a composição de funções podem aumentar a reusabilidade do código.
Exemplos de linguagens funcionais:
-
Haskell:
- É uma linguagem puramente funcional com tipagem estática.
- Exemplo:
Este código define uma função-- Define uma função que calcula o quadrado de um número square x = x * x -- Usa a função map para aplicar a função square a uma lista de números main = print (map square [1, 2, 3, 4, 5])
square
e a aplica a uma lista de números, retornando uma nova lista com os quadrados dos números originais.
-
Erlang:
- Usada principalmente para sistemas de telecomunicações, é conhecida por sua capacidade de lidar com sistemas concorrentes e distribuídos.
- Exemplo:
Este código usa o padrão de correspondência para definir a função fatorial de maneira recursiva.% Define uma função que calcula o fatorial de um número factorial(0) -> 1; factorial(N) -> N * factorial(N-1).
-
Scala:
- Combina programação orientada a objetos e funcional, rodando na JVM (Java Virtual Machine).
- Exemplo:
Este código usa uma função anônima para calcular o quadrado de cada número em uma lista e imprimir o resultado.// Define uma função anônima que calcula o quadrado de um número e a aplica a uma lista val numbers = List(1, 2, 3, 4, 5) val squaredNumbers = numbers.map(n => n * n) println(squaredNumbers)
-
Clojure:
- É uma linguagem funcional moderna que também roda na JVM.
- Exemplo:
Este código usa uma função anônima para calcular o quadrado de números em uma lista.;; Usa a função map com uma função anônima para calcular o quadrado de números (println (map #(Math/pow % 2) [1 2 3 4 5]))
-
F#:
- É uma linguagem funcional para a plataforma .NET.
- Exemplo:
Este código define uma função// Define uma função que calcula o quadrado de um número let square x = x * x // Aplica a função square a uma lista de números [1; 2; 3; 4; 5] |> List.map square |> printfn "%A"
square
e a aplica a uma lista de números, imprimindo os quadrados dos números originais.
-
Javascript:
- React JS é uma biblioteca JavaScript para construir interfaces de usuário que também adota princípios da programação funcional, especialmente com a introdução de Hooks.
- Exemplo:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
- Programação Funcional em Ruby
- Ruby não é uma linguagem funcional por natureza, mas permite a programação funcional através de lambdas e procs.
- Exemplo
squared_numbers = [1, 2, 3, 4, 5].map { |n| n ** 2 }
puts squared_numbers
Cada uma dessas linguagens oferece recursos únicos que as tornam adequadas para diferentes tipos de tarefas de programação funcional. A escolha da linguagem muitas vezes depende do ecossistema em que você está trabalhando (por exemplo, JVM, .NET) e das preferências pessoais ou da equipe.
Lógico
Agora, a coisa fica Sherlock Holmes. No paradigma lógico, você descreve o problema e o computador vira detetive para resolver o caso. Você diz o que precisa ser resolvido, e ele encontra a solução.
Características do Paradigma Lógico
- Declaratividade: Os programas são escritos de forma declarativa, especificando o "o quê" em vez do "como".
- Imutabilidade: Os fatos em um programa lógico não mudam uma vez que são estabelecidos.
- Backtracking: Muitas linguagens lógicas usam backtracking para encontrar soluções, revertendo decisões anteriores para explorar diferentes caminhos lógicos.
- Recursão: A recursão é uma ferramenta natural e poderosa em linguagens lógicas, permitindo definições concisas de problemas complexos.
Prolog
Prolog, que significa "Programação em Lógica", é uma das linguagens de programação lógica mais conhecidas. Ela é usada principalmente em sistemas de inteligência artificial e processamento de linguagem natural.
% Definição de parentesco
parent(philip, charles).
parent(queen_mother, elizabeth).
% Regra para encontrar um avô
grandparent(X, Y) :- parent(X, Z), parent(Z, Y).
% Consulta: Quem é o avô de Elizabeth?
?- grandparent(X, elizabeth).
Datalog
Datalog é uma linguagem de consulta e uma subconjunto do Prolog, frequentemente usada em bancos de dados e sistemas de informação.
% Fatos
likes(mary, food).
likes(john, football).
likes(susan, food).
% Regra
friend(X, Y) :- likes(X, Z), likes(Y, Z), X != Y.
% Consulta: Quem são amigos por gostarem das mesmas coisas?
?- friend(X, Y).
Mercury
Mercury é uma linguagem de programação lógica funcional que visa ser mais eficiente e fácil de usar do que o Prolog tradicional.
% Fato
likes("Alice", reading).
likes("Bob", chess).
likes("Carol", reading).
% Regra
friend(X, Y) :- likes(X, Activity), likes(Y, Activity), X \= Y.
% Consulta: Quem são amigos baseados em atividades comuns?
?- friend(Alice, Friend).
O paradigma lógico oferece uma abordagem única e poderosa para a resolução de problemas, permitindo que os programadores expressem complexidades de maneira concisa e clara. Ele é especialmente útil em campos como a inteligência artificial, onde a capacidade de representar e manipular conhecimento é fundamental.
Programação Orientada a Objetos
No paradigma orientado a objetos, você pensa em tudo como se fossem objetos do mundo real, com características e ações próprias. É como ter um time, onde cada jogador tem uma função específica.
Programação Orientada a Objetos (POO):
Conceitos e Aplicações
A Programação Orientada a Objetos (POO) é um paradigma de programação baseado no conceito de "objetos", que podem conter dados na forma de campos, frequentemente conhecidos como atributos, e código, na forma de procedimentos, frequentemente conhecidos como métodos. Um dos principais benefícios da POO é a capacidade de aumentar a reutilização de código e tornar os modelos de software mais compreensíveis.
Conceitos Fundamentais da POO
Abstração
A abstração é o processo de ocultar a complexidade real de um sistema, expondo apenas as partes necessárias. Em POO, isso é feito usando classes que representam tipos abstratos de objetos do mundo real.
Em Java, a abstração é frequentemente alcançada usando classes abstratas ou interfaces. Uma classe abstrata não pode ser instanciada por si só e é destinada a ser subclassificada, enquanto interfaces podem ser usadas para definir um contrato que outras classes implementarão.
// Exemplo de uma classe abstrata em Java
public abstract class Vehicle {
private String brand;
// Método abstrato
public abstract void honk(); // Os veículos honram de formas diferentes
// Métodos concretos
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
}
// Classe concreta que estende a classe abstrata
public class Car extends Vehicle {
@Override
public void honk() {
System.out.println("Beep beep!");
}
}
Encapsulamento
Encapsulamento é o conceito de esconder o estado interno de um objeto e exigir que toda a interação seja realizada através de métodos. Isso protege a integridade dos dados e esconde a complexidade.
O encapsulamento em Java é realizado usando modificadores de acesso: private
, protected
, e public
. Ao declarar os campos de uma classe como private
, você restringe o acesso direto a eles, forçando o uso de métodos públicos para ler ou modificar esses campos (getters e setters).
public class Account {
private double balance;
// Getter
public double getBalance() {
return balance;
}
// Setter
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
public void withdraw(double amount) {
if (amount <= balance) {
balance -= amount;
}
}
}
Herança
Herança permite que uma classe herde características (métodos e atributos) de outra classe. A classe que herda é chamada de subclasse ou classe derivada, e a classe da qual se herda é chamada de superclasse ou classe base.
A herança é um recurso chave da POO que permite que uma nova classe adquira as propriedades e comportamentos de uma classe existente. Em Java, a herança é realizada usando a palavra-chave extends
.
// Classe base ou superclasse
public class Animal {
public void eat() {
System.out.println("This animal eats food.");
}
}
// Subclasse que herda de Animal
public class Dog extends Animal {
public void bark() {
System.out.println("The dog barks.");
}
}
Polimorfismo
Polimorfismo é a capacidade de chamar o mesmo método em diferentes objetos e cada objeto responder de acordo com a classe a que pertence.
O polimorfismo permite que objetos sejam tratados como instâncias de sua classe base em vez de sua classe real. Em Java, isso significa que uma referência de superclasse pode referir-se a um objeto de qualquer subclasse.
public class Shape {
public void draw() {
System.out.println("Drawing a shape.");
}
}
public class Circle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a circle.");
}
}
public class Square extends Shape {
@Override
public void draw() {
System.out.println("Drawing a square.");
}
}
public class Main {
public static void main(String[] args) {
Shape shape1 = new Circle();
Shape shape2 = new Square();
shape1.draw(); // Saída: Drawing a circle.
shape2.draw(); // Saída: Drawing a square.
}
}
Neste exemplo de polimorfismo, o método draw()
é sobrescrito nas subclasses Circle
e Square
, mas podemos chamar draw()
em uma referência do tipo Shape
. Em tempo de execução, o método apropriado é chamado com base no tipo real do objeto referenciado.
Quando usar POO
A POO é ideal quando você tem um conjunto complexo de interações e relacionamentos entre entidades, e você quer modelar seu software de maneira próxima à representação do mundo real. É útil em sistemas grandes e complexos que requerem manutenção e escalabilidade a longo prazo.
Exemplos em Diferentes Linguagens
Smalltalk (A Mãe da POO)
"Definição de uma classe Pessoa"
Person class
superclass: Object
instanceVariableNames: 'name age'
"Definição de métodos"
Person methodsFor: 'acessando'
getName
^name
setName: aName
name := aName.
getAge
^age
setAge: anAge
age := anAge.
Java
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Ruby
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
end
Python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def get_name(self):
return self.name
def set_name(self, name):
self.name = name
def get_age(self):
return self.age
def set_age(self, age):
self.age = age
C++
class Person {
private:
std::string name;
int age;
public:
Person(std::string name, int age) : name(name), age(age) {}
std::string getName() const { return name; }
void setName(const std::string &name) { this->name = name; }
int getAge() const { return age; }
void setAge(int age) { this->age = age; }
};
Cada um desses exemplos ilustra como uma classe Person
pode ser definida em diferentes linguagens orientadas a objetos. Note que a sintaxe varia, mas os conceitos fundamentais de POO são consistentes em todas elas.
E aí, qual escolher?
Ei, não tem essa de melhor ou pior. Cada paradigma tem seu momento e seu problema para resolver. É como música: tem hora pra curtir um rock, um rap ou um sertanejo. Depende do problema que você tá tentando resolver.
Então é isso, galera. Programar é escolher a melhor conjunto de ferramentas pra resolver seu problema. E lembre-se: o importante é chegar lá, não importa se é de skate, de bike ou de patinete. Fica a dica e bora codar! 🤘