원클릭으로
coding-standards
Universal coding standards, best practices, and patterns for C#, ASP.NET Core, and Entity Framework Core development.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Universal coding standards, best practices, and patterns for C#, ASP.NET Core, and Entity Framework Core development.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Automatically extract reusable patterns from coding sessions and save them as learned skills for future use.
Instinct-based learning system that observes sessions via hooks, creates atomic instincts with confidence scoring, and evolves them into skills/commands/agents.
Pattern for progressively refining context retrieval to solve the subagent context problem in multi-agent workflows.
Suggests manual context compaction at logical intervals to preserve context through task phases rather than arbitrary auto-compaction.
Formal evaluation framework for coding sessions implementing eval-driven development (EDD) principles.
Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
| name | coding-standards |
| description | Universal coding standards, best practices, and patterns for C#, ASP.NET Core, and Entity Framework Core development. |
Universal coding standards applicable across all projects in this .NET solution.
// ✅ GOOD: Descriptive names following .NET conventions
public string LastName { get; set; }
private readonly IStudentRepository _studentRepository;
const int MaxEnrollmentsPerStudent = 8;
// ❌ BAD: Unclear or non-standard names
public string ln { get; set; }
private readonly IStudentRepository repo;
const int x = 8;
// ✅ GOOD: Verb-noun pattern, PascalCase
public async Task<Student> GetStudentByIdAsync(int id) { }
public bool IsValidEnrollmentDate(DateTime date) { }
public IEnumerable<Course> FilterByDepartment(int departmentId) { }
// ❌ BAD: Unclear or noun-only
public async Task<Student> Student(int id) { }
public bool Date(DateTime d) { }
// ✅ GOOD: Use records for immutable DTOs
public record StudentDto(string LastName, string FirstMidName, DateTime EnrollmentDate);
// ✅ GOOD: Use init-only setters
public class CreateStudentCommand
{
public string LastName { get; init; } = default!;
public string FirstMidName { get; init; } = default!;
public DateTime EnrollmentDate { get; init; }
}
// ❌ BAD: Mutable DTOs with public setters
public class StudentDto
{
public string LastName { get; set; } // MUTATION
}
// ✅ GOOD: Comprehensive error handling with context
public async Task<Student> GetStudentByIdAsync(int id)
{
try
{
var student = await _context.Students
.Include(s => s.Enrollments)
.FirstOrDefaultAsync(s => s.Id == id);
if (student is null)
{
throw new NotFoundException($"Student with ID {id} was not found.");
}
return student;
}
catch (Exception ex) when (ex is not NotFoundException)
{
_logger.LogError(ex, "Failed to retrieve student {StudentId}", id);
throw new DataAccessException("Unable to retrieve student.", ex);
}
}
// ❌ BAD: No error handling
public async Task<Student> GetStudentByIdAsync(int id)
{
return await _context.Students.FindAsync(id);
}
// ✅ GOOD: Parallel execution when possible
var studentsTask = _studentRepository.GetAllAsync();
var coursesTask = _courseRepository.GetAllAsync();
var departmentsTask = _departmentRepository.GetAllAsync();
await Task.WhenAll(studentsTask, coursesTask, departmentsTask);
var students = await studentsTask;
var courses = await coursesTask;
var departments = await departmentsTask;
// ❌ BAD: Sequential when unnecessary
var students = await _studentRepository.GetAllAsync();
var courses = await _courseRepository.GetAllAsync();
var departments = await _departmentRepository.GetAllAsync();
// ✅ GOOD: Strong typing with enums and value objects
public enum Grade { A, B, C, D, F }
public class Enrollment
{
public int StudentId { get; init; }
public int CourseId { get; init; }
public Grade? Grade { get; set; }
}
// ❌ BAD: Stringly typed or object
public class Enrollment
{
public object Grade { get; set; } // No type safety
}
// ✅ GOOD: Thin controller, logic in services
[ApiController]
[Route("api/[controller]")]
public class StudentsController : ControllerBase
{
private readonly IStudentService _studentService;
public StudentsController(IStudentService studentService)
{
_studentService = studentService;
}
[HttpGet("{id}")]
public async Task<ActionResult<StudentDto>> GetById(int id)
{
var student = await _studentService.GetByIdAsync(id);
if (student is null) return NotFound();
return Ok(student);
}
}
// ❌ BAD: Fat controller with business logic inline
[HttpGet("{id}")]
public async Task<ActionResult> GetById(int id)
{
var student = await _context.Students.FindAsync(id);
// 50 lines of business logic here...
}
// ✅ GOOD: Constructor injection with interfaces
public class StudentService : IStudentService
{
private readonly IStudentRepository _repository;
private readonly ILogger<StudentService> _logger;
public StudentService(
IStudentRepository repository,
ILogger<StudentService> logger)
{
_repository = repository;
_logger = logger;
}
}
// Registration in Program.cs
builder.Services.AddScoped<IStudentRepository, StudentRepository>();
builder.Services.AddScoped<IStudentService, StudentService>();
using System.ComponentModel.DataAnnotations;
// ✅ GOOD: Data annotation validation
public class CreateStudentDto
{
[Required]
[StringLength(50, MinimumLength = 1)]
public string LastName { get; init; } = default!;
[Required]
[StringLength(50, MinimumLength = 1)]
public string FirstMidName { get; init; } = default!;
[DataType(DataType.Date)]
public DateTime EnrollmentDate { get; init; }
}
// In controller — model binding validates automatically
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("LastName,FirstMidName,EnrollmentDate")] CreateStudentDto dto)
{
if (!ModelState.IsValid) return View(dto);
// proceed
}
// ✅ GOOD: Select only needed columns, use AsNoTracking for reads
var students = await _context.Students
.AsNoTracking()
.Where(s => s.EnrollmentDate >= startDate)
.Select(s => new StudentDto(s.LastName, s.FirstMidName, s.EnrollmentDate))
.ToListAsync();
// ❌ BAD: Load everything
var students = await _context.Students.ToListAsync();
// ✅ GOOD: Explicit includes
var student = await _context.Students
.Include(s => s.Enrollments)
.ThenInclude(e => e.Course)
.FirstOrDefaultAsync(s => s.Id == id);
// ❌ BAD: Relying on lazy loading (performance trap)
var student = await _context.Students.FindAsync(id);
var enrollments = student.Enrollments; // N+1 query
ContosoUniversity.sln
├── ContosoUniversity.Core/ # Domain layer
│ ├── Entities/ # Domain entities
│ └── Interfaces/ # Repository interfaces
├── ContosoUniversity.Infrastructure/ # Data access layer
│ ├── Data/ # DbContext, migrations
│ └── Repositories/ # Repository implementations
├── ContosoUniversity.Web/ # Presentation layer
│ ├── Controllers/ # MVC controllers
│ ├── Models/ # View models & DTOs
│ └── Views/ # Razor views
├── ContosoUniversity.Tests/ # Unit & integration tests
└── ContosoUniversity.PlaywrightTests/ # E2E tests
Entities/Student.cs # PascalCase, singular nouns
Controllers/StudentsController.cs # PascalCase, plural + Controller suffix
Interfaces/IStudentRepository.cs # PascalCase, I prefix for interfaces
Models/StudentDto.cs # PascalCase with Dto suffix
// ✅ GOOD: Explain WHY, not WHAT
// Use exponential backoff to avoid overwhelming the external API during outages
var delay = Math.Min(1000 * Math.Pow(2, retryCount), 30000);
// Deliberately bypassing change tracking for bulk read performance
var results = await _context.Students.AsNoTracking().ToListAsync();
// ❌ BAD: Stating the obvious
// Increment counter by 1
count++;
// Set name to student's name
name = student.LastName;
/// <summary>
/// Retrieves a student by their unique identifier, including enrollment data.
/// </summary>
/// <param name="id">The student's unique identifier.</param>
/// <returns>The student with enrollments, or null if not found.</returns>
/// <exception cref="DataAccessException">Thrown when the database is unavailable.</exception>
public async Task<Student?> GetStudentByIdAsync(int id)
{
// Implementation
}
// ✅ GOOD: Use IMemoryCache for frequently accessed data
public async Task<IEnumerable<Department>> GetDepartmentsAsync()
{
return await _cache.GetOrCreateAsync("departments", async entry =>
{
entry.SlidingExpiration = TimeSpan.FromMinutes(10);
return await _context.Departments.AsNoTracking().ToListAsync();
});
}
// ✅ GOOD: Always paginate large result sets
public async Task<PaginatedList<Student>> GetStudentsAsync(int pageIndex, int pageSize)
{
return await PaginatedList<Student>.CreateAsync(
_context.Students.AsNoTracking().OrderBy(s => s.LastName),
pageIndex,
pageSize);
}
[Fact]
public async Task GetStudentById_ExistingId_ReturnsStudent()
{
// Arrange
var expectedStudent = new Student { Id = 1, LastName = "Smith" };
_mockRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(expectedStudent);
// Act
var result = await _service.GetStudentByIdAsync(1);
// Assert
Assert.NotNull(result);
Assert.Equal("Smith", result.LastName);
}
// ✅ GOOD: MethodName_Condition_ExpectedResult pattern
[Fact] public async Task GetById_NonExistentId_ReturnsNotFound() { }
[Fact] public void Enroll_ExceedsMaxCredits_ThrowsException() { }
[Fact] public async Task Create_ValidStudent_ReturnsCreatedResult() { }
// ❌ BAD: Vague test names
[Fact] public void Works() { }
[Fact] public void TestStudent() { }
Watch for these anti-patterns:
// ❌ BAD: Method > 50 lines
public async Task ProcessEnrollment() { /* 100 lines */ }
// ✅ GOOD: Split into smaller methods
public async Task ProcessEnrollment()
{
var validated = await ValidateEnrollment();
var transformed = MapToEntity(validated);
await SaveEnrollment(transformed);
}
// ❌ BAD: 5+ levels of nesting
if (student != null)
{
if (student.IsActive)
{
if (course != null)
{
if (course.HasCapacity)
{
// Do something
}
}
}
}
// ✅ GOOD: Early returns (guard clauses)
if (student is null) return;
if (!student.IsActive) return;
if (course is null) return;
if (!course.HasCapacity) return;
// Do something
// ❌ BAD: Unexplained numbers
if (credits > 18) { }
// ✅ GOOD: Named constants
private const int MaxCreditsPerSemester = 18;
if (credits > MaxCreditsPerSemester) { }
Remember: Code quality is not negotiable. Clear, maintainable code enables rapid development and confident refactoring.