2024-02-20 00:45:01
Salut tout le monde!
J’ai une bibliothèque qui analyse les chansons. J’ai actuellement un objet Song, comme celui-ci (j’ai simplifié les choses), qui utilise ffmpeg (un décodeur audio tiers) pour décoder la chanson ; ma bibliothèque utilise ensuite cette chanson décodée pour l’analyser :
pub struct Chanson { titre de pub : Option
pub fn depuis_chemin
pub(crate) fn décoder(chemin : &Chemin) -> BlissResult
99% de mes utilisateurs voudront utiliser cette fonctionnalité “ffmpeg”, car ils ne se soucient pas de la façon dont une chanson est décodée, ils veulent juste passer du chemin de la chanson à la chanson analysée.
Cependant, ce serait bien si les 1% restants pouvaient se désinscrire de la dépendance à ffmpeg et décoder les chansons comme bon leur semble.
J’ai joué avec quelque chose comme ça :
pub trait Décoder { fn décoder (chemin : & Chemin) -> BlissResult
impl Decode for Song {fn decode(chemin : &Path) -> BlissResult
Cependant, je vois au moins deux problèmes à ce sujet :
- Je dois rendre publique la structure InternalSong, ce qui, j’en ai peur, risque de dérouter les utilisateurs (dois-je utiliser Song ? InternalSong ?). J’ai de la documentation, mais j’ai peur que cela crée plus de frictions que nécessaire
- Et plus important encore, cela signifie que c’est un changement radical pour les utilisateurs actuels, qui devront commencer à ajouter use crate::song::Decode partout où ils souhaitent utiliser Song::from_path (c’est-à-dire à chaque fois qu’ils veulent utiliser ma bibliothèque)
Donc, dans l’ensemble, j’ai peur de créer beaucoup plus de frictions inutiles pour 99 % des utilisateurs, juste pour que 1 % puissent profiter d’une interface agréable pour implémenter leur propre mécanisme de décodage.
Existe-t-il un autre moyen d’obtenir le meilleur des deux mondes ? C’est-à-dire laisser certains utilisateurs implémenter leur propre décodage et avoir tout intégré à Song::from_path (d’autres parties de la bibliothèque l’utilisent sur toute la ligne, donc ce serait très bien d’implémenter simplement le décodage et ensuite tout le reste fonctionne à partir de là), tandis que conserver la compatibilité pour le reste ?
Je pense qu’il me manque peut-être une autre belle abstraction de Rust
Acclamations!
moy2010 19 février 2024, 21h00 2
Vous pouvez activer la fonctionnalité ffmpeg par défaut et permettre à 1 % des utilisateurs de se désinscrire en la désactivant.
jofas 19 février 2024, 21h12 3 rue Polochon_:
#[cfg(feature = “ffmpeg”)]
impl Decode for Song {fn decode(chemin : &Path) -> BlissResult{ // Code spécifique à ffmpeg } }
Ne serait-il pas plus logique d’avoir un trait Decoder et de l’implémenter pour un type Ffmpeg que vous pourriez cacher derrière une porte de fonctionnalités ? Que se passe-t-il si les gens souhaitent prendre en charge plusieurs décodeurs ? Avec votre interface, ils ne pourraient pas faire ça. Cela dissocierait également votre morceau de la fonctionnalité de décodage, vous permettant ainsi de mieux masquer les détails crasseux du décodage dans votre API publique.
Quant à vos deux points (I) avoir un InternalSong / un autre type vers lequel le décodeur décode, cette conception ne me dérangerait pas. La mise en œuvre d’un décodeur sera quelque chose que seuls les utilisateurs experts de votre caisse feront, donnez-leur un exemple (ou simplement un lien vers vos implémentations existantes) et ils le comprendront. Et (II) casser votre interface actuelle : je ne sais pas sur quelle version vous êtes actuellement, mais si vous avez une version 0.*, cela ne me dérangerait pas de casser un peu votre interface. C’est le contrat des versions 0.*, elles ne sont pas censées offrir des garanties de stabilité à long terme (bien que certaines le fassent).
#Méthode #appropriée #pour #extraire #fournisseur #tiers #aide
1708381930