SoftwareArchitecture

Extracted and adapted from http://www.bredemeyer.com/pdf_files/ArchitectureDefinition.PDF

Architecture Views

Conceptual Architecture

The Conceptual Architecture identifies the high-level components of the system, and the relationships among them. Its purpose is to direct attention at an appropriate decomposition of the system without delving into details.

Goals:

Logical Architecture

In Logical Architecture, the externally visible properties of the components are made precise and unambiguous through well-defined interfaces and component specifications, and key architectural mechanisms are detailed.

Goals:

Execution Architecture

An Execution Architecture is created for distributed or concurrent systems. The process view shows the mapping of components onto the processes of the physical system, with attention being focused on such concerns as throughput and scalability.

UML simple steps

Reference: http://www.sparxsystems.com/resources/tutorial/uml_tutorial2.html

Steps:

http://agilemodeling.com/essays/agileArchitecture.htm

http://www.sparxsystems.com.au/resources/uml2_tutorial/

http://agilemodeling.com/artifacts/useCaseDiagram.htm

http://agilemodeling.com/artifacts/crcModel.htm

http://agilemodeling.com/artifacts/robustnessDiagram.htm

Recipe 1 - Unified Process - UML - Use case driven

SSD (System Sequence Diagram) Use cases - Behavioral Requirements

Use case:
Actors:
Goals:
Main scenario
1. The system ...
2. The user ...

Use case add numbers

@startuml
actor user
boundary system

system -> user : prompts first number
user -> system : inputs the first number
system -> user : prompts for the second number
user -> system : inputs the second number
system -> user : shows the sum of the two numbers
@enduml

   1 '''
   2 Use case: Add numbers
   3 Actors: User
   4 Goals: Add two numbers
   5 Main scenario:
   6 1. The system prompts for the first number
   7 2. The user inputs the first number
   8 3. The system prompts for the second number
   9 4. The user inputs the second number
  10 5. The system shows the sum of the two numbers 
  11 
  12 Extensions:
  13 2.a   The first number is invalid
  14 2.a.1 The system shows the message "Please check the inputed value for the first value"
  15 2.a.2 The use case continues at step 1
  16 
  17 4.a   The second number is invalid
  18 4.a.1 The system shows the message "Please check the inputed value for the second value"
  19 4.a.2 The use case continues at step 3
  20  
  21 Postcondition: two numbers are added
  22 '''
  23 # python useCaseAdd.py
  24 def readNumber(prompt,exceptionMessage):
  25     gotValue=False
  26     value=0
  27     while(gotValue==False):
  28         try:
  29             value = int( input(prompt) )
  30             gotValue=True
  31         except Exception as ex:
  32             print(exceptionMessage)
  33     return value
  34     
  35 first = readNumber('FirstNumber: ','Please check the inputed value for the first value')            
  36 second = readNumber('Second number: ','Please check the inputed value for the second value') 
  37 print('The sum is %d'%(first + second))

Add numbers SSD example

@startuml
actor user
boundary system
control business

loop while first number is invalid
  system -> user : prompts first number
  user -> system : inputs the first number

  alt success
    system -> user : First number is valid
  else invalid first number
    system -> user : Please check the inputed value for the first value
  end
end

loop while second number is invalid
  system -> user : prompts second number
  user -> system : inputs the second number

  alt success
    system -> user : second number is valid
  else invalid second number
    system -> user : Please check the inputed value for the second value
  end
end
system -> business : add(first,second)
business --> system : sum
system -> user : shows the sum of the two numbers
@enduml

addNumbersSSD.png

Functional requirements (High level)

Define a high level API, design by contract, interface for the whole system.

Just one service with a lot of methods that help fullfil the use cases.

Developer point of view.

Functional requirement addNumber

In the above diagram the functional requirement FR is the add function that return a sum.

add(first:int,second:int):int

The system must be able to add two numbers and return the sum result.

SSD (System Sequence Diagram) implementation examples

ssdBoundary.py

   1 #!/usr/bin/python3
   2 """
   3 All logic still in boundary/UI
   4 """
   5 class Entity:
   6     """ """
   7     def __init__(self):
   8         pass    
   9     
  10 class Boundary:
  11     """ """
  12     def __init__(self):
  13         pass 
  14     
  15 class Credencial(Entity):
  16     """ """
  17     def __init__(self,utilizador,password):
  18         """ """
  19         self.utilizador = utilizador
  20         self.password = password
  21 
  22 class Menu(Entity):
  23     def __init__(self,nome):
  24         """ """
  25         self.nome=nome
  26         self.opcoes=[]
  27         
  28     def adicionarOpcao(self,opcao):
  29         """ """
  30         self.opcoes.append(opcao)
  31         
  32     def getOpcoes(self):
  33         """ """
  34         return self.opcoes
  35         
  36 class Opcao(Entity):
  37     def __init__(self,nome,callback):
  38         """ """
  39         self.nome=nome
  40         self.callback = callback
  41 
  42 class Cotacao(Entity):
  43     def __init__(self,nome,valor,data):
  44         """ """
  45         self.nome=nome
  46         self.valor=valor
  47         self.data=data
  48     
  49     def __repr__(self):
  50         """ """
  51         return '%s %s %f'%(self.data, self.nome, self.valor)
  52     
  53 class UI(Boundary):
  54     def __init__(self):
  55         """ """
  56         self.menu=Menu('Menu')
  57         self.menu.adicionarOpcao(Opcao('Cotações',self.cotacoes))
  58         self.menu.adicionarOpcao(Opcao('Análises',self.analises))
  59         self.menu.adicionarOpcao(Opcao('Sair',self.sair))
  60         
  61         self.credenciais=[]
  62         self.credenciais.append( Credencial('vitor','12345678') )
  63         self.credenciais.append( Credencial('calvin','wally') )
  64         
  65         self.cotacoes=[]
  66         self.cotacoes.append(Cotacao('YHOO',1,'2016-01-02'))
  67         self.cotacoes.append(Cotacao('CSCO',1,'2016-01-02'))
  68         self.cotacoes.append(Cotacao('YHOO',2,'2016-01-03'))
  69         self.cotacoes.append(Cotacao('CSCO',2,'2016-01-03'))
  70 
  71         
  72     def pedirCredenciais(self):
  73         """ """
  74         print('Insira as suas credenciais')
  75         print('Utilizador:')
  76         utilizador = input()
  77         print('Password:')
  78         password = input()
  79         return Credencial(utilizador,password)
  80     
  81     def validarCredenciais(self,credencial):
  82         """ """
  83         found=False
  84         for c in self.credenciais:
  85             if(credencial.utilizador==c.utilizador and credencial.password==c.password):
  86                 found=True
  87                 
  88         if found:
  89             print('Credenciais válidas')
  90             return True            
  91         else:
  92             print('Credenciais inválidas')
  93             return False
  94             
  95     def mostrarMenu(self):
  96         for opcao in self.menu.getOpcoes():
  97             print(' %s'%(opcao.nome))
  98         opcao=input()
  99         selOpcao=None
 100         for o in self.menu.getOpcoes():
 101             if o.nome==opcao:
 102                 selOpcao=o
 103         return selOpcao
 104     
 105     def cotacoes(self):
 106         print('Menu Cotações')
 107         cots=[]
 108         for c in self.cotacoes:
 109             if c.nome not in cots:
 110                 cots.append(c.nome)
 111                 print(c.nome)
 112         print('Escolha a cotação')
 113         cotacao=input()
 114         #mostrar cotacões para acção escolhida
 115         for c in self.cotacoes:
 116             if c.nome == cotacao:
 117                 print(c)
 118         
 119     def analises(self):
 120         print('Menu Análises')
 121     
 122     def sair(self):
 123         exit(0)
 124     
 125 if __name__=='__main__':
 126     ui = UI()
 127     credencial = ui.pedirCredenciais()
 128     resultado = ui.validarCredenciais(credencial)
 129     
 130     if resultado==True:
 131         opcao = ui.mostrarMenu()
 132         opcao.callback()

ssdControl.py

   1 #!/usr/bin/python3
   2 """
   3 All logic in control/service classes 
   4 """
   5 class Entity:
   6     """ Model """
   7     def __init__(self):
   8         pass    
   9     
  10 class Boundary:
  11     """ View """
  12     def __init__(self):
  13         pass 
  14 
  15 class Control:
  16     """ Business Logic - Controller """
  17     def __init__(self):
  18         pass 
  19     
  20 class Credencial(Entity):
  21     """ """
  22     def __init__(self,utilizador,password):
  23         """ """
  24         self.utilizador = utilizador
  25         self.password = password
  26 
  27 class Menu(Entity):
  28     def __init__(self,nome):
  29         """ """
  30         self.nome=nome
  31         self.opcoes=[]
  32         
  33     def adicionarOpcao(self,opcao):
  34         """ """
  35         self.opcoes.append(opcao)
  36         
  37     def getOpcoes(self):
  38         """ """
  39         return self.opcoes
  40         
  41 class Opcao(Entity):
  42     def __init__(self,nome,callback):
  43         """ """
  44         self.nome=nome
  45         self.callback = callback
  46 
  47 class Cotacao(Entity):
  48     def __init__(self,nome,valor,data):
  49         """ """
  50         self.nome=nome
  51         self.valor=valor
  52         self.data=data
  53     
  54     def __repr__(self):
  55         """ """
  56         return '%s %s %f'%(self.data, self.nome, self.valor)
  57     
  58 class ControloCredencial(Control):
  59     def __init__(self):
  60         self.credenciais=[]
  61         self.credenciais.append( Credencial('vitor','********') )
  62         self.credenciais.append( Credencial('calvin','*') )
  63         
  64     def validarCredenciais(self,credencial):
  65         """ """
  66         found=False
  67         for c in self.credenciais:
  68             if(credencial.utilizador==c.utilizador and credencial.password==c.password):
  69                 found=True
  70                 
  71         if found:
  72             print('Credenciais válidas')
  73             return True            
  74         else:
  75             print('Credenciais inválidas')
  76             return False
  77 
  78 class ControloCotacoes(Control):
  79     def __init__(self):
  80         """ """
  81         self.cotacoes=[]
  82         self.cotacoes.append(Cotacao('YHOO',1,'2016-01-02'))
  83         self.cotacoes.append(Cotacao('CSCO',1,'2016-01-02'))
  84         self.cotacoes.append(Cotacao('YHOO',2,'2016-01-03'))
  85         self.cotacoes.append(Cotacao('CSCO',2,'2016-01-03'))
  86         
  87     def obterNomesAccoes(self):
  88         """ """
  89         accoes=[]
  90         for c in self.cotacoes:
  91             if c.nome not in accoes:
  92                 accoes.append(c.nome)
  93         return accoes
  94     
  95     def obterCotacoesParaAccao(self,accao):
  96         """ """
  97         cotacoesPorAccao=[]
  98         for c in self.cotacoes:
  99             if c.nome == accao:
 100                 cotacoesPorAccao.append(c)
 101         return cotacoesPorAccao
 102 
 103 class ControloMenus(Control):
 104     def __init__(self):
 105         """ """
 106         self.menu=Menu('Menu')
 107         self.menu.adicionarOpcao(Opcao('Cotações','cotacoes'))
 108         self.menu.adicionarOpcao(Opcao('Análises','analises'))
 109         self.menu.adicionarOpcao(Opcao('Sair','sair'))
 110         
 111     def getMenu(self):    
 112         """ """
 113         return self.menu
 114     
 115     def obterOpcaoPorNome(self,nomeOpcao):
 116         """ """
 117         selOpcao=None
 118         for o in self.menu.getOpcoes():
 119             if o.nome==nomeOpcao:
 120                 selOpcao=o
 121         return selOpcao
 122         
 123 class UI(Boundary):
 124     """ Lembrar de SSD System Sequence Diagram/Black Box"""
 125     def __init__(self):
 126         """ """
 127         self.controloMenus = ControloMenus()
 128         self.controloCredencial = ControloCredencial()
 129         self.controloCotacoes = ControloCotacoes()
 130         
 131     def pedirCredenciais(self):
 132         """ """
 133         print('Insira as suas credenciais')
 134         print('Utilizador:')
 135         utilizador = input()
 136         print('Password:')
 137         password = input()
 138         return Credencial(utilizador,password)   
 139     
 140     def validarCredenciais(self,credencial):
 141         """ """
 142         return self.controloCredencial.validarCredenciais(credencial)
 143         
 144     def mostrarMenu(self):
 145         for opcao in self.controloMenus.getMenu().getOpcoes():
 146             print(' %s'%(opcao.nome))
 147         opcao=input()
 148         
 149         selOpcao=self.controloMenus.obterOpcaoPorNome(opcao)
 150         mapa={'cotacoes':self.cotacoes,'analises':self.analises,'sair':self.sair}
 151         # define referencia de metodo conforme o nome de callback
 152         selOpcao.callback = mapa[selOpcao.callback]
 153         return selOpcao
 154     
 155     def cotacoes(self):
 156         print('Menu Cotações')
 157 
 158         for nomeAccao in self.controloCotacoes.obterNomesAccoes(): 
 159             print(nomeAccao)
 160             
 161         print('Escolha a cotação')
 162         cotacao=input()
 163         for c in self.controloCotacoes.obterCotacoesParaAccao(cotacao):
 164             print(c)
 165         
 166     def analises(self):
 167         print('Menu Análises')
 168     
 169     def sair(self):
 170         exit(0)
 171     
 172 if __name__=='__main__':
 173     ui = UI()
 174     credencial = ui.pedirCredenciais()
 175     resultado = ui.validarCredenciais(credencial)
 176     
 177     if resultado==True:
 178         opcao = ui.mostrarMenu()
 179         opcao.callback()

SOLID

Single responsibility principle

a class should have only a single responsibility

Open/closed principle

open for extension, but closed for modification. Decorator pattern add new responsibilities, behavior. final class java. sealed csharp class.

Liskov substitution principle

design by contract using interfaces, have loose coupling by using interfaces

Interface segregation principle

"many client-specific interfaces are better than one general-purpose interface."

Dependency inversion principle

depend upon abstractions (abstract classes or interfaces) not concrete stuff

Software design patterns

Singleton

Ensure a class has only one instance, and provide a global point of access to it

Decorator

Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality. (SOLID O principle, open for extension closed for modification

Iterator

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation. next() method. IEnumerable in Csharp. linked list, double linked list.

Memento

capture and externalize an object's internal state allowing the object to be restored to this state later. persist state and restore later (history state, undo).

Null object

Avoid null references by providing a default object. (Java8 Optional<T>, Csharp Nullable<T> )

Observer or Publish/subscribe

Define a one-to-many dependency between objects where a state change in one object results in all its dependents being notified and updated automatically. attach() notify() update()

Strategy

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. sorting algorhitms, hide used algorithm quicksort

SoftwareArchitecture (last edited 2023-06-01 11:03:06 by 127)