# 代码重构前后对比 ## 整体改进 ### 原项目问题 ``` ❌ 每次调用都重新创建对象(浪费资源,状态丢失) ❌ 流程不清晰,难以扩展 ❌ 职责混乱,不知道在哪里插入新功能 ❌ 数据模型不完整(缺少中间状态的定义) ❌ 无法直观看出数据在各步骤间如何流动 ``` ### 改进后的特点 ``` ✅ 对象复用(一次初始化,重复使用) ✅ 清晰的4步数据流(每步职责明确) ✅ 易于扩展(预留位置清楚标记) ✅ 完整的数据模型(每步都有输出定义) ✅ 充分的注释和伪代码(易于理解和修改) ``` ## 具体对比 ### 对比1:主程序入口 #### 原代码 (Main.kt) ```kotlin fun main() { } // 空的,什么都没有 ``` #### 新代码 (Main.kt) ```kotlin fun main() { // 1. 加载样本轨迹 val route = sampleRoute // 2. 创建模拟器(只创建一次) val simulator = TrajectorySimulator(route) // 3. 配置参数 simulator.setPhysicsParams(...) simulator.setNoiseParams(...) // 4. 模拟循环(逐时间步调用) for (time in 0.0..duration step 0.1) { val motionState = simulator.simulate(time) println(motionState) } } ``` **改进**:清晰展示了如何使用,每个步骤有注释说明 --- ### 对比2:主处理流程 #### 原代码 (Runner.getCoordinate) ```kotlin class Runner(val route: List) { fun getCoordinate(time: Double): Coordinate { val path = PathLinearize(route) // ❌ 每次都创建 val physicEngine = RunnerPhysic() // ❌ 每次都创建 val noiseEngine = PathNoiseEngine() // ❌ 每次都创建 val distance = physicEngine.getDistance(time) val coordinate = path.getPointDistance(distance) val finalCoordinate = noiseEngine.applyNoise(coordinate.lat, coordinate.lon, physicEngine) return finalCoordinate } } ``` **问题**: - 每次都重新创建对象,浪费资源 - NoiseEngine 中的漂移状态会丢失 - 流程混乱,无法清晰看出数据如何流转 - 返回值类型混乱(Coordinate vs 其他) #### 新代码 (TrajectorySimulator.simulate) ```kotlin class TrajectorySimulator(route: List) { // 一次初始化,重复使用 private val pathInterpolator: PathInterpolator = PathInterpolator(route) private val physicsEngine: RunnerPhysics = RunnerPhysics() private val noiseProcessor: NoiseProcessor = NoiseProcessor() fun simulate(time: Double): MotionState { // ════════════════════════════════════════════ // 步骤1:计算物理状态 // ════════════════════════════════════════════ val physicsState = physicsEngine.calculate(time) // ✅ 返回 PhysicsState // ════════════════════════════════════════════ // 步骤2:路径插值 // ════════════════════════════════════════════ val rawCoordinate = pathInterpolator.interpolate(physicsState.distance) // ✅ 返回 RawCoordinate // ════════════════════════════════════════════ // 步骤3:添加噪声 // ════════════════════════════════════════════ val noisyCoordinate = noiseProcessor.applyNoise(rawCoordinate, physicsState) // ✅ 返回 NoisyCoordinate // ════════════════════════════════════════════ // 步骤4:组装最终状态 // ════════════════════════════════════════════ return MotionState(...) // ✅ 返回完整的 MotionState } } ``` **改进**: - 对象复用,提高效率 - 4步流程清晰,每步职责明确 - 每步都有明确的输入输出类型 - 易于理解和调试 --- ### 对比3:坐标数据模型 #### 原代码 ```kotlin // 只有两个坐标类,中间状态混乱 data class Coordinate(val lon: Double, val lat: Double, val time: Double) data class MetaCoordinate(val lon: Double, val lat: Double) ``` #### 新代码 ```kotlin // 完整的数据流定义 data class MetaCoordinate(val lon: Double, val lat: Double) // 原始轨迹点 data class RawCoordinate(val lon: Double, val lat: Double) // 无噪声插值点 data class NoisyCoordinate( val lon: Double, val lat: Double, val gpsError: Double // 记录噪声大小 ) data class Coordinate(val lon: Double, val lat: Double, val time: Double) // 带时间的坐标 ``` **改进**: - 每个数据流阶段都有明确的数据类型 - 便于调试和理解数据的变换过程 - 预留了噪声信息的记录 --- ### 对比4:物理引擎 #### 原代码 ```kotlin class RunnerPhysic { fun getDistance(time: Double): Double {} // ❌ 未实现,空的 } ``` #### 新代码 ```kotlin class RunnerPhysics( private val totalDistance: Double = 0.0, private val duration: Double = 1000.0, private val maxVelocity: Double = 4.0 ) { /** * 计算指定时间的物理状态 * * @param time 当前时间(秒) * @return 包含距离、速度、加速度的物理状态 */ fun calculate(time: Double): PhysicsState { // 伪代码说明: // 1. 计算距离 // 2. 计算速度 // 3. 计算加速度 val distance = getDistance(time) val velocity = 0.0 // TODO: 实现 val acceleration = 0.0 // TODO: 实现 return PhysicsState(time, distance, velocity, acceleration) } fun getDistance(time: Double): Double { // 伪代码说明 return 0.0 // TODO: 实现 } } ``` **改进**: - 返回类型改为 PhysicsState(包含完整的物理信息) - 添加了伪代码说明实现思路 - 添加了TODO标记,清楚地标出需要实现的地方 - 参数化了初始值(便于配置) --- ### 对比5:路径插值器 #### 原代码 (pathLinearlizer.kt) ```kotlin class PathLinearize(val nodes: List) { private val segments = nodes.windowed(2).map { (a, b) -> val distance = haversine(a, b) Triple(a, b, distance) } fun haversine(node1: MetaCoordinate, node2: MetaCoordinate): Double { // ... 完整的Haversine算法(逻辑保留) } fun getPointDistance(totalDistance: Double): MetaCoordinate { // ... 插值逻辑 } } ``` #### 新代码 (PathInterpolator.kt) ```kotlin class PathInterpolator(val nodes: List) { private val segments = nodes.windowed(2).map { (a, b) -> val distance = calculateHaversineDistance(a, b) // ✅ 改名:更清晰 Triple(a, b, distance) } fun interpolate(totalDistance: Double): RawCoordinate { // ✅ 改名:更直观 // ... 同样的插值逻辑,完全保留 } private fun calculateHaversineDistance(node1: MetaCoordinate, node2: MetaCoordinate): Double { // ✅ Haversine逻辑完全保留,只改了方法名 // 和原代码一模一样 } } ``` **改进**: - 类名改为 PathInterpolator(更准确) - 方法名改为 `interpolate` 和 `calculateHaversineDistance`(更清晰) - 返回类型改为 RawCoordinate(更明确) - **核心逻辑完全保留**,只改了命名 --- ### 对比6:噪声处理 #### 原代码 ```kotlin class PathNoiseEngine( private val gpsErrorStdDev: Double = 0.00002, private val driftWeight: Double = 0.3 ) { private val random = Random() private var driftLat = 0.0 private var driftLon = 0.0 fun applyNoise(rawLat: Double, rawLon: Double, physic: RunnerPhysic): Coordinate { // ... 白噪声和漂移逻辑(完全保留) return Coordinate(rawLon+whiteNoiseLon+driftLon, rawLat+whiteNoiseLat+driftLat, time = Double) // ❌ time = Double 是个错误,应该是实际时间值 } } ``` #### 新代码 (GpsNoiseEngine.kt) ```kotlin class GpsNoiseEngine( private val gpsErrorStdDev: Double = 0.00002, private val driftWeight: Double = 0.3 ) { /** * 应用GPS噪声到坐标 * * 伪代码: * 1. 生成白噪声 * 2. 生成漂移 * 3. 合并噪声 */ fun applyNoise( rawLon: Double, rawLat: Double, physicsState: PhysicsState ): Triple { // ✅ 更清晰的返回类型 // 第1步:白噪声(逻辑完全保留) val whiteNoiseLat = random.nextGaussian() * gpsErrorStdDev val whiteNoiseLon = random.nextGaussian() * gpsErrorStdDev // 第2步:漂移(逻辑完全保留) driftLat = driftLat * 0.8 + random.nextGaussian() * gpsErrorStdDev * driftWeight driftLon = driftLon * 0.8 + random.nextGaussian() * gpsErrorStdDev * driftWeight // 第3步:合并(逻辑完全保留) val finalLon = rawLon + whiteNoiseLon + driftLon val finalLat = rawLat + whiteNoiseLat + driftLat val totalError = sqrt((whiteNoiseLon + driftLon).pow(2) + (whiteNoiseLat + driftLat).pow(2)) return Triple(finalLon, finalLat, totalError) // ✅ 返回噪声大小便于记录 } } ``` 新增 NoiseProcessor(协调多个噪声引擎): ```kotlin class NoiseProcessor { private val gpsNoiseEngine = GpsNoiseEngine() // 预留位置: // private val velocityNoiseEngine = VelocityNoiseEngine() // private val accelerationNoiseEngine = AccelerationNoiseEngine() fun applyNoise(rawCoord: RawCoordinate, physicsState: PhysicsState): NoisyCoordinate { val (noisyLon, noisyLat, gpsError) = gpsNoiseEngine.applyNoise( rawCoord.lon, rawCoord.lat, physicsState ) // ✅ 预留位置: // val velocityNoise = velocityNoiseEngine.applyNoise(physicsState.velocity) // val accelNoise = accelerationNoiseEngine.applyNoise(physicsState.acceleration) return NoisyCoordinate(noisyLon, noisyLat, gpsError) } } ``` **改进**: - 返回值更明确(Triple 包含噪声大小) - 创建 NoiseProcessor 协调多个噪声引擎 - **GPS噪声算法逻辑完全保留** - 清晰标记了预留位置供未来扩展 --- ## 总结 | 方面 | 原代码 | 新代码 | |------|--------|--------| | **项目独立性** | 修改原项目 | 新建独立项目,原项目不动 | | **对象管理** | 每次重建 | 一次初始化,重复使用 | | **流程清晰度** | 混乱 | 4步清晰流程 | | **数据模型** | 不完整 | 完整的中间状态定义 | | **命名规范** | 不规范 | 规范统一 | | **注释文档** | 无 | 充分的伪代码和说明 | | **扩展预留** | 无 | 清晰标记的预留位置 | | **核心算法** | 保留 | **完全保留** | --- ## 如何使用新项目 1. **快速上手**:看 Main.kt(完整使用示例) 2. **理解流程**:看 DATA_FLOW_GUIDE.md(数据流参考) 3. **要修改代码**:看 README.md(各文件职责说明) 4. **要加新功能**:看 GpsNoiseEngine.kt(预留位置已标记)