Best Practices 🎯

Code Organization

Category-based Import Strategy

// ❌ Bad - Importing everything
import 'package:normie/normie.dart';

// ✅ Good - Clear intention of usage
class ColorService {
  final _palette = Normie.palette;
  final _numeric = Normie.numeric;
  
  Color getContrastingColor(String hex) {
    final color = _palette.hexToColor(hex);
    return _palette.isLight(color) 
      ? Colors.black 
      : Colors.white;
  }
}

Error Handling

// ❌ Bad - No error handling
String formatUserInput(String input) {
  return Normie.words.titleCase(input);
}

// ✅ Good - Proper error handling
String formatUserInput(String? input) {
  if (input == null || input.isEmpty) return '';
  try {
    return Normie.words.titleCase(input);
  } catch (e) {
    Normie.guard.formatException(e);
    return input;
  }
}

Cache Management

// ❌ Bad - Unmanaged cache
class DataService {
  void saveData(String key, dynamic data) {
    Normie.cache.set(key, data);
  }
}

// ✅ Good - Managed cache with cleanup
class DataService {
  static const _maxCacheAge = Duration(hours: 1);
  
  void saveData(String key, dynamic data) {
    Normie.cache.set(key, data, expiry: _maxCacheAge);
  }
  
  void cleanup() {
    Normie.cache.removeExpired();
  }
}

Common Patterns 🔄

Builder Pattern with Normie

class UserProfile {
  final String name;
  final String email;
  final String avatar;

  factory UserProfile.fromMap(Map<String, dynamic> map) {
    final name = Normie.words.titleCase(map['name'] ?? '');
    final email = map['email']?.toString().toLowerCase() ?? '';
    final avatar = Normie.words.getStringInitial(name);
    
    return UserProfile(name: name, email: email, avatar: avatar);
  }
}

Validation Chain

class FormValidator {
  List<String> validateUser(Map<String, String> data) {
    final errors = <String>[];
    
    if (!Normie.check.isEmail(data['email'] ?? '')) {
      errors.add('Invalid email');
    }
    
    if (!Normie.check.isStrongPassword(data['password'] ?? '')) {
      errors.add('Weak password');
    }
    
    if (!Normie.check.isPhoneNumber(data['phone'] ?? '')) {
      errors.add('Invalid phone number');
    }
    
    return errors;
  }
}

Format Utilities

class FormatUtils {
  static String formatAmount(double amount) {
    return Normie.numeric.formatCurrency(
      amount,
      symbol: '\$',
      decimalPlaces: 2
    );
  }
  
  static String formatDate(String date) {
    return Normie.chrono.format(
      date: date,
      outputFormat: 'MMM dd, yyyy'
    );
  }
  
  static String formatFileSize(int bytes) {
    return Normie.numeric.formatFileSize(bytes);
  }
}

Performance Tips 🚀

Cache Expensive Operations

class ColorProcessor {
  final _cache = <String, Color>{};
  
  Color getProcessedColor(String hex) {
    if (_cache.containsKey(hex)) {
      return _cache[hex]!;
    }
    
    final color = Normie.palette.hexToColor(hex);
    final processed = Normie.palette.darken(color, 0.1);
    _cache[hex] = processed;
    
    return processed;
  }
}

Batch Operations

class BatchProcessor {
  List<String> processNames(List<String> names) {
    // ❌ Bad - Processing one by one
    return names.map((name) {
      final titled = Normie.words.titleCase(name);
      final noAccents = Normie.words.removeAccents(titled);
      return noAccents;
    }).toList();
    
    // ✅ Good - Batch processing
    return names.map((name) => name.toLowerCase())
      .map(Normie.words.titleCase)
      .map(Normie.words.removeAccents)
      .toList();
  }
}

Memory Management

class MemoryEfficientService {
  // ❌ Bad - Keeping all data in memory
  final allItems = <String, dynamic>{};
  
  // ✅ Good - Paginated data handling
  List<T> getPaginatedData<T>(List<T> items, int page) {
    return Normie.collection.paginate(items, page, 20);
  }
  
  // ✅ Good - Cleanup old cache
  void maintainCache() {
    if (Normie.cache.size > 1000) {
      Normie.cache.removeExpired();
    }
  }
}

Lazy Initialization

class LazyService {
  Map<String, Color>? _colorCache;
  
  Map<String, Color> get colorCache {
    return _colorCache ??= _initializeColorCache();
  }
  
  Map<String, Color> _initializeColorCache() {
    final baseColors = ['#FF5733', '#33FF57', '#5733FF'];
    return Map.fromEntries(
      baseColors.map((hex) => MapEntry(
        hex,
        Normie.palette.hexToColor(hex)
      ))
    );
  }
}

Best Practices by Category

Cache Best Practices

  • Set appropriate expiry times

  • Regularly clean expired items

  • Use type-safe getters

  • Handle cache misses gracefully

Validation Best Practices

  • Combine multiple validations

  • Provide clear error messages

  • Use appropriate regex patterns

  • Handle edge cases

Date/Time Best Practices

  • Use consistent formats

  • Handle timezone differences

  • Consider locale settings

  • Validate date strings

Collection Best Practices

  • Use appropriate page sizes

  • Handle empty results

  • Consider memory implications

  • Use efficient algorithms

File Best Practices

  • Validate file types

  • Handle large files appropriately

  • Use proper MIME types

  • Consider security implications

Remember: These are guidelines, not strict rules. Adapt them to your specific needs!

Last updated