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