Uniword follows established architecture patterns for maintainability, extensibility, and testability.
1. lutaml-model Patterns
All serializable models inherit from Lutaml::Model::Serializable and use the lutaml-model DSL:
-
Attributes are declared with
attributeusing explicit types -
XML mappings are defined in an
xml doblock -
Attributes MUST be declared BEFORE the
xmlblock (see Pattern 0)
class Bold < Lutaml::Model::Serializable
attribute :value, :boolean, default: -> { true }
xml do
element 'b'
namespace Uniword::Ooxml::Namespaces::WordProcessingML
map_attribute 'val', to: :value, render_nil: false,
render_default: false
end
end
2. Model vs Builder Separation
Model classes represent OOXML structure. Builder classes provide user-friendly APIs.
# Builder provides convenience (lib/uniword/builder/)
class ParagraphBuilder
def bold=(value)
ensure_properties.bold = Bold.new(value: value)
self
end
end
Model classes do NOT have custom getters or setters. All attribute access uses lutaml-model’s default mechanisms.
3. SOLID Principles
- Single Responsibility
-
Each class has one reason to change. Format handlers handle format-specific logic, models represent XML structure, builders provide convenient APIs.
- Open/Closed
-
New format handlers and validation rules are added without modifying existing code. The Registry pattern enables extension.
- Liskov Substitution
-
All format handlers implement the same interface. Any handler can be used wherever a handler is expected.
- Interface Segregation
-
Each class exposes only the methods its clients need. No "god objects" with hundreds of methods.
- Dependency Inversion
-
High-level code depends on abstractions (lutaml-model serialization), not on concrete XML parsers.
4. Design Patterns
- Strategy
-
Format handlers (DOCX, MHTML) implement different strategies for the same document operations.
- Factory
-
DocumentFactorycreates documents from files, handling format detection and handler selection. - Builder
-
The fluent builder API provides a convenient interface for constructing complex documents.
- Visitor
-
Document traversal for verification and transformation uses the Visitor pattern.
- Registry
-
Element and handler discovery uses a Registry pattern for dynamic lookup.
- Adapter
-
Format handlers adapt the internal document model to specific file formats.