Service Architecture¶
Overview¶
CharsetHelper v1.1 introduces a service-based architecture following SOLID principles. The new architecture provides better testability, flexibility, and maintainability while maintaining 100% backward compatibility.
Architecture Components¶
CharsetProcessorInterface¶
Service contract defining the API for charset processing operations.
Benefits: - Enables dependency injection - Facilitates testing with mocks - Allows custom implementations - Provides stable contract
CharsetProcessor¶
Service implementation with fluent API and mutable state.
Features:
- Instantiable service class
- Fluent API (all management methods return $this)
- Multiple independent instances
- Configurable transcoders, detectors, and encodings
CharsetHelper¶
Static facade delegating to CharsetProcessor.
Purpose: - Maintains backward compatibility - Provides convenient static API - Lazy initialization of processor
Design Principles¶
Single Responsibility Principle (SRP)¶
Each class has a single, well-defined responsibility:
- CharsetProcessorInterface: Defines the contract
- CharsetProcessor: Implements charset operations
- CharsetHelper: Provides static facade
Open/Closed Principle (OCP)¶
The architecture is open for extension but closed for modification:
- Custom transcoders via TranscoderInterface
- Custom detectors via DetectorInterface
- Custom implementations via CharsetProcessorInterface
Liskov Substitution Principle (LSP)¶
Any CharsetProcessorInterface implementation can be substituted without breaking client code.
Interface Segregation Principle (ISP)¶
The interface provides cohesive methods without forcing implementations to depend on unused functionality.
Dependency Inversion Principle (DIP)¶
High-level modules depend on abstractions (CharsetProcessorInterface), not concrete implementations.
Usage Patterns¶
Static Facade (Backward Compatible)¶
use Ducks\Component\EncodingRepair\CharsetHelper;
// Works exactly as before
$utf8 = CharsetHelper::toUtf8($data);
Service Instance¶
use Ducks\Component\EncodingRepair\CharsetProcessor;
$processor = new CharsetProcessor();
$utf8 = $processor->toUtf8($data);
Fluent API¶
$processor = new CharsetProcessor();
$processor
->addEncodings('SHIFT_JIS', 'EUC-JP')
->resetDetectors()
->registerTranscoder(new MyTranscoder(), 150);
$result = $processor->toUtf8($data);
Multiple Instances¶
// Production processor with strict encodings
$prodProcessor = new CharsetProcessor();
$prodProcessor->resetEncodings()->addEncodings('UTF-8', 'ISO-8859-1');
// Import processor with permissive encodings
$importProcessor = new CharsetProcessor();
$importProcessor->addEncodings('SHIFT_JIS', 'EUC-JP', 'GB2312');
// Both are independent
$prodResult = $prodProcessor->toUtf8($data);
$importResult = $importProcessor->toUtf8($legacyData);
Dependency Injection¶
use Ducks\Component\EncodingRepair\CharsetProcessorInterface;
class MyService
{
private CharsetProcessorInterface $processor;
public function __construct(CharsetProcessorInterface $processor)
{
$this->processor = $processor;
}
public function process($data)
{
return $this->processor->toUtf8($data);
}
}
// Easy to test with mocks
$mock = $this->createMock(CharsetProcessorInterface::class);
$service = new MyService($mock);
Migration Guide¶
From Static to Service¶
Before (v1.0):
CharsetHelper::registerTranscoder(new MyTranscoder());
$result = CharsetHelper::toUtf8($data);
After (v1.1):
$processor = new CharsetProcessor();
$processor->registerTranscoder(new MyTranscoder());
$result = $processor->toUtf8($data);
No Migration Required¶
The static facade still works:
// This still works in v1.1
CharsetHelper::toUtf8($data);
Benefits¶
Testability¶
// Easy to mock in tests
$mock = $this->createMock(CharsetProcessorInterface::class);
$mock->method('toUtf8')->willReturn('mocked');
$service = new MyService($mock);
$result = $service->process($data);
Flexibility¶
// Different configurations for different contexts
$webProcessor = new CharsetProcessor();
$webProcessor->addEncodings('UTF-8', 'ISO-8859-1');
$apiProcessor = new CharsetProcessor();
$apiProcessor->addEncodings('UTF-8', 'UTF-16');
Maintainability¶
- Clear separation of concerns
- Single Responsibility Principle
- Easy to extend without modifying existing code
Performance¶
No performance impact: - Static facade uses lazy initialization - Service instances have minimal overhead - Same underlying implementation
Backward Compatibility¶
100% backward compatible: - All existing code works unchanged - Static methods delegate to service - No breaking changes
See Also¶
- CharsetProcessorInterface - Service contract
- CharsetProcessor - Service implementation
- CharsetHelper - Static facade
- Advanced Usage - More examples