Code Monkey home page Code Monkey logo

prog-practica-libre-trimestre-2-lnarote777's Introduction

Review Assignment Due Date

Actividad: Desarrollo de Proyecto Software en Kotlin

ID actividad: 2324_PRO_u4u5u6_libre

Agrupamiento de la actividad: Individual


Descripción:

La actividad consiste en el desarrollo de un proyecto software en Kotlin, permitiendo al estudiante elegir la temática. Este proyecto debe demostrar la comprensión y aplicación de los conceptos de programación orientada a objetos (POO), incluyendo la definición y uso de clases, herencia, interfaces, genericos, principios SOLID y el uso de librerías externas.

Objetivo:

  • Demostrar comprensión de los fundamentos de POO mediante la instanciación y uso de objetos.
  • Aplicar conceptos avanzados de POO como herencia, clases abstractas, e interfaces.
  • Crear y usar clases que hagan uso de genéricos.
  • Aplicar principios SOLID.
  • Integrar y utilizar librerías de clases externas para extender la funcionalidad del proyecto.
  • Documentar y presentar el código de manera clara y comprensible.

Trabajo a realizar:

  1. Selección de la Temática: Elige un tema de tu interés que pueda ser abordado mediante una aplicación software. Esto podría ser desde una aplicación de gestión para una pequeña empresa, una herramienta para ayudar en la educación, hasta un juego simple. Define claramente el problema que tu aplicación pretende resolver.

  2. Planificación: Documenta brevemente cómo tu aplicación solucionará el problema seleccionado, incluyendo las funcionalidades principales que desarrollarás.

  3. Desarrollo:

    • Instancia de Objetos: Tu aplicación debe crear y utilizar objetos, demostrando tu comprensión de la instanciación y el uso de constructores, métodos, y propiedades.
    • Métodos Estáticos: Define y utiliza al menos un método estático, explicando por qué es necesario en tu aplicación.
    • Uso de IDE: Desarrolla tu proyecto utilizando un IDE, aprovechando sus herramientas para escribir, compilar, y probar tu código.
    • Definición de Clases: Crea clases personalizadas con sus respectivas propiedades, métodos, y constructores.
    • Clases con genéricos: Define y utiliza al menos una clase que haga uso de genéricos en tu aplicación.
    • Herencia y Polimorfismo: Implementa herencia y/o interfaces en tu proyecto para demostrar la reutilización de código y la flexibilidad de tu diseño. Usa los principios SOLID: Ten presente durante el desarrollo los principios SOLID y úsalos durante el diseño para mejorar tu aplicación.
    • Librerías de Clases: Integra y utiliza una o más librerías externas que enriquezcan la funcionalidad de tu aplicación.
    • Documentación: Comenta tu código de manera efectiva, facilitando su comprensión y mantenimiento.
  4. Prueba y Depuración: Realiza pruebas para asegurarte de que tu aplicación funciona como se espera y depura cualquier error encontrado.

  5. Contesta a las preguntas ver el punto Preguntas para la Evaluación

Recursos

  • Apuntes dados en clase sobre programación orientada a objetos, Kotlin, uso de IDEs, y manejo de librerías.
  • Recursos vistos en clase, incluyendo ejemplos de código, documentación de Kotlin, y guías de uso de librerías.

Evaluación y calificación

RA y CE evaluados: Resultados de Aprendizaje 2, 4, 6, 7 y Criterios de Evaluación asociados.

Conlleva presentación: SI

Rubrica: Mas adelante se mostrará la rubrica.

Entrega

La entrega tiene que cumplir las condiciones de entrega para poder ser calificada. En caso de no cumplirlas podría calificarse como no entregada.

  • Conlleva la entrega de URL a repositorio: El contenido se entregará en un repositorio GitHub.
  • Respuestas a las preguntas: Deben contestarse en este fichero, README.md

Preguntas para la Evaluación

Este conjunto de preguntas está diseñado para ayudarte a reflexionar sobre cómo has aplicado los criterios de evaluación en tu proyecto. Al responderlas, asegúrate de hacer referencia y enlazar al código relevante en tu README.md, facilitando así la evaluación de tu trabajo.

Criterio global 1: Instancia objetos y hacer uso de ellos

  • (2.a, 2.b, 2.c, 2.d, 2.f, 2.h, 4.f, 4.a): Describe cómo has instanciado y utilizado objetos en tu proyecto. ¿Cómo has aplicado los constructores y pasado parámetros a los métodos? Proporciona ejemplos específicos de tu código.

// Se cargan los archivos guardados antes de empezar
val gestionClientes = GestionClientes()
val polizas = PolizaMoto(gestionClientes) //solo es para llamar a la funcion
gestionClientes.guardarClientesDelArchivo()
polizas.guardarPolizasDelArchivo()
He instanciado dos objetos de las clases GestionClientes y Polizas en el main para utilizar los mettodos que guardan los datos que ay en los archivos de clientes y polizas en una lista que usaré a lo largo del programa para facilitar las búsquedas y demás sobre las listas.

También para llamar a las funciones de consola, he instanciado en las funciones que las utiliza un objeto de cosola.

Criterio global 2: Crear y llamar métodos estáticos

  • (4.i): ¿Has definido algún método/propiedad estático en tu proyecto? ¿Cuál era el objetivo y por qué consideraste que debía ser estático en lugar de un método/propiedad de instancia?

Si. En las clases Poliza y GestionClientes.

abstract class Poliza(val gestor: GestionClientes) {
companion object {
//Resguardo de las pólizas. Cuando empiza el programa se cargan las pólizas del archivo a la lista para operar más fácilmente
val polizas = mutableListOf<MutableMap<String, List<Any>>>()
private val path = "src/main/kotlin/baseDatos/polizas.txt"
private val archivo = File(path)
}
*/
class GestionClientes {
companion object{
private val path = "src/main/kotlin/baseDatos/Clientes.txt"
private val archivo = File(path)
//Resguardo de los clientes. Cuando empieza el programa se cargan los clientes del archivo a la lista para operar más fácilmente
private val datosClientes = mutableListOf<Cliente>()
}
El objetivo de esto era asegurar que solo existiera una instancia compartida de la lista de base de datos (polizas) en lugar de que cada instancia de Poliza y GestionClientes tuviera su propia lista.

  • (2.e): ¿En qué parte del código se llama a un método estático o se utiliza la propiedad estática?

    /**
    * Guarda una póliza en el archivo de registro.
    *
    * @param poliza El mapa de datos que representa la póliza a guardar. Debe contener la información de la póliza
    * en el formato especificado.
    */
    fun guardarPoliza(poliza: MutableMap<String, List<Any>>) {
    try {
    polizas.add(poliza)
    val fileWriter = FileWriter(archivo, true)
    val bufferedWriter = BufferedWriter(fileWriter)
    bufferedWriter.write(poliza.toString())
    bufferedWriter.newLine()
    bufferedWriter.close()
    consola.mostrarInfo("Polizas guardada correctamente")
    } catch (e: Exception) {
    consola.mostrarInfo("***Error***")
    }
    }
    En la función guardarPoliza de la clase Poliza, se utiliza la propiedad estática polizas que se encuentra dentro del companion object. Esta propiedad se utiliza para agregar la póliza recién creada a la lista de pólizas existente en la clase Poliza y añadirla al archivo de polizas.

Criterio global 3: Uso de entornos

  • (2.i): ¿Cómo utilizaste el IDE para el desarrollo de tu proyecto? Describe el proceso de creación, compilación, y prueba de tu programa.

    El IDE ha sido de gran ayuda en cuanto simplificación de código y corrección de errores de sintaxis. El modo de depuración ha sido una herramienta fundamental para ejecutar mi programa paso a paso, detectar y corregir errores.

Criterio global 4: Definir clases y su contenido

  • (4.b, 4.c, 4.d, 4.g): Explica sobre un ejemplo de tu código, cómo definiste las clases en tu proyecto, es decir como identificaste las de propiedades, métodos y constructores y modificadores del control de acceso a métodos y propiedades, para representar al objeto del mundo real. ¿Cómo contribuyen estas clases a la solución del problema que tu aplicación aborda?

    En este proyecto se definen diferentes tipos de clases,como data class, enum class y abstract class

    Usando estas clases de ejemplo, contribuyen significativamente a la solución del problema abordado por la aplicación, ya que proporcionan una estructura clara y coherente para representar la información de los clientes y los tipos de pólizas.

Criterio global 5: Herencia y uso de clases abstractas e interfaces

  • (4.h, 4.j, 7.a, 7.b, 7.c): Describe sobre tu código cómo has implementado la herencia o utilizado interfaces en tu proyecto. ¿Por qué elegiste este enfoque y cómo beneficia a la estructura de tu aplicación? ¿De qué manera has utilizado los principios SOLID para mejorar el diseño de tu proyecto? ¿Mostrando tu código, contesta a qué principios has utilizado y qué beneficio has obtenido?

    -Herencia y/o uso de interfaces En la herencia se ha utilizado para representar diferentes tipos de pólizas de seguro. Cada una hereda de una clase base común 'Póliza' la cual permite compartir funcionalidades y comportamientos comunes entre ellas. Con esta herencia se facilita la extensión de la aplicación. Se usa la interfaz Menu para definir unos métodos comunes para los diferentes menús del proyecto. Este enfoque facilita la reutilización del código , le da flexibilidad con el uso de la interfaz y una gran facilidad de mantenimiento.

    -Principios Solid -SRP - Principio de responsabilidad única. En este proyecto, cada clase tiene una responsabilidad clara y específica. Por ejemplo, la clase GestionClientes se encarga de la gestión de clientes, mientras que las clases PolizaMoto, PolizaHogar, etc., se ocupan de la gestión de diferentes tipos de pólizas.

    /**
    * Clase para gestionar clientes.
    * Permite añadir, dar de baja y buscar clientes, así como realizar operaciones de validación y manipulación de archivos.
    */
    class GestionClientes {
    companion object{
    private val path = "src/main/kotlin/baseDatos/Clientes.txt"
    private val archivo = File(path)
    //Resguardo de los clientes. Cuando empieza el programa se cargan los clientes del archivo a la lista para operar más fácilmente
    private val datosClientes = mutableListOf<Cliente>()
    }
    val consola = Consola<String>()
    val mensaje: String
    get() = "*** No puede dejar este campo en blanco ***"
    /**
    * Añade un nuevo cliente al archivo de registro.
    *
    * @param cliente El cliente que se va a añadir al archivo de registro.
    */
    fun altaCliente(cliente: Cliente){
    try {
    datosClientes.add(cliente)
    val fileWriter = FileWriter(archivo, true)
    val bufferedWriter = BufferedWriter(fileWriter)
    bufferedWriter.write(cliente.toString())
    bufferedWriter.newLine()
    bufferedWriter.close()
    println("Cliente añadido correctamente")
    }catch (e: Exception){
    println("***Error - al añadir cliente***")
    }
    }
    /**
    * Da de baja a un cliente con el DNI especificado.
    *
    * @param dni El número de DNI del cliente a dar de baja.
    */
    fun bajaCliente(dni: String){
    val cliente = buscarCliente(dni)
    try {
    if (cliente != null){
    datosClientes.remove(cliente)
    val lineas = archivo.readLines().filter { !it.contains(cliente.toString()) }
    archivo.writeText(lineas.joinToString("\n"))
    println("cliente eliminado")
    }else{
    println("No se pudo dar de baja porque no existe ningún cliente con dni: $dni")
    }
    }catch (e: Exception){
    println("*** Error Interno ***")
    }
    }
    /**
    class PolizaMoto(gestor : GestionClientes) : Poliza(gestor) {
    /**
    * Registra una nueva póliza en el sistema.
    * Se solicitan los datos del cliente, se genera un ID único para la póliza, se obtiene la fecha de alta,
    * y se almacenan estos datos junto con los datos específicos de la póliza en el sistema.
    * Finalmente, se guarda la información de la póliza en el archivo de registro.
    */
    override fun grabarPoliza() {
    val datosCliente = gestor.pedirDatosCliente()
    val tipoPoliza = TipoPoliza.MOTO
    val id = generarId()
    val fecha = generarFechaAlta()
    datosCliente.polizas[id] = tipoPoliza
    val datosMoto = datosEspecificos()
    val datos = listOf(datosCliente, datosMoto, fecha)
    poliza[id] = datos
    gestor.altaCliente(datosCliente)
    guardarPoliza(poliza)
    }
    /**
    * Recolecta los datos específicos de una póliza de moto, incluyendo la matrícula, marca y modelo.
    * Solicita al usuario introducir estos datos a través de la consola.
    * @return Una lista mutable que contiene la matrícula, marca y modelo de la moto.
    */
    override fun datosEspecificos(): MutableList<Any> {
    val moto = mutableListOf<Any>()
    val matricula = pedirMatricula()
    val marca = pedirMarca()
    val modelo = pedirModelo()
    moto.add(matricula)
    moto.add(marca)
    moto.add(modelo)
    return moto
    }
    /**

    -OCP - Principio de Abierto/Cerrado. Este principio sugiere que las entidades de software deben estar abiertas para la extensión pero cerradas para la modificación. En el proyecto, este principio se aplica en las clases de gestión de pólizas (PolizaMoto, PolizaHogar, etc.). Cada una de estas clases es fácilmente extensible para agregar nuevos tipos de pólizas sin modificar el código existente. Por ejemplo, si se quiere agregar una nueva póliza de salud, se puede crear una nueva clase PolizaSalud sin modificar las clases existentes.

    -LSP - Principio de Sustitución de Liskov. Este principio establece que los objetos de un programa deben ser reemplazables por instancias de sus subtipos sin alterar la corrección del programa. En el proyecto, la herencia se utiliza de manera efectiva para representar diferentes tipos de pólizas (PolizaMoto, PolizaHogar, etc.) que comparten ciertas características y comportamientos comunes pero también tienen comportamientos específicos.

    abstract class Poliza(val gestor: GestionClientes) {
    companion object {
    //Resguardo de las pólizas. Cuando empiza el programa se cargan las pólizas del archivo a la lista para operar más fácilmente
    val polizas = mutableListOf<MutableMap<String, List<Any>>>()
    private val path = "src/main/kotlin/baseDatos/polizas.txt"
    private val archivo = File(path)
    }
    val consola = Consola<String>()
    val poliza = mutableMapOf<String, List<Any>>()
    abstract fun grabarPoliza()
    abstract fun datosEspecificos(): MutableList<Any>
    */
    class PolizaHogar ( gestor: GestionClientes): Poliza(gestor) {
    /**
    * Registra una nueva póliza en el sistema.
    * Se solicitan los datos del cliente, se genera un ID único para la póliza, se obtiene la fecha de alta,
    * y se almacenan estos datos junto con los datos específicos de la póliza en el sistema.
    * Finalmente, se guarda la información de la póliza en el archivo de registro.
    */
    override fun grabarPoliza() {
    val datosCliente = gestor.pedirDatosCliente()
    val tipoPoliza = TipoPoliza.HOGAR
    val id = generarId()
    val fecha = generarFechaAlta()
    datosCliente.polizas[id] = tipoPoliza
    val datosHogar = datosEspecificos()
    val datos = listOf(datosCliente, datosHogar, fecha)
    poliza[id] = datos
    gestor.altaCliente(datosCliente)
    guardarPoliza(poliza)
    }
    /**
    * Devuelve una lista mutable que contiene datos específicos sobre un hogar.
    * Se solicita al usuario que introduzca la dirección, el número de habitaciones,
    * el número de personas habitantes y el número de puertas del hogar.
    *
    * @return Una lista mutable que contiene los datos específicos del hogar.
    */
    override fun datosEspecificos(): MutableList<Any> {
    val hogar = mutableListOf<Any>()
    println("Introduzca los siguientes datos:")
    val direccion = pedirDireccicon()
    val habitaciones = pedirHabitaciones()
    val personasHabitantes = personasHabitantes()
    val nPuertas = pedirPuertas()
    hogar.add(direccion)
    hogar.add(habitaciones)
    hogar.add(personasHabitantes)
    hogar.add(nPuertas)
    return hogar
    }
    /**

    -ISP - Principio de Segregación de Interfaces. Este principio sugiere que los clientes no deben verse obligados a depender de interfaces que no utilizan. En el proyecto, se utilizan interfaces como Menu para definir comportamientos comunes a diferentes tipos de menús. Esto permite que los menús específicos implementen solo los métodos que necesitan, evitando la dependencia de funcionalidades no utilizadas.

    interface Menu <T> {
    val consola: Consola<String>
    get() = Consola()
    fun menu()
    fun respuesta(): T
    }
    class MenuClienteExist: Menu<Int> {
    override fun menu() {
    val menu = "----Bienvenido de nuevo, elija una opción:\n\t1. Contratar nueva póliza\n\t2. Darse de baja de Ocaso\n\t3. Ver pólizas contratadas\n\t4. Ver estado cliente\n\t0. Atrás"
    consola.mostrarInfo(menu)
    }
    override fun respuesta(): Int {
    print("--> ")
    val opcion = consola.pedirOpcion()
    return opcion
    }
    }

Criterio global 6: Diseño de jerarquía de clases

Criterio global 7: Librerías de clases

  • (2.g, 4.k): Describe cualquier librería externa que hayas incorporado en tu proyecto. Explica cómo y por qué las elegiste, y cómo las incorporaste en tu proyecto. ¿Cómo extendió la funcionalidad de tu aplicación? Proporciona ejemplos específicos de su uso en tu proyecto.

    He implementado la librería de junit para la realización del test que compruebe la funcionalidad de algunas funciones de mi código y que funcione correctamente.

    import org.junit.jupiter.api.Test
    import org.junit.jupiter.api.Assertions.*
    import org.practicatrim2.Clientes.GestionClientes
    class GestionClientesTest {
    @Test
    fun validarDni() {
    val gestor = GestionClientes()
    assertEquals(true, gestor.validarDni("7823723827387"))
    assertEquals(true, gestor.validarDni("87a87237e"))
    assertEquals(false, gestor.validarDni("43567762L"))
    }
    }

Criterio global 8: Documentado

  • (7.h): Muestra ejemplos de cómo has documentado y comentado tu código. ¿Que herramientas has utilizado? ¿Cómo aseguras que tu documentación aporte valor para la comprensión, mantenimiento y depuración del código?

    /**
    * Busca un cliente por su número de DNI.
    *
    * @param dni El número de DNI del cliente a buscar.
    * @return El cliente correspondiente si se encuentra, o null si no se encuentra ningún cliente con ese DNI.
    */
    fun buscarCliente(dni: String): Cliente? = datosClientes.find { it.dni == dni }
    El código ha sido documentado con la documentación correspondiente de Kotlin(KDoc). Como herramienta externa para facilitar y aligerar este proceso he utilizado la IA de ChatGpt. La documentación proporciona una pequeña descripción del funcionamiento de cada función y/o clase, además de comentarios adicionales en los puntos que considero que deben ser aclarados.

Criterio global 9: Genéricos

  • (6.f): Muestra ejemplos de tu código sobre cómo has implementado una clase con genéricos. ¿Qué beneficio has obtenido?

    He implementado el genérico en la interfaz de menú, en el método de respuesta para que según el tipo de menú puede variar el tipo de dato de la respuesta. El genérico le proporciona flexibilidad al código, ya que se puede usar cualquier tipo de dato.

    interface Menu <T> {
    fun menu()
    fun respuesta(): T
    }
    También en la clase que gestiona la consola.
    */
    open class Consola <T>{
    /**
    * Muestra un mensaje en la consola.
    *
    * @param mensaje El mensaje a mostrar.
    */
    fun mostrarInfo(mensaje: T) {
    println(mensaje)
    }

prog-practica-libre-trimestre-2-lnarote777's People

Contributors

lnarote777 avatar github-classroom[bot] avatar

Watchers

José Manuel avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.