Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Graphs are unreadable past 15 dependencies #289

Open
fregante opened this issue Jul 17, 2021 · 5 comments
Open

Graphs are unreadable past 15 dependencies #289

fregante opened this issue Jul 17, 2021 · 5 comments
Labels
viz visualization enhancement, graphviz

Comments

@fregante
Copy link

fregante commented Jul 17, 2021

Hi! This is a great tool but I'm struggling to make it useful. Graphs are not a great way to represent dependencies because shared dependencies are pulled so far right and away from their importers, forcing you to follow thousands of pixels of lines.

a

The entry point has 6 direct dependencies, can you spot them in less than 10 seconds? 10 seconds is a long time to spot 6 dependencies.

The solution here is to use the textual output and that cleanly shows you the 6 dependencies… if you only find the entry point in this list in alphabetical order:

auth/token.ts
  ../node_modules/fast-deep-equal/index.js
  ../node_modules/js-cookie/src/js.cookie.js
  ../node_modules/webextension-polyfill-ts/lib/index.js
  chrome.ts
  telemetry/rollbar.ts
background/logging.ts
  ../node_modules/idb/with-async-ittr.js
  ../node_modules/lodash/lodash.js
  ../node_modules/serialize-error/index.js
  ../node_modules/type-fest/index.d.ts
  ../node_modules/uuid/dist/index.js
  ../node_modules/webext-detect-page/index.js
  background/protocol.ts
  background/telemetry.ts
  chrome.ts
  contentScript/connection.ts
  core.ts
  errors.ts
  telemetry/rollbar.ts
  utils/expectContext.ts
background/popup.ts
  ../node_modules/webextension-polyfill-ts/lib/index.js
  background/protocol.ts
  helpers.ts
  utils/expectContext.ts
background/protocol.ts
  ../node_modules/serialize-error/index.js
  ../node_modules/uuid/dist/index.js
  ../node_modules/webext-detect-page/index.js
  ../node_modules/webext-patterns/index.js
  ../node_modules/webext-polyfill-kinda/index.js
  ../node_modules/webextension-polyfill-ts/lib/index.js
  chrome.ts
  messaging/protocol.ts
background/telemetry.ts
  ../node_modules/axios/index.js
  ../node_modules/lodash/lodash.js
  ../node_modules/type-fest/index.d.ts
  ../node_modules/uuid/dist/index.js
  ../node_modules/webextension-polyfill-ts/lib/index.js
  auth/token.ts
  background/protocol.ts
  chrome.ts
  options/loader.ts
  services/baseService.ts
  utils.ts
chrome.ts
  ../node_modules/lodash/isEmpty.js
  ../node_modules/p-defer/index.js
  ../node_modules/p-timeout/index.js
  ../node_modules/webext-detect-page/index.js
  ../node_modules/webextension-polyfill-ts/lib/index.js
  utils/expectContext.ts
components/AsyncButton.tsx
  ../node_modules/react-bootstrap/cjs/Button.js
  ../node_modules/react/index.js
contentScript/backgroundProtocol.ts
  ../node_modules/serialize-error/index.js
  ../node_modules/webext-detect-page/index.js
  ../node_modules/webextension-polyfill-ts/lib/index.js
  errors.ts
  messaging/protocol.ts
  utils/expectContext.ts
contentScript/connection.ts
  contentScript/notify.ts
contentScript/notify.ts
  ../node_modules/lodash/lodash.js
  contentScript/backgroundProtocol.ts
core.ts
  ../node_modules/@rjsf/core/dist/cjs/index.js
  ../node_modules/@types/json-schema/index.d.ts
  ../node_modules/axios/index.js
  ../node_modules/lodash/lodash.js
  ../node_modules/serialize-error/index.js
  ../node_modules/type-fest/index.d.ts
  ../node_modules/webextension-polyfill-ts/lib/index.js
devTools/editor/components/Centered.tsx
  ../node_modules/react-bootstrap/cjs/index.js
  ../node_modules/react/index.js
errors.ts
  ../node_modules/serialize-error/index.js
  core.ts
extensionContext.ts
  ../node_modules/webextension-polyfill-ts/lib/index.js
helpers.ts
  ../node_modules/handlebars/lib/index.js
  ../node_modules/lodash/isPlainObject.js
  ../node_modules/lodash/mapKeys.js
  ../node_modules/lodash/mapValues.js
  ../node_modules/lodash/pickBy.js
  ../node_modules/mustache/mustache.js
  ../node_modules/nunjucks/index.js
  core.ts
  utils.ts
messaging/protocol.ts
  ../node_modules/is-promise/index.js
  ../node_modules/serialize-error/index.js
  ../node_modules/webextension-polyfill-ts/lib/index.js
  core.ts
options/loader.ts
  ../node_modules/type-fest/index.d.ts
  ../node_modules/webextension-polyfill-ts/lib/index.js
  core.ts
permissionsPopup.tsx
  ../node_modules/bootstrap/dist/css/bootstrap.min.css
  ../node_modules/react-dom/index.js
  ../node_modules/react/index.js
  extensionContext.ts
  popups/PermissionsPopup.tsx
  telemetry/rollbar.ts
popups/PermissionsPopup.tsx
  ../node_modules/@fortawesome/free-solid-svg-icons/index.js
  ../node_modules/@fortawesome/react-fontawesome/index.js
  ../node_modules/react-bootstrap/cjs/index.js
  ../node_modules/react/index.js
  ../node_modules/webextension-polyfill-ts/lib/index.js
  components/AsyncButton.tsx
  devTools/editor/components/Centered.tsx
  errors.ts
  telemetry/logging.ts
  utils/permissions.ts
services/baseService.ts
  ../node_modules/lodash/isEmpty.js
  ../node_modules/react/index.js
  ../node_modules/use-async-effect/index.js
  chrome.ts
telemetry/logging.ts
  ../node_modules/serialize-error/index.js
  ../node_modules/webext-detect-page/index.js
  background/logging.ts
  chrome.ts
  core.ts
  telemetry/rollbar.ts
telemetry/rollbar.ts
  ../node_modules/rollbar/src/server/rollbar.js
  background/telemetry.ts
  chrome.ts
utils.ts
  ../node_modules/lodash/lodash.js
  ../node_modules/type-fest/index.d.ts
utils/expectContext.ts
  ../node_modules/webext-detect-page/index.js
utils/permissions.ts
  ../node_modules/lodash/groupBy.js
  ../node_modules/lodash/sortBy.js
  ../node_modules/lodash/uniq.js
  ../node_modules/webextension-polyfill-ts/lib/index.js
  background/popup.ts
  background/protocol.ts

Additionally the list is monodimensional: I can see the 6 dependencies, but then I can't follow them easily.

@fregante
Copy link
Author

fregante commented Jul 17, 2021

If you're familiar with macOS, this should give you a good idea of how I'd expect to be able to explore the dependencies in a project:

Screen Shot 1

It gives you a clear view of each dependency and sub dependency:

  • the entry point has 6 dependencies
  • rollbar has 2 dependencies
  • chrome has 1 dependency

It's interactive but doesn't have to be: Shared dependencies can just end with a symbol, e.g. chrome.ts above could just show a non-linked extensionContext.ts item, which is on the second level already.

@fregante
Copy link
Author

I just realized that I can get what I'm suggesting by just opening each file and reading its import statements 🤔

What that lacks though is the ability to see the dependency branch (i.e. not just one list of imports at a time, but both the parents and the children of each dependency, like in the Finder screenshot above)

@PabloLION PabloLION added the viz visualization enhancement, graphviz label Jan 29, 2023
@PabloLION
Copy link
Collaborator

seems hard to do. what about we make the graph "reactive" and nodes and expand / collapse by clicking them?

@c-vetter
Copy link

I think this is a classic case of "what do we want to achieve?" and I agree that the current images are, by their nature and not a fault of madge's, ill-suited for large complex dependency graphs. Since I'm mostly interested in getting help with code organization, I use madge to detect circular dependencies, which it does itself, and to detect improper directionality. What I mean by this are two issues:

  1. a file importing its barrel file – whether or not you like barrel files, some projects use them, and this type of import should always be considered an error, so I check for it in a js script using madge's .obj()
  2. an uptstream module consuming a downstream module, e.g. an atom importing a molecule – the specific relation is project-dependent, but there's usually an implicit hierarchy of scopes and I also check for this by analysing .obj()

I think especially the second case can be illustrative for a better visualization strategy. I'd really like a vizualization that uses columns for scopes, sorting them hierarchically. In such a visualization, all arrows would be expected to point in the same direction, and a mismatch would be easily identifiable. Even without such directionality, just arranging columns for the first level of directories would probably be helpful.

That might be a good compromise for @fregante's idea. Could tie in with #381 but I'm not proficient with mermaid.

@PabloLION

seems hard to do. what about we make the graph "reactive" and nodes and expand / collapse by clicking them?

Sounds good, but I doubt the practicality of that idea. It would necessitate additional code that would bloat madge. I think I'd leave such interactivity to other packages that may either consume madge or be composed with it.

@c-vetter
Copy link

Also related to #202

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
viz visualization enhancement, graphviz
Projects
None yet
Development

No branches or pull requests

3 participants