funcion español c# .net function return-value

c# - español - ¿Deberían las funciones volver nulas o un objeto vacío?



return c# español (30)

¿Cuál es la mejor práctica cuando se devuelven datos desde funciones? ¿Es mejor devolver un objeto nulo o vacío? ¿Y por qué uno debería hacer uno sobre el otro?

Considera esto:

public UserEntity GetUserById(Guid userId) { //Imagine some code here to access database..... //Check if data was returned and return a null if none found if (!DataExists) return null; //Should I be doing this here instead? //return new UserEntity(); else return existingUserEntity; }

Vamos a pretender que habría casos válidos en este programa que no habría información de usuario en la base de datos con ese GUID. Me imagino que no sería apropiado lanzar una excepción en este caso? También tengo la impresión de que el manejo de excepciones puede dañar el rendimiento.


Un patrón TryGet asíncrono:

Para los métodos sincrónicos, creo que answer es el patrón a utilizar en todos los casos.

Sin embargo, el patrón TryGet con el outparámetro no funciona con métodos asíncronos.

Con Tuple Literals de C # 7 ahora puedes hacer esto:

async Task<(bool success, SomeObject o)> TryGetSomeObjectByIdAsync(Int32 id) { if (InternalIdExists(id)) { o = await InternalGetSomeObjectAsync(id); return (true, o); } else { return (false, default(SomeObject)); } }


Debe lanzar una excepción (solo) si se rompe un contrato específico.
En su ejemplo específico, pedir una UserEntity basada en una identificación conocida, dependería del hecho si faltan (eliminados) los usuarios son un caso esperado. Si es así, devuelva el null pero si no es un caso esperado, lance una excepción.
Tenga en cuenta que si la función se llamara UserEntity GetUserByName(string name) probablemente no se lanzará pero devolverá el valor nulo. En ambos casos, devolver una UserEntity vacía sería inútil.

Para cadenas, matrices y colecciones, la situación suele ser diferente. Recuerdo algunas pautas de MS que los métodos deberían aceptar null como una lista "vacía" pero devolver colecciones de longitud cero en lugar de null . Lo mismo para cuerdas. Tenga en cuenta que puede declarar matrices vacías: int[] arr = new int[0];


Depende de lo que tenga más sentido para su caso.

¿Tiene sentido devolver el valor nulo, por ejemplo, "no existe tal usuario"?

¿O tiene sentido crear un usuario predeterminado? Esto tiene más sentido cuando puede asumir con seguridad que si un usuario NO existe, el código de llamada pretende que exista uno cuando lo soliciten.

¿O tiene sentido lanzar una excepción (a la "FileNotFound") si el código que llama exige un usuario con una ID no válida?

Sin embargo, desde un punto de vista de separación / preocupación, los dos primeros son más correctos. Y técnicamente, el primero es el más correcto (pero solo por un pelo): GetUserById solo debe ser responsable de una cosa: obtener el usuario. El manejo de su propio caso de "usuario no existe" devolviendo algo más podría ser una violación de SRP. Separar en un cheque diferente - bool DoesUserExist(id) sería apropiado si elige lanzar una excepción.

Basado en los comentarios extensos a continuación : si esta es una pregunta de diseño de nivel de API, este método podría ser análogo a "OpenFile" o "ReadEntireFile". Estamos "abriendo" un usuario desde algún repositorio e hidratando el objeto de los datos resultantes. Una excepción podría ser apropiada en este caso. Puede que no lo sea, pero podría serlo.

Todos los enfoques son aceptables, solo depende, en función del contexto más amplio de la API / aplicación.


Devolver el valor nulo suele ser la mejor idea si pretende indicar que no hay datos disponibles.

Un objeto vacío implica que se han devuelto datos, mientras que devolver nulo indica claramente que no se ha devuelto nada.

Además, devolver un valor nulo dará como resultado una excepción nula si intenta acceder a miembros en el objeto, lo que puede ser útil para resaltar el código con errores: intentar acceder a un miembro de la nada no tiene sentido. El acceso a los miembros de un objeto vacío no fallará, lo que significa que los errores no se pueden descubrir.


En este caso, lo mejor es devolver "nulo" en un caso en el que no exista tal usuario. También haz tu método estático.

Editar:

Generalmente, los métodos como este son miembros de alguna clase de "Usuario" y no tienen acceso a sus miembros de instancia. En este caso, el método debe ser estático; de lo contrario, debe crear una instancia de "Usuario" y luego llamar al método GetUserById que devolverá otra instancia de "Usuario". De acuerdo esto es confuso. Pero si el método GetUserById es miembro de alguna clase "DatabaseFactory", no hay problema para dejarlo como miembro de instancia.


En nuestros Business Objects tenemos 2 métodos principales de Get:

Para mantener las cosas simples en el contexto o si cuestionas que serían:

// Returns null if user does not exist public UserEntity GetUserById(Guid userId) { } // Returns a New User if user does not exist public UserEntity GetNewOrExistingUserById(Guid userId) { }

El primer método se usa al obtener entidades específicas, el segundo método se usa específicamente al agregar o editar entidades en páginas web.

Esto nos permite tener lo mejor de ambos mundos en el contexto en el que se utilizan.


Esta es una pregunta de negocios, depende de si la existencia de un usuario con un Id. Guid específico es un caso de uso normal esperado para esta función, o si es una anomalía que evitará que la aplicación complete con éxito cualquier función que este método le proporcione al usuario. oponerse a...

Si se trata de una "excepción", la ausencia de un usuario con esa identificación evitará que la aplicación complete con éxito cualquier función que esté realizando (supongamos que estamos creando una factura para un cliente que enviamos el producto a ... ), entonces esta situación debería lanzar una excepción ArgumentException (o alguna otra excepción personalizada).

Si un usuario faltante está bien, (uno de los posibles resultados normales de llamar a esta función) devuelve un nulo ...

EDITAR: (para abordar el comentario de Adam en otra respuesta)

Si la aplicación contiene varios procesos de negocios, uno o más de los cuales requieren un Usuario para completar con éxito, y uno o más de los cuales pueden completarse con éxito sin un usuario, la excepción debe ser lanzada más arriba en la pila de llamadas, más cerca de donde los procesos de negocio que requieren un Usuario están llamando a este hilo de ejecución. Los métodos entre este método y ese punto (donde se lanza la excepción) deben comunicar que no existe ningún usuario (nulo, booleano, lo que sea, este es un detalle de la implementación).

Pero si todos los procesos dentro de la aplicación requieren un usuario, yo todavía lanzaría la excepción en este método ...


Normalmente vuelvo nulo. Proporciona un mecanismo rápido y fácil para detectar si algo se equivocó sin lanzar excepciones y usar toneladas de try / catch en todo el lugar.


Otro enfoque más consiste en pasar un objeto de devolución de llamada o delegado que operará en el valor. Si no se encuentra un valor, no se llama a la devolución de llamada.

public void GetUserById(Guid id, UserCallback callback) { // Lookup user if (userFound) callback(userEntity); // or callback.Call(userEntity); }

Esto funciona bien cuando quiere evitar las comprobaciones nulas en todo su código, y cuando no encuentra un valor no es un error. También puede proporcionar una devolución de llamada para cuando no se encuentren objetos si necesita un procesamiento especial.

public void GetUserById(Guid id, UserCallback callback, NotFoundCallback notFound) { // Lookup user if (userFound) callback(userEntity); // or callback.Call(userEntity); else notFound(); // or notFound.Call(); }

El mismo enfoque que utiliza un solo objeto podría tener el siguiente aspecto:

public void GetUserById(Guid id, UserCallback callback) { // Lookup user if (userFound) callback.Found(userEntity); else callback.NotFound(); }

Desde una perspectiva de diseño, me gusta mucho este enfoque, pero tiene la desventaja de hacer que el sitio de llamadas sea más amplio en idiomas que no admiten fácilmente funciones de primera clase.


Para los tipos de colección, devolvería una Colección vacía, para todos los demás tipos, prefiero usar los patrones NullObject para devolver un objeto que implemente la misma interfaz que la del tipo devuelto. para detalles sobre el patrón, echa un vistazo al texto del enlace

Usando el patrón NullObject esto sería: -

public UserEntity GetUserById(Guid userId)

{// Imagina algo de código aquí para acceder a la base de datos ...

//Check if data was returned and return a null if none found if (!DataExists) return new NullUserEntity(); //Should I be doing this here instead? return new UserEntity(); else return existingUserEntity;

}

class NullUserEntity: IUserEntity { public string getFirstName(){ return ""; } ...}


Para poner lo que otros han dicho de una manera concisa ...

Las excepciones son para circunstancias excepcionales.

Si este método es pura capa de acceso a datos, diría que dado un parámetro que se incluye en una declaración de selección, esperaría que no encontrase ninguna fila desde la cual construir un objeto, y por lo tanto, devolver un valor nulo sería aceptable ya que Es la lógica de acceso a los datos.

Por otro lado, si esperaba que mi parámetro reflejara una clave principal y solo obtuviera una fila atrás, si obtenía más de una copia atrás, lanzaría una excepción. 0 está bien para devolver nulo, 2 no lo es.

Ahora, si tuviera algún código de inicio de sesión que se comparara con un proveedor de LDAP y luego con una base de datos para obtener más detalles y esperaba que estuvieran sincronizados en todo momento, podría lanzar la excepción en ese momento. Como han dicho otros, son las reglas del negocio.

Ahora diré que es una regla general . Hay momentos en los que puede querer romper eso. Sin embargo, mi experiencia y experimentos con C # (mucho de eso) y Java (un poco de eso) me han enseñado que es mucho más costoso en términos de rendimiento tratar con excepciones que manejar problemas predecibles mediante lógica condicional. Estoy hablando con la melodía de 2 o 3 órdenes de magnitud más caras en algunos casos. Por lo tanto, si es posible que su código pueda terminar en un bucle, entonces le aconsejaría que devuelva el valor nulo y lo pruebe.


Perdona mi pseudo-php / code.

Creo que realmente depende del uso previsto del resultado.

Si pretende editar / modificar el valor de retorno y guardarlo, devuelva un objeto vacío. De esa manera, puede utilizar la misma función para rellenar datos en un objeto nuevo o existente.

Digamos que tengo una función que toma una clave principal y una matriz de datos, llena la fila con datos y luego guarda el registro resultante en la db. Ya que tengo la intención de rellenar el objeto con mis datos de cualquier manera, puede ser una gran ventaja obtener un objeto vacío de vuelta del captador. De esa manera, puedo realizar operaciones idénticas en cualquier caso. Usas el resultado de la función getter sin importar qué.

Ejemplo:

function saveTheRow($prim_key, $data) { $row = getRowByPrimKey($prim_key); // Populate the data here $row->save(); }

Aquí podemos ver que la misma serie de operaciones manipula todos los registros de este tipo.

Sin embargo, si la intención final del valor de retorno es leer y hacer algo con los datos, entonces devolvería el valor nulo. De esta manera, puedo determinar rápidamente si no se devolvieron datos y mostrar el mensaje apropiado al usuario.

Por lo general, detecto excepciones en mi función que recupera los datos (para poder registrar mensajes de error, etc.) y luego devolveré el valor nulo directamente desde el retén. En general, no le importa al usuario final cuál es el problema, por lo que me parece mejor encapsular mi registro / procesamiento de errores directamente en la función que obtiene los datos. Si mantiene una base de código compartida en una compañía grande, esto es especialmente beneficioso porque puede forzar el correcto registro / manejo de errores incluso en el programador más perezoso.

Ejemplo:

function displayData($row_id) { // Logging of the error would happen in this function $row = getRow($row_id); if($row === null) { // Handle the error here } // Do stuff here with data } function getRow($row_id) { $row = null; try{ if(!$db->connected()) { throw excpetion("Couldn''t Connect"); } $result = $db->query($some_query_using_row_id); if(count($result) == 0 ) { throw new exception("Couldn''t find a record!"); } $row = $db->nextRow(); } catch (db_exception) { //Log db conn error, alert admin, etc... return null; // This way I know that null means an error occurred } return $row; }

Esa es mi regla general. Ha funcionado bien hasta ahora.


Personalmente, devolvería el valor nulo, porque así es como esperaría que actuara la capa DAL / Repositorio.

Si no existe, no devuelva nada que pueda interpretarse como una obtención exitosa de un objeto, la null funciona a la perfección aquí.

Lo más importante es ser consistente en la capa DAL / Repos, para que no se confunda sobre cómo usarlo.


Personalmente, yo uso NULL. Deja claro que no hay datos para devolver. Pero hay casos en que un objeto nulo puede ser útil.


Prefiero null , ya que es compatible con el operador de unión nula ( ?? ).


Si el caso de que no se encuentre al usuario aparece con la frecuencia suficiente, y usted quiere lidiar con eso de varias maneras dependiendo de las circunstancias (a veces lanzando una excepción, a veces sustituyendo a un usuario vacío), también podría usar algo parecido a la Option F # o Haskell. Maybe tipo, que separa explícitamente el caso "sin valor" de "¡encontré algo!". El código de acceso a la base de datos podría verse así:

public Option<UserEntity> GetUserById(Guid userId) { //Imagine some code here to access database..... //Check if data was returned and return a null if none found if (!DataExists) return Option<UserEntity>.Nothing; else return Option.Just(existingUserEntity); }

Y ser usado de esta manera:

Option<UserEntity> result = GetUserById(...); if (result.IsNothing()) { // deal with it } else { UserEntity value = result.GetValue(); }

Desafortunadamente, todo el mundo parece rodar un tipo como este.


Si su tipo de retorno es una matriz, devuelva una matriz vacía; de lo contrario, devuelva nulo.


Soy un estudiante francés de informática, así que disculpa mi pobre inglés. En nuestras clases se nos dice que tal método nunca debe devolver un valor nulo, ni un objeto vacío. Se supone que el usuario de este método debe verificar primero que el objeto que está buscando existe antes de intentar obtenerlo.

Usando Java, se nos pide que agreguemos una assert exists(object) : "You shouldn''t try to access an object that doesn''t exist"; al comienzo de cualquier método que pudiera devolver nulo, para expresar la "condición previa" (no sé cuál es la palabra en inglés).

OMI, esto no es realmente fácil de usar, pero eso es lo que estoy usando, esperando algo mejor.


Usamos CSLA.NET, y toma la opinión de que una recuperación de datos fallida debería devolver un objeto "vacío". Esto es en realidad bastante molesto, ya que exige la convención de verificar si obj.IsNew lugar de obj == null .

Como se mencionó en un póster anterior, los valores de retorno nulos harán que el código falle de inmediato, reduciendo la probabilidad de problemas ocultos causados ​​por objetos vacíos.

Personalmente, creo que null es más elegante.

Es un caso muy común, y me sorprende que la gente aquí se vea sorprendida por ello: en cualquier aplicación web, los datos a menudo se obtienen mediante un parámetro de cadena de consulta, que obviamente puede modificarse, por lo que es necesario que el desarrollador maneje las incidencias de "no encontrado". ".

Usted podría manejar esto por:

if (User.Exists(id)) { this.User = User.Fetch(id); } else { Response.Redirect("~/notfound.aspx"); }

... pero esa es una llamada adicional a la base de datos cada vez, lo que puede ser un problema en las páginas de alto tráfico. Mientras:

this.User = User.Fetch(id); if (this.User == null) { Response.Redirect("~/notfound.aspx"); }

... requiere una sola llamada.


Variará según el contexto, pero generalmente devolveré nulo si busco un objeto en particular (como en su ejemplo) y devolveré una colección vacía si busco un conjunto de objetos pero no hay ninguno.

Si ha cometido un error en su código y devolver nulos lleva a excepciones de puntero nulo, cuanto antes lo detecte, mejor. Si devuelve un objeto vacío, su uso inicial puede funcionar, pero puede obtener errores más adelante.


Yo diría que devuelva nulo en lugar de un objeto vacío.

Pero en la instancia específica que mencionó aquí, está buscando un usuario por ID de usuario, que es una especie de clave para ese usuario, en ese caso probablemente querría lanzar una excepción si no se encuentra una instancia de instancia de usuario .

Esta es la regla que generalmente sigo:

  • Si no se encuentra ningún resultado en una operación de búsqueda por clave principal, lance la excepción ObjectNotFoundException.
  • Si no se encontró ningún resultado en una búsqueda por ningún otro criterio, devuelva nulo.
  • Si no se encuentran resultados en una búsqueda por un criterio no clave que puede devolver un objeto múltiple, devuelve una colección vacía.

Yo personalmente devuelvo una instancia predeterminada del objeto. La razón es que espero que el método devuelva cero a muchos o cero a uno (dependiendo del propósito del método). La única razón por la que sería un estado de error de cualquier tipo, utilizando este enfoque, es si el método no devolvió ningún objeto (s) y siempre se esperó que (en términos de un retorno de uno a muchos o singular).

En cuanto a la suposición de que esta es una pregunta de dominio empresarial, simplemente no la veo desde ese lado de la ecuación. La normalización de los tipos de retorno es una pregunta válida de la arquitectura de la aplicación. Como mínimo, está sujeto a la estandarización en las prácticas de codificación. Dudo que exista un usuario de negocios que diga "en el escenario X, simplemente déles un nulo".


tiendo a

  • return null si la identificación del objeto no existe cuando no se sabe de antemano si debería existir.
  • throw si la identificación del objeto no existe cuando debería existir.

Diferencio estos dos escenarios con estos tres tipos de métodos. Primero:

Boolean TryGetSomeObjectById(Int32 id, out SomeObject o) { if (InternalIdExists(id)) { o = InternalGetSomeObject(id); return true; } else { return false; } }

Segundo:

SomeObject FindSomeObjectById(Int32 id) { SomeObject o; return TryGetObjectById(id, out o) ? o : null; }

Tercero:

SomeObject GetSomeObjectById(Int32 id) { SomeObject o; if (!TryGetObjectById(id, out o)) { throw new SomeAppropriateException(); } return o; }


Si el objeto devuelto es algo que se puede iterar, devolvería un objeto vacío, para que no tenga que probar primero el valor nulo.

Ejemplo:

bool IsAdministrator(User user) { var groupsOfUser = GetGroupsOfUser(user); // This foreach would cause a run time exception if groupsOfUser is null. foreach (var groupOfUser in groupsOfUser) { if (groupOfUser.Name == "Administrators") { return true; } } return false; }


Creo que las funciones no deben devolver nulo, por la salud de su base de código. Puedo pensar en algunas razones:

Habrá una gran cantidad de cláusulas de protección que tratarán la referencia nula if (f() != null).

¿Qué es null, es una respuesta aceptada o un problema? ¿Es nulo un estado válido para un objeto específico? (Imagina que eres un cliente para el código). Me refiero a que todos los tipos de referencia pueden ser nulos, pero ¿deberían?

Tener tiempo nulldando vueltas casi siempre dará algunas excepciones inesperadas de NullRef de vez en cuando a medida que su base de código crezca.

Hay algunas soluciones, tester-doer patterno la implementación de la option typeprogramación funcional.


Estoy de acuerdo con la mayoría de los mensajes aquí, que tienden a null.

Mi razonamiento es que generar un objeto vacío con propiedades no anulables puede causar errores. Por ejemplo, una entidad con una int IDpropiedad tendría un valor inicial de ID = 0, que es un valor totalmente válido. Si ese objeto, bajo alguna circunstancia, se guarda en la base de datos, sería algo malo.

Para cualquier cosa con un iterador siempre usaría la colección vacía. Algo como

foreach (var eachValue in collection ?? new List<Type>(0))

Es el código de olor en mi opinión. Las propiedades de colección no deberían ser nulas, nunca.

Un caso de borde es String. Mucha gente dice String.IsNullOrEmptyque no es realmente necesario, pero no siempre se puede distinguir entre una cadena vacía y una nula. Además, algunos sistemas de base de datos (Oracle) no los distinguen en absoluto ( ''''se almacenan como DBNULL), por lo que se ven obligados a manejarlos por igual. El motivo es que la mayoría de los valores de cadena provienen de la entrada del usuario o de sistemas externos, mientras que ni los cuadros de texto ni la mayoría de los formatos de intercambio tienen representaciones diferentes para ''''y null. Entonces, incluso si el usuario desea eliminar un valor, no puede hacer nada más que borrar el control de entrada. Además, la distinción de nvarcharcampos de base de datos que admiten nulos y que no admiten nulos es más que cuestionable, si su DBMS no es Oracle, un campo obligatorio que permite''''es extraño, su interfaz de usuario nunca lo permitiría, por lo que sus restricciones no se asignan. Así que la respuesta aquí, en mi opinión es, manejarlos por igual, siempre.

Con respecto a su pregunta con respecto a las excepciones y el rendimiento: si lanza una excepción que no puede manejar por completo en la lógica de su programa, tiene que abortar, en algún momento, lo que sea que esté haciendo su programa y pedirle al usuario que rehaga lo que acaba de hacer. En ese caso, la penalización de rendimiento de a catches realmente la menor de sus preocupaciones: tener que preguntar al usuario es el elefante en la habitación (lo que significa volver a renderizar la IU completa o enviar algo de HTML a través de Internet). Por lo tanto, si no sigue el patrón de " Flujo de programa con excepciones ", no se moleste, simplemente lance uno si tiene sentido. Incluso en casos límite, como "Excepción de validación", el rendimiento realmente no es un problema, ya que, en cualquier caso, debe preguntar al usuario nuevamente.


Estoy perplejo ante la cantidad de respuestas (en toda la web) que dicen que necesita dos métodos: un método "IsItThere ()" y un método "GetItForMe ()" y por lo tanto esto conduce a una condición de carrera. ¿Qué está mal con una función que devuelve nulo, asignándola a una variable y verificando si la variable es nula en una sola prueba? Mi antiguo código C estaba salpicado de

if (NULL! = (variable = function (argumentos ...))) {

Así que obtienes el valor (o nulo) en una variable, y el resultado todo a la vez. ¿Se ha olvidado este idioma? ¿Por qué?


Más carne para moler: digamos que mi DAL devuelve un NULL para GetPersonByID según lo recomendado por algunos. ¿Qué debería hacer mi BLL (más bien delgado) si recibe un valor NULL? ¿Pasa ese NULL y deja que el consumidor final se preocupe por eso (en este caso, una página de ASP.Net)? ¿Qué tal si el BLL lanza una excepción?

ASP.Net y Win App, u otra biblioteca de clases, puede utilizar el BLL. Creo que es injusto esperar que el consumidor final "sepa" intrínsecamente que el método GetPersonByID devuelve un valor nulo (a menos que se utilicen tipos nulos, supongo ).

Mi opinión (para lo que vale) es que mi DAL devuelve NULL si no se encuentra nada. PARA ALGUNOS OBJETOS, está bien, podría ser un 0: muchos lista de cosas, así que no tener nada está bien (por ejemplo, una lista de libros favoritos). En este caso, mi BLL devuelve una lista vacía. Para la mayoría de las cosas de entidades individuales (por ejemplo, usuario, cuenta, factura) si no tengo una, eso definitivamente es un problema y una excepción costosa. Sin embargo, ver como recuperar un usuario por un identificador único que fue dado previamente por la aplicación siempre debería devolver un usuario, la excepción es una excepción "adecuada", como en su caso excepcional. El consumidor final de la BLL (ASP.Net, f''rinstance) solo espera que las cosas sean extrañas, por lo que se usará un Controlador de Excepciones no Controlado en lugar de envolver cada llamada a GetPersonByID en un bloque try-catch.

Si hay un problema evidente en mi enfoque, hágamelo saber ya que siempre estoy dispuesto a aprender. Como han dicho otros carteles, las excepciones son costosas, y el enfoque de "verificar primero" es bueno, pero las excepciones deberían ser solo eso, excepcionales.

Estoy disfrutando de esta publicación, muchas buenas sugerencias para los escenarios "depende" :-)


No me gusta devolver el valor nulo de ningún método, sino usar el tipo de opción funcional en su lugar. Los métodos que no pueden devolver ningún resultado devuelven una Opción vacía, en lugar de un valor nulo.

Además, los métodos que pueden devolver ningún resultado deberían indicar eso a través de su nombre. Normalmente pongo Try o TryGet o TryFind al principio del nombre del método para indicar que puede devolver un resultado vacío (por ejemplo, TryFindCustomer, TryLoadFile, etc.).

Eso permite que la persona que llama aplique diferentes técnicas, como la canalización de la colección (consulte la sección Pipeline de Martin Fowler ) en el resultado.

Este es otro ejemplo donde se usa la opción de retorno en lugar de nula para reducir la complejidad del código: Cómo reducir la complejidad ciclomática: Tipo funcional de la opción


Pregunta interesante y creo que no hay una respuesta "correcta", ya que siempre depende de la responsabilidad de su código. ¿Sabe su método si no hay datos encontrados es un problema o no? En la mayoría de los casos, la respuesta es "no" y es por eso que devolver la nulidad y dejar que la persona que llama maneje la situación es perfecto.

Tal vez un buen enfoque para distinguir los métodos de lanzamiento de los métodos de devolución nula es encontrar una convención en su equipo: los métodos que dicen que "obtienen" algo deberían generar una excepción si no hay nada que obtener. Los métodos que pueden devolver nulo podrían tener un nombre diferente, tal vez "Buscar ..." en su lugar.