How I use AI for code assistance

How I use AI for code assistance

Using ChatGPT and Github Copilot to code faster

I have found some use cases where AI can write good, functional code and can assist you in completing your code-writing tasks faster. I have been using the ChatGPT web tool and Copilot both for my work (Copilot is like a sibling to the GPT, given they are built around the same core internally [Ref])

tl;dr

  • Github co-pilot: For faster code auto-completion — Imagine it to be like a really well-prepared interview candidate for a first-level software engineer role and you are giving it code writing assignments. 😅

    • What I like:

      • Plugins embedded into VSCode, IntelliJ, Sublime

      • Good in predicting what I want to write and while it is not perfect, it has helped me get some mundane code pieces to be written quickly

  • ChatGPT: For getting an end-to-end instruction set of how to solve a problem or for writing code for an entire use-case which spans across multiple classes & functions. It also explains the code it provides which is something Co-pilot doesn’t give you when you do auto-complete.

Here are 6 ways I have used AI in my code writing:

1. CSS generation (Github Copilot)

While building Dr Droid, I took up the challenge to write our reactjs application and make new components. While we made our mockups using Figma, it takes some skills to replicate it onto your page design. I am a backend engineer by practising and writing CSS to take care of the grid, the mobile-friendliness & spacing are a bit daunting. So, I wrapped my HTML elements with a div with a class and then described the element from our Figma mockup in a prompt. Copilot added the CSS for that class with some assumptions on the actual measurements which I could fine-tune later, but it took the guessing part out on what CSS styles to use.

Input:
"""Give CSS for 3 classes, one for the parent div and two for the children div where the children should get aligned horizontally with their internal texts to the left and right"""

Output:
.parentDiv {
  flex-direction: 'inherit';
  display: 'flow-root';
  padding: '2px';
}

.leftDiv {
  width: '30%';
  height: '100%';
  background: 'white';
  float: 'left';
  border: '1px solid black';
    text-align: 'left';
}

.rightDiv {
  width: '70%';
  height: '100%';
  background: 'white';
  float: 'right';
  border: '1px solid black';
    text-align: 'right';
}

2. Telling the copilot to write functions, mostly for sorting or data manipulation

At Dr Droid, we have lots of data transformations happening at different layers and for different features on our platform. Copilot has proved to be quite useful in writing those transformations based on prompts and then we can test it with our test cases. It is also useful for writing functions to merge two data objects into a single object with a different schema by describing what the new fields are and how they are based on the older fields.

For example, I wanted to merge JSON objects in an array over two string keys in them and give different stats over the third numeric key. The best part is that it can write it in the context of your code so variable renaming is not needed and you can tell it which library to use for doing so.

Input:
"""Write function that merges json objects in an array over two string keys in them and give average, median stats over the third numeric key"""

Output:
function mergeJsonArray(jsonArray, key1, key2, key3) {
  let mergedJson = {};
  let mergedJsonArray = [];

  jsonArray.forEach(item => {
    if (item[key1] in mergedJson) {
      if (item[key2] in mergedJson[item[key1]]) {
        mergedJson[item[key1]][item[key2]].push(item[key3]);
      } else {
        mergedJson[item[key1]][item[key2]] = [item[key3]];
      }
    } else {
      mergedJson[item[key1]] = {};
      mergedJson[item[key1]][item[key2]] = [item[key3]];
    }
  });

  for (const key1 in mergedJson) {
    for (const key2 in mergedJson[key1]) {
      let sum = 0.0;
      let median = 0.0;
      let mean = 0.0;
      let count = 0;
      let min = 0.0;
      let max = 0.0;

      mergedJson[key1][key2].forEach(item => {
        sum += item;
        count += 1;
      });

      mean = sum / count;

      mergedJson[key1][key2].sort((a, b) => a - b);
      median = mergedJson[key1][key2][Math.floor(mergedJson[key1][key2].length / 2)];

      min = mergedJson[key1][key2][0];
      max = mergedJson[key1][key2][mergedJson[key1][key2].length - 1];

      mergedJsonArray.push({
        [key1]: key1,
        [key2]: key2,
        'count': count,
        'sum': sum,
        'mean': mean,
        'median': median,
        'min': min,
        'max': max
      });
    }
  }
    return mergedJsonArray;
}

3. Writing code with repeated patterns that the copilot is very good at detecting from your postcode

I was writing a data deletion script across multiple tables in my DB for my staging environment cleanup. All those tables had timestamp columns in each of them but with different names. I jotted down all table names in a comment in a comma-separated manner and then wrote a deletion SQL query on the first table and the whole deletion commands using the connection cursor. Once that was done, Co-pilot started auto-suggesting entire blurbs of selection code blocks for each of those tables iteratively, that too modifying the column name in them based on what the timestamp column name in it was. However, it couldn’t understand the order in which that deletion was possible, it only followed the order of how they were written in the model's file.

I have used Co-pilot plugins in IntelliJ and Sublime Text. I have found the IntelliJ plugin to be more intelligent in its recommendations, especially when it comes to the context of class definitions in other files.

4. Use ChatGPT to write entire reactjs components by describing what you want it to do, then it just needs some variable corrections

I was working with a reactjs library (react-flow) that allows a custom-written component to replace its own. My purpose is to make it look a little different & add some extra text on its top. While the documentation on how the new component can override the existing one was there, it wasn’t clear on how to extend it and keep the original features intact. So, I asked ChatGPT and this is what I got:

Prompt:
How to make a custom edge in react-flow which is thick violet line with a large arrow at the end

Output:
import React from 'react';

const CustomEdge = ({ id, sourceX, sourceY, targetX, targetY, style = {} }) => {
  const edgePath = `M ${sourceX},${sourceY} L ${targetX},${targetY}`;

  // Calculate the angle of the arrow
  const angle = Math.atan2(targetY - sourceY, targetX - sourceX);
  const arrowLength = 10; // Length of the arrow

  // Calculate the arrowhead points
  const arrowPoints = [
    [targetX - arrowLength * Math.cos(angle - Math.PI / 6), targetY - arrowLength * Math.sin(angle - Math.PI / 6)],
    [targetX, targetY],
    [targetX - arrowLength * Math.cos(angle + Math.PI / 6), targetY - arrowLength * Math.sin(angle + Math.PI / 6)],
  ];

  return (
    <>
      <path
        id={id}
        d={edgePath}
        style={{
          fill: 'none',
          strokeWidth: '4px',
          stroke: 'violet',
          ...style, // Allow overriding style
        }}
      />
      <polygon
        points={arrowPoints.map(p => p.join(',')).join(' ')}
        fill="violet"
        stroke="violet"
        strokeWidth="1"
      />
    </>
  );
};

export default CustomEdge;

// Use the custom edge component in your React Flow graph
import ReactFlow from 'react-flow-renderer';
import CustomEdge from './CustomEdge';

const elements = [
  // ... your nodes and edges
];

const App = () => {
  return (
    <div style={{ height: '500px' }}>
      <ReactFlow elements={elements} edgeTypes={{ customEdge: CustomEdge }} />
    </div>
  );
};

export default App;

I had to make some minor corrections in its chosen css measurements but it saved me like 30 minutes of writing the code that would have worked correctly.

5. Ask ChatGPT for some code snippets. If it is not working correctly, paste in the error response and it keep correcting it till it gets fixed with your feedback

ChatGPT is good at improving its answers based on more feedback. But the feedback shouldn’t just be regeneration or asking for a better solution. You can keep giving context in your feedback. Here is an example: I wanted to set up auto-arranging of my nodes in the react-flow graph and I found that there is a layout called cola that can help do it. I couldn’t find many examples of the same online, so I asked ChatGPT:

Prompt:
Give me a sample code of how to use react-flow and cola layout for arranging my nodes

Output:
import React from 'react';
import ReactFlow, { ReactFlowProvider, addEdge, removeElements, Controls } from 'react-flow-renderer';
import { ColaLayout } from 'react-flow-renderer/dist/layoutCola';

const MyFlowComponent = () => {
  const initialElements = [
    { id: '1', type: 'input', data: { label: 'Input Node' }, position: { x: 0, y: 0 } },
    { id: '2', data: { label: 'Node 2' }, position: { x: 200, y: 50 } },
    { id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } },
    { id: 'e1-2', source: '1', target: '2' },
    { id: 'e2-3', source: '2', target: '3' },

  ];

  const onLoad = (reactFlowInstance) => {
    reactFlowInstance.fitView(); // Fit the graph within the viewport
  };

  const layout = {
    type: 'cola',
    edgeLength: 180,
    animate: true,
    randomize: false,
    maxSimulationTime: 1500,
  };

  return (
    <div style={{ height: '500px' }}>
      <ReactFlowProvider>
        <ReactFlow elements={initialElements} onLoad={onLoad} layout={layout}>
          <Controls />
        </ReactFlow>
      </ReactFlowProvider>
    </div>
  );
};

export default MyFlowComponent;

// Install cola using npm:
npm install react-flow react-flow-renderer

But the code won’t work even after installation and it gave me an error, so I asked ChatGPT again in the same session:

Prompt:
It is giving me this error "Module not found: Error: Package path ./dist/layoutCola is not exported from package".

Output:
I apologize for the confusion. It seems that the layoutCola module is no longer available directly in the react-flow-renderer package. To use the "cola" layout algorithm with React Flow, you can install the react-flow-dagre package, which provides additional layout options including the "cola" layout.

It gave me an alternative code block and gave me a new library to install:

# Use npm
npm install react-flow react-flow-renderer react-flow-dagre

but this time there was an installation error:

npm ERR! 404 Not Found - GET <https://registry.npmjs.org/react-flow-dagre> - Not found

By now, ChatGPT had understood what i am asking without me asking for it and started giving other suggestions on how i can achieve my original goal of arranging the nodes. I eventually ended up achieving my goal without the cola layout but my problem was resolved.

I recently wanted to set up a connection of messages from a topic in my Kafka cluster to an OpenSearch service. Kafka does provide connectors for this but I was too new to this so I was scouting online for some examples of those configurations. While there were detailed examples of how to set up a connector to an s3 bucket, I couldn’t find a working example of OpenSearch being the data sink. I asked ChatGPT how it would work and I got the entire instruction set on how it could be done. I searched for the answer on the internet to see if it had taken it from memory or extrapolated it from other examples. It turns out there was no such article online.

Limitations and challenges

While AI-assisted coding is useful, it has its limitations which means you can’t blindly trust its written code. You have to review and test its generated code at each step.

Some limitations I observed:

  1. Sometimes Copilot will generate code using variables that do not exist in my code elsewhere but probably could have given the context and names of other variables. It is an exercise in writing good variable names but not correct when it comes to executing them.

  2. Asking ChatGPT for an instruction set for some tool or tech sometimes gives stale results since its data banks are older. Some of these tools could have evolved and no longer have the interface that your prompt result instructs you about. I have observed this for a few use cases in AWS.

Hope you enjoyed reading this.