oversized-impl
Level: warn · Article: Structs
A struct with 25 methods is usually three structs that haven’t been separated yet.
What it checks
The inherent impls of one type, in one file, hold more than 20 methods.
Don’t
#![allow(unused)]
fn main() {
struct User {
events: Vec<UserEvent>,
}
impl User {
fn activate(&mut self) {
self.events.push(UserEvent::Activate);
}
fn archive(&mut self) {
self.events.push(UserEvent::Archive);
}
fn ban(&mut self) {
self.events.push(UserEvent::Ban);
}
fn charge(&mut self, amount: Money) {
self.events.push(UserEvent::Charge(amount));
}
fn deactivate(&mut self) {
self.events.push(UserEvent::Deactivate);
}
fn delete(&mut self) {
self.events.push(UserEvent::Delete);
}
fn export(&mut self) {
self.events.push(UserEvent::Export);
}
fn invite(&mut self) {
self.events.push(UserEvent::Invite);
}
fn invoice(&mut self, amount: Money) {
self.events.push(UserEvent::Invoice(amount));
}
fn lock(&mut self) {
self.events.push(UserEvent::Lock);
}
fn notify(&mut self, message: Message) {
self.events.push(UserEvent::Notified(message));
}
fn promote(&mut self) {
self.events.push(UserEvent::Promote);
}
fn refund(&mut self, amount: Money) {
self.events.push(UserEvent::Refund(amount));
}
fn rename(&mut self, name: UserName) {
self.events.push(UserEvent::Renamed(name));
}
fn restore(&mut self) {
self.events.push(UserEvent::Restore);
}
fn subscribe(&mut self) {
self.events.push(UserEvent::Subscribe);
}
fn suspend(&mut self) {
self.events.push(UserEvent::Suspend);
}
fn unban(&mut self) {
self.events.push(UserEvent::Unban);
}
fn unlock(&mut self) {
self.events.push(UserEvent::Unlock);
}
fn unsubscribe(&mut self) {
self.events.push(UserEvent::Unsubscribe);
}
fn upgrade(&mut self) {
self.events.push(UserEvent::Upgrade);
}
}
}
Do
#![allow(unused)]
fn main() {
struct User {
billing: BillingProfile,
events: Vec<UserEvent>,
notifications: NotificationSettings,
}
impl User {
fn ban(&mut self) {
self.events.push(UserEvent::Banned);
}
fn promote(&mut self) {
self.events.push(UserEvent::Promoted);
}
}
struct BillingProfile {
ledger: Vec<Charge>,
}
impl BillingProfile {
fn charge(&mut self, amount: Money) {
self.ledger.push(Charge::Debit(amount));
}
fn invoice(&self) -> Invoice {
Invoice::from_ledger(&self.ledger)
}
fn refund(&mut self, amount: Money) {
self.ledger.push(Charge::Credit(amount));
}
}
struct NotificationSettings {
channels: Vec<Channel>,
}
impl NotificationSettings {
fn notify(&self, message: Message) {
for channel in &self.channels {
channel.send(&message);
}
}
fn subscribe(&mut self, channel: Channel) {
self.channels.push(channel);
}
fn unsubscribe(&mut self, channel: &Channel) {
self.channels.retain(|existing| existing != channel);
}
}
}
Ask which methods operate on a subset of the fields. That subset is its own struct, with five methods that actually belong to it.
Options
[thresholds]
oversized-impl = 20
Silence it
#![allow(unused)]
fn main() {
// rabot: allow(oversized-impl) builder: one method per option is the whole point
impl CommandBuilder { .. }
}