Skip to Content
Course content

145: Timed Mock Assessment on Core Rust

Click on the "Edit" button in the top corner of the screen to edit your slide content.

A few years ago, I was mentoring a developer named Sarah who was brilliant at theory. She could explain the difference between Box and Rc in her sleep and could whiteboard a trait hierarchy that would make a senior architect weep with joy. But during our first real-time pairing session to fix a race condition in a production middleware, she froze. It wasn't that she didn't know the language; it was that she had never practiced the "synthesis" phase—the act of pulling five different core concepts together while the clock is ticking and the pressure is on. She knew the notes, but she hadn't played the song.

That's why we're doing this mock assessment. By now, you've spent over a hundred lessons diving into the weeds of ownership, lifetimes, generics, and the standard library. You're comfortable with the syntax. But there is a distinct mental shift that happens when you stop following a guided tutorial and start solving a problem from scratch with a timer running. It forces you to stop overthinking the "perfect" architecture and start implementing the "correct" one.

Bridging the Gap Between Knowledge and Execution

The goal here isn't to trick you with obscure edge cases. I'm not interested in whether you remember the exact signature of a niche function in std::iter. Instead, I want to see if you can instinctively navigate the borrow checker when you're rushing. When we're relaxed, we're patient with the compiler. When we're under pressure, we tend to start throwing .clone() everywhere just to make the red lines go away. I want you to resist that urge. Use this session to see where your "reflexes" fail. If you find yourself fighting a lifetime error for twenty minutes, that's not a failure—it's a diagnostic. It tells us exactly where your mental model of memory management is still a bit fuzzy.

Managing Your Mental Stack During the Clock

In a timed environment, your biggest enemy isn't the code; it's your own anxiety about the time remaining. I've seen developers spend half their allotted time trying to implement a perfectly generic trait for a problem that only requires a simple concrete type. My advice? Build the "ugly" version that works first. In Rust, it's much easier to refactor a working, concrete implementation into a generic one than it is to debug a complex generic system that doesn't compile. Get the logic flowing, ensure the ownership transfers are correct, and only then start polishing the abstractions.

The Strategy for this Assessment

You'll be tasked with building a small but cohesive system. You'll need to handle error propagation using Result, manage shared state—likely requiring an Arc or a Mutex—and implement a trait to ensure extensibility. I suggest you spend the first five minutes just reading the requirements and sketching the data ownership on a piece of paper. Who owns the data? Who is borrowing it? If you can answer those two questions before you type a single character of struct definition, you've already won half the battle.




📋 Practical Task

Implement a Thread-Safe Multi-Producer Single-Consumer (MPSC) Event Logger

Your task is to build a simplified event logging system that can receive messages from multiple threads and write them to a central "log" (a Vec<String>) in a thread-safe manner. You must complete this without using high-level logging crates.

Requirements:

  • Create a Logger struct that holds the shared log state. It must be wrapped in a way that allows multiple threads to mutate the log (think Arc and Mutex).
  • Implement a trait called Loggable with a method to_log_string(&self) -> String.
  • Implement Loggable for at least two different types (e.g., a SystemEvent struct and a UserEvent struct).
  • Create a function process_events that takes a vector of Box<dyn Loggable + Send> and moves them into separate threads, where each thread logs its event to the shared Logger.
  • The final output should be the Logger printing the entire list of accumulated messages in the order they were successfully locked and written.

Constraints: Try to complete this in 60 minutes. Focus on correct ownership transfers and ensuring that no deadlocks occur when multiple threads attempt to access the Mutex.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.