This document outlines improvement opportunities for the OpenFeature Java API based on analysis of the current codebase structure.
✅ Completed: Builder class names have been standardized to use Builder instead of class-specific names (e.g., ImmutableMetadataBuilder → Builder)
- Mixed Mutability Patterns:
ProviderEvaluationis mutable with both builder pattern AND public setters, while event details are immutable with builders only - Constructor Overloading vs Builders: Some classes provide multiple constructors alongside builders
Make ProviderEvaluation immutable by:
1. Making all fields final
2. Removing public setters (setValue, setVariant, etc.)
3. Adding private constructor that takes all parameters
4. Ensuring builder is the only way to create instances
Remove constructor overloads from POJOs and standardize on builder pattern only for:
- FlagEvaluationDetails
- ProviderEvaluation
- EventDetails
- ProviderEventDetails
- Inconsistent Method Names: Some builders use
addX()(ImmutableMetadata), others usex() - Validation Inconsistency: Some builders validate in
build(), others in setter methods
Update ImmutableMetadata.Builder to use consistent naming:
- Change addString() → string()
- Change addInteger() → integer()
- Change addLong() → longValue()
- Change addFloat() → floatValue()
- Change addDouble() → doubleValue()
- Change addBoolean() → boolean()
Move all validation logic to build() methods instead of setter methods for:
- All builder classes that currently validate in setters
- Add comprehensive validation in build() with clear error messages
Ensure all builder methods return 'this' for fluent interface consistency
- Inconsistent Context Constructors:
ImmutableContextandMutableContexthave different constructor patterns - Value Conversion Duplication:
convertValue()method exists in multiple places
Create unified context creation patterns:
1. Add static factory methods: Context.of(), Context.empty(), Context.withTargeting(key)
2. Standardize constructor patterns between ImmutableContext and MutableContext
3. Add builder() static methods to both context types for consistency
Extract value conversion logic:
1. Create ValueConverter utility class
2. Move convertValue() from Structure interface to utility
3. Update all implementations to use centralized conversion logic
Add convenience methods for common structure operations:
- Structure.empty()
- Structure.of(Map<String, Object>)
- Structure.withAttribute(key, value)
- Interface Hierarchy:
ClientMetadatahas deprecatedgetName()method - Builder Inconsistency:
ImmutableMetadatabuilder usesaddType()methods vs standard patterns
Clean up metadata interfaces:
1. Remove deprecated getName() method from ClientMetadata after checking usage
2. Create clear separation between ClientMetadata and generic Metadata
3. Consider if both interfaces are needed or can be unified
Add metadata factory methods:
- Metadata.empty()
- Metadata.of(String name)
- Metadata.builder() shortcuts for common cases
Improve metadata builder ergonomics:
- Add putAll(Map<String, Object>) method
- Add convenience methods for common metadata patterns
- Complex Composition:
EventDetailscomposesProviderEventDetailsbut both implement same interface
Evaluate event details architecture:
1. Consider if separate ProviderEventDetails and EventDetails are necessary
2. Document the relationship and usage patterns clearly
3. If keeping both, ensure clear distinction in naming and purpose
Add event details convenience methods:
- EventDetails.forProviderError(String providerName, ErrorCode code, String message)
- EventDetails.forProviderReady(String providerName)
- EventDetails.forConfigurationChange(String providerName, List<String> flagsChanged)
Improve event details validation:
- Ensure providerName is always required per OpenFeature spec
- Add validation in builder.build() methods
- Provide clear error messages for invalid states
Add static import friendly factory methods:
- Value.of(Object) for common value creation
- Context.of(String targetingKey) for simple contexts
- Context.of(String targetingKey, Map<String, Object> attributes)
Add null safety annotations:
- @Nullable for optional parameters and return values
- @NonNull for required parameters
- Import javax.annotation or create custom annotations
Create fluent shortcuts for common patterns:
- EvaluationContext.withTargeting(String key)
- FlagEvaluationDetails.success(String flagKey, T value)
- FlagEvaluationDetails.error(String flagKey, T defaultValue, ErrorCode code, String message)
Reduce method overloading where builders can be used:
- Evaluate if multiple overloaded constructors are needed
- Prefer builder pattern over method overloads for complex objects
Improve error messages and validation:
- Add descriptive error messages in builder validation
- Include parameter names and expected values in exceptions
- Add @throws documentation for checked exceptions
Consider Optional usage for nullable returns:
- Evaluate using Optional<T> instead of null returns
- Focus on public API methods that commonly return null
- Document null-safety contracts clearly
Package structure optimization:
- Consider if all API classes need to be in single package
- Evaluate creating sub-packages for: contexts, events, metadata, evaluation
- Maintain backward compatibility during any restructuring
Documentation improvements:
- Add usage examples in class-level Javadocs
- Include common patterns and anti-patterns
- Add code examples for complex builder usage
Performance optimizations:
- Reduce object allocation in hot paths (evaluation)
- Consider object pooling for frequently created objects
- Optimize map operations in context merging
Based on current checkstyle errors:
Fix checkstyle issues in:
1. ProviderEventDetails.java:19 - Add empty line before @deprecated tag
2. FlagEvaluationDetails.java:4 - Remove unused Optional import
3. EventDetails.java - Add Javadoc comments for missing builder methods:
- flagsChanged() method
- message() method
- eventMetadata() method
- errorCode() method
- Document all breaking changes with migration guides
- Consider deprecation periods for public API changes
- Provide automated migration tools where possible
- Maintain existing public API surface where possible
- Use @Deprecated annotations with clear migration paths
- Version new features appropriately
- Add comprehensive tests for all builder patterns
- Test null safety and validation thoroughly
- Include integration tests for common usage patterns
- Maintain test coverage above 80% for all changes
- Fix Checkstyle Issues - Address the 6 current checkstyle violations
- Prioritize High-Value Changes - Start with POJO consistency and builder standardization
- Create Migration Guide - Document any breaking changes for users
- Update Documentation - Refresh examples and usage patterns
- Performance Testing - Ensure changes don't negatively impact performance
This document serves as a roadmap for incrementally improving the API while maintaining stability and backward compatibility.