organização de código em módulos · 2010. 8. 2. · dim0108.0 - conceitos e técnicas de...
TRANSCRIPT
DIM0108.0 - Conceitos e Técnicas de Programação
Organização de código em módulos
David Déharbe
1
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Introdução
• O desenvolvimento modular promove a divisão de uma aplicação em unidades de software.
• Cada módulo pode ser desenvolvido e compilado isoladamente, facilitando o trabalho em equipe.
• Um desenvolvedor pode utilizar um módulo sem ter acesso ao código fonte do mesmo, apenas precisa da interface.‣ A interface comporta a declaração das definições (tipos, funções, exceções,
outros módulos) exportadas pelo módulo‣ A interface permite usar o módulo sem conhecer a implementação do
mesmo.‣ A implementação do módulo pode ser alterada sem os usuários perceberem.
• A programação modular facilita a organização e a manutenção do código de aplicações.
• OCaml possui um mecanismo rico de módulos que permite definir módulos aceitam módulos em parâmetro (não apresentado).
2
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Organização modular
• Cada módulo deve corresponder a alguma funcionalidade.• Por exemplo, a biblioteca padrão da linguagem Objective Caml é dividida em
módulos:‣ Printf: impressão formatada,‣ Scanf: leitura formatada,‣ List: listas genêricas,‣ Graphics: manipulação de gráficos,‣ etc.
• O conceito de tipo de dados abstrato é muito importante em computação:‣ corresponde a um tipo (genêrico ou não) de dados,‣ possui funções para manipular valores daquele tipo,‣ o usuário não precisa saber como são implementadas as funções para usá-las,‣ exemplo: array‣ um tipo abstrato de dados pode ser implementado através de um módulo
3
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Compilação separada
• Módulos são compilados individualmente. • Mas, não são programas
‣ não podem ser executados!‣ opção -c do compilador: não tente gerar programa executável‣ o resultado da compilação é um componente pré-compilado que pode ser
usado em outro programa.‣ esses componentes podem ser agrupados em bibliotecas.
• Para um programa usar um módulo, devemos usar o compilador com o nome dos componentes pré-compilados.‣ Exemplo:
✓ ocamlopt graphics.cmxa -o game_of_life game_of_life.ml‣ Indica que a biblioteca graphics.cmxa deve ser incluída para construir o
programa game_of_life:
4
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Linkedição
• Comportamento defaut do compilador✓ ocamlopt fonte.ml -o programa
‣ compila o código fonte no arquivo fonte.ml‣ "combina" com alguns elementos da biblioteca padrão do OCaml e gera o
programa executável no arquivo programa‣ compilação + linkedição
• Linkedição é a combinação de vários códigos objetos em um arquivo executável.‣ Exemplo de códigos objetos:
✓ bibliotecas: graphics.cmxa✓ aplicação do compilador sem fase de linkedição:
- ocamlopt fonte.ml -cgera o arquivo objeto fonte.cmo.
✓ podemos juntar vários arquivos objetos para formar um programa.5
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Ilustração: exemplo 1
6
fonte.ml fonte.o programa
Pervasives.cmxa
Compilação Linkedição
ocamlopt fonte.ml -o programa
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Ilustração: exemplo 2
7
fonte3.ml fonte3.o programa
pervasives.cmxa
Compilação Linkedição
ocamlopt graphics.cmxa fonte3.ml -o programa
graphics.cmxa
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Ilustração: exemplo 3
8
fonte2.ml fonte2.oCompilação
ocamlopt fonte2.ml -c
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Ilustração: exemplo 3
9
fonte4.ml fonte4.o programa
pervasives.cmxa
Compilação Linkedição
ocamlopt graphics.cmxa fonte2.cmo fonte4.ml -o programa
graphics.cmxafonte2.o
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Ilustração: exemplo 3 - revisitado
10
fonte4.ml fonte4.o programa
pervasives.cmxa
Compilação Linkedição
ocamlopt graphics.cmxa fonte2.ml fonte4.ml -o programa
graphics.cmxafonte2.ofonte2.mlCompilação
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Exemplo: os números racionais
• Nesta aula, iremos prover um módulo para representar e manipular números racionais.
• Este módulo será compilado isoladamente, e não será executável: proverá funcionalidade para outros programas.
• Nosso módulo poderá ser usado por programas clientes que precisam fazer cálculos com números racionais.
• O nosso módulo será um fornecedor da funcionalidade: representação e manipulação de números racionais.
‣ Do que precisamos para representar os números racionais?‣ Quais operações deveriamos prover para manipular números racionais?
11
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
OCaml: arquivos e módulos
• Cada arquivo de programa (ou unidade de compilação) é um módulo.• Os nomes declarados em um módulo formam a interface ou assinatura daquele
módulo:‣ tipos,‣ funções,‣ exceções,‣ sub-módulos.
• O nome do arquivo (minúsculas) é um nome do módulo (capitalizado).
• Para declarar os tipos e funções definidas no arquivo, a assinatura do módulo é definida em um arquivo de interface (extensão .mli).‣ O arquivo rational.mli contem a declaração da assinatura do módulo
Rational.‣ O arquivo rational.ml contem a definição do módulo Rational.
12
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
O arquivo interface: rational.mli
• O arquivo rational.mli contem as declarações que queremos.‣ Compilar com ocamlc -c rational.mli‣ gera o arquivo rational.cmi
13
type t
exception Null_denominator
val create: int -> int -> tval to_string: t -> stringval numerator: t -> intval denominator: t -> intval (+|) : t -> t -> tval (-|) : t -> t -> tval (*|) : t -> t -> tval (/|) : t -> t -> tval (~-|) : t -> t
val (=|) : t -> t -> boolval (<>|) : t -> t -> boolval (<|) : t -> t -> boolval (>|) : t -> t -> boolval (<=|) : t -> t -> boolval (>=|) : t -> t -> bool
val zero : tval one : t
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
O arquivo interface: rational.mli
• O arquivo rational.mli contem as declarações que queremos.‣ Compilar com ocamlc -c rational.mli‣ gera o arquivo rational.cmi
13
type t
exception Null_denominator
val create: int -> int -> tval to_string: t -> stringval numerator: t -> intval denominator: t -> intval (+|) : t -> t -> tval (-|) : t -> t -> tval (*|) : t -> t -> tval (/|) : t -> t -> tval (~-|) : t -> t
val (=|) : t -> t -> boolval (<>|) : t -> t -> boolval (<|) : t -> t -> boolval (>|) : t -> t -> boolval (<=|) : t -> t -> boolval (>=|) : t -> t -> bool
val zero : tval one : t
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Exemplo de uso da interface
• Um programa testrat.ml cria números racionais:
14
let _ = let r1 : Rational.t = Rational.create 2 3 and r2 : Rational.t = Rational.create 3 4and s : Rational.t ref = ref Rational.zero in s := Rational.(+|) r1 r2; print_string ( (Rational.to_string r1) ^ " + " ^ (Rational.to_string r2) ^ " = " ^ (Rational.to_string !s) ^ "\n")
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Exemplo de uso da interface
• Um programa testrat.ml cria números racionais:
14
open Rational
let _ = let r1 : t = create 2 3 and r2 : t = create 3 4and s : t ref = ref zero in s := r1 +| r2; print_string ( (to_string r1) ^ " + " ^ (to_string r2) ^ " = " ^ (to_string !s) ^ "\n" )
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Exemplo de uso da interface
• Compilar com ocamlopt -c testrat.ml• Gera o arquivo testrat.o
‣ Obs. 1 Pode se compilar o código do cliente sem ter definido o componente!‣ Obs. 2 Não pode se gerar o programa sem ter definido o componente...
15
localhost: david$ ocamlc.opt testrat.ml -clocalhost: david$ ocamlc.opt testrat.ml rational.mli -o testratFile "rational.mli", line 1, characters 0-1:Error: Error while linking testrat.cmo:Reference to undefined global `Rational'
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
• O arquivo com as definições é um arquivo texto com código OCaml tal como foi praticado desde o início da disciplina.
‣ Questão que o fornecedor (nós) tem que se fazer:
‣ Como iremos representar os números racionais?✓ Isso nos indica como o tipo t deve ser definido
‣ Como iremos representar os valores constantes zero e one?‣ Como iremos calcular o resultado das operações declaradas na interface?
✓ Isso nos indica como as definições devem ser feitas.
Definição do módulo Rational
16
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Exemplo de definição de módulo
• Arquivo rational.ml:‣ vai ser definido o mínimo possível para poder executar o programa teste...‣ sempre tentar definir funções a partir de funções existentes.
17
type t = { num : int ; den : int }exception Null_denominatorlet create : int -> int -> t = fun (n : int) (d : int) -> if d = 0 then raise Null_denominator; { num = n ; den = d}let numerator : t -> int = fun (r : t) -> r.numlet denominator : t -> int = fun (r : t) -> r.denlet zero : t = create 0 1let one : t = create 1 1let to_string : t -> string = fun (r : t) -> "[" ^ (numerator r) ^ ":" ^ (denominator r) ^ "]"let (+|) : t -> t -> t = fun (r1 : t) (r2 : t) -> create (numerator r1 * denominator r2 + numerator r2 * denominator r1) (denominator r1 * denominator r2)
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Compilação da implementação do módulo
• Compilar com ocamlc -c rational.ml• Gera o arquivo rational.cmo
‣ Obs. Não se pode compilar enquanto todos os valores não foram definidos!
18
localhost: david$ ocamlc.opt rational.ml -cFile "rational.ml", line 1, characters 0-1:Error: The implementation rational.ml does not match the interface rational.cmi: The field `>=|' is required but not provided The field `<=|' is required but not provided The field `>|' is required but not provided The field `<|' is required but not provided The field `<>|' is required but not provided The field `=|' is required but not provided The field `~-|' is required but not provided The field `/|' is required but not provided The field `*|' is required but not provided The field `-|' is required but not provided
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Resto da definição de módulo (provisória)
• Eu estou muito ansioso para saber se funciona...• Quero testar as funcionalidades mais simples antes de trabalhar nas demais.
19
let (-|) : t -> t -> t = fun (r1 : t) (r2 : t) -> raise Not_implementedlet ( *|) : t -> t -> t = fun (r1 : t) (r2 : t) -> raise Not_implementedlet (/|) : t -> t -> t = fun (r1 : t) (r2 : t) -> raise Not_implementedlet (~-|) : t -> t -> t = fun (r1 : t) (r2 : t) -> raise Not_implementedlet (=|) : t -> t -> bool = fun (r1 : t) (r2 : t) -> raise Not_implementedlet (<>|) : t -> t -> bool = fun (r1 : t) (r2 : t) -> raise Not_implementedlet (<|) : t -> t -> bool = fun (r1 : t) (r2 : t) -> raise Not_implementedlet (<=|) : t -> t -> bool = fun (r1 : t) (r2 : t) -> raise Not_implementedlet (>|) : t -> t -> bool = fun (r1 : t) (r2 : t) -> raise Not_implementedlet (>=|) : t -> t -> bool = fun (r1 : t) (r2 : t) -> raise Not_implemented
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Resto da definição de módulo (provisória)
• Eu estou muito ansioso para saber se funciona...• Quero testar as funcionalidades mais simples antes de trabalhar nas demais.
19
let undef_combine : t -> t -> t = fun (r1 : t) (r2 : t) -> raise Not_implementedlet undef_compare : t -> t -> bool = fun (r1 : t) (r2 : t) -> raise Not_implemented
let (-|) : t -> t -> t = undef_combinelet ( *|) : t -> t -> t = undef_combinelet (/|) : t -> t -> t = undef_combinelet (~-|) : t -> t -> t = undef_combinelet (=|) : t -> t -> bool = undef_comparelet (<>|) : t -> t -> bool = undef_comparelet (<|) : t -> t -> bool = undef_comparelet (<=|) : t -> t -> bool = undef_comparelet (>|) : t -> t -> bool = undef_comparelet (>=|) : t -> t -> bool = undef_compare
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Geração do programa de teste
• Uma vez feitas todas as definições que correspondem à interface, iremos compilar essas definições‣ ocamlc.opt rational.ml -c
• Combinamos a implementação do módulo e o programa de teste para gerar um programa executável:‣ Compilar com ocamlc.opt testrat.cmo rational.cmo -o testrat‣ testrat é o nome do programa gerado;‣ Nos argumentos de ocamlc.opt, rational.cmo deve preceder testrat.cmo:
arquivo dos componentes devem vir antes do arquivo do código principal.
20
localhost: david$ ocamlc.opt testrat.cmo rational.cmo -o testratFile "_none_", line 1, characters 0-1:Error: Error while linking testrat.cmo:Reference to undefined global `Rational'localhost: david$ ocamlc.opt rational.cmo testrat.cmo -o testratlocalhost: david$ /testrat[2:3] + [3:4] = [17:12]
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Exercícios
• Enriquece o módulo Rational:‣ Define as demais funções.
• Cria programas clientes que testam cada função.
21
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Manutenção e evolução de módulo
• Representação reduzida dos racionais:‣ maior eficiência nas operações de comparação, ‣ diminuição dos casos de transbordamento.
22
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Manutenção e evolução de módulo
• Representação reduzida dos racionais:‣ maior eficiência nas operações de comparação, ‣ diminuição dos casos de transbordamento.
22
(* maior divisor comum *)let mdc : int -> int -> int =(n: int) (m: int) -> let big : int ref = ref (max n m) and small = ref (min n m) in while !big mod !small <> 0 do let tmp = !big mod !small in big := !small; small := tmp done; !smalllet create : int -> int -> t = fun (n : int) (d : int) -> if n = 0 then raise Null_denominator; if d = 0 then { num = 0; d = 1} else let m = mdc (abs n) (abs m) in let n' = (abs n) / m and d' = (abs d) / m in if n >= 0 & d > 0 or n < 0 && d < 0 then { num = n'; den = d' } else { num = ~- n'; den = d' }
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Manutenção e evolução de módulo
• Representação reduzida dos racionais:‣ maior eficiência nas operações de comparação, ‣ diminuição dos casos de transbordamento.
22
(* maior divisor comum *)let mdc : int -> int -> int =(n: int) (m: int) -> let big : int ref = ref (max n m) and small = ref (min n m) in while !big mod !small <> 0 do let tmp = !big mod !small in big := !small; small := tmp done; !smalllet create : int -> int -> t = fun (n : int) (d : int) -> if n = 0 then raise Null_denominator; if d = 0 then { num = 0; d = 1} else let m = mdc (abs n) (abs m) in let n' = (abs n) / m and d' = (abs d) / m in if n >= 0 & d > 0 or n < 0 && d < 0 then { num = n'; den = d' } else { num = ~- n'; den = d' }
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Conclusões: muitas vantagens!
• Programas usam componentes pré-existentes;• Existe a necessidade de criar novos componentes para novos tipos de
aplicações;• O conceito de módulo permite prover componentes de software
‣ interface: todos os valores (tipos, exceções, funções) providos pelo componente
‣ implementação: definição dos valores• O cliente não precisa saber como o módulo foi implementado
‣ o cliente apenas tem que conhecer a interface do módulo• Componentes/módulos podem ser reaproveitados em diversos programas.
‣ Existe um mercado para componentes de software.• Uma vez definida a interface, pode se trabalhar de forma independente na
definição do módulo e na implementação do cliente‣ facilita o desenvolvimento em equipe.
23
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Conclusões: e tem muito mais...
• Foi apresentada uma parte da linguagem de módulos da linguagem OCaml.‣ Útil para a noção de Tipo Abstrato de Dados (TAD) usada na disciplina
AED1.‣ Funtores tem módulos em parâmetro e geram novos módulos
✓ cálculo matricial- parâmetro: tipo numérico, operações de soma e multiplicação, valor zero
- resultado: cálculo matricial sobre o tipo t.
• A programação orientada a objetos também permite alcançar benefícios da programação modular.‣ Também há construções para orientação a objetos em OCaml...
• Programing in the large: considere a programação modular como recurso.
24
Sunday, August 1, 2010
DIM0108.0 - Conceitos e Técnicas de Programação
Módulos e o projeto de calculadora
• Módulo para pilhas:‣ quais funções deve prover‣ qual tipo essas funções devem ter
• Módulo para números‣ quais funções deve prover‣ qual tipo essas funções devem ter
• Defina a interface desses módulos
• Defina uma implementação para estes módulos
• Implemente uma versão parcial do programa e que use estes módulos.
25
Sunday, August 1, 2010