Import-linter was useful for layered architecture in Python

Overview

Even when developing in Python, the design may be based on a layered architecture. At that time, you may want to check the direction of dependence.

project_root/
  ├ infrastructure/
  │ └ db
  ├ interface/
  │ └ controllers
  ├ application/
  │ └ service
  └ domain/
    └ entity

As an example, consider the above package configuration. Suppose you define the direction of the dependency in the form infrastructure-> interface-> application-> domain. You can easily fix it by using import-linter to automatically check for imports that break the rules during development.

Sample repository is available. See here for the entire source code.

How to use

$ pip install import-linter

Define the layer definition and dependency direction with setup.cfg or .importlinter. First, define the layer in the [importlinter] section.

[importlinter]
root_packages =
    infrastructure
    interface
    application
    domain

type = layers is a rule setting for layered architecture. The direction of dependence is expressed in the order of layers.

[importlinter:contract:1]
name = layered architecture contract
type = layers
layers =
    infrastructure
    interface
    application
    domain

There are various options (https://github.com/seddonym/import-linter/tree/master/docs) that allow you to configure flexible rules. For example, if you want to limit the import of flask packages to a specific layer, you can enable include_external_packages and define it with type = forbidden as shown below.

[importlinter]
root_packages =
    infrastructure
    interface
    application
    domain
include_external_packages = True

[importlinter:contract:2]
name = Do not use `flask` outside the interface layer.
type = forbidden
source_modules =
    infrastructure
    application
    domain
forbidden_modules =
    flask

To check

After completing the rule settings, check with the following command.

$ lint-imports

pipenv run lintfix                                                                                                                            ✘ 1 main ✚ ✱ ◼
Skipped 2 files
=============
Import Linter
=============

---------
Contracts
---------

Analyzed 14 files, 15 dependencies.
-----------------------------------

Layered architecture contract BROKEN
Do not use `flask` outside the interface layer. BROKEN

Contracts: 0 kept, 2 broken.


----------------
Broken contracts
----------------

Layered architecture contract
-----------------------------

domain is not allowed to import application:

- domain.entity -> application.repository (l.5)


Do not use `flask` outside the interface layer.
-----------------------------------------------

infrastructure is not allowed to import flask:

-   infrastructure.db -> domain.entity (l.4)
    domain.entity -> flask (l.3)


application is not allowed to import flask:

-   application.repository -> domain.entity (l.4)
    domain.entity -> flask (l.3)

-   application.service -> domain.entity (l.6)
    domain.entity -> flask (l.3)


domain is not allowed to import flask:

-   domain.entity -> flask (l.3)

If there is code that violates the rule, it will display an error.

Let's define it in the CI tool and have it checked at the time of PR.

Recommended Posts

Import-linter was useful for layered architecture in Python
Love was born in Python 2
Think about architecture in python
Search for strings in Python
Techniques for sorting in Python
Love was born in Python 3
About "for _ in range ():" in python
Useful tricks related to list and for statements in Python
Check for memory leaks in Python
Check for external commands in python
Run unittests in Python (for beginners)
Notes on nfc.ContactlessFrontend () for nfcpy in python
Inject is recommended for DDD in Python
Tips for dealing with binaries in Python
Summary of various for statements in Python
Type annotations for Python2 in stub files!
Template for writing batch scripts in python
Process multiple lists with for in Python
MongoDB for the first time in Python
[Python] Script useful for Excel / csv processing
Zope.interface is useful for practicing Hexagonal Architecture
Get a token for conoha in python
Sample for handling eml files in Python
AtCoder cheat sheet in python (for myself)
Summary of useful techniques for Python Scrapy
I searched for prime numbers in python
Notes for using python (pydev) in eclipse
Tips for making small tools in python
Use pathlib in Maya (Python 2.7) for upcoming Python 3.7
A useful note when using Python for the first time in a while
Practical example of Hexagonal Architecture in Python
Template for creating command line applications in Python
CERTIFICATE_VERIFY_FAILED in Python 3.6, the official installer for macOS
++ and-cannot be used for increment / decrement in python
I was able to recurse in Python: lambda
Add quotation marks ">" for replying emails in Python3
Logging settings for daily log rotation in python
Tips for hitting the ATND API in Python
Display candlesticks for FX (forex) data in Python
Boost.NumPy Tutorial for Extending Python in C ++ (Practice)
Zero padding for dynamic variable values in Python
Try to calculate RPN in Python (for beginners)
Notes for implementing simple collaborative filtering in Python
Don't use readlines () in your Python for statement!
PDF files and sites useful for learning Python 3
[Implementation for learning] Implement Stratified Sampling in Python (1)
Settings for Python coding in Visual Studio Code
[Introduction for beginners] Working with MySQL in Python
Basic story of inheritance in Python (for beginners)
Settings for getting started with MongoDB in python
2016-10-30 else for Python3> for:
Quadtree in Python --2
Python in optimization
python [for myself]
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Unittest in python
Selenium-Screenshot is useful for screenshots of web pages in Python3, Selenium and Google Chrome