Trabajar con formas más eficientes pero menos funcionales de almacenar datos

8

Desde que aprendí programación orientada a objetos, me he sentido confundido acerca de cómo manejar múltiples formas de almacenar datos que tienen diferentes niveles de funcionalidad y eficiencia. Soy un poco nuevo en esto, así que probablemente me esté perdiendo algo o me estoy acercando a este mal.

Diga que estoy escribiendo un hipotético programa de edición de imágenes (no lo estoy, pero este fue el mejor ejemplo que pude encontrar) y me preocupa el rendimiento: se trata de archivos muy grandes. El programa puede manejar imágenes en escala de grises y en color, y ambas se usan comúnmente. Es más eficiente trabajar con imágenes en escala de grises porque requieren menos memoria y pueden manipularse más rápidamente, pero no admiten todas las operaciones que realizan las imágenes en color (como ajustar el tono). Me gustaría usar imágenes en escala de grises siempre que sea posible.

Si estoy diseñando una clase que representa una imagen junto con algunas utilidades útiles, debería:

  1. ¿Crear una interfaz Image con todos los comandos posibles y las implementaciones de ColorImage / GrayscaleImage , y solo hacer que GrayscaleImage falle cuando encuentra algo que no puede hacer?
  2. ¿Crear una única clase Image con múltiples modos de operación?
  3. ¿Hacer que ColorImage se extienda desde GrayscaleImage , porque las imágenes en color agregan más funcionalidad?
  4. Hacer que GrayscaleImage se extienda desde ColorImage , ¿porque las imágenes en escala de grises son un subconjunto de imágenes en color?
  5. ¿Hacer que ColorImage ajuste un GrayscaleImage y agregarle información de color?
  6. ¿Algo más?

Ninguna de esas opciones me parece correcta. El primero y el segundo requerirían una gran cantidad de código duplicado para las funciones de utilidad de imagen; el tercero y el cuarto no parecen correctos conceptualmente (una imagen en color definitivamente no es una imagen en escala de grises, pero las imágenes en escala de grises no extienden la funcionalidad de las imágenes en color); y el quinto sería una manera molesta de almacenar información de la imagen porque no podría obtener los valores RGB exactos. ¿Y qué haría si se me ocurrieran otras formas de trabajar con imágenes de manera más eficiente, como los colores indexados?

En general, cuando tengo una forma más eficiente de almacenar y trabajar con datos pero no es compatible con todas las funciones, ¿qué debo hacer?

    
pregunta Jacob van't Hoog 17.07.2016 - 23:24

2 respuestas

6

Deje de preocuparse por la eficiencia y comience a preocuparse por crear una buena abstracción que sea aplicable al dominio y complete las necesidades del cliente / usuario / llamante.

Para hacer esto, primero identificamos qué capacidades necesita el cliente / usuario / llamante. En términos generales, para una buena abstracción, todas estas capacidades deben encontrarse juntas o, de lo contrario, el cliente / usuario / llamante tendrá que comprender más de su implementación de lo que deberían cuando intentan compensar la diferencia.

Por lo tanto, primero identifique el conjunto de capacidades que necesitan sus usuarios para operar sobre este contenido. Por ejemplo, considere la creación de contenido, búsqueda, visualización, transformación (formatos, compresión / descompresión, audio / video, etc.), colaboración.

A continuación, diseñe (una o más) interfaces que juntas presenten la abstracción y proporcionen al cliente / usuario / llamante estas capacidades.

Por último, implemente estas interfaces, utilizando la herencia según sea necesario para reutilizar o personalizar la implementación / código.

Encuentro que la eficiencia y la buena abstracción a menudo se pueden tener juntas. Cuando está pidiendo consejos sobre cómo diseñar sus clases, sostengo que esta pregunta es más sobre el diseño de la abstracción correcta que sobre la implementación eficiente. Muchas de sus alternativas tocan uno o más de mis puntos. Con suerte, puede ver que no todas sus alternativas se excluyen mutuamente.

Si diseña una buena abstracción, podrá sustituir implementaciones de diferentes mecanismos subyacentes utilizando la misma abstracción (por ejemplo, interfaz (es)). Por lo tanto, puedes experimentar con eficiencia.

    
respondido por el Erik Eidt 18.07.2016 - 03:32
2

Un mapa de bits en escala de grises se puede colorear bien. Será necesario volver a codificar otros formatos de archivo de imagen si de repente dejan de ser escala de grises. Si el usuario intenta convertir su imagen en escala de grises en tono sepia usted tiene que decidir si dejarlos o decirles que no.

De forma similar, tendrá que decidir cómo reaccionar cuando los métodos solicitados no son válidos con su objeto en un estado particular. Puedes cambiar de estado, lanzar una excepción o no hacer nada. Ninguna de estas opciones requiere que cambies tu interfaz. Lo que cambias es el comportamiento que se produce cuando se llama.

Sinceramente, no veo cómo se trata el rendimiento. Este mismo problema surge con muchas estructuras de datos. Por ejemplo, ¿qué significa capitalizar un entero? Aunque odio cuando las cosas fallan silenciosamente, creo que un 1 en mayúscula es solo un 1.

    
respondido por el candied_orange 18.07.2016 - 00:16

Lea otras preguntas en las etiquetas