# Archeometer

Archeometer is a laboratory and a set of tools for understanding Elixir code bases from
the point of view of design, architecture and code quality. You can use Archeometer to
conduct investigations about the real architecture and quality of a given project, or
simply to have a better understanding of the project you've just arrived.

Among other things, you can

- Get a queryable inventory of applications, modules, functions and macros.
- Investigate code properties: size, cyclomatic complexity, coverage.
- Visualize dependencies between applications and modules.
- Detect cyclic dependencies.

The goal is to provide you the tools to obtain insights into how a project is organized
and how it could be improved.

## Installation

Simply add `archeometer` as a dependency to your project. If you already use Credo, be
sure to use at least the `1.6.6` version.

def deps do
    # If you want to use the latest public release
    {:archeometer, "~> 0.5"},

    # Or if you prefer living on the edge, use this instead
    # {:archeometer, git: ""},

    # and if you already use Credo, be sure to use at least the 1.6.6 version
    {:credo, "~> 1.6", only: [:dev, :test], runtime: false}

Or alternatively, you can clone this repository and add the dependency as a  `path:
"path/to/the/repo"` instead.

## Usage

### Collecting Data
To collect all the data in a single run, try this
mix arch.collect

A SQLite database will be created in your local directory with all the collected data.

You can skip running tests (for example, it tests take too long to run or if they are
broken) and collecting coverage information with the `--no-coverage` flag.

mix arch.collect --no-coverage

Under the hood, data collection is divided in several phases.

You can also run each phase individually. They are:

- `mix arch.collect.static`: to run the static analysis section and create the database;
  it needs Credo,
- `mix arch.collect.xrefs`: collects cross reference data; it needs to force compile the
- `mix arch.collect.apps`: collects OTP application data; it needs the project to be
  previously compiled.
- `mix arch.collect.ecto`: collects modules with Ecto schema and their associations.
- `mix arch.collect.credo_issues`: to run Credo and collect the issues it found.
- `mix arch.collect.coverage`: collects test coverage information; it requires to run all
  the tests.

### Include dependencies in analysis

You can target dependencies in the project with the tasks `collect.static`,
`collect.apps`, `collect.xrefs` and `collect.ecto`. Pass the flag `--include-deps
'filter'`  where 'filter' is a dependency name or a wildcard expression, example.


mix arch.collect.static --include-deps "phoenix*"


   For more information  see: [Basic usage guide](guides/introduction/

### Mix tasks

There are some predefined tasks that can help you to have an overview of the project under
the lens.

`mix`: Creates a comprehensive report for the project under review. The report
contains lots of examples about how you can use `Archeometer`. Adding the `--format
livemd` option creates [Livebook]( notebooks!

![HTML Report](guides/img/

Documentation for [](

`mix arch.apps.xref --format png --out apps.png` will create a dependency graph between
the applications in your umbrella project.

![Apps Xrefs](guides/img/arch.apps.xref.png)

Documentation for

`mix arch.dsm`: will create a [Design Structure
Matrix](, and will use it to find the cyclic
dependencies in the project. In the following example, colored squares represents groups
of modules whose dependencies form cycles.


Documentation for [arch.dsm](

The cycles can be confirmed with yet another task: `mix arch.xref --format png --out
out.png Mod1 Mod2... ModN` will create the dependency graph of the given module names.


Documentation for [arch.xref](

`mix arch.treemap --app jissai --out jissai_treemap.svg`: will generate a
[treemap]( of the modules within an specific
application, thus allowing you to visually understand the relative size of each module,


Documentation for

### Code Query Language

Besides mix tasks, we created a Code Query Language (CQL) that you can use to make your
own investigations. For example, to get the list of the biggest modules in a specific
application, you can use

iex(10)> Repo.all(
...(10)>   from m in Module,
...(10)>   select: [
...(10)>     name:,
...(10)>     num_lines: m.num_lines
...(10)>   ],
...(10)>   order_by: [desc: num_lines],
...(10)>   where: == "jissai",
...(10)>   limit: 10
...(10)> ) |> IO.puts()
 |name                         |num_lines |
 |---------------------------- |--------- |
 |Jissai.AtamaData             |504       |
 |Jissai.AnalyticsMock         |496       |
 |Jissai.AtamaDataMock         |458       |
 |Jissai.ProcessAlgorithmsTest |428       |
 |Jissai.AtamaDataTest         |420       |
 |Jissai.Reports               |361       |
 |Jissai.DataAnalysisMock      |359       |
 |Jissai.ReportProvider        |355       |
 |Jissai.ClassDynamicsProcess  |349       |
 |Jissai.ReportsTest           |345       |


The CQL and available schemas (Modules, Apps, Functions, XRefs, Behaviours, Macros) are
documented [here](

### Directly poke at the database

For everything else, you can always run SQL queries directly into the generated database.
For example, the SQL equivalent of the last example would be

select, m.num_lines
from modules m
inner join apps a on m.app_id =
where = 'jissai'
order by m.num_lines desc
limit 10;

There are plenty of more examples in the

## Setup for development

To use the correct Erlang and Elixir version we use [asdf-vm]( You
need to run

asdf install

on the root of the repository.

To add the git hooks you must change the default hooks path to `githooks` using the
following command

git config core.hooksPath .githooks

with this, before each commit the hook will find issues related with compilation errors
and warnings, failures in tests, issues or warnings in Credo and a correct code

### Third party dependencies

Some non Elixir dependencies are necessary:

- [SQLite]( : is used to store all the project
- [Graphviz]( : to create `png` dependency graphs