Entendendo orientação a objetos

ActionScript 3.0, Orientação a Objetos, PHP, Padrões de projeto 5 Comentários »

Entre tudo o que estudei, de longe o que mais tive dificuldade em assimilar foi a orientação a objetos. Talvez por programar com o ActionScript 1.0 por alguns anos e ter toda lógica de programação voltada para o desenvolvimento estruturado. Bom, continuo estudando este paradigma, e quanto mais o estudado mais percebo a importância desta maneira de trabalhar no desenvolvimento de softwares. Como tendência todas as linguagens modernas seguem este princípio, como o ActionScript 3.0, o PHP 4 e 5, o Java, o VB.Net, o Ruby on Rails, o Python, entre outras.A orientação a objetos é um paradigma de análise, projeto e programação de sistemas de software baseado na composição e interação entre diversas unidades de software chamadas de objetos. Escrevemos código em torno de objetos e não de funções. Desta maneira, não teremos que controlar todo o processo de funcionamento do software, mas separando em grupos (classes) de responsabilidade, onde cada objeto é responsável por si próprio e tem responsabilidades (métodos) claramente definidas.Podemos entender o que são objetos sob as perspectivas de Fowler:

  • Em nível conceitual - Um objeto é um conjunto de responsabilidades. Neste nível o objeto é projetado de maneira a saber o que realizará e não como realizará.
  • Em nível de especificação - Um objeto é um conjunto de métodos (funções) que podem ser invocados por outros objetos ou por si próprio.
  • Em nível de implementação - Um objeto são código e dados. Ou seja, como realizará suas responsabilidades.

Vamos para um exemplo prático:

  1. Imagine o objeto controle remoto para televisão.
  2. Identifique quais são os objetos que compõem o controle remoto e quais suas responsabilidades:
    1. Botão Power - responsável por ligar e desligar a televisão.
    2. Botão CH+ - responsável por trocar para um canal acima do atual.
    3. Botão CH- - responsável por trocar para um canal abaixo do atual.
    4. Botão VOL+ - responsável por aumentar o volume
    5. Botao VOL- - responsável por diminuir o volume

Podemos perceber como torna-se fácil definir o que são objetos e quais suas responsabilidades dentro de um caso cotidiano e este é o principal objetivo do paradigma de orientação a objetos: tornar-se mais próxima a linguagem humana, principalmente quando falamos em nível conceitual.Mas, digamos que agora nós precisamos desenvolver um controle remoto para um aparelho de som. Poderíamos utilizar vários aspectos comuns do controle remoto para televisão, por serem comuns a todos os controles remotos, como o Botão Power, o Botão VOL + e 0 Botão VOL -. De que maneira poderiamos reutilizar o que já foi programado, agora em nível de implementação?Vamos nos aprofundar no paradigma, inicialmente como existem responsabilidades e dados comuns a qualquer controle remoto, podemos desenvolver um controle remoto geral que disponibilizará métodos associados a todos os controles remotos, podendo utilizá-los ou adaptá-los de acordo com as necessidades individuais de cada controle.Quando falamos sobre orientação a objetos, esse controle remoto geral é denominado classe, a qual deve ser entendida como definição do comportamento de um objeto. Onde teremos:

  • Os elementos de dados que o objeto contém - variáveis
  • Os métodos que o objeto pode utilizar - funções
  • A maneira como esses elementos de dados e métodos podem ser acessado - tipos de acesso

Como os elementos de dados que um objeto contém podem variar, cada objeto do mesmo tipo pode dispor de dados diferentes, mas terá a mesma funcionalidade (conforme definida nos métodos).Para obter um objeto, digo ao programa que desejo um novo objeto desse tipo ( isto é, a classe à qual pertence). Esse novo objeto é denominado como instância da classe. A criação de instâncias de uma classe é denominada instanciação.Denominamos esta classe controle remoto geral, a qual podemos chamar de ControleRemoto, também como uma classe abstrata. Em outras palavras a classe ControleRemoto é a classe-base para desenvolvimento de outras classes, denominadas classes concretas.Este tipo de relacionamento é denominado relacionamento é-um, formalmente chamado de herança. Assim podemos desenvolver a classe ControleRemotoTV e ControleRemotoSom, herdando os métodos e dados da classe abstrata ControleRemoto. Implementando as funcionalidades particulares a cada uma destas classes derivadas o que denominamos como polimorfismo.Polimorfismo, que deriva de poli (muitos) e morfi (forma). Um nome bem apropriado, visto que nos referimos a instâncias especificas de classes derivadas de classes abstratas. Sendo que, no momento que dizemos para aos objetos para fazer, conceitualmente, alguma coisa por meio de referência abstrata, obtenho um comportamento diferente, dependendo do tipo específico do objeto derivado de que disponho. Ou seja, quando pressionamos o Botão Power, dependendo do controle remoto observaremos uma ação diferente.Como os objetos são responsáveis por si próprios, existem muitas coisas que eles necessitam expor a outros objetos. Para isso, podemos implementar tipos de acesso, como principais podemos citar os seguintes:

  • Público - qualquer objeto pode vêlo
  • Protegido - apenas objetos dessa classe e de classes derivadas pdem vê-lo.
  • Privativo - apenas objetos dessa classe podêm vê-lo.

Isso nos leva ao conceito de encapsulamento. Onde os objetos não expõem seus dados, onde a visibilidade destes dados é privativa ou protegida.Como complemento abaixo um pequeno dicionário do que falamos:

  • Classe abstrata -Define os métodos e os atributos comuns a um conjunto de classes que são conceitualmente similares. Nunca são instanciadas.
  • Objeto - Uma entidade que tem responsabilidades. Implemento objetos escrevendo uma classe (em código) que define membros de dados (as variáveis associadas com os objetos) e métodos (as funções associadas com os objetos)
  • Classe - O repositório de métodos. Define os membros de dados de objetos. O código é organizado em torno da classe
  • Construtor - Método especial invocado quando um objeto é criado
  • Destruidor - Método especial invocado quando um objeto é removido
  • Superclasse - Uma classse a partir da qual outras classes são derivadas. Contém definições mestras de atributos e métodos a serem utilizados (e possivelmente redefinidos) por todas as classes derivadas
  • Classe derivada - Uma classe que é especializada a partir de sua superclasse. Contém todos os atributos (variáveis) e métodos (funções) da supeclasse; entretanto, pode conter também outros atributos ou diferentes implementações de métodos
  • Encapsulamento - Tipicamente descrito como ocultação de dados, embora seja melhor definindo como qualquer tipo de ocultação
  • Herança - Uma classe é um tipo especial de uma outra classe. Essas classes especializadas são denominadas derivações da classe-basse (a classe inicial), algumas vezes denominada superclasse; as classes derivadas, por sua vez, são eventualmente chamadas de subclasses.
  • Instância - Um exemplo particular de uma classe (é sempre um objeto)
  • Instanciação - O processo de criar uma instância de uma classe
  • Polimorfismo - Ser capaz de se referir a diferentes derivações de uma classe do mesmo modo, obtendo, porém, o comportamento apropriado da classe derivada a que se está referindo.
  • Perspectivas - Existem três diferentes perspectivas para observação de objetos: a conceitual, a de especificação e a de implementação. Essas distinções são úteis para entender o relacionamento entre classes abstratas e suas derivações. A classe abstrata define como resolver problemas conceitualmente. Ela também provê a especificação para a comunicação com qualquer objeto derivado a partir dela. Cada derivação fornece a implementação especifica necessária.

Padrões de projeto

Padrões de projeto Deixe um comentário »

Qual programador que nunca teve um tremendo medo de alterações de sistema, que normalmente surgem com um pedido do cliente por novas implementações. E qual gerente de projetos ou diretor de empresa de desenvolvimento de software que nunca ficou com os cabelos em pé ao ver várias partes do sistema serem reescritas, simplesmente por terem sido desenvolvidas ao acaso, sem seguir nenhuma regra ou processo de desenvolvimento, sem uma lógica que futuramente permitisse que o sistema fosse flexível o suficiente para ser escalonável e reaproveitado.

Este tipo de situação normalmente ocorre devido a más práticas de desenvolvimento ou mesmo por maneiras individualistas e próprias de cada programador escrever seu código, o que arruina qualquer desenvolvimento em equipe e também acarreta em desgaste dos desenvolvedores, como por exemplo na saída de um integrante da equipe. Pois aos que ficam, resta entender o que foi escrito por outra pessoa e assim poder dar manutenção ou fazer uma nova implementação num código que não foi escrito por eles, ou seja, levarão muito tempo para entender a lógica de outra pessoa e que possivelmente terá seu código reescrito, por levar menos tempo.

Mas desta forma ficamos num ciclo vicioso onde o código estará sendo reescrito cada vez que passar na mão de um novo programador.

Este processo é desgastante e extremamente desmotivador, sem falar nos prejuízos para a empresa. Mas existem diversas práticas e disciplinas para amenizar este processo, além de implantar um processo de desenvolvimento, documentando, especificando, e sobretudo projetando.

Estas práticas e disciplinas nomeamos de PADRÕES DE PROJETO, ou do inglês Design Patterns. Termo criado pelo arquiteto Christopher Alexander na década de 1970.

Os Padrões de Projeto descrevem características comuns em projetos que devem ter, idealmente, as seguintes características (WIKIPÉDIA, 2007):

  • Encapsulamento : um padrão encapsula um problema/solução bem definido. Ele deve ser independente, específico e formulado de maneira a ficar claro onde ele se aplica.
  • Generalidade : todo padrão deve permitir a construção de outras realizações a partir deste padrão.
  • Equilíbrio : quando um padrão é utilizado em uma aplicação, o equilíbrio dá a razão, relacionada com cada uma das restrições envolvidas, para cada passo do projeto. Uma análise racional que envolva uma abstração de dados empíricos, uma observação da aplicação de padrões em artefatos tradicionais, uma série convincente de exemplos e uma análise de soluções ruins ou fracassadas pode ser a forma de encontrar este equilíbrio.
  • Abstração : os padrões representam abstrações da experiência empírica ou do conhecimento cotidiano.
  • Abertura : um padrão deve permitir a sua extensão para níveis mais baixos de detalhe.
  • Combinatoriedade : os padrões são relacionados hierarquicamente. Padrões de alto nível podem ser compostos ou relacionados com padrões que endereçam problemas de nível mais baixo.

Além da definição das características de um padrão, Alexander definiu o formato que a descrição de um padrão deve ter. Ele estabeleceu que um padrão deve ser descrito em cinco partes:

  • Nome : referência que descreve de forma bastante sucinta o padrão.
  • Exemplo : uma ou mais figuras, diagramas ou descrições que ilustrem um protótipo de aplicação.
  • Contexto : a descrição das situações sob as quais o padrão se aplica.
  • Problema : (motivação, intenção e objjetiivos, aplicabilidade): apresenta o contexto do padrão e quando
    ele pode ser usado.
  • Solução : (estrutura, participantes, exemplos de código): descreve a solução e os elementos que a compõem

Além disso, os Padrões possuem características comuns quanto aos problemas que são resolvidos, possibilitando a reunião em 3 grupos, chamados também de famílias: Padrões de Criação, Padrões Estruturais e Padrões Comportamentais.

Seguiremos nos próximos posts, discutindo cada um destes grupos juntamente com o paradigma de orientação a objetos e sobre a linguagem de programação ActionScript 3.0. Todos estes serão de grande importância no nosso processo de aprendizagem de desenvolvimento com qualidade.

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Login