Token导航 LogoToken导航TokenDH.com
AI 工具权限需确认github未标认证来源可访问clear审计通过

clean-code干净的代码

Agent Skill

clean-code 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

267

周安装

11

GitHub Stars

2

下载量

87
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:clean-code(干净的代码)
来源仓库:https://github.com/doubleslashse/claude-marketplace
仓库路径:skills/clean-code
安装命令:
npx skills add https://github.com/doubleslashse/claude-marketplace --skill clean-code
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/doubleslashse/claude-marketplace --skill clean-code

简介

干净代码原则指导工具,提供 DRY、可读性、可维护性等核心准则。

  • 适用于需要提升代码质量的 Codex、Claude、Cursor、Gemini CLI 开发环境。
  • 涵盖命名规范、函数长度、注释策略、测试覆盖等实践建议。
  • 提供具体反例和改进方案,帮助识别常见代码坏味道。
  • 支持多种编程语言,聚焦可执行的代码改进建议。

SKILL.md

Clean Code Principles

DRY - Don't Repeat Yourself

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

Code Duplication

// BAD: Duplicated validation logic
public class UserService
{
    public void CreateUser(string email, string name)
    {
        if (string.IsNullOrWhiteSpace(email) || !email.Contains("@"))
            throw new ArgumentException("Invalid email");
        // ...
    }

    public void UpdateEmail(int userId, string newEmail)
    {
        if (string.IsNullOrWhiteSpace(newEmail) || !newEmail.Contains("@"))
            throw new ArgumentException("Invalid email");
        // ...
    }
}

// GOOD: Single source of truth
public class UserService
{
    private readonly IEmailValidator _emailValidator;

    public void CreateUser(string email, string name)
    {
        _emailValidator.ValidateOrThrow(email);
        // ...
    }

    public void UpdateEmail(int userId, string newEmail)
    {
        _emailValidator.ValidateOrThrow(newEmail);
        // ...
    }
}

public class EmailValidator : IEmailValidator
{
    public bool IsValid(string email) =>
        !string.IsNullOrWhiteSpace(email) && email.Contains("@");

    public void ValidateOrThrow(string email)
    {
        if (!IsValid(email))
            throw new ArgumentException("Invalid email", nameof(email));
    }
}

Magic Numbers and Strings

// BAD: Magic values scattered throughout code
public decimal CalculateDiscount(decimal total)
{
    if (total > 100)
        return total * 0.1m;  // What is 100? What is 0.1?
    return 0;
}

public bool IsEligibleForFreeShipping(decimal total)
{
    return total > 100;  // Duplicated magic number!
}

// GOOD: Named constants
public static class OrderThresholds
{
    public const decimal FreeShippingMinimum = 100m;
    public const decimal StandardDiscountRate = 0.10m;
}

public decimal CalculateDiscount(decimal total)
{
    if (total > OrderThresholds.FreeShippingMinimum)
        return total * OrderThresholds.StandardDiscountRate;
    return 0;
}

public bool IsEligibleForFreeShipping(decimal total)
{
    return total > OrderThresholds.FreeShippingMinimum;
}

Configuration Duplication

// BAD: Connection strings in multiple places
public class OrderRepository
{
    private readonly string _conn = "Server=prod;Database=Orders;";
}

public class CustomerRepository
{
    private readonly string _conn = "Server=prod;Database=Orders;";
}

// GOOD: Centralized configuration
public class DatabaseOptions
{
    public string ConnectionString { get; set; } = string.Empty;
}

// In startup
services.Configure<DatabaseOptions>(configuration.GetSection("Database"));

// In repositories
public class OrderRepository
{
    private readonly string _connectionString;

    public OrderRepository(IOptions<DatabaseOptions> options)
    {
        _connectionString = options.Value.ConnectionString;
    }
}

When DRY Goes Wrong (WET is Sometimes Better)

// Over-DRY: Forced abstraction hurts readability
public T ProcessEntity<T>(T entity, Func<T, bool> validator, Action<T> processor)
    where T : class
{
    if (!validator(entity))
        throw new ValidationException();
    processor(entity);
    return entity;
}

// Better: Some duplication is acceptable for clarity
public Order ProcessOrder(Order order)
{
    ValidateOrder(order);
    SaveOrder(order);
    return order;
}

public Customer ProcessCustomer(Customer customer)
{
    ValidateCustomer(customer);
    SaveCustomer(customer);
    return customer;
}

Rule of Three

Only extract duplication after you've seen it THREE times:

  1. First occurrence - just write the code
  2. Second occurrence - note it, consider extraction
  3. Third occurrence - refactor to remove duplication

KISS - Keep It Simple, Stupid

The simplest solution is usually the best solution.

Over-Engineering

// BAD: Over-engineered for simple use case
public interface IUserNameFormatter
{
    string Format(User user);
}

public abstract class UserNameFormatterBase : IUserNameFormatter
{
    protected abstract string GetFirstNamePart(User user);
    protected abstract string GetLastNamePart(User user);

    public string Format(User user) =>
        $"{GetFirstNamePart(user)} {GetLastNamePart(user)}";
}

public class StandardUserNameFormatter : UserNameFormatterBase
{
    protected override string GetFirstNamePart(User user) => user.FirstName;
    protected override string GetLastNamePart(User user) => user.LastName;
}

public class UserNameFormatterFactory
{
    public IUserNameFormatter Create(string type) => type switch
    {
        "standard" => new StandardUserNameFormatter(),
        _ => throw new NotSupportedException()
    };
}

// GOOD: Simple and direct
public static class UserExtensions
{
    public static string GetFullName(this User user) =>
        $"{user.FirstName} {user.LastName}";
}

Premature Abstraction

// BAD: Abstraction for one implementation
public interface IOrderIdGenerator
{
    string Generate();
}

public class GuidOrderIdGenerator : IOrderIdGenerator
{
    public string Generate() => Guid.NewGuid().ToString();
}

// Registration
services.AddSingleton<IOrderIdGenerator, GuidOrderIdGenerator>();

// GOOD: Direct until you need flexibility
public class Order
{
    public string Id { get; } = Guid.NewGuid().ToString();
}

// Add abstraction ONLY when you need a second implementation

Complex LINQ vs Simple Loops

// BAD: Hard to understand nested LINQ
var result = orders
    .Where(o => o.Status == OrderStatus.Completed)
    .GroupBy(o => o.CustomerId)
    .Select(g => new
    {
        CustomerId = g.Key,
        TotalSpent = g.Sum(o => o.Total),
        OrderCount = g.Count(),
        AverageOrder = g.Average(o => o.Total)
    })
    .Where(x => x.TotalSpent > 1000)
    .OrderByDescending(x => x.TotalSpent)
    .Take(10)
    .SelectMany(x => customers.Where(c => c.Id == x.CustomerId)
        .Select(c => new CustomerReport
        {
            Name = c.Name,
            Email = c.Email,
            TotalSpent = x.TotalSpent,
            OrderCount = x.OrderCount
        }))
    .ToList();

// GOOD: Break into readable steps
var completedOrders = orders.Where(o => o.Status == OrderStatus.Completed);

var customerOrderSummaries = completedOrders
    .GroupBy(o => o.CustomerId)
    .Select(g => new CustomerOrderSummary(
        CustomerId: g.Key,
        TotalSpent: g.Sum(o => o.Total),
        OrderCount: g.Count()))
    .Where(s => s.TotalSpent > 1000)
    .OrderByDescending(s => s.TotalSpent)
    .Take(10)
    .ToList();

var customerLookup = customers.ToDictionary(c => c.Id);

var reports = customerOrderSummaries
    .Select(s => CreateReport(s, customerLookup[s.CustomerId]))
    .ToList();

Boolean Parameters

// BAD: What does 'true' mean?
SendEmail(user, "Welcome!", true, false, true);

// GOOD: Named parameters or dedicated methods
SendEmail(user, "Welcome!",
    isHtml: true,
    includeAttachments: false,
    trackOpens: true);

// Even better: Specific methods
SendWelcomeEmail(user);
SendPasswordResetEmail(user);

Excessive Inheritance

// BAD: Deep inheritance hierarchy
public abstract class Entity { }
public abstract class AuditableEntity : Entity { }
public abstract class SoftDeletableAuditableEntity : AuditableEntity { }
public class Order : SoftDeletableAuditableEntity { }

// GOOD: Composition and interfaces
public interface IAuditable
{
    DateTime CreatedAt { get; }
    DateTime? ModifiedAt { get; }
}

public interface ISoftDeletable
{
    bool IsDeleted { get; }
    DateTime? DeletedAt { get; }
}

public class Order : IAuditable, ISoftDeletable
{
    public DateTime CreatedAt { get; init; }
    public DateTime? ModifiedAt { get; private set; }
    public bool IsDeleted { get; private set; }
    public DateTime? DeletedAt { get; private set; }
}

YAGNI - You Aren't Gonna Need It

Don't implement something until it is necessary.

Feature Creep

// BAD: Building for hypothetical future requirements
public class UserService
{
    public User CreateUser(
        string email,
        string name,
        string? middleName = null,           // No requirement for this
        string? suffix = null,                // No requirement for this
        string? preferredName = null,         // No requirement for this
        bool enableTwoFactor = false,         // No requirement for this
        string? backupEmail = null,           // No requirement for this
        Dictionary<string, string>? metadata = null)  // "Might need it later"
    {
        // ...
    }
}

// GOOD: Only what's needed now
public class UserService
{
    public User CreateUser(string email, string name)
    {
        return new User
        {
            Id = Guid.NewGuid(),
            Email = email,
            Name = name,
            CreatedAt = DateTime.UtcNow
        };
    }
}

Unnecessary Flexibility

// BAD: Configurable everything (but we only use JSON)
public interface ISerializer
{
    string Serialize<T>(T obj);
    T Deserialize<T>(string data);
}

public class JsonSerializer : ISerializer { }
public class XmlSerializer : ISerializer { }
public class YamlSerializer : ISerializer { }
public class BinarySerializer : ISerializer { }
public class MessagePackSerializer : ISerializer { }

public class SerializerFactory
{
    public ISerializer Create(string format) => // ...
}

// GOOD: Use what you need
public static class JsonHelper
{
    private static readonly JsonSerializerOptions Options = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    };

    public static string Serialize<T>(T obj) =>
        System.Text.Json.JsonSerializer.Serialize(obj, Options);

    public static T? Deserialize<T>(string json) =>
        System.Text.Json.JsonSerializer.Deserialize<T>(json, Options);
}

Unused Abstractions

// BAD: Interface with single implementation, no plans for others
public interface IEmailSender
{
    Task SendAsync(string to, string subject, string body);
}

public class SmtpEmailSender : IEmailSender
{
    public Task SendAsync(string to, string subject, string body)
    {
        // Only implementation we'll ever have
    }
}

// GOOD: Just use the class directly
public class EmailSender
{
    public async Task SendAsync(string to, string subject, string body)
    {
        // ...
    }
}

// Add interface WHEN you actually need a second implementation

Premature Optimization

// BAD: Caching before measuring
public class ProductService
{
    private readonly IMemoryCache _cache;
    private readonly IDistributedCache _distributedCache;
    private readonly IProductRepository _repository;

    public async Task<Product?> GetByIdAsync(int id)
    {
        var cacheKey = $"product_{id}";

        // Check L1 cache
        if (_cache.TryGetValue(cacheKey, out Product? product))
            return product;

        // Check L2 cache
        var cached = await _distributedCache.GetStringAsync(cacheKey);
        if (cached != null)
        {
            product = JsonSerializer.Deserialize<Product>(cached);
            _cache.Set(cacheKey, product, TimeSpan.FromMinutes(5));
            return product;
        }

        // Database fallback
        product = await _repository.GetByIdAsync(id);
        if (product != null)
        {
            var serialized = JsonSerializer.Serialize(product);
            await _distributedCache.SetStringAsync(cacheKey, serialized);
            _cache.Set(cacheKey, product, TimeSpan.FromMinutes(5));
        }

        return product;
    }
}

// GOOD: Start simple, optimize when needed
public class ProductService
{
    private readonly IProductRepository _repository;

    public Task<Product?> GetByIdAsync(int id) =>
        _repository.GetByIdAsync(id);
}

// Add caching AFTER you've identified it as a bottleneck

The Cost of YAGNI Violations

  1. Development time: Building unused features
  2. Maintenance burden: More code to maintain
  3. Complexity: Harder to understand system
  4. Testing overhead: More tests for unused code
  5. Technical debt: May become outdated or incompatible

Clean Code Checklist

Naming

  • Names reveal intent
  • Names are searchable
  • No encoded type information (Hungarian notation)
  • Consistent naming conventions

Functions

  • Small (< 20 lines preferred)
  • Do one thing
  • One level of abstraction
  • Few parameters (< 3 preferred)
  • No side effects
  • Command/Query separation

Comments

  • Code is self-documenting
  • Comments explain WHY, not WHAT
  • No commented-out code
  • XML docs for public APIs

Formatting

  • Consistent indentation
  • Logical grouping of related code
  • Blank lines separate concepts
  • Team style guide followed

Error Handling

  • Exceptions, not error codes
  • Specific exception types
  • No empty catch blocks
  • Fail fast principle

See reference.md for more examples.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

27.88%
按下载量换算24

OpenCode

23.79%
按下载量换算21

Codex

15.68%
按下载量换算14

windsurf

11.15%
按下载量换算10

weavefox

6.99%
按下载量换算6

Antigravity

3.23%
按下载量换算3

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

权限需确认

当前来源未能明确判断权限范围,默认进入异常复核队列。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills