Identificar metodos en OOP

Iniciado por GonzaFz, 15 Enero 2018, 17:45 PM

0 Miembros y 1 Visitante están viendo este tema.

GonzaFz

Estoy estudiando diseño de sistemas y me estoy comiendo la cabeza con la definición de algunos métodos. Lo que me cuesta identificar es quien debe llevar a cabo algunos métodos.

El escenario con el que estuve practicando es muy simple: "Un laboratorio de analisis clinicos ha comenzado el desarrollo de un sistema para la registracion de los analisis realizados por sus pacientes y el profesional que los solicita".

Partiendo de eso identifique cuatro clases: Paciente, Medico, Laboratorio y Analisis.

  • Paciente: representa una persona que se atiende en el laboratorio
  • Medico: representa un profesional de la salud
  • Analisis: representa un estudio solicitado por un medico especifico para un paciente determinado
  • Laboratorio: representa la clinica donde los medicos realizan analisis a los pacientes

De ahi pase a realizar el digrama de clases UML teniendo en cuenta que:

  • Un paciente puede tener muchos analisis. El paciente debe conocer los analisis que se realizo
  • Un medico puede haber solicitado muchos analisis. Debe tener cuenta de los analisis que requirio



Mi problema es que ese diagrama no me convence porque no tengo forma de asegurar que cuando se ejecuta paciente.addAnalisis(a), el analisis a ya haya sido cargado en el laboratorio.

Para ponerlo de otra forma, cualquiera que tenga acceso a un objeto Paciente podria agregar un analisis al paciente sin cargar ese mismo analisis al laboratorio y/o medico correspondiente. Lo mismo pasaria para un medico, cualquiera que tenga una referencia al medico podria cargarle un analisis sin tambien agregarlo al laboratorio ni al paciente. Esto supongo que generaria mucha inconsistencia en el sistema.

Yo podria implementar esa logica en Laboratorio::addAnalisis(a: Analisis), pero de nuevo, nada impide que alguien se salte esto y lo agregue manualmente.


Entonces mi otra solucion fue elminar los metodos addAnalisis y getListaAnalisis tanto de medico como de paciente, y luego agregar dos metodos a Laboratorio:

  • getAnalisisByPaciente(p: Paciente): Analisis[0..*]
  • getAnalisisByMedico(m: Medico): Analisis[0..*]

En este caso solo podria agregar analisis desde la clase Laboratorio, y asi implementar toda la logica necesaria en un solo lugar. Verifico que el medico y paciente asignado al analisis existan y luego lo agrego a la lista.
El problema es que ahora no estaria reflejando lo de que un paciente y un medico tienen que llevar cuenta de los analisis realizados.

Entonces no se como es la forma correcta de resolver esto.

Quizas no me deberia importar que alguien pueda llamar a Paciente.addAnalisis() y me estoy complicando por nada

Perdon por la falta de coherencia en todo esto pero tengo una ensalada en la cabeza y no se como explicarlo mejor. Saludos

Serapis

#1
Esto se resolvería mejor con una base de datos, peor vamos si tienes que operar con objetos, se debe considerar ciertas tablas reunidos en los objetos que has definido.
Un modo eficiente sería más complejo, porque requeriría varios objetos más, tales com un despachador de citas y otro de eventos y algunos notificadores, varias colecciones, etc...

Veamos... la mejor forma es mirar la cuestión de forma lógica es suponer la situación 'real', en 'tiempo real'. Un ejemplo...

El paciente tiene un problema médico, llama por teléfono a la clínica y reclama una cita con el médico que corresponda (quizás tenga uno asignado).
El día de la cita, acude al médico, y relata su problema.
El médico tras escuchar al paciente, decide que se le realice una analítica y le da cita para la analítica o bien lo pone en cola del laboratorio quienes le llamarán cuando encuentren hueco...
El paciente regresa para que le hagan la analítica (extracción de sangre, entrega de orina... por ejemplo).
El laboratorio, toma la muestra (o quizás otro personal de la clínica, o en otro lado), el caso es que la muestra llega al laboratorio donde se analiza (donde recogen las muestras y donde se realicen las analíticas podrían ser sitios diferentes).
Al paciente se le insta a regresar x día, para los resultados de la analítica, o se le señala que ya se le llamará para indicarle la fecha de recogida (o bien le deriva a la cita del médico, quien le entrega los resultados).
Una vez que el laboratorio concluye la analítica entrega los resultados (digamos que deposita un informe en el ordenador, asociado al historial del paciente).
Cuando el paciente tenga fecha de entrega o bien va a recoger los resultados al laboratorio y luego vuelve a pedir cita al médico, o mejor acude al médico quien ya tiene los resultados en su ordenador, y le indicará el tratamiento o lo que proceda.

Viendo el transcurso, puede dibujarse el flujo... y al mismo tiempo crearse una primera aproximación a los objetos necesarios.

Paciente: Básicamente tendrá algunos datos y lo demás serán métodos.
 Datos: informaticos del paciente, nombre apellidos, id de paciente, historia clínica (una tabla con su historial).
 PedirCita: el paciente reclama una cita. podría ser genérica rellenando ciertos campos, ó podría reclamar por un especialista específico. Normalmente es lo primero.
 AcudirACita: para explicar su problema al médico, para recoger la analítica, recoger medicación, para exploración, toma de muestras...
 AsignarMedico, CambiarMedico: Lo razonable es que si tiene asignado un médico, se le asocie un id al médico, en tal caso, sus peticiones de cita, podría llevar tal id. Mejor aún, es que el propio sistema verifique si el aciente (con su nombre y apellidos y número médico tiene ya asociado un médico, y si no es el caso, se le propone un formulario más amplio para rellenar (darse de alta en dicha clínica, ser socio, etc..)...
 ConsultarCita: El paciente consulta si tiene citas pednientes, en tal caso se le devuelven una lista con las fecha, hora, lugar y especialista...

Medico:
  Datos: Nombre y apellidos, id en la clínica, id de colegiado, especialidad, horario, etc...
  Agenda: Es una colección en realidad, Es una selección de citas, para el día presente, indica que citas tiene a qué hora y con qué paciente. En la propia agenda se señala la razón de la cita: (entevista al paciente, entregar análisis, seguimiento de un tratamiendo, etc..)
  ConsultarAgenda: Dados unos datos, devolver las fechas que se encuentren (por ejemplo, dados un nombre de paciente y apellidos, o su id de paciente). Varios tipos de consulta... que serán sobrecargas.
  SolicitarAnalisis: El médico solicita un ánalisis para un paciente, para ello adjunta: id del médico, id del paciente, id del tipo de análisis, como devolución de la solicitud, podría recibirse la cita exacta o aproximada, si es aproximada, será la gestión del  laboratorio quien mediante el id del paciente, obtenga su tf. para indicarle cuando proceda la fecha exacta para el ánálisis, o bien la enfermera del médico que al recibir la notificación de la fecha del análisis (en la agenda del médico), deba llamar al paciente para citarle en el laboratorio...

Laboratorio: El laboratorio debe gestionar las citas para la recogida de muestras y (quizás también) las citaciones para la entrega de los resultados de la analítica. Tambien tendrá un método de consulta de dichas citaciones y un método de entregar resultados cuando éstos estén listos.
   Datos: id de laboratorio, lista de Ids de analíticas que puede realizar, etc... (en general si la clínica dispone de un solo laboratorio, parece que el id no fuera necesario, pero es conveniente prever que eso cambie a futuro, y mientras la tabla de IDs no va a crecer, luego no importa que se añada aunque no tenga un uso intensivo de momento, es previsión de futuro).
   Agenda: Igual que el médico tiene citas a x hora, el laboratorio tiene las suyas...
   CitacionesRecogidaMuestras: Dada una cola de solicitudes de analíticas, ofrece fecha y hora para cada tipo de analítica (y como se dijo en un apartado previo, o bien desde aquíse gestiona directamente la citación del paciente, obien se devuelve al médico que lo solicitó como parte de su agenda y ya desde allí se informa. Parece más sensato que fuera desde aquí, en orden a que el paciente pueda si fuera preciso, alterar la fecha (retrasarla), si no le va bien la fecha y hora propuesta...
   CitacionesEntregaAnalíticas: Como lo previo, otra cola que gestiona las citas de los pacientes cuando la analítica ya está lista. Concordando con el paciente una fecha y hora, activa una cita en la agenda del médico que figura en la solicitud y entrega de la analítica. abrá analíticas que quizás sea el paciente quien deba recogerlas personalmente y con ella pedir cita al médico para su evaluación y tratamiento, etc... El sistema puede variar en función de si es ficiticio, o si un caso real exige uno u otro modelo o  está abierto a opciones.
   ConsultarCitas: Indicando la naturaleza de la cita (etega de muestras del paciente, o entrega de los resultados). Devuelve si hay cita para tal id de paciente, dados unos datos (el propio id, historia clínica, nombre y apellidos + tf., etc...) y desde aquí no se debería poder modificar ni eliminar citas, solo consultar...
   ModificacionCitas: Si un paciente quiere cancelacir, adelantar o posponer una cita, tras tener los datos de su cita (sea porque la recibió de 'citacionesRecogida...' ó citacionesEstrega...' o mediantye ConsultarCitas, puede alterar la fecha.
   EntregaDeAnaliticas: El laboratorio tras competar una analítica debe entregar el resultado. Lo mejor es que el resultado se quede en la base de datos y en la Agenda del médico se añada un ítem de consulta al historial clínico del paciente referido. La enfermera del médico, cada díal o primero que hará por la mañana es revisar los ítems pendientes de revisar y solicitar la citación al paciente a la consulta del médico para entregarle los resultados, indicarle el tratamiento, etc... otra alternativa como se dijo, es que se entregara directamente al paciente. Si esto último, no será el sistema usado entonce sla funcionalidad de: "CitacionesEntregaAnalíticas", debería retirarse de este objeto y ser añadido a la del médico.
   Procesar: Se supone que habrá un método procesar analítica, en realidad es un hueco cde tiempo en la cita, tal que el profesional en el laboratorio retira una cita para efectuar la analítica y pulsa 'entregar' a su finalización, luego pulsa otra vez en procesar para recibir la siguiente analítica... Si la agenda es la lista de citas (tareas), esto sería marcar que la está atendiendo, es decir responde al sistema... que aitende una y al final cuando para cerrarla modifica el estado, indicando el resultado que porceda... por ejemplo: Paciente no vino, muestra desechada, analitica finalizada, etc...

Clinica: La clínica enlaza todo, debiera ser el objeto principal. Relaciona pacientes con médicos y médicos con laboratorio. La base de datos rige en la clínica, los demás objetos consultan a la clínica, para todo.    
   PedirCita: Recoge los datos del paciente, nombre apellidos o id de paciente, y si es posible, especialista para el que pide cita, si no será su médico asociado y naturaleza de la consulta...
   AltaPaciente: Si un paciente solicita una cita y no tiene Id en la clínica se le da de alta en la misma como paso previo a la cita.
   AltaCita: Una vez realizada la petición de cita, se realiza una consulta a la Agenda del médico (cuyo id ya quedo claro) en busca de un hueco libre en la fecha que solicita el paciente, si la hay se la da si no, s ele propone la primera fecha y hora libre, etc... Si acepta finalmente se inscribe la cita en la agenda del médico.
   AltaMedico: Cuando un médico se adjunta a la clínica.
   AltaLaboratorio: Lo mismo, cuando se adjunta un nuevo laboratorio a la clínica

  (Nota: Aunque se llamen Alta... también debiera gestionar la baja, si resultare complejo, entonces mejor que sea una función aparte). El alta, genera el Id en cada caso (de paciente, de médico, de cita, de laboratorio, de analítica, etc...

Analitica: Es un objeto que recoge lo preciso que se reclama.
    Datos: Id paciente, id medico, id analisis, fecha citacion recogida de muestras, fecha aprox de entrega de resultados (sin confirmar). Id analitica previa relacionada, Id analítica posterior relacionada.
    Resultados: Texto (y/o imágenes)  que describen el resultado de los que se solicitó.
    Estado: un valor de enumeración que describa el estado del ítem: Recibido solicitud de analítica, buscando fecha para citar al paciente entrega de meustras, pactando fecha de entrega de muestras con el paciente, espera hasta fecha de cita, entrega de muestras realizada, envio al laboratorio (especialista que realiza el análisis), analizando muestras, analitica realizada, pactar fecha de entrega de resultados, espera hasta fecha de entrega, entrega realizada, pactar fecha citacion medido para evaluacion, espera hasta dicha fecha, evaluación y tratamiento de los resultados (cuando el paciente acude ya al médico) y desde aquí deriva hacia otro frente si contínúa se abre otro expediente con el que se relaciona
    Fecha de estado: Cada estado puede a su vez tener un campo fecha, que señala la fecha y hora en que pasa de un estado a otro, así puede hacerse un seguimiento si resulta preciso.
    EstadoFinal: Estado que indica que sucedió tras que el médico diera los resultados al paciente. Podría ser: finalizado, o podría ser solitatud de una analítica adicional, o podría ser nueva analítica tras 3 meses, ingreso en clínica, etc... (incluso fallecimiento dle paciente antes o durante el proceso).

Imaginemos una aplicación... la interfaz de la misma son los datos externos, crudos del paciente. Por dentro hay un objeto paciente, el objeto paciente actúa sobre el objeto clínica, en general entregando una referencia del objeto paciente
   
Básicamente tu concepto está bien, aunque hay algunas inconsistencias y la manera de evitar lo que temes es usar colas que quedan ocultas al resto de objetos. Dichas colas actúan temporizadas, resuelta una tarea de la cola se toma la siguiente, la propia tarea mantiene una referencia al objeto al que debe entregar los resultados (en forma de evento)...

Por ejemplo: Paciente.AddAnalisis(a), no es correcto.
Lo razonable sería: Laboratorio.ModificacionCitas(operacion = "ADD", analitica a)
A esto se ha llegado tras el "Analitica a = Médico.CrearAnalitica(IdMedico, IdPaciente, IdAnalitica, Motivacion)" // un texto del médico describiendo textualmente lo que sea preciso. El id Analítica identifica que se reclama, probablemente sea una confunción y requiera más parámetros un id podría representar simplemente una espcialidad y otro id más específico , las variedades de esa especialidad, por ejemplo una analítica de sangre puede solicitar 2-3-4 decenas de parámetros, luego el id, sería un entero donde cada bit indica si uno de esos analisis se requieren: hemoglobina, colesterol, glóbulos blancos, plaquetas, etc...
Y para llegar al 'CrearAnalitica, ants se ha hecho un Clinica.PedirCita (paciente p, motivo m)
Motivo podría ser otro pequeño objeto, qeu rápidamente aclare la razón de la cita al médico, incluso un cuestionario relleno, o solo un texto, o unos pocos atributos, tipo: Ya ha realizaod una consulta previa por el mismo motivo?.
Y para llegar a PedirCita, el paciente ha creado el objeto paciente rellenando su datos.

Paciente p = Clinica.Login(Nombre, apellidos, idPaciente) // si id paciente=vacio, se entiende un alta, o bien que no recuerda su id, en cuyo caso si existe algún paciente con ese nombre y apellidos se le podrá indicar que elija entre: Ya soy paciente de esta clínica y entonces pedir su número de identificación personal (en España se llama DNI, en otros lares cédula de identidad) o incluso el tf. (por si hay más de 1 perosna coincidente en nombre y apellidos), o bien No soy cliente aún en esta clínica, y solicitarle que rellene mas datos o bien informarle que al encuentro de su cita deberá rellenar más datos...


Paciente p = Clinica.Login(Nombre, apellidos, idPaciente)
Si p.Logueado =True luego 
   Cita c= Clinica.PedirCita (paciente p, motivo m)
    Si c.Estado=EnCurso luego  //si se acepta
        Citas.AddEnCola(c, "TomaDeMuestras")
    fin si
fin si


Más adelante... cuando al paciente se le da la cita y acude al médico.

Analitica a = Médico.CrearAnalitica(IdMedico, IdPaciente, IdAnalitica, Motivacion)
Si a.Estado=Creada luego
   Cita c = Analiticas.AddEnCola(analitica a) //y devuelve una cita
    Si c.Estado=encurso luego
       Citas.AddEncola(c, "EntregaResultados", Estado=Solicitud)
   fin si
fin si


Como ves a la hora de ir describiendo en pseudocódigo ya te van saliendo otros objetos... Cita: es un objeto que recoge los siguientes datos:
   Idcliente (lo relaciona con Paciente, mediante él tenemos acceso a más datos del paciente).
   IdMedico: (ídem con médico).
   Motivo: Razón de la citya, una enumeración... consultamedico, entregamuestras, recogidaresultados
    Estado: de la cita... otra enumeración que señala las fases por las queatraviesa, la gestión interna actúa en función de este estado.
    FechaProgramada: obvio...

Igualmente Citas es una colección de citas. Hay más colecciones también obvias, como Pacientes, que es donde mediante el IdPaciente entrega un objeto paciente. El ide puede ser un hash obtenido a partir de algunos de sus datos: nombre, apellidos, DNI, telefono, algún número de registor interno y algún dato que permanece en propiedad de la clínica.
También es obvio que habrá una colección Medicos, y Laboratorios y que sus respectivos Ids, hacen lo priopio que para paciente.
Medicos, Citas, Pacientes, Laboratorios, Analiticas, todas son un mismo objeto colección que se diferencia exclusivamente por el tipo de objeto que almacenan, los métodos que tienen son los mismos, Add, Remove, GetById, GetByName, GetByETC... y todas esas colecciones son privadas dentro del objeto clínica...
Los objetos "Agenda", también son una colección pero algo distinta es una selección de 'citas' ó 'Analíticas' para el día vigente, asociado a una fecha específica y quizás duración' (tiempo concedido aprox. para ello).
Ahora que ves claro las colecciones, puesdes ver más claro las inconsistencias que te decía... laboratorio, no requiere métodos addMedico, addPaciente... laboratorio, recibe analiticas, en un estado dado y las entrega en otro estado, conocerá el número de analiticas pendientes o el de servidas, y tendrá la Agenda del día...

El problema es que describir un entorno completo en este campo es tan grande como uno quiera hacerlo o tan simple como también uno quiera hacerlo, pero a buen seguro te saldrá una veintena de objetos para manejarlo de modo eficiente...

Además es preciso tomar algunas decisiones sobre algunos aspectos para elegir un modelo cuando hay varias opciones (como los casos que he planteado respecto de la forma de 'entregar los resultados', o formalizar las citas a través de la enfermera del médico (que se´ria lo más personalizado para el paciente), ó centralizado desde el objeto Citas (que sería lo más óptimo, pero más rígido), ó que las realice el departamente especializado al que se recurre (laboratorio, por ejemplo para analíticas), que es lo más óptimo de cara al profesional y la gestión interna eficiente del tiempo). Dichas decisiones determinan la forma, en que se opera, los objetos que deben crearse y la relación o 'trazado' que han de tener las llamadas a funciones...

Creo que ya tienes para inspirarte y avanzar, luego si tienes alguna duda específica, plantéala...

srWhiteSkull

Laboratorio en este caso es una entidad estática, o por lo menos yo lo entiendo así. Si el caso figurara que existen diversas clínicas-laboratorio, habría que instanciar y por lo tanto habría que crear alguna propiedad que distinguiera a cada instancia(por ejemplo nombre de la clínica o una id), como una clave primaria. Lo mismo pasa con Paciente. Si deseamos crear un análisis para determinado paciente el laboratorio debe asociar el paciente, por lo tanto la función pienso que debería ser así : Laboratorio::addAnalisis(paciente) y retornar Analisis . Luego el paciente solicita al laboratorio los analisis : paciente.getAnalisis() en un caso de Laboratorio estático, paciente.getAnalisis(laboratorio) para el caso de que se pueda escoger un laboratorio. Ambos casos retornarían una colección de Analisis [0..*]

... así que tampoco necesitas el Laboratorio::getPaciente(...) porque ninguna entidad lo requiere por como está descrito en el ejercicio... en fin, no quiero mojarme a ver si vas a suspender por mi propio razonamiento... pero yo lo haría así.

GonzaFz

#3
Muchas gracias a ambos. Demore en responder porque estaba procesando todo, mas lo que me respondieron tambien en stackoverflow.

Me han aclarado la mente, tan mal estaba que hasta formule mal la pregunta inicial, en realidad tendría que haber sido sobre como definir quien debe implementar cada requisito del sistema, pero lo que me respondieron me sirvio mucho, la conclusión es que tengo que sentarme a leer sobre patrones, y en particular sobre GRASP.

Supongo que toda mi confusión viene porque en una materia de la facultad nos hicieron desarrollar una aplicación con JavaEE donde las entidades eran solo modelos de datos, y toda la logica estaba ubicada en otra capa. Al parecer esto se conoce como "Anemic domain model".
De ahi que no podia conectar en mi cerebro otra forma de ver la orientacion a objetos, segun wikipedia ese modelo es anti-oop.


NEBIRE, simplemente gracias por el analisis tan completo.

WhiteSkull en cuanto a que Laboratorio tendria que ser una entidad estatica es cierto, segun el escenario el sistema es para un solo Laboratorio/Hospital, de todas formas entiendo que NEBIRE hizo un analisis mas completo, suponiendo algunas otras cosas y por eso su diseño es diferente.
Tambien tenes razon sobre lo de devolver el paciente, me olvide de aclarar que en otro ejercicio me lo pedian que lo incluya, a igual que con los medicos.


Ahora tengo otra duda con respecto al diseño/arquitectura como lo plantee inicialmente, dado que el sistema debe poder devolver un medico y un paciente si el usuario se lo pide, y suponiendo que uno quiere saber los analisis de un paciente y los analisis que un medico solicito.
Cuales serian las formas correctas de modelar esto?

  • 1- Podria hacer que paciente y medico conozcan cuales son los analisis en los que participan, pero para ello tendria que implementarles un metodo addAnalisis() a ambos, y eso implica que no tengo forma de contolar que al agregar un analisis a un paciente, tambien se lo haga al medico que lo solicito. Es decir, podria, pero nada quita que en alguna parte del programa alguien llame a Paciente::addAnalisis() y pase por alto hacerlo tambien al medico, y que paciente se encargue de cargar al medico y viceversa me generaria problemas de acoplamiento
  • 2- Lo de arriba me lleva a pensar que podria generar una clase que funcione como repositorio de analisis, y que nunca este expuesta fuera de Laboratorio, Paciente y Medico. De esta forma, al llamar a Laboratorio::addAnalisis(), cargaria el analisis al repositorio, y luego Paciente::getAnalisis() haria una consulta al repositorio. De esta forma me evitaria tener los metodos Laboratorio::getAnalisisByPaciente() y Laboratorio:getAnalisiByMedico()
    En parte seria plantear lo mismo que puse en mi primer post pero de una forma mas elegante, sin sobrecargar demasiado a Laboratorio

Serapis

#4
Más o menos ya te respondí... pero me extiendo con más detalle (en alguna parte, no con todo que es muy largo)

Debes crear una clase que es una colección de análisis, que son internas al objeto clínica.

El médico cuando solicita un análisis, lo crea 'vacío', con los datos del paciente y que se análisis se desea y se inserta en la colección de análisis, con el estado adecuado, y deja en cola del laboratorio un objeto 'notificación', que el laboratorio usará para rescatar la analítica y genera el objeto 'citacion' para citar al paciente. El laboratorio, cuando reciba el objeto notificacion, sabrá que debe hacer con ella, rescatando el objeto analítica creada por el médico, donde constan los datos de lo que se solicita, quien lo solicita y para quien se solicita, ****

Entonces el laboratorio dará la cita al paciente, actualiza el estado del objeto análisis (que pasa a fase 'citado') y encola en la agenda del laboratorio, para el día de la cita, la entrega de muestras-extracción,etc.. , cuando las muestras se hayan realizado, se actualiza de nuevo el estado del análisis y ahora ese análisis pasa a la agenda del laboratorio. Cuando el laboratorio procese la muestra, vuelve a actualizar el análisis, ahora además de cambiar el estado, rellena los datos del resultado de la analítica, y el sistema genera otro objeto citación (en el objeto clínica, o médico depende de quien gestiones las citaciones como te dije en el mensaje anterior) para el paciente (ahora para que acuda al médico), y una vez citado a consulta, se actualiza de nuevo los datos de estado del análisis, y se deposita en la agenda del médico para el día de la citación.

Cuando llegue el día de la citación, el médico consulta su agenda y con el id del análisis haría una consulta al análisis... es todo privado, el paciente es un objeto, pero dentro de la clínica, físicamente el paciente no tiene acceso a nada, tan solo se le cita, interacciona con personas... tampoco estaría mal una 'web' de la clínica para consultas, haciendo login y usando su "id de paciente", para revisar sus citaciones, etc...

Así escribiendo sobre la marcha, la cascada de sucesos con los objetos podría ser algo como esto:


paciente p= Clinica.Login(string idPaciente)
citacion c = Clinica.PedirCita(paciente p, especialista e, motivo m)

Motivo podría ser un objeto, un valor enumerado o un simple string con o sin formato.
Al pedirCita, lo que hará esa función puede variar si es atendido por personal humano o  es automático. Si se atiende exclusivamente por personal humano, se encola y cuando los operarios de la clínica lleguen a esa petición, llamarán al paciente para concertar día y hora. si es automático, lo lógico es que sacara una ventana con un calendario para elegir día y hora (posibilidad de cambiar mes), desactivando horas ocupadas y tachando días que no se pasa consulta.

Pongamos que el usuario ya rellenó dichos datos, pués ahora se crea un objeto citación y se guarda en la coleccion de citas, se pasa una entrada del íd de cita a la agenda del médico para el día y hora concertada. Retomando desde atrás...

El paciente solicitar una cita en la clínica para el especialista deseado, en una fecha elegible (entre las libres)

Buleano = Funcion SolicitarCita(string idPaciente)
    paciente p= Clinica.Login(string idPaciente)
    Si (p.Estado=ErrorLogin) luego
        // indicar el motivo del error, fallo en id paciente no resgistrado, etc...
        Devolver FALSE
    Fin si

    citacion c = Clinica.PedirCita(paciente p, especialista e, motivo m)
    Si (c.estado=EsperandoSeleccionFecha) luego
        calendario f = = Clinica.Medicos(Especialista e).GetCalendario //selecciona el calendario disponible para el médico/especialista
        f.ShowCalendario  // se muestra la ventana al usuario para que elija la fecha.
        Si (f.Estado=FechaSeleccionada) luego // otro estado posible sería Cancelado.
            c.fecha = f.fecha // copia la fecha elegida a la citación
            Clinica.Citaciones.Add(citacion c)    // añade la citación a la colección de citaciones
            Clinica.Medicos(especialista e).Agenda.add(c.fecha, Id p.IdPaciente)  //asienta la cita en la agenda del especialista
            Devolver TRUE
        sino
            // cancelado, el paciente desisitó de seleccionar fecha. Es raro que aquí ocurriera un problema, pero podría pasar, por ejmplo un problrma temporal con el espacialista/médico.
            Devolver FALSE
        fin si
    sino
        // cancelado o algún problema responder según corresponda
        devolver FALSE
    fin si
fin funcion


Tras la citación... y llega el día ...damos por hecho que el médico tiene su programa permanentemente abierto, pero vamos al punto donde toma la citación del paciente de su agenda.

El especialista pulsará en un botón similar a: "Siguiente Cita" y el botón haría algo similar a esto:

Funcion BotonSiguienteCita_Click
    citacion c = Agenda.Next
    paciente p = Clinica.GetPacienteById(c.IdPaciente)
    // mostrar en la ventana certos datos de la cita y el paciente, por ejemplo:
    textboxNombrePaciente.Texto = p.Nombre + p.Apellidos
    textboxMotivo.Text = c.Motivo
    textboxFecha.Text = c.fecha.Tostring
    textboxDuracionConsulta= c.Duracion.ToString // según el tipo de consulta puede requerir x minutos.... el médico debe gestionar su tiempo, procurando ajustarse a ello... exacto nunca va a ser, pero le ayudará...
    // el especialista, o la enfermera si dispone de ella entonces lee el nombre apellidos, verifica la hora y el tiempo que puede dedicar, lee el motivo de consulta y acto seguido llama al paciente... que se supone que acude
   // incluso podría proveerse un sistema de TextToSpeech, conectado a un altavoz:
    tts.Talk("Se llama al señor" + textboxNombrePaciente.Texto + "acuda a la consulta nº" + medico.Room + "del Dr." + medico.Alias)
Fin funcion

Si el paciente no entra, lo vuelve a llamar, si no comparece, lo deja (no lo elimina d ela agenda), si la clínica tolera cierta flexibilidad, tovadía podría atenderlo más atarde, mediante un botón no de "siguiente Cita", si no de "cita por nombre", que muestra el listado con al menos dos columnas,  el nombre de los pacientes y hora de la cita. Es posible que el médic o vaya adelantado sobre el horario y por tanto haya pacientes que aún no hayan legado, o que uno se retrase, pero al atender al siguien te, el retrasado puede ocupar el puesto del que es atendido...

Damos por hecho que el médico le atiende, y pongamos que al final le tiene que pedir una analiítica...


funcion BotonSolicitarAnalitica_Click
    analitica a = ElegirYRellenarAnalitica  // se elige el tipo de analítica y se rellenan los datos
    Si (a.Estado = creado) luego  // Si no hubo problemas, ni se canceló, etc...
        string IdAnalitica = Clinica.Analiticas.Add(a)    // se añade a la colección de analíticas de la clínica, y devuelve un Id, usado para identificarlo en la colección.
        notificacion n = Clinica.GenerarNotificacion(origen="medico", destino="laboratorio", Id=IdAnalitica) // una notificación es para enviar eventos de un objeto a otro,
        // se indica un origen y un destino y tendrá más campos, unos genericos y otros específicos,
        // un Id que representa el id de una colección de donde se debe rescatar el objeto que versa la notificación
        n.ColeccionId= "analitica"
        n.Motivo = "citacion muestras"
        n.Urgente = FALSE
        n.Destino.Notificar(n)  // genera un evento en el objeto destino (el laboratorio), que encola la notificación, a la espera de que los operarios puedan atenderla.
    fin si
fin funcion

El evento notificar, entrega la notificación, que contiene el objeto remitente (en el ejemplo Medicos), para saber de donde procede, luego se acompaña de otros datos. Por eejmplo como se acompaña de un Id, debe sabersea que colección pertenece el id, por eso el miembro ColeccionId, lo aclara, tomarán de la colección:
Analitica a = Clinica.Analiticas.GetById(n.Id)
el motivo aclara que se está pidiendo al laboratorio, que realicen una citación para extracción/recogida de uestras la paciente que figura en la analítica, solicitada por el médico. Datos que figuran en la analítica...

El objeto Medico, Laboratorio, Clinica, etc... tienen todos un evento o método Notificar(notificacion n), así es posible hacer notificaciones que se encolan de unos a otros. Si es Urgente, al meterse en la cola, antecede a todos los no urgentes en la colección.

Evento Notificar(notificacion n)
    string idNotifica = Laboratorio.Notificaciones.Add(n, n.Urgente)   // se añade la notificación en la cola de notificaciones.
    // Notificaciones es una agenda no preparada, con horario, cuando se atiende una se retira y se atiende la siguiente, sin horario específico.
   // tiene a diferencia d ela Agenda, una variacion en el método ADD, la colección mantiene  un índice señalando donde terminan las urgentes, s
fin evento


Añadiendo una notificación a  una colección (se ha supuesto una colección basada en una lista enlazada).
éste sería un método de la colección 'notificaciones', diferentes objetos mantienen una colección de este tipo...

string = Funcion Add(notificacion n, buleano urgente)
    n.IdNotifica = Hash(n, GlobalItems)
    GlobalItems +=1
   
    Si (urgente = TRUE) luego
        entero k = IndexUrgentes
        notificacion u= Notificaciones.GetByIndex(k)
        n.Siguiente = u.Siguiente
        n.Siguiente.Anterior= n
        u.Siguiente = n
        n.Anterior = u

        IndexUrgentes += 1
    sino
        notificacion u = Notificaciones.Ultima
        u.Siguiente = n
        n.Anterior = u
        Notificaciones.Ultima = n
    fin si

    Items +=1
   
    Devolver n.IdNotifica
fin funcion


Eliminado una notificación de una colección...

Buleano = Funcion Delete(entero Index)
    notificacion n
    Si (Index = 0) luego
        n = Primera
        Primera = n.Siguiente
        n.Siguiente.Anterior = nada
        n.Siguiente = nada       
    oSi (Index= (Items-1)) luego
       n = Ultima
       Ultima = n.Anterior
       n.Anterior.Siguiente = nada
       n.Anterior = nada
    sino
        Si (index>0) y (index < Items) luego
            k=1
            n= Primera.Siguiente
            Mientras k < index
                n = n.Siguiente
            Repetir

            n.Anterior.Siguiente = n.Siguiente
            n.Siguiente.Anterior = n.Anterior
            n.Siguiente = nada
            n.Anterior = nada
        sino
            Devolver FALSE
        fin si
    fin si

    Si (n.Urgente = TRUE) luego
        IndexUrgentes -=1           
    fin si
    Items -=1   
    n = nada

    Devolver TRUE
fin funcion


Alguien en el laboratorio, reclama la siguiente notificación, para procesarla....

funcion BotonSiguienteNotificacion_Click
    Si (Items >0) luego
        notificacion n = Notificaciones.Primera       
        Notificaciones.Eliminar(0) // se elimina de la colección, pero reside aún, gracia a al referencia 'n'
        DespacharNotificacion(n)
    sino
        mensaje "no quedan notificaciones pendientes..."
    fin si
fin funcion


Ejemplo de una función que despacha notificaciones, en este caso para el laboratorio...
Según el tipo de notificación se abrirá una ventana que se rellena con los datos procedente de la notificación...
Se va a lo rápido asumiendo que las funciones invocadas serealizan desde interfaz de usuario en general... luego aquí son 'pasos'...

funcion DespacharNotificacion(notificacion n)
    Seleccionar n.ColeccionId
        caso "analitica"
            analitica a = Clinica.Analiticas.GetById(n.Id)
            Selecionar n.Motivo
                caso "citacion muestras", "citacion entregas"                   
                       paciente p = Clinica.Pacientes.GetById(a.IdPaciente)
                       Seleccionar n.Contacto
                           caso "email"
                               fecha f = Laboratorio.Agenda.GetPrimeraFechaLibreParaMuestras                               
                               rellenarEmail(p.email, textoCitacion, f)
                               enviarEmail
                           caso "telefono"                             
                               calendario f = Laboratorio.ShowAgenda //se abre una ventana con fechas que un operario ve si está libre y la propone al paciente                               
                               llamadaTelefono(p.TelefonoDecontacto, textoCitacion, f)  // se informa por teléfono de la fecha de la
cita para recogida de muestras.
                                Hacer
                                       f= Calendario.OtraFechaLibre
                                Mientras paciente no acepte f
                           caso "carta", "mensajero"
                               fecha f = Laboratorio.Agenda.GetPrimeraFechaLibreParaMuestras                               
                               rellenarCarta(p.direccion, p.Nombre + p.Apellidos, textoCitacion, f)
                               Si (n.Contacto= "carta") luego
                                    EntregarCartaEnBuzon  // la carta se introduce en un buzón de correos, se supone que la fecha tiene un plazo mayor que elde entrega de la carta.
                               sino
                                    Llamaramensajero
                                    EntregarCartaAMensajero // un mensajero lleva la carta al domicilio del paciente. 
                               fin si
                       Fin seleccion
                caso "analizar"
                    // se lleva a cabo la analítica por el operario correpondiente, quien al término actualiza los datos que correpondan en la analítica.
                caso ...
                    ...
                ... más casos
            fin seleccion
            a.fecha = f
            a.Estado = citado

        caso "citacion"
            citacion c = Clinica.Citaciones.GetById(n.id)
            ...
        caso "medico"
            medico m = Clinica.Medicos.GetById(n.Id)
            ...
        caso "..."
            ....
        .....
    fin seleccionar

    n.Eliminar
fin funcion


Se elige el tipo de analítica y se rellenan los datos

Analitica a = Funcion ElegirYRellenarAnalitica
    Analitica a= Clinica.ShowTiposDeAnalitica  //muestra al médico una lista con los tipos de analíticas disponibles, el médico elige la que corresponda
    Si (a.Estado=NoCancelado) luego
        a.ShowRellenarDatosSolicitud  // una ventana emergente con los datos específicos que deben rellenarse,
        // algunos serán elegibles haciendo click en sus casillas,
        // otros lo rellenará a mano
        // y otros se pueden hacer por código, como los siguientes:
        a.IdMedico = m.IdMedico   // m es el objeto medico del que se loguea cuando prende su ordenador.
        a.IdPaciente = p.IdPaciente
        ... // más cosas
        a.Estado = creado
        Devolver a   
    fin si
fin funcion


Esta función sería del objeto clinica.

notificacion n = Funcion GenerarNotificacion(string origen, string destino, string Id)
     notificacion n

     Seleccionar origen
          Si origen = medico luego
              n.origen = Medicos  // objeto medicos.
          oSi origen = "laboratorio" luego
              n.Origen = Laboratorio  // si hubiera varios, sería la colección.
          oSi origen = ....
              n.Origen = ....
          ...
          fin si
    fin seleccion

    Seleccionar destino
          Si destino = "medico" luego
              n.Destino = Medicos  // objeto medicos.
          oSi destino = "laboratorio" luego
              n.Destino = Laboratorio  // si hubiera varios, sería la colección.
          oSi destino = ....
              n.Destino = ....
          ...
          fin si
    fin seleccion

    n.Id = Id
    n.Fecha = Ahora
   
    Devolver n
Fin funcion


Y aquí lo dejo de momento.... todo el pseudocódigo expuesto, cumple solo el primer párrafo del comienzo (4 líneas), resolver todo (los otros párrafos) con este escaso pero significativo nivel de detalle, me llevaría 2 ó 3 horas... Creo que debieras ser capaz de seguir tú, ya, desde aquí...

Ten en cuenta que a medida que lo vas planteando en pseudocódigo, vas viendo la luz, el camino a seguir... sale solo y acabas corrigiendo pequeños errores en los conceptos previos... también date cuenta que cuando pases a nivel de código, es fácil que vuelvas a cambiar algo que en pseudocódigo se veía bien, por algo que en el lenguaje es más cómodo, dominas mejor, etc... y como te dije puede ser mucho más complejo (por extenso), o sencillo (por breve), por eso la fase previa de análisis de requisitos, es clave para avanzar en la senda que te reclaman... y no profundizar en una jungla si no te lo piden.