Skip to content

Commit b9edbab

Browse files
committed
Start C# expert track with modularization module
1 parent 6b45468 commit b9edbab

15 files changed

Lines changed: 379 additions & 2 deletions

File tree

LANGUAGE_PARITY_MATRIX.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,17 @@ Current parity progress in non-C++ tracks:
5656
| 4 | inheritance-and-polymorphism | Done | Done | Done | Done |
5757
| 5 | templates-basics | Done | Done | Done | Done |
5858

59-
`04-expert` remains C++ only for now.
59+
`04-expert` has started in C# with `modularization-and-build-structure`; broader expert parity is still planned.
60+
61+
### Expert (`04-expert`) - Early Expansion
62+
63+
| Order | Module | C++ | C# | Go | Python |
64+
| --- | --- | --- | --- | --- | --- |
65+
| 1 | memory-management-and-raii | Done | Planned | Planned | Planned |
66+
| 2 | smart-pointers-in-depth | Done | Planned | Planned | Planned |
67+
| 3 | concurrency-basics | Done | Planned | Planned | Planned |
68+
| 4 | performance-and-profiling-basics | Done | Planned | Planned | Planned |
69+
| 5 | modularization-and-build-structure | Done | Done | Planned | Planned |
6070

6171
## Checkpoint Parity
6272

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# C# 04 Expert
2+
3+
This level is starting experimentally in C# while the rest of expert parity is still in progress.
4+
5+
## Module Order
6+
7+
1. [modularization-and-build-structure](./modularization-and-build-structure/README.md)
8+
2. memory-management-and-raii (planned)
9+
3. smart-pointers-in-depth (planned, language-adapted)
10+
4. concurrency-basics (planned)
11+
5. performance-and-profiling-basics (planned)
12+
13+
Track progress in [../CHECKLIST.md](../CHECKLIST.md).
14+
15+
## Study Tip
16+
17+
Use this module to learn how C# organizes code across files, namespaces, and project references before adding concurrency or performance topics.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Modularization and Build Structure (C#)
2+
3+
This module introduces multi-file organization and project references in C#.
4+
5+
## Quick Run
6+
7+
~~~bash
8+
dotnet run --project example/modularization-and-build-structure-example.csproj
9+
~~~
10+
11+
## Topics Covered
12+
13+
- Splitting domain logic, formatting, and application flow across separate files.
14+
- Grouping reusable code under a namespace.
15+
- Referencing one project from another with `ProjectReference`.
16+
- Keeping console entrypoints thin and coordination-focused.
17+
18+
## Common Pitfalls
19+
20+
- Putting every class into `main.cs` even when responsibilities diverge.
21+
- Mixing formatting, calculations, and input flow in one method.
22+
- Forgetting to include files explicitly when default compile items are disabled.
23+
- Treating project layout as an afterthought instead of part of design.
24+
25+
## Exercise Focus
26+
27+
- exercises/01.cs: separate invoice calculations into focused helper types.
28+
- exercises/02.cs: build reusable command operations consumed by two callers.
29+
30+
### Exercise Specs
31+
32+
1. exercises/01.cs
33+
- Input: subtotal, discount percent, tax percent.
34+
- Output: subtotal breakdown and final total.
35+
- Edge cases: negative subtotal; percentages outside valid ranges.
36+
37+
2. exercises/02.cs
38+
- Input: command name and integer operands.
39+
- Output: result from a reusable operation registry.
40+
- Edge cases: unsupported command; division by zero.
41+
42+
## Checkpoint
43+
44+
- [ ] I can explain why a namespace or project boundary exists.
45+
- [ ] I can separate coordination code from reusable services.
46+
- [ ] I can describe how `ProjectReference` affects a build.
47+
- [ ] I completed exercises/01.cs.
48+
- [ ] I completed exercises/02.cs.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace ModularizationAndBuildStructureExample.Pricing;
5+
6+
public static class InvoiceCalculator
7+
{
8+
public static InvoiceSummary BuildSummary(
9+
IReadOnlyList<LineItem> items,
10+
decimal discountPercent,
11+
decimal fee
12+
)
13+
{
14+
decimal subtotal = 0.0m;
15+
foreach (LineItem item in items)
16+
{
17+
subtotal += item.Total;
18+
}
19+
20+
decimal normalizedDiscount = Math.Clamp(discountPercent, 0.0m, 100.0m);
21+
decimal discountValue = subtotal * normalizedDiscount / 100.0m;
22+
decimal finalTotal = subtotal - discountValue + fee;
23+
24+
return new InvoiceSummary(items, subtotal, discountValue, fee, finalTotal);
25+
}
26+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Text;
2+
3+
namespace ModularizationAndBuildStructureExample.Pricing;
4+
5+
public static class InvoiceFormatter
6+
{
7+
public static string Render(InvoiceSummary summary)
8+
{
9+
StringBuilder builder = new StringBuilder();
10+
11+
builder.AppendLine("Invoice summary");
12+
builder.AppendLine("------------------------------");
13+
foreach (LineItem item in summary.Items)
14+
{
15+
builder.AppendLine(
16+
$"{item.Name, -12} qty={item.Quantity, 2} unit={item.UnitPrice, 6:F2} total={item.Total, 7:F2}"
17+
);
18+
}
19+
20+
builder.AppendLine("------------------------------");
21+
builder.AppendLine($"Subtotal: {summary.Subtotal:F2}");
22+
builder.AppendLine($"Discount: -{summary.DiscountValue:F2}");
23+
builder.AppendLine($"Fee: +{summary.Fee:F2}");
24+
builder.AppendLine($"Final total: {summary.FinalTotal:F2}");
25+
26+
return builder.ToString();
27+
}
28+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections.Generic;
2+
3+
namespace ModularizationAndBuildStructureExample.Pricing;
4+
5+
public sealed class InvoiceSummary
6+
{
7+
public InvoiceSummary(
8+
IReadOnlyList<LineItem> items,
9+
decimal subtotal,
10+
decimal discountValue,
11+
decimal fee,
12+
decimal finalTotal
13+
)
14+
{
15+
Items = items;
16+
Subtotal = subtotal;
17+
DiscountValue = discountValue;
18+
Fee = fee;
19+
FinalTotal = finalTotal;
20+
}
21+
22+
public IReadOnlyList<LineItem> Items { get; }
23+
public decimal Subtotal { get; }
24+
public decimal DiscountValue { get; }
25+
public decimal Fee { get; }
26+
public decimal FinalTotal { get; }
27+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace ModularizationAndBuildStructureExample.Pricing;
2+
3+
public sealed class LineItem
4+
{
5+
public LineItem(string name, int quantity, decimal unitPrice)
6+
{
7+
Name = name;
8+
Quantity = quantity;
9+
UnitPrice = unitPrice;
10+
}
11+
12+
public string Name { get; }
13+
public int Quantity { get; }
14+
public decimal UnitPrice { get; }
15+
public decimal Total => Quantity * UnitPrice;
16+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net8.0</TargetFramework>
4+
<ImplicitUsings>disable</ImplicitUsings>
5+
<Nullable>enable</Nullable>
6+
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
7+
</PropertyGroup>
8+
<ItemGroup>
9+
<Compile Include="LineItem.cs" />
10+
<Compile Include="InvoiceSummary.cs" />
11+
<Compile Include="InvoiceCalculator.cs" />
12+
<Compile Include="InvoiceFormatter.cs" />
13+
</ItemGroup>
14+
</Project>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Example purpose: show the module flow with a separate reusable library project.
2+
3+
using System;
4+
using ModularizationAndBuildStructureExample.Pricing;
5+
6+
class Program
7+
{
8+
static void Main()
9+
{
10+
// Program flow: define input data, delegate calculations, then format a report.
11+
LineItem[] items =
12+
{
13+
new LineItem("Notebook", 2, 3.50m),
14+
new LineItem("Pencil", 5, 0.80m),
15+
new LineItem("Backpack", 1, 29.99m),
16+
};
17+
18+
InvoiceSummary summary = InvoiceCalculator.BuildSummary(items, 10.0m, 7.50m);
19+
20+
// Intent: keep console output in the entrypoint while reusable logic stays in the library.
21+
Console.WriteLine(InvoiceFormatter.Render(summary));
22+
}
23+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>disable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
8+
</PropertyGroup>
9+
<ItemGroup>
10+
<Compile Include="main.cs" />
11+
</ItemGroup>
12+
<ItemGroup>
13+
<ProjectReference Include="PricingModule/PricingModule.csproj" />
14+
</ItemGroup>
15+
</Project>

0 commit comments

Comments
 (0)