Skip to main content

Number of External Imports (NOEI)

v1.4.0
short name: NOEI
effort: 10m
default threshold: 5

Number of external imports is a quantitative metric that measures the number of dart: and all package: imports coming from pub dependencies (package: from the same monorepo are not counted as external if they are installed via path).

Having files that serve as integration points and contain many imports (including external imports) is normal, but it becomes a problem when there are many such files in a codebase as those files are affected by any update in their direct and indirect dependencies.

Why Be Cautious

High number of external imports can lead to:

  • Maintainability Challenges: High number of external imports can indicated files with too many responsibilities and too many integration point that require attention when any of the external dependency changes.
  • Increased Complexity: The more external packages a file depends on, the harder it can be to understand and debug.
  • Difficulty in Testing: High number of external imports requires a lot of mocks for the external code which complicates testing.

How to Address High Number of External Imports?

First, understand the responsibility of the file. If that file is supposed to be the file that integrates different parts of your app together, having many imports is normal.

For other cases, consider splitting the file into several smaller files, each encapsulating a specific piece of functionality. For example, create a separate class that handles server interactions and make it depend on the relevant external packages, never importing those packages into other files in your code. This way, if something changes in any of those packages, you only need to update your class while keeping other code intact.

info

If you want some files to have 0 external dependencies, configure multiple thresholds.

Config Example

analysis_options.yaml
dcm:
metrics:
number-of-external-imports:
threshold: 5

To set multiple threshold or other common config options, refer to the Configuring Metrics page.

Example

info

To view what contributes to the metric value, generate an HTML report.

❌ Bad: High Number of External Imports

// NOEI: 10
import 'dart:io';
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:http/http.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:vector_graphics/vector_graphics.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:your_project/services/api_service.dart';
import 'package:your_project/utils/constants.dart';

// Main code follows here...

✅ Good: Low Number of External Imports

main.yaml
// NOEI: 5
import 'dart:io';
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:your_project/network_service.dart'; // using http
import 'package:your_project/auth_service.dart'; // using firebase_auth, google_sign_in, shared_preferences
import 'package:your_project/utils/constants.dart';

// Main code follows here...
auth_service.dart
// NOEI: 3
import 'package:shared_preferences/shared_preferences.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart';

// Implementation
network_service.dart
// NOEI: 1
import 'package:http/http.dart';

// Implementation