Plataforma de E-Learning
Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy — lección 105 de 107.
Desafío
Fácil¡Vamos a construir una Plataforma de E-Learning que gestione cursos, estudiantes y realice un seguimiento del progreso de aprendizaje! Combinarás structs, interfaces, composición y polimorfismo para crear un sistema cohesivo donde los estudiantes puedan inscribirse en cursos y completar lecciones.
Organizarás tu código en cinco archivos:
lesson.go: Define un structLessonque representa unidades de aprendizaje individuales. Cada lección tiene unID,TitleyDuration(en minutos). Incluye un constructorNewLessonque devuelva un puntero a un Lesson.course.go: Crea un structCourseque contenga unID,Title,Instructory un slice de punteros*Lesson. Incluye un constructorNewCoursey un métodoAddLesson. También implementa un métodoTotalDuration() intque devuelva la suma de todas las duraciones de las lecciones en el curso.student.go: Define un structStudentcon los camposID,NameyEmail. Incluye un constructorNewStudent.enrollment.go: Aquí es donde ocurre la magia del seguimiento del progreso. Crea un structEnrollmentque vincule a un estudiante con un curso y rastree qué lecciones ha completado. Debe tener:- Un puntero al
Student - Un puntero al
Course - Un mapa
CompletedLessons(ID de la lección a booleano)
Define una interfaz
Progressablecon un métodoProgress() float64que devuelva un porcentaje (de 0.0 a 100.0).Implementa estos métodos en Enrollment:
NewEnrollment(student *Student, course *Course) *Enrollment— constructor que inicializa un mapa de lecciones completadas vacíoCompleteLesson(lessonID string) string— marca una lección como completada. Devuelve"lesson not found"si la lección no existe en el curso,"already completed"si ya se completó, o"completed"en caso de éxitoProgress() float64— devuelve el porcentaje de lecciones completadas (completadas/totales * 100), o 0.0 si el curso no tiene lecciones
- Un puntero al
main.go: Construye tu plataforma y procesa las operaciones de inscripción.Lee el ID, título e instructor de un curso. Luego lee el número de lecciones y el ID, título y duración de cada lección. Lee el ID, nombre y correo electrónico de un estudiante. Crea una inscripción vinculando al estudiante con el curso.
Luego lee el número de operaciones. Cada operación es
"complete [lessonID]"o"progress". Para las operaciones complete, imprime el mensaje de resultado. Para las operaciones progress, imprime el progreso formateado con un decimal seguido de un signo de porcentaje.
Se proporcionarán las siguientes entradas:
- ID del curso, Título, Instructor (3 líneas)
- Número de lecciones, luego el ID, Título y Duración de cada lección (3 líneas cada una)
- ID del estudiante, Nombre, Correo electrónico (3 líneas)
- Número de operaciones, luego cada operación (1 línea cada una)
Por ejemplo, dado:
C001
Go Fundamentals
Jane Smith
3
L001
Variables
30
L002
Functions
45
L003
Structs
60
S001
Alice
alice@learn.com
5
progress
complete L001
progress
complete L001
complete L002Tu salida debería ser:
0.0%
completed
33.3%
already completed
completedY dado:
C100
Python Basics
Bob Teacher
2
L100
Intro
20
L101
Loops
40
S100
Charlie
charlie@edu.com
4
complete L999
complete L100
complete L101
progressTu salida debería ser:
lesson not found
completed
completed
100.0%Observa cómo el struct Enrollment utiliza la composición para vincular a estudiantes y cursos, mientras que la interfaz Progressable permite que cualquier tipo informe su estado de finalización. Este diseño facilita la extensión: ¡podrías agregar seguimiento de progreso a lecciones individuales o rutas de aprendizaje completas utilizando la misma interfaz!
Pruébalo tú mismo
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Función auxiliar para leer una línea
readLine := func() string {
scanner.Scan()
return strings.TrimSpace(scanner.Text())
}
// Leer la información del curso
courseID := readLine()
courseTitle := readLine()
courseInstructor := readLine()
// TODO: Crear el curso usando NewCourse
_ = courseID
_ = courseTitle
_ = courseInstructor
// Leer el número de lecciones
numLessons, _ := strconv.Atoi(readLine())
// TODO: Leer cada lección y añadirla al curso
for i := 0; i < numLessons; i++ {
lessonID := readLine()
lessonTitle := readLine()
lessonDuration, _ := strconv.Atoi(readLine())
// TODO: Crear la lección y añadirla al curso
_ = lessonID
_ = lessonTitle
_ = lessonDuration
}
// Leer la información del estudiante
studentID := readLine()
studentName := readLine()
studentEmail := readLine()
// TODO: Crear el estudiante usando NewStudent
_ = studentID
_ = studentName
_ = studentEmail
// TODO: Crear la inscripción vinculando al estudiante con el curso
// Leer el número de operaciones
numOps, _ := strconv.Atoi(readLine())
// Procesar cada operación
for i := 0; i < numOps; i++ {
operation := readLine()
if operation == "progress" {
// TODO: Llamar a Progress() e imprimir con el formato "%.1f%%"
fmt.Println("0.0%") // Reemplazar con el progreso real
} else if strings.HasPrefix(operation, "complete ") {
lessonID := strings.TrimPrefix(operation, "complete ")
// TODO: Llamar a CompleteLesson e imprimir el resultado
_ = lessonID
fmt.Println("") // Reemplazar con el resultado real
}
}
}
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de POO en Go
Archivos externosEspacio de trabajo y módulos de GoPaquetes e importacionesNombres exportados vs. no exportadosIntroducción a la POO en GoStructs como clasesDefinición de métodos en structsReceptores de puntero vs. de valorInicialización de structsFunciones constructorasResumen - Calculadora simple4Interfaces
Introducción a las interfacesImplementación implícitaLa interfaz como contratoInterfaz vacía (any)Type AssertionType SwitchComposición de interfacesInterfaces Stringer y ErrorResumen: Calculadora de figuras7Encapsulamiento
Campos exportados vs. no exportadosEncapsulamiento a nivel de paqueteMétodos Getter y SetterOcultamiento de información en GoResumen - Registros de estudiantes10Genéricos (Go 1.18+)
Introducción a los GenéricosParámetros de tipoRestricciones de tipoStructs genéricosSolución alternativa para métodos genéricosResumen - Colección genérica13Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón Abstract FactoryPatrón ObserverPatrón Strategy2Inmersión profunda en Tipos y Structs
Tipos básicos y compuestosDefiniciones de tipos personalizadosEtiquetas de StructsStructs anónimosStructs anidadosValores cero y por defectoRepaso - Libreta de contactos5Composición sobre herencia
Por qué Go no tiene herenciaConceptos básicos de incrustación de structsPromoción de métodosIncrustación de múltiples structsIncrustación vs AgregaciónShadowing de métodos incrustadosResumen - Jerarquía de empleados8Manejo de Errores y OOP
La interfaz errorTipos de errores personalizadosEnvoltura de errores (fmt.Errorf)Errores centinelaerrors.Is() y errors.As()Panic, Defer y RecoverResumen - Analizador de archivos3Punteros y Memoria
Fundamentos de punteros en GoPunteros a StructsPaso por valor vs referenciaLa función new()Garbage Collection en GoResumen - Constructor de Linked List6Polimorfismo en Go
Polimorfismo mediante interfacesDuck Typing en GoReglas de satisfacción de interfacesColecciones polimórficasInyección de dependenciasResumen - Procesador de pagos9Concurrencia y POO
Fundamentos de GoroutinesChannels y comunicaciónChannels con buffer vs. sin bufferSentencia Selectsync.Mutex y sync.RWMutexsync.WaitGroupDiseño de estructuras Thread-SafeResumen - Worker Pool