# Contributing to Murphy
Thank you for your interest in contributing to Murphy for Delphi! This guide will help you get started.
## Ways to Contribute
- Report bugs and issues
- Suggest new features or patterns
- Improve documentation
- Submit bug fixes
- Add new resilience patterns
- Write tests
- Share usage examples
## Getting Started
### 1. Fork and Clone
```bash
# Fork the repository on GitHub
# Clone your fork
git clone https://github.com/YOUR_USERNAME/murphy-delphi.git
cd murphy-delphi
```
### 2. Create a Branch
```bash
git checkout -b feature/my-new-feature
# or
git checkout -b fix/bug-description
```
### 3. Set Up Development Environment
- Delphi 11 Alexandria or later
- Install Blocks package manager (optional but recommended)
- Load `Murphy.dpk` or the demo project
## Code Standards
### Coding Style
Murphy follows standard Delphi conventions:
```pascal
// Use XML documentation comments
///
/// Brief description of what this does.
///
function MyFunction: Integer;
// Use meaningful names
var
RetryCount: Integer; // Good
var i: Integer; // Bad for non-loop variables
// Use inline variables (Delphi 11+)
procedure Example;
begin
var LocalVar := 'value';
end;
```
### File Organization
```
Source/
Murphy.Base.Policy.pas # Base classes
Murphy.Policy.YourPattern.pas # New pattern
Murphy.Services.*.pas # Support services
Tests/
Murphy.Tests.YourPattern.pas # Unit tests
Demos/
Samples.YourPattern.pas # Usage examples
```
## Adding a New Pattern
### 1. Create the Interface
```pascal
type
IYourPolicy = interface(IPolicy)
['{GENERATE-NEW-GUID}']
procedure Execute(AProc: TProc);
function ConfigMethod(AValue: Integer): IYourPolicy;
end;
```
### 2. Implement the Policy
```pascal
type
TYourPolicy = class(TPolicy, IYourPolicy)
private
FConfigValue: Integer;
public
constructor Create(AExceptionTypes: TArray); override;
procedure Execute(AProc: TProc);
function ConfigMethod(AValue: Integer): IYourPolicy;
end;
```
### 3. Create the Builder
```pascal
type
TYourPolicyBuilder = class sealed(TPolicyBuilder)
public
class function Handle(AExceptionTypes: TArray): IYourPolicy; override;
end;
```
### 4. Add Tests
```pascal
unit Murphy.Tests.YourPattern;
interface
uses
DUnitX.TestFramework,
Murphy.Policy.YourPattern;
type
[TestFixture]
TYourPolicyTests = class
public
[Test]
procedure TestBasicFunctionality;
[Test]
procedure TestExceptionHandling;
end;
implementation
// Implementation...
end.
```
### 5. Add Demo
Create a sample in `Demos/00_Primer/Samples.YourPattern.pas`
### 6. Update Documentation
- Add pattern guide in `Docs/Patterns/YourPattern.md`
- Add API reference in `Docs/API-Reference/YourPattern-Policy.md`
- Update main README.md
## Testing Requirements
### All Contributions Must Include Tests
```pascal
[Test]
procedure TYourTests.TestYourFeature;
begin
MurphyTestModeEnabled := True;
try
// Arrange
var Policy := TYourBuilder.Handle(Exception).Build;
// Act
Policy.Execute(procedure begin ... end);
// Assert
Assert.IsTrue(...);
finally
MurphyTestModeEnabled := False;
end;
end;
```
### Test Coverage
- Happy path (successful execution)
- Failure scenarios
- Exception handling
- Edge cases
- Configuration validation
### Run All Tests Before Submitting
```bash
# Open Murphy.Tests.dpr
# Run all tests
# Ensure all tests pass
```
## Documentation Requirements
### Code Comments
```pascal
///
/// Executes the provided procedure with your pattern logic.
///
/// The procedure to execute
///
/// Additional details about behavior, exceptions, or usage.
///
procedure Execute(AProc: TProc);
```
### Markdown Documentation
For new patterns, create:
- Pattern guide (`Docs/Patterns/YourPattern.md`)
- API reference (`Docs/API-Reference/YourPattern-Policy.md`)
Include:
- Description and purpose
- When to use / when not to use
- Quick start example
- Common scenarios (3-5 examples)
- Best practices
## Submitting Changes
### 1. Commit Your Changes
```bash
git add .
git commit -m "Add: New timeout pattern implementation"
# Use conventional commit messages:
# Add: New feature
# Fix: Bug fix
# Update: Improvements to existing feature
# Docs: Documentation changes
# Test: Test additions or changes
```
### 2. Push to Your Fork
```bash
git push origin feature/my-new-feature
```
### 3. Create Pull Request
- Go to GitHub and create a pull request
- Fill in the PR template (if provided)
- Describe your changes clearly
- Reference any related issues
### PR Checklist
- [ ] Code compiles without warnings
- [ ] All existing tests pass
- [ ] New tests added for new functionality
- [ ] Documentation updated
- [ ] Code follows Murphy conventions
- [ ] Commit messages are clear
- [ ] No unnecessary changes (whitespace, formatting)
## Reporting Issues
### Bug Reports
Include:
- Delphi version
- Murphy version
- Steps to reproduce
- Expected behavior
- Actual behavior
- Code sample (minimal reproducible example)
Example:
```
## Bug Report
**Environment:**
- Delphi 11.3
- Murphy v1.0.0
- Windows 11
**Description:**
Retry policy doesn't respect wait delay in specific scenario...
**To Reproduce:**
```pascal
var Policy := TRetryBuilder
.Handle(Exception)
.Retry(3)
.Wait(TTimeSpan.FromSeconds(5))
.Build;
// Steps...
```
**Expected:** Should wait 5 seconds between retries
**Actual:** No delay observed
```
### Feature Requests
Include:
- Use case description
- Proposed API
- Example usage
- Benefits
## Code Review Process
- Maintainers will review your PR
- You may be asked to make changes
- Once approved, your PR will be merged
- Your contribution will be credited
## Community Guidelines
- Be respectful and constructive
- Help others in discussions
- Share your Murphy usage experiences
- Report issues you encounter
## Recognition
Contributors will be:
- Listed in CONTRIBUTORS.md (if created)
- Credited in release notes
- Mentioned in the project README
## Questions?
- Open an issue for questions
- Check existing documentation
- Look at existing patterns for examples
## License
By contributing, you agree that your contributions will be licensed under the MIT License.
---
Thank you for contributing to Murphy for Delphi! 🎉
[Back to Index](../Home.md)