Skip to content

Commit 08a7874

Browse files
CopilotKSemenenko
andauthored
Add comprehensive GitHub Copilot instructions following ASP.NET Core best practices (#43)
* Initial plan * Initial repository exploration and validation completed Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com> * Add comprehensive .github/copilot-instructions.md with validated commands and scenarios Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com> * Clean up copilot-instructions.md and remove unnecessary files Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com> * Remove dotnet installation instructions and focus on important project information Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com> * Add comprehensive best practices, code style, and Copilot instructions Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com> * Improve copilot-instructions.md based on ASP.NET Core best practices Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com> * Simplify build commands to basic dotnet build and dotnet test Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com> * Improve copilot-instructions.md for better project consistency Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com> * Fix test example to match actual project code style Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com>
1 parent f77541d commit 08a7874

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

.github/copilot-instructions.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# ManagedCode.Communication
2+
3+
Result pattern for .NET that replaces exceptions with type-safe return values. Features railway-oriented programming, ASP.NET Core integration, RFC 7807 Problem Details, and built-in pagination.
4+
5+
## General
6+
7+
* Always prefer Result types over throwing exceptions for expected error cases.
8+
* Use railway-oriented programming patterns with `Map`, `Then`, `Compensate` for chaining operations.
9+
* Always use the latest C# features, currently C# 13.
10+
* Make only high confidence suggestions when reviewing code changes.
11+
* Never change `Directory.Build.props`, or solution files unless explicitly asked.
12+
13+
## .NET Environment
14+
15+
* This project targets .NET 9.0 and uses C# 13.0.
16+
* The project uses nullable reference types and treats warnings as errors.
17+
18+
## Building and Testing
19+
20+
```bash
21+
dotnet build
22+
dotnet test
23+
```
24+
25+
## Formatting
26+
27+
* Apply code-formatting style defined in `.editorconfig`.
28+
* Prefer file-scoped namespace declarations and single-line using directives.
29+
* Insert a newline before the opening curly brace of any code block.
30+
* Use pattern matching and switch expressions wherever possible.
31+
* Use `nameof` instead of string literals when referring to member names.
32+
33+
### Nullable Reference Types
34+
35+
* Declare variables non-nullable, and check for `null` at entry points.
36+
* Always use `is null` or `is not null` instead of `== null` or `!= null`.
37+
* Trust the C# null annotations and don't add null checks when the type system says a value cannot be null.
38+
39+
## Testing
40+
41+
* We use xUnit for tests with FluentAssertions for assertions.
42+
* Do not emit "Arrange", "Act" or "Assert" comments.
43+
* Use the naming pattern: `Method_Scenario_ExpectedResult()`.
44+
* Copy existing style in nearby test files for method names and capitalization.
45+
46+
```csharp
47+
[Fact]
48+
public void Succeed_ShouldCreateSuccessfulResult()
49+
{
50+
var result = Result.Succeed();
51+
52+
result.IsSuccess
53+
.Should()
54+
.BeTrue();
55+
result.IsFailed
56+
.Should()
57+
.BeFalse();
58+
result.Problem
59+
.Should()
60+
.BeNull();
61+
}
62+
```
63+
64+
## Core Result Types
65+
66+
This library implements the Result pattern for functional error handling:
67+
68+
* `Result` - Success/failure without a value
69+
* `Result<T>` - Success with value T or failure
70+
* `CollectionResult<T>` - Collections with built-in pagination
71+
* `Problem` - RFC 7807 compliant error details
72+
73+
## Railway-Oriented Programming
74+
75+
Chain operations using functional combinators:
76+
77+
```csharp
78+
// Basic Result usage
79+
var success = Result.Succeed();
80+
var failure = Result.Fail("Error message");
81+
82+
// Railway-oriented programming
83+
return ValidateEmail(email)
84+
.Then(ProcessEmail)
85+
.Then(SaveToDatabase);
86+
```
87+
88+
## Best Practices
89+
90+
**DO ✅ Use Result for operations that can fail:**
91+
```csharp
92+
public Result<User> GetUser(int id)
93+
{
94+
var user = _repository.FindById(id);
95+
return user is not null
96+
? Result<User>.Succeed(user)
97+
: Result<User>.FailNotFound($"User {id} not found");
98+
}
99+
```
100+
101+
**DO ✅ Provide specific error information:**
102+
```csharp
103+
public Result ValidateEmail(string email)
104+
{
105+
if (string.IsNullOrEmpty(email))
106+
return Result.FailValidation(("email", "Email is required"));
107+
108+
if (!email.Contains('@'))
109+
return Result.FailValidation(("email", "Invalid email format"));
110+
111+
return Result.Succeed();
112+
}
113+
```
114+
115+
**DON'T ❌ Throw exceptions from Result-returning methods:**
116+
```csharp
117+
public Result<User> GetUser(int id)
118+
{
119+
if (id <= 0)
120+
return Result<User>.FailValidation(("id", "ID must be positive")); //
121+
// NOT: throw new ArgumentException("Invalid ID"); // ❌
122+
}
123+
```
124+
125+
**DON'T ❌ Ignore Result values:**
126+
```csharp
127+
var result = UpdateUser(user);
128+
if (result.IsFailed)
129+
return result; // ✅ Handle the failure
130+
```
131+
132+
## Framework Integration
133+
134+
**ASP.NET Core:**
135+
* Controllers can return Result types directly
136+
* Automatic HTTP status code mapping from Problem Details
137+
* Built-in filters for Result handling
138+
139+
**Orleans:**
140+
* Use `UseOrleansCommunication()` for automatic serialization
141+
* Result types work across grain boundaries
142+
143+
**Performance:**
144+
* `Result` and `Result<T>` are structs - avoid boxing
145+
* Use railway-oriented programming to avoid intermediate variables
146+
* Cache common Problem instances for frequent errors

0 commit comments

Comments
 (0)