.NET - Programação Orientada a Objetos x Programação Procedural
Neste artigo eu vou tratar mais um vez dos conceitos da programação orientada a objetos (OO) e da programação procedural mostrando as diferenças entre ambas procurando usar uma linguagem simples e objetiva. |
O termo
Programação procedural (ou programação procedimental)
é às vezes utilizado como sinônimo de Programação imperativa (Paradigma
de programação que especifica os passos que um programa deve seguir para
alcançar um estado desejado), mas o termo pode se referir a um paradigma
de programação baseado no conceito de chamadas a procedimento.
Procedimentos,
também conhecidos como rotinas, sub-rotinas, métodos, ou funções
simplesmente contém um conjunto de passos computacionais a serem executados.
Um dado procedimento pode ser chamado a qualquer hora durante a execução de
um programa, inclusive por outros procedimentos ou por si mesmo. |
O que é exatamente um objeto ?
É uma questão complexa
e simples ao mesmo tempo.
Complexa porque o
aprendizado de qualquer método de desenvolvimento de software não é trivial.
Simples porque as
pessoas já pensam em termos de objetos.
Quando você olha para uma pessoa você vê a pessoa como um objeto, e um objeto é definido por dois termos: atributos e comportamento.
Uma pessoa tem
atributos como olhos, cor, idade, altura,
peso, etc.
Uma pessoa possui
comportamentos como caminhar, falar,
respirar, etc.
Em uma definição
básica um objeto é uma entidade que contém dados e
comportamento.
A palavra 'e' é a chave para diferenciar a programação orientada a objetos e outras metodologias de programação.
Na programação procedural, por exemplo, o código é colocado em funções ou procedimentos totalmente distintos.
Assim, esses procedimentos tornam-se caixas pretas onde temos a entrada e a saída do resultado. Os dados são colocados em estruturas separadas e é manipulado por essas funções ou procedimentos.
OOP x Procedural
No projeto OO os atributos e comportamentos estão contidos dentro de um único objeto, ao passo que no projeto procedural ou estruturado, os atributos e comportamentos estão normalmente separados.
Como ilustrado na figura abaixo, na programação estruturada os dados são frequentemente separados dos procedimentos e as algumas vezes os dados são globais, sendo assim muito fácil modificar os dados de fora do escopo do seu código.
A consequência disso é
que o acesso aos dados é descontrolado e imprevisível (isto é, várias funções
podem ter acesso aos dados globais). E como você não tem controle
sobre quem tem acesso aos dados, testar e depurar o seu código será muito
difícil.
A programação orientada a objetos (OO) resolve esse problema através da
combinação de dados e comportamento em um pacote completo.
Apenas para ilustrar, abaixo temos uma tabela comparando as características básicas do paradigma OO e do procedural:
Programação Orientada a Objetos | Programação Estruturada |
Métodos | Procedimentos e funções |
Instâncias de variáveis | Variáveis |
Mensagens | Chamadas a procedimentos e funções |
Classes | Tipos de dados definidos pelo usuário |
Herança | não disponível |
Polimorfismo | não disponível |
O projeto adequado
Podemos afirmar que quando projetado adequadamente não existem dados globais em um modelo da programação orientada a objetos. Este fato fornece uma grande integridade aos dados em sistemas OO.
Programas estruturados possuem uma estrutura complexa de dados como arrays, inteiros, strings, etc., mas objetos são muito mais do que estruturas e tipos de dados primitivos como inteiros e strings.Embora objetos possam conter entidades como inteiros e strings, os quais são usados para representar atributos, eles também contém métodos que representam comportamentos.
Na terminologia OO, os dados são referidos como atributos e os comportamentos referidos como métodos.
Em um objeto, métodos são usados para realizar operações nos dados bem como outras ações. O mais importante disso é que você pode controlar o acesso aos membros de um objeto (aos atributos e métodos). Isso significa que alguns membros, os atributos e métodos podem ser escondidos de outros objetos.
Restringir o acesso a determinados atributos e/ou métodos é chamado de ocultamento de dados.(data hiding)
Pela combinação de atributos e métodos na mesma entidade, que na terminologia OO é chamada de encapsulamento, podemos controlar o acesso aos dados de um objeto.
Como exemplo vamos definir o objeto chamado Calculadora que contém dois inteiros int1 e int2 e que também contém métodos para atribuir e retornar os valores de int1 e int2. Além disso esse objeto contém um método chamado Soma() que é usado para somar esses dois inteiros.
O que ocorre quando outro objeto chamado MeuObjeto quer acessar a soma de int1 com int2 ?
Ele envia uma mensagem ao objeto Calculadora.
A figura abaixo mostra como os dois objetos se comunicam entre si através de seus métodos.
A mensagem é na verdade uma chamada ao método Soma() do objeto Calculadora. O método Soma() então retorna o valor para MeuObjeto.
A beleza disto é que MeuObjeto não precisa saber como a soma é calculada.
Com essa metodologia de projeto você pode alterar como o objeto Calculadora calcula a soma sem ter que fazer qualquer alteração em MeuObjeto. Você quer apenas a soma e não se importa como ela é calculada.
Usando uma simples calculadora para ilustrar o conceito, quando você realiza a soma com uma calculadora tudo o que você usa é a interface da calculadora, o teclado e os leds do painel de exibição dos números.A calculadora possui um método Soma() que é invocado quando você pressiona as teclas corretas para obter o resultado correto, porém você não tem ideia de como o resultado foi obtido.
Calcular a soma não é responsabilidade de MeuObjeto, é responsabilidade do objeto Calculadora.
Tão logo MeuObjeto tenha acesso ao objeto Calculadora, ele pode enviar as mensagens apropriadas e obter o resultado pertinente.
Em geral objetos não manipulam dados internos de outros objetos ou seja MeuObjeto não pode alterar diretamente o valor de int1 e int2.
Programação Procedural
A programação procedural normalmente separa os dados do sistema das operações que manipulam os dados. Por exemplo se você quer enviar uma informação através da rede, somente os dados relevantes são enviados com a expectativa que outro programa que vai receber os dados na rede saiba o que fazer com os dados.
Em outras palavras, um espécie de acordo precisa existir entre o cliente e o servidor para transmitir os dados.
Programação Orientada a Objetos
A vantagem fundamental da OO é que os dados e as operações que manipulam os dados (o código) estão ambos encapsulados no objeto.
Por exemplo, quando um objeto é transportado através de um rede, o objeto inteiro, incluindo os dados e o comportamento vai junto com ele.
O que é exatamente uma classe ?
Na programação OO usamos os objetos seus atributos e comportamentos, mas de onde vêm os objetos ? a partir do que são gerados ?
Uma classe é um modelo para um objeto.
Quando você instancia um objeto você usa uma classe como base para construir o objeto.
É difícil descrever uma classe sem usar o termo objeto e vice-versa.
Assim a classe tem que existir primeiro pois um objeto não pode ser instanciado sem uma classe.
Classes são modelos para objetos
As classes podem ser vistas como modelos para objetos. Um modelo é como um molde a partir do qual podemos criar diversos objetos.
Na figura abaixo temos um exemplo onde a classe Estrela funciona como um modelo para criar objetos Estrela:
Lembre-se que cada objeto tem seus próprios atributos (campos) e comportamentos (funções e rotinas). Uma classe define os atributos e comportamentos que todos os objetos criados a partir dela irão possuir.
Dessa forma classes são pedaços de código, e os objetos instanciados a partir de classes podem ser distribuídos individualmente ou como parte da biblioteca.
Como os objetos são criados a partir de classes, temos que as classes precisam definir os fundamentos básicos da construção de objetos (atributos, comportamentos e mensagens).
Assim temos que projetar a classe antes de criar seus objetos.
Apenas para mostrar um exemplo com código abaixo temos um exemplo de uma classe Pessoa que tanto pode ser usado com C# como com Java:
public class Pessoa
{
//Atributos
private String nome;
private String endereco;
//Metodos
public String getNome()
{
return nome;
}
public void setName(String _nome)
{
nome = _nome;
}
public String getEndereco()
{
return endereco;
}
public void setEndereco(String _endereco)
{
endereco = _endereco;
}
}
|
Na classe Pessoa os atributos são representados por nome e endereco.
Quando um tipo de dados ou método é definido como Public outros objetos podem acessá-los diretamente.
Quando um tipo de dados ou método é definido como Private o acesso a eles é restrito.
Na classe Pessoa os comportamentos (métodos) getNome(), setNome(), getEndereco() e setEndereco() foram definidos como Public permitindo que outros objetos inspecionem e alterem os valores dos atributos do objeto.
Atualmente usamos a linguagem UML - Unified Modeling Language - para modelar um projeto de software OO, e na UML, o usamos o diagrama de classes para ilustrar as classes que projetamos.
Abaixo vemos o diagrama da classe Pessoa que criamos acima:
O retângulo é o
desenho que representa a classe e ele esta dividido em três áreas :
|
|
Uma das principais vantagens do uso de objetos é que o objeto não precisa revelar todos os seus atributos e comportamentos.
Em um bom projeto OO
(pelo menos o que é geralmente aceito como bom), um objeto só deve
revelar as interfaces que outros objetos deve ter para interagir com ele. Os
detalhes não pertinentes para a utilização do objeto deve estar oculto de todos
os outros objetos.
O encapsulamento é definido pelo fato de que os objetos contêm tanto os
atributos como os comportamentos. O ocultamento de dados é uma parte importante
do encapsulamento.
Por exemplo, um objeto que calcula o quadrado de um número deve fornecer uma
interface para obter o resultado. Contudo, os atributos internos e os algoritmos
usados para calcular o quadrado não precisam ser disponibilizados para o objeto
solicitante.
Classes robustas são projetadas com encapsulamento em mente.
A interface definida em cada classe define os meios fundamentais de comunicação entre objetos. Cada projeto de classe especifica as interfaces para a instanciação adequada e operação de objetos. Qualquer comportamento que o objeto fornece deve ser executado por uma mensagem enviada usando uma das interface fornecidas.
A interface deve descrever completamente como os usuários da classe interagem com a classe. Na maioria das linguagens OO, os métodos que fazem parte da interface são designados como Public.
Herança, a palavra mágica
Uma das
características mais poderosas de programação OO é, talvez, a
reutilização de código.
Se você esta pensando que um projeto estruturado também permite reusar código,
tudo bem , ele permite, mas existe um limite para isso, e, quando você escreve
um procedimento pode usá-lo quantas vezes quiser, mas o projeto OO vai um passo
adiante; ele permite que que você defina relacionamentos entre as classes e isso
facilita não somente a reutilização de código mas melhora todo o projeto,
através da organização das classes.
A herança é principal meio de fornecer essa funcionalidade.
A herança permite que uma classe herde os atributos e métodos de outra classe, e isso permite a criação de novas classes pela abstração de atributos e comportamentos comuns.
Polimorfismo
Polimorfismo significa muitas formas , na orientação a objetos você pode enviar uma mesma mensagem para diferentes objetos e fazê-los responder da maneira correta. Você pode enviar a mensagem mover para cada objeto semelhante a um veiculo e cada um vai se comportar de maneira diferente para atender a sua solicitação.
Quando uma mesma mensagem pode ser processada de diferentes formas temos um exemplo de polimorfismo.
Usando polimorfismo podemos :
Implementação C# e VB .NET
A seguir temos uma implementação na linguagem C# e VB .NET da classe Pessoa e sua utilização em uma aplicação do tipo Console:
1- Linguagem C#
using System;
namespace Classes_objetos
{
class Program
{
static void Main(string[] args)
{
Pessoa macoratti = new Pessoa();
macoratti.Nome = "Macoratti";
macoratti.Endereco = "Rua Projetada 100";
Console.WriteLine(macoratti.getEnderecoCompleto());
Console.ReadLine();
}
}
public class Pessoa
{
public String Nome { get; set; }
public String Endereco { get; set; }
public string getEnderecoCompleto()
{
return Nome + "\n" + Endereco;
}
}
}
|
2- Linguagem VB .NET
Module Module1
Sub Main()
Dim macoratti As New Pessoa()
macoratti.Nome = "Macoratti"
macoratti.Endereco = "Rua Projetada 100"
Console.WriteLine(macoratti.getEnderecoCompleto())
Console.ReadLine()
End Sub
Public Class Pessoa
Public Property Nome() As [String]
Public Property Endereco() As [String]
Public Function getEnderecoCompleto() As String
Return Nome + vbLf + Endereco
End Function
End Class
End Module
|
Após definir a classe Pessoa criamos um objeto do tipo Pessoa chamado macoratti usando a instrução New.
A seguir atribuímos valores para os atributos Nome e Endereco e usamos o método GeEnderecoCompleto() para exibir o nome e endereço do objeto criado.
Finalizando eu gostaria de deixar claro que haveria muita coisa para cobrir quando se discute o paradigma orientado a objetos. No entanto, espero que você tenha tido uma boa compreensão dos seguintes tópicos:
Para saber mais sobre os conceitos do paradigma da orientação a objetos na linguagem VB .NET acompanhe o curso:
|
Assim também vós, meus irmãos, fostes mortos quanto à lei mediante o corpo de Cristo, para pertencerdes a outro, àquele que ressurgiu dentre os mortos a fim de que demos fruto para Deus.
Pois, quando estávamos na carne, as paixões dos pecados, suscitadas pela lei, operavam em nossos membros para darem fruto para a morte.
Mas agora fomos libertos da lei, havendo morrido para aquilo em que estávamos retidos, para servirmos em novidade de espírito, e não na velhice da letra.
Rom 7:4-6
Referências: