Table of Contents

v1.4.3 "Seiri" - Code Organization & Serialization Cleanup

Release Date: 2025-01-08
Code Name: "Seiri" (整理 - Organization/Cleanup)
Type: Patch Release


🎯 Overview

Version 1.4.3 is a focused cleanup release that eliminates code duplication and resolves serialization issues within the Jiro.Shared library. This release refactors the command result architecture to eliminate redundancy with the main Jiro.Commands project, resulting in cleaner separation of concerns and improved maintainability.

The "Seiri" release embodies the Japanese concept of organization and systematic arrangement, removing unnecessary complexity while maintaining full backward compatibility.

🔧 Breaking Changes

⚠️ Command Result Type Removal

Affected Types (removed from Jiro.Shared):

  • ICommandResult interface
  • TextResult class
  • GraphResult class
  • CommandType enum
  • TextType enum

Migration Path: Applications should use their own ICommandResult implementations from domain-specific packages (e.g., Jiro.Commands) instead of relying on Jiro.Shared types.

SessionCommandResponse Changes

Before (v1.4.2):

public class SessionCommandResponse
{
    public CommandType CommandType { get; set; }  // Enum
    public ICommandResult? Result { get; set; }   // Strongly typed
}

After (v1.4.3):

public class SessionCommandResponse  
{
    public string CommandType { get; set; }       // String for flexibility
    public object? Result { get; set; }           // Generic object
}

🚀 Key Improvements

Architecture Cleanup

  • Eliminated Duplication: Removed duplicate ICommandResult types that existed in both Jiro.Shared and Jiro.Commands
  • Proper Separation: Jiro.Shared now focuses purely on transport/communication contracts
  • Domain Independence: Applications can use their own command result implementations

Enhanced Serialization

  • Generic Result Handling: SessionCommandResponse.Result is now object? for maximum flexibility
  • JSON Compatibility: Full JSON serialization support with proper type handling
  • Framework Agnostic: No dependency on specific result type implementations

gRPC Extension Updates

Updated ClientMessageExtensions:

// Now creates anonymous objects instead of typed results
Result = new
{
    Response = textResult.Response,
    TextType = textResult.TextType.ToString().ToLower()
}

📋 Technical Details

Serialization Behavior

The updated SessionCommandResponse serializes all result types as JSON objects:

String Results:

{
  "commandType": "text",
  "result": "Simple string result"
}

Complex Results:

{
  "commandType": "graph",
  "result": {
    "message": "Graph data",
    "data": "{\"x\":[1,2,3]}",
    "units": {"x": "seconds"}
  }
}

Consumer Implementation

Applications consuming Jiro.Shared should implement their own result type handling:

// In consuming application
var response = await GetSessionCommandResponse();

if (response.Result is JsonElement element)
{
    var myResult = JsonSerializer.Deserialize<MyCustomResult>(element);
    // Handle typed result
}

🧪 New Test Coverage

Serialization Tests

Added comprehensive test suite for SessionCommandResponse serialization:

  • String result serialization/deserialization
  • Complex object result handling
  • Null result handling
  • Empty command type scenarios

Test Coverage: 4 new test methods ensuring robust serialization behavior

🔄 Migration Guide

For Library Consumers

  1. Remove Direct Type Dependencies: Stop importing command result types from Jiro.Shared
  2. Implement Domain Types: Use your own ICommandResult implementations
  3. Update Deserialization: Handle object? results with proper type conversion
  4. String Command Types: Update code expecting CommandType enum to handle strings

Example Migration

Before:

using Jiro.Shared;

var response = await client.ExecuteCommand();
if (response.Result is TextResult textResult)
{
    Console.WriteLine(textResult.Response);
}

After:

using MyApp.Commands; // Your own result types

var response = await client.ExecuteCommand();
if (response.Result is JsonElement element)
{
    var textResult = JsonSerializer.Deserialize<MyTextResult>(element);
    Console.WriteLine(textResult.Response);
}

🐛 Issues Resolved

  • Serialization Conflicts: Eliminated polymorphic serialization issues with abstract types
  • Type Duplication: Removed redundant type definitions between projects
  • Architecture Coupling: Decoupled transport layer from domain-specific types
  • Maintenance Overhead: Reduced code duplication and maintenance burden

📈 Benefits

Development Experience

  • Cleaner Architecture: Clear separation between shared infrastructure and domain logic
  • Flexible Integration: Applications can define their own result type hierarchies
  • Reduced Coupling: No forced dependency on specific command result implementations

Performance & Reliability

  • Improved Serialization: Eliminated complex polymorphic serialization scenarios
  • Smaller Footprint: Reduced assembly size by removing unnecessary types
  • Better Testability: Simplified testing with generic object handling

🔗 Dependencies

No dependency changes in this release. All dependencies remain consistent with v1.4.2:

  • Grpc.AspNetCore: 2.71.0
  • Google.Protobuf: 3.31.1
  • Microsoft.AspNetCore.SignalR: 1.2.0
  • Microsoft.AspNetCore.SignalR.Client: 9.0.8

⚡ Compatibility

Backward Compatibility

  • Transport Layer: Full compatibility for WebSocket and gRPC communication
  • JSON Serialization: Previous JSON structures remain parseable
  • Extension Methods: ClientMessageExtensions maintain same method signatures

Forward Compatibility

  • Extensible Design: Generic object? result type supports any future result implementations
  • Version Agnostic: No version-specific type dependencies

Implementation Note: This release focuses on architectural cleanup and proper separation of concerns. While some types have been removed from Jiro.Shared, the functionality remains available through domain-specific implementations in consuming applications, resulting in a cleaner and more maintainable architecture.