proto-socket/agent-task/dart_legacy_refactor/plan_0.log
toki 9cc1f1d58f sync: update communicator implementation across all languages
- Align protocol documentation (PROTOCOL.md, README.md, VERSIONING.md)
- Go: add nonce test, update communicator
- Kotlin: update Communicator, TcpClient, TcpServer, add TLS test
- Python: update all modules, add certificate test resources
- TypeScript: update communicator, tcp/ws clients and servers, add tests
- Dart: update communicator, heartbeat mixin, and tests
2026-04-26 05:31:56 +09:00

183 lines
6.1 KiB
Text

<!-- task=dart_legacy_refactor plan=0 tag=REFACTOR -->
# Dart Communicator 레거시 정리
## 이 파일을 읽는 구현 에이전트에게
각 항목의 체크리스트를 완료 표시하고, 중간 검증 명령을 실행한 뒤 출력을 CODE_REVIEW.md의 `검증 결과` 섹션에 붙여 넣는다. 최종 검증까지 완료한 후 CODE_REVIEW.md의 각 항목을 `[x]`로 체크한다.
## 배경
Dart `Communicator`는 `send<T>()` 메서드가 `abstract`로 선언되어 모든 서브클래스나 믹스인이 구현해야 한다. Go·Kotlin·Python·TypeScript 4개 언어는 `Communicator.send()`가 직접 `queuePacket`을 호출하는 concrete 구현을 제공한다. Dart의 이 설계 차이는 `HeartbeatMixin`이 `Communicator`에 믹스인되는 초기 구조에서 비롯된 레거시로, `@Deprecated transmitPacket`과 `_LegacyCommunicatorTransport` 데드코드를 동반한다. 테스트의 `_FakeCommunicator`도 동일한 이유로 불필요한 `send()` 오버라이드를 포함한다. 이번 작업으로 Dart를 다른 언어 구현과 동일한 구조로 맞춘다.
---
## [REFACTOR-1] `communicator.dart` — `send()` concrete 구현 + 레거시 삭제
### 문제
- `dart/lib/src/communicator.dart:63` — `send()`가 `abstract`여서 서브클래스 모두 구현 강제
- `dart/lib/src/communicator.dart:47-53` — `@Deprecated transmitPacket` 데드코드
- `dart/lib/src/communicator.dart:35,37` — `initialize()`의 `transport` 파라미터가 nullable이며, null 시 이미 삭제 대상인 `_LegacyCommunicatorTransport(this)` 폴백을 사용
- `dart/lib/src/communicator.dart:192-204` — `_LegacyCommunicatorTransport` 클래스 데드코드
### 해결 방법
1. `initialize()`의 `{Transport? transport}` → `{required Transport transport}` 변경
2. `_transport = transport ?? _LegacyCommunicatorTransport(this)` → `_transport = transport`
3. `@Deprecated transmitPacket` 메서드 삭제
4. `abstract Future<void> send<T>(T data)` → concrete 구현으로 교체
5. `_LegacyCommunicatorTransport` 클래스 삭제
**Before (communicator.dart:33-38):**
```dart
void initialize(
Map<String, GeneratedMessage Function(List<int>)> instanceGenerator,
{Transport? transport}) {
_instanceGenerator = instanceGenerator;
_transport = transport ?? _LegacyCommunicatorTransport(this);
}
```
**After:**
```dart
void initialize(
Map<String, GeneratedMessage Function(List<int>)> instanceGenerator,
{required Transport transport}) {
_instanceGenerator = instanceGenerator;
_transport = transport;
}
```
**Before (communicator.dart:47-53):**
```dart
/// Deprecated compatibility path for subclasses that still override writes.
///
/// New clients should pass a [Transport] to [initialize] instead.
@Deprecated('Pass a Transport to initialize instead.')
Future<void> transmitPacket(PacketBase base) {
return Future.error(StateError('transport is not initialized'));
}
```
**After:** 전체 삭제
**Before (communicator.dart:63):**
```dart
Future<void> send<T extends GeneratedMessage>(T data);
```
**After:**
```dart
Future<void> send<T extends GeneratedMessage>(T data) async {
if (isAlive) {
await queuePacket(PacketBase()
..typeName = data.info_.qualifiedMessageName
..nonce = ++nonce
..data = data.writeToBuffer());
}
}
```
**Before (communicator.dart:192-204):**
```dart
class _LegacyCommunicatorTransport implements Transport {
final Communicator _communicator;
_LegacyCommunicatorTransport(this._communicator);
@override
Future<void> writePacket(PacketBase base) {
return _communicator.transmitPacket(base);
}
@override
Future<void> close() async {}
}
```
**After:** 전체 삭제 (이 클래스 바로 아래의 `abstract class IDataHandler` 이후는 그대로 유지)
### 수정 파일 및 체크리스트
- `dart/lib/src/communicator.dart`
- [x] `initialize()` 파라미터: `{Transport? transport}` → `{required Transport transport}`
- [x] `initialize()` 바디: `_transport = transport ?? _LegacyCommunicatorTransport(this)` → `_transport = transport`
- [x] `@Deprecated transmitPacket` 메서드 전체 삭제 (docstring 포함)
- [x] `abstract Future<void> send<T extends GeneratedMessage>(T data)` → concrete 구현으로 교체
- [x] `_LegacyCommunicatorTransport` 클래스 전체 삭제
### 테스트 작성
추가 테스트 불필요. 기존 `communicator_test.dart` 6개 테스트가 `send()` 경로를 포함해 충분히 커버한다.
### 중간 검증
```
$ cd dart && dart analyze lib/src/communicator.dart
(No issues found!)
```
---
## [REFACTOR-2] `communicator_test.dart` — `_FakeCommunicator.send()` 오버라이드 제거
### 문제
`dart/test/communicator_test.dart:24-33` — `_FakeCommunicator.send()` 오버라이드가 REFACTOR-1 이후 `Communicator.send()`와 동일한 로직을 중복 구현한다.
```dart
@override
Future<void> send<T extends GeneratedMessage>(T data) async {
if (isAlive) {
await queuePacket(PacketBase()
..typeName = data.info_.qualifiedMessageName
..nonce = ++nonce
..data = data.writeToBuffer());
}
return Future.value();
}
```
### 해결 방법
`_FakeCommunicator.send()` 오버라이드 블록 전체 삭제. `Communicator.send()` 기본 구현이 그대로 사용된다.
### 수정 파일 및 체크리스트
- `dart/test/communicator_test.dart`
- [x] `_FakeCommunicator.send()` 오버라이드 삭제 (lines 24-33, `@override`부터 닫는 `}` 포함)
### 테스트 작성
기존 6개 테스트 그대로 사용.
### 중간 검증
```
$ cd dart && dart test test/communicator_test.dart
00:00 +6: All tests passed!
```
---
## 수정 파일 요약
| 파일 | 항목 |
|------|------|
| `dart/lib/src/communicator.dart` | REFACTOR-1 |
| `dart/test/communicator_test.dart` | REFACTOR-2 |
## 의존 관계 및 구현 순서
REFACTOR-1 먼저, 이후 REFACTOR-2 진행. REFACTOR-2는 REFACTOR-1이 완료된 상태에서만 컴파일된다.
## 최종 검증
```
$ cd dart && dart analyze
No issues found!
$ cd dart && dart test
00:xx +43: All tests passed!
```