Si .Create() no puede crear una instancia, ¿debería devolver un objeto vacío, nulo o generar una excepción?

StackOverflow https://stackoverflow.com/questions/975545

Pregunta

Quiero poder crear una instancia de cualquier objeto en mi aplicación con este tipo de código:

SmartForm smartForm = SmartForm.Create("id = 23");
Customer customer = Customer.Create("id = 222");

Ahora estoy debatiendo qué debería devolver Create() si ese objeto no existe.

  • si Create() devuelve un objeto vacío, entonces esto es una especie de "patrón nulo" y aún puedo pasar ese objeto por mi aplicación y llamar a métodos en él, lo que hace que programar con este modelo sea conveniente y fácil.

  • si Create() regresa nulo, entonces necesito verificar después de cada creación de instancias si el objeto es nulo o no, lo que hace que la programación sea un poco más tediosa pero más explícita.Un problema con esto es que si olvida verificar el valor nulo, su aplicación podría funcionar durante mucho tiempo sin que usted sepa que no está verificando el valor nulo y luego fallar de repente.

  • si crear() lanza una excepción, es básicamente lo mismo que devolver nulo, pero hace que la programación sea aún más tediosa al obligarte a crear un bloque try, next, finalmente para cada instanciación, pero puedes generar varios tipos de excepciones (que no puedes con la solución nula) que podría surgir para que pueda manejar más explícitamente los errores profundos en su interfaz de usuario, por lo que creo que esta es la solución más sólida, aunque produciría un exceso de código de prueba/captura.

Entonces parece ser un equilibrio ligereza/robustez. ¿Alguien tiene alguna experiencia en tomar una decisión en este sentido? ¿Dónde experimentó ventajas o desventajas debido a esa decisión?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestFactory234.Models
{
    public class SmartForm : Item
    {
        public string IdCode { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public int LabelWidth { get; set; }

        public SmartForm() { }

        private SmartForm(string loadCode)
        {
            _loadCode = loadCode;
            TryToInstantiateFromDatabase();
        }

        public static SmartForm Create(string loadCode)
        {
            SmartForm smartForm = new SmartForm(loadCode);

            if (!smartForm.IsEmpty())
            {
                return smartForm;
            }
            else
            {
                return null;
            }
        }
    }
}
¿Fue útil?

Solución

Depende - si falla porque algo está definitivamente mal, entonces una excepción hace que la programación más fácil - no se escribe un try / catch alrededor de cada llamada, que acaba de dejar la excepción burbujear. Compare eso con la comprobación de un valor devuelto nulo / blanco y después lanzar una excepción.

Esto suena como el momento adecuado para usar ArgumentException, la OMI.

Si usted se encuentra la creación de try / catch "hinchazón", echar un vistazo a por qué usted realmente necesita para detectar las excepciones en lugar de dejar que ellos brotan.

Otros consejos

Si se devuelve un objeto blanco, luego podrás proceder asumiendo que es válido - o tener que hacer algún tipo de prueba elaborada para ver si es blanco o no. Si se devuelve un valor nulo que siempre tiene que comprobar NULL (y tal vez eso está bien). Yo preferiría que inició una excepción - el supuesto de que el código está diseñado para que esto no se supone que debe ocurrir. Si se trata de un escenario normal, un valor nulo podría ser una mejor opción.

Cuando el comportamiento por defecto es crear una instancia, entonces el comportamiento excepcional es el error con la creación -> Excepción

¿Qué harías con un EmptyObject? Usted dice que todavía puede pasar alrededor - hace que esto realmente tiene sentido? ¿Qué hacen los métodos, cuando se llama a ellos?

Tal vez debería implementar una segunda TRYCREATE () método.

Me poner en práctica la excepción variante, pero depende de la conducta que necesita.

Su código de muestra llama a un método "intentar cargar desde la base de datos" y la convención Crear se parece mucho a una Castillo ActiveRecord objeto.¿Por qué no separar la operación Obtener/Crear base de datos, permitir que el marco haga el trabajo y confiar en sus convenciones?

[ActiveRecord("Forms")]
public class SmartForm : Item
{
    [PrimaryKey("Id")]
    public string IdCode { get; set; }
    [Property]
    public string Title { get; set; }
    [Property]
    public string Description { get; set; }
    [Property]
    public int LabelWidth { get; set; }
}

Obtienes/creas instancias como esta

SmartForm entity = ActiveRecordMediator<SmartForm>.Find(1);
SmartForm otherEntity = ActiveRecordMediator<SmartForm>.FindFirst(/* criteria */);

Hay muchos otros métodos disponibles para encontrar instancias.Creo que encontrarás que ActiveRecord valores predeterminados acerca de lanzamiento excepciones, que devuelven nulo o, en el caso de colecciones, una colección vacía, son muy consistentes y están bien implementados.

Si va a crear una fábrica de la forma, que sería mejor pasar una enumeración en lugar de una cadena (a menos que, por supuesto, esto representa una arquitectura plug-in).

Si es previsible que la creación puede fallar, pero una gran cantidad de código de la aplicación se va a esperar que va a trabajar, que realmente debe implementar dos versiones del método de creación, uno de los cuales o bien debe tener éxito o lanzar una excepción, y el otro de los cuales es conveniente indicar fallos esperada por algunos medios distintos de lanzar una excepción, y lanzar una excepción sólo para la persona que llama fracasos probablemente no está anticipando (por ejemplo CpuIsOnFireException). Un patrón común para hacer esto es tener un método TRYCREATE devuelve un booleano que indica el éxito, almacenar el argumento creado a un argumento-ref. Yo no me gusta mucho ese patrón, ya que no existe ninguna forma de indicar que no sea un estado de paso a fallar (es decir nada acerca de por qué no) nada. Creo que sería mejor tener un "probar" retorno de la función o bien la nueva cosa o nula, pero tienen un argumento-ref indicando el motivo del fallo. Tenga en cuenta que este enfoque permitiría una mejor utilización de los tipos implícitos (por ejemplo, la palabra clave "var" en C #).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top