tutorial oriented language help documentacion development concepts c# oop

language - object oriented concepts c#



Cómo crear la aplicación OOP perfecta (10)

Aquí hay un gran ejemplo de un patrón de OO para productos, impuestos, etc. Observe el uso de interfaces, que es esencial en el diseño de OO.

http://www.dreamincode.net/forums/topic/185426-design-patterns-strategy/

Recientemente estuve intentando para una empresa ''x''. Me enviaron algunas preguntas y me dijeron que resolviera solo una.

El problema es así -

El impuesto básico a las ventas se aplica a una tasa del 10% sobre todos los bienes, excepto libros, alimentos y productos médicos que están exentos.
El derecho de importación es un impuesto a las ventas adicional aplicable a todas las mercancías importadas a una tasa del 5%, sin exenciones.

Cuando compro artículos, recibo un recibo que enumera el nombre de todos los artículos y su precio (incluido el impuesto), finaliza con el costo total de los artículos y los montos totales de los impuestos pagados.
Las reglas de redondeo para el impuesto a las ventas son que para una tasa de impuesto de n%, un precio de estantería de p contiene (np / 100 redondeado al valor más cercano a 0.05) el impuesto a las ventas.

"Me dijeron que están interesados ​​en el aspecto de diseño de su solución y que les gustaría evaluar mis habilidades de programación orientadas a objetos ".

Esto es lo que dijeron en sus propias palabras

  • Para la solución, nos gustaría utilizar Java, Ruby o C #.
  • Estamos interesados ​​en el ASPECTO DE DISEÑO de su solución y nos gustaría evaluar sus Habilidades de Programación Orientada a Objetos .
  • Puede usar bibliotecas o herramientas externas para construir o realizar pruebas. Específicamente, puede usar bibliotecas de pruebas unitarias o herramientas de compilación disponibles para el idioma que elija (por ejemplo, JUnit, Ant, NUnit, NAnt, Test :: Unit, Rake, etc.)
  • Opcionalmente, también puede incluir una breve explicación de su diseño y suposiciones junto con su código.
  • Tenga en cuenta que NO estamos esperando una aplicación basada en la web o una interfaz de usuario completa. Más bien, esperamos una aplicación simple basada en la consola e interesado en su código fuente.

Así que proporcioné el siguiente código: solo puede copiar el código de pegado y ejecutarlo en VS.

class Program { static void Main(string[] args) { try { double totalBill = 0, salesTax = 0; List<Product> productList = getProductList(); foreach (Product prod in productList) { double tax = prod.ComputeSalesTax(); salesTax += tax; totalBill += tax + (prod.Quantity * prod.ProductPrice); Console.WriteLine(string.Format("Item = {0} : Quantity = {1} : Price = {2} : Tax = {3}", prod.ProductName, prod.Quantity, prod.ProductPrice + tax, tax)); } Console.WriteLine("Total Tax : " + salesTax); Console.WriteLine("Total Bill : " + totalBill); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.ReadLine(); } private static List<Product> getProductList() { List<Product> lstProducts = new List<Product>(); //input 1 lstProducts.Add(new Product("Book", 12.49, 1, ProductType.ExemptedProduct, false)); lstProducts.Add(new Product("Music CD", 14.99, 1, ProductType.TaxPaidProduct, false)); lstProducts.Add(new Product("Chocolate Bar", .85, 1, ProductType.ExemptedProduct, false)); //input 2 //lstProducts.Add(new Product("Imported Chocolate", 10, 1, ProductType.ExemptedProduct,true)); //lstProducts.Add(new Product("Imported Perfume", 47.50, 1, ProductType.TaxPaidProduct,true)); //input 3 //lstProducts.Add(new Product("Imported Perfume", 27.99, 1, ProductType.TaxPaidProduct,true)); //lstProducts.Add(new Product("Perfume", 18.99, 1, ProductType.TaxPaidProduct,false)); //lstProducts.Add(new Product("Headache Pills", 9.75, 1, ProductType.ExemptedProduct,false)); //lstProducts.Add(new Product("Imported Chocolate", 11.25, 1, ProductType.ExemptedProduct,true)); return lstProducts; } } public enum ProductType { ExemptedProduct=1, TaxPaidProduct=2, //ImportedProduct=3 } class Product { private ProductType _typeOfProduct = ProductType.TaxPaidProduct; private string _productName = string.Empty; private double _productPrice; private int _quantity; private bool _isImportedProduct = false; public string ProductName { get { return _productName; } } public double ProductPrice { get { return _productPrice; } } public int Quantity { get { return _quantity; } } public Product(string productName, double productPrice,int quantity, ProductType type, bool isImportedProduct) { _productName = productName; _productPrice = productPrice; _quantity = quantity; _typeOfProduct = type; _isImportedProduct = isImportedProduct; } public double ComputeSalesTax() { double tax = 0; if(_isImportedProduct) //charge 5% tax directly tax+=_productPrice*.05; switch (_typeOfProduct) { case ProductType.ExemptedProduct: break; case ProductType.TaxPaidProduct: tax += _productPrice * .10; break; } return Math.Round(tax, 2); //round result before returning } }

puede descomprimir la entrada y ejecutar para diferentes entradas.

Proporcioné la solución pero fui rechazado.

"Dijeron que no podían considerarme para nuestras posiciones abiertas actuales porque la solución del código no es satisfactoria".

Por favor, guíame lo que falta aquí. ¿Esta solución no es una buena solución OOAD?
¿Cómo puedo mejorar mis habilidades OOAD?
Mis superiores también dicen que la aplicación OOAD perfecta tampoco funcionará en la práctica.

Gracias


Desde una perspectiva estrictamente OOA / D, un problema importante que veo es que la mayoría de los atributos de su clase tienen el nombre redundante de la clase en el nombre del atributo. por ejemplo , precio del producto , tipo de producto . En este caso, en todos los lugares donde use esta clase, tendrá un código demasiado detallado y algo confuso, por ejemplo, product.productName. Elimine los prefijos / sufijos de nombre de clase redundante de sus atributos.

Además, no vi ninguna clase relacionada con la compra y la creación de un recibo como se hizo en la pregunta.


En primer lugar, cielos buenos no hacen cálculos financieros en doble . Haga cálculos financieros en decimal ; Esto es para lo que sirve. Usa el doble para resolver problemas de física , no problemas financieros .

El principal defecto de diseño en su programa es que la política está en el lugar equivocado . ¿Quién está a cargo de calcular los impuestos? Usted ha puesto el producto a cargo de calcular los impuestos, pero cuando compra una manzana o un libro o una lavadora, lo que está a punto de comprar no es responsable de decirle cuánto impuesto va a pagar en eso. La política del gobierno es responsable de decirte eso. Su diseño viola de manera masiva el principio básico de diseño de OO de que los objetos deberían ser responsables de sus propias preocupaciones , y no de las de nadie más. La preocupación de una lavadora es lavar su ropa, no cobrar el derecho de importación correcto. Si cambian las leyes fiscales, no desea cambiar el objeto de la lavadora , desea cambiar el objeto de política .

Entonces, ¿cómo abordar este tipo de problemas en el futuro?

Hubiera empezado resaltando cada sustantivo importante en la descripción del problema:

El impuesto básico a las ventas se aplica a una tasa del 10% sobre todos los bienes , excepto libros , alimentos y productos médicos que están exentos. El derecho de importación es un impuesto a las ventas adicional aplicable a todas las mercancías importadas a una tasa del 5%, sin exenciones . Cuando compro artículos , recibo un recibo que enumera el nombre de todos los artículos y su precio (incluido el impuesto ), finaliza con el costo total de los artículos y los montos totales de los impuestos pagados. Las reglas de redondeo para el impuesto a las ventas son que para una tasa de impuesto de n%, un precio de estantería de p contiene (np / 100 redondeado al valor más cercano a 0.05) el impuesto a las ventas .

Ahora, ¿cuáles son las relaciones entre todos esos nombres?

  • El impuesto básico a las ventas es una especie de impuesto a las ventas
  • Import Duty es un tipo de impuesto a las ventas
  • Un impuesto sobre las ventas tiene una tasa que es un decimal
  • Los libros son un tipo de artículo
  • La comida es un tipo de artículo
  • Los productos médicos son un tipo de artículo
  • Los artículos pueden ser importados
  • Un artículo tiene un nombre que es una cadena
  • Un artículo tiene un precio de estante que es un decimal. (Nota: ¿un artículo realmente tiene un precio? Dos lavadoras idénticas pueden estar a la venta por diferentes precios en diferentes tiendas, o en la misma tienda en diferentes momentos. Un mejor diseño podría ser decir que una política de precios relaciona un artículo con su precio.)
  • Una política de exención de impuestos a las ventas describe las condiciones bajo las cuales un impuesto a las ventas no es aplicable a un artículo.
  • Un recibo tiene una lista de artículos, sus precios y sus impuestos.
  • Un recibo tiene un total
  • Un recibo tiene un impuesto total

... y así. Una vez que tenga todas las relaciones entre todos los sustantivos resueltos, entonces puede comenzar a diseñar una jerarquía de clases. Hay un artículo abstracto de la clase base. El libro hereda de él. Hay una clase abstracta SalesTax; BasicSalesTax hereda de él. Y así.


En primer lugar, esta es una pregunta de entrevista muy buena. Es un buen indicador de muchas habilidades.

Hay muchas cosas que necesita comprender para proporcionar una buena respuesta (no hay una respuesta perfecta), tanto de alto como de bajo nivel. Aquí hay una pareja:

  • Modelado de dominio -> ¿cómo se crea un buen modelo de la solución? ¿Qué objetos creas? ¿Cómo van a resolver los requisitos? Buscar los sustantivos es un buen comienzo, pero ¿cómo decides si tu elección de entidades es buena? ¿Qué otras entidades necesitas? ¿Qué conocimiento de dominio necesitas para resolverlo?
  • Separación de preocupaciones, acoplamiento débil, alta cohesión -> ¿Cómo se separan las partes del diseño que tienen diferentes preocupaciones o tasas de cambio y cómo se relacionan? ¿Cómo mantienes tu diseño flexible y actual?
  • Pruebas unitarias, refactorización, TDD -> ¿Cuál es su proceso para encontrar una solución? ¿Escribes pruebas, utilizas objetos simulados, refactorizas, iteras?
  • Código de limpieza, modismos de idioma -> ¿Utiliza las características de su lenguaje de programación para ayudarlo? ¿Escribes un código comprensible? ¿Sus niveles de abstracción tienen sentido? ¿Qué tan fácil de mantener es el código?
  • Herramientas : ¿Usas control de fuente? ¿Construir herramientas? IDEs?

A partir de ahí, puede tener muchas discusiones interesantes, que incluyan principios de diseño (como los principios SOLID), patrones de diseño, patrones de análisis, modelado de dominio, opciones de tecnología, trayectorias de evolución futura (por ejemplo, qué sucede si agrego una base de datos o una interfaz de usuario enriquecida). ¿Qué necesita cambiar?), compensaciones, requisitos no funcionales (rendimiento, mantenimiento, seguridad, ...), pruebas de aceptación, etc.

No comentaré cómo debería cambiar su solución, solo que debe enfocarse más en estos conceptos.

Pero, puedo mostrarle cómo resolví (parcialmente) este problema , solo como un ejemplo (en Java). Mire en la clase Program para ver cómo se combina todo para imprimir este recibo:

------------------ THIS IS YOUR ORDER ------------------ (001) Domain Driven Design ----- $69.99 (001) Growing Object Oriented Software ----- $49.99 (001) House M.D. Season 1 ----- $29.99 (001) House M.D. Season 7 ----- $34.50 (IMD) Growing Object Oriented Software ----- $2.50 (BST) House M.D. Season 1 ----- $3.00 (BST) House M.D. Season 7 ----- $3.45 (IMD) House M.D. Season 7 ----- $1.73 SUB-TOTAL ----- $184.47 TAX TOTAL ----- $10.68 TOTAL ----- $195.15 ---------------- THANKS FOR CHOOSING US ----------------

Definitivamente deberías echarle un vistazo a esos libros :-)

Solo como una advertencia: mi solución aún es muy incompleta, simplemente me centré en el escenario de la ruta feliz para tener una buena base sobre la que construir.


Esto es altamente subjetivo, pero aquí hay algunos puntos que haría sobre su código:

  • En mi opinión, mezcló Product y ShoppingCartItem . Product debe tener el nombre del producto, el estado fiscal, etc., pero no la cantidad. La cantidad no es propiedad de un producto; será diferente para cada cliente de la compañía que compre ese producto en particular.

  • ShoppingCartItem debe tener un Product y la cantidad. De esta forma, el cliente puede comprar libremente más o menos del mismo producto. Con su configuración actual eso no es posible.

  • El cálculo del impuesto final tampoco debe formar parte del Product ; debe formar parte de algo como ShoppingCart ya que el cálculo del impuesto final puede implicar conocer todos los productos en el carrito.


Excepto por el hecho de que está utilizando una clase llamada producto, no ha demostrado que sabe qué es la herencia, no ha creado múltiples clases heredadas del Producto, no polimorfismo. El problema podría haberse resuelto usando múltiples conceptos de OOP (incluso solo para mostrar que los conoces). Este es un problema de entrevista, por lo que desea mostrar cuánto sabe.

Sin embargo, no me convertiría en depresión en este momento. El hecho de que no los hayas demostrado aquí no significa que no los conozcas o que no los puedas aprender.

Solo necesitas un poco más de experiencia con OOP o entrevistas.

¡Buena suerte!


Las personas que han comenzado a aprender programación con OOP no tienen grandes problemas para entender lo que significa, porque es igual que en la vida real . Si tiene habilidades con otra programación familiar que OO, podría ser más difícil de entender.

En primer lugar, apague la pantalla o salga de su IDE favorito. Tome un papel y un lápiz y haga una lista de entidades , relaciones , personas , máquinas , procesos , cosas , etc. todo lo que pueda encontrar en su programa final.

Segundo, intente obtener las diferentes entidades básicas . Comprenderás que algunos pueden compartir propiedades o habilidades , debes ponerlo en objetos abstractos . Deberías comenzar a dibujar un buen esquema de tu programa.

Luego tiene que poner fonctionnalities (métodos, funciones, subrutinas, llamarlo como quiera): por ejemplo, un objeto de producto no debería poder calcular el impuesto a las ventas . Un objeto del motor de ventas debería.

No sientas problemas con todas las palabras grandes ( interfaces , propiedades , polimorfismo , herencia , etc.) y patrones de diseño por primera vez, ni siquiera trates de crear código hermoso o lo que sea ... Solo piensa en objetos simples y interracciones entre ella como en la vida real .

Después, trate de leer una literatura seria y concisa sobre esto. Creo que Wikipedia y Wikibooks son una muy buena forma de comenzar y luego simplemente leer sobre GoF y Design Patterns y UML .


Si la empresa dice algo acerca de bibliotecas como NUnit, JUnit o Test :: Unit es más que probable que TDD sea realmente importante para ellos. En su muestra de código no hay pruebas en absoluto.

Intentaré demostrar conocimiento práctico de:

  • Pruebas unitarias (p. Ej., NUnit)
  • Burlarse (por ejemplo, RhinoMocks)
  • Persistencia (por ejemplo, NHibernate)
  • Contenedores de IoC (por ejemplo, NSpring)
  • patrones de diseño
  • Principio SÓLIDO

Me gustaría recomendar www.dimecasts.net como una fuente impresionante de screencasts gratuitos y de buena calidad que cubren todos los temas mencionados anteriormente.


Un buen punto de partida sobre las reglas de diseño son los principios SOLID .

Por ejemplo, el principio de Open Closed establece que si desea agregar una nueva funcionalidad no necesita agregar código a la clase existente, sino agregar una nueva clase.

Para su aplicación de muestra, esto significaría que agregar un nuevo impuesto a las ventas requeriría agregar una nueva clase. Lo mismo ocurre con diferentes productos que son excepciones a la regla.

La regla de redondeo obviamente va en una clase separada: el principio de Responsabilidad Individual establece que cada clase tiene una responsabilidad única.

Creo que tratar de escribir el código usted mismo traería con mucho más beneficio que simplemente escribir una buena solución y pegarla aquí.

Un algoritmo simple para escribir el programa diseñado perfecto sería:

  1. Escriba algún código que resuelva el problema
  2. Verifique si el código cumple con los principios SÓLIDOS
  3. Si hay violaciones a las reglas que goto 1.

Una implementación perfecta de OOP es completamente discutible. Según lo que veo en su pregunta, podría modularizar el código en función del rol que desempeñan para calcular el precio final, como Producto, Impuesto, ProductoDB, etc.

  1. Product podría ser una clase abstracta y los tipos derivados como Libros, Comida podrían heredarse de ella. La aplicabilidad de impuestos puede decidirse por los tipos derivados. El producto diría si el impuesto es aplicable o no en función de la clase derivada.

  2. TaxCriteria puede ser una enumeración y esto se puede especificar durante la compra (importado, aplicabilidad del impuesto a las ventas).

  3. Tax clase impositiva calculará el impuesto basado en el TaxCriteria .

  4. Tener un ShoppingCartItem como lo sugiere XXBBCC puede encapsular las instancias de productos y de impuestos, y es una gran manera de segregar los detalles del producto con la cantidad, el precio total con impuestos, etc.

Buena suerte.