loguinho 1.0.0
loguinho: ^1.0.0 copied to clipboard
Framework de logging estruturado, seguro, de alta performance e multiplataforma para aplicações Dart e Flutter.
example/example.dart
import 'package:loguinho/loguinho.dart';
// =============================================================================
// 1. CAMADA DE ABSTRAÇÃO / CONTRATO (Inversão de Dependência - DIP)
// =============================================================================
/// Contrato genérico de Logger da aplicação.
/// O código de domínio (UseCases, Repositories, Services) depende APENAS desta abstração.
abstract class ILogger {
void debug(String message, {String? category, Map<String, dynamic>? attributes});
void info(String message, {String? category, Map<String, dynamic>? attributes});
void success(String message, {String? category, Map<String, dynamic>? attributes});
void warning(String message, {String? category, Map<String, dynamic>? attributes, Object? error});
void error(String message, {String? category, Map<String, dynamic>? attributes, Object? error, StackTrace? stackTrace});
}
// =============================================================================
// 2. ADAPTADOR DO LOGUINHO (Adapter Pattern)
// =============================================================================
/// Implementação concreta do ILogger que encapsula o Loguinho Framework.
/// Isola a biblioteca de terceiros do restante da sua arquitetura.
class LoguinhoLoggerAdapter implements ILogger {
LoguinhoLoggerAdapter({bool showTimestamp = false}) {
Loguinho.configure(LoggerConfig.development(showTimestamp: showTimestamp));
}
@override
void debug(String message, {String? category, Map<String, dynamic>? attributes}) {
Loguinho.debug(message, category: category, attributes: attributes);
}
@override
void info(String message, {String? category, Map<String, dynamic>? attributes}) {
Loguinho.info(message, category: category, attributes: attributes);
}
@override
void success(String message, {String? category, Map<String, dynamic>? attributes}) {
Loguinho.success(message, category: category, attributes: attributes);
}
@override
void warning(String message, {String? category, Map<String, dynamic>? attributes, Object? error}) {
Loguinho.warning(message, category: category, attributes: attributes, error: error);
}
@override
void error(String message, {String? category, Map<String, dynamic>? attributes, Object? error, StackTrace? stackTrace}) {
Loguinho.error(message, category: category, attributes: attributes, error: error, stackTrace: stackTrace);
}
}
// =============================================================================
// 3. FAKE/MOCK LOGGER PARA TESTES UNITÁRIOS
// =============================================================================
/// Implementação Fake para ser injetada em testes de unidade sem poluir o console.
class FakeLogger implements ILogger {
final List<String> loggedMessages = [];
@override
void debug(String message, {String? category, Map<String, dynamic>? attributes}) => loggedMessages.add('DEBUG: $message');
@override
void info(String message, {String? category, Map<String, dynamic>? attributes}) => loggedMessages.add('INFO: $message');
@override
void success(String message, {String? category, Map<String, dynamic>? attributes}) => loggedMessages.add('SUCCESS: $message');
@override
void warning(String message, {String? category, Map<String, dynamic>? attributes, Object? error}) => loggedMessages.add('WARN: $message');
@override
void error(String message, {String? category, Map<String, dynamic>? attributes, Object? error, StackTrace? stackTrace}) => loggedMessages.add('ERROR: $message');
}
// =============================================================================
// 4. CAMADA DE NEGÓCIO DESACOPLADA (Clean Architecture / Domain Services)
// =============================================================================
/// Serviço de Autenticação que NÃO sabe da existência do Loguinho.
/// Ele depende exclusivamente do contrato `ILogger` injetado via construtor.
class AuthService {
final ILogger _logger;
AuthService(this._logger);
Future<void> login({required String email, required String password}) async {
_logger.info(
'Iniciando tentativa de login do usuário',
category: 'AUTH',
attributes: {
'email': email,
'password': password, // O LoguinhoLoggerAdapter vai mascarar automaticamente!
},
);
if (password.length < 6) {
_logger.warning('Senha com comprimento inválido fornecida', category: 'AUTH');
throw ArgumentError('Senha precisa ter no mínimo 6 caracteres');
}
// Simulação de login efetuado
_logger.success('Usuário autenticado com sucesso', category: 'AUTH', attributes: {'cpf': '123.456.789-00'});
}
}
/// Serviço de Pagamentos desacoplado.
class PaymentService {
final ILogger _logger;
PaymentService(this._logger);
void processPayment({required double amount, required String creditCardNumber}) {
_logger.info(
'Processando pagamento no valor de R\$ $amount',
category: 'PAYMENT',
attributes: {'creditCard': creditCardNumber},
);
if (amount <= 0) {
_logger.error('Valor de pagamento inválido', category: 'PAYMENT', attributes: {'amount': amount});
return;
}
_logger.success('Pagamento aprovado pelo gateway', category: 'PAYMENT');
}
}
// =============================================================================
// 5. INICIALIZAÇÃO DA APLICAÇÃO (Main Composition Root)
// =============================================================================
void main() async {
print('\n======================================================');
print('🪵 DEMO DESACOPLADA - INVERSÃO DE DEPENDÊNCIA (SOLID)');
print('======================================================\n');
// A. Criamos a instância do adaptador concreto no Composition Root (main)
final ILogger logger = LoguinhoLoggerAdapter(showTimestamp: false);
// B. Injetamos o logger desacoplado nas classes de negócio
final authService = AuthService(logger);
final paymentService = PaymentService(logger);
// C. Executamos os serviços de negócio
try {
await authService.login(email: 'user.dev@empresa.com.br', password: 'MinhaSenha123');
} catch (e) {
print('Erro capturado: $e');
}
paymentService.processPayment(amount: 249.90, creditCardNumber: '1234-5678-9012-3456');
// D. Demonstrando Teste de Unidade com FakeLogger
print('\n======================================================');
print('🧪 SIMULAÇÃO DE TESTE UNITÁRIO COM FAKE LOGGER');
print('======================================================\n');
final fakeLogger = FakeLogger();
final testAuthService = AuthService(fakeLogger);
await testAuthService.login(email: 'teste@domain.com', password: '123456789');
print('Logs capturados no FakeLogger durante o teste:');
for (final log in fakeLogger.loggedMessages) {
print(' -> $log');
}
print('\n======================================================');
print('✅ DEMONSTRAÇÃO DE ARQUITETURA DESACOPLADA CONCLUÍDA!');
print('======================================================\n');
}