Files
ch34/.planning/codebase/CONVENTIONS.md
2026-04-21 12:57:40 +08:00

8.7 KiB

Coding Conventions

Analysis Date: 2026-04-16

Overview

This is a Flutter plugin package (ch34) that provides USB-to-serial communication for WCH CH34X series chips. The codebase is written in Dart with Android native code (Java). The plugin follows the standard Flutter plugin federated architecture pattern.

Naming Patterns

Files:

  • Dart files use snake_case: ch34_manager.dart, ch34_platform_interface.dart, ch34_method_channel.dart, ch34_types.dart
  • Test files mirror source file names: ch34_test.dart, ch34_method_channel_test.dart
  • Java native files use PascalCase: Ch34Plugin.java, Ch34UsbStateStreamHandler.java

Classes:

  • PascalCase with Ch34 prefix for public API: Ch34Manager, Ch34Platform, MethodChannelCh34, Ch34Exception
  • Domain models without prefix: GpioStatus, SerialParameter, ModemStatus, UsbDeviceInfo
  • Enum naming: DataBits, StopBits, Parity, GpioDirection, GpioValue, SerialErrorType

Functions/Methods:

  • camelCase for all methods: getPlatformVersion(), enumDevice(), openDevice(), setSerialParameter()
  • Callback-style methods use descriptive names: setUsbStateListener(), registerDataCallback(), registerModemStatusCallback()
  • Private methods use underscore prefix: _cancelDataSubscription()
  • Private constructor pattern: Ch34Manager._() (static-only class)

Variables:

  • camelCase: deviceName, serialNumber, gpioIndex, onStateChanged
  • Private fields use underscore prefix: _dataSubscription, _modemCallback
  • Constants use const: const MethodChannel('ch34')

Parameters:

  • Named parameters use curly braces for optional: {int timeout = 0}
  • Required named parameters use required keyword in data classes

Code Style

Formatting:

  • Uses flutter_lints package (^3.0.0) with default flutter.yaml ruleset
  • Config: D:/code/new_git_code/flutter/ch34/analysis_options.yaml
  • Example app config: D:/code/new_git_code/flutter/ch34/example/analysis_options.yaml (same base, with commented-out custom rules)
  • No custom lint rules are enabled beyond the default Flutter set
  • No .prettierrc or other formatter config (uses Dart formatter defaults)

SDK Constraints:

  • SDK: >=3.4.3 <4.0.0 (D:/code/new_git_code/flutter/ch34/pubspec.yaml)
  • Flutter: >=3.3.0

Import Organization:

  1. Dart SDK imports first: import 'dart:typed_data';, import 'dart:async';
  2. Flutter framework imports: import 'package:flutter/services.dart';
  3. Third-party package imports: import 'package:plugin_platform_interface/plugin_platform_interface.dart';
  4. Relative local imports last: import 'ch34_platform_interface.dart';, import 'types/ch34_types.dart';
  • Groups separated by blank lines

Path Aliases:

  • No path aliases detected; all imports use relative paths within the package

Patterns

Static Manager Pattern: D:/code/new_git_code/flutter/ch34/lib/src/ch34_manager.dart uses a private constructor (Ch34Manager._()) with all static methods, delegating to Ch34Platform.instance. This provides a clean public API without requiring instantiation.

class Ch34Manager {
  Ch34Manager._();

  static Future<String?> getPlatformVersion() {
    return Ch34Platform.instance.getPlatformVersion();
  }
}

Platform Interface (Federated Plugin): D:/code/new_git_code/flutter/ch34/lib/src/ch34_platform_interface.dart extends PlatformInterface from plugin_platform_interface. Uses token-based verification for instance safety:

abstract class Ch34Platform extends PlatformInterface {
  Ch34Platform() : super(token: _token);
  static final Object _token = Object();
  static Ch34Platform? _instance;

  static Ch34Platform get instance { ... }
  static set instance(Ch34Platform instance) { ... }
}

MethodChannel + EventChannel Pattern: D:/code/new_git_code/flutter/ch34/lib/src/ch34_method_channel.dart uses:

  • MethodChannel for request-response calls: methodChannel.invokeMethod<bool>('openDevice', {...})
  • EventChannel for streaming data: dataEventChannel.receiveBroadcastStream({'deviceName': deviceName}).listen(...)
  • @visibleForTesting annotation for testable fields (channel names)

Data Class Pattern: D:/code/new_git_code/flutter/ch34/lib/src/types/ch34_types.dart uses immutable classes with:

  • const constructors
  • fromMap() factory for deserialization
  • toMap() method for serialization
  • toString() override for debugging
  • copyWith() for mutable updates (e.g., SerialParameter.copyWith())
  • ==/hashCode override for equality (e.g., UsbDeviceInfo)
class SerialParameter {
  const SerialParameter({
    this.baud = 115200,
    this.dataBits = DataBits.bits8,
    ...
  });

  factory SerialParameter.fromMap(Map<dynamic, dynamic> map) { ... }
  Map<String, dynamic> toMap() { ... }
  SerialParameter copyWith({ ... }) { ... }
}

Enum with Associated Values: Enums use associated integer values with fromValue() factory:

enum DataBits {
  bits5(5), bits6(6), bits7(7), bits8(8);
  const DataBits(this.value);
  final int value;
  static DataBits fromValue(int value) =>
    DataBits.values.firstWhere((e) => e.value == value, orElse: () => DataBits.bits8);
}

Null-Safe Default Handling: Method channel results consistently use null-coalescing for safe defaults:

return result ?? false;       // boolean methods
return result ?? 0;           // integer methods
return result ?? [];          // list methods
return result ?? Uint8List(0); // byte data

Section Comments: Code is organized with clear separator comments:

/// ==================== 基础方法 ====================
/// ==================== 设备枚举与识别 ====================
/// ==================== 数据读写 ====================

Error Handling

Custom Exception: D:/code/new_git_code/flutter/ch34/lib/src/ch34_method_channel.dart defines Ch34Exception:

class Ch34Exception implements Exception {
  const Ch34Exception(this.message);
  final String message;
  @override
  String toString() => 'Ch34Exception: $message';
}

Usage Patterns:

  • Platform interface methods document @throws Ch34Exception in JSDoc comments for methods that may fail
  • Actual throwing is limited: only GPIO methods throw Ch34Exception when native returns null
  • Most boolean methods return false on failure rather than throwing
  • Example app uses generic catch (e) for error display in UI:
    } catch (e) {
      setState(() {
        _status = '扫描失败: $e';
      });
    }
    
  • StateError thrown when platform instance not initialized:
    throw StateError('Ch34Platform.instance has not been initialized...');
    

Stream Error Handling: EventChannel streams use onError callback with debugPrint:

onError: (error) {
  debugPrint('CH34 data callback error: $error');
}

Logging

Framework: Flutter's debugPrint from package:flutter/foundation.dart

Patterns:

  • Used only in error callbacks within the method channel implementation
  • Log messages are descriptive with context prefix: 'CH34 USB state error: $error'
  • No logging framework beyond debugPrint
  • Debug mode toggle available via Ch34Manager.setDebug(bool) (passes to native side)

Comments & Documentation

API Documentation:

  • All public methods have /// Dart doc comments in Chinese
  • Consistent param/return documentation using @param and @return
  • Exception documentation using @throws
  • Library-level docs at D:/code/new_git_code/flutter/ch34/lib/ch34.dart include usage example in code block

Inline Comments:

  • Chinese section headers for method grouping
  • Method-level comments explain purpose, parameters, and return values

JSDoc/TSDoc Style:

  • Uses /// (not /** */) for doc comments
  • Parameter docs: /// @param deviceName 设备名称。
  • Return docs: /// @return \true` 成功,`false` 失败。`

Module Design

Exports:

  • Main entry D:/code/new_git_code/flutter/ch34/lib/ch34.dart exports all public types:
    export 'src/ch34_manager.dart';
    export 'src/types/ch34_types.dart';
    export 'src/ch34_platform_interface.dart' show Ch34Platform;
    export 'src/ch34_method_channel.dart' show Ch34Exception;
    
  • Backward-compatible barrel files at lib/ root:
    • D:/code/new_git_code/flutter/ch34/lib/ch34_platform_interface.dart
    • D:/code/new_git_code/flutter/ch34/lib/ch34_method_channel.dart

Layer Separation:

lib/ch34.dart                              -> Public API entry (exports)
lib/src/ch34_manager.dart                  -> Static facade (public-facing)
lib/src/ch34_platform_interface.dart       -> Abstract interface
lib/src/ch34_method_channel.dart           -> Concrete implementation
lib/src/types/ch34_types.dart              -> Data types and enums

Convention analysis: 2026-04-16