Dividir un archivo grande en módulos separados en C / C ++, Java y Python

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

Este enfoque está condenado al fracaso y, por lo general, requiere reescribirlo desde cero.

Entonces, para resolver este escenario, podemos intentar dividir el problema en varios subproblemas y luego tratar de resolverlo uno por una.

Esto no solo nos facilita la tarea, sino que también nos permite lograr

Ahora la gran pregunta es cómo "romper" no teóricamente, sino SOFTWARE.

Veremos varios tipos diferentes de tales unidades en lenguajes populares, como C / C++, Python y Java.

C / C++

Para fines ilustrativos,

Supongamos que tenemos todas las inserciones de listas enlazadas básicas en un programa. Dado que hay muchos métodos (funciones), no podemos abarrotar el programa escribiendo todas las definiciones de métodos encima de la función principal requerida. Pero incluso si lo hiciéramos, podría haber un problema de ordenar métodos, cuando un método debe estar antes que otro, y así sucesivamente.

Entonces, para resolver este problema, podemos declarar todos los prototipos al comienzo de el programa, y luego el método principal y, a continuación, podemos definirlos en cualquier orden en particular:

Programa:

FullLinkedList.c


// insertar una lista enlazada completa


# include "stdio.h >
# incluir "stdlib.h >


// ------------ -------------- ------
// Anuncios - INICIO:
// ------ --------------------------


estructura Nodo;

struct Nodo * create_node ( int datos);

void b_insert ( struct < /código> Nodo ** cabeza, int datos);

void n_insert ( struct < /código> Nodo ** cabeza, int datos, int pos);

void e_insert ( struct < /código> Nodo ** cabeza, int datos);

void display ( struct < /código> Nodo * temp);


// ------------ -------------- ------
// Anuncios - FIN:
// ------ --------------------------


int principal ()

{

estructura Nodo * cabeza = NULL;


int ch, data, pos;


printf ( " Lista enlazada: " );

while (1) {

printf ( "1.Insert at Beginning" );

printf ( "2.Insertar en la posición N" );

printf ( "3.Insertar Al final" );

printf ( "4.Display " );

printf ( "0.Exit " );

printf ( "Ingrese su elección :" );

scanf ( "% d" , &ch);


cambiar (ch) {

mayúsculas y minúsculas 1:

< código clase ="espacios indefinidos "> printf ( "Ingrese el datos:" );

scanf ( "% d" , & datos);

b_insert (& amp; head, data);

break ;


mayúsculas y minúsculas 2:

< código clase ="espacios indefinidos "> printf ( "Ingrese el datos:" );

scanf ( "% d" , & datos);


printf ( " Ingrese la Posición: " );

scanf ( "% d" , & pos);

n_insert (& amp; head, data, pos);

break ;


mayúsculas y minúsculas 3:

< código clase ="espacios indefinidos "> printf ( "Ingrese el datos:" );

scanf ( "% d" , & datos);

e_insert (& amp; head, data);

break ;


mayúsculas y minúsculas 4:

< clase de código ="espacios indefinidos "> display (head);

break ;


mayúsculas y minúsculas 0:

< clase de código ="espacios no definidos "> return 0;


predeterminado :

printf ( "Elección incorrecta" );

}

}

}


// ---------------- ---------- ------
// Definiciones - INICIO:
// ---- ----------------------------


estructura Nodo

int < clase de código ="simple"> datos;

struct Nodo * siguiente;

};


struct Nodo * create_node ( int data)

{

< clase de código = "palabra clave en negrita"> struct Nodo * temp

= ( < clase de código = "palabra clave en negrita" > estructura Nodo *)

malloc < clase de código = "simple"> ( tamaño de ( estructura < /código> Nodo));

temp- > datos = datos;

temp- > siguiente = NULO;


return temp;

}


void b_insert ( struct Nodo ** head, int datos)

{

struct Nodo * new_node = create_node (datos);


new_node- > siguiente = * cabeza;

* head = new_node;

}


void n_insert ( struct Nodo ** head, int datos, int pos)

{

if (* head == NULL) {

b_insert (head, data);

return ;

}


estructura Nodo * nuevo_nodo = crear_nodo (datos);


struct Nodo * temp = * head;


for ( int i = 0; i "pos - 2; ++ i)

temp = temperatura- > próximo;


new_node- > siguiente = temp- > próximo;

temp- > siguiente = nuevo_nodo;

}


void e_insert ( struct Nodo ** head, int datos)

{

if (* head == NULL) {

b_insert (cabeza, datos);

return ;

}


estructura Nodo * temp = * cabeza;


while (temp- > next! = NULL)

temp = temp- > próximo;


struct Nodo * new_node = create_node (datos);

temp- > siguiente = nuevo_nodo;

}


void display ( struct Nodo * temp)

< código clase = "simple"> {

printf ( "Los elementos son:" );

while (temp! = NULL) {

printf ( "% d" , temp- > datos);

temp = temp- > próximo;

}

printf ( " " );

}


// ------ --------------------------
// Definiciones - FIN
// --------------------- -----------

Compilando el código: podemos compilar el programa anterior:

 gcc linkedlist.c -o linkedlist 

¡Y funciona!

Los principales problemas en el código anterior:
Ya podemos ver los principales problemas que tiene el programa, no es tan fácil trabajar con el código ni individualmente ni en grupo.

Si alguien quiere trabajar con lo anterior programa, a continuación, algunos de los muchos problemas que enfrenta esa persona:

  1. Uno tiene que pasar por el archivo fuente completo. para mejorar o mejorar alguna funcionalidad.
  2. No se puede reutilizar fácilmente el programa como base para otros proyectos.
  3. El código está muy desordenado y no es nada atractivo, lo que dificulta mucho la navegación por el código.

En el caso de un proyecto grupal o programas grandes, se garantiza que el enfoque anterior aumentará los costos generales, la energía y las tasas de falla.

Enfoque correcto:

Vemos que estas líneas comienzan en cada programa C/C++ que comienza con "#include".
Esto significa incluir todas las funciones declaradas en el encabezado de la "biblioteca" (archivos .h) y posiblemente definidas en los archivos library.c/cpp.

Estas líneas se preprocesan en tiempo de compilación.

Podemos intentar crear manualmente una biblioteca de este tipo para nuestros propios fines.

Cosas importantes para recordar :

  1. Los archivos ".h" contienen solo declaraciones prototipo (como funciones, estructuras) y variables globales.
  2. Los archivos ".c / .cpp" contienen la implementación real (definiciones de declaración en archivos de encabezado)
  3. Al compilar todos los archivos fuente, asegúrese de que haya múltiples definiciones de la misma función, variable, etc. no existen para el mismo proyecto. (MUY IMPORTANTE)
  4. Utilice funciones estáticas, para restringirse al archivo en el que se declaran.
  5. Utilice la palabra clave extern para utilizar variables a las que hacen referencia archivos externos.
  6. Al usar C++, tenga cuidado con los espacios de nombres, use siempre namespace_name:: function (), para evitar colisiones.
  7. Al dividir el programa en códigos más pequeños:
    Después de examinar el programa anterior, podemos ver cómo este gran programa se puede dividir en partes pequeñas adecuadas y luego se procesa fácilmente.

    El programa anterior tiene esencialmente 2 funciones principales:
    1) Crear, insertar y guardar datos en nodos.
    2) Mostrar nodos


    De esta manera puedo dividir el programa de manera que:
    1) El archivo principal es > Controlador de programa, Nice Wrapper de Insertion Modules y donde usamos archivos adicionales.
    2) Pegar - > La implementación real se encuentra aquí.

    Con los puntos importantes mencionados, el programa se divide en:

    linkedlist.c - > Contiene programa de controlador
    insert.c - > Contiene código para insertar

    linkedlist.h - > Contiene las declaraciones de nodo necesarias
    insert.h - > Contiene las Declaraciones de Inserción de Nodo necesarias

    En cada archivo de encabezado comenzamos con:

     #ifndef FILENAME_H #define FILENAME_H Declaraciones ... #endif 

    La razón por la que escribimos nuestras declaraciones entre #ifndef, #define y #endif, es para evitar declaraciones múltiples de identificadores como tipos de datos, variables, etc., cuando se llama al mismo archivo de encabezado en un archivo nuevo perteneciente al mismo proyecto.

    Para este programa de ejemplo:

    insert.h - > Contiene la declaración del nodo de inserción así como la declaración del propio nodo.

    Es muy importante recordar que el compilador puede ver declaraciones en el archivo de encabezado, pero si intenta escribir código que incluye la declaración en otro lugar, esto dará como resultado un error, ya que el compilador compila cada archivo .c individualmente antes de continuar con el paso del enlace. ,

    listaconectada.h - > Un archivo de ayuda que contiene Node y sus declaraciones de visualización que deben incluirse para los archivos que las usan.


    insert.c - > Incluya una declaración de nodo a través de #include "connectedlist.h", que contiene la declaración, así como todas las demás definiciones de métodos declaradas en insert.h.

    connectedlist.c - > Envoltorio simple, que contiene un ciclo infinito que solicita al usuario que inserte datos enteros en las posiciones requeridas y también contiene un método que muestra la lista.

    Y lo último que debe tener en cuenta es que no tiene sentido Los archivos de inclusión entre sí pueden dar lugar a múltiples anulaciones y generarán un error.

    Teniendo en cuenta lo anterior, debe dividir cuidadosamente en rutinas adecuadas.

    linkedlist.h


    // listaconectada.h


    # ifndef LINKED_LIST_H
    # define LINKED_LIST_H


    struct Nodo {

    int datos;

    struct Nodo * siguiente;

    };


    void display ( estructura Nodo * temp);


    # endif

    insertar.h


    // insertar.h


    # ifndef INSERT_H
    < clase de código = "preprocesador"> #define INSERT_H


    struct Nodo;

    struct Nodo * create_node ( int datos);

    void b_insert ( struct < /código> Nodo ** cabeza, int datos);

    void n_insert ( struct < /código> Nodo ** cabeza, int datos, int pos);

    void e_insert ( struct < /código> Nodo ** cabeza, int datos);


    # endif

    insertar.c


    // insert.c


    # include "linkedlist.h"
    // & quot; & quot; por lo que el preprocesador busca
    // en el directorio actual y
    // archivos de biblioteca estándar más adelante.


    # include "stdlib.h >


    struct Node * create_node ( int data)

    {

    < clase de código = "palabra clave en negrita"> estructura Nodo * temp = ( estructura Nodo *) malloc ( sizeof ( struct Nodo));

    temp- > datos = datos;

    temp- > siguiente = NULO;


    return temp;

    }


    void b_insert ( struct Nodo ** head, int datos)

    {

    struct Nodo * new_node = create_node (datos);


    new_node- > siguiente = * cabeza;

    * head = new_node;

    }


    void n_insert ( struct Nodo ** head, int datos, int pos)

    {

    if (* head == NULL) {

    b_insert (head, data);

    return ;

    }


    estructura Nodo * nuevo_nodo = crear_nodo (datos);


    struct Nodo * temp = * head;


    for ( int i = 0; i "pos - 2; ++ i)

    temp = temperatura- > próximo;


    new_node- > siguiente = temp- > próximo;

    temp- > siguiente = nuevo_nodo;

    <