una tutorial puede proyecto polimorfismo interfaz interfaces instancia implementación implementacion herencia crear clase abstracta c# unit-testing interface dependency-injection project-organization

tutorial - no se puede crear una instancia de la clase o interfaz abstracta c#



¿Dónde pongo todas estas interfaces? (5)

Estoy tratando de mojarme los pies con la prueba de la unidad. Actualmente no estoy acostumbrado a escribir interfaces para clases a menos que prevea alguna razón por la que necesitaría cambiar en una implementación diferente. Bueno, ahora preveo una razón: la burla.

Dado que voy a pasar de unas pocas interfaces a quizás cientos, lo primero que me vino a la cabeza fue: ¿Dónde debería colocar todas estas interfaces? ¿Simplemente los mezclo con todas las implementaciones concretas o debo colocarlas en una subcarpeta? Por ejemplo, ¿las interfaces del controlador deben ir a raíz / Controladores / Interfaces, raíz / Controladores, o alguna otra cosa completamente? ¿Qué recomiendas?


Antes de discutir la organización:

Bueno, ahora preveo una razón: la burla.

Puedes burlarte de las clases, también. La subclasificación funciona bien para simularse como una opción en lugar de hacer siempre interfaces.

Las interfaces son increíblemente útiles, pero recomendaría que solo se haga una interfaz si hay una razón para hacer una interfaz. A menudo veo interfaces creadas cuando una clase funcionaría bien y sería más apropiada en términos de lógica. No deberías tener que crear "cientos de interfaces" solo para permitirte simular implementaciones: la encapsulación y la subclase funcionan bastante bien para eso.

Dicho esto, normalmente organizaré mis interfaces junto con mis clases, ya que agrupar tipos relacionados en los mismos espacios de nombres tiende a tener más sentido. La excepción principal es con las implementaciones internas de interfaces, que pueden estar en cualquier lugar, pero a veces crearé una carpeta "Interna" + un espacio de nombres interno que uso específicamente para implementaciones de interfaces "privadas" (así como otras clases que son implementaciones puramente internas ). Esto me ayuda a mantener el espacio de nombres principal despejado, por lo que los únicos tipos son los tipos principales relacionados con la API en sí.



Aquí hay una sugerencia: si la mayoría de las interfaces admiten solo una clase, solo agregue la interfaz al mismo archivo que la clase en el mismo espacio de nombres. De esa manera, no tiene un archivo separado para la interfaz que realmente podría saturar el proyecto o necesitar una subcarpeta solo para interfaces.

Si se encuentra creando diferentes clases usando la misma interfaz, dividiría la interfaz en la misma carpeta que la clase a menos que se vuelva completamente ingobernable. Pero no creo que eso suceda porque dudo que tengas cientos de archivos de clase en la misma carpeta. Si es así, se debe limpiar y subcargar de acuerdo con la funcionalidad y el resto se hará cargo de sí mismo.


Depende. Hago esto: si tiene que agregar un ensamblado de un tercero dependiente, mueva las versiones concretas a una biblioteca de clases diferente. Si no, pueden permanecer al lado en el mismo directorio y espacio de nombres.


Encuentro que cuando necesito cientos de interfaces en mi proyecto para aislar dependencias, encuentro que puede haber un problema en mi diseño. Este es especialmente el caso cuando muchas de estas interfaces terminan teniendo solo un método. Una alternativa a hacer esto es que sus objetos generen eventos y luego vinculen sus dependencias a esos eventos. Por ejemplo, supongamos que desea simular una persistencia de sus datos. Una forma perfectamente razonable de hacer esto sería hacer esto:

public interface IDataPersistor { void PersistData(Data data); } public class Foo { private IDataPersistor Persistor { get; set; } public Foo(IDataPersistor persistor) { Persistor = persistor; } // somewhere in the implementation we call Persistor.PersistData(data); }

Otra forma de hacer esto sin usar interfaces o simulacros sería hacer esto:

public class Foo { public event EventHandler<PersistDataEventArgs> OnPersistData; // somewhere in the implementation we call OnPersistData(this, new PersistDataEventArgs(data)) }

Luego, en nuestra prueba, puedes hacer esto en lugar de crear un simulacro:

Foo foo = new Foo(); foo.OnPersistData += (sender, e) => { // do what your mock would do here }; // finish your test

Me parece que esto es más limpio que el uso excesivo de burlas.