6. The Accounts Package from a User Point of View

With using <module name> in your code, you make the exported functions and types immediately accessible in the current scope. You can display the elements by typing Account. followed by pressing twice on the Tab-button.

In this chapter, you define the functions and types that you want to export.

Contents

Accounts.jl

The modified main module with the exports enabled. The user can use the functions and types when he loads the Accounts module.

module Accounts

export EMAIL, WORK # from Domain #1
export create # from API #2
export add_to_file, read_from_file # from Infrastructure #3

include("Domain.jl"); using .Domain
include("API.jl"); using .API
include("Infrastructure.jl"); using .Infrastructure

end

#1 EMAIL and WORK are values we need in the create-function.

#2 The user needs to create addresses and persons

#3 The functions are used to store and retrieve persons.

Activity 6.1: Export Elements

In this activity, you define which functions, and types are exported when a software programmer uses our module Accounts.

Prerequisites

In this activity you will:

  1. Modify Accounts.jl.
  2. Display the Exported Elements.
  3. Update the GitHub Repository.

Step 1: Modify Accounts.jl.

The code contains already the export element, but some lines precede with hashtags. You remove the hashtags.

StepActionComment
1$ cd ~/.julia/dev/AccountsGo to the Accounts project folder.
2$ code .Start Atom/Juno.
3Open the file Accounts.jl
4Remove the hashtagsAccording to section Accounts.jl
5Ctrl-SSave the file.
Step 2: Display the Exported Elements.

The Julia REPL supports code completion using the Tab. With a double Tab, it shows all values you can choose. It works differently in VSCode; use Ctrl-Space and Tab to achieve the same.

StepActionComment
1Ctrl+Shift-PShow All Commands.
2Select: Julia: start REPLStart Julia REPL. The code will be recompiled.
3julia> ]Start the package manager.
4pkg> activate .Open the Accounts environment.
5Press: <BackSpace>Return to the REPL.
6julia> using AccountsLoad the Accounts module.
7julia> Accounts. <Tab><Tab>Display the exported elements. DON'T FORGET the dot (.) after Accounts.
julia> Accounts.

API            EMAIL           WORK            create          include
Domain         Infrastructure  add_to_file     eval            read_from_file

Try the following:

StepActionComment
8julia> Accounts.Domain. <Tab><Tab>Show the exported values of the sub-domain Domain.
9julia> fieldnames(Account.Domain.Person) <Enter>Show the fields of the object Person.
10julia> Accounts.Domain.AddressType <Enter>Show the enumarated values of AddressType.
julia> Accounts.Domain.AddressType
Enum Accounts4.Domain.AddressType:
EMAIL = 0
WORK = 1
Step 3: Update the GitHub Repository.

You have done this before.

StepActionComment
1Shift+Ctrl-GOpen Git panel when closed.
2Put the cursor in the field Message (Ctrl+Enter to commit on'Master'`
3Type: Define export elements Account.jl
4On the line Changes, select: +Stage All Changes.
5Click on: Stage All
6At the top of the pane, click on: ✓Click on the checkmark ✓ (Commit) at the top.
7Click on: ∙∙∙Open Views and More Actions menu. It is located in the upper right corner of the pane.
8Select: PushPush your changes to GitHub.
9Verify on GitHub whether you see the uncommented exports in Accounts.jl

test_accounts.jl

We use the package DataFrames in the example code. With DataFrames you can manipulate tabular data. See DataFrames for more information.

The code first starts with loading DataFrames in a try-catch block. When the statement using DataFrames throws an error then it starts the package manager and loads the package.

The high order functions map and filter are used. High order functions use functions as arguments and operates on collections. The functions are mostly anonymous in the form of x -> <expression using x> where x is a consecutive element of the collection.

using Pkg

Pkg.activate(".")

using Accounts

@info("With DataFrames you can manipulate data")
try
  using DataFrames
catch e
  Pkg.add("DataFrames")
  using DataFrames
end

mm_email = create(EMAIL, "mickey@duckcity.com")
dd_email = create(EMAIL, "donald@duckcity.com")
dd_work = create(WORK,
  """
  Magic Kingdom
  1180 Seven Seas Dr
  Lake Buena Vista
  FL 32830
  United States
  """
)

dd_addresses = [dd_email, dd_work]

donald = create("Donald Duck", dd_addresses)
mickey = create("Mickey Mouse", [mm_email])

@info("Save and retrieve the data")

const FILE_ACCOUNTS = "./test_accounts.txt"

@info("Add Donald and Mickey to a file")
add_to_file(FILE_ACCOUNTS, [donald, mickey])

@info("Read the data from the file and pass it to a DataFrame")
df = read_from_file(FILE_ACCOUNTS) |> DataFrame

# @info("Describe DataFrame df")
# println(describe(df))

@info("Show some data")
println(df.name)

@info("Print all rows and two columns")
println(df[:, [:created, :name]])

@info "Add a column email"
df[!, :email] = map(x -> (filter(y -> y.address_type == EMAIL, x))[1].address, df[:, :addresses])
println(df[:, [:created, :name, :email]])

@info("Remove the file $FILE_ACCOUNTS")
try
  rm("$FILE_ACCOUNTS") # remove the file
  @warn("File $FILE_ACCOUNTS removed from disk")
catch e
  @warn(e.msg)
end

Activity 6.2: Test the Module as User

Users add Julia packages they need for their application. It can also be Julia packages on GitHub that are not registered like our Accounts.jl module. You need the URL of the package.

Requisites

  • Ubuntu 20.04.
  • Julia 1.5+ installed.
  • VSCode installed.
  • Git installed.
  • GitHub repository of Accounts is available on GitHub.

In this activity you will:

  1. Add and Test the Module Accounts.jl from GitHub.
  2. Create a program that uses Accounts.jl.

Step 1: Add and Test the Module Accounts.jl from GitHub.

You can add a package from GitHub. The package name must end on .jl. The add command of the package manager accepts a URL as an argument.

StepActionComment
1$ cd projectsCreate the folder projects when it doesn't exist.
2$ mkdir TestAccounts
3$ cd TestAccounts
4$ code .Start CVSCode.
5Ctrl+Shift-PShow All Commands.
6Select: Julia: start REPLStart Julia REPL. The code will be compiled.
7julia> ]Open package manager.
8pkg> activate .Activate local environment.
9(TestAccounts) pkg> add https://github.com/<your account name>/Accounts.jlLoad the package. Use rbontekoe as an account name in case you don't have a GitHub repository of Accounts yourself.
10(TestAccounts) pkg>test AccountsRun the tests.
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

If you use rbontekoe as account name you get another message, because in exercise 6.1 you will change the test code:

Test Summary: | Pass  Total
Accounts.jl   |    1      1
    Testing Accounts tests passed 
Step 2: Create a program that uses Accounts.jl.
StepActionComment
1Press: <BackSpace>Press the BackSpace button to return to Julia.
2File > New File
3Ctrl-SSave the file and give it the name, e.g. test_accounts.jl.
4Press: <Enter>Create the file.
5Paste the code under the section test_ accounts.jl in the file
6Ctrl-SSave the file.
7Use repeatably Alt-Enter to execute the linesRun the code line by line.

The output looks like:

environment at `~/.julia/dev/Accounts/Project.toml`
[ Info: With DataFrames you can manipulate data
[ Info: Save and retrieve the data
[ Info: Add Donald and Mickey to a file
[ Info: Read the data from the file and pass it to a DataFrame
[ Info: Show some data
["Donald Duck", "Mickey Mouse"]

[ Info: Print all rows
│ Row │ created                 │ name         │
│     │ Dates.DateTime          │ String       │
├─────┼─────────────────────────┼──────────────┤
│ 1   │ 2020-08-19T12:07:12.236 │ Donald Duck  │
│ 2   │ 2020-08-19T12:07:12.605 │ Mickey Mouse │

[ Info: Add a column email
2×3 DataFrame
│ Row │ created                 │ name         │ email               │
│     │ Dates.DateTime          │ String       │ String              │
├─────┼─────────────────────────┼──────────────┼─────────────────────┤
│ 1   │ 2020-08-19T12:07:12.236 │ Donald Duck  │ donald@duckcity.com │
│ 2   │ 2020-08-19T12:07:12.605 │ Mickey Mouse │ mickey@duckcity.com │

[ Info: Remove the file ./test_accounts.txt
┌ Warning: File ./test_accounts.txt removed from disk
└ @ Main ~/.julia/dev/Accounts2/src/test_accounts.jl:56

runtest.jl

The modified runtests.jl file.

using Accounts
using Test

const FILE_ACCOUNTS = "./test_accounts.txt"

@testset "Accounts.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` # linux remove file statement
    run(cmd) # remove file
end

Exercise 6.1: Redefine runtests.jl

In this exercise, you run a test in the folder TestAccounts again with the modified Accounts module.

  1. Return to the Accounts development environment and change the contents of Accounts.jl conform the section runtest.jl.
  2. Go to the package manager and run test Accounts.
  3. Push the changes to your GitHub repository.
  4. Go to the TestAccounts folder, start VSCode and the Julia REPL, and activate the next package manager commands:
  • activate .
  • status
  • update Accounts
  • test Accounts
(@v1.5) pkg> activate .
 Activating environment at `~/projects/TestAccounts/Project.toml`

(TestAccounts) pkg> status
Status `~/projects/TestAccounts/Project.toml`
  [c01e8521] Accounts v0.1.0 `https://github.com/rbontekoe/Accounts.jl#master`
  [a93c6f00] DataFrames v0.21.6

(TestAccounts) pkg> update Accounts
   Updating registry at `~/.julia/registries/General`
######################################################################## 100,0%
   Updating git-repo `https://github.com/rbontekoe/Accounts.jl`
Updating `~/projects/TestAccounts/Project.toml`
  [c01e8521] ~ Accounts v0.1.0 `https://github.com/rbontekoe/Accounts.jl#master` ⇒ v0.1.0 `https://github.com/rbontekoe/Accounts.jl#master`
Updating `~/projects/TestAccounts/Manifest.toml`
  [c01e8521] ~ Accounts v0.1.0 `https://github.com/rbontekoe/Accounts.jl#master` ⇒ v0.1.0 `https://github.com/rbontekoe/Accounts.jl#master`

(TestAccounts) pkg> test Accounts
    Testing Accounts

Test Summary: | Pass  Total
Accounts.jl   |    1      1
    Testing Accounts tests passed

You might decide to change the version number of the module, for example to 0.2.0. You change the version number in the file Project.toml.

name = "Accounts"
uuid = "c01e8521-f333-4719-ae6f-8e8181cc4e4d"
authors = ["Rob Bontekoe <rbontekoe@appligate.nl> and contributors"]
version = "0.1.0"

The version number consists of three parts, where the notation x.y.z has the following meaning:

  • x = main version number, 0-~.
  • y = feature number, 1-~. Increase this number if the change contains new features with or without bug fixes.
  • z = hotfix number, 0-~. Increase this number if the change only contains bug fixes.

Summary

When you use an unregistered Julia package from GitHub, you can add it with the package manager. The add command needs the URL as an argument without the .git extension.