|
| 1 | +# Agent Guidelines for Exceptionless.RandomData |
| 2 | + |
| 3 | +You are an expert .NET engineer working on Exceptionless.RandomData, a focused utility library for generating random data useful in unit tests and data seeding. The library provides methods for generating random integers, longs, doubles, decimals, booleans, strings, words, sentences, paragraphs, dates, enums, IP addresses, versions, and coordinates. It also includes an `EnumerableExtensions.Random<T>()` extension method to pick a random element from any collection. |
| 4 | + |
| 5 | +**Craftsmanship Mindset**: Every line of code should be intentional, readable, and maintainable. Write code you'd be proud to have reviewed by senior engineers. Prefer simplicity over cleverness. When in doubt, favor explicitness and clarity. |
| 6 | + |
| 7 | +## Repository Overview |
| 8 | + |
| 9 | +Exceptionless.RandomData provides random data generation utilities for .NET applications: |
| 10 | + |
| 11 | +- **Numeric** - `GetInt`, `GetLong`, `GetDouble`, `GetDecimal` with optional min/max ranges |
| 12 | +- **Boolean** - `GetBool` with configurable probability (0-100%) |
| 13 | +- **String** - `GetString`, `GetAlphaString`, `GetAlphaNumericString` with configurable length and allowed character sets |
| 14 | +- **Text** - `GetWord`, `GetWords`, `GetTitleWords`, `GetSentence`, `GetParagraphs` with lorem ipsum-style words and optional HTML output |
| 15 | +- **DateTime** - `GetDateTime`, `GetDateTimeOffset`, `GetTimeSpan` with optional start/end ranges |
| 16 | +- **Enum** - `GetEnum<T>()` to pick a random enum value (constrained to `struct, Enum`) |
| 17 | +- **Network** - `GetIp4Address` for random IPv4 addresses |
| 18 | +- **Version** - `GetVersion` for random version strings with optional min/max |
| 19 | +- **Coordinate** - `GetCoordinate` for random lat/lng pairs |
| 20 | +- **Collection** - `EnumerableExtensions.Random<T>()` to pick a random element from any `IEnumerable<T>` |
| 21 | + |
| 22 | +Design principles: **simplicity**, **thread safety** (uses `Random.Shared`), **cryptographic quality strings** (uses `RandomNumberGenerator`), **modern .NET features** (targeting net8.0/net10.0). |
| 23 | + |
| 24 | +## Quick Start |
| 25 | + |
| 26 | +```bash |
| 27 | +# Build |
| 28 | +dotnet build Exceptionless.RandomData.slnx |
| 29 | + |
| 30 | +# Test |
| 31 | +dotnet run --project test/Exceptionless.RandomData.Tests -f net8.0 |
| 32 | + |
| 33 | +# Format code |
| 34 | +dotnet format Exceptionless.RandomData.slnx |
| 35 | +``` |
| 36 | + |
| 37 | +## Project Structure |
| 38 | + |
| 39 | +```text |
| 40 | +src |
| 41 | +└── Exceptionless.RandomData |
| 42 | + └── RandomData.cs # All random data generation + EnumerableExtensions |
| 43 | +test |
| 44 | +└── Exceptionless.RandomData.Tests |
| 45 | + ├── RandomDataTests.cs # Unit tests |
| 46 | + └── Properties |
| 47 | + └── AssemblyInfo.cs # Disables test parallelization |
| 48 | +``` |
| 49 | + |
| 50 | +## Coding Standards |
| 51 | + |
| 52 | +### Style & Formatting |
| 53 | + |
| 54 | +- Follow `.editorconfig` rules (file-scoped namespaces, K&R braces) |
| 55 | +- Follow [Microsoft C# conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions) |
| 56 | +- Use `String.`/`Int32.`/`Char.` for static method access per `.editorconfig` `dotnet_style_predefined_type_for_member_access = false` |
| 57 | +- Run `dotnet format` to auto-format code |
| 58 | +- Match existing file style; minimize diffs |
| 59 | +- No code comments unless necessary—code should be self-explanatory |
| 60 | + |
| 61 | +### Code Quality |
| 62 | + |
| 63 | +- Write complete, runnable code—no placeholders, TODOs, or `// existing code...` comments |
| 64 | +- Use modern C# features available in **net8.0/net10.0** |
| 65 | +- **Nullable reference types** are enabled—annotate nullability correctly, don't suppress warnings without justification |
| 66 | +- **ImplicitUsings** are enabled—don't add `using System;`, `using System.Collections.Generic;`, etc. |
| 67 | +- Follow SOLID, DRY principles; remove unused code and parameters |
| 68 | +- Clear, descriptive naming; prefer explicit over clever |
| 69 | + |
| 70 | +### Modern .NET Idioms |
| 71 | + |
| 72 | +- **Guard APIs**: Use `ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual()`, `ArgumentOutOfRangeException.ThrowIfLessThan()`, `ArgumentOutOfRangeException.ThrowIfGreaterThan()`, `ArgumentNullException.ThrowIfNull()`, `ArgumentException.ThrowIfNullOrEmpty()` instead of manual checks |
| 73 | +- **`Random.Shared`**: Use `Random.Shared` instead of `new Random()` for thread-safe random number generation |
| 74 | +- **`RandomNumberGenerator.Fill()`**: Use the static method instead of `RandomNumberGenerator.Create()` + disposal |
| 75 | +- **Collection expressions**: Use `[...]` syntax for array initialization |
| 76 | +- **`Span<T>`**: Use `stackalloc` and span-based APIs to avoid allocations in hot paths |
| 77 | +- **Expression-bodied members**: Use for single-expression methods |
| 78 | +- **`Math.Clamp`**: Use instead of separate `Math.Min`/`Math.Max` calls |
| 79 | +- **Generic constraints**: Use `where T : struct, Enum` instead of runtime `typeof(T).IsEnum` checks |
| 80 | +- **Pattern matching**: Use `is null` / `is not null` instead of `== null` / `!= null` |
| 81 | + |
| 82 | +### Exceptions |
| 83 | + |
| 84 | +- Use `ArgumentOutOfRangeException.ThrowIf*` guard APIs at method entry |
| 85 | +- Use `ArgumentException` for invalid arguments that don't fit range checks |
| 86 | +- Include parameter names via `nameof()` where applicable |
| 87 | +- Fail fast: throw exceptions immediately for invalid arguments |
| 88 | + |
| 89 | +## Making Changes |
| 90 | + |
| 91 | +### Before Starting |
| 92 | + |
| 93 | +1. **Gather context**: Read `RandomData.cs` and the test file to understand the full scope |
| 94 | +2. **Research patterns**: Find existing usages of the code you're modifying |
| 95 | +3. **Understand completely**: Know the problem, side effects, and edge cases before coding |
| 96 | +4. **Plan the approach**: Choose the simplest solution that satisfies all requirements |
| 97 | + |
| 98 | +### While Coding |
| 99 | + |
| 100 | +- **Minimize diffs**: Change only what's necessary, preserve formatting and structure |
| 101 | +- **Preserve behavior**: Don't break existing functionality or change semantics unintentionally |
| 102 | +- **Build incrementally**: Run `dotnet build` after each logical change to catch errors early |
| 103 | +- **Test continuously**: Run tests frequently to verify correctness |
| 104 | +- **Match style**: Follow the patterns in surrounding code exactly |
| 105 | + |
| 106 | +### Validation |
| 107 | + |
| 108 | +Before marking work complete, verify: |
| 109 | + |
| 110 | +1. **Builds successfully**: `dotnet build Exceptionless.RandomData.slnx` exits with code 0 |
| 111 | +2. **All tests pass**: `dotnet run --project test/Exceptionless.RandomData.Tests -f net8.0` shows no failures |
| 112 | +3. **No new warnings**: Check build output for new compiler warnings (warnings are treated as errors) |
| 113 | +4. **API compatibility**: Public API changes are intentional and backward-compatible when possible |
| 114 | +5. **Breaking changes flagged**: Clearly identify any breaking changes for review |
| 115 | + |
| 116 | +## Testing |
| 117 | + |
| 118 | +### Framework |
| 119 | + |
| 120 | +- **xUnit v3** with **Microsoft Testing Platform** as the test runner |
| 121 | +- Test parallelization is disabled via `Properties/AssemblyInfo.cs` |
| 122 | + |
| 123 | +### Running Tests |
| 124 | + |
| 125 | +```bash |
| 126 | +# All tests, both TFMs |
| 127 | +dotnet run --project test/Exceptionless.RandomData.Tests -f net8.0 |
| 128 | +dotnet run --project test/Exceptionless.RandomData.Tests -f net10.0 |
| 129 | +``` |
| 130 | + |
| 131 | +### Note on Namespace Conflict |
| 132 | + |
| 133 | +The test project uses `<RootNamespace>Exceptionless.Tests</RootNamespace>` to avoid a namespace conflict where the xUnit v3 MTP source generator creates a namespace `Exceptionless.RandomData.Tests` that shadows the `Exceptionless.RandomData` class. The test code uses `using Xunit;` and references `RandomData.*` methods directly since the `Exceptionless` namespace is accessible from within `Exceptionless.Tests`. |
| 134 | + |
| 135 | +## Resources |
| 136 | + |
| 137 | +- [README.md](README.md) - Overview and usage examples |
| 138 | +- [NuGet Package](https://www.nuget.org/packages/Exceptionless.RandomData/) |
0 commit comments