Skip to content

[REFACTOR] Consolidate Result<T> headers from 9 to 3 - C++20 Module preparation #255

Description

@kcenon

Summary

Consolidate 9 Result related header files into 3 logical groups, preparing for C++20 module migration while following Kent Beck's "Fewest Elements" principle.

Current State

Directory: include/kcenon/common/patterns/

File Inventory (9 files)

patterns/
├── result.h              # Umbrella header (includes all below)
├── result_helpers.h      # Additional helpers
└── result/
    ├── fwd.h                    # Forward declarations
    ├── error_info.h             # error_info struct
    ├── result_core.h            # Result<T> class
    ├── optional.h               # Optional utilities
    ├── result_funcs.h           # Factory functions (ok, err)
    ├── error_codes_compat.h     # Legacy error code support
    ├── exception_conversion.h   # Exception utilities
    └── result_macros.h          # Convenience macros

Current result.h (umbrella)

#pragma once

#include "result/fwd.h"
#include "result/error_info.h"
#include "result/result_core.h"
#include "result/optional.h"
#include "result/result_funcs.h"
#include "result/error_codes_compat.h"
#include "result/exception_conversion.h"
#include "result/result_macros.h"

Problem Analysis

Issue Impact
9 files for 1 concept Complex include dependencies
Unclear which header to include User confusion
Module boundary unclear C++20 migration difficulty
Compile-time overhead 9 file opens per include

Kent Beck Principles

  • Fewest Elements: 9 files → 3 files
  • Reveals Intention: Unclear separation of concerns

C++20 Module Impact

When converting to modules, need clear partitions:

export module kcenon.common.result;       // Primary
export module kcenon.common.result:core;  // Partition
export module kcenon.common.result:utils; // Partition

Proposed Solution: 3 Logical Groups

New Structure

patterns/
├── result.h              # Umbrella (unchanged, backward compat)
└── result/
    ├── core.h            # Combined: fwd + error_info + result_core + optional
    ├── utilities.h       # Combined: result_funcs + exception_conversion + macros
    └── compat.h          # Legacy: error_codes_compat

core.h Contents

#pragma once

#include <optional>
#include <string>
#include <variant>
#include <kcenon/common/utils/source_location.h>

namespace kcenon::common {

// Forward declarations (from fwd.h)
template<typename T> class Result;
using VoidResult = Result<void>;

// Error info (from error_info.h)
struct error_info {
    int code;
    std::string message;
    std::string module;
    std::optional<std::string> details;
    // ... rest of implementation
};

// Result class (from result_core.h)
template<typename T>
class Result {
    // ... full implementation
};

// Optional utilities (from optional.h)
// ... if needed

} // namespace kcenon::common

utilities.h Contents

#pragma once

#include "core.h"

namespace kcenon::common {

// Factory functions (from result_funcs.h)
template<typename T>
Result<T> make_ok(T&& value);

template<typename T>
Result<T> make_err(error_info error);

// Exception conversion (from exception_conversion.h)
template<typename T, typename F>
Result<T> try_catch(F&& func);

// Macros (from result_macros.h)
#define KCENON_TRY(expr) ...
#define KCENON_UNWRAP(expr) ...

} // namespace kcenon::common

compat.h Contents

#pragma once

#include "core.h"

namespace kcenon::common {

// Legacy error codes (from error_codes_compat.h)
// For backward compatibility with older error handling

[[deprecated("Use error_info directly")]]
enum class error_code { ... };

} // namespace kcenon::common

Migration Path

Phase 1: Create new consolidated headers

  • Create core.h, utilities.h, compat.h
  • Copy content from individual files

Phase 2: Update umbrella header

// result.h - maintains backward compatibility
#pragma once

// New consolidated headers
#include "result/core.h"
#include "result/utilities.h"
#include "result/compat.h"  // Optional, for legacy support

Phase 3: Deprecate individual headers

// result/fwd.h
#pragma once
#pragma message("result/fwd.h is deprecated. Use result/core.h")
#include "core.h"

Phase 4: Remove deprecated (next major version)

  • Remove individual files
  • Update documentation

Tasks

  • Create result/core.h combining fwd + error_info + result_core + optional
  • Create result/utilities.h combining result_funcs + exception_conversion + macros
  • Create result/compat.h with error_codes_compat
  • Update result.h umbrella to use new headers
  • Add deprecation pragma to old individual headers
  • Update internal includes
  • Update documentation
  • Verify no API changes

Acceptance Criteria

  • result.h still works as umbrella (backward compat)
  • Individual includes still work with deprecation warning
  • 3 logical files instead of 9
  • Clear separation for C++20 module conversion
  • All tests pass
  • No public API changes

C++20 Module Ready Structure

// Future module structure
export module kcenon.common.result;

export import :core;       // Primary types
export import :utilities;  // Factory functions
// :compat is internal only

Metrics

Metric Before After
Header files 9 3 (+1 umbrella)
Include depth 8 2
Module partitions unclear 3 clear

Related

  • C++20 Module Migration Epic
  • Kent Beck "Fewest Elements" principle

Metadata

Metadata

Assignees

Labels

architectureArchitectural changes and designpriority:mediumMedium priority issuerefactoringCode refactoring and improvements

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions