Ir al contenido


Foto

Sugerencia nombres de ciertas clases


  • Por favor identifícate para responder
9 respuestas en este tema

#1 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 12 diciembre 2016 - 03:48

Que tal comunidad. Hoy en dia vengo con un problemilla de diseño que me tiene medio loco. El contexto es simplon pero como me gusta escribir para que cualquiera entienda, el cuentito es medio largo, asi que tenganme paciencia :)

 

Veran el problema es que no se como nombrar una clase. La definicion de la clase e incluso algun prototipo funcional ya lo tengo, pero no encuentro un buen nombre para la clase (en realidad es una interfaz pero para lo que es el hilo es lo mismo)

 

Un breve resumen del contexto. Sea el tipico sistema de facturacion y gestion contable, el cual es capaz de manejar los siguientes tipos de comprobantes/documentos: facturas, pedidos (o si quieren pueden decirle "preventa") y presupuestos

 

La factura vendria a ser el mas comprobante "oficial", por decirlo de alguna manera, dentro de nuestras reglas de negocio, es una venta ya confirmada y acordada por las dos partes; digamos que si una operacion de venta llega a la instancia de factura quiere decir que el cliente ya acordo que va a comprar determinada mercancia y pagarla bajo ciertos terminos

 

El pedido o preventa es una especie de "reserva" de productos. Dicho a lo bestia es, guardame estos productos que despues te los pago. El "despues te los pago" es, dentro de unos dias (existe un plazo de vencimiento, no viene al caso) me haces la factura. Aca es donde nos metemos mas en el tema en cuestion: El pedido debe satisfacer dos requerimientos:

 

- Existe la posibilidad de que dicho pedido "congele" el precio de los productos. 

- Al ser efectivo, es decir, al facturar el pedido se pueden agregar o adosar mas productos en la factura

 

Ejemplo practico:

 

Se crea el Pedido # 1234 con los siguientes productos:

100 lamparitas de 40w x 100 $ c/u

20 mts cable x 20 $ c/mt

 

Se reserva el stock y se "congela" el precio para ese pedido, y luego a los dos dias viene Pepito y dice: Haceme la factura, pero agregame 100 portalamparas que me olvide. El pedido queda igual pero la factura tiene que quedar asi:

 

100 lamparitas de 40w x 100 $ c/u

20 mts cable x 20 $ c/mt

100 portalamparas x 12 $ c/u

 

El presupuesto es similar al pedido pero el stock no se reserva. Osea, llevandolo a diseño OO responde a la misma interfaz, la unica diferencia es que no se toca el stock

 

Dentro del circuito de facturacion, el presupuesto puede pasar directamente a factura, o puede primero pasar a pedido, y luego en algun momento facturar el pedido

 

Mi problema, ahora si, es como llamar a la clase o interfaz que modela el "detalle" que se adosa. Osea yo ya tengo un pedido o presupuesto creado, ahora quiero pasar al siguiente paso de facturacion (podria ser un presupuesto que pase a pedido, o cualquiera de los dos a factura, da igual)

 

Un pequeño esbozo en UML podria verse asi:

 

Archivo adjunto  uml.png   146,75KB   0 descargas

 

Mi puntual es como nombrar las dos clases de abajo de todo

 

Imaginense un Form que se inicializa recibiendo una instancia de "Comprobante" y el agarra recorre todo el detalle que ya existe y lo pone en pantalla. El form tambien conoce una instancia de esta clase que no le encuentro el nombre y es ahi en donde se van agregando todo lo "nuevo" que se adosa a la factura final. 

 

Como le ponemos de nombre a estas clases? Escucho sugerencias :)

 

Salutes

 

 


  • 0

#2 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 12 diciembre 2016 - 08:33

¡Llegó el "profe" de OO! :D Offtopic: Como me gustaría poder decir eso ;)

Déjame ver si estoy comprendiendo: tu duda es como debería llamarse las clases especializada (y que por lo que entiendo de tu diagrama, hereda) de LineaDetalle y que se encargaría de manejar los precios y otros temas relacionados con el caso de un congelamiento de precios.

Básicamente: estamos en el contexto de un pedido.

 

De ser así, yo siguiendo el esquema propuesto simplemente le llamaría LineaDetallePedido y se sobre entendiende ahora que al ser contexto de pedido, los precios son congelados, etc.

 

Ahora bien, esto a mi me genera un poquito de "ruido". La primera pregunta, ¿Y cual sería el propósito de ese detalle extra adosado temporal? ¿Que es realmente lo que motiva su aparición? No le encuentro significado, presencia.

 

Siguiendo entonces, con el ruido, me vuelvo para atrás, y digo: si esto es LineaDetallePedido, y tenemos una clase Pedido que sería su "dueña", ¿Sería útil entonces razonar algo como Factura tiene LineaDetalleFactura, y más aún un Presupuesto un LineaDetallePresupuesto? En cierto modo SI. Porque son una especialización de lo que definimos abstractamente como un comprobante.

 

He aquí entonces que a ese diseño, le podría ser útil promoverlo ya pensando en un patrón pensado para esto: Fabricacion Abstracta. Voy a compartir contigo y con los demás, una muy pequeña parte de lo que yo llamo "mi secreto profesional". Adjunto escaneada una hoja de mis apuntes de estudio sobre prácticas de patrones.

 

 

Archivo adjunto  FabricacionAbstracta.jpg   45,28KB   0 descargas

 

En ocasiones los diagramas que uno lee en los artículos, libros, etc. como que te nublan y confunden un poco. A mi me servía estudiar el patrón: ver sus bases, sus partes y elaborar mis propios diagramas en base a lo practicado. Al menos a mi me ha ayudado a comprender mejor.

 

¿A donde quiero llegar? A que efectivamente tenemos un contexto abstracto: comprobante, que mantiene una estructura de detalles abstracta. Y existen derivaciones específicas y concretas de esta estructura: Facturas, Pedidos y Presupuesto. Cada uno hace a un contexto y se puede definir en ellos la naturaleza propia que le corresponde.

 

Lo que puede marear un poco es la parte del concepto Factoría. No tenemos per se varios productos en cada factoría, sino uno solo: LineaDetalleX, nuestros DetallesX concretos serían los encargados de mantener la lista de LineaDetalleX. Adicionalmente está luego la clase Comprobante especializada de cada uno. Entonces el diseño sería algo así:

 

Factura ---- DetalleFactura <>---------- LineaDetalleFactura

 

Pedido ---- DetallePedido <>---------- LineaDetallePedido

 

Presupuesto ---- DetallePresupuesto <>---------- LineaDetallePresupuesto

 

El giro de tuerca es que en esta puesta en práctica en particular del patrón, el grado de herencia de clases es uno más. Aunque quizá merezca destinar unos momentos a analizar que tan útil es disponer esa clase intermedia entre X y LineaDetalleX. Es decir ¿Nos aporta valor el concepto Detalle? O bien podría directamente prescrindir de éste y que su lógica pase a X?

 

De esta forma ahora si se ve mejor la aparición del patrón:

 

Factura <>------- DetalleFactura

Pedido <>-------- DetallePedido

Presupuesto <>--------- DetallePresupuesto

 

Factura, Pedido, Presupuesto son las factorías específicas, DetalleFactura, DetallePedido y DetallePresupuesto son los productos específicos.

 

Al menos así es como lo pensaría yo. Pensando en el patrón de Fabricacion Abstracta tiene cierto sentido lógico, fuerza a aparecer las estructuras comunes y en ciertas ocasiones nos dirije y sugiere los nombres. Otro motivo de aplicar este patrón es que no va a suponer un cambio radical a ese diseño. El principio ya está, solo cambian algunas relaciones y de paso ya aprovechamos de la existencia de esta clase abstracta (o Interface en tu caso)  ;)

Y por último, otra razón de peso: Nos separa las cosas por contexto: tenemos bien identificados cada uno. Y nada impide que se haga ese trabajo en "cadena" que va desde Pedido a Factura, o bien desde Presupuesto a Pedido y/o por último a Factura.

 

Ahora, como visión personal. Si me lo permites, lo habitual y a como se suele entender la mayoría de las veces el concepto de Pedido es que para una Factura pueden haber muchos Pedidos. Tu visión sugiere una relación de dependencia única. No digo que estuviera mal, en buena parte simplica las cosas. Tu diseño en lugar de ir generando pedidos simplemente a ese único pedido que se transformará en la factura lo que hace es ir metiéndole las líneas de detalle que hagan falta.

Te lo comento porque generalmente lo que sugiere la relación (1,M) entre Factura y Pedido está basado en una ventana de tiempo. Por lo cual cada Pedido tiene como particularidad de que se realiza en una fecha/hora determinada, y esto ayuda a determinar la trazabilidad de los productos y la disponibilidad de inventario o stock al momento.

 

No más me permito este espacio para comentarlo y revises si te hace ruido o no.

 

Espero haberte sido de ayuda y no marearte.

 

Saludos,


  • 1

#3 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 12 diciembre 2016 - 09:17

Primero que nada tomo nota del tema de que la relación pedido factura no es 1 a 1. Nunca se me pasó por la cabeza y la gente con la que he hablado tampoco. No tendría que cambiar casi nada de lo que ya está andando para incorporar algo así.
 
Mis sospechas se confirman, no he llegado al grado de abstracción que me gustaría, ya que no soy capaz de explicar el problema siquiera  :D
 
En realidad la clase que no se nombrar es una clase de soporte. Las fabricas ya existen, quiza no sea la mejor manera de encararlo, pero resumido maso es asi:
 
 


delphi
  1. IComprobante = interface
  2. function CrearDetalle: IDetalleComprobante;
  3. end;
  4.  
  5. IDetalleComprobante = interface
  6. function AgregarLinea: ILineaDetalle;
  7. function AgregarLineaCopiando(const OtraLinea: ILineaDetalle): ILineaDetalle;
  8. end;

 
Osea cada especializacion de Comprobante sabe crear a la clase concreta que mas conviene para su detalle, por ej:
 


delphi
  1. TComprobante = class abstract(TInterfacedObject, IComprobante)
  2. private
  3. FDetalle: IDetalleComprobante;
  4. protected
  5. function CrearDetalle: IDetalleComprobante; virtual; abstract;
  6. end;
  7.  
  8. TFactura = class(TComprobante)
  9. protected
  10. // crea una implementacion que crea instancias de TLineaDetalleFactura
  11. function CrearDetalle: IDetalleComprobante; override;
  12. end;

 
Y asi para el resto. Todas las clases que andan dando vuelta y se comunican entre si siempre hablan con las interfaces, eso esta clarito
 
Ahora, tema es este. Suponete que ya grabe un pedido o presupuesto (da lo mismo). Eso lo tengo que pasar a factura. Para eso instancio un form al que le paso en el constructor:
 


delphi
  1. IPreventa = interface(IComprobante)
  2. end;
  3.  
  4. TFacturadorPreventas = class(TForm)
  5. public
  6. constructor Create(const Preventa: IPreventa);
  7. end;

Supongamos que IPreventa es una interface que van a implementar los pedidos y los presupuestos, es decir, a mi lo unico que me interesa es que tienen una coleccion (un detalle) de productos que se encargaron o se reservaron. El punto clave es que esa coleccion no se toca, no puedo agregar ni sacar ni cambiar, eso ya esta "grabado" (es deseable que se mantenga el pedido original y que lo que se agrega en la factura solo figure en la factura, para detectar cosas "raras")
 
La clase que me genera problemas es "similar" al Detalle en el sentido de que mantiene una lista de lineas de detalle, que no son parte de la preventa original pero que se agregaron a ultimo momento. La clave es que esta solamente la conoce el form, por eso digo que es una clase de apoyo. Digamos que cuando se da la orden de "aceptar" o "confirmar", yo tengo que agarrar, crear un objeto TFactura y hacer un "merge" de los dos detalles que tengo: el de la preventa y el del form, a grandes rasgos es esto:
 


delphi
  1. procedure Confirmar;
  2. var
  3. Factura: IComprobante;
  4. EachLineaDetalle: ILineaDetalle;
  5. EachLineaExtra: ILineaExtra;
  6. begin
  7. Factura := TFactura.Create;
  8. for EachLineaDetalle in Preventa.Detalle do
  9. Factura.AgregarLineaCopiando(EachLineaDetalle);
  10.  
  11. for EachLineaExtra in DetalleExtraQueSoloConoceElForm do
  12. Factura.AgregarLineaCopiando(EachLineaExtra);
  13.  
  14. // grabar la factura en el sistema
  15. end;

 
En terminos visuales (quiza ayude a expresarme un poco mejor) seria esto:
 
Archivo adjunto  prev.png   138,44KB   0 descargas
 
En donde el primer grupo del ListView  (en este caso "Pedido") seria lo que aca llamo el "Detalle de la preventa", y en donde el segundo grupo del ListView (en este caso llamado "Factura") es lo que yo no se como se llama  :p. Es importante saber que en este momento el objeto Factura en si no existe (lamentablemente es codigo legado y esta muy muy mal diseñado y prefiero mantenerme lo mas lejos posible de la clase hasta el momento final que es cuando junto todo y lo mando a guardar a la BD)

 

Lo que yo tengo andando hoy dia es la conversion Pedido --> Factura. Lo que obviamente he ido buscando es ir usando herencia sobre los form para no tener copias de mas de lo mismo y hacer que todo ande redefiniendo o implementando un par de metodos.

 

unque como decia mas arriba, requiere subir mas el grado de abstraccion, o al menos llegar a algo que me deje conforme

 

PD: El apunte si que no entendi nada  :p


Editado por Agustin Ortu, 12 diciembre 2016 - 09:18 .

  • 0

#4 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 12 diciembre 2016 - 09:52

Me alegro saber que ya lo estabas encarando por el lado del patrón Factoría Abstracta. (y)

 

Respecto a lo de la relación entre factura y pedidos es (1,M) como te dije, es una visión muy habitual. Aunque no necesariamente quiere decir que tu concepción esté errada. Se le da ese carácter puesto que al no existir físicamente una factura, para marcar a lo largo del tiempo es que se confeccionan tantos pedidos como se necesiten.

Luego al momento de facturar se hace el merge que dices y se concibe la factura con todos los pedidos.

 

Ahora bien, en términos de implementación se necesita de un registro en la base de datos que hacen a esa "pila de pedidos". Lo que se suele hacer es justamente disponer de una tabla facturas con un campo flag que indica cuando se materializa o se confecciona. Mientras tanto permanece en ese "estado temporal". Como es de esperar, no se le da número, solamente cuando se imprime la factura hecha es que se le asigna el número y se cambia el flag a emitida.

 

En realidad a vos nada te impide ese trabajo, y como bien dices, es algo relativamente trivial.

Parte de este mismo principio lo puedes llevar justamente para el caso que te preocupa. ¿No consideraste que en lugar de disponer de dos detalles (uno "fijo" y el otro con los "extras") en simplemente tener un único detalle y disponer un campo flag/boolean que te permita diferenciarlos? Porque se podría detectar esas "rarezas" que dices en base a este campo y/u otros adicionales.

Ahora, si deseas mantener esa doble lista, no me parece mal la idea que el nombre sea Adicionales. Después de todo, es justamente eso: extras, detalles adicionales no contemplados.

 

Respecto a que no se se entendió el apunte pues... quizá debí haberlo escaneado con mejor calidad :p :D

 

Saludos,


  • 1

#5 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 12 diciembre 2016 - 10:16

Creo que ahora sí me entendiste un poco mejor. El tema es que unir en una única lista me lleva al condicional if que siempre trato de evitar. Y además me complica las factories porque la línea de detalle adicional (me gusta adicionales!!) responde a una interfaz que es descendiente de la genérica (otro gran motivo por tener fuera de la jerarquía del comprobante la clase que administre los adicionales).

Como ves por ahí los botoncitos esos de eliminar y modificar, esos están habilitados para los adicionales pero no para los que ya vienen. Si agrego el flag boolean voy a tener siempre el if. Y hay otros pormenores más que deberia tener en cuenta

Lo extraño es eso quizá: son parecidas, están ahí cerca pero son colaboradores separados. Como decía el diseño viejo si que no puedo tocarlo hasta que algún día con mucha paciencia lo revea tranquilo y prefiero mantener distancia. Lo viejo es el típico modelo anemico, que sigue más el paradigma procedimental que oo y como obviamente no tengo test (y aunque quisiera escribirlos sería difícil, porque como toda cosa mal diseñada es difícil de testear) y siendo que se trata de casi la columna vertebral busque un enfoque de modo tal que se pueda integrar cosas que por como son los requerimientos necesariamente están relacionadas y son dependientes pero dentro del código no lo son tanto pero por este motivo

Los patrones para solucionar los "problemas del constructor" los estoy aplicando todo el tiempo. Diria que son los más útiles, no existe una sola aplicación que se me venga a la mente en los que no uses factory method, abstract factory, y también en menor medida builder. Estos tres se han convertido en mis favoritos sin duda y vienen muy bien a la hora de escribir tests, aunque sirven para muchas más cosas


En algunos días tenía pensado liberar algunas pequeñas bibliotecas que tengo por ahí dando vueltas en la que se ve uso y abuso de los mismos.

Editado por Agustin Ortu, 12 diciembre 2016 - 10:17 .

  • 0

#6 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 12 diciembre 2016 - 11:25

Por cierto, a nivel tabla si que existen flags para conocer el estado de los pedidos. En este punto no me molestan porque se trata de modelo relacional; además en algún lado tengo que guardar como vos decís el estado. Tanto los pedidos como el presupuesto saben responder al mensaje estado. De hecho las fábricas se basan en eso para crear una instancia aún más concreta según corresponda. Difieren en cosas como el formato con el que se imprimen, si pueden ser o no anulados, si se anulan el proceso puede ser distinto (unos reflejan stock mientras que otros no)

Se puede conocer fácilmente en que fecha de confeccionó un pedido, cual es su estado actual, y cual es la factura o pedido en que se convirtió en caso de haberlo hecho. Por eso como decía, el mayor problema que le veo hoy a una relación 1 a M es más de experiencia de usuario que de proceso interno

Y ya casi me estaba olvidando de darte las gracias..
  • 0

#7 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 13 diciembre 2016 - 05:25

Me alegro que te haya gustado el nombre.

Si te estuve entendiendo, aunque a mi parecer no viene mal tener ambas listas en una.

Es cierto que te implica trabajar con condicionales, pero tampoco es una muerte. Yo también me he planteado el dilema de tener 2 listas o una. En el hilo en donde yo buscaba la forma de reubicar un índce. Yo lo pensé en un momento pero fueron más las necesidades que me dijeron que las necesito juntas.

 

Si dichos usuarios no han experimentado una situación de (1,m) quizá no valga la pena considerarlo. Debe ser una situación o naturaleza propia, alguna forma de trabajar de ellos que hace que la relación que se han detectado consista en un (1,1).

Al menos para mi, en las experiencias que he tenido, y es más en las prácticas en la universidad ya preveíamos una relación de uno a muchos entre facturas y pedidos. Ya verás si te vale la pena considerarlo. Si te sobra tiempo, o si después de conversarlo bien con la gente ves que resulta apropiado, ahí si lo implementaria asi. Si lo dejaría como ya lo tienes.

 

Comparto tu sentir... tocar demasiado un sisteme heredado de otro es dolor de hue***. Se la piensa mucho antes de tirar todo y comenzar de cero o armarse de valor y continuar como estaba. Mi práctica profesional para técnico fue así: me dieron un sistema que lo habían comenzado otro chico que abandonó y me dijeron "ahora es esto es tuyo" Tenía un mes. Tuve que hacer magia y tentarme no mandar todo a la mierda... ha... y encima era en VB. Asi que vos ves...

 

Saludos,


  • 1

#8 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 13 diciembre 2016 - 01:23

Comparto tu sentir... tocar demasiado un sisteme heredado de otro es dolor de hue***. Se la piensa mucho antes de tirar todo y comenzar de cero o armarse de valor y continuar como estaba. Mi práctica profesional para técnico fue así: me dieron un sistema que lo habían comenzado otro chico que abandonó y me dijeron "ahora es esto es tuyo" Tenía un mes. Tuve que hacer magia y tentarme no mandar todo a la mierda... ha... y encima era en VB. Asi que vos ves...

 

Lo mas lindo es que esa porqueria la escribi yo mismo  :dlaug:  :dlaug:  :dlaug: al menos hoy me doy cuenta de a que me enfrento. Que se le va a hacer, al menos me di cuena que hoy estoy mejor que hace unos años


Editado por Agustin Ortu, 13 diciembre 2016 - 01:33 .

  • 0

#9 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 13 diciembre 2016 - 03:12

Lo mas lindo es que esa porqueria la escribi yo mismo  :dlaug:  :dlaug:  :dlaug: al menos hoy me doy cuenta de a que me enfrento. Que se le va a hacer, al menos me di cuena que hoy estoy mejor que hace unos años

 

Entonces no es una porquería. Las porquerías no las escribe uno, las hace otro... Te falta práctica, asi que ya sabes: siempre hay que decir que fue otro  :D  Recuerda que si hiciste algo y con el tiempo no te gusta como quedó, no es un error, ni defecto, es una característica diversificada no tradicional. Las macanas propias no existen. :angel:

 

Saludos,


  • 1

#10 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 13 diciembre 2016 - 05:14

Entonces no es una porquería. Las porquerías no las escribe uno, las hace otro... Te falta práctica, asi que ya sabes: siempre hay que decir que fue otro  :D  Recuerda que si hiciste algo y con el tiempo no te gusta como quedó, no es un error, ni defecto, es una característica diversificada no tradicional. Las macanas propias no existen. :angel:

 

Saludos,

 

Como dicen por acá, son puntos de mejora :D :D :D
 

Saludos


  • 0




IP.Board spam blocked by CleanTalk.