Dart & Flutter with ChatGPT: Is it worth it?

Last week, Open AI released this new ChatGPT assistant, and it has taken the world by storm.

But what is ChatGPT, and how does it work?

According to the official announcement:

We’ve trained a model called ChatGPT which interacts in a conversational way. The dialogue format makes it possible for ChatGPT to answer followup questions, admit its mistakes, challenge incorrect premises, and reject inappropriate requests.

ChatGPT is optimized for dialogue, and this makes it somewhat different from GitHub Copilot.

To find out how good it is with Dart & Flutter, I decided to take it for a ride and test it with various coding tasks.

So in this article, I'll share some of my experiments with ChatGPT, show you how well it did, and try to give objective answers to the most pressing questions in life:

  • Can you trust ChatGPT to produce correct code for you? πŸ˜‰
  • How to make the most of it? πŸ› 
  • Will AI take your job away? 😱

Ready? Let's dive in!

Using ChatGPT with Dart & Flutter: Methodology

To get started, I decided to test ChatGPT on various kinds of tasks:

  • Detect and correct common coding errors
  • Explain how code works
  • Write or complete code to solve a given task

For code writing tasks, I followed a two-step process:

  1. ask to write code to solve a specific, discrete problem
  2. verify if the code compiles, runs, and produces the correct output

When the output was not as expected, I asked follow-up questions to see if ChatGPT would correct itself.

I repeated this process with nine different tasks. You can find all the results below, along with my observations. πŸ‘‡

Note that this is a long article. If you're short on time and want to cut to the chase, feel free to jump to the final results and evaluation.

For improved readability, I have included my dialogues with ChatGPT without modifications (rather than pasting screenshots). You can ask the very same questions on the ChatGPT page if you wish - though note that the output can vary, and ChatGPT will produce slightly different responses every time. To learn about how the model was trained, read here and here.

Experiment 1: Detect and Fix an Error

Me: Is there something wrong with this code?

Future<String> doSomeAsyncWork(String debugName) async { Future.delayed(Duration(seconds: 1)); return debugName; }

AI: Yes, there is a problem with this code. The Future.delayed method returns a Future, but in this code, the returned Future is not being awaited or assigned to a variable. This means that the code will not actually pause for one second before returning the debugName parameter.

Here is one way to fix the code:

Future<String> doSomeAsyncWork(String debugName) async { await Future.delayed(Duration(seconds: 1)); return debugName; }

Alternatively, you can use the then method to chain a function that will be called once the Future returned by Future.delayed completes:

Future<String> doSomeAsyncWork(String debugName) { return Future.delayed(Duration(seconds: 1)).then((_) => debugName); }

In both of these examples, the code will pause for one second before returning the debugName parameter.

My comments

Forgetting to use await is a common mistake and not something the static analyzer will point out (since it's not a syntax error).

But with ChatGPT, it didn't go unnoticed.

What's more, it pointed out an alternative implementation based on .then. I didn't think about that! 🀯

This shows that ChatGPT can reduce the time spent on debugging. πŸ‘

Final result: success! βœ…

If we want, we can explicitly enable the unawaited_futures linter rule (which is disabled by default) to get a warning if we forget to await a Future inside an async function body. To learn more about custom lint rules, read: Flutter Linting and Linter Comparison.

Experiment 2: Explain how some code works

Me: Can you explain how this code works?

import 'package:freezed_annotation/freezed_annotation.dart'; import 'tmdb_movie.dart'; part 'tmdb_movies_response.freezed.dart'; part 'tmdb_movies_response.g.dart'; @freezed class TMDBMoviesResponse with _$TMDBMoviesResponse { factory TMDBMoviesResponse({ required int page, required List<TMDBMovie> results, @JsonKey(name: 'total_results') required int totalResults, @JsonKey(name: 'total_pages') required int totalPages, @Default([]) List<String> errors, }) = _TMDBMoviesResponse; factory TMDBMoviesResponse.fromJson(Map<String, dynamic> json) => _$TMDBMoviesResponseFromJson(json); }

AI This code defines a TMDBMoviesResponse class in the Dart programming language. The class is marked with the @freezed annotation, which is a Dart package called freezed_annotation that provides a way to create "immutable and serializable classes" in Dart.

The TMDBMoviesResponse class has several fields that represent data that might be returned from some kind of API, such as page, results, totalResults, and totalPages. These fields are marked as required, which means that they must be provided when creating an instance of the class.

The TMDBMoviesResponse class also has a errors field, which is marked with the @Default annotation and is initialized to an empty List<String> (an empty list of strings). This means that if no value is provided for the errors field when creating an instance of the class, it will be initialized to an empty list.

The class also has a factory constructor called TMDBMoviesResponse.fromJson, which takes in a Map<String, dynamic> (a map of keys and values where the values can be of any type) and uses it to create and initialize an instance of the TMDBMoviesResponse class. This constructor is used to create an instance of the class from a JSON object, which is commonly used as a way to represent data in APIs.

It's worth noting that the code includes two part directives: 'tmdb_movies_response.freezed.dart' and 'tmdb_movies_response.g.dart'. The part directive is a way to include code from another file in the same Dart library or package. In this case, it's likely that the tmdb_movies_response.freezed.dart file contains additional code that is related to the freezed package, while the tmdb_movies_response.g.dart file contains generated code that is used to create instances of the TMDBMoviesResponse class from a JSON object.

My comments

ChatGPT clearly knows about the Freezed package and how it works. ❄️

People who never used Dart code generation would struggle to understand the syntax above and will highly appreciate such a detailed explanation. πŸ™

Final result: success! βœ…

Experiment 3: Complete a binary search implementation

Me: I'm writing a binary search function to find an item in an ordered list of integers. Can you add the missing code and briefly explain how it works?

int binarySearch(List<int> list, int item) { int low = 0; int high = list.length - 1; // TODO: implement // If the item is not found, return -1 return -1; }

AI: Sure, here's one way to implement a binary search function in Dart:

int binarySearch(List<int> list, int item) { int low = 0; int high = list.length - 1; while (low <= high) { // Calculate the middle index int mid = (low + high) ~/ 2; // Get the item at the middle index int guess = list[mid]; if (guess == item) { // If the guess is correct, return the index return mid; } else if (guess > item) { // If the guess is too high, reduce the high index high = mid - 1; } else { // If the guess is too low, increase the low index low = mid + 1; } } // If the item is not found, return -1 return -1; }

This function uses a binary search algorithm to find the item in the given list. It starts by setting the low and high indices to the beginning and end of the list, respectively. It then enters a loop where it continuously divides the search space in half until it finds the item or determines that it's not in the list.

At each iteration of the loop, the function calculates the middle index of the current search space, and compares the item at that index to the target item. If they match, the function returns the index. If the item at the middle index is greater than the target item, the function reduces the search space to the lower half of the list (by setting the high index to the middle index minus one). Otherwise, it increases the search space to the upper half of the list (by setting the low index to the middle index plus one).

If the loop ends without finding the item, the function returns -1 to indicate that the item was not found in the list.


My comments

Once again, good job!

Given that ChatGPT is a general purpose tool that wasn't specifically trained for coding problems, it's remarkably accurate when dealing with data structures and algorithms. πŸ”₯

And I'm sure many CS students would use this to cheat on their exams! πŸ˜…

Final result: success! βœ…

Experiment 4: Play Rock, Paper, and Scissors

Me: Write a Dart program that lets a human play rock, paper, and scissors against the computer. The human can choose each move by typing it from the command line. The computer should choose each move at random.


AI: Here is a sample program in Dart that lets a human play rock, paper, scissors against the computer:

import 'dart:io'; import 'dart:math'; void main() { // Create a list of moves. final moves = ['rock', 'paper', 'scissors']; // Create a random number generator. final random = Random(); // Play the game. while (true) { // Get the human move. print('Enter your move (rock, paper, or scissors):'); final humanMove = stdin.readLineSync().toLowerCase(); // Check if the human move is valid. if (!moves.contains(humanMove)) { print('Invalid move!'); continue; } // Get the computer move. final computerMove = moves[random.nextInt(moves.length)]; print('Computer plays $computerMove'); // Determine the winner. if (humanMove == computerMove) { print('It\'s a tie!'); } else if ( (humanMove == 'rock' && computerMove == 'scissors') || (humanMove == 'paper' && computerMove == 'rock') || (humanMove == 'scissors' && computerMove == 'paper') ) { print('You win!'); } else { print('Computer wins!'); } print(); } }

In this program, we create a list of moves that the human and the computer can choose from. Then, we use a Random object to generate random numbers, which we use to choose the computer's moves.

In each round of the game, the human enters their move from the command line, and the computer chooses a move at random. We check if the human's move is valid, and if it is, we determine the winner of the round based on the rules of rock, paper, scissors.

Finally, we print the result of the round and continue to play until the human quits the game.


My comments

The code in the answer seems plausible, and the follow-up explanation is clear and confident.

But is it correct?

At first sight, the code is concise and includes some defensive programming (checking if the human move is valid).

The AI added a game loop (while (true)) without being prompted. This shows a good understanding of how I might want to play the game.

When a question is not specific enough, ChatGPT will make assumptions about your intention. If you hit "Try again" to get a different answer, it may make different assumptions.

Does the code compile?

Well, I copied it over to a dart file in VSCode, and spotted two compile errors:

final humanMove = stdin.readLineSync().toLowerCase(); // The method 'toLowerCase' can't be unconditionally invoked because the receiver can be 'null'.
print(); // 1 positional argument(s) expected, but 0 found.

The first error is easily fixed by adding a ! since readLineSync() returns a nullable value:

final humanMove = stdin.readLineSync()!.toLowerCase();

And the second error is fixed by removing the print() statement altogether (not sure why it was added in the first place).

Lo and behold, the game is now playable! πŸ‘‡

➜ dart rock_paper_scissors.dart Enter your move (rock, paper, or scissors): rock Computer plays rock It's a tie! Enter your move (rock, paper, or scissors): scissors Computer plays paper You win! Enter your move (rock, paper, or scissors): paper Computer plays scissors Computer wins! Enter your move (rock, paper, or scissors):

It would have taken me ~15 minutes to write the same program.

Yet ChatGPT got it right on the first try, and I got the code to work in 1 minute with very minor fixes.

Very impressive indeed. πŸ‘

Final result: success! βœ…

Experiment 5: Get the Current Weather

Me: Write a Dart program to fetch the current weather for a given city using the OpenWeatherMap API. The input city should be passed as a command line argument.


AI: Here is a simple Dart program that uses the http package to make a GET request to the OpenWeatherMap API to fetch the current weather for a given city:

import 'package:http/http.dart' as http; void main(List<String> args) { if (args.length != 1) { print("Please provide a city name as a command line argument."); return; } // Replace this with your own OpenWeatherMap API key. String apiKey = "<your_api_key>"; // Replace this with the correct URL for the OpenWeatherMap API. String url = "https://api.openweathermap.org/data/2.5/weather?q=${args[0]}&appid=$apiKey"; http.get(url).then((response) { if (response.statusCode == 200) { // The API returned a successful response. print(response.body); } else { // The API returned an error. print("Failed to fetch weather data. Please check your API key and city name and try again."); } }); }

In this example, the city name is passed as a command line argument, and the API key is hard-coded into the program. You will need to replace <your_api_key> with your own API key from OpenWeatherMap.


My comments

At first sight, this looks good!

There is one compile error on this line:

http.get(url).then((response) { // The argument type 'String' can't be assigned to the parameter type 'Uri'

This is easily fixed using the Uri.parse method:

http.get(Uri.parse(url)).then((response) {

Most likely, ChatGPT was unaware of a breaking change requiring to pass a Uri rather than a String when calling any of the http methods.

ChatGPT claims to be trained with public data up to 2021, and we should keep it in mind if we use APIs with recent breaking changes.

The code style could be improved by using async/await rather than .then, but this can be easily changed by hand.


After adding my API key (as instructed), I ran the program and got this:

➜ dart bin/weather.dart London {"coord":{"lon":-0.1257,"lat":51.5085},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],"base":"stations","main":{"temp":278.51,"feels_like":275.38,"temp_min":277.33,"temp_max":279.4,"pressure":1016,"humidity":83},"visibility":10000,"wind":{"speed":4.12,"deg":60},"clouds":{"all":100},"dt":1670156052,"sys":{"type":2,"id":2075535,"country":"GB","sunrise":1670140072,"sunset":1670169228},"timezone":0,"id":2643743,"name":"London","cod":200}

The program works but prints the entire JSON response from the API.

So let's fix this!

Second prompt in thread

Me: Modify this to only print the current temperature.


AI: Here is a modified version of the Dart program that only prints the current temperature from the response from the OpenWeatherMap API:

Note: the output was the same as before, with just one change in the parsing code:

// The API returned a successful response. var data = json.decode(response.body); var temperature = data['main']['temp']; print("The current temperature in ${args[0]} is $temperature degrees.");

In this example, the response body from the API is decoded using the json package, and the temp field from the main section of the JSON data is extracted and printed. This program assumes that the response from the API will be in the correct format and will contain the necessary data. You may need to add additional error handling to handle any unexpected response formats or missing data.


My comments

Very good!

Let's run this again:

➜ dart bin/weather.dart London The current temperature in London is 278.51 degrees.

Better, but "278.51 degrees" doesn't seem right. I guess I wasn't specific enough with my request.

Third prompt in thread

Me: The output temperature should be in Celsius, not Kelvin.


AI: Here is a modified version of the Dart program that converts the temperature from Kelvin to Celsius before printing it:

Note: the output was the same as before, with just this one change on the parsing code:

// The API returned a successful response. var data = json.decode(response.body); var temperature = data['main']['temp']; var temperatureC = temperature - 273.15; print("The current temperature in ${args[0]} is $temperatureC degrees Celsius.");

In this example, the temperature is converted from Kelvin to Celsius by subtracting 273.15 from the temperature in Kelvin. This is a simple approximation that assumes a temperature of 0Β°C is equivalent to 273.15Β°K, which is a common approximation but may not be accurate at all temperatures. You may need to use a more accurate conversion formula if you require greater precision.


My comments

Spot on!

Here's the output after the last change:

dart bin/weather.dart London The current temperature in London is 5.360000000000014 degrees Celsius.

At this point, I could have asked the AI to print the temperature as an integer.

But it's clear that ChatGPT remembers the context of the previous conversation and uses it when producing the next answer.

This means that if our initial prompt is not precise enough, we don't need to restart from scratch, and we can get a refined solution by following up with more details.

Overall, this feels like having a dialogue with a competent assistant. πŸ‘Œ

Final result: success! βœ…

Experiment 6: CustomPainter

For this experiment, I asked the AI to write some Flutter code using CustomPainter, since doing this by hand can be time-consuming.

Me: Write a Flutter CustomPainter that draws a smiling face with two eyes.


AI: Here is an example of a Flutter CustomPainter that draws a smiling face with two eyes:

class SmilingFacePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint(); // Set the color to blue paint.color = Colors.blue; // Create a circle for the face final center = Offset(size.width / 2, size.height / 2); final radius = min(size.width / 2, size.height / 2); canvas.drawCircle(center, radius, paint); // Create two eyes final eyeOffset = radius / 3; final leftEye = Offset(center.dx - eyeOffset, center.dy - eyeOffset); final rightEye = Offset(center.dx + eyeOffset, center.dy - eyeOffset); final eyeRadius = radius / 6; canvas.drawCircle(leftEye, eyeRadius, paint); canvas.drawCircle(rightEye, eyeRadius, paint); // Create a smile final smilePath = Path(); smilePath.moveTo(center.dx - radius / 2, center.dy); smilePath.quadraticBezierTo(center.dx, center.dy + radius / 2, center.dx + radius / 2, center.dy); canvas.drawPath(smilePath, paint); } @override bool shouldRepaint(CustomPainter oldDelegate) => false; }

To use this CustomPainter, you can pass an instance of SmilingFacePainter to the CustomPaint widget in your Flutter app.

CustomPaint( painter: SmilingFacePainter(), );

This will draw a smiling face with two eyes on the screen. You can customize the appearance of the face by modifying the values in the paint object, such as the color or the size of the eyes.


My comments

A pretty good start!

After bringing this code into Dartpad I noticed that there is only one small problem:

final radius = min(size.width / 2, size.height / 2); // The method 'min' isn't defined for the type 'SmilingFacePainter'.

This is easily fixed by importing dart:math (which can be done using Quick Fix in VSCode):

import 'dart:math';

Here's a Dartpad preview of the code above:

CustomPainter code generated by ChatGPT

But hang on, where are the eyes and mouth?

As it turns out, they have been drawn but are not visible because they have the same blue color as the face.

Second prompt in thread

Me: Make the face yellow. The eyes and mouth should be red.


AI: To make the face yellow, you can modify the paint.color property in the SmilingFacePainter class like this:

paint.color = Colors.yellow;

To make the eyes and mouth red, you can create a new Paint object with the color set to red and use it to draw the eyes and mouth like this:

class SmilingFacePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint(); // Set the color to yellow for the face paint.color = Colors.yellow; // Create a circle for the face final center = Offset(size.width / 2, size.height / 2); final radius = min(size.width / 2, size.height / 2); canvas.drawCircle(center, radius, paint); // Set the color to red for the eyes and mouth paint.color = Colors.red; // Create two eyes final eyeOffset = radius / 3; final leftEye = Offset(center.dx - eyeOffset, center.dy - eyeOffset); final rightEye = Offset(center.dx + eyeOffset, center.dy - eyeOffset); final eyeRadius = radius / 6; canvas.drawCircle(leftEye, eyeRadius, paint); canvas.drawCircle(rightEye, eyeRadius, paint); // Create a smile final smilePath = Path(); smilePath.moveTo(center.dx - radius / 2, center.dy); smilePath.quadraticBezierTo(center.dx, center.dy + radius / 2, center.dx + radius / 2, center.dy); canvas.drawPath(smilePath, paint); } @override bool shouldRepaint(CustomPainter oldDelegate) => false; }

This will make the face yellow, and the eyes and mouth red. You can further customize the appearance of the face by modifying the values in the paint object, such as the size of the eyes or the width of the mouth.


My comments

Nice! Now I just need to update the code and violà! 🎨

Tweaked CustomPainter code generated by ChatGPT

Well done, ChatGPT. I'm proud of you!

Final result: success! βœ…

Experiment 7: Declare three routes using the GoRouter package

Me: Suppose I have a Flutter app with three routes: /login, /home, and /account. Declare these routes using the GoRouter package.


AI: To declare routes using the GoRouter package in a Flutter app, you would first need to import the package:gorouter/gorouter.dart library. Then, you could define the routes as follows:

var router = GoRouter(); router.define('/login', handler: (context) { // Handle the /login route }); router.define('/home', handler: (context) { // Handle the /home route }); router.define('/account', handler: (context) { // Handle the /account route });

Alternatively, you could define the routes using the .add() method, which allows you to specify additional options for each route, such as the HTTP methods that it supports or the handler function to be called when the route is accessed:

var router = GoRouter(); router.add('/login', methods: ['GET', 'POST'], handler: (context) { // Handle the /login route }); router.add('/home', methods: ['GET'], handler: (context) { // Handle the /home route }); router.add('/account', methods: ['GET', 'PUT'], handler: (context) { // Handle the /account route });

Once you have defined your routes, you can use the router.run() method to start the router and listen for incoming requests. For example:

router.run();

This will start the router and allow it to handle requests to the defined routes. You can then use the router.navigateTo() method to navigate to a specific route within your Flutter app. For example:

router.navigateTo('/login');

This will navigate to the /login route and call the corresponding handler function.


My comments

Completely wrong!

I guess ChatGPT doesn't know about GoRouter and just tried to guess the answer based on some (server-side?) routing package outside the Flutter ecosystem.

In this case, ChatGPT is useless, and not suited for the task.

Final result: fail! ❌

Experiment 8: Write a Firebase Cloud Function

Since ChatGPT is proficient with many languages, I decided to move away from Dart & Flutter and ask it to write a Cloud Function.

Me: Write a Firebase Cloud function that is triggered when any document inside a /product/{pid}/reviews collection changes. The function should calculate the average review score and write it back as an avgRating field inside the /product/{pid} document.


AI: Here is an example of a Firebase Cloud Function that is triggered when a document inside a /product/{pid}/reviews collection changes. This function calculates the average review score and writes it back as an avgRating field inside the /product/{pid} document:

const functions = require('firebase-functions'); const admin = require('firebase-admin'); admin.initializeApp(); exports.calculateAverageRating = functions.firestore .document('/product/{pid}/reviews/{reviewId}') .onWrite(async (change, context) => { // Get the product ID from the context const pid = context.params.pid; // Get a reference to the reviews collection const reviewsRef = admin .firestore() .collection('/product/' + pid + '/reviews'); // Get all the reviews for the product const reviewsSnapshot = await reviewsRef.get(); // Calculate the average rating let totalRating = 0; let numRatings = 0; reviewsSnapshot.forEach(review => { totalRating += review.data().rating; numRatings++; }); const avgRating = totalRating / numRatings; // Get a reference to the product document const productRef = admin.firestore().doc('/product/' + pid); // Update the product document with the average rating return productRef.update({ avgRating: avgRating }); });

This function listens for changes to any document in the /product/{pid}/reviews collection using a wildcard {pid} and {reviewId} in the path. When a change is detected, the function gets a reference to the /product/{pid}/reviews collection and retrieves all the reviews for the product. It then calculates the average rating by summing up all the ratings and dividing by the number of ratings. Finally, the function gets a reference to the /product/{pid} document and updates it with the avgRating field.


My comments

The code compiles, so it's a good start!

I haven't tried running it, but I think ChatGPT got a few things right:

  • how to write a trigger to update a document
  • extracting parameters from the context
  • calculating the average rating
  • writing it to the correct document

I wasn't too fond of the imports at the top, so I followed up with this. πŸ‘‡

Second prompt in thread

Me: Can you use module imports rather than require?


AI: Yes, you can use module imports rather than require in JavaScript. Here is an example of how you might import the firebase-functions and firebase-admin modules in your Firebase Cloud Function:

import * as functions from 'firebase-functions'; import * as admin from 'firebase-admin'; admin.initializeApp(); // Rest of the Cloud Function code goes here...

In this example, we are using the import * as syntax to import the entire module and assign it to a variable named functions and admin. You can then use the imported functions and classes from the firebase-functions and firebase-admin modules by referencing them through the functions and admin variables.


My comments

This thing is lit! πŸ”₯

Final result: success! βœ…

Experiment 9: How to seed Cloud Firestore with some test data?

Me: How can I seed Cloud Firestore with some test data?


AI: To seed Cloud Firestore with test data, you can use the Firebase CLI to write data directly to your database. First, make sure that the Firebase CLI is installed on your machine. Then, use the following steps to seed your database:

  1. Navigate to the directory where your Firebase project is stored.
  1. Run the firebase login command to authenticate the Firebase CLI with your Google account.
  1. Run the firebase database:get command to retrieve the current data in your database. This will create a local file called database.json in your project directory, which you can use as a starting point for your test data.
  1. Edit the database.json file to add the test data that you want to seed your database with. Make sure to follow the proper JSON syntax and structure when adding data to this file.
  1. Once you have added your test data, run the firebase database:set command to write the data to your database.
  1. You can verify that your test data has been added to your database by running the firebase database:get command again, which will retrieve the current data in your database and print it to the console.

That's it! You have successfully seeded your Cloud Firestore database with test data.


My comments

While the answer sounds plausible, it is wrong!

According to the docs, database:get is indeed a valid command, but it only works on Firebase Realtime Database, and there is no equivalent for Cloud Firestore.

I told my friendly assistant about it, but it answered with commands like firestore:set and firestore:add that don't actually exist.

And it kept giving wrong answers with confidence. πŸ™„

Final result: fail! ❌

Final Results and Evaluation

I must say I'm very impressed by the natural language processing skills of ChatGPT. Clearly, the AI did understand every single question, and that in itself is a very remarkable feat!

Beyond that, ChatGPT managed to score 7 out of 9 points and proved valuable in all these areas:

  • Detect and correct common coding errors
  • Explain how code works
  • Write or complete code to solve a given task

ChatGPT failed two tasks, showing that it is not up to date with the latest packages and APIs, and it kept giving wrong answers when prompted.

But on the remaining tasks, I was very impressed with the explanations and thought the code was pretty good.

Some minor syntax errors were present, but they were easy to fix, and I got the code to work much faster than if I had written it by hand.

Some reflections on ChatGPT and a word of caution

After spending more time getting acquainted with ChatGPT, I would summarise as follows:

  • ChatGPT always gives answers that look plausible in a very confident tone, even when they are wrong.
  • It is very good at answering specific questions where the solution is not too complex.
  • It is particularly good with questions about data structures and algorithms (you know, those that always pop up during tech interviews 😎).
  • It clearly doesn't know the latest APIs (I asked questions about GoRouter, Riverpod, and other packages, and it was completely off-mark).
  • It can explain code in a lot of detail.
  • If you ask generic questions, you'll get generic answers that lack insight (try asking about state management or app architecture and you'll see).

If you're working on simple, well-defined, and self-contained tasks based on data that ChatGPT was trained on, a ChatGPT-based workflow can be 10x faster than coding the solution by hand. And this is quite remarkable!

ChatGPT is good enough at writing pure Dart code (such as business logic) that doesn't rely on APIs and frameworks. Since it "knows" all the mainstream programming languages, it can definitely help you in areas where you're not an expert, especially when you're writing new code.

But when you're working on existing code, you need a lot of context about how the system works as a whole, and an AI model trained on public code is unlikely to be of much help.

Be particularly careful if you use ChatGPT with dynamically typed languages that don't give you any compile-time guarantees. If the answer is wrong, you'll only find out at runtime, and we all know how fun that is.

Developer days before and after Open AI
Developer days before and after Open AI. Source: r/ProgrammerHumor

ChatGPT can be helpful but unreliable, so keep this in mind:

ChatGPT is "just" an assistant, and you are responsible for ensuring the code is correct! 🫡

In fact, ChatGPT is not an authoritative source like a high-quality tutorial or official documentation.

Here's an interesting take by Daniel Vassallo:

Making the most of ChatGPT with Prompt Engineering

To make the most of ChatGPT and other AI tools, you need to get good at prompt engineering.

Here are some thoughts I shared about it:

Prompt engineering is certainly a valuable skill today. But what role will AI play in the future?

Will AI take your job away?

Developer tools are getting better and better.

In addition to compilers, debuggers, static analyzers, language servers, and powerful IDEs, we now have the power of AI at our disposal.

AI can help us ship better software faster if we learn to use it strategically, and for now, ChatGPT and GitHub Copilot can help us solve basic programming problems.

But as AI continues to get better, we have to wonder:

  • Will it take our jobs away?

I'll quote Fireship on this one, as he has already made some great videos about GitHub Copilot and ChatGPT. This is his take:

  • Step 1 - developers share code data
  • Step 2 - build an AI with that data
  • Step 3 - reinforce the AI with developers
  • Step 4 - replace developers with AI

It seems that we are squarely at step 3 today, and I hear GPT-4 is just round the corner.

To find out what will really happen, I decided to ask one last question to ChatGPT. πŸ‘‡

Will ChatGPT take our jobs away?
Will ChatGPT take our jobs away?

That was obviously made up. If you wanna hear what a real expert thinks about AI, check this podcast where Lex Friedman asked John Carmack about AGI (and much more).

I guess we'll wait and see. πŸ˜…

Happy coding!

References

To better understand how ChatGPT works and what it can do, I found these resources helpful:

Want More?

Invest in yourself with my high-quality Flutter courses.

The Complete Dart Developer Guide

The Complete Dart Developer Guide

Learn Dart Programming in depth. Includes: basic to advanced topics, exercises, and projects. Fully updated to Dart 2.15.

The Complete Flutter Course Bundle

The Complete Flutter Course Bundle

Learn about State Management, App Architecture, Navigation, Testing, and much more by building a full-stack Flutter eCommerce app on iOS, Android, and web.

Flutter Animations Masterclass - Full Course

Flutter Animations Masterclass - Full Course

Master Flutter animations and build a completely custom habit tracking application.