238 lines
8.7 KiB
Markdown
238 lines
8.7 KiB
Markdown
# 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.
|
|
|
|
```dart
|
|
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:
|
|
|
|
```dart
|
|
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`)
|
|
|
|
```dart
|
|
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:
|
|
|
|
```dart
|
|
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:
|
|
```dart
|
|
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:
|
|
```dart
|
|
/// ==================== 基础方法 ====================
|
|
/// ==================== 设备枚举与识别 ====================
|
|
/// ==================== 数据读写 ====================
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
**Custom Exception:**
|
|
`D:/code/new_git_code/flutter/ch34/lib/src/ch34_method_channel.dart` defines `Ch34Exception`:
|
|
```dart
|
|
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:
|
|
```dart
|
|
} catch (e) {
|
|
setState(() {
|
|
_status = '扫描失败: $e';
|
|
});
|
|
}
|
|
```
|
|
- `StateError` thrown when platform instance not initialized:
|
|
```dart
|
|
throw StateError('Ch34Platform.instance has not been initialized...');
|
|
```
|
|
|
|
**Stream Error Handling:**
|
|
EventChannel streams use `onError` callback with `debugPrint`:
|
|
```dart
|
|
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:
|
|
```dart
|
|
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*
|