Communitygithub.com

GuerthCastro/claude-skills-dotnet

Convenciones de codificación y pruebas .NET empaquetadas como Skills de Agente: estilo C#, patrones de prueba, revisión de SOLID y Clean Architecture, y referencia de características de C# 14 / .NET 10. Funciona con Claude Code, aplicaciones Claude y cualquier herramienta que lea SKILL.md. MIT.

¿Qué es claude-skills-dotnet?

Este skill de agente proporciona un marco estructurado para realizar revisiones de código basadas en los principios SOLID y Clean Architecture, específicamente orientado a proyectos .NET (C#). Es útil para desarrolladores que usan Claude Code, Claude Desktop u otras herramientas compatibles con SKILL.md, ya que automatiza la evaluación de código siguiendo una metodología rigurosa. El skill guía al agente a través de un proceso paso a paso: identificar el lenguaje y la capa, evaluar cada uno de los cinco principios SOLID de forma independiente, generar un informe estructurado con estado (PASS/VIOLATION) y severidad (Critical, Major, Minor), y proporcionar versiones refactorizadas concretas para violaciones críticas o mayores. Además, incluye detección de violaciones de capas en Clean Architecture, como dependencias inversas o fuga de responsabilidades de infraestructura en la capa de aplicación. Está diseñado para trabajar sin problemas con herramientas que ejecutan SKILL.md, ofreciendo una revisión consistente y reproducible.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add GuerthCastro/claude-skills-dotnet

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Revisión SOLID

Autor: Guerth Castro (github.com/GuerthCastro). Licenciado bajo MIT.

Proceso de revisión

Cuando se proporciona código para revisión:

  1. Identificar el lenguaje y la capa (entidad de dominio C#, manejador de aplicación, servicio Angular, componente React, etc.).
  2. Evaluar cada uno de los cinco principios de forma independiente.
  3. Producir un informe estructurado usando el formato a continuación.
  4. Clasificar las violaciones por severidad: Crítico (rompe la arquitectura) sobre Mayor (degrada la mantenibilidad) sobre Menor (preferencia de estilo).
  5. Proporcionar una versión refactorizada concreta para cada violación Crítica o Mayor.

No añadir relleno al informe. Si un principio se cumple genuinamente, indicar PASS y continuar.

Los cinco principios

S: Principio de Responsabilidad Única

Una clase, una razón para cambiar.

Violaciones a buscar:

  • Una clase realiza acceso a datos y lógica de negocio.
  • Un servicio envía correos, valida datos y escribe en la base de datos.
  • Un componente obtiene datos, los formatea y gestiona el estado de la UI.
  • Un manejador orquesta varias operaciones no relacionadas.
  • Clases "dios" con diez o más métodos que abarcan múltiples dominios.

VIOLACIÓN. OrderService valida, persiste y notifica. La llamada de notificación es la que no pertenece.

public class OrderService(IOrderRepository repository, IEmailService email)
{
    public async Task<bool> AddItem(long orderId, long productId)
    {
        Order order = await repository.GetById(orderId);
        if (order.ItemCount >= order.MaxItems)
        {
            return false;
        }

        await repository.AddItem(orderId, productId);

        await email.SendOrderUpdated(orderId);
        return true;
    }
}

Solución: extraer un servicio de notificación y dejar que el manejador coordine las dos llamadas.

O: Principio Abierto/Cerrado

Abierto para extensión, cerrado para modificación.

Violaciones a buscar:

  • Cadenas de if/else if o bloques switch sobre cadenas de tipo o enumeraciones que crecen con cada funcionalidad.
  • Agregar un nuevo tipo de informe requiere editar el servicio de informes existente.
  • Agregar un nuevo método de pago requiere editar el manejador de pago.
  • Dependencias concretas donde corresponde una abstracción.

VIOLACIÓN. Un nuevo formato de exportación significa editar este método.

public byte[] ExportInvoice(string format, IEnumerable<InvoiceLine> lines)
{
    if (format == "pdf")
    {
        return GeneratePdf(lines);
    }

    if (format == "excel")
    {
        return GenerateExcel(lines);
    }

    throw new NotSupportedException(format);
}

Solución: una abstracción IInvoiceExporter con implementaciones PdfInvoiceExporter y ExcelInvoiceExporter, resueltas por clave desde el contenedor.

L: Principio de Sustitución de Liskov

Los subtipos deben ser sustituibles por sus tipos base.

Violaciones a buscar:

  • Una clase derivada lanza NotImplementedException para un miembro heredado.
  • Una anulación cambia el comportamiento esperado: un no-op silencioso, una forma de retorno diferente, un nuevo tipo de excepción.
  • Una interfaz declara miembros que algunas implementaciones no pueden implementar de manera significativa.
  • Conversión a un tipo concreto para alcanzar comportamiento: if (repository is SqlOrderRepository sql).

I: Principio de Segregación de Interfaces

Ninguna clase debe ser forzada a implementar miembros que no usa.

Violaciones a buscar:

  • Interfaces gruesas con quince o más miembros donde las implementaciones usan tres.
  • Un IRepository<T> genérico que fuerza GetAll, GetById, Create, Update, Delete, Paginate, Search y BulkInsert en cada entidad.
  • Una interfaz de servicio que mezcla lecturas y escrituras cuando los consumidores solo necesitan un lado.

VIOLACIÓN. Un consumidor de solo lectura de informes se ve forzado a ver Crear, Actualizar y Eliminar.

public interface IOrderRepository
{
    Task<Order> GetById(long id);
    Task<IEnumerable<Order>> GetAll();
    Task Create(Order order);
    Task Update(Order order);
    Task Delete(long id);
}

Solución: dividir en IOrderReader e IOrderWriter. Componerlos donde ambos sean necesarios.

D: Principio de Inversión de Dependencias

Depender de abstracciones, no de concreciones.

Violaciones a buscar:

  • new instanciando un servicio o repositorio dentro de la lógica de negocio.
  • Una dependencia directa en SqlConnection o NpgsqlConnection dentro de un servicio.
  • La capa de Aplicación importando tipos de Infraestructura.
  • Clases de servicio estáticas que mantienen estado mutable.

VIOLACIÓN. El manejador construye su propio repositorio concreto y conexión.

public class GetOrderHandler
{
    public async Task<OrderDto> Handle(long id)
    {
        OrderRepository repository = new(new SqlConnection("..."));
        Order order = await repository.GetById(id);
        return order.MapToDto();
    }
}

Solución: inyectar IOrderRepository a través del constructor primario y registrarlo en el contenedor en la raíz de composición.

Formato del informe

Producir esta estructura para cada revisión:

## Revisión SOLID: [NombreClase o nombre de archivo]
**Idioma/Capa:** Manejador de Aplicación C#, Servicio Angular, etc.

### S: Responsabilidad Única
Estado: PASS / VIOLACIÓN (Crítico, Mayor, Menor)
Hallazgo: [lo que la clase hace más allá de su responsabilidad única]
Solución: [acción concreta]

### O: Abierto/Cerrado
Estado: PASS / VIOLACIÓN
Hallazgo: ...
Solución: ...

### L: Sustitución de Liskov
Estado: PASS / VIOLACIÓN / N/A (sin herencia)
Hallazgo: ...

### I: Segregación de Interfaces
Estado: PASS / VIOLACIÓN / N/A (sin interfaces)
Hallazgo: ...

### D: Inversión de Dependencias
Estado: PASS / VIOLACIÓN
Hallazgo: ...
Solución: ...

### Violaciones prioritarias
1. [Crítico] DIP: el manejador instancia un repositorio concreto
2. [Mayor] SRP: el servicio también envía el correo de notificación

### Versión refactorizada
[bloque de código completo corregido]

Violaciones de capas de Clean Architecture

Más allá de SOLID, marcar estos problemas transversales:

  • Una entidad de Dominio importa tipos de Aplicación o Infraestructura (violación de dirección de dependencia).
  • Un controlador contiene lógica de negocio que pertenece a un manejador.
  • Un repositorio devuelve DTOs en lugar de entidades de dominio. El mapeo pertenece a Aplicación.
  • Infraestructura llama a una API externa directamente en lugar de implementar una interfaz declarada en Aplicación o Dominio.
  • Un manejador toca HttpContext, filtrando una preocupación de infraestructura en la capa de aplicación.
  • Un registro de DI en el ensamblado incorrecto, por lo que una capa tiene que hacer referencia hacia abajo para compilar.

Skills relacionados