Introdução à Análise Orientada a Objetos e Projeto Arquitetural



Documentos relacionados
UNIVERSIDADE FEDERAL DO PARANÁ UFPR Bacharelado em Ciência da Computação

UML 2. Guia Prático. Gilleanes T.A. Guedes. Novatec. Obra revisada e ampliada a partir do título Guia de Consulta Rápida UML 2

Programação Estruturada e Orientada a Objetos. Fundamentos Orientação a Objetos

UNIVERSIDADE FEDERAL DO PARANÁ UFPR Bacharelado em Ciência da Computação

Análise e Projeto Orientados por Objetos

Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 03 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO)

Histórico da Orientação a Objetos Ciclo de vida de Desenvolvimento de SW

UML - Unified Modeling Language

UML 01. Curso Superior de Tecnologia em Banco de Dados Disciplina: Projeto de Banco de Dados Relacional 1 Prof.: Fernando Hadad Zaidan

Modelos de Sistema by Pearson Education. Ian Sommerville 2006 Engenharia de Software, 8ª. edição. Capítulo 8 Slide 1.

Orientação à Objetos. Aécio Costa

ENGENHARIA DE SOFTWARE I

Análise e Projeto de Software

ANÁLISE E PROJETO ORIENTADO A OBJETOS. Isac Aguiar isacaguiar.com.br isacaguiar@gmail.com

Modelagemde Software Orientadaa Objetos com UML

Wilson Moraes Góes. Novatec

Aula 2 Revisão 1. Ciclo de Vida. Processo de Desenvolvimento de SW. Processo de Desenvolvimento de SW. Processo de Desenvolvimento de SW

Tópicos em Engenharia de Software (Optativa III) AULA 2. Prof. Andrêza Leite (81 )

Modelagem OO com UML. Vítor E. Silva Souza ~ vitorsouza

do grego: arkhé (chefe ou mestre) + tékton (trabalhador ou construtor); tekhne arte ou habilidade;

2 Engenharia de Software

Eduardo Bezerra. Editora Campus/Elsevier

O que é a UML? Introdução a UML. Objetivos da Modelagem. Modelos. A UML não é. Princípios da Modelagem. O que é um modelo?

Engenharia de Software I: Análise e Projeto de Software Usando UML

Desenvolvimento de Sistemas Orientados a Objetos com UML UP/RUP: Projeto

LINGUAGENS E PARADIGMAS DE PROGRAMAÇÃO. Ciência da Computação IFSC Lages. Prof. Wilson Castello Branco Neto

Introdução à Programação. Adair Santa Catarina Curso de Ciência da Computação Unioeste Campus de Cascavel PR

A Linguagem de Modelagem Unificada (UML)

Engenharia de Software na Prática Hélio Engholm Jr.

UNIVERSIDADE DO ESTADO DE SANTA CATARINA - UDESC DCC Departamento de Ciência da Computação Joinville-SC

Modelagem de Casos de Uso (Parte 1)

Conteúdo. Disciplina: INF Engenharia de Software. Monalessa Perini Barcellos. Centro Tecnológico. Universidade Federal do Espírito Santo

Engenharia de Software: conceitos e aplicações. Prof. Tiago Eugenio de Melo, MSc tiagodemelo@gmail.com

Introdução à Engenharia de Software

Algumas propriedades dos objetos:

Processo de Desenvolvimento Unificado

Organização e Arquitetura de Computadores I. de Computadores

Na medida em que se cria um produto, o sistema de software, que será usado e mantido, nos aproximamos da engenharia.

Análise e Projeto de Sistemas de Informação. Andrêza Leite andreza.lba@gmail.com

Autoria:Aristófanes Corrêa Silva Adaptação: Alexandre César M de Oliveira

Engenharia de Software III

1 UML (UNIFIED MODELING LANGUAGE)

PROGRAMAÇÃO AVANÇADA -CONCEITOS DE ORIENTAÇÃO A OBJETOS. Prof. Angelo Augusto Frozza, M.Sc. frozza@ifc-camboriu.edu.br

Modelo Cascata ou Clássico

Unisant Anna Gestão Empresarial com ERP 2014 Modelagem de Sistemas - UML e MER

O Rational Unified Process (RUP) é um processo de desenvolvimento de software inspirado no

Hardware (Nível 0) Organização. Interface de Máquina (IM) Interface Interna de Microprogramação (IIMP)

Curso Técnico em Redes

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008

2 Diagrama de Caso de Uso

Capítulo 2. Processos de Software Pearson Prentice Hall. Todos os direitos reservados. slide 1

Modelagem de Software Prof. Flávio de Oliveira Silva, Ph.D.

Histórico da Revisão. Versão Descrição Autor. 1.0 Versão Inicial

Engenharia de Requisitos Estudo de Caso

3. PARADIGMA ORIENTADO A OBJETOS

Gerenciamento de Projetos Modulo II Ciclo de Vida e Organização do Projeto

Metodologias de Desenvolvimento de Sistemas. Analise de Sistemas I UNIPAC Rodrigo Videschi

Notas de Aula 04: Casos de uso de um sistema

Banco de Dados Aula 1 Introdução a Banco de Dados Introdução Sistema Gerenciador de Banco de Dados

Programa Analítico. Introdução. Origens da programação Orientada a Objetos. Paradigma procedural. Paradigma Orientado a Objetos.

Uma Abordagem usando PU

Desenho de Software. Desenho de Software 1

Forneça a próxima onda de inovações empresariais com o Open Network Environment

Linguagem de Programação I

UML Aspectos de projetos em Diagramas de classes

Orientação a Objetos

Engenharia de Software e Gerência de Projetos Prof. Esp. André Luís Belini Bacharel em Sistemas de Informações MBA em Gestão Estratégica de Negócios

Análise e Projeto de Sistemas. Engenharia de Software. Análise e Projeto de Sistemas. Contextualização. Perspectiva Histórica. A Evolução do Software

MÓDULO 9 METODOLOGIAS DE DESENVOLVIMENTO DE SISTEMAS

3.1 Definições Uma classe é a descrição de um tipo de objeto.

ATRIBUTOS PRIVADOS 6. ENCAPSULAMENTO MÉTODOS PRIVADOS MÉTODOS PRIVADOS

Ciclo de Vida Clássico ou Convencional CICLOS DE VIDA DE DESENVOLVIMENTO DE SISTEMAS. Ciclo de Vida Clássico ou Convencional. Enfoque Incremental

Unidade II MODELAGEM DE PROCESSOS

Programa do Módulo 2. Processo Unificado: Visão Geral

Engenharia de Software: Introdução. Mestrado em Ciência da Computação 2008 Profa. Itana Gimenes

Tarciane Andrade.

UFG - Instituto de Informática

! Introdução. " Motivação para Processos de Software. ! Processo Unificado (USDP) " Definições " RUP x USDP " Características do Processo Unificado

REVISÃO ENGENHARIA DO SOFTWARE. Isac Aguiar isacaguiar.com.br

Fábrica de Software 29/04/2015

Modelagem de Processos. Prof.: Fernando Ascani

1 INTRODUÇÃO 1.1 CONCEITO DE PARADIGMAS DE LINGUAGEM DE PROGRAMAÇÃO PARADIGMAS DE LINGUAGEM DE PROGRAMAÇÃO

AUTOR: DAVID DE MIRANDA RODRIGUES CONTATO: CURSO FIC DE PROGRAMADOR WEB VERSÃO: 1.0

Prof. Marcelo Henrique dos Santos

O Processo Unificado: Captura de requisitos

Engenharia de Software

Capítulo 11. Conceitos de Orientação a Objetos. Rui Rossi dos Santos Programação de Computadores em Java Editora NovaTerra

1

Guia de utilização da notação BPMN

Universidade Católica de Petrópolis Análise Orientada a Objetos. Introdução

Introdução à Engenharia de. Software. Introdução à Engenharia de. Software. O que é a Engenharia de Software? Software

Um Processo para Desenvolvimento de Aplicações Web Baseado em Serviços. Autores: Fábio Zaupa, Itana Gimenes, Don Cowan, Paulo Alencar e Carlos Lucena

Introdução a UML. Hélder Antero Amaral Nunes haanunes@gmail.com

INTRODUÇÃO ÀS LINGUAGENS DE PROGRAMAÇÃO

ENGENHARIA DE SOFTWARE Prof. Ricardo Rodrigues Barcelar

Resolução da lista de exercícios de casos de uso

Professor: Curso: Disciplina:

Transcrição:

Introdução à Análise Orientada a Objetos e Projeto Arquitetural Cecília Mary Fischer Rubira cmrubira@ic.unicamp.br http://www.ic.unicamp.br/ cmrubira Patrick Henrique da Silva Brito pbrito@ic.unicamp.br http://www.ic.unicamp.br/ pbrito Instituto de Computação - UNICAMP 2009

2

Sumário Sumário Lista de Tabelas Lista de Figuras i v vii 1 Introdução 1 1.1 Estruturação de Software................................. 1 1.1.1 Gerenciamento da Complexidade do Software.................. 2 1.1.2 Técnicas de Estruturação de Software...................... 2 1.1.3 Crise de Software.................................. 3 1.2 Evolução da Abstração em Linguagens de Programação................ 4 1.2.1 Desenvolvimento de Software........................... 4 1.2.2 Módulos, Pacotes e Subsistemas......................... 6 1.2.3 Tipos Abstratos de Dados............................. 8 1.2.4 Programação Orientada a Objetos........................ 8 1.2.5 Programação Orientada a Objetos vs. Programação Estruturada....... 10 1.2.6 Linguagens Orientadas a Objetos......................... 11 1.3 Fundamentos do Paradigma de Objetos......................... 12 1.3.1 O Conceito de Objeto............................... 12 1.3.2 Classes....................................... 13 1.3.3 Classificação/Instanciação............................. 14 1.3.4 Abstração de Dados e Hierarquias de Abstrações................ 15 1.3.5 Generalização/Especialização........................... 16 1.3.6 Agregação/Decomposição............................. 16 1.3.7 Associações..................................... 18 1.3.8 Dependências.................................... 19 1.4 Análise e Projeto Orientado a Objetos.......................... 19 1.4.1 Processos Tradicionais vs. Processos Orientados a Objetos........... 20 1.4.2 Limitações do Modelo de Objetos......................... 23 1.5 Engenharia de Software Baseada em Componentes................... 23 1.5.1 Componentes de Software............................. 23 1.5.2 Reusabilidade, Modularidade e Extensibilidade................. 24 1.5.3 Desenvolvimento Baseado em Componentes................... 25 1.6 Resumo........................................... 26 i

ii 1.7 Exercícios.......................................... 27 2 Modelagem de Casos de Uso 29 2.1 Introdução.......................................... 29 2.2 Casos de Usos........................................ 31 2.3 Atores e Papéis....................................... 32 2.4 Fluxo de Eventos...................................... 33 2.5 Cenários........................................... 35 2.6 Formato e Convenções para Casos de Uso........................ 36 2.7 Diagramas de Casos de Uso................................ 37 2.8 Relacionamentos entre Casos de Uso........................... 38 2.8.1 Generalização.................................... 38 2.8.2 Inclusão....................................... 39 2.8.3 Extensão...................................... 40 2.9 Método para a Modelagem de Casos de Uso....................... 41 2.9.1 Identificação de Casos de Uso Baseada em Atores................ 43 2.9.2 Identificação de Casos de Uso Baseada em Atributos.............. 45 2.9.3 Identificação de Casos de Uso Baseada em Análise de Domínio........ 45 2.9.4 Construção de um Glossário e Termos...................... 46 2.9.5 Levantamento Inicial dos Casos de Uso..................... 47 2.9.6 Descrição de Casos de Usos............................ 49 2.9.7 Gerenciamento de Casos de Uso Complexos................... 49 2.9.8 Descrições Formais de Casos de Usos....................... 50 2.9.9 Diagrama de Casos de Uso do Sistema da Biblioteca.............. 51 2.9.10 Diagrama de Atividades para Fluxo de Eventos................. 51 2.9.11 Diagramas de Interação de Sistema........................ 54 2.9.12 Início da Análise.................................. 56 2.10 Resumo........................................... 57 2.11 Exercícios.......................................... 58 3 Análise Orientada a Objetos: Modelagem Estática 63 3.1 Análise OO x Projeto OO................................. 63 3.2 Modelagem Estática x Modelagem Dinâmica...................... 64 3.3 Metodologias para Análise Orientada a Objetos..................... 65 3.3.1 OMT........................................ 66 3.3.2 RUP......................................... 67 3.4 Um Método para Análise Orientada a Objetos Usando UML............. 69 3.4.1 Técnicas para Extração de Informações..................... 70 3.5 Atividade 1: Identificar Classes de Análise........................ 72 3.5.1 Atividade 1.1: Extrair Classes Candidatas.................... 72 3.5.2 Atividade 1.2: Eliminar Classes Inapropriadas.................. 75 3.5.3 Atividade 1.3: Refinar a Lista de Classes Candidatas.............. 76 3.6 Atividade 2: Atualizar Dicionário de Dados....................... 77 3.7 Atividade 3: Identificar os relacionamentos entre as classes............... 78 3.7.1 Atividade 3.1: Identificar Associações...................... 78

iii 3.7.2 Atividade 3.2: Identificar Agregações....................... 79 3.7.3 Atividade 3.3: Identificar Herança........................ 79 3.8 Atividade 4: Identificar/Atributos das Classes de Análise............... 80 3.9 Atributos das Classes de Análise no Estudo de Caso.................. 81 3.10 Atividade 5: Iterar e Refinar............................... 82 3.10.1 Atividade 1 (iteração 2): Identificar Classes de Análise............. 82 3.10.2 Atividade 3 (Iteração 2): Identificar os Relacionamentos entre as Classes... 85 3.11 Padrões de Modelagem................................... 85 3.12 Resumo........................................... 87 3.13 Exercícios.......................................... 88 4 Modelagem Estrutural em UML 91 4.1 Objetos e Classes...................................... 91 4.1.1 Classes Concretas................................. 91 4.1.2 Instanciação de Objetos em UML......................... 92 4.1.3 Operações Construtoras.............................. 94 4.1.4 Visilibilidade de Atributo e Operação...................... 95 4.2 Tipo Abstrato de Dados.................................. 95 4.2.1 Tipos e Classes................................... 95 4.2.2 Tipos Abstratos de Dados............................. 96 4.3 Relacionamento de Agregação e Associação....................... 99 4.4 Relacionamento de Generalização............................. 101 4.4.1 Herança Simples de Classes............................ 101 4.4.2 Visibilidade Protegida de Atributos e Operações................ 103 4.4.3 Clientes por Herança e por Instanciação..................... 105 4.4.4 Herança de Implementação............................ 106 4.4.5 Herança de Comportamento............................ 110 4.4.6 Herança Múltipla.................................. 111 4.4.7 Exemplo de Herança Múltipla em UML..................... 113 4.5 Polimorfismo........................................ 115 4.5.1 O que é polimorfismo?............................... 115 4.5.2 Coerção....................................... 118 4.5.3 Sobrecarga..................................... 119 4.5.4 Polimorfismo Paramétrico............................. 119 4.5.5 Polimorfismo de Inclusão............................. 120 4.5.6 Exemplo: Pilha de Publicações.......................... 122 4.6 Classes Abstratas...................................... 123 4.6.1 Operação Abstrata vs. Operação Concreta................... 124 4.6.2 Classe Raiz, Classe Folha e Operação Folha................... 125 4.6.3 Exemplo 1: Hierarquia de Raças de Cães.................... 126 4.6.4 Exemplo 2: Hierarquia de Figuras Gráficas................... 128 4.7 Interfaces.......................................... 130 4.7.1 Relacionamento de Realização em UML..................... 131 4.7.2 Herança Simples e Múltipla entre Interfaces................... 133 4.7.3 Exemplo 1 - Integração Objeto-Relacional.................... 134

iv 4.7.4 Exemplo 2 - Alternativa à Herança Múltipla de Classes............ 135 4.7.5 Exemplo 3 - Classes, Interfaces e Tipos..................... 138 4.8 Pacotes em UML...................................... 139 4.8.1 Visibilidade de Classes, Atributos e Operações................. 142 4.9 Relacionamento de Delegação............................... 143 4.9.1 Sistemas baseados em Delegação......................... 143 4.9.2 Delegação versus Herança............................. 144 4.9.3 Delegação em Sistemas Basedos em Classes................... 145 4.9.4 O Padrão Delegação para Sistemas baseados em Classes............ 147 4.9.5 Uma Aplicação do Padrão Delegação....................... 148 4.10 Metaclasses......................................... 154 4.10.1 Exemplo de utilização de metaclasses...................... 156 4.11 Resumo........................................... 159 4.12 Exercícios.......................................... 160 5 Análise Orientada a objetos: Modelagem Dinâmica 167 5.1 Atividades da Modelagem Dinâmica........................... 168 5.2 Atividade 1: Identificar Eventos do Sistema....................... 169 5.2.1 Análise Textual do Caso de Uso Emprestar Exemplar.............. 169 5.2.2 Eventos Identificados................................ 171 5.3 Atividade 2: Construir Diagrama de seqüência para o Caso de Uso.......... 172 5.3.1 Diagrama de Seqüência de Sistema........................ 172 5.3.2 Diagrama de Seqüência Refinado......................... 173 5.4 Atividade 3: Construção de um Diagrama de Colaboração para o Sistema...... 175 5.5 Atividade 4: Atualizar interfaces públicas das classes de análise............. 176 5.6 Atividade 5: Construir Diagramas de Estados...................... 179 6 Estudo de Caso: Sistema de Caixa Automático 181 6.1 Enunciado do Problema.................................. 181 6.2 Descrição dos Casos de Uso................................ 183 6.2.1 Caso de Uso Efetuar Login............................. 183 6.2.2 Diagrama de Atividades do Caso de Uso Efetuar Login............. 184 6.2.3 Diagrama de Seqüencia do Caso de Uso Efetuar Login............. 184 6.2.4 Caso de Uso Consultar Saldo............................ 184 6.2.5 Diagrama de atividades do caso de uso Consultar Saldo............. 185 6.2.6 Diagrama de Seqüencia do Caso de Uso Consultar Saldo............ 186 6.2.7 Caso de Uso Efetuar Saque............................. 187 6.2.8 Diagrama de Atividades do Caso de Uso Efetuar Saque............. 188 6.2.9 Diagrama de Seqüência do Caso de Uso Efetuar Saque............. 188 6.2.10 Caso de Uso Efetuar Depósito........................... 189 6.2.11 Diagrama de Atividades do Caso de Uso Efetuar Depósito........... 191 6.2.12 Diagrama de Seqüencia do Caso de Uso Efetuar Depósito............ 191 6.3 Modelagem Estática.................................... 192 6.3.1 Atividade 1: Identificar as Classes de Análise.................. 192 6.3.2 Atividade 1.1: Extrair as Classes Candidatas.................. 197

v 6.3.3 Atividade 1.2: Refinar Classes Candidatas.................... 197 6.3.4 Atividade 1.3: Revisar Lista de Classes Candidatas............... 199 6.3.5 Atividade 2: Construir o Dicionário de Dados.................. 199 6.3.6 Atividade 3: Identificar os Relacionamentos entre as Classes.......... 200 6.3.7 Atividade 4: Identificação de Atributos..................... 201 6.3.8 Atividade 5 (Iteração 2): Iterar e Refinar.................... 202 6.4 Modelagem Dinâmica................................... 206 6.4.1 Passo 1: Identificar Eventos............................ 206 6.4.2 Diagramas de Seqüência.............................. 213 6.5 Diagrama de Colaboração................................. 215 6.6 Diagrama Final de Classes da Análise.......................... 215 6.7 Diagrama de Estados da Classe Conta.......................... 216 6.8 Refinamentos do Diagrama de Classes de Análise.................... 217 7 Transição da Análise OO para o Projeto OO 221 7.1 Fases do Projeto...................................... 223 7.1.1 OMT........................................ 223 7.1.2 RUP......................................... 224 7.2 Propriedades Não-Funcionais do Sistema Realizadas na Arquiteturas de Software.. 225 7.3 Visões da Arquitetura de Software............................ 226 7.4 O Padrão Arquitetural de Camadas........................... 227 7.5 Arquitetura do Sistema de Caixa Automático...................... 229 7.6 O Padrão de Projeto State................................. 232 7.6.1 Problema...................................... 233 7.6.2 Solução....................................... 233 7.6.3 Conseqüências................................... 234 7.6.4 Aplicação do Padrão State ao Sistema de Caixa Automático.......... 234 7.7 O Padrão de Projeto Singleton.............................. 238 7.7.1 Problema...................................... 238 7.7.2 Solução....................................... 238 7.7.3 Conseqüências................................... 239

vi

Lista de Tabelas 1.1 Comparação entre a Programação Estruturada e a Orientada a Objetos....... 11 2.1 Modelo Sugerido para a definição do Glossário..................... 47 2.2 Glossário dos Termos da Biblioteca............................ 47 3.1 Categorias e Entidades identificadas para o sistema da biblioteca........... 73 3.2 Atributos identificados para o sistema de bibliotecas.................. 82 4.1 Especificação Informal do TAD Pilha........................... 97 4.2 Especificação do TAD Pilha Utilizando Pré e Pós-condições.............. 99 5.1 Eventos relevantes para as Classes identificadas...................... 177 6.1 Atributos Identificados das Classes de Entidade..................... 202 7.1 Resumo das Visões do Modelo 4+1............................ 228 vii

viii

Lista de Figuras 1.1 Passos Intermediários da Modelagem da Realidade................... 5 1.2 Programação Estruturada vs. Programação Orientada a Objetos........... 10 1.3 Classificação de Wegner.................................. 11 1.4 O Conceito de Objeto................................... 13 1.5 Operações, Métodos e Atributos............................. 13 1.6 Classes e Objetos em UML................................ 14 1.7 Exemplo de Classificação/Instanciação.......................... 15 1.8 Exemplo de Generalização/Especialização........................ 17 1.9 Exemplo de Agregação/Decomposição.......................... 17 1.10 Associações em UML.................................... 19 1.11 Relacionamento de Dependência em UML........................ 19 1.12 Modelo Cascata....................................... 21 1.13 Modelo Espiral....................................... 22 1.14 Representação de um componente UML......................... 24 1.15 Diagramas de classes com Possíveis Erros de Modelagem................ 28 2.1 Casos de Uso na Especificação dos Requisitos...................... 30 2.2 Caso de Uso Emprestar Exemplar em UML........................ 32 2.3 Representação de Atores em UML............................ 33 2.4 Caso de Uso Emprestar Exemplar com seus atores.................... 33 2.5 Diagrama de Casos de Uso para o Sistema de Biblioteca................ 38 2.6 Exemplo de Generalização no Diagrama de Casos de Uso............... 39 2.7 Exemplo de Inclusão entre Casos de Uso......................... 40 2.8 Exemplo de Extensão entre Casos de Uso........................ 40 2.9 Realizações dos Casos de Uso em Modelos Diferentes.................. 42 2.10 Modelagem Alternativa do Caso de Uso Manter Dados Publicação........... 49 2.11 Pacotes de Casos de Uso.................................. 50 2.12 Diagrama de Casos de Uso do Sistema da Biblioteca.................. 52 2.13 Um Exemplo Simples de Diagrama de Atividades.................... 53 2.14 Diagrama de Atividades para o Caso de Uso Emprestar Exemplar........... 54 2.15 Diagrama de Seqüência de Sistema para um Cenário de Emprestar Exemplar..... 55 2.16 Diagrama de Colaboração de Sistema para um Cenário de Emprestar Exemplar.... 56 2.17 Modelo de Classes Preliminar para o Sistema da Biblioteca.............. 57 3.1 Estágio da Análise..................................... 66 3.2 Atividades da Modelagem Estática............................ 69 ix

x 3.3 Extração de Informações a partir do Enunciado do Problema............. 71 3.4 Diagrama de Classes Inicial de Análise.......................... 80 3.5 Diagrama de Classes Inicial de Análise (com Pacotes)................. 80 3.6 Diagrama de Classes Inicial de Análise com Relacionamentos e Atributos...... 83 3.7 Representações Gráficas para Estereótipos de Classes de Análise........... 84 3.8 Ligações Possíveis entre as Classes do Padrão MVC................... 85 3.9 Diagrama de Classes de Análise Refinado........................ 86 4.1 Classe que representa as publicações de uma biblioteca................. 92 4.2 Instanciação de dois objetos da classe Publicacao.................... 92 4.3 Criação de um Objeto................................... 93 4.4 Classe Publicacao com duas Operações Construtoras.................. 94 4.5 Estrutura de um Tipo Abstrato de Dados........................ 96 4.6 Classe Pilha, que define um TAD............................. 97 4.7 Hierarquia de Agregação de uma Biblioteca....................... 100 4.8 Diagrama de Colaboração com Propagação de Mensagem............... 101 4.9 Exemplo de Herança de Classes.............................. 102 4.10 Hierarquia de Classes de Usuários............................. 103 4.11 Hierarquia de Lista e Pilha com Herança......................... 106 4.12 Hierarquia de Lista e Pilha com Herança de Implementação.............. 108 4.13 Solução Alternativa com Agregação............................ 109 4.14 Analogia entre Supertipo/Subtipo e Conjunto/Subconjunto.............. 110 4.15 Hierarquia de Figuras Geométricas............................ 111 4.16 Problema do Diamante em Herança Múltipla...................... 112 4.17 Hierarquia de um Relógio-Calendário........................... 113 4.18 Alternativa à Herança Múltipla com Agregação..................... 115 4.19 Método Polimórfico..................................... 116 4.20 Uma Hierarquia de Tipos e Subtipos Polimórficos.................... 117 4.21 Taxonomia de Cardelli e Wegner............................. 117 4.22 Polimorfismo de Sobrecarga na Classe Publicacao.................... 119 4.23 Polimorfismo Paramétrico................................. 120 4.24 Uma Pilha de Publicações................................. 122 4.25 Um Exemplo de Polimorfismo de Inclusão com Redefinição de Operações...... 123 4.26 Exemplo de Classe Abstrata e Concreta......................... 124 4.27 Uma Hierarquia de Classes de Reserva de Publicações................. 125 4.28 Exemplo de Hierarquia de Classes............................ 126 4.29 Hierarquia de Classe para Cães.............................. 127 4.30 Hierarquia de Classes para Figuras Gráficas...................... 129 4.31 Exemplo de Interface em Sistemas Computacionais................... 130 4.32 Uma Hierarquia de Classes e Interfaces.......................... 131 4.33 Uma Interface Implementada por Duas Classes..................... 132 4.34 Uma Classe que Implementa Duas Interfaces e Estende Outra Classe......... 132 4.35 Herança Simples e Múltipla entre Interfaces....................... 133 4.36 Separação Explícita Entre Camadas de Negócios e Dados............... 134 4.37 Herança Múltipla Entre Classes.............................. 136

xi 4.38 Solução em Java Usando Interfaces............................ 136 4.39 Uma Hierarquia de Figuras Geométricas......................... 137 4.40 Uma Hierarquia Mais Complexa............................. 139 4.41 Exemplo de Organização em Pacotes........................... 140 4.42 Visibilidade de atributos e operações em UML..................... 142 4.43 Exemplo de Visibilidade de Pacote em UML....................... 143 4.44 Exemplo de Protótipos Geométricos........................... 144 4.45 Delegação de mensagens entre protótipos........................ 145 4.46 Figuras Geométricas baseadas em Classes........................ 146 4.47 Implementação de Delegação em Linguagens Baseadas em Classes.......... 147 4.48 Representação Explícita dos Estados da Publicação................... 150 4.49 Estrutura do Padrão de Projeto State.......................... 151 4.50 Padrão state Aplicado na Hierarquia de Publicações.................. 152 4.51 O Conceito de Metaclasse................................. 154 4.52 Fusão de Metaclasse com Classe............................ 155 4.53 Metaclasses......................................... 155 4.54 Atributos e métodos de classe............................... 156 4.55 Solução com Atributos e Métodos Estáticos....................... 156 4.56 O Padrão de Projeto Factory Method........................... 159 4.57 Especialização da Classe Pessoa em Duas Dimensões.................. 161 4.58 Hierarquia de Classes de um Buffer............................ 164 4.59 Sistema de Controle de Consultas............................. 164 4.60 Hierarquia de Cômodos de um Hotel........................... 165 5.1 Extração de Informações a partir do Enunciado do Problema............. 169 5.2 Diagrama de seqüência de Sistema............................ 173 5.3 Diagrama de seqüência Refinado............................. 174 5.4 Diagrama de Colaboração................................. 176 5.5 Diagrama de Classes de Análise com Operações..................... 178 5.6 Um Diagrama de Estados UML.............................. 179 5.7 Diagrama de Estados para a Classe Usuário....................... 180 6.1 Sistema de Caixa Automático............................... 182 6.2 Diagrama de atividades para o caso de uso Efetuar Login................ 184 6.3 Diagrama de seqüência do caso de uso Efetuar Login.................. 185 6.4 Diagrama de atividades para o caso de uso Consultar Saldo............... 186 6.5 Diagrama de seqüência do caso de uso Consultar Saldo................. 187 6.6 Diagrama de atividades para o caso de uso Efetuar Saque................ 189 6.7 Diagrama de seqüência do caso de uso Efetuar Saque.................. 190 6.8 Diagrama de atividades para o caso de uso Efetuar Depósito.............. 191 6.9 Diagrama de seqüência do caso de uso Efetuar Depósito................. 192 6.10 Atividades simplificadas da análise textual........................ 193 6.11 Diagrama inicial de classes com agregações........................ 200 6.12 Diagrama inicial de classes com pacote.......................... 200 6.13 Identificação dos relacionamentos entre as classes..................... 201

xii 6.14 Diagrama inicial de classes de análise com atributos................... 202 6.15 Diagrama de classes final de análise (sem operações).................. 205 6.16 Atividades da Modelagem Dinâmica........................... 206 6.17 Diagrama de seqüência Efetuar Login........................... 214 6.18 Diagrama de seqüência Consultar Saldo.......................... 214 6.19 Diagrama de seqüência Efetuar Saque........................... 215 6.20 Diagrama de seqüência Efetuar Depósito......................... 216 6.21 Diagrama de colaboração................................. 216 6.22 Diagrama de Classes de Análise com Operações..................... 217 6.23 Diagrama de Estados da Classe Conta.......................... 218 6.24 Nova hierarquia para contas................................ 218 6.25 Hierarquia de contas revisada................................ 218 7.1 Realização do caso de uso Efetuar Saque durante a análise................ 222 7.2 O modelo 4+1 para a representação de arquiteturas de software............ 228 7.3 Subsistemas do Sistema de Caixa Automático Visão Lógica.............. 230 7.4 Mapeamento inicial entre as classes de análise e as classes de projeto.......... 232 7.5 Divisão das classes de projeto entre as camadas da arquitetura............. 232 7.6 Estrutura do Padrão State................................. 233 7.7 Modelagem simplificada.................................. 234 7.8 Modelagem usando o padrão State............................ 235 7.9 Estrutura do Padrão Singleton.............................. 239

Capítulo 1 Introdução Este capítulo define e discute vários conceitos fundamentais do modelo de objetos. A evolução das técnicas de programação e das abstrações nas linguagens de programação são apresentados de como uma mudança crescente na forma de desenvolver software. O paradigma de programação procedural (ou imperativo) e o paradigma orientado a objetos são comparados e as novas estruturas abstratas do modelo de objetos são apresentadas. Finalmente, o capítulo apresenta algumas das principais limitações do modelo de objetos e como a engenharia de software baseada em componentes tenta superá-las. 1.1 Estruturação de Software Sistemas de software modernos requerem um alto grau de confiabilidade, disponibilidade e segurança. Alguns exemplos são sistemas de controle para centrais telefônicas, sistemas bancários, sistemas financeiros sistemas de e-banking, etc. Entretanto, a construção de sistemas de software complexos é uma tarefa difícil que exige o emprego de técnicas especializadas durante todo o ciclo de vida do sistema. O modelo de objetos apresenta-se como um modelo promissor para o desenvolvimento de software confiável e robusto devido a características inerentes ao próprio modelo de objetos, tais como, abstração de dados, encapsulamento, herança e reutilização de objetos (classes e componentes). O uso de técnicas orientadas a objetos facilita o controle da complexidade do sistema, uma vez que promove uma melhor estruturação de suas partes. Além disso, o seu uso permite que elementos de software já validados sejam reutilizados, promovendo a reutilização dos casos de teste. 1

2 Capítulo 1: Introdução 1.1.1 Gerenciamento da Complexidade do Software Sistemas de software são intrinsicamente complicados e têm se tornado mais complicados ainda com os novos requisitos impostos pelas aplicações modernas: alta confiabilidade, alto desempenho, desenvolvimento rápido e barato, tudo isso associado a uma complexidade de funcionalidade crescente. É possível, e muitas vezes até desejável, ignorar a complexidade dos sistemas de software, mas isso não resolve totalmente o problema; pois ela certamente aparecerá em algum outro lugar. Aplicações de software que tratam de problemas complicados devem lidar com tal complexidade em alguma hora. Como seres humanos, nós empregamos vários mecanismos para gerenciar essa complexidade, tais como abstração, generalização e agregação. Abstração é um meio pelo qual evitamos a complexidade não desejada e é uma das ferramentas mais eficientes para lidarmos com o nosso mundo complexo. Cientistas de computação já reconheceram há algum tempo que a chave para o sucesso no desenvolvimento de software está no controle da sua complexidade. O conceito de linguagens de programação de alto nível e seus compiladores foi um grande passo em direção a este objetivo, pois proporcionou uma abstração do funcionamento interno do computador, permitindo que o desenvolvedor de software programasse sem precisar ser um especialista no funcionamento do hardware utilizado. Depois disso, os pesquisadores e profissionais começaram a reconhecer a necessidade de melhores processos e ferramentas para gerenciar a complexidade; como conseqüência, surgiram os conceitos de programação estruturada e bibliotecas de programas. Embora essas contribuições tenham sido valiosas, elas ainda deixam muito a desejar em termos de reutilização de software. Em outras palavras, existe uma complexidade ainda maior do que simplesmente tentar minimizar a complexidade local de cada parte de um programa. Um tipo de complexidade mais importante está relacionada com a complexidade da sua organização global: a macro complexidade da estrutura de um programa ou sistema (i.e., o grau de associação ou interdependência entre as principais partes de um programa). A estrutura dos módulos do sistema e a comunicação entre eles é representada pela arquitetura de software. Esse conceito será visto no Capítulo 7 (Seção 7.2). Podemos dizer que a complexidade de um componente ou subsistema de software é alguma medida do esforço mental requerido para entendê-lo. De uma forma mais pragmática, ela é função dos relacionamentos entre os diversos elementos do sistema. Complexidade é um dos principais fatores que contribui para que a produção de software seja de baixa qualidade. 1.1.2 Técnicas de Estruturação de Software Uma diferença visível entre uma organização de programa bem estruturada e uma organização mal estruturada está na complexidade. Alguns conceitos da teoria geral de sistemas podem ser aplicados para reduzir a complexidade de sistemas de software, a saber [37]: (i) particionamento de sistemas em partes que sejam muito bem delimitadas, procedimento conhecido por modularização do sistema; (ii) representação do sistema como uma hierarquia com separação de níveis de abstração, que proporcionam uma visão hierárquica do sistema; (iii) maximização da independência entre

Capítulo 1: Introdução 3 as partes do sistema, que proporciona o baixo acoplamento entre os elementos do sistema; e o (iv) agrupamento das partes inter-relacionadas do sistema, o que reduz a necessidade de troca de mensagens entre as partes do sistema, nesse caso, dizemos que o sistema possui alta coesão. O particionamento de um programa em componentes menores e individuais pode reduzir a sua complexidade até certo ponto. Uma justificativa plausível para essa redução é o fato do particionamento criar um número de interfaces bem definidas dentro do modelo, isto é, as interações entre os módulos seguem listas pré-definidas, com as operações de cada módulo. Essas interfaces são muito úteis para o entendimento do programa, uma vez que mostram quais elementos são relevantes e quais não são em determinados contextos, estreitando o foco de atenção. Em outras palavras, a interface esconde informação irrelevante atrás dela, sendo considerada um importante mecanismo de abstração. O conceito de hierarquia é de vital importância tanto para o entendimento quanto para a construção de sistemas. Pelo fato da mente humana ter um limite pequeno para o número de fatos com os quais pode lidar simultaneamente, nós podemos entender melhor os sistemas que estão definidos de forma hierárquica [43]. Hierarquias permitem a estratificação de um sistema em vários níveis de detalhes. Cada camada (ou nível) abstrai os detalhes representados nas camadas inferiores. O conceito de camada facilita o entendimento do sistema, uma vez que possibilita o ocultamento de níveis de detalhes desnecessários. Embora o particionamento e a estrutura hierárquica sejam conceitos muito importantes na estruturação de sistemas, existe um terceiro conceito relacionado que é igualmente importante: independência. Este conceito implica na maximização da independência de cada componente do sistema para que a sua complexidade seja reduzida. Portanto, o problema não é meramente particionar um programa numa hierarquia, mas determinar como particionar um programa numa estrutura hierárquica de tal forma que cada subsistema seja tão independente dos outros quanto possível. Portanto, modularidade pode ser definida como a propriedade de um sistema que foi decomposto num conjunto de módulos fracamente acoplados e altamente coesos. Outra noção muito importante relacionada com as três discutidas anteriormente é o da representação explícita das inter-conexões entre os componentes do sistema [36]. Esse foco na interação entre os componentes, além de facilitar o entendimento, possibilita uma definição clara de protocolos de comunicação entre eles. Essas vantagens são percebidas mais claramente em sistemas de grande porte, onde é comum a ocorrência de efeitos colaterais decorrentes da falta de clareza desses inter-relacionamentos. 1.1.3 Crise de Software O termo Crise de Software 1 foi cunhado na Conferência de Engenharia de Software da OTAN em 1968, na Europa. Naquela época concluiu-se que os métodos de produção de software não eram adequados para as necessidades crescentes das indústrias de defesa e de processamento de dados. Vários problemas foram identificados nos sistemas de software produzidos na época, por exemplo, 1 do inglês software crisis

4 Capítulo 1: Introdução eles eram pouco predizíveis, apresentavam uma baixa qualidade, tinham alto custo de manutenção e havia muita duplicação de esforços em sua construção. Os processos subseqüentes foram tentativas de superar essa crise de software. Entretanto, apesar da proliferação dos processos de análise e de projeto, existem várias evidências de que muitos projetos de software ainda são entregues atrasados, com o orçamento estourado e com a especificação incompleta. Nesse contexto, surge o modelo de objetos que, embora nos ofereça novas ferramentas e uma abordagem mais moderna para desenvolvimento de software, é considerado mais uma abordagem evolucionária do que revolucionária, no sentido de que o modelo engloba conceitos bem conhecidos, inovando principalmente na maneira como são estruturados e utilizados. Os benefícios advindos do emprego do modelo de objetos são vários, por exemplo, abstração de dados/encapsulamento, modularidade, reutilização, maior facilidade de extensão e manutenção. 1.2 Evolução da Abstração em Linguagens de Programação 1.2.1 Desenvolvimento de Software Muitos pesquisadores reconhecem que existe um relacionamento muito próximo entre os pensamentos e a linguagem humana usada para expressá-los. De fato, a natureza da linguagem modela e dá forma aos nossos pensamentos e vice-versa: linguagem e pensamento modelam mutuamente um ao outro e não há uma precedência entre eles. A relação entre programas de software e a linguagem de programação usada para desenvolvê-los é semelhante [20]. Por esse motivo, as linguagens de programação são as representações abstratas mais comuns em computação. Entretanto, é difícil transformar as abstrações do mundo diretamente nas abstrações de uma linguagem de programação sem ser necessário passar por passos intermediários, como apresentado na Figura 1.1. Neste caso, notações gráficas intermediárias são úteis para ajudar o programador na representação das suas abstrações para a linguagem. Podemos, então, definir desenvolvimento de software como um processo através do qual nós refinamos transformações sucessivas de uma representação de alto nível para uma representação de mais baixo nível executável num computador. Conseqüentemente, o processo inteiro é dependente das facilidades para a representação de abstrações disponíveis na linguagem de programação alvo. Se a linguagem restringe de alguma forma o modo como as abstrações podem ser definidas, ela certamente limitará a modelagem das aplicações. A construção descendente 2 é uma técnica útil que requer que uma aplicação seja projetada considerando inicialmente sua macro-estrutura como um todo. Nos passos seguintes do desenvolvimento, esta estrutura é detalhada até que uma implementação seja produzida. O refinamento passo-a-passo( do inglês stepwise refinement) proporciona uma estratégia para a realização desse detalhamento [7, 39]. De fato, o processo de refinamento passo-a-passo acontece até que a solução do problema se torne um programa. Este processo considera cada subproblema como um prob- 2 do inglês top-down

Capítulo 1: Introdução 5 Figura 1.1: Passos Intermediários da Modelagem da Realidade lema separado, cria uma descrição de alto nível para ele e então refina-o em termos de outros subproblemas. A abordagem descendente é uma disciplina de Engenharia de Software madura na qual foram baseados diversos processos de projeto estruturado durante os últimos 30 anos. Como será visto na Seção 1.2, processos de análise e projeto Orientado a Objetos apresentam uma alternativa para esta abordagem convencional, especialmente quando tratamos de sistemas grandes e complexos. No início do desenvolvimento de linguagens de programação, linguagens de montagem permitiam aos projetistas escrever programas baseados em instruções de máquina (operadores) que manipulavam os conteúdos das locações de memória (operandos). Portanto, as abstrações de dados e controle eram de muito baixo nível. Um grande passo de evolução ocorreu quando surgiram as primeiras grandes linguagens de programação imperativas (Fortran e Cobol). Fortran foi importante porque introduziu a noção de subprogramas (funções e procedimentos), enquanto Cobol introduziu a noção de descrição de dados. Subseqüentemente, Algol-60 introduziu o conceito de estrutura de bloco, procedimento, etc. Ela influenciou fortemente numerosas linguagens de programação que foram chamadas linguagens baseadas em Algol. A filosofia de Algol-68 consistia da escolha de um conjunto adequado de mecanismos que deveriam ser combinados sistematicamente. Apesar da importância de Algol-60 para a evolução das linguagens de programação, foi Pascal que tornou-se a linguagem de programação mais popular, principalmente por causa da sua simplicidade, sistemática e eficiência de implementação. As duas linguagens possuem estruturas de controle ricas e definições de tipos e estruturas de dados, seguindo as idéias da programação estruturada criadas por Wirth, Dijkstra and Hoare [16].

6 Capítulo 1: Introdução 1.2.2 Módulos, Pacotes e Subsistemas Desde os anos 70, as linguagens têm se preocupado em dar mais suporte para programação em larga escala. Este tipo de programação (complementar à programação em pequena e média escala) preocupa-se com a construção de programas grandes a partir de módulos. Um módulo é uma unidade de programa que pode ser implementado de uma maneira mais ou menos independente dos outros módulos. Um módulo bem projetado tem um propósito bem definido, assim como suas interfaces de comunicação com outros módulos. Tal módulo é considerado reutilizável, quando tem grande chance de ser reutilizado, podendo ser incorporado a vários programas; e modificável, quando pode ser alterado sem causar grandes mudanças em outros módulos relacionados. A disciplina do ocultamento da informação, também conhecida como encapsulamento, foi proposta por Parnas [38], por volta de 1972 e sua idéia era encapsular variáveis globais em um módulo juntamente com o grupo de operações que tinham acesso direto a elas. Outros módulos podiam acessar essas variáveis somente indiretamente, através das operações oferecidas pelos módulos. Somente o que o módulo faz é passado para o seu cliente; o como é implementado somente diz respeito ao implementador do módulo. Se um módulo é implementado desta forma, é dito que esse módulo encapsula seus componentes. Para a obtenção de uma interface bem definida, um módulo tipicamente faz com que apenas um número pequeno de componentes sejam visíveis para os clientes externos. Tais componentes são exportados pelo módulo, enquanto muitos outros componentes permanecem ocultos dentro dele. Portanto, encapsulamento sugere que à medida que uma estrutura de dados deve residir dentro de um módulo, uma interface oferece o acesso necessário a tais estruturas para módulos externos. Em resumo, o encapsulamento minimiza as inter-dependências entre módulos escritos separadamente através da definição de interfaces estritas. Um conceito semelhante aos módulos é o que conhecemos como subsistemas. Um subsistema pode ser visto como um tipo particular de módulo que, por ser auto-contido, pode oferecer seus serviços sem necessitar interagir com o meio externo. Seguindo esse raciocínio, um sistema pode ser visto como um subsistema de um outro sistema maior. Existem pelo menos três mecanismos de linguagens de programação que dão apoio à modularização: (i) módulos, como implementados em Modula-2; (ii) pacotes, como implementado em Ada, Java [3] e C# [24]; e (iii) tipo abstrato de dados, tipos definidos indiretamente através de suas operações. Um módulo consiste de duas partes relacionadas: (i) especificação do módulo, chamada de spec e (ii) implementação do módulo, chamada de body. Enquanto a parte spec contém um conjunto de declarações de estruturas de dados e assinaturas de procedimentos, a parte body contém as implementações declaradas na spec. Cada entidade declarada na spec deve estar implementada no body. Entretanto, o body pode conter estruturas de dados e procedimentos adicionais usados para implementar as entidades visíveis. Essas entidades adicionais declaradas apenas no body devem ser privadas, sendo invisíveis aos clientes da spec, a fim de não interferir na interface oferecida pelo módulo. O trecho de código a seguir apresenta um exemplo de implementado do módulo stack na linguagem ADA. Esse módulo representa a estrutura de uma pilha. As linhas de 1 a 6 apresentam

Capítulo 1: Introdução 7 a especificação da pilha, que através das operações públicas Push(...) e Pop(...) (Linhas 4 e 5), se comunicam com os módulos externos. Além disso, a especificação define uma variável que representa a capacidade máxima da pilha (Linha 2). A implementação da pilha (body, linhas de 9 a 29) define o comportamento das operações da pilha (Linhas 14 a 28) e além disso, define um tipo Table (Linha 10) e duas variáveis internas (Linhas 11 e 12), invisíveis externamente. 1 especificação 2 Size : Positive ; 3 package Stack i s 4 procedure Push(E : in Integer ) ; 5 procedure Pop (E : out Integer ) ; 6 end Stack ; 7 8 implementação 9 package body Stack i s 10 type Table is array ( Positive range <>) of Integer ; 11 Space : Table (1.. Size ) ; 12 Index : Natural := 0; 13 14 procedure Push(E : in Integer ) is 15 begin 16 if Index < Size then 17 Index := Index + 1; 18 Space ( Index ) := E; 19 end if ; 20 end Push ; 21 22 procedure Pop(E : out Integer ) is 23 begin 24 if Index > 0 then 25 E := Space ( Index ) ; 26 Index := Index 1; 27 end if ; 28 end Pop ; 29 end Stack ; A maioria das linguagens de programação atuais utilizam o conceito de pacotes, discutido em maiores detalhes na Seção 4.8 do Capítulo 4, de uma maneira mais genérica que em ADA. A principal diferença entre esses dois conceitos de pacotes é que enquanto em ADA há uma separação

8 Capítulo 1: Introdução explícita entre especificação e implementação, em linguagens como Java e C# os pacotes determinam apenas espaço de nomes, deixando a critério dos desenvolvedores separar ou não a especificação da implementação. Os espaços de nomes são utilizados como um mecanismo para organizar elementos em grupos hierárquicos, podendo controlar inclusive quais elementos são visíveis externamente. A questão da visibilidade em orientação a objetos será abordada em detalhes na Seção 4.8.1 do Capítulo 4. 1.2.3 Tipos Abstratos de Dados A noção de tipos abstratos de dados (TAD) se refere ao encapsulamento de uma estrutura de dados juntamente com as operações que manipulam essas estruturas dentro de uma região protegida. Uma linguagem dá apoio a tipos abstratos de dados quando ela possui mecanismos que permitem a sua representação diretamente. Linguagens de programação como Ada e Modula-2 dão apoio a tipos abstratos de dados, mas ainda têm certas limitações. As principais são: (i) o sistema de tipos é unidimensional, ou seja, um programa é desenvolvido como um conjunto de tipos abstratos de dados cuja estrutura é definida no nível horizontal: as hierarquias de generalização/especialização não podem ser representadas explicitamente. (ii) tipos abstratos de dados não são representados explicitamente em tempo de execução, isto é, embora tipos abstratos de dados sejam úteis durante as fases de análise, projeto e implementação, eles desaparecem durante o tempo de execução e o software se torna de novo um monte de linhas de código agrupadas em módulos completamente desestruturados. No exemplo do módulo de pilha apresentado anteriormente, o TAD Stack seria definido pelas operações públicas Push(...) e Pop(...), além da variável pública Size, declarada na especificação do módulo. 1.2.4 Programação Orientada a Objetos O próximo passo da evolução das linguagens de programação foi introduzido com o conceito de objetos, criado por Dahl e Nygaard com a linguagem Simula-67 [17], e consolidado com a linguagem Smalltalk-76. Simula-67 introduziu os conceitos de classe, objeto e herança. O modelo clássico de objetos emprega classes para a descrição de objetos. Essas classes contém a definição da estrutura dos objetos (i.e. dados e funções). Além disso, através dos mecanismos de herança e agregação, classes já existentes podem compartilhar seu comportamento com novas classes. Essencialmente, o modelo de objetos trata dados e funções como aspectos indivisíveis no domínio do problema. O forte relacionamento entre o modelo de objetos e a noção de tipo abstrato de dados se torna evidente, uma vez que os objetos podem ser vistos como instâncias de tipos abstrato de dados. Na verdade, na maioria das linguagens orientadas a objetos, a definição de uma classe descreve um tipo de dados associado com as operações que podem ser executadas nas instâncias desse tipo.

Capítulo 1: Introdução 9 Fazendo um panorama histórico, destacamos seis acontecimentos principais que marcaram a criação do modelo de objetos. O primeiro deles, que já foi relatado anteriormente a introdução do conceito de objetos no ano de 1967, lançamento da linguagem Simula-67. Em seguida, em 1972 Dahl escreveu um artigo sobre ocultamento de informações. Apesar de nesta etapa da história o conceito de objetos já estar bem definido, apenas em 1976, com o lançamento da primeira versão do Smalltalk a orientação a objetos foi consolidada. A partir daí, o modelo de objetos evoluiu no sentido de oferecer novas linguagens de programação. Em 1983 foi disponibilizada a primeira versão do C++, versão orientada a objetos da disseminada linguagem C. Em 1988, foi lançada a linguagem Eiffel, a primeira linguagem considerada orientada a objetos pura. Finalmente, já no final do século XX, mais precisamente no ano de 1995, foi lançada a primeira versão da linguagem Java, uma linguagem orientada a objetos pura, baseada na sua antecessora C++. Programação orientada a objetos é um modelo de programação baseado em conceitos, tais como objetos, classes, tipos, ocultamento da informação, herança, polimorfismo e parametrização. Análise e projeto orientados a objetos oferecem uma maneira de usar todos esses conceitos para a estruturação e construção de sistemas. Esses conceitos são intrinsicamente independentes de linguagens e cada uma tem sua própria maneira de implementá-los. A essência da programação orientada a objetos é a resolução de problemas baseada na identificação de objetos do mundo real pertencentes ao domínio da aplicação e no processamento requerido por esses objetos, através de interações entre eles. Esta idéia de programas simulando o mundo real cresceu com o lançamento do Simula-67, que inicialmente foi projetada para o desenvolvimento de aplicações de simulação. Devido ao fato do mundo estar povoado de objetos, uma simulação de tal mundo deveria conter objetos simulados capazes de enviar e receber mensagens e reagir às mensagens recebidas. Conseqüentemente, na programação orientada a objetos, a execução de um programa consiste de um conjunto de objetos relacionados que trocam mensagens entre si, isto é, que se comunicam através da execução das operações uns dos outros. Cada objeto tem um estado interno composto por atributos que são modificados mediante a recepção e o envio de mensagens. Programas são construídos através da definição de classes, que se relacionam e formam hierarquias de abstração (Seção 1.3.4). Este estilo de programação tem algumas características positivas, por exemplo: (i) modularidade, (ii) suporte explícito para refatorar os grupos comuns, (iii) visão unificada de dados e operações, e (iv) desenvolvimento incremental e evolucionário. Muito do interesse no modelo de objetos é uma conseqüência da melhor estruturação do sistema e do encapsulamento entre dados e funções, o que auxilia principalmente na construção de programas complexos. Embora as especulações sobre o aumento da reutilização não tenham se mostrado reais, a estruturação do raciocínio e o menor acoplamento proporcionado pelo conceito de objetos melhoram a qualidade do produto final e reduzem os custos de manutenção do sistema. Ao longo deste livro, diversos diagramas representando aspectos diferentes de sistemas de software orientados a objetos são apresentados. Todos estes diagramas seguem uma notação gráfica chamada UML (sigla do inglês Unified Modeling Language) [9], na sua versão 2.0. A linguagem UML é uma linguagem para especificar sistemas orientados a objetos que se tornou um padrão tanto na indústria quanto na academia. A linguagem UML unifica as notações propostas pelos

10 Capítulo 1: Introdução processos de Rumbaugh (OMT) [40], Booch [49] e Jacobson [25] e é independente do processo ou linguagem de programação adotados. Ela foi padronizada por um comitê internacional que lida com tecnologias orientadas a objetos chamado Object Management Group (OMG). A linguagem UML é uma linguagem de modelagem, não um processo. 1.2.5 Programação Orientada a Objetos vs. Programação Estruturada Para a resolução de problemas, a abordagem estruturada utiliza uma técnica conhecida como decomposição funcional. Dessa forma, uma operação complexa é dividida em operações menores e assim sucessivamente, até atingir um nível de detalhes que possa ser implementado facilmente. Dessa forma, as funções assumem um papel central no desenvolvimento, que recebem dados de entrada e produzem dados de saída. Apesar da estreita relação entre dados e funções, nas linguagens estruturadas esses dois conceitos são completamente disjuntos, tratando cada um deles de uma maneira particular. Por essa razão, os processos estruturados de desenvolvimento de software exigem mudanças de contexto constantes, o que dificulta o mapeamento dos artefatos de diferentes fases do desenvolvimento. O encapsulamento de dados e funções, decorrente do conceito de objetos e classes foi um grande passo para a homogenização do raciocínio e a redução da complexidade dos sistemas. Com essa visão unificada, a idéia central passa a ser a decomposição de dados, ao invés da decomposição funcional. As funções se tornam ligadas a um modelo de dados, que juntos formam o conceito de classe. Em OO, as classes desempenham um papel semelhante aos módulos da programação estruturada, com a vantagem de garantir a coesão entre elementos agrupados (dados e funções). A Figura 1.2 explicita a diferença estrutural existente entre a programação estruturada e a programação orientada a objetos. Paradigma Estruturado Paradigma OO procedimentos A( ) B( ) C( ) D( ) E( ) dados i j D() Variáveis locais Objeto 4 (tipo T4) Objeto 3 (tipo T3) C() Variáveis locais interface pública A() Variáveis locais B() Variáveis locais Objeto 2 (tipo T2) Objeto 1 (tipo T1) Figura 1.2: Programação Estruturada vs. Programação Orientada a Objetos Apesar das particularidades de cada uma delas, existem algumas similaridades entre a programação estruturada e a programação orientada a objetos. A Tabela 1.1 traça um paralelo entre