2009-09-22 14 views
6

He estado usando f # y Haskell para aprender programación funcional desde hace un tiempo. Hasta que pueda obtener la aprobación de f # en nuestra compañía, aún debo usar C#. Todavía intento sin embargo mantenerme en el estilo funcional ya que he notado varios beneficios.De OO a programación funcional a 10,000 pies

Aquí hay un problema típico.

  1. hay una mesa-set clave en la base de datos con 3 llaves (6,5 millones de filas)
  2. Hay 4 otras mesas de apoyo de tamaño pequeño a mediano.
  3. Existen fórmulas complejas basadas en varias entradas.

Tengo que usar datos de todo lo anterior para calcular un valor y asociarlo con cada fila de juego de claves y enviarlo de regreso a la base de datos. Hay muchas búsquedas en las otras 4 tablas. Por el bien del rendimiento todo está hecho en la memoria.

Sé exactamente cómo lo haría en OO con diccionarios estáticos, modelos de objetos, patrones de estrategia y demás, pero de una manera funcional no puedo deshacerme del mal olor del uso de algunos de estos constructos.

Actualmente estoy haciendo las siguientes suposiciones para una solución funcional.

  1. Los diccionarios estáticos son malos. Parece que la función podría tener efectos secundarios.

  2. Necesito una función Calcular, toma un objeto inmutable (s) y devuelve un objeto inmutable con las tres claves y el valor calculado. Dentro de esta función podría haber otra función en el mismo estilo.

  3. Los patrones OO tradicionales probablemente no funcionen.

¿Cómo diseñarías esto a un alto nivel?

¿Estoy equivocado? ¿Me he perdido algo?

Respuesta

6

No, no estás equivocado. Tanto el OOP como la programación funcional tienen sus ventajas y sus inconvenientes.

Un desarrollador necesita saber cómo y cuándo usar cada estilo de desarrollo. Es una suerte que C# sea compatible con ambos estilos de desarrollo.

En mi opinión, y uso tanto estilos de programación funcionales como de programación diaria, lo mejor es oop cuando se trata de interacciones complejas e interdependencias entre diversos artefactos abstractos (entidades, sustantivos, etc.). La programación funcional se utiliza mejor cuando se trata de algoritmos, transformaciones de datos, etc. situaciones en las que la complejidad de las declaraciones necesarias para resolver un problema determinado es excelente.

Generalmente utilizo programación orientada a objetos en mi dominio (entidades, agregados, objetos de valor, repositorios y eventos) y reservo programación funcional para mis objetos de servicio.

La mayoría de las veces se trata de un olor o sensación que es mejor, ya que en el desarrollo de software no son casos claros, y la experiencia y la práctica a menudo es el mejor criterio para una opción determinada.

0

La programación funcional en un idioma OO tiende a ser incorrecta. Produce código excesivamente prolijo que no funciona bien y es más propenso a errores (por ejemplo, la escritura de funciones recursivas profundamente en un idioma que no admite llamadas de cola.)

cita en bloque 1. diccionarios estáticos son malas. Parece que la función podría tener efectos secundarios.

O tiene o no tiene efectos secundarios. Un diccionario estático puede ser una buena manera de implementar la memorización en un idioma OO.

Blockquote 3. Los patrones de OO tradicionales probablemente no funcionen.

OO patrones funcionan bien en un lenguaje OO tratando de conectar cuerno técnicas FP en un idioma OO producirá código detallado y frágil. Es más bien como tratar de usar un destornillador con técnicas de martillo, seguro que produce un resultado, pero hay mejores formas. Intenta usar tus herramientas de la mejor manera posible. Ciertas técnicas de PF pueden ser útiles, pero ignorar por completo el lenguaje no servirá para obtener un código de buena calidad.

+0

Depende del idioma de OO en cuestión. C# hace un trabajo bastante bueno con técnicas funcionales. Y algunas cosas se pueden hacer de una manera bastante funcional en lenguajes OO más dolorosamente inflexibles como Java, pero ciertamente hay una buena cantidad de fricción cognitiva en ese caso. – JasonTrue

+1

Si termina haciendo algo funcional y está en el entorno Java, probablemente sea mejor hacerlo en Clojure. Si bien técnicamente es un lenguaje Lisp y no basado en ML, puede funcionar con aplicaciones Java (genera bytecode JVM) y admite el desarrollo de un estilo funcional. –

+0

C# falla en muchas técnicas funcionales.La inferencia de tipo extremadamente limitada es solo un obstáculo. Intente escribir el tipo de función que usa varios parámetros genéricos, como un diccionario de funciones. Ay. – MichaelGG

2

Si busca velocidad, es posible que desee considerar las estructuras de datos subyacentes que utiliza. El diccionario <> en C# es una tabla hash, mientras que SortedDictionary <> en C# es un árbol de búsqueda binaria.

F # y Haskell hacen un buen trabajo representando estructuras de datos de árbol. Es posible que desee considerar el uso de una estructura de datos más específica sobre las predeterminadas que proporciona C#.

En un nivel alto, averiguaría qué características de rendimiento muestran sus fórmulas y las compararé con diferentes estructuras de datos (la wikipedia es una buena fuente si necesita un repaso). Una vez que descubra qué estructuras de datos usar, me preocuparía qué implementaciones usar.

+1

No sé sobre C#, pero una tabla hash implementada correctamente no tiene búsquedas lentas. Sin embargo, para mantener la velocidad de búsqueda, las inserciones tienen que volver a generar toda la tabla. (Pero esto no es un gran problema, incluso BerkeleyDB hace esto por sus hash en disco). La ventaja de un árbol sobre una tabla hash es la localidad de referencia; si está iterando sobre un trozo de la tabla "en orden", es fácil precomprobar los "siguientes" nodos. – jrockway

+0

Quité mis comentarios sobre lo que es más rápido o más lento. Existen muchas ventajas y desventajas diferentes para las tablas hash frente a los árboles binarios, dependiendo de cómo los use. C# Dictionary <> sí tiene un tiempo de búsqueda rápido. "el tiempo promedio de ejecución asintótica para agregar, eliminar y buscar la tabla hash mediante el sondeo es el tiempo constante, O (1)" http://msdn.microsoft.com/en-us/library/ms379571(VS.80).aspx – gradbot

1

¿Cómo diseñarías esto a un alto nivel?

Básicamente, utiliza funciones de orden superior para convertir el trabajo en componentes reutilizables con una baja carga sintáctica. A continuación, puede migrar desde estructuras de datos imperativas a estructuras de datos puramente funcionales (cómputo puramente funcional envuelto en efectos secundarios para escrituras de bases de datos similares a IO). Finalmente, incluso puede rastrear los efectos secundarios (completamente puramente funcionales).

Como una guía aproximada, estas tres gradaciones para completar la pureza se ven en primer lugar en Lisp (en gran parte impuro), ML estándar (uso mucho más pesado de estructuras de datos puramente funcionales) y Haskell (pureza completa).

No puedo dar más detalles sin saber exactamente el problema, pero puede estar seguro de que muchas personas lo están haciendo a diario y funciona extremadamente bien.

Cuestiones relacionadas