Giter VIP home page Giter VIP logo

archan's Introduction

Archan

ci documentation pypi version gitpod gitter

Analysis of your architecture strength based on DSM data.

A Python module that analyzes your architecture strength based on Design Structure Matrix (DSM) data.

Archan is a Python module that analyzes the strength of your project architecture according to some criteria described in "The Protection of Information in Computer Systems", written by Jerome H. Saltzer and Michael D. Schroeder.

Features

  • Usable directly on the command-line.
  • Support for plugins. See for example the Provider plugin in dependenpy. You can also take a look at django-meerkat, a Django app using Archan.
  • Configurable through command-line or configuration file (YAML format).
  • Read DSM data on standard input.

Installation

With pip:

pip install archan

With pipx:

python3.8 -m pip install --user pipx
pipx install archan

Usage

Archan defines three main classes: Analyzer, Provider and Checker. A provider is an object that will produce data and return it in the form of a DSM (Design Structure Matrix). The checker is an object that will analyze this DSM according to some criteria, and return a status code saying if the criteria are verified or not. An analyzer is just a combination of providers and checkers to run a analysis test suite.

On the command-line

Examples:

$ archan -h
usage: archan [-c FILE] [-h] [-i FILE] [-l] [--no-color] [--no-config] [-v]

Analysis of your architecture strength based on DSM data

optional arguments:
    -c FILE, --config FILE  Configuration file to use.
    -h, --help              Show this help message and exit.
    -i FILE, --input FILE   Input file containing CSV data.
    -l, --list-plugins      Show the available plugins. Default: false.
    --no-color              Do not use colors. Default: false.
    --no-config             Do not load configuration from file. Default: false.
    -v, --version           Show the current version of the program and exit.
# See a list of all supported Archan plugins
archan --list-plugins

# Archan can locate the configuration file automatically (See the Configuration section)
archan
# or a specific configuration can be specified
archan --config my_config.yml

# Archan can load DSM data in CSV format such as the output from dependenpy (install separately)
dependenpy pytest --format=csv --output pytest_dsm.csv

# Read CSV data from file (No configuration)
archan --no-config --input pytest_dsm.csv
# or read CSV data from STDIN
dependenpy pytest --format=csv | archan --no-config

Configuration

Archan applies the following methods to find the configuration file folder:

  1. read the contents of the file .configconfig in the current directory to get the path to the configuration directory,
  2. use config folder in the current directory if it exists,
  3. use the current directory.

It then searches for a configuration file named:

  1. archan.yml
  2. archan.yaml
  3. .archan.yml
  4. .archan.yaml

Format of the configuration file is as follow:

analyzers: [list of strings and/or dict]
  - identifier: [optional string]
      name: [string]
      description: [string]
      providers: [string or list]
        - provider.Name: [as string or dict]
            provider_arguments: as key value pairs
      checkers: [string or list]
        - checker.Name: [as string or dict]
            checker_arguments: as key value pairs

It means you can write:

analyzers:
  # a first analyzer with one provider and several checker
  - name: My first analyzer
      description: Optional description
      providers: just.UseThisProvider
      checkers:
        - and.ThisChecker
        - and.ThisOtherChecker:
            which: has
            some: arguments
  # a second analyzer with several providers and one checker
  - name: My second analyzer
      providers:
        - use.ThisProvider
      checkers: and.ThisChecker
  # a third analyzer, using its name directly
  - some.Analyzer

Every checker support an ignore argument, set to True or False (default). If set to True, the check will not make the test suit fail.

You can reuse the same providers and checkers in different analyzers, they will be instantiated as different objects and won't interfere between each other.

As an example, see Archan's own configuration file.

To get the list of available plugins in your current environment, run archan --list-plugins or archan -l.

Writing a plugin

Plugin discovery

You can write three types of plugins: analyzers, providers and checkers. Your plugin does not need to be in an installable package. All it needs to be summoned is to be available in your current Python path. However, if you want it to be automatically discovered by Archan, you will have to make it installable, through pip or simply python setup.py install command or equivalent.

If you decide to write a Python package for your plugin, I recommend you to name it archan-your-plugin for consistency. If you plan to make it live along other code in an already existing package, just leave the name as it is.

To make your plugin discoverable by Archan, use the archan entry point in your setup.py:

from setuptools import setup

setup(
    ...,
    'entry_points': {
        'archan': [
            'mypackage.MyPlugin = mypackage.mymodule:MyPlugin',
        ]
    }

If you build your package with Poetry, use this instead:

[tool.poetry.plugins.archan]
"mypackage.MyPlugin" = "mkdocstrings.plugin:MkdocstringsPlugin"

The name of the entry point should by convention be composed of the name of your package in lower case, a dot, and the name of the Python class, though you can name it whatever you want. Remember that this name will be the one used in the configuration file.

Also a good thing is to make the plugin importable thanks to its name only:

import mypackage.MyPlugin

But again, this is just a convention.

Plugin class

You can write three types of plugins: analyzers, providers and checkers. For each of them, you have to inherit from its corresponding class:

from archan import Analyzer, Provider, Checker

class MyAnalyzer(Analyzer): ...
class MyProvider(Provider): ...
class MyChecker(Checker): ...

A provider or checker plugin must have the following class attributes:

  • identifier: the identifier of the plugin. It must be the same name as in your entry points, so that displaying its help tells how to summon it.
  • name: the verbose name of the plugin.
  • description: a description to explain what it does.
  • (optional) arguments: a tuple/list of Argument instances. This one is only used to display some help for the plugin. An argument is composed of a name, a type, a description and a default value.
from archan import Provider, Argument

class MyProvider(Provider):
    identifier = 'mypackage.MyProvider'
    name = 'This is my Provider'
    description = """
    Don't hesitate to use multi-line strings as the lines will be de-indented,
    concatenated again and wrapped to match the console width.

    Blank lines will be kept though, so the above line will not be removed.
    """

    arguments = (
        Argument('my_arg', int, 'This argument is useful.', 42),
        # don't forget the ending comma if you have just one   ^   argument
    )

Additionally, a checker plugin should have the hint class attribute (string). The hint describe what you should do if the check fails.

For now, the analyzers plugins just have the providers and checkers class attributes.

Plugin methods

A provider must implement the get_dsm(self, **kwargs) method. This method must return an instance of DSM. A DSM is composed of a two-dimensions array, the matrix, a list of strings, the keys or names for each line/column of the matrix, and optionally the categories for each key (a list of same size).

from archan import DSM, Provider

class MyProvider(Provider):
    name = 'mypackage.MyProvider'

    def get_dsm(self, my_arg=42, **kwargs):
        # this is where you compute your stuff
        matrix_data = [...]
        entities = [...]
        categories = [...] or None
        # and return a DSM instance
        return DSM(matrix_data, entities, categories)

A checker must implement the check(self, dsm, **kwargs) method.

from archan import DSM, Checker

class MyChecker(Checker):
    name = 'mypackage.MyChecker'

    def check(self, dsm, **kwargs):
        # this is where you check your stuff
        # with dsm.data, dsm.entities, dsm.categories, dsm.size (rows, columns)
        ...
        # and return True, False, or a constant from Checker: PASSED or FAILED
        # with an optional message
        return Checker.FAILED, 'too much issues in module XXX'

Logging messages

Each plugin instance has a logger attribute available. Use it to log messages with self.logger.debug, info, warning, error or critical.

Available plugins

Here is the list of plugins available in other packages.

See other plugins published to PyPi by searching for "archan-"

Providers

  • dependenpy.InternalDependencies: Provide matrix data about internal dependencies in a set of packages. Install it with pip install dependenpy.

archan's People

Contributors

kyleking avatar pawamoy avatar pyup-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

woosuk1103

archan's Issues

Initial Update

Hi 👊

This is my first visit to this fine repo, but it seems you have been working hard to keep all dependencies updated so far.

Once you have closed this issue, I'll create seperate pull requests for every update as soon as I find one.

That's it for now!

Happy merging! 🤖

Quick Start Questions

I started asking a question, then mostly answered it. This is the condensed version number ~5. Essentially I just ran into a bunch of issues understanding how archan works and how to apply it to my project. I think my below notes might be helpful to others and could be optionally integrated to the README

Would you consider reordering the example commands? I think creating the CSV with dependenpy might be the most common use case and would be helpful if listed first. I wasn't sure where the CSV files were coming from until I dug further

# Generate CSV DSM data for archan (dependenpy must be installed)
dependenpy archan --format=csv archan_dsm.csv

# No configuration, read CSV data from file
archan --no-config --input archan_dsm.csv
# or read CSV data from STDIN
dependenpy archan --format=csv | archan --no-config

# Load configuration file and run archan (see Configuration section to know how archan finds the config file)
archan
# or specify the configuration file to load
archan --config my_config.yml

# Output the list of available plugins in the current environment
archan --list-plugins

I created a modified version of the archan config, but I had to comment out the names to prevent skipping the steps:

analysis:
  archan_pylint.PylintProvider:
    # name: Pylint
    arguments:
      pylint_args:
        - dash_charts
    checkers:
      archan.CodeClean:
        allow_failure: true
        arguments:
          threshold: 10
  dependenpy.InternalDependencies:
    # name: Software Architecture
    arguments:
      packages:
        - dash_charts
    checkers:
      - archan.CompleteMediation
      - archan.EconomyOfMechanism:
          allow_failure: true
          arguments:
            simplicity_factor: 2
      - archan.LayeredArchitecture
      - archan.LeastCommonMechanism:
          allow_failure: true
          arguments:
            independence_factor: 5
  Open Design:
    Source Code: true

Installed the dependencies and ran archan

> poetry add dependenpy git+https://github.com/pawamoy/archan-pylint.git git+https://github.com/pawamoy/archan.git -D

Updating dependencies
Resolving dependencies... (25.4s)

Writing lock file

Package operations: 8 installs, 0 updates, 0 removals

  • Installing dependenpy (3.3.0)
  • Installing lazy-object-proxy (1.4.3)
  • Installing wrapt (1.12.1)
  • Installing astroid (2.4.2)
  • Installing pylint (2.6.0)
  • Installing archan-pylint (0.1.0 ef4a609)
  • Installing tap.py (3.0)
  • Installing archan (0.3.0 9443064)

❯ poetry run archan -c .archan.yaml
TAP version 13
# TAP results for Pylint Provider: Issues per Module
ok 1 Code Clean (ALLOWED FAILURE)
# TAP results for Internal Dependencies
ok 2 Complete Mediation
ok 3 Economy of Mechanism
ok 4 Layered Architecture
ok 5 Least Common Mechanism (ALLOWED FAILURE)
# TAP results for Open Design
ok 6 Source Code

On a side-note, can you publish a new wheel to PyPi? The current one has a typo bug for .ingo and some API differences (notably analyzers vs. analysis)

Windows?

What work is there to port this to windows?

Example CSV files?

Would it be too much to ask to include examples of CSV files to help people try to reverse engineer how this software is working please?

Rework the way archan uses groups

Currently, the user is forced to use the following names for groups:

  • framework
  • core_lib
  • app_lib
  • app_module
  • broker
  • data

It must be more flexible. It would allow a better integration in django-archan

Update documentation

  • new ignore param on all checkers
  • new identifier class attributes on every plugin
  • usage of self.logger in plugins
  • new YAML format: identifier, name and description

Implement checks

  • Layered architecture
  • Code clean: some pyflakes and mccabe on app modules
  • Open design: will be okay when all others will be implemented
  • Least privileges: need user/object access matrix
  • Separation of privileges: like above

Add capabilities to DSM class

The DSM class should beneficiates from other methods related to adjacency matrices. See the wikipedia pages to list some functions that could be of interest, then implement them. We could have functions to change/sort the order of the elements, and also transitive closure function.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.