A árvore de arquivos
Com as camadas e os papéis definidos, falta decidir onde cada classe mora no disco. Esta página mostra a estrutura completa de pastas e arquivos que o tutorial constrói, e a ordem em que cada peça é escrita.
Uma classe por arquivo
Cada arquivo .py contém uma classe, e o nome do arquivo vem do nome da classe escrito em
snake_case (palavras em minúsculas separadas por _): ViewState fica em view_state.py,
GenerateMaze em generate_maze.py. Quando a pasta já diz o contexto, o nome encurta:
MazeGenerator fica em mazegen/generator.py, e FileConfigRepository em
repositories/config_repository.py.
A pasta de cada arquivo é a do seu papel: as entidades em entities/, os value objects em
value_objects/, e assim por diante. Os dois pacotes repetem alguns desses nomes: há uma pasta
services/ dentro de mazegen/ (com Carver, Braider e Solver, parte do gerador, no anel
central das camadas) e outra dentro de amazeing/ (com RenderService, a camada services do
anel de fora).
a_maze_ing.py ponto de entrada e barreira de erros
mazegen/ o gerador (vai para o pacote)
__init__.py documentação; exporta MazeGenerator e MazeError
py.typed marca o pacote como tipado
errors.py MazeError
generator.py MazeGenerator
entities/
maze.py Maze
value_objects/
cell.py Cell
direction.py Direction
pattern42.py Pattern42
services/
carver.py Carver
braider.py Braider
solver.py Solver
amazeing/ a aplicação
errors.py AppError, ConfigError, OutputError
domain/
entities/
view_state.py ViewState
value_objects/
maze_config.py MazeConfig
generated_maze.py GeneratedMaze
use_cases/
ports.py MazeRepository
generate_maze.py GenerateMaze
repositories/
config_repository.py FileConfigRepository
maze_repository.py FileMazeRepository
services/
render_service.py RenderService
ui/
menu.py Menu
utils/
value_parser.py ValueParser
ansi.py Ansi
Três tipos de arquivo fogem da regra "uma classe por arquivo". Os dois primeiros são explicados na parte 3:
__init__.py: o arquivo que transforma uma pasta em pacote Python. Toda pasta da árvore tem um, mesmo que não apareça acima. O demazegen/também guarda a documentação de uso do gerador.py.typed: um arquivo vazio que avisa às ferramentas de verificação de tipos que o pacotemazegentem anotações de tipo (o-> int, o: strdas funções).
O terceiro são os errors.py, que guardam os tipos de erro de cada pacote: MazeError para o
gerador e, para a aplicação, AppError junto com as suas variações ConfigError e
OutputError, três classes pequenas no mesmo arquivo.
A ordem de construção
O tutorial constrói primeiro o que não depende de nada e por último o que liga tudo. Assim, toda peça nova só importa peças que já existem e já funcionam:
| Parte | Constrói |
|---|---|
| 3 | o ambiente: Makefile, pyproject.toml, configuração do lint, pastas vazias |
| 4 | os value objects Direction, Cell e Pattern42, e antes deles o MazeError (uma exceção, não um value object: vem primeiro porque não depende de nada e todas as outras peças podem levantá-lo) |
| 5 | Maze |
| 6 | Carver |
| 7 | Solver |
| 8 | Braider |
| 9 | MazeGenerator, a documentação e o pacote |
| 10 | AppError, ValueParser, Ansi |
| 11 | MazeConfig, FileConfigRepository |
| 12 | GeneratedMaze, MazeRepository, FileMazeRepository, GenerateMaze |
| 13 | ViewState, RenderService |
| 14 | Menu, a_maze_ing.py |
| 15 | o README.md e o pacote final |
| 16 | o bônus |
Os dois pacotes são construídos em sequência: as partes 4 a 9 fazem o mazegen inteiro, e só
depois as partes 10 a 14 fazem a aplicação que o usa.