I can distinguish two types of trait, at least for the purpose of naming them in the application I'm developing.
- A role-named trait is named for what it does and may have several implementors. For example,
trait Printablemight have a functionprint()that is implemented by diverse structs suchInvitationandOrder.struct PrintSchedulerhas something likepub fn queue(&mut self, to_be_printed: Arc<Mutex<dyn Printable>>)to queue things to to be printed in due course. - A service interface trait abstracts a single concrete struct so it can be injected and mocked. I've not yet been able to find a Rust-idiomatic way to name such traits. So let's explore one of many real examples from my application.
Tuner is a struct that receives microtuning specifications in a given format, and converts each microtuning into a set of MIDI messages that are then sent to a synthesizer of a particular range of models. From the MIDI messages, the synthesizer's firmware configures its tuning to conform with the required microtuning. To facilitate testing, actually sending the MIDI messages is decoupled from Tuner . We need:
- a struct that can actually send MIDI messages (the production struct);
- a struct that sends no MIDI messages but allows tests to confirm that
Tunerwill send them correctly (the mock struct); - a trait that allows either struct to be injected into
Tuner.
What would you call the two MIDI sender structs and their common trait? The mock struct is the easy one: MockMidiSender. But what about the the production struct and the trait? There are several options.
trait MidiSenderwith something likestruct MidiSenderImplorstruct RealMidiSender. Yet, as the production struct is what actually sends MIDI, we should not have to qualify its name. And I understand that Rust naming guidelines discourageImplsuffixes for structs.struct MidiSenderwith something liketrait MidiSenderTraitortrait MidiSenderBase. It's a trait, so it should not need aTraitsuffix. AndBasesounds like a superclass in object-oriented programming languages, which it not what is going on here.struct MidiSenderwithtrait TMidiSender. I like that. However,Tin Rust is a common type parameter, so perhaps it would be better to avoid it in this context.struct MidiSenderwithtrait IMidiSender, whereIstands for interface and is the standard prefix for interface names, where interface is the equivalent of trait in .NET. This is what I've chosen as the standard for service interface traits in my application. But many Rust developers will understandably not like borrowing from a rather different development technology. I'm an experienced C#/.NET developer and am quite new to Rust.
What would you do?