5. Create and Test Infrastructure.jl
The Infrastructure has functions that refer to the outer world and can use elements from the Domain and API layers. For example:
- converting JSON data to Julia objects or visa versa.
- storing Julia's objects.
- retrieving objects.
- Event Sourcing, registering events, and replaying a history of events.
- CQRS (Command Query Responsibility Segregation), separating events from queries.
In this chapter, you learn to store and retrieve data-types.
Contents
Infrastructure.jl
module Infrastructure #1
import ..Accounts: Domain, API #2
using .Domain, .API #3
using Serialization #4
export add_to_file, read_from_file #5
function add_to_file(file::String, data::Array{T, 1} where T <: Any) #6
io = open(file, "a+")
[serialize(io, r) for r in data]
close(io)
end
function read_from_file(file::String) #7
io = open(file, "r")
r = []
while !eof(io)
push!(r, deserialize(io))
end
close(io)
return r
end
end
#1 The name of the module is Infrastructure.
#2 The sub-module uses only the elements from the higher onion
peels, Domain, API, Julia, and any loaded packages.
#3 The code loads the sub-modules Domain and API.
#4 You have to serialize data you want to store on disk.
#5 We export the methods read_from_file
and add_to_file
.
#6 Read the data from a text file and deserialize it.
#7 Serialize the data and write it to a text file.
Accounts.jl
The main module should also load the Infrastructure sub-module.
module Accounts
#export EMAIL, WORK # Domain
#export create # API
#export add_to_file, read_from_file # Infrastructure
include("Domain.jl"); using .Domain
include("API.jl"); using .API
include("Infrastructure.jl"); using .Infrastructure
end
test_infr.jl
An example of how to use the code.
using Pkg; Pkg.activate(".") # activate the Accounts environment from Julia
import Accounts: Domain, API, Infrastructure
using .Domain, .API, .Infrastructure
const FILE_ACCOUNTS = "./test_accounts.txt" # Julia gives a warning when the value is changed
donald_email = create(EMAIL, "donald@duckcity.com")
donald_work = create(WORK,
"""
Donalds Hardware Store
attn. Donald Duck
1190 Seven Seas Dr
FL 32830 Lake Buena Vista
USA
"""
)
addresses = [donald_email, donald_work]
donald = create("Donald Duck", addresses)
add_to_file(FILE_ACCOUNTS, [donald])
result = read_from_file(FILE_ACCOUNTS)
println(result)
runtests.jl
The tests are extended for the sub-module Infrastructure
using Accounts
using Test
const FILE_ACCOUNTS = "./test_accounts.txt"
import Accounts: Domain, API, Infrastructure
using .Domain, .API, .Infrastructure
@testset "Domain.jl" begin
donald_email = Address(EMAIL, "donald@duckcity.com")
donald = Person("Donald duck", [donald_email])
email_addresses = filter(x -> x.address_type == EMAIL, donald.addresses)
@test email_addresses[1].address == "donald@duckcity.com"
end
@testset "API.jl" begin
donald_email = Address(EMAIL, "donald@duckcity.com")
donald = Person("Donald Duck", [donald_email])
email_addresses = filter(x -> x.address_type == EMAIL, donald.addresses)
@test email_addresses[1].address == "donald@duckcity.com"
end
@testset "Infrastructure.jl" begin
donald_email = create(EMAIL, "donald@duckcity.com")
donald = create("Donald Duck", [donald_email])
add_to_file(FILE_ACCOUNTS, [donald])
result = read_from_file(FILE_ACCOUNTS)
first_person = result[1]
@test first_person.addresses[1].address == "donald@duckcity.com"
cmd = `rm $FILE_ACCOUNTS`
run(cmd)
end
Exercise 5.1: Adding the Sub-Module Infrastructure
In this exercise, you perform the following tasks.
Step 1 - You create the file Infrastructure.jl
with the Infrastructure sub-module code and update Accounts.jl
. Add Serialization
as a dependency of the module in Project.toml
.
Step 2 - You append the unit test code to the file runtests.jl
and verify it.
Step 3 - You see an example of the code on how to use it as a programmer.
Step 4 - You update your GitHub repository.
- Create the file
Infrastructure.jl
and add the code of section Infrastructure.jl to the file. - Modify
Accounts.jl
according to section Accounts.jl. - Add the
Serialization
package as dependency toProject.toml
. - Add the code from section runtests.jl to the file runtests.jl.
- Go to the package manager, activate Accounts (
activate .
). - Run the test (
test Accounts
). You should see:
Test Summary: | Pass Total
Domain.jl | 1 1
Test Summary: | Pass Total
API.jl | 1 1
Test Summary: | Pass Total
Infrastructure.jl | 1 1
Testing Accounts tests passed
- Create the file
test_infr.jl
and copy the code from section test_infr.jl into it. - Test the code.
- Push the changes to your GitHub repository. Check the changes on GitHub.
Summary
The outer shell of the Onion Architecture is the Infrastructure. It communicates with the inner peels. You use it for data storage, for example.
To be able to store our custom data types and retrieve them afterward, you need to serialize the objects. You use the package Serialization
for this purpose.