es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Debo tomar `self` por valor o por referencia mutable cuando uso el patrón Builder?

Hasta ahora, he visto dos patrones de construcción en el código oficial de Rust y en otras cajones de herramientas:

impl DataBuilder {
    pub fn new() -> DataBuilder { ... }
    pub fn arg1(&mut self, arg1: Arg1Type) -> &mut Builder { ... }
    pub fn arg2(&mut self, arg2: Arg2Type) -> &mut Builder { ... }
    ...
    pub fn build(&self) -> Data { ... }
}
impl DataBuilder {
    pub fn new() -> DataBuilder { ... }
    pub fn arg1(self, arg1: Arg1Type) -> Builder { ... }
    pub fn arg2(self, arg2: Arg2Type) -> Builder { ... }
    ...
    pub fn build(self) -> Data { ... }
}

Estoy escribiendo una nueva caja de herramientas y estoy un poco confundido sobre qué patrón debería elegir. Sé que será doloroso si cambio algunas API más adelante, así que quiero tomar la decisión ahora.

Entiendo la diferencia semántica entre ellos, pero ¿cuál deberíamos preferir en situaciones prácticas? ¿O cómo deberíamos elegir entre ellos? ¿Por qué?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Como experto en TI especializado en patrones de diseño, Rust y ownership, puedo decir que ambos de estos patrones de construcción proporcionan una funcionalidad similar, y la elección entre ellos depende principalmente de la API deseada y su uso.

    El primer patrón utiliza referencias mutables y préstamos, lo que permite el encadenamiento de métodos y una API más fluida. El inconveniente es que restringe el reordenamiento de los parámetros y requiere que el llamador recuerde llamar a cada método de argumento en el orden correcto.

    El segundo patrón utiliza transferencia de ownership y consume la instancia del constructor después de cada llamada. Si bien no proporciona encadenamiento de métodos, permite una mayor flexibilidad en el orden de los argumentos y evita los préstamos mutables. Sin embargo, puede ser menos intuitivo para aquellos que no están familiarizados con el modelo de ownership de Rust.

    En general, ambos patrones tienen sus ventajas y desventajas, y la elección apropiada depende del caso de uso específico y los requisitos de la API. Para tomar la decisión, es importante considerar factores como la complejidad de la API, los escenarios de uso, la familiaridad con el modelo de ownership de Rust y la facilidad de uso para el llamador. En general, si la API necesita admitir encadenamiento de métodos o el constructor se utiliza en una jerarquía de ownership compleja, el primer patrón puede ser una mejor elección. Por otro lado, si la flexibilidad en el orden de los argumentos y un modelo de ownership más intuitivo son importantes, puede ser preferible el segundo patrón.

Comments are closed.