适用场景:个人开发者 + AI大模型协作模式

目录


0. 单兵+AI协作开发原则

第一性原理:为AI而写

你的代码有三个读者:

  1. 编译器(执行代码)
  2. 未来的你(维护代码)
  3. AI助手(理解和修改代码)

在单兵+AI模式下,AI是你最重要的结对编程伙伴

核心问题: 当你3个月后把这段代码粘贴给AI时,它能瞬间理解你要做什么吗?

最大化目标: 你与AI这个"双人团队"的长期开发效率。


为什么单兵更需要规范?

没有团队意味着:

  • 没有代码审查帮你发现问题
  • 没有同事提醒你重构
  • 所有技术债务都由你一个人承担
  • 3个月后的你就是"另一个人"

有AI协作意味着:

  • AI是你唯一的、永恒的、但有点"健忘"的结对伙伴
  • AI理解清晰结构的代码效率更高
  • 规范的代码让AI提供更准确的建议
  • 良好的命名和注释是AI的上下文
  • 小文件、单职责更利于AI逐个击破

关键转变: 从"写给自己看"到"写给AI理解"

单兵开发的核心原则

原则1: “AI友好” = “人类可读”

// AI擅长处理明确、无歧义、有模式的结构

// 不好 - 过于隐晦
var results = orders.Where(o => o.Status == 1).SelectMany(o => o.Items).GroupBy(i => i.Category);

// 好 - 显式步骤,AI和人类都容易理解
var activeOrders = orders.Where(o => o.Status == OrderStatus.Active);
var allItems = activeOrders.SelectMany(o => o.Items);
var itemsByCategory = allItems.GroupBy(i => i.Category);

原则2: "原子化"一切(最重要)

// 这是AI能高效工作的核心
// 方法必须极度短小:核心逻辑20-30行,工具方法10-15行

// 不好 - AI难以理解和修改
public void ProcessOrder(Order order)
{
    // 验证、计算、更新、通知...500行代码
}

// 好 - AI可以精准定位和修改每个步骤
public void ProcessOrder(Order order)
{
    ValidateOrder(order);
    var total = CalculateTotal(order);
    ApplyDiscount(order, total);
    UpdateInventory(order);
    SendConfirmationEmail(order);
}

原则3: 未来的你 = 健忘的AI

// 永远不要相信你未来的记忆力
// 把未来的你当成一个需要所有上下文的、全新的AI实例

// 不好 - 依赖记忆
public void Process(int t, bool f) { }

// 好 - 自解释
public void ProcessScanResults(int timeoutSeconds, bool forceRefresh) { }

原则4: AI先行开发法

// 工作流程:
// 1. 向AI描述需求
// 2. AI生成基础框架(保证结构是AI友好的)
// 3. 你在此基础上修改和优化
// 4. 让AI生成测试
// 5. 你运行测试并调整

// 示例Prompt:
// "AI,帮我写一个C#方法,检查订单是否属于该用户,
//  使用EF Core,处理订单不存在的情况,返回Result<bool>"

原则5: 小步快跑,频繁验证

  • 写完一个方法就测试,不要等到写完整个类
  • 使用AI帮你写单元测试,立即验证逻辑
  • Git提交要频繁,每个提交都是可运行的状态

原则6: 注释即Prompt

// 把注释当作你未来要发给AI的指令来写

/// <summary>
/// --- AI CONTEXT ---
/// Purpose: 计算运费,基于重量、目的地区域、会员状态
/// Dependencies: 调用ShippingApi.GetRates()(可能很慢,建议缓存1小时)
/// Special Cases:
/// - 重量>50kg视为超大件,返回固定高价
/// - 会员用户(isPremium=true)享受基础费率5折优惠
/// Last Modified: 2024-12-03 - 调整会员折扣从3折改为5折
/// </summary>
public decimal CalculateShippingCost(Order order)
{
    // 实现
}

// 3个月后,你只需复制这段注释给AI说:
// "根据这个逻辑,帮我修改,现在30kg以上就算大件"

与AI高效协作的技巧

技巧1: 使用明确的命名作为AI的上下文

// AI看到这个,就知道是临时文件清理策略
public class TempFileCleanStrategy : ICleanStrategy 
{
    // 方法名告诉AI具体做什么
    public void RemoveFilesOlderThanDays(string path, int days) { }
}

技巧2: 文件是"上下文容器",必须小而专注

  • 理想大小:200行以内(AI的完美上下文单元)
  • 可接受上限:300行
  • 必须拆分:>400行
  • 原因: 当你向AI提问时,提供的上下文越干净、越集中,AI的回答质量越高
  • 一个200行、职责单一的文件 = 完美的上下文单元
  • 一个1000行的"万能工具类" = 上下文污染源

技巧3: 用注释告诉AI你的思路

// TODO: 这里后续需要添加缓存,避免重复扫描同一目录
// 预期实现:使用MemoryCache,过期时间5分钟
public ScanResult Scan(string path)
{
    // AI看到这个注释,未来可以直接帮你实现缓存功能
}

技巧4: 标准化异常处理,让AI学习你的模式

// 统一的异常处理模式,AI可以在新代码中复制这个模式
public async Task<Result<T>> ExecuteAsync<T>(Func<Task<T>> operation)
{
    try
    {
        var result = await operation();
        return Result<T>.Success(result);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "操作失败");
        return Result<T>.Failure(ex.Message);
    }
}

单兵开发的时间投资建议

活动 团队开发 单兵开发 原因
前期设计 20% 30% 没人帮你发现架构问题
编码实现 50% 40% AI辅助提速
测试验证 20% 20% 不能省
文档注释 10% 10% 给未来的自己

何时求助于AI?

适合AI的场景:

  • 生成样板代码(CRUD、DTO)
  • 编写单元测试
  • 重构优化现有代码
  • 解释复杂的第三方库用法
  • 生成XML文档注释

不适合AI的场景:

  • 核心业务逻辑设计
  • 性能关键路径的优化
  • 安全敏感的代码
  • 架构层面的决策

单兵开发的红线

绝对不能做的事:

  1. 不测试就提交"应该没问题吧"
  2. 硬编码"临时用一下就改"
  3. 跳过异常处理"不会出错的"
  4. 不提交Git"代码还没写完"
  5. 依赖记忆"这个变量我记得是什么意思"

记住: 3个月后的你和现在的你是两个人,未来的你会感谢现在规范的你,也会诅咒现在偷懒的你。


1. 文件与类的规模控制

文件行数限制

类型 理想范围 可接受上限 需要重构
ViewModel 150-250行 300行 >400行
Service类 200-300行 400行 >500行
Repository 100-200行 250行 >300行
Helper/Util 50-150行 200行 >250行
Domain Model 50-100行 150行 >200行
Plugin实现 100-200行 250行 >300行

类职责数量

  • 单一职责: 一个类只应有一个变更原因
  • 最多职责: 不超过3个紧密相关的核心职责
  • 依赖注入参数: 构造函数参数不超过5个(超过则考虑引入配置对象)

拆分策略

场景1: ViewModel过大

// 不好的做法 - 单个ViewModel处理所有逻辑
public class MainViewModel : ViewModelBase
{
    // 文件管理相关
    public void ScanFiles() { }
    public void DeleteFiles() { }
    
    // 设置相关
    public void SaveSettings() { }
    public void LoadSettings() { }
    
    // 报告相关
    public void GenerateReport() { }
    public void ExportReport() { }
}

// 好的做法 - 按功能域拆分
public class MainViewModel : ViewModelBase
{
    private readonly FileManagementViewModel _fileManagement;
    private readonly SettingsViewModel _settings;
    private readonly ReportViewModel _report;
}

场景2: Service过大

// 不好的做法 - 上帝类
public class FileService
{
    public void Scan() { }
    public void Delete() { }
    public void Move() { }
    public void Compress() { }
    public void Analyze() { }
    public void Export() { }
}

// 好的做法 - 职责分离
public class FileScanService { }
public class FileCleanService { }
public class FileAnalysisService { }
public class FileExportService { }

2. 方法复杂度管理

方法长度规则(为AI优化)

核心理念: 方法越短,AI越容易理解、修改和优化。

方法类型 理想长度 可接受上限 必须拆分 原因
工具/辅助方法 5-10行 15行 >20行 AI可以一眼看穿逻辑
核心业务方法 15-25行 30行 >40行 AI可以完整理解业务流程
协调方法 10-20行 25行 >30行 只协调,不包含复杂逻辑

总原则:

  • 绝对上限:50行(任何方法超过50行必须拆分)
  • AI最爱:10-15行的纯函数(输入→处理→输出,无副作用)

圈复杂度控制

  • 简单方法: 圈复杂度 ≤ 5
  • 中等复杂: 圈复杂度 6-10
  • 需要重构: 圈复杂度 > 10

降低复杂度技巧

技巧1: 提前返回(Early Return)

// 不好的做法 - 多层嵌套
public bool ValidateFile(string path)
{
    if (!string.IsNullOrEmpty(path))
    {
        if (File.Exists(path))
        {
            if (new FileInfo(path).Length > 0)
            {
                return true;
            }
        }
    }
    return false;
}

// 好的做法 - 提前返回
public bool ValidateFile(string path)
{
    if (string.IsNullOrEmpty(path)) return false;
    if (!File.Exists(path)) return false;
    if (new FileInfo(path).Length == 0) return false;
    return true;
}

技巧2: 策略模式替代条件分支

// 不好的做法 - 大量if-else
public void CleanFile(FileType type)
{
    if (type == FileType.Temp)
    {
        // 临时文件清理逻辑
    }
    else if (type == FileType.Cache)
    {
        // 缓存文件清理逻辑
    }
    else if (type == FileType.Log)
    {
        // 日志文件清理逻辑
    }
}

// 好的做法 - 策略模式
public interface ICleanStrategy
{
    void Clean(string path);
}

public class TempFileCleanStrategy : ICleanStrategy { }
public class CacheFileCleanStrategy : ICleanStrategy { }
public class LogFileCleanStrategy : ICleanStrategy { }

public class FileCleanService
{
    private readonly Dictionary<FileType, ICleanStrategy> _strategies;
    
    public void CleanFile(FileType type, string path)
    {
        _strategies[type].Clean(path);
    }
}

技巧3: 提取方法

// 不好的做法 - 一个方法做太多事
public async Task<ScanResult> ScanDirectory(string path)
{
    var result = new ScanResult();
    
    // 验证路径
    if (string.IsNullOrEmpty(path)) throw new ArgumentException();
    if (!Directory.Exists(path)) throw new DirectoryNotFoundException();
    
    // 扫描文件
    var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
    
    // 分析文件
    foreach (var file in files)
    {
        var info = new FileInfo(file);
        if (info.Length > 1024 * 1024) result.LargeFiles.Add(file);
        if (info.Extension == ".tmp") result.TempFiles.Add(file);
        if (info.LastAccessTime < DateTime.Now.AddMonths(-6)) result.OldFiles.Add(file);
    }
    
    // 生成报告
    result.TotalSize = result.LargeFiles.Sum(f => new FileInfo(f).Length);
    
    return result;
}

// 好的做法 - 提取方法
public async Task<ScanResult> ScanDirectory(string path)
{
    ValidatePath(path);
    var files = GetAllFiles(path);
    var result = AnalyzeFiles(files);
    CalculateStatistics(result);
    return result;
}

private void ValidatePath(string path) { }
private IEnumerable<string> GetAllFiles(string path) { }
private ScanResult AnalyzeFiles(IEnumerable<string> files) { }
private void CalculateStatistics(ScanResult result) { }

3. SOLID原则实践

单一职责原则 (SRP)

定义: 一个类应该只有一个引起它变化的原因

// 违反SRP - 类做了太多事
public class FileManager
{
    public void ScanFiles() { }
    public void DeleteFiles() { }
    public void LogOperation() { }
    public void SendNotification() { }
    public void UpdateDatabase() { }
}

// 遵循SRP - 职责分离
public class FileScanner
{
    public ScanResult Scan(string path) { }
}

public class FileCleaner
{
    public void Delete(IEnumerable<string> files) { }
}

public class OperationLogger
{
    public void Log(string message) { }
}

开闭原则 (OCP)

定义: 对扩展开放,对修改关闭

// 违反OCP - 每次新增类型都要修改
public class ReportGenerator
{
    public void Generate(ReportType type)
    {
        if (type == ReportType.Pdf)
        {
            // PDF生成逻辑
        }
        else if (type == ReportType.Excel)
        {
            // Excel生成逻辑
        }
        // 新增类型需要修改这里
    }
}

// 遵循OCP - 通过继承扩展
public abstract class ReportGenerator
{
    public abstract void Generate(ScanResult result);
}

public class PdfReportGenerator : ReportGenerator
{
    public override void Generate(ScanResult result) { }
}

public class ExcelReportGenerator : ReportGenerator
{
    public override void Generate(ScanResult result) { }
}

// 新增类型只需添加新类,不修改现有代码
public class HtmlReportGenerator : ReportGenerator
{
    public override void Generate(ScanResult result) { }
}

里氏替换原则 (LSP)

定义: 子类必须能够替换其基类

// 违反LSP - 子类改变了基类的行为契约
public class FileReader
{
    public virtual string Read(string path)
    {
        return File.ReadAllText(path);
    }
}

public class CompressedFileReader : FileReader
{
    public override string Read(string path)
    {
        throw new NotSupportedException("使用ReadCompressed方法");
    }
}

// 遵循LSP - 子类保持基类的契约
public abstract class FileReader
{
    public abstract string Read(string path);
}

public class TextFileReader : FileReader
{
    public override string Read(string path)
    {
        return File.ReadAllText(path);
    }
}

public class CompressedFileReader : FileReader
{
    public override string Read(string path)
    {
        // 解压并读取,但接口契约不变
        return DecompressAndRead(path);
    }
}

接口隔离原则 (ISP)

定义: 不应强迫客户端依赖它不使用的方法

// 违反ISP - 接口过于臃肿
public interface IFileService
{
    void Scan();
    void Delete();
    void Move();
    void Compress();
    void Encrypt();
    void Backup();
}

// 客户端只需要扫描功能,却被迫依赖所有方法
public class QuickScanner : IFileService
{
    public void Scan() { /* 实现 */ }
    
    // 不需要这些方法,但必须实现
    public void Delete() => throw new NotImplementedException();
    public void Move() => throw new NotImplementedException();
    public void Compress() => throw new NotImplementedException();
    public void Encrypt() => throw new NotImplementedException();
    public void Backup() => throw new NotImplementedException();
}

// 遵循ISP - 接口细化
public interface IFileScanner
{
    void Scan();
}

public interface IFileCleaner
{
    void Delete();
}

public interface IFileArchiver
{
    void Compress();
    void Encrypt();
}

// 客户端只依赖需要的接口
public class QuickScanner : IFileScanner
{
    public void Scan() { /* 实现 */ }
}

依赖倒置原则 (DIP)

定义: 高层模块不应依赖低层模块,两者都应依赖抽象

// 违反DIP - 直接依赖具体类
public class ScanService
{
    private readonly FileSystemScanner _scanner = new FileSystemScanner();
    
    public void Scan()
    {
        _scanner.Scan();
    }
}

// 遵循DIP - 依赖抽象
public interface IScanner
{
    void Scan();
}

public class FileSystemScanner : IScanner
{
    public void Scan() { }
}

public class EverythingScanner : IScanner
{
    public void Scan() { }
}

public class ScanService
{
    private readonly IScanner _scanner;
    
    // 依赖注入,依赖抽象而非具体
    public ScanService(IScanner scanner)
    {
        _scanner = scanner;
    }
    
    public void Scan()
    {
        _scanner.Scan();
    }
}

4. 命名规范

基本规则

  • 类名: PascalCase,名词或名词短语
  • 接口名: PascalCase,以"I"开头
  • 方法名: PascalCase,动词或动词短语
  • 变量名: camelCase
  • 常量名: PascalCase或UPPER_CASE
  • 私有字段: _camelCase(下划线前缀)

命名的艺术

原则1: 见名知意

// 不好的命名
public class Manager { }
public void Process() { }
public int d; // 天数? 距离? 删除?

// 好的命名
public class FileScanManager { }
public void ProcessScanResults() { }
public int durationInDays;

原则2: 避免缩写

// 不好的命名
public void DelTmpFiles() { }
public int cnt;
public string usr;

// 好的命名
public void DeleteTemporaryFiles() { }
public int fileCount;
public string userName;

原则3: 具体而非抽象

// 不好的命名
public class DataManager { }
public void Handle() { }
public void DoWork() { }

// 好的命名
public class ScanResultRepository { }
public void HandleFileDeleteRequest() { }
public void ScanDirectoryForTempFiles() { }

原则4: 使用领域语言

// CleanTools项目的领域术语
public class ScanSession { }      // 扫描会话
public class CleaningRule { }     // 清理规则
public class FileCategory { }     // 文件类别
public class PluginMetadata { }   // 插件元数据

禁用的命名模式

禁止的类名后缀

  • Manager - 过于宽泛(除非真正管理生命周期)
  • Helper - 职责不明确
  • Util - 容易成为垃圾桶
  • Common - 过于抽象

替代方案

// 不好
public class FileHelper { }

// 好 - 根据具体职责命名
public class FilePathValidator { }
public class FileExtensionDetector { }
public class FileSizeCalculator { }

5. 依赖管理

依赖注入最佳实践

规则1: 构造函数注入优先

// 好的做法 - 依赖明确
public class ScanService
{
    private readonly IFileScanner _scanner;
    private readonly ILogger<ScanService> _logger;
    
    public ScanService(
        IFileScanner scanner,
        ILogger<ScanService> logger)
    {
        _scanner = scanner ?? throw new ArgumentNullException(nameof(scanner));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }
}

规则2: 避免服务定位器

// 不好的做法 - 服务定位器
public class ScanService
{
    public void Scan()
    {
        var scanner = ServiceLocator.Get<IFileScanner>();
        scanner.Scan();
    }
}

// 好的做法 - 依赖注入
public class ScanService
{
    private readonly IFileScanner _scanner;
    
    public ScanService(IFileScanner scanner)
    {
        _scanner = scanner;
    }
    
    public void Scan()
    {
        _scanner.Scan();
    }
}

规则3: 控制依赖数量

// 不好的做法 - 依赖过多(上帝类)
public class ScanService
{
    public ScanService(
        IFileScanner scanner,
        IFileCleaner cleaner,
        ILogger logger,
        IConfiguration config,
        INotifier notifier,
        IReporter reporter,
        IAnalyzer analyzer,
        IValidator validator)
    { }
}

// 好的做法 - 引入聚合依赖或拆分服务
public class ScanConfiguration
{
    public IFileScanner Scanner { get; set; }
    public ILogger Logger { get; set; }
    public IConfiguration Configuration { get; set; }
}

public class ScanService
{
    private readonly ScanConfiguration _config;
    
    public ScanService(ScanConfiguration config)
    {
        _config = config;
    }
}

生命周期管理

// Program.cs 或 Startup.cs
services.AddSingleton<IConfiguration, AppConfiguration>();     // 单例 - 配置
services.AddScoped<IScanSession, ScanSession>();               // 作用域 - 会话
services.AddTransient<IFileScanner, FileSystemScanner>();      // 瞬时 - 无状态服务

生命周期选择指南

  • Singleton: 无状态服务、配置、缓存
  • Scoped: 单次操作的上下文(如扫描会话)
  • Transient: 轻量级无状态服务

6. 异步编程规范

基本规则

规则1: 异步到底

// 不好的做法 - 异步方法同步调用
public void ScanFiles()
{
    var result = ScanFilesAsync().Result; // 可能死锁
}

// 好的做法 - 异步链
public async Task ScanFilesAsync()
{
    var result = await ScanFilesInternalAsync();
}

规则2: 避免async void

// 不好的做法 - 异常无法捕获
public async void DeleteFiles()
{
    await fileService.DeleteAsync();
}

// 好的做法 - 返回Task
public async Task DeleteFilesAsync()
{
    await fileService.DeleteAsync();
}

// 唯一例外:事件处理器
private async void OnButtonClick(object sender, EventArgs e)
{
    try
    {
        await DeleteFilesAsync();
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "删除文件失败");
    }
}

规则3: ConfigureAwait正确使用

// 库代码或服务层 - 使用ConfigureAwait(false)
public async Task<ScanResult> ScanAsync()
{
    var files = await GetFilesAsync().ConfigureAwait(false);
    return await AnalyzeAsync(files).ConfigureAwait(false);
}

// UI代码 - 不使用ConfigureAwait或使用ConfigureAwait(true)
private async void OnScanClick(object sender, EventArgs e)
{
    var result = await _scanService.ScanAsync();
    ResultTextBox.Text = result.ToString(); // 需要UI上下文
}

并发控制

场景: 限制并发数量

public class FileScanService
{
    private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(4); // 最多4个并发
    
    public async Task<List<FileInfo>> ScanDirectoriesAsync(IEnumerable<string> directories)
    {
        var tasks = directories.Select(async dir =>
        {
            await _semaphore.WaitAsync();
            try
            {
                return await ScanDirectoryAsync(dir);
            }
            finally
            {
                _semaphore.Release();
            }
        });
        
        var results = await Task.WhenAll(tasks);
        return results.SelectMany(r => r).ToList();
    }
}

取消令牌

public async Task<ScanResult> ScanAsync(
    string path,
    IProgress<ScanProgress> progress,
    CancellationToken cancellationToken)
{
    var result = new ScanResult();
    var files = Directory.GetFiles(path);
    
    for (int i = 0; i < files.Length; i++)
    {
        cancellationToken.ThrowIfCancellationRequested();
        
        await ProcessFileAsync(files[i]);
        
        progress?.Report(new ScanProgress
        {
            Current = i + 1,
            Total = files.Length
        });
    }
    
    return result;
}

7. 错误处理

异常处理原则

原则1: 快速失败

public class FileScanService
{
    private readonly IFileScanner _scanner;
    
    public FileScanService(IFileScanner scanner)
    {
        _scanner = scanner ?? throw new ArgumentNullException(nameof(scanner));
    }
    
    public ScanResult Scan(string path)
    {
        if (string.IsNullOrWhiteSpace(path))
            throw new ArgumentException("路径不能为空", nameof(path));
        
        if (!Directory.Exists(path))
            throw new DirectoryNotFoundException($"目录不存在: {path}");
        
        return _scanner.Scan(path);
    }
}

原则2: 异常分层

// 领域异常
public class ScanException : Exception
{
    public ScanException(string message) : base(message) { }
    public ScanException(string message, Exception innerException) 
        : base(message, innerException) { }
}

public class FileAccessException : ScanException
{
    public string FilePath { get; }
    
    public FileAccessException(string filePath, string message) 
        : base(message)
    {
        FilePath = filePath;
    }
}

// 使用
public async Task<ScanResult> ScanAsync(string path)
{
    try
    {
        return await _scanner.ScanAsync(path);
    }
    catch (UnauthorizedAccessException ex)
    {
        throw new FileAccessException(path, "无权限访问文件", ex);
    }
    catch (IOException ex)
    {
        throw new ScanException("扫描过程中发生IO错误", ex);
    }
}

原则3: 不要吞掉异常

// 不好的做法
try
{
    DeleteFile(path);
}
catch
{
    // 静默失败,问题难以定位
}

// 好的做法1 - 记录日志
try
{
    DeleteFile(path);
}
catch (Exception ex)
{
    _logger.LogError(ex, "删除文件失败: {Path}", path);
    throw; // 重新抛出
}

// 好的做法2 - 转换异常
try
{
    DeleteFile(path);
}
catch (IOException ex)
{
    throw new FileDeleteException(path, "无法删除文件", ex);
}

返回值 vs 异常

使用异常的场景

  • 真正的错误条件(文件不存在、权限不足)
  • 无法继续执行的情况
  • 调用者无法预见的错误

使用返回值的场景

  • 预期的失败(验证失败)
  • 可选操作的结果
  • 需要携带详细错误信息
// 场景1: 验证使用返回值
public ValidationResult Validate(FileInfo file)
{
    if (file.Length == 0)
        return ValidationResult.Fail("文件为空");
    
    if (file.Extension != ".txt")
        return ValidationResult.Fail("不支持的文件类型");
    
    return ValidationResult.Success();
}

// 场景2: IO操作使用异常
public string ReadFile(string path)
{
    if (!File.Exists(path))
        throw new FileNotFoundException("文件不存在", path);
    
    return File.ReadAllText(path);
}

8. 注释与文档

核心原则:注释是给AI的Prompt

注释的三个读者优先级:

  1. AI(未来帮你修改代码)
  2. 未来的你(3个月后维护代码)
  3. 当前的你(理解代码逻辑)

结构化注释模板(AI上下文)

对于核心方法,使用结构化的AI上下文注释:

/// <summary>
/// --- AI CONTEXT ---
/// Function: CalculateTotalPrice
/// Purpose: 计算订单总价,包含折扣、运费、税费
/// 
/// Dependencies:
/// - PricingService.GetBasePrice() - 获取基础价格
/// - DiscountService.ApplyDiscounts() - 应用折扣规则
/// - ShippingApi.CalculateShipping() - 计算运费(可能慢,建议缓存)
/// 
/// Business Rules:
/// - VIP用户享受基础价格8折
/// - 满500元包邮
/// - 税率根据用户地区不同:本地5%,外地8%
/// 
/// Special Cases:
/// - 如果是礼品卡订单,跳过运费和税费计算
/// - 预售商品不参与折扣活动
/// 
/// Performance:
/// - 该方法会调用外部API,平均耗时200ms
/// - 建议对相同参数的结果缓存5分钟
/// 
/// Last Modified: 2024-12-03 - 调整VIP折扣从7折改为8折
/// Related Issues: #123 (用户反馈折扣计算有误)
/// </summary>
public decimal CalculateTotalPrice(Order order, User user)
{
    // 实现
}

简化版(普通方法):

/// <summary>
/// 验证文件路径是否合法
/// 检查:路径非空、文件存在、有读取权限
/// 失败时抛出ArgumentException或UnauthorizedAccessException
/// </summary>
public void ValidateFilePath(string path)
{
    // 实现
}

注释的基本原则

原则1: 代码说What,注释说Why

// 不好 - 注释重复代码
// 获取文件大小
public long GetSize(string path)
{
    return new FileInfo(path).Length;
}

// 好 - 注释说明Why
/// <summary>
/// 使用FileInfo而非FileStream以避免锁定文件
/// 在扫描大量文件时,FileStream会导致"文件被占用"错误
/// </summary>
public long GetFileSizeWithoutLocking(string path)
{
    return new FileInfo(path).Length;
}

原则2: 注释是未来给AI的指令

// 好的注释可以这样用:
// 3个月后,复制注释给AI:
// "根据上面的AI CONTEXT,帮我修改代码,现在VIP折扣改为7折"
// AI就能精准修改,无需你解释业务逻辑

XML文档注释

必须添加XML注释的情况

  • 公共API
  • 复杂算法
  • 非显而易见的行为
/// <summary>
/// 扫描指定目录中的临时文件
/// </summary>
/// <param name="path">要扫描的目录路径</param>
/// <param name="recursive">是否递归扫描子目录</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>包含所有临时文件信息的扫描结果</returns>
/// <exception cref="ArgumentException">路径为空或无效</exception>
/// <exception cref="DirectoryNotFoundException">目录不存在</exception>
/// <exception cref="UnauthorizedAccessException">无权限访问目录</exception>
public async Task<ScanResult> ScanTempFilesAsync(
    string path,
    bool recursive = true,
    CancellationToken cancellationToken = default)
{
    // 实现
}

TODO注释规范

// 单兵开发:日期和原因比姓名更重要
// TODO: 2024-12-03 - 添加缓存以提升性能,当前每次都重新扫描
// FIXME: 2024-12-03 - 处理并发访问冲突,复现场景:同时扫描和清理
// HACK: 2024-12-03 - 临时方案,等待Everything API更新到v2.0
// NOTE: 此处使用异步而非并行以避免文件锁冲突
// IDEA: 可以考虑使用观察者模式,让UI自动响应扫描进度

项目文档:README是AI的"项目总纲"

核心理念: README.md是你向AI介绍整个项目的"第一句话"。当你把整个项目交给AI时,先给它看README,它就能建立全局认知。

README.md必备内容
# CleanTools - 系统清理工具

## 一句话简介
面向开发者和普通用户的高效系统清理工具,集成Everything搜索引擎,支持极速扫描和插件化扩展。

## 核心业务流程
1. 用户选择扫描目录
2. 系统识别文件类型(临时文件、缓存、日志等)
3. 展示扫描结果和清理建议
4. 用户确认后执行清理
5. 生成清理报告

## 技术栈
- **框架**: .NET 8 + WPF
- **架构**: MVVM + 插件化
- **数据库**: SQLite (文件类型规则)
- **依赖注入**: Microsoft.Extensions.DependencyInjection
- **日志**: Serilog
- **可选集成**: Everything API (极速文件搜索)

## 项目结构

CleanTools/
├── src/
│ ├── CleanTools.App/ # WPF应用程序主入口
│ ├── CleanTools.Core/ # 核心业务逻辑和服务
│ ├── CleanTools.SDK/ # 公共接口和类型定义
│ ├── CleanTools.PluginHost/ # 插件宿主和管理
│ └── CleanTools.Infrastructure/ # 基础设施服务
├── plugins/ # 插件目录
├── data/ # 数据库和配置文件
└── docs/ # 项目文档

## 核心设计模式
- **插件模式**: 所有清理策略都是插件,实现ICleanerPlugin接口
- **仓储模式**: 数据访问层使用Repository模式
- **策略模式**: 文件类型识别和清理规则使用策略模式

## 快速开始
```bash
# 克隆项目
git clone https://github.com/username/CleanTools.git

# 还原依赖
dotnet restore

# 运行应用
dotnet run --project src/CleanTools.App

# 运行测试
dotnet test

关键配置

  • 数据库位置: d:\Work\CleanTools\data\FileTypes.db
  • 插件目录: ./plugins
  • 日志目录: ./logs

AI协作提示

当使用AI修改代码时,建议:

  1. 先阅读本README了解全局架构
  2. 查看相关模块的AI CONTEXT注释
  3. 修改后运行单元测试验证
  4. 更新相关文档

注意事项

  • Everything集成是可选的,未安装时使用标准文件搜索
  • 清理操作会移动文件到回收站,而非直接删除
  • 插件开发参考 docs/plugin-development.md
#### 其他推荐文档

**ARCHITECTURE.md** - 架构设计文档
```markdown
# CleanTools 架构设计

## 分层架构
[四层架构图和说明]

## 核心模块交互
[模块交互流程图]

## 关键技术决策
- 为什么使用Everything API?
- 为什么采用插件化架构?
- 为什么使用SQLite而非JSON配置?

CHANGELOG.md - 变更日志

# 变更日志

## [1.2.0] - 2024-12-03
### Added
- 新增大文件扫描功能
- 支持自定义清理规则

### Changed
- 优化文件扫描性能,速度提升50%
- 调整UI布局,更符合用户习惯

### Fixed
- 修复并发扫描时的文件锁定问题
为什么项目文档对AI很重要?

场景1: 全新开始一个功能

你: "请阅读README.md,然后帮我设计一个新的插件,
     用于清理Chrome浏览器缓存"
AI: [理解全局架构后] "好的,根据你的插件模式,
    需要实现ICleanerPlugin接口..."

场景2: 修改现有功能

你: "根据ARCHITECTURE.md中的分层架构,
     帮我把文件扫描逻辑从Core层移到Infrastructure层"
AI: [理解架构约束后] "明白,这样修改不会破坏依赖关系..."

场景3: 排查问题

你: "看看CHANGELOG.md中1.2.0版本修复的并发问题,
     现在又出现了,帮我分析一下"
AI: [根据历史修复记录] "上次修复使用了锁,现在可能是..."

9. 测试策略(单兵实用版)

单兵开发不需要追求高覆盖率,但关键逻辑必须有保障。

单兵开发的测试现实

团队开发的测试金字塔(不适合单兵):

       /\
      /  \      E2E测试 (10%)
     /----\
    /      \    集成测试 (20%)
   /--------\
  /          \  单元测试 (70%)  ← 太理想化
 /____________\

单兵开发的实际测试策略:

手动测试 (60%) - 改完就测,通过就继续
自动测试 (40%) - 只测关键逻辑和回归场景

何时需要写自动化测试?

必须写测试的场景(避免反复手动测):

  1. 复杂业务逻辑

    • 文件类型识别算法
    • 清理规则匹配逻辑
    • 文件大小计算(单位转换)
  2. 容易出错的边界条件

    • null、空字符串、空集合
    • 文件不存在、权限不足
    • 极大/极小数值
  3. 曾经出过bug的地方

    • 修复bug后写个测试,防止再犯
    • 这是最有价值的测试
  4. 经常改动的代码

    • 需求频繁变化的部分
    • 写测试避免改一个坏一堆

不需要写测试的场景(手动测就行):

  • 简单的CRUD操作
  • UI交互逻辑
  • 一次性的数据迁移脚本
  • 显而易见的Get/Set属性
  • 配置读写

单兵测试的三个层次

层次1: 手动冒烟测试(每次改动必做)

改完代码 → F5运行 → 点几下UI → 看看是否正常 → 继续

这是最实际的做法,不要有心理负担。

层次2: 关键路径测试(AI辅助生成)

// 让AI帮你写,5分钟搞定
[Fact]
public void CleanTempFiles_ShouldDeleteOnlyTempFiles()
{
    // 这种测试值得写,因为逻辑重要且容易出错
}

层次3: 回归测试(出过bug的必写)

// 曾经这里出过bug:文件大小为0时除零异常
[Fact]
public void CalculateAverageSize_WhenFileCountIsZero_ReturnsZero()
{
    var result = calculator.CalculateAverageSize(0, 0);
    Assert.Equal(0, result);
}

实用测试技巧

技巧1: 让AI帮你写测试

你:"请为这个方法生成单元测试,覆盖正常情况和边界条件"
AI:"好的,这是测试代码..."
你:复制粘贴,运行,通过,提交

技巧2: 测试即文档

// 好的测试名称就是文档
[Fact]
public void Scan_WithNonExistentDirectory_ThrowsDirectoryNotFoundException()
{
    // 3个月后看到这个测试,立刻明白行为
}

技巧3: 一个测试只测一件事

// 不好 - 测试太多东西
[Fact]
public void ComplexTest()
{
    // 测试扫描
    var scanResult = scanner.Scan();
    Assert.NotNull(scanResult);
    
    // 测试清理
    var cleanResult = cleaner.Clean();
    Assert.True(cleanResult);
    
    // 测试报告
    var report = reporter.Generate();
    Assert.NotEmpty(report);
}

// 好 - 一个测试一个关注点
[Fact]
public void Scan_ReturnsNonNullResult()
{
    var result = scanner.Scan();
    Assert.NotNull(result);
}

技巧4: 建立测试模板

// 创建一个测试基类,复用常用逻辑
public class FileServiceTestBase
{
    protected string CreateTempFile(string content)
    {
        var path = Path.GetTempFileName();
        File.WriteAllText(path, content);
        return path;
    }
    
    protected void Cleanup(string path)
    {
        if (File.Exists(path))
            File.Delete(path);
    }
}

// 测试类继承基类
public class FileScannerTests : FileServiceTestBase
{
    [Fact]
    public void Test()
    {
        var file = CreateTempFile("test");
        try
        {
            // 测试逻辑
        }
        finally
        {
            Cleanup(file);
        }
    }
}

单兵测试的时间分配建议

改动小功能(30分钟):
- 手动测试: 5分钟
- 自动测试: 0分钟(不写)

改动核心逻辑(2小时):
- 手动测试: 10分钟
- 自动测试: 10分钟(让AI写)

修复bug(1小时):
- 手动测试: 5分钟
- 回归测试: 5分钟(防止再犯)

测试覆盖率的现实目标

不要追求:

  • ❌ 90%覆盖率(浪费时间)
  • ❌ 所有方法都有测试(没必要)
  • ❌ 100%分支覆盖(过度工程)

实际目标:

  • ✅ 核心算法有测试(20-30%覆盖率)
  • ✅ 出过bug的地方有回归测试
  • ✅ 复杂逻辑有边界条件测试
  • ✅ 手动测试覆盖主要功能

何时运行测试?

每次运行全部测试(如果有):

  • 提交代码前
  • 修改核心逻辑后
  • 发布新版本前

只运行相关测试:

  • 日常开发时
  • 修改局部功能时

完全依赖手动测试:

  • 改UI样式
  • 调整配置
  • 修改文本提示

可测试性设计(可选)

如果你愿意写测试,这些设计会让测试更容易:

// 使用依赖注入,方便替换实现
public class FileScanner
{
    private readonly IFileSystem _fileSystem;
    
    public FileScanner(IFileSystem fileSystem)
    {
        _fileSystem = fileSystem;
    }
}

// 返回值而非void,方便验证结果
public Result<int> DeleteFiles(List<string> files)
{
    return Result<int>.Success(deletedCount);
}

// 纯函数优于有副作用的函数,容易测试
public static long CalculateSize(IEnumerable<FileInfo> files)
{
    return files.Sum(f => f.Length);
}

但如果不写测试,这些设计可以简化:

// 直接使用具体实现
public class FileScanner
{
    public void Scan(string path)
    {
        var files = Directory.GetFiles(path); // 直接调用
    }
}

记住

测试的目的是保证质量,不是完成KPI:

  • 手动测试通过 = 代码可以提交
  • 关键逻辑有测试 = 未来改动有保障
  • 不写测试不代表不负责,写了测试也不代表代码质量高

单兵开发的黄金准则:
改完就测,测完就提交,出bug就补测试。简单有效。


10. 自我检查清单

单兵开发没有代码审查,所以要学会自己审查自己。
建议:每天下班前花10分钟检查今天写的代码。

A. 设计层面(架构自查)

核心问题:3个月后的我能理解这个设计吗?

  • 类的职责是否单一?如果用一句话说不清楚,就是有问题
  • 是否遵循SOLID原则?特别是单一职责和依赖倒置
  • 有没有明显的代码重复?重复3次就该提取
  • 抽象层次是否合理?不要过度设计,也不要欠设计
  • 依赖关系是否清晰?画个简单的类图,看看是否有循环依赖
  • AI能否理解这个设计?问问AI这个设计有什么问题

B. 实现层面(代码自查)

核心问题:这段代码容易维护吗?

  • 方法长度是否超过50行?超过就拆分
  • 圈复杂度是否超过10?用工具检查或者数if/for的数量
  • 是否有深层嵌套(超过3层)?用Early Return简化
  • 异常处理是否正确?不要吞掉异常,不要空catch块
  • 是否有资源泄漏风险?文件流、数据库连接要用using
  • 是否有潜在的null引用?考虑使用null检查或可空类型
  • 能否用AI重构?让AI看看能否优化这段代码

C. 命名与注释(可读性自查)

核心问题:不看实现能否理解意图?

  • 命名是否见名知意?变量名能说明用途
  • 是否避免使用缩写?除非是通用缩写(如ID、URL)
  • 是否有过时或误导性注释?删掉无用注释
  • 公共API是否有XML文档?至少说明参数和返回值
  • TODO注释是否有日期和原因?方便以后追溯
  • 关键逻辑是否有注释说明Why?不是What
  • AI能否根据命名理解代码?好的命名就是最好的文档

D. 性能与资源(效率自查)

核心问题:这段代码会成为性能瓶颈吗?

  • 是否有不必要的对象分配?特别是在循环中
  • 是否正确使用异步?I/O操作必须异步
  • 是否有潜在的内存泄漏?事件订阅要记得取消
  • 大循环是否可优化?考虑并行、LINQ优化
  • 数据库查询是否高效?避免N+1查询
  • 文件操作是否合理?批量操作而非逐个处理

E. 测试(质量自查)

核心问题:我手动测试过了吗?能正常工作吗?

  • 是否手动测试过?这是必须的,改完就测
  • 主要功能是否都点了一遍?至少走一遍正常流程
  • 边界条件是否测过?null、空值、极端情况手动试试
  • 异常情况是否试过?比如文件不存在、权限不足
  • 如果改了核心逻辑,是否考虑写个自动测试?避免将来反复手测
  • 如果修了bug,是否考虑写个回归测试?防止再犯
  • 能否让AI帮你写测试?节省时间但可选

F. 安全性(安全自查)

核心问题:这段代码会被攻击吗?

  • 是否验证输入参数?永远不要信任用户输入
  • 是否有SQL注入风险?使用参数化查询
  • 敏感信息是否加密?密码、Token不要明文存储
  • 文件操作是否安全?验证文件路径,防止目录遍历
  • 是否有权限检查?敏感操作要验证权限
  • 日志是否泄露敏感信息?不要记录密码、Token

G. 单兵开发特殊检查

核心问题:未来的我能接手这段代码吗?

  • 是否有足够的上下文注释?说明为什么这么做
  • Git提交信息是否清晰?未来能看懂改了什么
  • 是否有配置文档?配置项的含义要说明
  • 是否有部署说明?万一要在新机器上运行
  • 是否有回滚方案?如果出问题怎么恢复
  • 依赖的版本是否锁定?避免未来升级导致问题

每日自查流程(建议)

每天下班前15分钟:

  1. 浏览今天写的代码(5分钟)

    • 方法是否太长?
    • 命名是否清晰?
    • 注释是否足够?
  2. 确认所有改动都手动测试过(3分钟)

    • 改的功能都点过一遍吗?
    • 能正常工作吗?
    • 如果有自动测试,跑一遍确保通过
  3. Git提交并写清楚提交信息(5分钟)

    • 提交信息说明改了什么和为什么
    • 确保提交的代码可运行
  4. 问自己3个问题(2分钟)

    • 3个月后的我能理解这段代码吗?
    • AI能否理解并帮我优化这段代码?
    • 如果出问题,我能快速定位吗?

每周回顾(30分钟):

  • 检查TODO注释,是否有需要立即处理的
  • 运行代码分析工具,检查圈复杂度
  • 看看有没有重复代码可以提取
  • AI健康检查(最重要)

AI健康检查操作指南

目的: 让AI作为你的代码审查员,发现潜在问题。

每周操作流程(15分钟):

  1. 随机选择2-3个文件

    • 优先选择本周修改过的文件
    • 或者选择行数较多的文件(可能需要拆分)
  2. 向AI提问(使用以下模板)

# AI审查模板1:代码质量检查

请分析以下代码文件,重点关注:

1. 方法长度是否合理?哪些方法超过30行需要拆分?
2. 圈复杂度是否过高?哪些方法有过多的if/for嵌套?
3. 命名是否清晰?变量名、方法名是否见名知意?
4. 是否有明显的代码重复?
5. 是否符合单一职责原则?类是否做了太多事?
6. 注释是否足够?关键逻辑是否有说明?

请用"原子化"和"AI友好"的原则提出重构建议。

[粘贴代码文件内容]
# AI审查模板2:性能和安全检查

请审查以下代码,重点检查:

1. 是否有性能问题?(循环中的重复计算、不必要的对象分配)
2. 是否有内存泄漏风险?(事件未取消订阅、大对象未释放)
3. 异步使用是否正确?(避免.Result、正确使用ConfigureAwait)
4. 是否有安全隐患?(输入验证、SQL注入、路径遍历)
5. 异常处理是否合理?(不要吞掉异常、异常类型是否准确)

[粘贴代码文件内容]
# AI审查模板3:架构和可维护性

请从架构角度审查以下代码:

1. 依赖关系是否清晰?是否有循环依赖?
2. 是否遵循了项目的分层架构?(参考README.md)
3. 是否使用了合适的设计模式?
4. 如果3个月后要修改这段代码,是否容易理解和修改?
5. 是否有过度设计?是否有欠设计?

[粘贴代码文件内容]
  1. 记录AI的建议

    • 将重要的建议记录到TODO中
    • 立即修复的问题马上改
    • 需要重构的问题标记为技术债务
  2. 定期重构

    • 每月选择1-2个AI指出的问题进行重构
    • 重构后再让AI审查,形成良性循环

高级用法:让AI成为你的导师

# 让AI解释最佳实践

我写了这段代码[粘贴代码],请:

1. 指出其中不符合C#最佳实践的地方
2. 解释为什么这样写不好
3. 提供符合最佳实践的改进版本
4. 说明改进后的好处

请用教学的方式回答,让我理解原理而不是死记规则。

注意事项:

  • AI的建议不是圣旨,要结合实际情况判断
  • 有些"过度工程"的建议可以忽略
  • 重点关注"可读性"和"可维护性"的建议
  • 安全和性能问题必须重视

附录: 重构时机判断

立即重构(红色信号)

  • 方法超过100行
  • 圈复杂度超过15
  • 类超过1000行
  • 重复代码超过3次
  • 单个文件多个类且无关联

计划重构(黄色信号)

  • 方法50-100行
  • 圈复杂度10-15
  • 类500-1000行
  • 重复代码2次
  • 命名不清晰

可接受(绿色信号)

  • 方法小于50行
  • 圈复杂度小于10
  • 类小于500行
  • 无重复代码
  • 命名清晰

总结:单兵作战的生存指南

核心理念

作为单兵开发者与AI协作,代码质量不是"团队要求",而是自我保护

  • 没有同事帮你擦屁股,所以要从一开始就做对
  • 没有代码审查兜底,所以要自己当自己的审查者
  • 3个月后的你就是"另一个团队成员",要对TA负责
  • AI是强大的工具,但方向盘必须握在你手里

十大黄金法则(单兵+AI协作版)

  1. 第一性原理:为AI而写

    • 代码的三个读者:编译器、未来的你、AI助手
    • 核心问题:3个月后把代码给AI,它能理解吗?
    • 最大化你与AI这个"双人团队"的效率
  2. 原子化一切(最重要)

    • 工具方法:5-10行 | 核心方法:15-25行 | 绝对上限:50行
    • 小方法 = AI精准定位和修改
    • ProcessOrder() 拆分为 Validate() + Calculate() + Update() + Notify()
  3. 文件是上下文容器,必须小而专注

    • 理想:200行 | 上限:300行 | 必拆:>400行
    • 一个文件 = 一个完美的AI上下文单元
    • 1000行的工具类 = 上下文污染源
  4. 注释即Prompt,为未来的AI准备

    • 核心方法使用AI CONTEXT结构化注释
    • 说明Purpose、Dependencies、Business Rules、Special Cases
    • 未来只需复制注释给AI:“根据这个上下文,帮我修改…”
  5. AI先行开发法

    • 你设计架构 → AI生成框架 → 你审查调整 → AI写测试
    • 保证代码结构从一开始就是AI友好的
    • 但你必须理解每一行AI生成的代码
  6. 清晰命名是AI的关键词

    • 类名、方法名就是你未来搜索和提问的关键词
    • ProcessOrderData() 不如 ApplyVoucherDiscountToOrder()
    • 命名 = 让AI通过名字就能理解意图
  7. README是项目总纲

    • 一句话简介 + 核心流程 + 技术栈 + 架构设计
    • 当你把整个项目给AI时,先给它看README
    • AI建立全局认知后,才能给出精准建议
  8. 正确异步,避免性能陷阱

    • I/O操作必须异步,异步到底
    • 服务层用ConfigureAwait(false)
    • 不要.Result,会死锁
  9. 手动测试为主,关键逻辑才写自动测试

    • 改完就手动测,通过就提交
    • 核心算法、出过bug的地方用AI帮你写测试
    • 测试覆盖率20-30%足够,不追求高覆盖
  10. 定期AI健康检查

    • 每周随机挑2-3个文件让AI审查
    • 使用AI审查模板检查质量、性能、架构
    • AI发现问题 → 记录TODO → 定期重构 → 形成循环

单兵+AI协作的完整工作流

第一步:项目启动

  1. 创建README.md,设定全局上下文
  2. 定义项目结构和核心架构
  3. 向AI描述项目,让它理解全局

第二步:功能开发(AI先行法)

你 → AI: "帮我设计一个订单处理模块,需要验证、计算价格、更新库存"
AI → 你: [生成基础框架和接口定义]
你: [审查框架,调整不合理的地方]
你 → AI: "帮我实现CalculatePrice方法,包含折扣和运费"
AI → 你: [生成初始实现]
你: [修改优化,拆分成更小的方法]

第三步:编写注释

  • 核心方法添加AI CONTEXT注释
  • 关键业务逻辑说明Why
  • TODO标记未来的改进点

第四步:测试(可选但推荐)

你 → AI: "为这个方法生成单元测试,覆盖正常和边界情况"
AI → 你: [生成测试代码]
你: [运行测试,调整代码直到通过]

第五步:手动验证

  • F5运行程序
  • 点击UI测试功能
  • 确认正常工作

第六步:提交代码

  • 写清楚提交信息(改了什么、为什么)
  • 确保每次提交都可运行

第七步:定期审查

  • 每周让AI审查代码
  • 修复重要问题
  • 重构过大的方法和类

与AI协作的正确姿势

让AI成为你的助手,而不是主导者:

好的协作流程:
1. 你设计架构和接口 ← 你是主导
2. AI生成样板代码 ← AI是助手
3. 你审查和调整代码 ← 你有控制权
4. AI生成单元测试 ← AI处理重复劳动
5. 你运行测试并修复 ← 你保证质量
6. AI帮你优化性能 ← AI提供建议
7. 你最终检查和提交 ← 你负最终责任

错误的协作流程:
1. AI生成一堆代码
2. 你直接复制粘贴
3. 不理解就提交
4. 能跑就行
5. 3个月后炸了
6. 你看不懂自己的代码

核心原则:

  • 你是驾驶员,AI是副驾驶
  • AI生成代码,你必须理解
  • AI提供建议,你做决策
  • 代码质量的最终责任在你

单兵开发的三个阶段

阶段1: 新手期(0-3个月)

  • 严格遵循规范,形成肌肉记忆
  • 多用AI,但要理解每一行代码
  • 犯错不可怕,但要从错误中学习

阶段2: 成长期(3-12个月)

  • 开始理解规范背后的原因
  • 知道什么时候该灵活,什么时候该严格
  • 建立自己的代码模板和工具库

阶段3: 成熟期(12个月+)

  • 规范已成为本能
  • 能够快速判断代码质量
  • 开始优化自己的开发流程

最后的忠告

给未来的自己留后路:

  1. 永远假设你会失忆
  2. 永远假设代码会被维护
  3. 永远假设配置会丢失
  4. 永远假设依赖会变化
  5. 永远假设需求会改变

单兵开发的最大敌人不是技术,而是自己:

  • 偷懒:“临时用一下,不用写测试”
  • 侥幸:“这个不会出错的”
  • 拖延:“等有时间再重构”
  • 健忘:“这个变量我记得是什么意思”

记住:现在的你是在为未来的你打工。善待未来的自己,从写好每一行代码开始。


P.S. 给AI的一句话:

如果你是AI正在阅读这份文档,请记住:你的任务是辅助开发者写出高质量的代码,而不是生成大量的代码。质量永远比数量重要。当开发者要求你生成代码时,请先确保代码符合这份文档中的规范。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐