utilities_ab 0.0.7 copy "utilities_ab: ^0.0.7" to clipboard
utilities_ab: ^0.0.7 copied to clipboard

Dart utility helper classes and functions for general purpose use.

Pub

A comprehensive Dart utilities package providing essential tools for Flutter and Dart applications including caching, error handling, and logging utilities.

Features #

  • 🔧 Cache Module: Generic cache with LFU/LRU eviction algorithms
  • ⚠️ Error Handling: Structured exception handling with stack trace support
  • 📝 Logging: Configurable logging system with console and developer tools support

Installation #

Add to your pubspec.yaml:

dependencies:
  utilities_ab: ^0.0.5

Usage #

Import the entire utilities package: #

import 'package:utilities_ab/utilities.dart';

Or import specific modules: #

import 'package:utilities_ab/cache/cache.dart';
import 'package:utilities_ab/error/app_exception.dart';
import 'package:utilities_ab/logging/init_logging.dart';

🔧 Cache Module #

A generic cache implementation supporting LFU and LRU eviction algorithms with automatic loading from backing stores.

Features #

  • Generic Type Support: Works with any key and value types
  • Multiple Eviction Algorithms: Supports both LFU (Least Frequently Used) and LRU (Least Recently Used)
  • Automatic Loading: Automatically loads missing values from backing stores using callback functions
  • Overloaded Indexing Operator: Access cache values using cache[key] syntax
  • Pluggable Storage: Extensible storage interface with in-memory implementation included
  • Async Support: Full async/await support for all operations

Basic Usage #

import 'package:utilities_ab/cache/cache.dart';

// Create a loader function that fetches data from your backing store
Future<String> loadUserData(String userId) async {
  // Simulate API call or database query
  await Future.delayed(Duration(milliseconds: 100));
  return 'User data for $userId';
}

// Create an LRU cache with max 100 items
final cache = Cache<String, String>(
  storage: InMemoryStorage<String, CacheEntry<String, String>>(),
  algorithm: EvictionAlgorithm.lru,
  maxSize: 100,
  loader: loadUserData,
);

// Access data - automatically loads if not in cache
final userData = await cache['user123'];
print(userData); // "User data for user123"

// Subsequent accesses use cached data
final cachedData = await cache['user123']; // No loading, uses cache

LFU Cache Example #

// Create an LFU cache
final lfuCache = Cache<String, Map<String, dynamic>>(
  storage: InMemoryStorage<String, CacheEntry<String, Map<String, dynamic>>>(),
  algorithm: EvictionAlgorithm.lfu,
  maxSize: 50,
  loader: (key) async {
    // Load complex data structure
    return {'id': key, 'data': 'complex object'};
  },
);

// Access data multiple times to increase frequency
await lfuCache['key1'];
await lfuCache['key1']; // Increases frequency
await lfuCache['key1']; // Increases frequency again

Direct Assignment #

// Store values directly in cache (immediate storage, no eviction check)
cache['manual'] = 'Directly stored value';

// Or use the async put method (with eviction check)
await cache.put('manual', 'Directly stored value');

// Retrieve the value
final value = await cache['manual'];
print(value); // "Directly stored value"

Cache Management #

// Check if key exists
if (await cache.containsKey('user123')) {
  print('User data is cached');
}

// Remove specific item
await cache.remove('user123');

// Get cache statistics
final size = await cache.size;
final keys = await cache.keys;
final values = await cache.values;

// Clear entire cache
await cache.clear();

Cache Architecture #

Components

  1. Cache: Main cache class with eviction logic
  2. CacheEntry: Wrapper for cached values with metadata
  3. CacheStorage: Interface for storage implementations
  4. InMemoryStorage: In-memory storage implementation
  5. EvictionAlgorithm: Enum for supported algorithms

Eviction Algorithms

LRU (Least Recently Used)

  • Removes items that haven't been accessed for the longest time
  • Good for temporal locality patterns
  • Updates access time on every read/write

LFU (Least Frequently Used)

  • Removes items that are accessed least often
  • Good for frequency-based access patterns
  • Increments frequency counter on every access

Storage Interface

The CacheStorage interface allows you to implement custom storage backends:

class CustomStorage<K, V> implements CacheStorage<K, V> {
  @override
  Future<bool> put(K key, V value) async {
    // Your implementation
  }
  
  @override
  Future<V?> get(K key) async {
    // Your implementation
  }
  
  // ... implement other methods
}

⚠️ Error Handling Module #

The AppException class provides structured exception handling with support for nested exceptions and detailed stack traces.

Features #

  • Structured Exceptions: Consistent exception format across your application
  • Nested Exceptions: Support for chaining exceptions with inner exceptions
  • Stack Trace Management: Automatic stack trace capture and formatting
  • Logging Integration: Built-in logging support for exception tracking
  • Customizable Output: Formatted exception messages for debugging

Basic Usage #

import 'package:utilities_ab/error/app_exception.dart';

try {
  // Your code that might throw an exception
  throw Exception('Something went wrong');
} catch (e, stackTrace) {
  // Create a structured exception
  final appException = AppException(
    message: 'Failed to process user data',
    stackTrace: stackTrace,
    innerException: e is Exception ? e : null,
  );
  
  // Log or handle the exception
  print(appException.toString());
}

Nested Exceptions #

try {
  // Outer operation
  try {
    // Inner operation that fails
    throw Exception('Database connection failed');
  } catch (innerError, innerStackTrace) {
    throw AppException(
      message: 'Failed to save user data',
      stackTrace: StackTrace.current,
      innerException: innerError is Exception ? innerError : null,
      innerStackTrace: innerStackTrace,
    );
  }
} catch (outerError, outerStackTrace) {
  if (outerError is AppException) {
    print(outerError.toString());
    // Output will show the chain of exceptions
  }
}

Exception Output Format #

The AppException provides formatted output including:

  • Exception type and message
  • Formatted stack trace
  • Nested exception information
  • Clean stack trace formatting (removes internal framework calls)

Example output:

AppException: Failed to process user data
	at MyClass.processData (my_file.dart:25)
	at MyClass.main (my_file.dart:10)
Caused by: Exception: Database connection failed
	at Database.connect (database.dart:15)

📝 Logging Module #

The logging module provides a configurable logging system that integrates with Flutter's developer tools and console output.

Features #

  • Configurable Log Levels: Set appropriate log levels for different environments
  • Console Integration: Optional console output for debugging
  • Developer Tools Integration: Logs appear in Flutter DevTools
  • Structured Logging: Consistent log format with timestamps and context
  • Error Tracking: Automatic error and stack trace logging

Basic Usage #

import 'package:utilities_ab/logging/init_logging.dart';
import 'package:logging/logging.dart';

void main() {
  // Initialize logging with INFO level
  initLogging(Level.INFO, logToConsole: true);
  
  // Create a logger for your class
  final logger = Logger('MyClass');
  
  // Use the logger
  logger.info('Application started');
  logger.warning('This is a warning');
  logger.severe('This is an error');
}

Configuration Options #

// Development environment - verbose logging to console
initLogging(
  Level.ALL,
  logToConsole: true,
);

// Production environment - only errors and warnings
initLogging(
  Level.WARNING,
  logToConsole: false,
);

// Custom logging functions
initLogging(
  Level.INFO,
  logToConsole: false,
  logFn: (message, {time, level, name, error, stackTrace}) {
    // Custom logging implementation
    print('[$name] $level: $message');
  },
  consoleLogFn: (object) {
    // Custom console output
    print('CONSOLE: $object');
  },
);

Log Levels #

  • ALL: Log everything
  • FINEST: Very detailed tracing
  • FINER: More detailed tracing
  • FINE: Detailed tracing
  • CONFIG: Static configuration messages
  • INFO: General information
  • WARNING: Potential issues
  • SEVERE: Serious problems
  • SHOUT: Critical errors
  • OFF: Disable all logging

Error Logging #

final logger = Logger('ErrorHandler');

try {
  // Risky operation
  riskyOperation();
} catch (error, stackTrace) {
  logger.severe(
    'Operation failed',
    error,
    stackTrace,
  );
}

Log Output Format #

Console Output:

2024-01-15 10:30:45.123 [MyClass] INFO: Application started
2024-01-15 10:30:46.456 [MyClass] WARNING: This is a warning
2024-01-15 10:30:47.789 [MyClass] SEVERE: This is an error

Error with Stack Trace:

2024-01-15 10:30:47.789 [MyClass] SEVERE: Operation failed =>
====================
Exception: Something went wrong
at MyClass.riskyOperation (my_file.dart:25)
at MyClass.main (my_file.dart:10)

Performance Considerations #

Cache Module #

  • Memory Usage: In-memory storage keeps all data in RAM
  • Eviction Overhead: O(n) complexity for eviction decisions
  • Concurrency: Not thread-safe by default
  • Async Operations: All storage operations are async for flexibility

Error Handling #

  • Stack Trace Overhead: Capturing stack traces has performance impact
  • Memory Usage: Exception objects hold references to stack traces
  • Logging Impact: Exception logging can be expensive in high-frequency scenarios

Logging #

  • Console Output: Console logging can impact performance in production
  • Log Level Filtering: Use appropriate log levels to minimize overhead
  • Async Logging: Consider async logging for high-frequency applications

Testing #

Run the tests to verify functionality:

# Run all tests
dart test

# Run specific test files
dart test test/cache_test.dart
dart test test/app_exception_test.dart

Test Coverage #

  • Cache Tests: LRU/LFU eviction logic, storage interface, direct assignment
  • Error Tests: Exception formatting, nested exceptions, stack trace handling
  • Logging Tests: Log level configuration, output formatting

Contributing #

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass
  6. Submit a pull request

License #

This project is licensed under the MIT License - see the LICENSE file for details.

1
likes
150
points
492
downloads

Publisher

verified publisherappbricks.io

Weekly Downloads

Dart utility helper classes and functions for general purpose use.

Homepage

Documentation

API reference

License

GPL-3.0 (license)

Dependencies

logging, uuid

More

Packages that depend on utilities_ab