ChatGPT comme outil de compréhension de code

Mar 01 2023
93 % des ingénieurs en logiciel signalent une documentation insuffisante comme source de baisse de productivité. Si cela ne vous effraie pas, j'ai une autre statistique qui le fera.

93 % des ingénieurs en logiciel signalent une documentation insuffisante comme source de baisse de productivité. Si cela ne vous effraie pas, j'ai une autre statistique qui le fera. Les recherches montrent que les développeurs passent 58 % de leur temps sur des tâches de compréhension de code.

Cela soulève des questions intéressantes. Et si ChatGPT pouvait accélérer la compréhension du code, une tâche à laquelle les développeurs consacrent plus de la moitié de leur temps ?

Qu'est-ce que la compréhension de code ?

La compréhension du code est le temps que les ingénieurs logiciels passent à lire du code précédemment écrit pour comprendre comment il fonctionne. C'est une partie essentielle de l'ingénierie logicielle car 99% du codage dépend de l'utilisation de morceaux de code que quelqu'un d'autre a écrits.

Comment ChatGPT peut-il vous aider ?

Tout le monde sait que ChatGPT peut résumer des phrases, des paragraphes et même des articles. Tout le monde ne sait pas que cela fonctionne également pour le code. Le code est écrit dans un format compréhensible à la fois par les humains et les ordinateurs. Le résultat est que parfois le code peut être difficile à comprendre pour les humains sans le lire ligne par ligne. C'est là qu'intervient ChatGPT. ChatGPT peut résumer rapidement un morceau de code et le convertir dans un format plus rapidement compris par un humain. Alors lançons ChatGPT et essayons-le.

Un souvenir perdu

Pendant mes études supérieures, j'ai écrit un programme Python & CUDA pour traiter les données d'astronomie. Si vous n'êtes pas familier avec CUDA, c'est une API qui permet un traitement parallèle sur un GPU. Après la fin de mon cours d'informatique parallèle, le projet a été jeté au placard alors que de nouveaux projets de classe commençaient. Maintenant que j'ai obtenu mon diplôme, j'ai décidé de le retirer et de recommencer à travailler dessus.

Graphique des données d'astronomie post-traitées

Immédiatement après avoir ouvert le projet dans mon IDE préféré (VS Code, bien sûr), j'ai réalisé que je n'avais presque aucun souvenir de la façon dont le programme avait été écrit. Après 20 minutes désagréables de lecture de l'ancien projet, j'ai eu l'idée de demander à ChatGPT de faire le gros du travail pour moi. Mais il y avait une inquiétude persistante au fond de mon esprit. Je ne savais pas si je pouvais faire confiance à ChatGPT pour cette tâche. Avant de confier l'ensemble de mon projet à ChatGPT, j'ai décidé de mener une expérience facilement vérifiable. J'ai sorti un petit morceau de code que j'ai déjà compris

galaxies = []
with open('GalaxiesWithDistances.csv', 'r') as file:
    reader = csv.reader(file)
    first = True
    for row in reader:
        if first:
            first = False
            continue
        galaxies.append({'Name': row[0], 'RA': row[1], "DEC": row[2], "LY": row[3]})

ChatGPT a pris quelques secondes pour réfléchir, puis a commencé à taper l'explication suivante

Le code lit les données d'un fichier CSV nommé 'GalaxiesWithDistances.csv' et crée une liste appelée 'galaxies'. Il utilise le module 'csv' pour lire les données du fichier et les stocker dans la variable 'reader'. La première ligne du fichier CSV est ignorée à l'aide d'une 'première' variable booléenne. Pour chaque ligne suivante du fichier CSV, un dictionnaire contenant le nom de la galaxie, l'ascension droite, la déclinaison et la distance est créé et ajouté à la liste des "galaxies".

Pas mal hein ? Cela a pris à peu près aussi longtemps qu'il me faudrait pour le comprendre.

Mais je me sens avide de résultats et je n'ai pas la patience de faire cette fonction une à la fois. Je mets en évidence l'ensemble du projet Python (trouvé surhttps://github.com/Tyler-Hilbert/SpaceTripPlanner/blob/master/EdgeCreator.py)

import csv
import math

MAXIMUM_DISTANCE = 1 # The maximum number of light years a spaceship can travel before needing a refuel
GRAPH_NUMERIC = False # If the output GV file should output id number instead of galaxy names

# Get the X, Y, Z cordinates of a galaxy
def getCord(gal):
    theta = 15 * (int(gal['RA'].split(" ")[0]) + float(gal['RA'].split(" ")[1])/60)
    phi = int(gal['DEC'].split(" ")[0]) + int(gal['DEC'].split(" ")[1])/60
    x = float(gal['LY']) * math.cos(math.radians(theta)) * math.cos(math.radians(phi))
    y = float(gal['LY']) * math.sin(math.radians(theta)) * math.cos(math.radians(phi))
    z = float(gal['LY']) * math.sin(math.radians(phi))
    cord = (x, y, z)
    return cord


# Calculates the distance between 2 galaxies
def calcDistance(startGal, endGal):
    startCord = getCord(startGal)
    endCord = getCord(endGal)
    return math.sqrt(
        (startCord[0] - endCord[0]) ** 2 +
        (startCord[1] - startCord[1]) ** 2 +
        (startCord[2] - startCord[2]) ** 2
    )

# Counts the number of edges with the given start node
# This is used for outputting the length in cuda
def getStartCount(edges, start):
    count = 0
    for edge in edges:
        if edge['start'] == start:
            count += 1
    return count

# Cleans up galaxy name so it will work with DOT
def cleanName(name):
    replacements = [
        (".", ""),
        ("/", "_"),
        ("'", ""),
        ("=", "_"),
        ("-", ""),
        (" ", "_"),
        (" ", "_"),
        ("_", "")
    ]
    for repl in replacements:
        while repl[0] in name:
            name = name.replace(repl[0], repl[1])
    return name


# Read in galaxy data
galaxies = []
with open('GalaxiesWithDistances.csv', 'r') as file:
    reader = csv.reader(file)
    first = True
    for row in reader:
        if first:
            first = False
            continue
        galaxies.append({'Name': row[0], 'RA': row[1], "DEC": row[2], "LY": row[3]})

# Calculate edges
edges = []
for startGalIndex in range(len(galaxies)):
    for endGalIndex in range(len(galaxies)):
        if startGalIndex != endGalIndex and calcDistance(galaxies[startGalIndex], galaxies[endGalIndex]) < MAXIMUM_DISTANCE:
            edge = {'start':"{0:0=2d}".format(startGalIndex), 'end':"{0:0=2d}".format(endGalIndex)}
            edges.append(edge)

# Print
print ("********** \n EDGES \n******* \n ")
for edge in edges:
    print (edge)

# Print graph in CUDA code
f = open("graph_variables.cu", "w")
f.write ("// THIS IS A GENERATED FILE USING EdgeCreator.py\n")
f.write ("// Number of lightyears a spaceship can travel: ")
f.write (str(MAXIMUM_DISTANCE))
f.write ("\n")
f.write("Node node[")
f.write(str(len(galaxies)))
f.write("];\n")

completedStart = []
for i in range(len(edges)):
    if edges[i]['start'] not in completedStart:
        completedStart.append(edges[i]['start'])
        startS = "node[" + str(edges[i]['start']) + "].start = " + str(i) + ";\n"
        f.write (startS)
        lengthS = "node[" + str(edges[i]['start']) + "].length = " + str(getStartCount(edges, edges[i]['start'])) + ";\n"
        f.write (lengthS)


for i in range(len(galaxies)):
    nameS = 'node[' + str(i) + '].name = "' + galaxies[i]['Name'].replace("'", "") + '";\n'
    f.write (nameS)
    id0 = str( (int)((i - (i%10))/10))
    id1 = str(i % 10)
    idS = "node[" + str(i) + "].id[0] = '" + id0 + "'; node[" + str(i) + "].id[1] = '" + id1 + "';\n"
    f.write (idS)


f.write("int edges[")
f.write(str(len(edges)))
f.write("];\n")

for i in range(len(edges)):
    edgeS = "edges[" + str(i) + "] = " + str(edges[i]['end']) + ";\n"
    f.write (edgeS)

f.close()


# Print graph in regular C++ datastructure for sequential BFS (for comparison to CUDA)
f = open("graph_variables.cpp", "w")
f.write ("// THIS IS A GENERATED FILE USING EdgeCreator.py\n")
f.write ("// Number of lightyears a spaceship can travel: ")
f.write (str(MAXIMUM_DISTANCE))
f.write ("\n")

# Add nodes
for i in range(len(galaxies)):
    nameS = 'graph.AddNode("' + galaxies[i]['Name'].replace("'", "") + '");\n'
    f.write (nameS)

# Add edges
for edge in edges:
    edgeS = "graph.AddEdge(" +  edge['start'] + "," + edge['end'] + ");\n"
    f.write(edgeS)

f.close()

# Graph (dot) creator
f = open("output.gv", "w")
f.write("strict graph G {\n")
for edge in edges:
    if GRAPH_NUMERIC:
        eStr = edge['start'] + " -- " + edge['end'] + "\n"
    else:
        eStr = cleanName(galaxies[int(edge['start'])]['Name'])
        eStr += " -- "
        eStr += cleanName(galaxies[int(edge['end'])]['Name'])
        eStr += "\n"
    f.write(eStr)
f.write("}")
f.close()

ChatGPT a de nouveau pris quelques secondes pour réfléchir avant de commencer à taper une réponse

Le code lit les données sur les galaxies à partir d'un fichier CSV, calcule la distance entre chaque paire de galaxies et crée des contours entre celles qui se trouvent à une certaine distance maximale. Le code génère ensuite deux fichiers de sortie : "graph_variables.cu" et "graph_variables.cpp", qui contiennent respectivement des structures de données à utiliser dans les programmes CUDA et C++ standard. Les fichiers de sortie incluent des informations sur les nœuds (c'est-à-dire les galaxies) et les arêtes du graphe. Le code comprend également diverses fonctions pour calculer les coordonnées d'une galaxie, compter le nombre d'arêtes avec un nœud de départ donné et nettoyer les noms de galaxies.

Ouah. C'était beaucoup plus rapide que si je l'avais fait moi-même.

Mais je n'ai pas encore fini. Il est temps de passer à la partie difficile du projet. Ce projet épineux compte plus de 500 lignes de code CUDA écrites en C. Parce que je suis une personne gentille, je ne les publierai pas toutes dans cet article, mais si vous êtes intéressé, n'hésitez pas à les consulter sur mon GitHub (https://github.com/Tyler-Hilbert/SpaceTripPlanner/blob/master/ParallelBFS.cu).

Connectons-le à ChatGPT et voyons comment cela fonctionne

Encore une fois, ChatGPT a pris quelques secondes pour réfléchir, puis a commencé à taper une explication.

Il s'agit d'un programme CUDA qui effectue une recherche en largeur (BFS) sur un graphique. Il définit d'abord une structure Nodeavec des champs pour l'index de départ des arêtes, le nombre d'arêtes et l'ID du nœud. Ensuite, il définit une fonction noyau Bfs_Kernelqui exécute BFS en utilisant un tableau de sommets, d'arêtes, de frontières, de nœuds visités, de distances et de chemins. La fonction principale initialise les données du graphe en définissant l'index de départ et la longueur des arêtes pour chaque nœud, puis elle appelle la fonction noyau.

Wow, c'était un code GPU de bas niveau moche et ChatGPT vient de l'expliquer comme un champion. Je suis maintenant prêt à commencer à ajouter de nouvelles fonctionnalités à mon programme et je suis heureux que ChatGPT ait pu me faire gagner du temps pour démarrer.

Prochaines étapes

Maintenant que je vous ai raconté mon histoire d'utilisation de ChatGPT pour aider à ramener un ancien projet, je vous encourage à faire de même. Allez-y et essayez vos propres programmes et voyez comment ils fonctionnent. De plus, si vous avez besoin d'aide pour utiliser ChatGPT pour améliorer votre cohmphernsion de code, n'hésitez pas à me contacter à [email protected]