Fecha y hora actual: Domingo 25 Ago 2019 05:29
Índice del Foro

Foros de programación informática, diseño gráfico y Web

En esta comunidad intentaremos dar soporte de programación a todos los niveles, desde principiantes a profesionales de la informática, desarrollo de programas, programación web y mucho más.

Programando desde 0: 43- Descripción Nomina de Personas.

Responder al Tema

Índice del Foro > Programación en general > Programando desde 0: 43- Descripción Nomina de Personas.

Autor Mensaje
Kyshuo Ayame
Moderador Global


Registrado: 07 Ene 2011
Mensajes: 1043

Mensaje Publicado: Lunes 02 Ene 2012 18:46

Título del mensaje: Programando desde 0: 43- Descripción Nomina de Personas.

Responder citando

Lección 43: Descripción Nomina de Personas

Veremos en esta lección el planteo de un nuevo problema que nos llevará a diseñar un pequeño sistema básico de gestión. Veremos en esta lección un acercamiento a dos temas importantes: Acoplamiento y Cohesión, sin embargo no profundizaremos en ellos demasiado a lo largo de esta parte del curso.

Respecto al problema que veremos, tendremos toda su descripción en esta lección pero no toda su implementación, ya que todo junto sería muy extenso. Este pequeño sistema y sus análisis nos llevarán tres lecciones aproximadamente teniendo en cuenta esta.

-------------------------------------------------------------------------------------

Un sistema muy pequeño: Nómina de personas

Sabemos entonces qué es un TAD, o al menos tenemos una idea bastante acertada al respecto. Es así entonces que haremos un pequeño sistema de solo tres módulos llamado NominaPersonas, el cual tendrá una lista de personas en la que podremos agregar una nueva persona o quitar una existente entre otras cosas. Supongan entonces que es un pequeño sistema de gestión de personas. Utilizaremos el módulo Persona que ya hemos implementado para crear un nuevo módulo llamado ListaPersonas el cual será el encargado justamente de manejar el listado de personas del sistema.

La ilustración de dependencias será entonces así:



Ese tipo de dibujos ayuda mucho a visualizar qué es lo que hay que hacer, es decir que, tomar antes lápiz y papel para pensar en el problema es una gran idea. Uno generalmente tiende a sentarse a escribir código sin pensar mucho antes a qué se atiene. Sin embargo hay que tener bien presente el diseño antes de querer programar algo.

Descripción del problema: Imaginen que la empresa que nos pide el software escribe lo siguiente:

Nuestro personal está en constante movimiento, lo cual implica que cada día existe una gran cantidad de altas y bajas de funcionarios, así como también se nos hace necesario modificar y consultar los datos de todos ellos para distintas tareas. Hoy día esto se hace a mano mediante planillas, sin embargo esto lleva mucho tiempo por lo cual es ineficiente, además de que se está propenso a muchos errores. Las búsquedas de datos entre tantos ficheros se hace casi imposible.

Es así que nuestra empresa solicita se cree un software que nos permita ingresar los datos de nuestro personal, modificar dichos datos, realizar búsquedas y gestionar altas y bajas de manera constante.


Entonces nosotros como diseñadores debemos tener una reunión con la empresa para comenzar a hablar los detalles:

¿Qué datos tiene una persona? ¿Qué tipo de consultas desean realizar? ¿Qué tipo de búsquedas y cómo serán realizadas? ¿Qué dato será clave? ¿Podrá cualquier persona utilizar el sistema o no?

En fin, habría muchas cosas que negociar y afinar, eso siempre sucede porque describir bien un problema que será solucionado programando software no es sencillo. De este modo, supongamos que los diseñadores han logrado obtener todo lo que necesitan y nos pasan a nosotros, programadores (en realidad somos los implementadores del diseño), la siguiente letra:

Cita:
Se pide implementar un sistema llamado Nómina Personas el cual permita gestionar un listado de funcionarios como se describirá más adelante. Cada funcionario tendrá los siguientes datos:

  • Nombre
  • Apellido
  • Edad
  • Documento
  • SueldoPorHora
  • HorasTrabajadas


El sistema podrá ser usado sin problemas por lo que no se pedirá ningún tipo de validación o contraseña. Las funcionalidades que se esperan son las siguientes:

Altar funcionario: Permitirá dar de alta a un nuevo funcionario para el cual se ingresarán los datos mencionados más arriba, en el siguiente formato:

Código:
Ingrese el documento--> Un valor para el documento
Ingrese el nombre---> Un nombre para el funcionario
Ingrese el apellido---> Un apellido para el funcionario
Ingrese la edad---> Un valor para la edad
Sueldo a ganar por hora---> Un valor para el sueldo a ganar
Horas trabajadas---> Un valor para las horas trabajadas


El nuevo funcionario será ingresado a la lista de funcionarios en el sistema, ordenado de forma ascendente según su documento.
Control:
    **No debe existir un funcionario con un documento idéntico al que se va a ingresar.
    **La edad debe ser mayor que 20 años.
    **Si el sueldo a ganar por hora ingresado es menor que 50 entonces se establecerá en 50.
    **Si las horas trabajadas ingresadas corresponden a un valor negativo entonces se establecerán en 0.


Bajar funcionario: Permitirá dar de baja a un funcionario que ya está de alta, para el cual solo se ingresará la cédula.

Control: Debe existir un funcionario con un documento idéntico al que se ingresa para bajar.

Buscar por documento: Desplegará en pantalla los datos de un funcionario incluyendo el sueldo ganado, dado su documento. Si el documento no está de alta entonces se desplegará el mensaje “El documento ingresado no corresponde a un funcionario que esté de alta en el sistema.”.
La búsqueda debe ser realizada por bipartición. El formato de muestra es el siguiente:

Código:
Documento: ValorDelDocumento
Nombre: NombrePersona
Apellido: ApellidoPersona
Edad: EdadPersona
Sueldo por hora: ValorDelSueldo
Horas trabajadas: CantidadDeHorasTrabajadas
Sueldo ganado: ValorDelSueldoGanado.


Modificar datos: Permitirá modificar los datos de un funcionario dado su documento, pidiendo que se ingrese todo nuevamente, como si fuera el alta.

Control:
    **El documento del funcionario cuyos datos se modificarán debe estar de alta.
    **Luego de ingresados los nuevos datos se debe controlar lo mismo que cuando se da de alta.


Listar funcionarios: Mostrará en pantalla el documento, el nombre y el apellido de todos los funcionarios que estén dados de alta en ese momento, según el siguiente formato:

Código:
Documento1 Nombre1 Apellido1
Documento2 Nombre2 Apellido2
. . .
DocumentoN NombreN ApellidoN


Control: Si la lista de funcionarios está vacía se desplegará el mensaje “No hay ningún funcionario dado de alta en el sistema.
Para cualquier otro error se desplegará el mensaje “Ha habido un error.”.

Al abrir el programa se mostrará el siguiente mensaje:
Código:

Bienvenido a Nomina de Personas
Por favor, ingrese el comando deseado para realizar una operación:
>> 


Los posibles comandos a ingresar por el usuario son:

listarFuncionarios
altarFuncionario
bajarFuncionario
modificarDatos
buscarFuncionario
salir
ayuda


Cada vez que se ingresa un comando, se realizarán las tareas descritas más arriba, luego se volverá a mostrar el prompt

>>

y el programa quedará a la espera de un nuevo comando.

Todos los comandos se corresponden con una de las operaciones ya descritas, excepto salir y ayuda. El primero simplemente cerrará el programa. El segundo mostrará el listado de comandos posibles y una descripción de lo que hace:

Código:
listarFuncionarios: Muestra un listado de todos los funcionarios ingresados al sistema.
altarFuncionario: Da de alta a un nuevo funcionario al sistema.
bajarFuncionario: Da de baja a un funcionario existente en el sistema.
modificarDatos: Modifica todos los datos de un funcionario existente en el sistema.
buscarFuncionario: Busca y muestra los datos de un funcionario dado su documento.
salir: Salir del sistema.
ayuda: Desplegar la ayuda.


Cada vez que se ingrese un comando no válido, el programa deberá mostrar el mensaje:

Código:
ERROR. Ingrese un comando válido o tipee 'ayuda' para ver un listado.
>>




Algo muy importante y que debo destacar es que, como han visto, cada funcionalidad tiene uno o más controles a tener en cuenta. Estos controles se corresponden a los posibles errores que se pueden dar al intentar ejecutar una funcionalidad. Si todos los controles dan positivo, entonces se ejecuta la funcionalidad, en caso contrario debe mostrarse un mensaje de error.
Entonces, listaré nuevamente las funcionalidades y los controles, detallando el mensaje de error que se debe mostrar para cada uno en caso de que de negativo:



Como ven, a cada mensaje se le asocia un identificador. Estos identificadores son inventados por mi, podrían haber sido otros. Luego veremos cómo utilizarlos para representar a los mensajes de error en el sistema.

Perfecto, tenemos descrito un sistema básico de gestión de funcionarios. Como ven, no es tan básico y tiene sus cositas complejas. Lo que haremos es lo siguiente:

  • Crearemos un nuevo proyecto llamado NominaPersonas.
  • Crearemos un módulo principal llamado NominaPersonas.
  • Copiaremos el módulo Persona hacia nuestro nuevo proyecto. Para esto debemos:

      Copiar el archivo de definición en la carpeta DEF de nuestro nuevo proyecto.
      Copiar el archivo de implementación en la carpeta SRC de nuestro nuevo proyecto.


  • Agregaremos al tipo Persona el campo Apellido que será de TipoNombre, y por lo tanto agregaremos al módulo Persona las operaciones ModificarApellido y ObtenerApellido.
  • Implementamos las nuevas operaciones.


Para este ejemplo implementaré yo mismo todos los módulos. Les haré mucho énfasis en el uso correcto de comentarios ya que normalmente los módulos se programan para que puedan ser reutilizados, sea por nosotros mismos o por otra persona. Más adelante les pediré a ustedes que implementen los módulos que iremos diseñando para nuestros sistemas, de modo que aprendan realmente, y confiaré en que lo harán. De haber conceptos nuevos claro que lo haré yo para que puedan ver un ejemplo, pero luego tendrán que atacarlo ustedes.

Nuestro pequeño sistema, justamente por ser pequeño, está incompleto. ¿Por qué? Pues por varias cosas que se irán dando a medida que avancemos. Una de ellas es que la idea al crear un módulo es que este se encargue solo de sus tareas específicas y nada más. Esto se conoce como cohesión. Si nosotros creamos un módulo que tiene un bajo grado de cohesión significa que hace tareas muy diversas lo cual no es bueno por motivos que explicaré en breve.

Un alto grado de cohesión no significa “Hacer pocas cosas”, sino “Hacer cosas específicas”, las cuales pueden ser muchas. Nuestro módulo Persona se encarga solo y únicamente de crear un objeto Persona, manipular sus datos y eliminarlo. Podríamos por ejemplo, agregar a ese módulo una funcionalidad que permita manipular varias personas, es decir, un listado. Sin embargo, como vieron en la ilustración, crearemos un módulo específico para eso que se encargará solo y únicamente de manipular una lista de personas, nada más.

Como dije antes, nuestro programa está incompleto, porque como verán más adelante, nuestro módulo principal se encargará de hacer las gestiones con el módulo ListaPersonas y además se encargará de leer los comandos que se ingresan. Esto significa que hace cosas diversas, tiene baja cohesión. Lo bueno sería tener un módulo específico que ese encargue de leer los comandos, pero eso lo veremos luego.

Ahora bien, en estos ejemplos donde tenemos pocos módulos las dependencias entre ellos son mínimas, es más, las mínimas posibles. Sin embargo, existe algo llamado acoplamiento. El acoplamiento hace referencia a las dependencias de un módulo, es decir, un módulo que depende de muchos otros tiene alto acoplamiento y en contraparte si depende de pocos módulos tiene bajo acoplamiento.

Lo ideal para un módulo sería tener alta cohesión (hago solo lo que debo hacer) y bajo acoplamiento (dependo o me relaciono con pocos módulos de mi alrededor).

Sin embargo, tener alta cohesión, es decir, hacer solo algo muy específico implica que resuelve parte de un problema y por ende el resto del problema será asignado a otro módulo. Esto hace que comiencen a existir más módulos y por tanto se gane nivel de acoplamiento. En nuestro ejemplo, tenemos dos módulos además del principal, y esto es porque hemos designado al módulo Persona solo lo que corresponde a una persona, y asignaremos al módulo ListaPersonas solo lo que corresponde a la manipulación de un listado de 0 o más personas. Podríamos bien haber creado un único módulo que haga ambas gestiones.

Como ven, mejorar en una cosa hace que empeoremos en otra. Si tenemos alta cohesión tenemos alto acoplamiento, y si tenemos bajo acoplamiento tenemos baja cohesión. Entonces lo que se hace es intentar balancear la cuestión, es decir, tener un nivel aceptable de cohesión y uno aceptable de acoplamiento.

Todo esto corresponde al diseño de un sistema. Nosotros no aprenderemos aquí todo lo relativo al diseño, pero les iré dando las pautas para que lo vayan aprendiendo. Por eso iremos diseñando nuestros sistemas poco a poco juntos.

Digamos entonces que nuestro sistema básico para gestión de personas está bastante balanceado, sin embargo el módulo principal tiene baja cohesión (hace cosas diversas) y lamentablemente para aumentarla debe crear un nuevo módulo para leer los comandos lo cual aumenta el acoplamiento, que por ahora está super bien.

Vayamos entonces al código fuente de nuestro sistema. Les presentaré primero el archivo de definición del módulo Persona completo y con los comentarios que debería tener para que cualquiera pueda usarlo en sus programas. Luego les mostraré el archivo de implementación también con los comentarios necesarios. Con eso terminaremos por ahora la lección y continuaremos con nuestro sistema en la siguiente:

Módulo de definición de Persona
Código:
(******************************************************************************
Un objeto Persona estará representado por los siguientes datos:

   DOCUMENTO
   NOMBRE
   APELLIDO
   EDAD
   SUELDO POR HORA
   HORAS TRABAJADAS
Esta interfáz describe las operaciones que se pueden realizar con un objeto del
tipo Persona.*)

DEFINITION MODULE Persona;
CONST
    MAX_LARGO_NOMBRE= 50;
TYPE
    Persona; (*Es un tipo opaco.*)
   (*Tipo para el nombre y el apellido*)
   TipoNombre= ARRAY[1..MAX_LARGO_NOMBRE] OF CHAR;
   (************************************)
   (*          CONSTURCOTRAS           *)
   (************************************)
   
   (*Crea un nuevo objeto persona a partir de los datos ingresados como parámetros*)
   PROCEDURE CrearPersona(documento: INTEGER; nombre, apellido: TipoNombre;
               edad: INTEGER; sueldo, horas: REAL): Persona;
   
   (************************************)
   (*          SELECTORAS              *)
   (************************************)
   
   (*Retorna el documento de una persona pasada como parámetro*)
   PROCEDURE ObtenerDocumentoPersona(p: Persona): CARDINAL;

   (*Retorna el nombre de una persona pasada como parámetro*)
   PROCEDURE ObtenerNombrePersona(p: Persona): TipoNombre;
   
   (*Retorna el apellido de una persona pasada como parámetro*)
   PROCEDURE ObtenerApellidoPersona(p: Persona): TipoNombre;
   
   (*Retorna la edad de una persona pasada como parámetro*)
   PROCEDURE ObtenerEdadPersona(p: Persona): CARDINAL;
   
   (*Retorna el sueldo que una persona gana por hora trabajada*)
   PROCEDURE ObtenerSueldoPorHora(p: Persona): REAL;
   
   (*Retorna la cantidad de horas trabajadas por una persona*)
   PROCEDURE ObtenerHorasTrabajadas(p: Persona): REAL;
   
   (*Retorna el sueldo ganado por una persona según el sueldo que gana por
   hora trabajada y la cantidad de horas trabajadas*)
   PROCEDURE CalcularSueldoGanado(p: Persona): REAL;

   (************************************)
   (*          MODIFICADORAS           *)
   (************************************)
   
   (*Asigna un nuevo documento a la persona pasada como parámetro*)
   PROCEDURE ModificarDocumentoPersona(documento: CARDINAL; VAR p: Persona);
   
   (*Asigna un nuevo nombre a la persona pasada como parámetro*)
   PROCEDURE ModificarNombrePersona(nombre: TipoNombre; VAR p: Persona);
   
   (*Asigna un nuevo apellido a la persona pasada como parámetro*)
   PROCEDURE ModificarApellidoPersona(apellido: TipoNombre; VAR p: Persona);
   
   (*Asigna una nueva edad a la persona pasada como parámetro*)
   PROCEDURE ModificarEdadPersona(edad: CARDINAL; VAR p: Persona);
   
   (*Asigna un nuevo sueldo a ganar por hora trabajada para la persona
   pasada como parámetro*)
   PROCEDURE ModificarSueldoPorHora(sueldo: REAL; VAR p: Persona);   
   (*Asigna una cantidad de horas trabajadas para la persona pasada ocmo parámetro*)
   PROCEDURE ModificarHorasTrabajadas(horas: REAL; VAR p: Persona);
   
   (************************************)
   (*          INFORMACIÓN             *)
   (************************************)

   (*Imprime los datos de p en el siguiente formato:
   Documento: ValorDelDocumento
   Nombre: NombrePersona
   Apellido: ApellidoPersona
   Edad: EdadPersona
   Sueldo por hora: ValorDelSueldo
   Horas trabajadas: CantidadDeHorasTrabajadas*)
   PROCEDURE ImprimirPersona(p: Persona);
   
   (************************************)
   (*          DESTRUCTORAS            *)
   (************************************)
   
   (*Liebera la memoria ocupada por p*)
   PROCEDURE DestruirPersona(VAR p: Persona);
END Persona.


Módulo de implementación de Persona
Código:
(******************************************************************************
Un objeto Persona estará representado por los siguientes datos:
   DOCUMENTO
   NOMBRE
   APELLIDO
   EDAD
   SUELDO POR HORA
   HORAS TRABAJADAS
Esta interfáz describe las operaciones que se pueden realizar con un objeto del
tipo Persona.*)

IMPLEMENTATION MODULE Persona;

FROM Storage IMPORT ALLOCATE, DEALLOCATE;
FROM STextIO IMPORT WriteString, WriteLn;
FROM SWholeIO IMPORT WriteCard;
FROM SRealIO IMPORT WriteReal;

TYPE
    Persona= POINTER TO DatosPersona;

    DatosPersona= RECORD
        Nombre, Apellido: TipoNombre;
        Edad, Documento: CARDINAL;
        SueldoPorHora: REAL;
        HorasTrabajadas: REAL;
    END;
   (************************************)
   (*          CONSTURCOTRAS           *)
   (************************************)
   
   (*Crea un nuevo objeto persona a partir de los datos ingresados como parámetros*)
   PROCEDURE CrearPersona(documento: INTEGER; nombre, apellido: TipoNombre;
               edad: INTEGER; sueldo, horas: REAL): Persona;
   VAR p: Persona;
   
   BEGIN
      NEW(p);
      p^.Nombre:= nombre;
      p^.Apellido:= apellido;
      p^.Documento:= documento;
      p^.Edad:= edad;
      p^.SueldoPorHora:= sueldo;
      p^.HorasTrabajadas:= horas;
      RETURN p;
   END CrearPersona;
   
   (************************************)
   (*          SELECTORAS              *)
   (************************************)
   
   (*Retorna el documento de una persona pasada como parámetro*)
   PROCEDURE ObtenerDocumentoPersona(p: Persona): CARDINAL;
   BEGIN
      RETURN p^.Documento;
   END ObtenerDocumentoPersona;
   
   (*Retorna el nombre de una persona pasada como parámetro*)
   PROCEDURE ObtenerNombrePersona(p: Persona): TipoNombre;
   BEGIN
      RETURN p^.Nombre;
   END ObtenerNombrePersona;
   
   (*Retorna el apellido de una persona pasada como parámetro*)
   PROCEDURE ObtenerApellidoPersona(p: Persona): TipoNombre;
   BEGIN
      RETURN p^.Apellido;
   END ObtenerApellidoPersona;
   
   (*Retorna la edad de una persona pasada como parámetro*)
   PROCEDURE ObtenerEdadPersona(p: Persona): CARDINAL;
   BEGIN
      RETURN p^.Edad;
   END ObtenerEdadPersona;
   
   (*Retorna el sueldo que una persona gana por hora trabajada*)
   PROCEDURE ObtenerSueldoPorHora(p: Persona): REAL;
   BEGIN
      RETURN p^.SueldoPorHora;
   END ObtenerSueldoPorHora;
   (*Retorna la cantidad de horas trabajadas por una persona*)
   PROCEDURE ObtenerHorasTrabajadas(p: Persona): REAL;
   BEGIN
      RETURN p^.HorasTrabajadas;
   END ObtenerHorasTrabajadas;
   
   (*Retorna el sueldo ganado por una persona según el sueldo que gana por
   hora trabajada y la cantidad de horas trabajadas*)
   PROCEDURE CalcularSueldoGanado(p: Persona): REAL;
   BEGIN
      RETURN ObtenerSueldoPorHora(p) * ObtenerHorasTrabajadas(p);
   END CalcularSueldoGanado;

   (************************************)
   (*          MODIFICADORAS           *)
   (************************************)
   
   (*Asigna un nuevo documento a la persona pasada como parámetro*)
   PROCEDURE ModificarDocumentoPersona(documento: CARDINAL; VAR p: Persona);
   BEGIN
      p^.Documento:= documento;
   END ModificarDocumentoPersona;
   
   (*Asigna un nuevo nombre a la persona pasada como parámetro*)
   PROCEDURE ModificarNombrePersona(nombre: TipoNombre; VAR p: Persona);
   BEGIN
      p^.Nombre:= nombre;
   END ModificarNombrePersona;
   
   (*Asigna un nuevo apellido a la persona pasada como parámetro*)
   PROCEDURE ModificarApellidoPersona(apellido: TipoNombre; VAR p: Persona);
   BEGIN
      p^.Apellido:= apellido;
   END ModificarApellidoPersona;
   
   (*Asigna una nueva edad a la persona pasada como parámetro*)
   PROCEDURE ModificarEdadPersona(edad: CARDINAL; VAR p: Persona);
   BEGIN
      p^.Edad:= edad;
   END ModificarEdadPersona;
   
   (*Asigna un nuevo sueldo a ganar por hora trabajada para la persona
   pasada como parámetro*)
   PROCEDURE ModificarSueldoPorHora(sueldo: REAL; VAR p: Persona);
   BEGIN
      p^.SueldoPorHora:= sueldo;
   END ModificarSueldoPorHora;
   
   (*Asigna una cantidad de horas trabajadas para la persona pasada ocmo parámetro*)
   PROCEDURE ModificarHorasTrabajadas(horas: REAL; VAR p: Persona);
   BEGIN
      p^.HorasTrabajadas:= horas;
   END ModificarHorasTrabajadas;   
   (************************************)
   (*          INFORMACIÓN             *)
   (************************************)

   (*Imprime los datos de p en el siguiente formato:
   Documento: ValorDelDocumento
   Nombre: NombrePersona
   Apellido: ApellidoPersona
   Edad: EdadPersona
   Sueldo por hora: ValorDelSueldo
   Horas trabajadas: CantidadDeHorasTrabajadas*)
   PROCEDURE ImprimirPersona(p: Persona);
   BEGIN
      WriteString("Documento: ");
      WriteCard(ObtenerDocumentoPersona(p),1);
      WriteLn;
      
      WriteString("Nombre: ");
      WriteString(ObtenerNombrePersona(p));
      WriteLn;
      
      WriteString("Apellido: ");
      WriteString(ObtenerApellidoPersona(p));
      WriteLn;
      
      WriteString("Edad: ");
      WriteCard(ObtenerEdadPersona(p),1);
      WriteLn;
      
      WriteString("Sueldo por hora: ");
      WriteReal(ObtenerSueldoPorHora(p),1);
      WriteLn;
      
      WriteString("Horas trabajadas: ");
      WriteReal(ObtenerHorasTrabajadas(p),1);
END ImprimirPersona;
   
   (************************************)
   (*          DESTRUCTORAS            *)
   (************************************)
   
   (*Liebera la memoria ocupada por p*)
   PROCEDURE DestruirPersona(VAR p: Persona);
   BEGIN
      DISPOSE(p);
   END DestruirPersona;
END Persona.


Todo lo dado hasta el momento junto con los comentarios de estos códigos son más que suficiente para que los comprendan, así que no voy a detallar nada en absoluto acerca de ellos.

Continuaremos con nuestro sistema en la siguiente lección.

Saludos.

Volver arriba
Ver perfil del usuario Enviar mensaje privado
pirdy
Usuario Inquieto


Registrado: 11 Feb 2010
Mensajes: 137

Mensaje Publicado: Martes 03 Ene 2012 02:48

Título del mensaje: Re: Programando desde 0: 43- Descripción Nomina de Personas.

Responder citando

Excelente como siempre profe.

Feliz año. Este año me he propuesto aprender a programar y tomar una buena base.

Su curso es el reto y la guía a seguir.

En breve espero empezar a resolver más dudas. Que ciertamente con todo el material que hay no son pocas.


Saludos y un muy Buen 2012 a todos pero si me lo permitis en especial a nuestro profe que ya va para el año y subiendo más lecciones.

Volver arriba
Ver perfil del usuario Enviar mensaje privado
Responder al Tema
Mostrar mensajes anteriores:   
Ir a:  
Todas las horas están en GMT + 2 Horas

Temas relacionados

Tema Autor Foros Respuestas Publicado
El foro no contiene ningún mensaje nuevo

Buenas desde el sur del sur =)

Maugarni Preséntate a la comunidad 1 Jueves 22 Ago 2019 14:09 Ver último mensaje
El foro no contiene ningún mensaje nuevo

Hola desde bcn

Dav2k6 Preséntate a la comunidad 2 Miércoles 26 Jun 2019 19:22 Ver último mensaje
El foro no contiene ningún mensaje nuevo

Existen problemas al descargar musica desde you...

SusanaP Tu PC 2 Martes 26 Mar 2019 19:22 Ver último mensaje
El foro no contiene ningún mensaje nuevo

hola!! los saludo desde argentina

mery Preséntate a la comunidad 2 Jueves 13 Dic 2018 17:28 Ver último mensaje
El foro no contiene ningún mensaje nuevo

Llamada a web service desde form

mrrobot2 Programación Web en general 1 Martes 14 Nov 2017 00:50 Ver último mensaje
Panel de Control
No puede crear mensajes, No puede responder temas, No puede editar sus mensajes, No puede borrar sus mensajes, No puede votar en encuestas,