<overview>
Clean code principles based on Robert Martin's Clean Code and industry research. SOLID principles, naming conventions, and code smell detection.
</overview>

<solid_principles>
| Principle | Rule | Violation Sign |
|-----------|------|----------------|
| **S**ingle Responsibility | One reason to change | Class/function does multiple things |
| **O**pen/Closed | Open for extension, closed for modification | Adding features requires changing existing code |
| **L**iskov Substitution | Subtypes must be substitutable | Subclass breaks when used as parent |
| **I**nterface Segregation | No forced dependencies | Implementing unused interface methods |
| **D**ependency Inversion | Depend on abstractions | Direct instantiation of dependencies |
</solid_principles>

<function_guidelines>
<size_and_scope>
Function size targets:

- Maximum 50 lines (ideally <20)
- Do ONE thing well
- Single level of abstraction
- Fit on one screen without scrolling
</size_and_scope>

<parameters>
Parameter limits:

- Maximum 3 parameters
- Avoid flag arguments (split into separate methods)
- Use objects for related parameters

**Parameter Object Pattern (for 4+ parameters):**

```csharp
// ❌ BAD - Too many parameters (S107)
public void CreateUser(
    string name,
    string email,
    string phone,
    string address,
    bool isActive,
    Guid tenantId)
{
    // ...
}

// ✅ GOOD - Use parameter object
public record CreateUserRequest(
    string Name,
    string Email,
    string Phone,
    string Address,
    bool IsActive,
    Guid TenantId);

public void CreateUser(CreateUserRequest request)
{
    // Access via request.Name, request.Email, etc.
}
```

**Benefits:**
- Easier to extend (add new parameters without changing signature)
- Self-documenting (grouped related data)
- Enables validation logic on the object itself
- Reduces method signature complexity
</parameters>

<naming>
Function naming patterns:

- Verbs for functions: `getUserById()`, `calculateTotal()`
- Reveals intent without reading body
- No abbreviations: `getTransaction()` not `getTx()`
</naming>

<string_comparison>
**C# String Comparison Best Practices:**

ALWAYS use `StringComparison` overloads to avoid culture-specific issues (CA1873).

```csharp
// ❌ BAD - Culture-dependent, performance issue
if (str1.ToLower() == str2.ToLower()) { ... }
if (str1.ToUpper() == str2.ToUpper()) { ... }

// ✅ GOOD - Explicit comparison
if (string.Equals(str1, str2, StringComparison.OrdinalIgnoreCase)) { ... }
if (str1.Equals(str2, StringComparison.OrdinalIgnoreCase)) { ... }

// ❌ BAD - Culture-dependent Contains
if (str.ToLower().Contains("keyword")) { ... }

// ✅ GOOD - Explicit comparison (C# 5.0+)
if (str.Contains("keyword", StringComparison.OrdinalIgnoreCase)) { ... }

// ❌ BAD - Culture-dependent StartsWith/EndsWith
if (str.ToLower().StartsWith("prefix")) { ... }

// ✅ GOOD - Explicit comparison
if (str.StartsWith("prefix", StringComparison.OrdinalIgnoreCase)) { ... }
```

**StringComparison options:**
- `Ordinal` - Binary comparison (fastest, case-sensitive)
- `OrdinalIgnoreCase` - Binary comparison (case-insensitive)
- `CurrentCulture` - Culture-aware (rarely needed)
- `InvariantCulture` - Culture-invariant (for data storage)

**Rule of thumb:**
- Use `Ordinal` for identifiers, file paths, keys
- Use `OrdinalIgnoreCase` for user input comparison
- Avoid `ToLower()`/`ToUpper()` for comparison
</string_comparison>
</function_guidelines>

<naming_conventions>
General naming rules:

✓ Descriptive, unambiguous names
✓ Pronounceable and searchable
✓ Class names: nouns (User, PaymentProcessor)
✓ Method names: verbs (validate, calculate, fetch)
✗ Single letter variables (except loop counters)
✗ Hungarian notation (strName, intCount)
✗ Abbreviations (usr, txn, cfg)
</naming_conventions>

<code_smells>
<critical_smells>
Flag these in review:

| Smell | Detection | Fix |
|-------|-----------|-----|
| **Duplicated Code** | Same logic in 2+ places | Extract to shared function |
| **Large Class/Method** | >50 lines, multiple responsibilities | Split by responsibility |
| **Long Parameter List** | >3 parameters | Use parameter object |
| **Feature Envy** | Method uses another class's data more | Move method to that class |
| **God Object** | One class controls everything | Split into focused classes |
</critical_smells>

<medium_smells>
Suggest these fixes:

| Smell | Detection | Fix |
|-------|-----------|-----|
| **Deep Nesting** | >3 levels of indentation | Guard clauses, early returns |
| **Magic Numbers** | Unexplained literals | Named constants |
| **Dead Code** | Commented-out or unreachable code | Delete it |
| **Shotgun Surgery** | Small change touches many files | Consolidate related code |
| **Nested Ternary** | `? ( ? : ) :` patterns | Extract to function/if-else |
| **TODO/FIXME** | Untracked technical debt | Create ticket or fix immediately |
</medium_smells>

<nested_ternary_detection>
**Nested Ternary Operators (S3358):**

Nested ternaries are hard to read and maintain.

```typescript
// ❌ BAD - Nested ternary
const status = isActive
  ? (isPremium ? 'premium-active' : 'standard-active')
  : 'inactive';

const color = type === 'error'
  ? 'red'
  : type === 'warning' ? 'yellow' : 'blue';

// ✅ GOOD - Early returns in function
function getStatus(isActive: boolean, isPremium: boolean): string {
  if (!isActive) return 'inactive';
  if (isPremium) return 'premium-active';
  return 'standard-active';
}

// ✅ GOOD - If-else chain
let color: string;
if (type === 'error') {
  color = 'red';
} else if (type === 'warning') {
  color = 'yellow';
} else {
  color = 'blue';
}

// ✅ GOOD - Map/lookup for simple cases
const colorMap: Record<string, string> = {
  error: 'red',
  warning: 'yellow',
  info: 'blue'
};
const color = colorMap[type] ?? 'blue';
```

**Detection pattern:** Look for `? ... ? ... : ... :` in code.
</nested_ternary_detection>

<todo_fixme_tracking>
**TODO/FIXME Comments (S1135):**

Untracked TODOs become technical debt. Either fix immediately or create a tracked ticket.

```typescript
// ❌ BAD - Untracked TODO
// TODO: handle edge case

// ❌ BAD - Vague FIXME
// FIXME: this is broken

// ✅ ACCEPTABLE - Linked to ticket
// TODO(#1234): Implement retry logic for transient failures

// ✅ ACCEPTABLE - With deadline
// FIXME(2026-02-15): Remove legacy API call after migration

// ✅ BEST - No comment, just fix it
// (Actually implement the fix instead of leaving a comment)
```

**Code review action:**
1. Search for `TODO`, `FIXME`, `HACK`, `XXX`, `REFACTOR` comments
2. For each:
   - Is it linked to a ticket? If not, create one or fix now
   - Is it still relevant? If not, delete
   - Does it have context? If not, add details
3. Report untracked TODOs as `[SUGGESTION]` in review
</todo_fixme_tracking>
</code_smells>

<complexity_reduction>
<example_before>
Complex nested conditions:

```javascript
function process(user) {
  if (user) {
    if (user.isActive) {
      if (user.hasPermission) {
        // actual logic here
      }
    }
  }
}
```
</example_before>

<example_after>
Simplified with guard clauses:

```javascript
function process(user) {
  if (!user) return;
  if (!user.isActive) return;
  if (!user.hasPermission) return;

  // actual logic here
}
```
</example_after>
</complexity_reduction>

<comments_best_practices>
<good_comments>
Valuable comments explain:

- Explain WHY (intent), not WHAT (code does that)
- Warn of consequences
- TODO with ticket number
</good_comments>

<bad_comments>
Avoid these comment types:

- Redundant (restates the code)
- Commented-out code (delete it)
- Closing brace comments (`} // end if`)
- Journal comments (use git history)
</bad_comments>
</comments_best_practices>

<boy_scout_rule>
> Leave code cleaner than you found it.

**Important**: In PRs, only clean code already being changed. Don't expand scope.
</boy_scout_rule>

<sources>
- Clean Code by Robert C. Martin
- [Google Engineering Practices](https://google.github.io/eng-practices/)
- [Microsoft Code Review Guide](https://microsoft.github.io/code-with-engineering-playbook/)
</sources>
