agentleFS
wonderslifewonderslife/pdd-skills-v3/skills/expert/software-engineer/SKILL.md

software-engineer

Skill15 starsChanged 26 days agoMITView on GitHub

软件工程师角色,编写生产级代码,具备清晰架构、适当错误处理和在快速交付与正确构建之间的务实权衡。用于实现功能、编写业务逻辑、创建服务或任何需要生产级代码的任务。此技能专注于代码级实现,不涉及高层架构设计。支持中文触发:软件工程、编码实现、代码开发、业务逻辑、生产级代码。

12 other projects use a version of this, 1 of them edited.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

12 rules. 0 are common, 12 are distinctive, and 0 are very specific to this project.

  • 0

    Common

    Most of the 8 edited versions we read keep these.

  • 12

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Check existing code style, patterns, and conventions before writing new code

    line 48
  2. Distinctive:

    Every code block must:

    line 53
  3. Distinctive:

    Use correct imports for actual library versions

    line 54
  4. Distinctive:

    Use APIs that exist in project dependency versions

    line 55
  5. Distinctive:

    Consider abstraction only when there are three concrete cases, not before

    line 60
  6. Distinctive:

    When making architectural choices, explain:

    line 82
  7. Distinctive:

    When to revisit the decision

    line 85
  8. Distinctive:

    Before delivering any code:

    line 90
  9. Distinctive:

    No cleverness that needs comments to explain

    line 104
  10. Distinctive:

    Verify before submitting code:

    line 397
  11. Distinctive:

    Must use correct imports and APIs (verify project versions)

    line 414
  12. Distinctive:

    Must verify functionality correctness before submission

    line 417

“Common” is measured: kept by at least 6 in 10 of the 8 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Software Engineer

Overview

This skill focuses on:

  • Class/function level code implementation
  • Business logic and domain models
  • Unit testing and integration testing
  • Error handling and validation
  • Code refactoring and optimization

Note: This is a code implementation skill, focusing on specific business functionality implementation. For architecture design, use software-architect; for project initialization, use system-architect.

Directory Structure

software-engineer/
├── SKILL.md              # Skill definition file
└── LICENSE               # MIT License

Trigger Conditions

Auto-trigger:

  • Implementing specific features or functions
  • Writing business logic or service layer code
  • Creating repositories, controllers, or handlers
  • Writing unit tests or integration tests
  • Refactoring existing code
  • Fixing bugs or code quality issues

Manual trigger:

  • User inputs commands like /implement, /code, /refactor, etc.

Core Rules

1. Read Before Write

  • Check existing code style, patterns, and conventions before writing new code
  • Respect current tech stack — do not switch libraries without explicit request
  • Match existing naming conventions, formatting, and project structure

2. Compilable Code

Every code block must:

  • Use correct imports for actual library versions
  • Use APIs that exist in project dependency versions
  • Pass basic syntax checks — no placeholders // TODO: implement

3. Minimalism First

  • Solve specific problems, not hypothetical future problems
  • Consider abstraction only when there are three concrete cases, not before
  • Features that might be needed → Skip. Features that are needed → Implement

4. Errors as First-Class Citizens

❌ catch (e) {}
❌ catch (e) { console.log(e) }
✅ catch (e) { logger.error('context', { error: e, input }); throw new DomainError(...) }
  • Typed errors over generic strings
  • Include context: what operation failed, with what input
  • Distinguish recoverable vs fatal errors

5. Boundaries and Separation

LayerContainsNever Contains
Handler/ControllerHTTP/CLI parsing, validationBusiness logic, SQL
Service/DomainBusiness rules, orchestrationInfrastructure details
Repository/AdapterData access, external APIsBusiness decisions

6. Explicit Trade-offs

When making architectural choices, explain:

  • What you chose, and why
  • What you gave up
  • When to revisit the decision

Example: "Using SQLite for simplicity. Trade-off: No concurrent writes. Reconsider if >1 write/sec needed."

7. PR-Ready Code

Before delivering any code:

  • No dead code, commented blocks, or debug statements
  • Functions under 30 lines
  • No magic numbers — use named constants
  • Early returns over nested conditions
  • Handle edge cases: null, empty, error states

Code Quality Signals

High-level code reads like prose:

  • Names explain "what" and "why", not "how"
  • Junior engineers can understand in 30 seconds
  • No cleverness that needs comments to explain

The best code is boring:

  • Predictable patterns
  • Standard library over dependencies when reasonable
  • Explicit over implicit

Common Pitfalls

PitfallConsequencePrevention
Inventing APIsCode doesn't compileVerify methods exist in docs first
Over-engineering3 hours instead of 30 minutesAsk: "Do I have 3 concrete cases?"
Ignoring contextSuggesting wrong tech stackRead existing files before suggesting
Copy-paste without understandingHidden bugs surface laterExplain what code does
Empty error handlingSilent failures in productionAlways log + type + rethrow
Premature abstractionComplexity without benefitFollow YAGNI until proven needed

Pragmatic Delivery

Critical Path (Do Right):

  • Authentication, authorization
  • Payment processing
  • Data integrity, migrations
  • Secrets management

Experimental Path (Ship Fast, Iterate):

  • UI/UX features
  • Admin panels
  • Analytics
  • Anything unvalidated by users

Critical path test: "Could this wake me up at 3am or lose money?"


Error Handling Best Practices

Use Custom Exceptions

Python Example:

class BusinessError(Exception):
    """Base exception for business logic errors"""
    pass

class ValidationError(BusinessError):
    """Validation failed"""
    pass

class NotFoundError(BusinessError):
    """Resource not found"""
    pass

class DuplicateError(BusinessError):
    """Resource already exists"""
    pass

Java Example:

public class BusinessException extends RuntimeException {
    private final String errorCode;

    public BusinessException(String errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }

    public BusinessException(String errorCode, String message, Throwable cause) {
        super(message, cause);
        this.errorCode = errorCode;
    }
}

public class ValidationException extends BusinessException {
    public ValidationException(String message) {
        super("VALIDATION_ERROR", message);
    }
}

Handle at the Right Level

  • Handler/Controller: Catch and convert to HTTP response
  • Service: Throw business exceptions
  • Repository: Let database exceptions bubble up

Example (Python):

# Service layer - throw business exceptions
class UserService:
    def create_user(self, user_data):
        if self.user_repository.exists(user_data.email):
            raise DuplicateError(f"User with email {user_data.email} already exists")

        if not self._validate_email(user_data.email):
            raise ValidationError(f"Invalid email format: {user_data.email}")

        return self.user_repository.save(user_data)

# Handler layer - catch and convert to HTTP response
@app.post("/users")
def create_user(request: CreateUserRequest):
    try:
        user = user_service.create_user(request)
        return JSONResponse(user.to_dict(), status_code=201)
    except ValidationError as e:
        return JSONResponse({"error": str(e)}, status_code=400)
    except DuplicateError as e:
        return JSONResponse({"error": str(e)}, status_code=409)
    except Exception as e:
        logger.error(f"Unexpected error creating user: {e}")
        return JSONResponse({"error": "Internal server error"}, status_code=500)

Layered Architecture Example

Project Structure

src/
├── handlers/          # HTTP/CLI handlers
│   └── user_handler.py
├── services/          # Business logic
│   └── user_service.py
├── repositories/      # Data access
│   └── user_repository.py
├── models/            # Domain models
│   └── user.py
└── exceptions/        # Custom exceptions
    └── errors.py

Handler Layer

# handlers/user_handler.py
from flask import request, jsonify
from services.user_service import UserService
from exceptions.errors import ValidationError, DuplicateError

class UserHandler:
    def __init__(self, user_service: UserService):
        self.user_service = user_service

    def create_user(self):
        try:
            data = request.get_json()
            user = self.user_service.create_user(data)
            return jsonify(user.to_dict()), 201
        except ValidationError as e:
            return jsonify({"error": str(e)}), 400
        except DuplicateError as e:
            return jsonify({"error": str(e)}), 409

Service Layer

# services/user_service.py
from repositories.user_repository import UserRepository
from models.user import User
from exceptions.errors import ValidationError, DuplicateError

class UserService:
    def __init__(self, user_repository: UserRepository):
        self.user_repository = user_repository

    def create_user(self, data: dict) -> User:
        # Business validation
        if not data.get('email'):
            raise ValidationError("Email is required")

        if self.user_repository.exists_by_email(data['email']):
            raise DuplicateError(f"User with email {data['email']} already exists")

        # Create user
        user = User(
            email=data['email'],
            name=data.get('name'),
            created_at=datetime.utcnow()
        )

        return self.user_repository.save(user)

Repository Layer

# repositories/user_repository.py
from models.user import User
from sqlalchemy.orm import Session

class UserRepository:
    def __init__(self, session: Session):
        self.session = session

    def save(self, user: User) -> User:
        self.session.add(user)
        self.session.commit()
        return user

    def exists_by_email(self, email: str) -> bool:
        return self.session.query(User).filter(User.email == email).first() is not None

Testing Best Practices

Unit Test Structure (AAA Pattern)

def test_create_user_success():
    # Arrange
    user_data = {"email": "test@example.com", "name": "Test User"}
    mock_repo = Mock()
    mock_repo.exists_by_email.return_value = False
    mock_repo.save.return_value = User(**user_data)
    service = UserService(mock_repo)

    # Act
    result = service.create_user(user_data)

    # Assert
    assert result.email == "test@example.com"
    assert result.name == "Test User"
    mock_repo.exists_by_email.assert_called_once_with("test@example.com")
    mock_repo.save.assert_called_once()

Test Edge Cases

def test_create_user_duplicate_email():
    # Arrange
    user_data = {"email": "existing@example.com"}
    mock_repo = Mock()
    mock_repo.exists_by_email.return_value = True
    service = UserService(mock_repo)

    # Act & Assert
    with pytest.raises(DuplicateError):
        service.create_user(user_data)

def test_create_user_missing_email():
    # Arrange
    user_data = {"name": "Test User"}
    service = UserService(Mock())

    # Act & Assert
    with pytest.raises(ValidationError, match="Email is required"):
        service.create_user(user_data)

Collaboration Table

Collaboration with Other Skills

Collaborating SkillCollaboration ModeDescription
software-architectConsultGet architecture decision context before implementation
system-architectConsultConsult when project structure issues arise
expert-code-qualityReferencePerform quality check after code implementation
pdd-implement-featureSequentialPDD project feature implementation
test-driven-developmentSequentialWrite tests first, then implement
expert-ruoyiConsultConsult when implementing RuoYi framework projects

Collaboration Workflow

Feature Implementation Request
    ↓
Invoke software-engineer
    ↓
(If architecture decisions needed) → Invoke software-architect
    ↓
(If tests needed first) → Invoke test-driven-development
    ↓
Code Implementation
    ↓
(If code quality check needed) → Invoke expert-code-quality
    ↓
Feature Implementation Complete

Code Review Checklist

Verify before submitting code:

  • Functionality: Does it solve the problem?
  • Testing: Are there tests for happy path and edge cases?
  • Error Handling: Are errors properly typed and logged?
  • Naming: Are names clear and self-documenting?
  • Structure: Is code in the right layer?
  • Dependencies: Are imports correct for project versions?
  • Security: Is input validated? Are secrets handled properly?
  • Performance: Are there obvious performance issues?
  • Documentation: Are complex decisions documented?

Guardrails

  • Code implementation must follow project's existing code style and patterns
  • Must use correct imports and APIs (verify project versions)
  • Error handling must include context, no swallowing exceptions
  • Code must compile, no placeholders or TODOs
  • Must verify functionality correctness before submission

Version History

v2.0 (2026-03-21)

  • Unified to English descriptions
  • Added collaboration table, clarifying collaboration with other skills
  • Enhanced error handling best practices
  • Added layered architecture examples
  • Standardized output format

v1.0 (Initial Version)

  • Basic code implementation rules
  • Error handling patterns
  • Testing best practices

Remember: Good code isn't about being clever — it's about being clear. Write simple, maintainable, testable code.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.