app.rs
Let’s start with the same struct
as we had before:
/// Application.#[derive(Debug, Default)]pub struct App { /// should the application exit? pub should_quit: bool, /// counter pub counter: u8,}
We can add additional methods to this Application
struct:
impl App { /// Constructs a new instance of [`App`]. pub fn new() -> Self { Self::default() }
/// Handles the tick event of the terminal. pub fn tick(&self) {}
/// Set should_quit to true to quit the application. pub fn quit(&mut self) { self.should_quit = true; }
pub fn increment_counter(&mut self) { if let Some(res) = self.counter.checked_add(1) { self.counter = res; } }
pub fn decrement_counter(&mut self) { if let Some(res) = self.counter.checked_sub(1) { self.counter = res; } }}
We use the principle of encapsulation to expose an interface to modify the state. In this particular instance, it may seem like overkill but it is good practice nonetheless.
The practical advantage of this is that it makes the state changes easy to test.
#[cfg(test)]mod tests { use super::*; #[test] fn test_app_increment_counter() { let mut app = App::default(); app.increment_counter(); assert_eq!(app.counter, 1); }
#[test] fn test_app_decrement_counter() { let mut app = App::default(); app.decrement_counter(); assert_eq!(app.counter, 0); }}