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
Ch34prefix 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
requiredkeyword in data classes
Code Style
Formatting:
- Uses
flutter_lintspackage (^3.0.0) with defaultflutter.yamlruleset - 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
.prettierrcor 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:
- Dart SDK imports first:
import 'dart:typed_data';,import 'dart:async'; - Flutter framework imports:
import 'package:flutter/services.dart'; - Third-party package imports:
import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - 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:
MethodChannelfor request-response calls:methodChannel.invokeMethod<bool>('openDevice', {...})EventChannelfor streaming data:dataEventChannel.receiveBroadcastStream({'deviceName': deviceName}).listen(...)@visibleForTestingannotation 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:
constconstructorsfromMap()factory for deserializationtoMap()method for serializationtoString()override for debuggingcopyWith()for mutable updates (e.g.,SerialParameter.copyWith())==/hashCodeoverride 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 Ch34Exceptionin JSDoc comments for methods that may fail - Actual throwing is limited: only GPIO methods throw
Ch34Exceptionwhen native returns null - Most boolean methods return
falseon failure rather than throwing - Example app uses generic
catch (e)for error display in UI:} catch (e) { setState(() { _status = '扫描失败: $e'; }); } StateErrorthrown 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
@paramand@return - Exception documentation using
@throws - Library-level docs at
D:/code/new_git_code/flutter/ch34/lib/ch34.dartinclude 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.dartexports 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.dartD:/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