ワンクリックで
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.