Решение задач: разбейте задачу на части
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
// Задача: реализация API для GUI
// Вопрос: какое минимальное полезное поведение нужно API для рисования?
pub trait DrawApi {
fn arc(&self, center: [f32; 2], radius: f32, start_angle: f32, end_angle: f32);
fn line(&self, start: [f32; 2], end: [f32; 2]);
}
pub struct TextDraw;
impl DrawApi for TextDraw {
fn arc(&self, center: [f32; 2], radius: f32, start_angle: f32, end_angle: f32) {
println!("arc of radius ")
}
fn line(&self, start: [f32; 2], end: [f32; 2]) { /* ... */
}
}
// Вопрос: какой API будет удобен пользователям?
pub trait Draw {
fn draw<T: DrawApi>(&self, surface: &mut T);
}
pub struct Rect {
start: [f32; 2],
end: [f32; 2],
}
impl Draw for Rect {
fn draw<T: DrawApi>(&self, surface: &mut T) {
surface.line([self.start[0], self.start[1]], [self.end[0], self.start[1]]);
surface.line([self.end[0], self.start[1]], [self.end[0], self.end[1]]);
surface.line([self.end[0], self.end[1]], [self.start[0], self.end[1]]);
surface.line([self.start[0], self.end[1]], [self.start[0], self.start[1]]);
}
}
- Вы уже умеете разбивать задачи на части, но, скорее всего, привыкли опираться на методы в стиле ООП.
Это не кардинальное изменение: нужно лишь переставить порядок, в котором вы подходите к задачам.
-
Сначала попробуйте решить задачу с помощью обобщений и трейтов или перечислений.
Требует ли задача определённого набора типов? Перечисление может оказаться самым чистым способом её решения.
Действительно ли задаче важны конкретные детали задействованных типов или можно сосредоточиться на поведении?
-
Выстраивайте решение задач вокруг поиска минимального достаточного объёма знаний для реализации чего-либо.
Существует ли уже трейт для этого случая? Если да, используйте его!
-
Если вам действительно нужны разнородные коллекции, используйте их! В Rust они существуют как инструмент не просто так.
Остерегайтесь XY-проблемы: задача может казаться легче всего решаемой одним способом, но это решение может не затрагивать первопричину и привести к новым трудным проблемам в будущем.
То есть прежде чем использовать динамическую диспетчеризацию с объектами трейтов, убедитесь, что она действительно нужна.
Прежде чем использовать трейты, убедитесь, что они действительно нужны.