Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2016-2017 (rascunho): Difference between revisions

From Wiki**3

< Programação com Objectos‎ | Projecto de Programação com Objectos
 
(121 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{PRJPOAvisosEN20162017}}
#REDIRECT [[ist:Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2016-2017 (rascunho)]]
{{PRJPOMandatory20162017}}
{{TOCright}}
<!--'''<font color="red">ÉPOCA NORMAL</font>'''-->
 
O objectivo do projecto é criar uma aplicação que permite ver e gerir um conjunto de expressões.
 
Neste texto que se segue, o tipo '''negrito''' indica um literal (i.e., é exactamente como apesentado); o símbolo <amsmath>\verb*| |</amsmath> indica um espaço; e o tipo ''itálico'' indica uma parte variável (i.e., uma descrição).
 
= Funcionalidade da Calculadora =
 
A calculadora permite interpretar e avaliar expressões. Possui também várias formas de preservar o seu estado.
 
== Interpretação de expressões ==
 
As expressões, apresentadas à calculadora em forma de texto, devem ser interpretadas antes de serem armazenadas. O texto original não é preservado.
 
O texto de uma expressão a interpretar pode ser providenciado via interface da própria calculadora ou na forma de um ficheiro que contém a expressão.
 
A falha de interpretação de uma expressão causa o lançamento da excepção '''pex.ParserException'''.
 
== Armazenamento de expressões ==
 
A calculadora permite associar expressões a identificadores, preservando-as. Note-se que isto não corresponde a guardar o valor da expressão, mas a guardar toda a informação sobre a expressão, resultante da interpretação da forma textual. Se o identificador já estever em uso, a associação à expressão anterior é perdida.
 
A calculadora permite, dado um identificador, recuperar a expressão a ele associada. Se o identificador não tiver sido definido, o valor nulo é retornado e o identificador mantém-se indefinido.
 
Os identificadores definidos na calculadora podem ser utilizados na escrita de novas expressões, antes ou depois de terem sido definidos (são sempre avaliados quando a expressão onde ocorrem é avaliada, i.e., não são "expandidos" quando a expressão onde ocorrem é interpretada).
 
== Avaliação de expressões ==
 
A avaliação de expressões guardadas na calculadora é feita de forma flexível, sendo possível -- sem alterar o código das expressões ou da calculadora -- definir novas formas de avaliação. O avaliador por omissão calcula simplesmente o valor de uma expressão.
 
Uma outra "avaliação" possível é a produção de descrições textuais a partir de expressões (isto permite recuperar a forma inicial das expressões).
 
== Escrita textual ==
 
É possível escrever todo o conteúdo da calculadora como uma sequência de atribuições de expressões a identificadores (ficheiro textual). Desta forma, o resultado da avaliação dessa sequência é indistinguível do conteúdo original da calculadora.
 
== Serialização ==
 
É possível reiniciar, guardar e recuperar a sessão de interacção com o utilizador.
 
= Estrutura de uma expressão =
 
Uma expressão é uma representação algébrica de uma quantidade: todas as expressões têm um tipo e devolvem um valor.
 
Uma expressão pode ser descrita por uma linguagem cuja interpretação resulta na representação dessa expressão como uma estrutura de dados, sobre a qual pode ser executado o processo de avaliação, para determinação do valor da expressão.
 
Neste documento utiliza-se uma linguagem simples e uniforme para descrever qualquer expressão, que pode ser categorizada como expressão primitiva (literais e identificadores) ou como expressão composta (operadores).
 
== Expressões primitivas ==
 
As expressões primitivas, ou representam directamente um valor (expressões literais), ou referem outra expressão (identificadores).
 
===Literais===
 
As expressões literais são de três tipos: inteiros, reais e cadeias de caracteres.
 
* Um literal inteiro é um número não negativo. Literais inteiros decimais são constituídos por sequências de 1 (um) ou mais dígitos de '''0''' a '''9'''. Exemplos: '''1''', '''23'''
* Um literal reais é expressos em notação científica (tal como em C). Um literal sem '''.''' (ponto decimal) nem parte exponencial é do tipo inteiro. Exemplos: '''12.34e-24''' = 12.34 x 10<sup>-24</sup>.
* As cadeias de caracteres são delimitadas por aspas ('''"''') e podem conter quaisquer caracteres. É possível designar caracteres por sequências especiais (iniciadas por '''\'''), especialmente úteis quando não existe representação gráfica directa. As sequências especiais correspondem aos caracteres [[wp:ASCII|ASCII]] LF, CR e HT ('''\n''', '''\r''' e '''\t''', respectivamente), aspa ('''\"'''), barra ('''\\'''). Exemplos: '''"hello, world!\n"''', '''"abcd"'''.
 
=== Identificadores ===
 
São iniciados por uma letra, seguindo-se 0 (zero) ou mais letras ou dígitos. O comprimento do nome é ilimitado e dois nomes são distintos se houver alteração de maiúscula para minúscula, ou vice-versa, de pelo menos um carácter.
 
== Expressões compostas ==
 
Os valores das expressões compostas correspondem à avaliação de um operador sobre os seus argumentos. O tipo de argumentos e de resultado depende do operador: alguns operadores podem aceitar vários tipos de argumentos e produzir vários tipos de resultados, enquanto outros podem restringir tanto os tipos dos argumentos como o do resultado.
 
O formato de representação de uma expressão composta é como se segue:
 
'''(''' ''nome-do-operador'' ''argumento-1'' ... ''argumento-N'' ''')'''
 
Alguns operadores têm um número fixo de argumentos, enquanto outros têm um número variável de argumentos (operadores variádicos).
 
Exemplos:
* '''(add 1 2)''' -- representa a operação '''add''' com dois argumentos (expressões '''1''' e '''2'''), tedo o significado Java '''1+2'''
* '''(mul (add 1 2) 3)''' -- representa a operação '''mul''' com dois argumentos (expressões '''(add 1 2)''' e '''3'''), tedo o significado Java '''(1+2)*3'''
* '''(eq id1 id2)''' -- representa a operação '''eq''' com dois argumentos (expressões designadas pelos identificadores '''id1''' e '''id2''') e testa se os valores das expressões referidas pelos identificadores '''id1''' e '''id2''' são iguais
 
=== Tabela de operadores ===
 
Os vários operadores e a correspondente semântica são apresentados na tabela. A maioria dos operadores segue a semântica da família da linguagem C, excepto onde explicitamente indicado. Tal como em C, os valores lógicos são 0 (zero) (valor falso), e diferente de zero (valor verdadeiro).
 
{|
| '''Designação'''
| '''Operadores'''
| '''Operandos'''
| '''Semântica'''
|-
! style="vertical-align: top; font-weight: normal;" | aritméticos (unários)
! style="vertical-align: top; font-weight: normal;" | '''neg'''
! style="vertical-align: top; font-weight: normal;" | inteiros, reais
! style="vertical-align: top; font-weight: normal;" | C
|-
! style="vertical-align: top; font-weight: normal;" | aritméticos (binários)
! style="vertical-align: top; font-weight: normal;" | '''add''', '''sub''', '''mul''', '''div''', '''mod'''
! style="vertical-align: top; font-weight: normal;" | inteiros, reais
! style="vertical-align: top; font-weight: normal;" | C -- '''mod''' é apenas para inteiros
|-
! style="vertical-align: top; font-weight: normal;" | comparação (binários)
! style="vertical-align: top; font-weight: normal;" | '''lt le ge gt'''
! style="vertical-align: top; font-weight: normal;" | inteiros, reais, strings
! style="vertical-align: top; font-weight: normal;" | C -- Para cadeias de caracteres, como '''strcmp'''
|-
! style="vertical-align: top; font-weight: normal;" | igualdade (binários)
! style="vertical-align: top; font-weight: normal;" | '''eq ne'''
! style="vertical-align: top; font-weight: normal;" | inteiros, reais
! style="vertical-align: top; font-weight: normal;" | C -- Para cadeias de caracteres, como '''strcmp'''
|-
! style="vertical-align: top; font-weight: normal;" | lógicos (unários)
! style="vertical-align: top; font-weight: normal;" | '''not'''
! style="vertical-align: top; font-weight: normal;" | inteiros
! style="vertical-align: top; font-weight: normal;" | C
|-
! style="vertical-align: top; font-weight: normal;" | lógicos (binários)
! style="vertical-align: top; font-weight: normal;" | '''and or'''
! style="vertical-align: top; font-weight: normal;" | inteiros
! style="vertical-align: top; font-weight: normal;" | C -- Para '''and''', o 2º argumento só é avaliado se o 1º não for falso. Para '''or''', o 2º argumento só é avaliado se o 1º não for verdadeiro.
|-
! style="vertical-align: top; font-weight: normal;" | atribuição (binário)
! style="vertical-align: top; font-weight: normal;" | '''set'''
! style="vertical-align: top; font-weight: normal;" | todos os tipos
! style="vertical-align: top; font-weight: normal;" | O valor da expressão (2º argumento) é associado ao identificador (1º argumento). O valor da expressão é o do seu 2º argumento.
|-
! style="vertical-align: top; font-weight: normal;" | sequência (variádico)
! style="vertical-align: top; font-weight: normal;" | '''seq'''
! style="vertical-align: top; font-weight: normal;" | todos os tipos
! style="vertical-align: top; font-weight: normal;" | As sub-expressões são avaliadas em sequência. O valor da expressão é o do seu último argumento.
|-
! style="vertical-align: top; font-weight: normal;" | impressão (variádico)
! style="vertical-align: top; font-weight: normal;" | '''print'''
! style="vertical-align: top; font-weight: normal;" | todos os tipos
! style="vertical-align: top; font-weight: normal;" | As sub-expressões são avaliadas em sequência e os valores correspondentes apresentados na saída. O valor da expressão é o do seu último argumento.
|-
! style="vertical-align: top; font-weight: normal;" | leitura (sem argumentos)
! style="vertical-align: top; font-weight: normal;" | '''readi''', '''readr''', '''reads'''
! style="vertical-align: top; font-weight: normal;" | inteiros, reais, cadeias de caracteres (respectivamente)
! style="vertical-align: top; font-weight: normal;" | Pedem a introdução (pelo utilizador) de valores com os tipos correspondentes.
|-
! style="vertical-align: top; font-weight: normal;" | condicional (trenário)
! style="vertical-align: top; font-weight: normal;" | '''if'''
! style="vertical-align: top; font-weight: normal;" | condição (1º argumento) deve ser inteira
! style="vertical-align: top; font-weight: normal;" | C -- Comporta-se de modo semelhante ao do operador trenário '''?:''' (não exige concordância de tipos entre os 2º e 3º argumentos). Apenas é avaliado o argumento correspondente ao valor lógico indicado pela condição.
|-
! style="vertical-align: top; font-weight: normal;" | ciclo (binário)
! style="vertical-align: top; font-weight: normal;" | '''while'''
! style="vertical-align: top; font-weight: normal;" | condição (1º argumento) deve ser inteira
! style="vertical-align: top; font-weight: normal;" | Avalia o 1º argumento: se o valor lógico for falso, returna-o; se o valor lógico for verdadeiro, avalia o 2º argumento, após o que reinicia o ciclo com nova avaliação do 1º argumento, etc. O valor da expressão é o valor da mais recente avaliação do seu primeiro argumento.
|}
 
=== Exemplos de expressões compostas ===
 
Os exemplos seguintes apresentam casos de uso simples dos operadores acima.
 
Exemplo 1: sequência com 3 expressões (valor '''9'''):
* '''(seq (add 1 2.3) (sub 1 2) (mul (add 1 2) 3))'''
 
Exemplo 2: seuência com 5 expressões (valor '''"olá"'''):
* '''(seq (add 1 2.3) (sub 1 2) (mul (add 1 2) 3.2) (div 2 0) "olá")'''
 
Exemplo 3: sequência com 2 expressões (valor final '''0''') (note-se que esta sequência corresponde a um pequeno "programa" que apresenta o valor do identificador '''ix''' na saída):
* '''(seq (set ix 0) (while (lt ix 30) (seq (print "ix =" ix) (set ix (add ix 1)))))'''
 
= Interacção com o Utilizador =
 
Descreve-se nesta secção a '''funcionalidade máxima''' da interface com o utilizador. Em geral, os comandos pedem toda a informação antes de proceder à sua validação (excepto onde indicado). Todos os menus têm automaticamente a opção '''Sair''' (fecha o menu).
 
As operações de leitura e escrita '''devem''' realizar-se através do objecto '''ist.po.ui.Dialog.IO'''. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] ('''po-uilib''' e '''pex-support'''). As mensagens não podem ser usadas no núcleo da aplicação ("core"). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.
 
As excepções usadas na interacção, excepto se indicado, são subclasses de '''ist.po.ui.DialogException''', são lançadas pelos comandos e tratadas por '''ist.po.ui.Menu'''. Outras excepções não devem substituir as fornecidas nos casos descritos.
 
Note-se que os comandos e menus a seguir descritos, assim como o programa principal, já estão parcialmente implementados  nas classes das ''packages'' '''pex.textui''', '''pex.textui.main''' e '''pex.textui.evaluator'''. Estas classes são de uso obrigatório e  estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório CVS|CVS]] (módulo '''pex-textui''').
 
== Menu Principal ==
 
As acções do menu, listadas em '''pex.textui.main.MenuEntry''', permitem gerir a salvaguarda do estado da aplicação, assim como operar sobre o documento actual: [[#Salvaguarda do Documento Actual|Criar]], [[#Salvaguarda do Documento Actual|Abrir]], [[#Salvaguarda do Documento Actual|Guardar]], [[#Salvaguarda do Documento Actual|Guardar Textualmente]] e [[#Editar|Editar]]. A classe '''pex.textui.main.Message''' define os métodos para geração das mensagens de diálogo. Inicialmente, a aplicação tem uma calculadora vazia.
 
=== Salvaguarda do Documento Actual ===
 
O conteúdo do documento pode ser guardado para posterior recuperação (via serialização Java: '''java.io.Serializable'''). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:
 
* '''Criar''' -- Cria um novo documento anónimo não associado a nenhum ficheiro.
* '''Abrir''' -- Carrega um documento anteriormente salvaguardado, ficando o documento carregado associado ao ficheiro nomeado: pede-se o nome do ficheiro a abrir ('''openFile()'''). Caso o ficheiro não exista, é apresentada a mensagem '''fileNotFound()'''.
* '''Guardar''' -- Guarda o documento actual no ficheiro associado. Se não existir associação, pede-se o nome do ficheiro a utilizar, ficando a ele associada. Esta interacção realiza-se através do método '''newSaveAs()'''. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.
* '''Guardar Textualmente''' -- Guarda as expressões da calculadora num ficheiro. O nome do ficheiro a abrir para escrita é sempre pedido ('''openFile()'''), não ficando associado à calculadora. Esta interacção realiza-se através do método '''newSaveAs()'''. Escritas no mesmo ficheiro substituem o conteúdo anterior.
 
A opção '''Sair''' nunca guarda o estado da aplicação, mesmo que existam alterações.
 
Estes comandos já estão parcialmente implementados  nas classes da ''package'' '''pex.textui.main''' (disponível no CVS): '''New''', '''Open''', '''Save''', '''WriteDescription'''.
 
=== Editar ===
 
Abre o menu de edição (alteração) do documento e do seu conteúdo, estabelecendo como secção actual o nível de topo do documento.
 
Este comando já está parcialmente implementado  na classe da ''package'' '''pex.textui.main''' (disponível no CVS): '''Edit'''.
 
== Menu de Edição ==
 
Este menu permite efectuar operações sobre um documento. A lista completa é a seguinte: [[#Alterar título|Alterar título]], [[#Listar secções|Listar secções]], [[#Mostrar conteúdo|Mostrar conteúdo]], [[#Ir para secção|Ir para secção]], [[#Inserir secção|Inserir secção]], [[#Nomear secção|Nomear secção]], [[#Remover secção|Remover secção]], [[#Inserir parágrafo|Inserir parágrafo]], [[#Nomear parágrafo|Nomear parágrafo]], [[#Alterar parágrafo|Alterar parágrafo]], [[#Remover parágrafo|Remover parágrafo]].
 
As etiquetas das opções deste menu estão definidas na classe '''edt.textui.section.MenuEntry'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''edt.textui.section.Message'''.
 
Em todos os casos, só podem ser indicados secções e parágrafos filhos da secção actual. O documento é estruturalmente semelhante a uma secção, sendo considerado a secção raiz (na primeira abertura deste menu).
 
=== Alterar título ===
 
Permite alterar o título da secção actual (ou do próprio documento). Para tal, pede-se o novo título ('''requestSectionTitle()''').
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''ChangeTitle'''.
 
=== Listar secções ===
 
É apresentada a lista de títulos de todas as subsecções da secção actual (recursivamente): cada título entre chavetas é precedido pelo seu identificador único entre parênteses rectos (ou só os parânteses, caso o identificador não esteja definido). Se algum título for vazio, apresentam-se apenas as chavetas.
 
Exemplos:
[x123] {Isto é um título}
[] {Isto é outro título}
[w83] {}
[] {}
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''ListSections'''.
 
=== Mostrar conteúdo ===
 
Apresenta o título e todo o conteúdo da secção actual: o texto de cada parágrafo é apresentado por ordem; cada secção é apresentada tal como no caso da apresentação do índice, seguida dos seus parágrafos e subsecções (apresentação recursiva).
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''ShowContent'''.
 
=== Ir para secção ===
 
Permite seleccionar a secção indicada pelo utilizador (através da especificação do identificador local '''requestSectionId()'''). Se a secção indicada não existir, continua na secção actual, sendo apresentada a mensagem '''noSuchSection()'''. Caso contrário, é apresentada a mensagem '''newActiveSection()''' e o menu de edição de secções é aberto para a secção seleccionada.
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''SelectSection'''.
 
=== Inserir secção ===
 
Permite inserir uma subsecção antes de outra de referência (indicada pelo identificador local '''requestSectionId()'''). É pedido o título ('''requestSectionTitle()''') da nova secção. Se a subsecção de referência não existir, insere a nova subsecção no final da secção actual.
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''InsertSection'''.
 
=== Nomear secção ===
 
Permite atribuir um identificador único (no contexto do documento) a uma secção. É pedido o identificador local (inteiro) da subsecção a identificar ('''requestSectionId()''') e o identificador único a atribuir ('''requestUniqueId()''') (cadeia de caracteres). Se a secção não existir é apresentada a mensagem '''noSuchSection()''' e a acção termina. Se o identificador já existir, passa a designar a nova secção (a ligação anterior é destruída). Se a secção já tiver um identificador, a mensagem de aviso '''sectionNameChanged()''' é apresentada e é atribuído o novo identificador único à secção.
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''NameSection'''.
 
=== Remover secção ===
 
Permite remover a secção indicada pelo utilizador através do identificador local ('''requestSectionId()'''). Se a secção indicada não existir, apresenta a mensagem '''noSuchSection()''' e não realiza nenhuma acção.
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''RemoveSection'''.
 
=== Inserir parágrafo ===
 
Permite inserir um novo parágrafo antes de outro parágrafo da secção actual. É pedido o número do parágrafo de referência ('''requestParagraphId()''') e o texto do novo parágrafo ('''requestParagraphContent()'''). Se o parágrafo de referência não existir, insere o novo parágrafo no final da sequência de parágrafos da secção.
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''InsertParagraph'''.
 
=== Nomear parágrafo ===
 
Permite atribuir um identificador único (no contexto do documento) a um parágrafo. É pedido o número do parágrafo a identificar ('''requestParagraphId()''') e o identificador único a atribuir ('''requestUniqueId()''') (cadeia de caracteres). Se o parágrafo não existir é apresentada a mensagem '''noSuchParagraph()''' e a acção termina. Se o identificador já existir, passa a designar o novo parágrafo (a ligação anterior é destruída). Se o parágrafo já tiver um identificador, a mensagem de aviso '''paragraphNameChanged()''' é apresentada e é atribuído o novo identificador único ao parágrafo.
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''NameParagraph'''.
 
=== Alterar parágrafo ===
 
Permite alterar o texto do parágrafo indicado. É pedido o número do parágrafo a alterar ('''requestParagraphId()''') e o texto do novo parágrafo ('''requestParagraphContent()'''). Se o parágrafo indicado não existir, apresenta a mensagem '''noSuchParagraph()''' e não realiza nenhuma acção.
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''EditParagraph'''.
 
=== Remover parágrafo ===
 
Permite remover o parágrafo indicado pelo utilizador ('''requestParagraphId()''').  Se o parágrafo indicado não existir, apresenta a mensagem '''noSuchParagraph()''' e não realiza nenhuma acção.
 
Este comando já está parcialmente implementado  na classe da ''package'' '''edt.textui.section''' (disponível no CVS): '''RemoveParagraph'''.
 
= Leitura de Expressões a Partir de Ficheiros Textuais =
Além das opções de manipulação de ficheiros descritas no [[#Salvaguarda do Documento Actual|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java '''[[#Execução dos Programas e Testes Automáticos|import]]'''. Este ficheiro contém uma expressão que é avaliada pela calculadora, podendo ser usado como forma cómoda de inicialização da sua memória (através de expressões '''set'''). Se não existirem definições de variáveis, a avaliação não deixa traços na memória da calculadora. Apenas é lida a primeira expressão presente no ficheiro.
 
== Exemplo de ficheiro a importar ==
 
Note-se que, neste exemplo, a sequência de topo garante que são lidas todas as outras. Note-se também que, apesar de nenhuma sequência ser memorizada, o identificador '''ix''' fica registado (associado à expressão correspondente ao último valor da iteração).
 
(seq
    (seq (add 1 2.3) (sub 1 2) (mul (add 1 2) 3))
    (seq (add 1 2.3) (sub 1 2) (mul (add 1 2) 3.2) (div 2 0) "olá")
    (seq (set ix 0) (while (lt ix 30) (seq (print "ix =" ix) (set ix (add ix 1))))))
 
== Exemplo de pequeno "programa" ==
 
Este exemplo corresponde a um pequeno "programa" ('''triangulos.pex''') para verificar se três segmentos de recta formam um triângulo. Tal como no exemplo anterior, os identificadores '''a''', '''b''' e '''c''' ficam associados a valores usados durante a avaliação, embora a expressão do "programa" não seja memorizada.
 
(seq
    (print "Introduza as dimensões do 1º lado do triângulo: ")
    (set a (readi))
    (print "Introduza as dimensões do 2º lado do triângulo: ")
    (set b (readi))
    (print "Introduza as dimensões do 3º lado do triângulo: ")
    (set c (readi))
    (if (lt a 1)
        (print "As dimensões dos lados do triângulo devem ser positivas")
        (if (lt b 1)
            (print "As dimensões dos lados do triângulo devem ser positivas")
            (if (lt c 1)
                (print "As dimensões dos lados do triângulo devem ser positivas")
                (if (le (add a b) c)
                    (print "Não é um triângulo")
                    (if (le (add a c) b)
                        (print "Não é um triângulo")
                        (if (le (add c b) a)
                            (print "Não é um triângulo")
                            (if (eq a b)
                                (if (eq b c)
                                    (print "Triângulo equilátero")
                                    (print "Triângulo isósceles"))
                                (if (eq b c)
                                    (print "Triângulo isósceles")
                                    (print "Triângulo escaleno"))))))))))
 
A calculadora pode produzir ficheiros textuais com o conteúdo da sua memória, mas nunca os lê a partir de nenhum comando.
 
Embora o interpretador de expressões da calculadora tenha de assinalar problemas relativos à interpretação de expressões mal especificadas, assume-se que não há entradas mal-formadas nestes ficheiros (embora tenham de ser detectadas).
 
= Considerações sobre Flexibilidade e Eficiência =
Devem ser possíveis extensões ou alterações de funcionalidade com impacto mínimo no código já produzido para a calculadora. O objectivo é aumentar a flexibilidade da aplicação relativamente ao suporte de novas funções. Em particular, a solução encontrada para salvaguardar textualmente o conteúdo do documento deve ser suficientemente flexível de modo a permitir visualizar o conteúdo de um documento noutro formato (por exemplo, XML) sem que isso implique alterações no código ''core'' da aplicação.
 
= Execução dos Programas e Testes Automáticos =
 
Usando os ficheiros '''test.pex''', '''test.in''' e '''test.out''', é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável '''CLASSPATH''' (ou da opção equivalente '''-cp''' do comando '''java'''), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação ('''pex.textui.App.main'''). As propriedades são tratadas automaticamente pelo código de apoio.
 
        java -Dimport=test.pex -Din=test.in -Dout=test.outhyp pex.textui.App
 
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída '''test.outhyp'''. Em caso de sucesso, os ficheiros das saídas esperada ('''test.out''') e obtida ('''test.outhyp''') devem ser iguais. A comparação pode ser feita com o comando:
 
        diff -b test.out test.outhyp
 
Este comando não deve produzir qualquer resultado quando os ficheiros são iguais. Note-se, contudo, que este teste não garante o correcto funcionamento do código desenvolvido, apenas verificando alguns aspectos da sua funcionalidade.
 
[[category:Ensino]]
[[category:PO]]
[[category:Projecto de PO]]
[[en:Object-Oriented Programming]]

Latest revision as of 17:26, 7 November 2018