Skip to content

Commit 8f90bba

Browse files
committed
Split Luhn class
- Clear separation of concerns: The project is well-structured, with distinct classes for calculation (`LuhnCalculator`), validation (`LuhnValidator`), and core algorithm logic (`LuhnAlgorithm`). This promotes maintainability and testability. - Extension methods: The use of extension methods for string manipulation and validation provides a fluent and convenient API. Resolves: No entry
1 parent 250348a commit 8f90bba

13 files changed

+1213
-875
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
- Add `RemoveSeparators` method to remove all separators from a string. Use it, for example, with credit card numbers.
1111

1212
### Changed
13-
- Renamed `Luhn.ConvertAlphaNumericToNumeric` to `Luhn.AlphaNumericToNumeric`
13+
- Renamed `ConvertAlphaNumericToNumeric` to `AlphaNumericToNumeric`
1414

1515
### Removed
1616
- Removed `Luhn.IsValid` methods

benchmark/LuhnDotNetBenchmark.cs

+90-10
Original file line numberDiff line numberDiff line change
@@ -15,66 +15,146 @@ public class LuhnDotNetBenchmark
1515
private const string ComputeLuhnCheckDigitCategory = "Compute Luhn check digit";
1616
private const string IsValidLuhnNumberCategory = "Validate Luhn number";
1717
private const string IsValidLuhnCheckDigitCategory = "Validate Luhn check digit";
18+
private const string AlphaNumericToNumericCategory = "AlphaNumeric to Numeric";
19+
private const string RemoveSeparatorCategory = "Remove separators";
20+
private const string ValidationChainCategory = "Validation chain";
21+
private const string ComputeChainCategory = "Compute chain";
1822

19-
public static IEnumerable<string> NumbersAsString()
23+
public static IEnumerable<string> NumericNumbersAsString()
2024
{
2125
yield return "79927398713";
2226
yield return "79927398718234234134645645645624563445654634343462545462546546245624356245625624565265432";
2327
}
2428

29+
public static IEnumerable<string> AlphaNumericNumbersAsString()
30+
{
31+
yield return "US79927398713";
32+
yield return "79927398713DE";
33+
yield return "ABCDEF";
34+
yield return "DE79927398718234234134645645645624563445654634343462545462546546245624356245625624565265432";
35+
}
36+
37+
public static IEnumerable<string> SeparatedNumbersAsString()
38+
{
39+
yield return "7992-7398-7134";
40+
yield return "79927398/71823423413464564564562456344565463434346254546254654/6245624356245625624565265432";
41+
}
42+
43+
public static IEnumerable<string> SeparatedAlphaNumericNumbersAsString()
44+
{
45+
yield return "US-7992-7398-7134";
46+
yield return "A7992-B7398-C7134";
47+
}
48+
2549
[Benchmark(Baseline = true), BenchmarkCategory(ComputeLuhnNumberCategory)]
26-
[ArgumentsSource(nameof(NumbersAsString))]
50+
[ArgumentsSource(nameof(NumericNumbersAsString))]
2751
public void ComputeLuhnNumberBasedOnString(string number)
2852
{
2953
number.ComputeLuhnNumber();
3054
}
3155

3256
[Benchmark(Baseline = true), BenchmarkCategory(ComputeLuhnCheckDigitCategory)]
33-
[ArgumentsSource(nameof(NumbersAsString))]
57+
[ArgumentsSource(nameof(NumericNumbersAsString))]
3458
public void ComputeLuhnCheckDigitBasedOnString(string number)
3559
{
3660
number.ComputeLuhnCheckDigit();
3761
}
3862

3963
[Benchmark(Baseline = true), BenchmarkCategory(IsValidLuhnNumberCategory)]
40-
[ArgumentsSource(nameof(NumbersAsString))]
64+
[ArgumentsSource(nameof(NumericNumbersAsString))]
4165
public void IsValidLuhnNumberBasedOnString(string number)
4266
{
4367
number.IsValidLuhnNumber();
4468
}
4569

4670
[Benchmark(Baseline = true), BenchmarkCategory(IsValidLuhnCheckDigitCategory)]
47-
[ArgumentsSource(nameof(NumbersAsString))]
71+
[ArgumentsSource(nameof(NumericNumbersAsString))]
4872
public void IsValidLuhnCheckDigitBasedOnString(string number)
4973
{
5074
byte.MinValue.IsValidLuhnCheckDigit(number);
5175
}
5276

5377
[Benchmark, BenchmarkCategory(ComputeLuhnNumberCategory)]
54-
[ArgumentsSource(nameof(NumbersAsString))]
78+
[ArgumentsSource(nameof(NumericNumbersAsString))]
5579
public void ComputeLuhnNumberBasedOnSpan(string number)
5680
{
5781
number.AsSpan().ComputeLuhnNumber();
5882
}
5983

6084
[Benchmark, BenchmarkCategory(ComputeLuhnCheckDigitCategory)]
61-
[ArgumentsSource(nameof(NumbersAsString))]
85+
[ArgumentsSource(nameof(NumericNumbersAsString))]
6286
public void ComputeLuhnCheckDigitBasedOnSpan(string number)
6387
{
6488
number.AsSpan().ComputeLuhnCheckDigit();
6589
}
6690

6791
[Benchmark, BenchmarkCategory(IsValidLuhnNumberCategory)]
68-
[ArgumentsSource(nameof(NumbersAsString))]
92+
[ArgumentsSource(nameof(NumericNumbersAsString))]
6993
public void IsValidLuhnNumberBasedOnSpan(string number)
7094
{
7195
number.AsSpan().IsValidLuhnNumber();
7296
}
7397

7498
[Benchmark, BenchmarkCategory(IsValidLuhnCheckDigitCategory)]
75-
[ArgumentsSource(nameof(NumbersAsString))]
99+
[ArgumentsSource(nameof(NumericNumbersAsString))]
76100
public void IsValidLuhnCheckDigitBasedOnSpan(string number)
77101
{
78102
byte.MinValue.IsValidLuhnCheckDigit(number.AsSpan());
79103
}
80-
}
104+
105+
[Benchmark(Baseline = true), BenchmarkCategory(AlphaNumericToNumericCategory)]
106+
[ArgumentsSource(nameof(AlphaNumericNumbersAsString))]
107+
public void AlphaNumericToNumericBasedOnString(string number)
108+
{
109+
number.AlphaNumericToNumeric();
110+
}
111+
112+
[Benchmark, BenchmarkCategory(AlphaNumericToNumericCategory)]
113+
[ArgumentsSource(nameof(AlphaNumericNumbersAsString))]
114+
public void AlphaNumericToNumericBasedOnSpan(string number)
115+
{
116+
number.AsSpan().AlphaNumericToNumeric();
117+
}
118+
119+
[Benchmark(Baseline = true), BenchmarkCategory(RemoveSeparatorCategory)]
120+
[ArgumentsSource(nameof(SeparatedNumbersAsString))]
121+
public void RemoveSeparatorBasedOnString(string number)
122+
{
123+
number.RemoveSeparators();
124+
}
125+
126+
[Benchmark, BenchmarkCategory(RemoveSeparatorCategory)]
127+
[ArgumentsSource(nameof(SeparatedNumbersAsString))]
128+
public void RemoveSeparatorBasedOnSpan(string number)
129+
{
130+
number.AsSpan().RemoveSeparators();
131+
}
132+
133+
[Benchmark(Baseline = true), BenchmarkCategory(ComputeChainCategory)]
134+
[ArgumentsSource(nameof(SeparatedAlphaNumericNumbersAsString))]
135+
public void ComputeChainBasedOnString(string number)
136+
{
137+
number.RemoveSeparators().AlphaNumericToNumeric().ComputeLuhnNumber();
138+
}
139+
140+
[Benchmark, BenchmarkCategory(ComputeChainCategory)]
141+
[ArgumentsSource(nameof(SeparatedAlphaNumericNumbersAsString))]
142+
public void ComputeChainBasedOnSpan(string number)
143+
{
144+
number.AsSpan().RemoveSeparators().AlphaNumericToNumeric().ComputeLuhnNumber();
145+
}
146+
147+
[Benchmark(Baseline = true), BenchmarkCategory(ValidationChainCategory)]
148+
[ArgumentsSource(nameof(SeparatedAlphaNumericNumbersAsString))]
149+
public void ValidationChainBasedOnString(string number)
150+
{
151+
number.RemoveSeparators().AlphaNumericToNumeric().IsValidLuhnNumber();
152+
}
153+
154+
[Benchmark, BenchmarkCategory(ValidationChainCategory)]
155+
[ArgumentsSource(nameof(SeparatedAlphaNumericNumbersAsString))]
156+
public void ValidationChainBasedOnSpan(string number)
157+
{
158+
number.AsSpan().RemoveSeparators().AlphaNumericToNumeric().IsValidLuhnNumber();
159+
}
160+
}

0 commit comments

Comments
 (0)