6

Dep Tree - a tool for rendering and linting your project's dependency tree in th...

 2 years ago
source link: https://dev.to/gabotechs/dep-tree-a-tool-for-rendering-and-linting-your-projects-dependency-tree-in-the-terminal-25om
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Dep Tree

https://github.com/gabotechs/dep-tree

Coding is a team sport, and team members should agree on conventions and strategies for taking projects across the line.

For example, team members may agree on a specific code style, and configure linters for enforcing it, that way no one can’t get their code merged without first be compliant with the styling rules.

Team members could also choose to agree on strategies for managing dependencies, something like “files in folder X” should never depend on “anything under folder Y”. A clean dependency management is crucial for a project’s maintainability and scalability in the long term, but there is not that many tools for enforcing dependency higiene as there is for code style higiene.

Dep Tree aims to solve this, not only by allowing developers to visualize in an interactive way their project’s dependency tree, but also by providing a tool for enforcing some user-defined dependency rules. Something like a linter, but for dependencies.

Dependency tree visualization

The first step for knowing how messy a project is, is by graphically visualizing it. Dep Tree allows rendering an interactive dependency tree in the terminal, which is super useful for understanding what pieces of a project depend on what, and what other things are correctly decoupled.

Take this project of mine as an example: https://github.com/gabotechs/react-gcode-viewer

That project is just a very simple React component library, and as usually, it has an entrypoint in src/index.ts. A very important thing to note, is that there is always an entrypoint, either the index file used for exposing a library, or the executable file with the program’s main function.

Running dep-tree render src/index.ts under that project’s root folder will render something like this in the terminal:

index.ts                                                                        
│                                                                               
└▷GCodeViewer/GCodeViewer.tsx                                                   
  │                                                                             
  ├▷GCodeViewer/GCodeModel.tsx                                                  
  └▷│GCodeViewer/gcode/reader/UrlReader.ts                                      
    ││                                                                          
    ├│▷GCodeViewer/GCodeLines.tsx                                               
    ├│▷│GCodeViewer/SceneElements/Camera.tsx                                    
    ├│▷│GCodeViewer/SceneElements/Floor.tsx                                     
    ├│▷│GCodeViewer/SceneElements/OrbitControls.tsx                             
    ├│▷│GCodeViewer/gcode/GCode.ts                                              
    │└▷││GCodeViewer/gcode/reader/base.ts                                       
    │  ││                                                                       
    │  │├─▷GCodeViewer/gcode/parser.ts                                          
    │  ││  │                                                                    
    └──┴┴──┴▷GCodeViewer/gcode/types.ts

💡 Dep Tree does not check third-party dependencies, it will only take into account the source code of the project, ignoring any dependency to a external library.

This is just copy-pasted from a terminal, but the truth is that users can navigate through the entries using the keyboard, and select specific entries for rendering their isolated dependency trees.

Demo Gif

Dependency rules check

Once users are already aware of how messy their project’s dependencies are, they may choose to fix it and enforce some dependency rules. In the same way that developers configure linters for checking that new code matches the expected style, they can define rules to ensure that new code does not introduce dependencies between parts of the application that are meant to be decoupled.

In Dep Tree, this rules are defined in a .dep-tree.yml file in the root of the project with the following structure:

entrypoints:
  - src/index.ts
allow:
  "this-folder-can-only-depend-on.../**":
    - "this/*.ts"
    - "and-this/*.ts"
deny:
  "this-one-cannot-depend-on.../**":
    - "not-this/*.ts"
    - "neither-this/*.ts"

Some real life examples:

⚛ React pages and components

Imagine a React application, with a pages folder and a components folder. Probably, files under pages will use the reusable components defined in components for building whole pages, but components are just isolated testable components that should not depend on page-specific details:

entrypoints:
  - src/app.tsx
deny:
  "src/components/**/*.tsx":
    - "src/pages/**"

running dep-tree check with this .dep-tree.yml file would fail if any component tries to depend on something that lives under the pages folder.

🔧 The classic utils folder

Who hasn’t dealt with this? a project that starts being a small thing, with some innocent helper functions that are placed under a utils folder. Then the project keeps growing, every new addition has its own “util” function or class, and because of the vague and generic meaning of the word “util”, everything can be considered a “util”. Some months later half of the project ends up living in a utils folder.

entrypoints:
  - src/main.ts
allow:
  "src/utils/**":
    - "src/utils/**"

This config will limit files under src/utils to only import other files under src/utils. That way a “util” can’t depend on parts of the application with business logic important for a specific functionality, developers are forced to colocate things that are designed for functionality X under the folder designed for functionality X, and the utils folder is left just for some generic and basic helper functions.

🔄 Dependency inversion

Last letter of the SOLID principles and one of the most powerful tools in software development, but lets directly dive-in in a real world example:

An application that is in charge of managing users, that uses MySQL as a database, will probably have some MySQL client code under src/mysql-client, and some user management code under src/users. As the application is using MySQL for persisting user information, then the code under src/users will depend on src/mysql-client for storing the users.

The src/users high level module is depending on the src/mysql-client low level module, which has some serious impact in testability in isolation of infrastructure-specific details, or in other words, not needing a whole MySQL database running just for testing src/users.

Dependency inversion can help here by breaking the dependency between both modules, putting an interface in between, and making src/mysql-client depend on that interface. But explaining how dependency inversion work is out of the scope here, so let's see directly how Dep Tree can help here:

entrypoints:
  - src/main.ts
deny:
  "src/users/**":
    - "src/mysql-client/**"

This will enforce the src/users module to not depend on MySQL-specific details.

Even better, if all the infrastructure-specific code is gathered under a infra package, the dependency banning can go even further:

entrypoints:
  - src/main.ts
deny:
  "src/users/**":
    - "infra/**"

Summary

Dep Tree aims to be another automated tool for helping in the maintainability of medium/large code bases. It helps to understand the dependency flow of an application and provides tools for validating it against the rules defined in a configuration file.

If you find it helpful, feel free to stop by the source repository https://github.com/gabotechs/dep-tree and give it a try, feedback is much appreciated!


Recommend

  • 102

    webhint Quick start user guide webhint is a customizable linting tool that helps you improve your site's accessibility, speed, cross-browser compatibility, and more by checking your code for best practices and common errors....

  • 60

    README.md xiblint The xiblint script will test .xib and .storyboard files for compliance with best practices and team policies. The...

  • 8
    • zhuanlan.zhihu.com 4 years ago
    • Cache

    wepack 之 dependency tree

    halo,大家好,我是西天小如来 132,米娜好久不贱,真的好久好久 最近状态特别不好,工作上做了一个短期不会产生收益的项目,加上最近老被质疑,有点怀疑人生了…… 其实,我在公司里,写的是一个叫 wepack 的轮子...

  • 5
    • bugs.webkit.org 3 years ago
    • Cache

    Dependency tree for Bug 208988

    Dependency tree for Bug 208988 WebKit Bugzilla Dependency tree for Bug 208988: [WebXR] Implement WebXR device API

  • 3
    • blog.knoldus.com 3 years ago
    • Cache

    Reading SBT dependency tree

    Reading Time: 3 minutes In this post, we are going to look into reading sbt dependency tree and resolving one of the scenario using an example.

  • 4

    My week started with way more work than expected. Today I started today off by finishing the JS Basics portion of FreeCodeCamp. These lessons seem to be very well structured, so I'm going to continue with this course...

  • 9
    • deepsource.io 3 years ago
    • Cache

    Lightweight linting with tree-sitter

    Tree-sitter queries allow you to search for patterns in syntax trees, much like a regex...

  • 4

    IntroductionGreat to see you take an interest to understand the impact of dependency tree depth on your Gradle builds.After you finish reading this article here is what you’ll take away, depending on where you are...

  • 8
    • blog.droidchef.dev 2 years ago
    • Cache

    Mastering The Gradle Dependency Tree

    Mastering The Gradle Dependency Tree Jan 11, 2023...

  • 6

    Attention TypeScript Developers: Are You Linting Your Files All Wrong?Transform Your TypeScript Projects Overnight with This Mind-Blowing Linting Secret!...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK