| name | software-engineer |
| description | 软件工程师角色,编写生产级代码,具备清晰架构、适当错误处理和在快速交付与正确构建之间的务实权衡。用于实现功能、编写业务逻辑、创建服务或任何需要生产级代码的任务。此技能专注于代码级实现,不涉及高层架构设计。支持中文触发:软件工程、编码实现、代码开发、业务逻辑、生产级代码。 |
| license | MIT |
| author | neuqik@hotmail.com |
| version | 2.0 |
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
| Layer | Contains | Never Contains |
|---|
| Handler/Controller | HTTP/CLI parsing, validation | Business logic, SQL |
| Service/Domain | Business rules, orchestration | Infrastructure details |
| Repository/Adapter | Data access, external APIs | Business 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:
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
| Pitfall | Consequence | Prevention |
|---|
| Inventing APIs | Code doesn't compile | Verify methods exist in docs first |
| Over-engineering | 3 hours instead of 30 minutes | Ask: "Do I have 3 concrete cases?" |
| Ignoring context | Suggesting wrong tech stack | Read existing files before suggesting |
| Copy-paste without understanding | Hidden bugs surface later | Explain what code does |
| Empty error handling | Silent failures in production | Always log + type + rethrow |
| Premature abstraction | Complexity without benefit | Follow 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):
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)
@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
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
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:
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")
user = User(
email=data['email'],
name=data.get('name'),
created_at=datetime.utcnow()
)
return self.user_repository.save(user)
Repository Layer
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():
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)
result = service.create_user(user_data)
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():
user_data = {"email": "existing@example.com"}
mock_repo = Mock()
mock_repo.exists_by_email.return_value = True
service = UserService(mock_repo)
with pytest.raises(DuplicateError):
service.create_user(user_data)
def test_create_user_missing_email():
user_data = {"name": "Test User"}
service = UserService(Mock())
with pytest.raises(ValidationError, match="Email is required"):
service.create_user(user_data)
Collaboration Table
Collaboration with Other Skills
| Collaborating Skill | Collaboration Mode | Description |
|---|
| software-architect | Consult | Get architecture decision context before implementation |
| system-architect | Consult | Consult when project structure issues arise |
| expert-code-quality | Reference | Perform quality check after code implementation |
| pdd-implement-feature | Sequential | PDD project feature implementation |
| test-driven-development | Sequential | Write tests first, then implement |
| expert-ruoyi | Consult | Consult 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:
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.