Will AI make software engineers obsolete?
Tags: ai, go, githubcopilot, mongodb
Published: 2024-06-30 18:53:13

## Is GitHub Copilot worth the money?

Some months ago I tried out [GitHub Copilot](https://github.com/features/copilot) for free. At this time I started with [Go](https://go.dev/) and I was too lazy to read a book. I am a software engineer and normally use C# for programming. Copilot helped me to get started with the basics of Go. There are some stumbling blocks when you come from C#.

![GitHub Copilot Icon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4tlw41rr6e6amrsqfa0d.png)

The initial euphoria quickly soon began to fade. The code examples did not always compile and were full of errors. My corrections were always accepted. But more than once I found myself going around in circles because the next time I suggested fixing something, previously fixed errors would get re-included.

Did I waste money by buying GitHub Copilot?

***

## Does GitHub Copilot make me smarter?

I am writing a microservice for storing files. I have decided to use [MongoDB](https://www.mongodb.com/) to persist the file metadata. I have no experience with this specific database and I have never used a database with Golang. In my opinion, this is a perfect spotlight for the use of AI.

**Task 1: Create a docker-compose file**

First of all, I need a test database. I use docker-compose for that. Let’s ask the AI for help.

![Generate me a docker-compose file for MongoDB, please!
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iwpdvzumrmqztxs52zt1.png)

```docker
version: '3.8'
services:
  mongodb:
    image: mongo:latest
    container_name: mongodb_container
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
    volumes:
      - mongodb_data:/data/db
    ports:
      - 27017:27017
volumes:
  mongodb_data:
```

The AI answers with an example and a lot of text about how docker-compose works. Apart from the fact that the newest version is 3.9 ( [the source is probably the outdated docker documentation](https://forums.docker.com/t/docker-compose-version-3-8-or-3-9-for-latest/102439) ), this is very useful. But one explanation makes me suspicious:

![Explanation of the volume that is mapped in the docker-compose file
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dip393y3p903i0zm6baj.png)

Previously I only used [PostgreSQL](https://www.postgresql.org/) and I have never declared a volume for the database in the docker-compose file. For use as a test system, I want all data to be removed when I delete the Docker container. Let’s ask the AI how to achieve this instead of using Google:

![AI explained](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pfx5wiylriild7quzd71.png)

I didn’t know that but I expected this behaviour. Let’s teach the AI exactly what I want:

![AI helped](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gb72eyaoxfmbfqd2f1f.png)

```
mongodb:
  image: mongo:latest
  container_name: mongodb_container
  environment:
    MONGO_INITDB_ROOT_USERNAME: root
    MONGO_INITDB_ROOT_PASSWORD: example
  volumes:
    - /data/db
  ports:
    - 27017:27017
```

Nice one. My existing docker-compose file uses a network to allow communication between the database and the service. GitHub Copilot did not detect this. The container name does not follow my naming scheme. I fixed both problems manually. Overall good work.

**Task 2: Create a repository**

The use of a [repository to encapsulate the database](https://medium.com/@pantaanish/understanding-repository-pattern-with-implementation-a-step-by-step-guide-ca1bf36be3b4) is quite common. In my experience, Go is a bit different and I prefer to follow standards. So let’s ask GitHub Copilot if I have the right design:

![Repository pattern for Go?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xnnvrr1uhruixehj3lwc.png)

Never trust just one source is a good principle on the Internet. So ask about the sources the AI used:

![Who should I trust?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4h147qj0ds15d9190n7.png)

GitHub Copilot’s last sentence sounds like he is talking to a child. But I am not a child anymore. I am an experienced software developer. Two of the links are broken because the authors have changed the names of the Git repositories on GitHub. But as a human, I can find the correct links.

![One link is broken!](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/olt44k6fs9nnd4w5fi87.png)

![Another link is broken!](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0mag4wt1ts8x1ta7902i.png)

GitHub Copilot accepts my corrections without objection. Who is the child now? 🤪 As a good practice, I have to ask the child if it understood what I explained. Listen and repeat:

![Ask the same question again](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8hcj4e95qyxa4i0j8ro9.png)

The third source was removed. I have provided the corrected link and invested my time in correcting this. Let’s remind the AI.

![Getting to the bottom of it](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3p1muckub7yalq8enayi.png)

Let’s try to convince them to add the link again. The link was quite useful and I do not want to make GitHub Copilot any dumber.

![I am complaining](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/msundbdu53b2lxhfncn0.png)

This time, I give it a thumbs up (highlighted in yellow) to increase the chances that the answer will be used later. At least I hope it works that way.

Now that I know I want a repository, let’s create one. Of course, I use AI to do this, because programming is a lazy job.

![Generate repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/762xgek5orujlpqavu9s.png)

```golang
package repository

import (
    "context"
    "time"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type Repository struct {
    client *mongo.Client
    db     *mongo.Database
}

func NewMongoDBRepository(uri string, dbName string) (*Repository, error) {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
    if err != nil {
        return nil, err
    }
    db := client.Database(dbName)
    return &Repository{
        client: client,
        db:     db,
    }, nil
}

func (r *Repository) Close() error {
    return r.client.Disconnect(context.Background())
}
```

In general, that is ok. The code compiles, which was not the case in some other examples. Small modifications are needed. I prefer to use the [_context_ cancellation support](https://pkg.go.dev/context#WithCancel). Oops… I missed that there is a _WithTimeout_ function on the _context_. I always used _WithDeadline_. I have learned something from the AI. Today is a good day.

![A question that can only be asked by a software engineer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dr4u1e4fz1myzw9rbr0j.png)

So I can create the repository once, store it in a package-level variable, and initialize it from the main.go file. I manually add an initialization function for this.

```golang
var File file.FileRepository // package-level variable

func InitializeMongoDBRepository(uri string, databaseName string) error {
 var err error
 File, err = NewMongoDBRepository(uri, databaseName)
 return err
}
```

Phew… that one’s tough. I was typing code by myself. I want to rest now, so the AI should take over.

![Extend docker compose](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/297po7de43o5rqb5iwyd.png)

```golang
package main

import (
    "log"
    "github.com/kinneko-de/restaurant-file-store-svc/internal/app/repository"
)

func main() {
    // The URI should be in the format: mongodb://<username>:<password>@<host>:<port>
    uri := "mongodb://root:example@localhost:27017"
    databaseName := "mydatabase"
    err := repository.InitializeMongoDBRepository(uri, databaseName)
    if err != nil {
        log.Fatalf("Failed to initialize MongoDB repository: %v", err)
    }
    // The rest of your main function...
}
```

Stop… these are not the variables I used in my docker-compose file. Here is my final docker-compose file:

```
mongodb:
    image: mongo:latest
    networks:
      - project-network
    container_name: restaurant-file-store-db
    environment:
      MONGO_INITDB_ROOT_USERNAME: rootuser
      MONGO_INITDB_ROOT_PASSWORD: rootpassword
    volumes:
      - /data/db
    ports:
      - 27017:27017
```

I did not show the docker-compose file to GitHub Copilot as a reference. So I show it the file so it can fix the variables itself.

![Correct the code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ff8qbuj29aunij0u228.png)

```golang
package main

import (
    "log"
    "github.com/kinneko-de/restaurant-file-store-svc/internal/app/repository"
)

func main() {
    // The URI should be in the format: mongodb://<username>:<password>@<host>:<port>
    uri := "mongodb://rootuser:rootpassword@mongodb:27017"
    databaseName := "mydatabase"
    err := repository.InitializeMongoDBRepository(uri, databaseName)
    if err != nil {
        log.Fatalf("Failed to initialize MongoDB repository: %v", err)
    }
    // The rest of your main function...
}
```

![Final explanation by GitHub Copilot
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ep7y6avxi60qacdj3i5y.png)

Now the user and password are correct. But I think _‘mongodb’_ is the wrong value for the database host. I use _‘restaurant-file-store-db’_ as the container name in my docker-compose declaration. But humans are fallible, so let’s ask GitHub Copilot:

![I help the AI this time](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h962yajrtb321075p6ov.png)

```golang
package main

import (
    "log"
    "github.com/kinneko-de/restaurant-file-store-svc/internal/app/repository"
)

func main() {
    // The URI should be in the format: mongodb://<username>:<password>@<host>:<port>
    uri := "mongodb://rootuser:rootpassword@restaurant-file-store-db:27017"
    databaseName := "mydatabase"
    err := repository.InitializeMongoDBRepository(uri, databaseName)
    if err != nil {
        log.Fatalf("Failed to initialize MongoDB repository: %v", err)
    }
    // The rest of your main function...
}
```

Now I am a little bit confused. In its answer, the AI told me to use the _‘service name’_ which is _‘mongodb’_ and not _‘restaurant-file-store-db’_. But it still replaced my suggestion in the example. Does it just want to follow what I say even if it is wrong? I need to test this.

Testing shows that both versions work. Using [Stackoverflow as a resource for human knowledge](https://stackoverflow.com/questions/71829173/does-docker-use-service-name-or-container-name-to-resolve-service-reference-in-d), it turns out that using the service name is preferable. It works even if you have multiple instances. Not that it matters for my tests here, but I change the host back to the service name _‘mongodb’_.

![Never listen to humans, stupid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0grqw8kvpu18894exzib.png)

Overall, GitHub Copilot gives me a lot of good suggestions. The quality of the examples varies. It also cannot provide code examples for more advanced uses that a software engineer would normally have to take care of.

For example, I added health checks to the docker-compose file to ensure that the systems start in the right order and don’t crash non-deterministically. It also doesn’t realize that I need support for Kubernetes health checks and pod shutdown in the main.go file. The client, the database, and the collection of ‘mongodb’ are thread-safe and should not be recreated for each use. The examples are for demonstration and explanation only and are not production-ready.

***

## Conclusion

GitHub Copilot (and AI in general) is not (yet?) ready to replace me as a software engineer. It saves me some mindless typing and time-consuming internet research. It allows me to learn new things faster. I love this ❤.

At this stage, the AI is still a kid who needs my help to cross the street.

![man holding the baby's hand](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ghczu9w385soj1hfrra.jpg)
_Foto von <a href="https://unsplash.com/de/@benwhitephotography?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Ben White</a> auf <a href="https://unsplash.com/de/fotos/mann-halt-die-hand-des-babys-JJ9irt1OZmI?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a>_

I’m excited to see the kid grow up.