c# · level 3 · unit 7 · lesson 3
- meet it
- guess first
- your turn
- fix it
- nailed it
Tap a green word if you get lost.
meet it
Hand an object what it needs instead of letting it grab it.
A class that builds its own helpers is welded to them. An OpeningHours class that reads the real clock gives a different answer every hour, so nobody can test it. The clock is a : something a class needs to do its job.
means passing dependencies in, usually through the constructor, typed as interfaces. OpeningHours asks for any IClock. The real program hands it one that reads the computer's clock. A test hands it a : a stand-in that always says the same time, so the answer can be checked.
No framework is needed. A constructor and an interface are enough.
using System;
var early = new OpeningHours(new FixedClock(new DateTime(2024, 5, 3, 8, 30, 0)));
var lunch = new OpeningHours(new FixedClock(new DateTime(2024, 5, 3, 12, 15, 0)));
Console.WriteLine($"8:30 {early.Status()}");
Console.WriteLine($"12:15 {lunch.Status()}");
interface IClock { DateTime Now { get; } }
record FixedClock(DateTime Now) : IClock;
class OpeningHours
{
private readonly IClock clock;
public OpeningHours(IClock clock) => this.clock = clock;
public string Status() => clock.Now.Hour switch
{
>= 9 and < 17 => "Open",
_ => "Closed",
};
} The real program would pass a clock whose Now reads the computer's time, and OpeningHours would never know.
guess first
Same greeter, two writers. What will this show?
Guess before you run it. Wrong guesses are how you learn, and nothing is marked.
using System;
var app = new Greeter(new LoudWriter());
app.Greet("Sam");
app = new Greeter(new QuietWriter());
app.Greet("Sam");
interface IWriter { void Write(string text); }
class LoudWriter : IWriter { public void Write(string text) => Console.WriteLine(text.ToUpper() + "!"); }
class QuietWriter : IWriter { public void Write(string text) => Console.WriteLine(text.ToLower()); }
class Greeter
{
private readonly IWriter writer;
public Greeter(IWriter writer) => this.writer = writer;
public void Greet(string name) => writer.Write($"Hello {name}");
}
your turn
Your turn. Test a converter with a fake rate.
On line 10, make the fake return an exchange rate of your choice. On line 16, write the type the constructor should ask for, so any rate source can be plugged in.
output
press run to see what happens
fix it
The order service crashes. Can you fix it?
output
press run to see what happens
- It crashes with
NullReferenceExceptionon line 21. Is theemailfield ever set? - Inside the constructor,
emailmeans the parameter, soemail = emailcopies it onto itself. - Change line 20 to end with
this.email = email;, so the field is set, then run.
nailed it
your classes are ready to be tested. :D
- A dependency is something a class needs to do its job.
- Pass dependencies in through the constructor, as interfaces.
- A fake stands in for the real thing in tests.
new words in your collection
- dependency
- dependency injection
- fake
This lesson isn’t saved. A free account remembers every lesson you finish.