210 likes | 304 Views
1. Benefícios/Dificuldades da programação orientada por objectos. 2. Regras básicas de construção de software orientado por objectos. 3. Introdução à Modela ção (UML - U nified M odeling L anguage ). Uma linguagem de programação procurar seguir dois objectivos que se relacionam:
E N D
1.Benefícios/Dificuldades da programação orientada por objectos 2. Regras básicas de construção de software orientado por objectos 3. Introdução à Modelação (UML - Unified Modeling Language)
Uma linguagem de programação procurar seguir dois objectivos que se relacionam: 1. Deve fornecer ao programador meios de especificar as acções que devem ser executadas e 2. Deve ser um conjunto de conceitos que o programador possa utilizar quando pensa numa forma/método para resolver um problema O primeiro aspecto idealmente requer que a linguagem “esteja próxima da máquina”. A linguagem C foi inicialmente concebida com esta directiva O segundo aspecto idealmente requer que a linguagem “esteja mais próxima do problema a resolver”. As facilidades adicionadas ao C para criar o C++ tinham este objectivo
Idealmente, o projecto de um programa divide-se em três etapas: • 1) compreensão clara do problema • 2) identificação dos conceitos chave envolvidos na solução • 3) expressar a solução por intermédio de um programa Eu posso apresentar um conjunto de regras que vocês devem seguir enquanto aprendem C++. Não as sigam literalmente. Para escrever um bom programa é necessário inteligência, gosto/prazer e paciência.
1. Quando vocês programam, criam uma representação concreta das vossas ideias para a solução do problema. Vamos fazer com que a estrutura do programa reflicta essas ideias tão directamente quanto possível. 1.1. Podem considerar “isto” como uma ideia, criem uma classe. 1.2. Podem considerar “isto” como uma entidade, criem um objecto de uma classe. 1.3. Se duas classes têm algo significativo em comum, façam essa semelhança pertencer a uma classe base. 1.4. Se uma classe for um recipiente de objectos, façam-na um template
2. Quando definem uma classe que não implementa uma entidade matemática como uma matriz, um número complexo ou um tipo de baixo nível, como por exemplo uma lista ligada: 2.1. Não usem dados globais. 2.2. Não usem funções globais (funções que não são métodos de classes). 2.3. Não usem atributos públicos. 2.4. Não usem friends excepto para eliminar [2.1], [2.2] ou [2.3]. 2.5. Não acedam directamente aos dados ou a qualquer outro objecto. 2.6. Não usem campos que identifiquem a classe: usem funções virtuais. 2.7. Não usem funções inline a não ser que constituam uma optimização significativa.
Introdução à Modelação (UML - Unified Modeling Language) A Linguagem de Modelação Unificada é uma linguagem e uma notação para especificação, construção, visualização e documentação de modelos de sistemas de software A UML na sua versão actual 1.4 pode ser vista como um standard da indústria. Foi desenvolvida segundo a direcção de Grady Booch, Ivor Jacobson e James Rumbaugh da Rational Software A UML é uma linguagem e uma notação para modelação mas não é um método, intencionalmente. UML serve de base a vários métodos e fornece um conjunto bem definido de modelos de construção com uma notação e uma semântica uniformes
História da linguagem UML 1. História da Programação Orientada por Objectos - 35 anos. 2. O primeiro livro sobre análise e desenvolvimento desta área apareceu em 1990 (Booch, Goad, Yourdon, Rumbaugh, etc.) 3. A partir de 1990 os métodos de Grady Booch e James Rumbaugh são os mais conhecidos. 4. Em 1995 Booch e Rumbaugh criaram um método que se chama Unified Method (UM). 5. Em 1997 Booch, Rumbaugh e Jacobson criaram uma linguagem que se chama Unified Modeling Language (UML).
class class object object instance of A UML inclui uma enorme quantidade de elementos e detalhes de modelos Por exemplo, seguindo a notação UML, as classes e os objectos são representados por rectângulos. Para os diferenciar, os nomes dos objectos foram sublinhados Se pretendermos representar a relação entre classe e objecto (relação de instanciação), desenhamos uma seta a tracejado a ligar o objecto à classe, no sentido do objecto para a classe
A relação de herança é representada por uma seta a apontar sempre da classe derivada para a classe base. Este princípio é normalmente chamado generalização ou especialização Por exemplo, a classe forma é uma generalização da circunferência e a circunferência é uma especialização da forma - dependendo do ponto de vista Isto é o caso da semântica “é um(a)” (is-a): uma circunferência “é uma” forma (a circle "is a" shape). Os objectos das classes derivadas podem sempre ser utilizados em vez dos objectos da sua classe(s) base (princípio da substituição) Esta ilustração mostra a herança simples numa hierarquia de formas. Além desta iremos considerar a herança múltipla, onde uma classe pode ter mais do que uma classe base
Existem várias alternativas para a herança, como por exemplo, delegação, agregação, programação genérica (tais como as classes parameterizadas e templates C++), etc. A herança não possui uso ilimitado e nalguns casos a sua utilização nem é razoável O diagrama de classes apresenta um exemplo de generalização e especialização de formas. Voltando ao exemplo das formas: Assume-se que todas as figuras podem ser mostradas no ecrã e podem ser apagadas e deslocadas. Como estas propriedades são aplicáveis a todas as figuras, então devem ser situadas na classe forma, juntamente com os atributos que guardam a posição no ecrã e o estado de visualização As propriedades adicionadas não podem ser generalizadas; assim, o modelo é o seguinte
shape x : int y : int visible : Boolean draw() rotate() setPosition(newX, newY) Circle Rectangle Triangle radius (radius>0) a (a>0) b (b>0) setRadius(newR) setA(newA) setB(newB) Nas classes derivadas circunferência, rectângulo e triângulo, os lados (a, b, c) ou o raio são definidos, juntamente com as restrições a estes dados e funções para modificar os dados
Rectangle a (a>0) b (b>0) setA(newA) setB(newB) Square (a=b) Note que uma circunferência é desenhada de forma diferente de um triângulo. Isto justifica o facto de que as funções draw() e rotate() da classe forma devem ser abstractas. Só dentro das classes Circle, Rectangle, etc, é que se tornam funções concretas Neste diagrama a classe Square é modelada como uma classe derivada da classe Rectangle pois é um caso particular de um rectângulo. A classe Square é uma especialização da classe Rectangle : os lados a e b têm de ser iguais, o que é formulado como uma restrição. Assim, a especificação de apenas um lado é suficiente
displays Window Shape Um objecto deve estar apto a agir. De forma a expressar mecanismos de comunicação a UML possui ferramentas especiais chamadas CRC (Class-Responsibility-Collaboration). Os CRCs são usados para especificar quais as classes que uma dada classe deve cooperar Uma pré-condição para cooperação é que as instâncias de uma classe se conheçam. É o caso da relação de herança. Se não existir herança a cooperação baseia-se na associação e na agregação Uma associação é uma relação entre objectos diferentes de uma ou mais classes. Um exemplo simples é a relação entre uma janela e um conjunto de formas Num caso simples, uma associação é representada por uma linha simples entre duas classes. No entanto, normalmente as associações são representadas o mais detalhadamente possível
consist of consist of Enterprise Department Employee 1 1.. 1 1.. As associações são também chamadas relações de utilização Geralmente podemos diferenciar entre associação uni-direccional, bi-direccional e não-direccional. A UML, infelizmente, não distingue as associações bi-direccionais das não-direccionais A agregação é outro tipo de relação entre classes. Um carro, por exemplo, é uma agregação de pneus, motor, rodas motoras, travões, etc. Estas partes, por sua vez, podem ser também agregações: um travão consiste num disco, pastilhas, cilindro hidráulico, etc. Agregações são relações de “inclusão” (has): Um carro “inclui” um motor (A car "has" an engine).
A comunicação entre objectos é conseguida trocando mensagens. Os objectos enviam mensagens uns aos outros. Uma mensagem é representada por um nome de uma função com argumentos entre parêntesis (quando é necessário) e uma seta indicando o sentido da mensagem. Enquanto o diagrama de uma classe representa as relações entre as classes, os diagramas de colaboração e sequência são usados para mostrar uma operação ou situação específica. Vejamos outro exemplo de agregação: Considerem a classe CircSquare cujos objectos formam um agregado (aqui, uma sobreposição gráfica) de um quadrado e uma circunferência. CircSquare agrega uma circunferência e um rectângulo com lados iguais.
shape x : int y : int visible : Boolean CircSquare (2*c.radius = r.a = r.b) draw() rotate() setPosition(newX, newY) setA(newA) draw() rotate() resize(factor) Circle Rectangle radius (radius>0) a (a>0) b (b>0) setRadius(newR) setA(newA) setB(newB) 1 c 1 r has has Isto é uma composição porque os dois objectos, Circle e Rectangle, que formam um CircSquare estão existencialmente relacionados.
Como um CircSquare tem de conhecer os seus objectos parciais mas os objectos não necessitam de saber quais os agregados de que fazem parte, são representadas relações direccionais class CircSquare : public shape { Circle c; Rectangle r; public: void draw() { c.draw(); r.draw(); } void rotate() { c.rotate(); r.rotate(); } void setA(int newA) { c.setRadius(newA/2); r.setA(newA); r.setB(newA); } void resize(float factor) { setA(r.getA()*factor); } };
O diagrama de colaboração ou sequência reflecte um cenário e mostra as mensagens individuais entre os objectos que são necessários numa dada operação. Os seguintes dois diagramas mostram um cenário deste tipo. Um objecto da classe CircSquare recebe uma mensagem de redimensionamento, que significa que o agregado de figuras vai ser redimensionado por um factor que é especificado (por exemplo, 1.5).
:CircSquare r:Rectangle c:Circle resize(factor) getA() setA(a*factor) setRadius(newRadius) setA(newA) setB(newA) a O diagrama de sequência
A operação de redimensionamento implica a seguinte troca de mensagens: 1. O objecto CircSquare envia ao rectângulo a mensagem getA(). O rectângulo responde com o valor do comprimento actual do seu lado e CircSquare guarda-o temporariamente na variável a. 2. Posteriormente, CircSquare envia uma mensagem setA(a*factor) para ele próprio. 1.2.1. Dentro da função setA(new A), o objecto CircSquare envia primeiro uma mensagem setRadius(new A/2) à circunferência. 1.2.2. De seguida, é enviada a mensagem setA(new A) ao rectângulo 1.2.3. Seguida da mensagem setB(new A). Assim, se o comprimento inicial do lado é 12 e o factor de redimensionamento for 1.5, o raio será 9 e o novo comprimento do lado é 18.
CircSquare 1. resize(factor) 1.2: setA(a*factor) 1.1: a=getA() 1.2.2: setA(newA) 1.2.3: setB(newA) 1.2.1: setRadius(newA/2) r:Rectangle c:Circle O diagrama de colaboração