SEが、ChatGPTでコーディングを手伝ってもらえるか、ちょっと遊んでみた
最近、毎日AIの話題を聞くようになったように思います。
ChatGPTでプログラムが書けるという話もよく聞きます。
私は普段SEとして働いています。今のところまるまるChatGPTにプログラムを作成させようとは思いませんが、うまく使えばコーディングの時間はかなり減らせるのでは?と思い、ちょっとChartGPTにコーディングさせて遊んでみました。
宣言などのコーディング
単純な宣言
単純な定数宣言などをChatGPTに手伝ってもらえないか?ということで、まず試してみたのがこれ。
おお、ちゃんとコーディングされています。
こういうのって必要な場合もあるので、数が多い場合はかなり時短になるかも。
配列
コードが見切れているのでコード部分を抜き出しました。
string[] numbers = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
変数名を指示していないですが、numbers って変数にしてくれてます。良いですね。こういうのも作るときがあるので、これは助かるかも。
定数宣言クラス
次に試したのが、これ。
一回の指示でクラスができるかな?と思い、試した指示。
ちゃんと出力されていますね。これなんか手で打つと何気に面倒だから助かるかも。
定数以外でクラス定義
さらにもうちょっと高度にしてみます。
コーディングの後ろにChatGPTがいろいろ説明をつけてましたが長くなるので割愛しました。
これはちょっと驚き。
指示していないコンストラクタやメンバ変数、値取得のメソッドまで出力されているし、static しか指示していないのに static readonly になっている。確かに static readonly の方が望ましい。
場合によっては、余計なお世話になる場合もあるけど、今回のケースでは正解かな。
コーディングの修正
できたコーディングで、自分が気に入らない部分の修正や、追加したいものなどを指示してみます。
削除と追加
Valueプロパティの仕様などは指示していないが、期待通りになっています。「代わりに」というワードが効いているのでしょうか。
記述方法を変更
C#9.0以降、型がわかっている場合は初期化の際、newの後の型は省略できます。それを指示してみます。
静的変数が読取専用のプロパティに変わりました。おまけにコンストラクタやプロパティもラムダ式に変わっている。C#9.0ってワードが効いた?
メソッドの追加指示
メソッドの追加も指示してみました。
コードが長くなってきたので、出力されたコード部分だけ抜き出します。
public class Month {
public static Month January { get; } = new(1);
public static Month February { get; } = new(2);
public static Month March { get; } = new(3);
public static Month April { get; } = new(4);
public static Month May { get; } = new(5);
public static Month June { get; } = new(6);
public static Month July { get; } = new(7);
public static Month August { get; } = new(8);
public static Month September { get; } = new(9);
public static Month October { get; } = new(10);
public static Month November { get; } = new(11);
public static Month December { get; } = new(12);
private readonly int value;
private Month(int value) => this.value = value;
public int Value => value;
public Month Add(int months) {
int newValue = (value - 1 + months) % 12 + 1;
return newValue switch {
1 => January,
2 => February,
3 => March,
4 => April,
5 => May,
6 => June,
7 => July,
8 => August,
9 => September,
10 => October,
11 => November,
12 => December,
_ => throw new InvalidOperationException("Invalid month value"),
};
}
}
ちゃんとできていますね。12月を超えても処理できるようになっているし、指示していないが、new Month(newValue) ではなく、ちゃんと各静的宣言したプロパティを返しています。例外処理まで書いてますね。
もっといろいろ修正させる
public class Month
{
private readonly int _value;
private readonly string _name;
public static Month January { get; } = new Month(1, "January");
public static Month February { get; } = new Month(2, "February");
public static Month March { get; } = new Month(3, "March");
public static Month April { get; } = new Month(4, "April");
public static Month May { get; } = new Month(5, "May");
public static Month June { get; } = new Month(6, "June");
public static Month July { get; } = new Month(7, "July");
public static Month August { get; } = new Month(8, "August");
public static Month September { get; } = new Month(9, "September");
public static Month October { get; } = new Month(10, "October");
public static Month November { get; } = new Month(11, "November");
public static Month December { get; } = new Month(12, "December");
public Month(int value, string name)
{
_value = value;
_name = name;
}
public int Value => _value;
public string Name => _name;
public static Month FromValue(int value)
{
return value switch
{
1 => January,
2 => February,
3 => March,
4 => April,
5 => May,
6 => June,
7 => July,
8 => August,
9 => September,
10 => October,
11 => November,
12 => December,
_ => throw new ArgumentException("Invalid value for month"),
};
}
public static Month FromName(string name)
{
return name.ToLower() switch
{
"january" => January,
"february" => February,
"march" => March,
"april" => April,
"may" => May,
"june" => June,
"july" => July,
"august" => August,
"september" => September,
"october" => October,
"november" => November,
"december" => December,
_ => throw new ArgumentException("Invalid name for month"),
};
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
Month other = (Month)obj;
return _value == other._value && _name == other._name;
}
public override int GetHashCode()
{
return HashCode.Combine(_value, _name);
}
}
今回は余計なお世話をしてくれたようです。
頼んでもいない name を追加しているし、先程頼んだAddメソッドも消えています。
指摘したら修正した。今度は修正箇所だけを返してきました。
これも長くなったのでコーディング部分だけ。
public class Month
{
private static readonly string[] MonthNames = new string[] {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};
public static readonly Month January = new Month(1);
public static readonly Month February = new Month(2);
public static readonly Month March = new Month(3);
public static readonly Month April = new Month(4);
public static readonly Month May = new Month(5);
public static readonly Month June = new Month(6);
public static readonly Month July = new Month(7);
public static readonly Month August = new Month(8);
public static readonly Month September = new Month(9);
public static readonly Month October = new Month(10);
public static readonly Month November = new Month(11);
public static readonly Month December = new Month(12);
private readonly int _value;
public Month(int value)
{
if (value < 1 || value > 12)
{
throw new ArgumentOutOfRangeException(nameof(value), "Month value must be between 1 and 12.");
}
_value = value;
}
public int Value
{
get { return _value; }
}
public Month Add(int months)
{
int newValue = (_value - 1 + months) % 12 + 1;
return new Month(newValue);
}
public override string ToString()
{
return MonthNames[_value - 1];
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
Month otherMonth = (Month)obj;
return Value == otherMonth.Value;
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
}
前半に文字列あるな、と思ったら ToString() 用のようです。まぁ、それはいいか。
でも、せっかく途中 C#9.0 で簡潔に書けていたのに元に戻ってしまいました。
public class Month
{
public string Name { get; }
public int Value { get; }
private Month(int value, string name) => (Value, Name) = (value, name);
public static Month January { get; } = new(1, "January");
public static Month February { get; } = new(2, "February");
public static Month March { get; } = new(3, "March");
public static Month April { get; } = new(4, "April");
public static Month May { get; } = new(5, "May");
public static Month June { get; } = new(6, "June");
public static Month July { get; } = new(7, "July");
public static Month August { get; } = new(8, "August");
public static Month September { get; } = new(9, "September");
public static Month October { get; } = new(10, "October");
public static Month November { get; } = new(11, "November");
public static Month December { get; } = new(12, "December");
public Month Add(int months)
{
var result = (Value + months - 1) % 12 + 1;
return result < Value ? new Month(result, FromValue(result).Name) : new Month(result, Name);
}
public override bool Equals(object obj) => obj is Month month && Value == month.Value;
public override int GetHashCode() => Value;
public static Month FromValue(int value) => value switch
{
1 => January,
2 => February,
3 => March,
4 => April,
5 => May,
6 => June,
7 => July,
8 => August,
9 => September,
10 => October,
11 => November,
12 => December,
_ => throw new ArgumentOutOfRangeException(nameof(value), value, "Invalid month value")
};
}
using System;
public class Month
{
private readonly int value;
private Month(int value)
{
if (value < 1 || value > 12)
{
throw new ArgumentOutOfRangeException(nameof(value), "Month must be between 1 and 12.");
}
this.value = value;
}
public static Month FromValue(int value)
{
return new Month(value);
}
public int Value => value;
public override bool Equals(object obj)
{
return obj is Month other && value == other.value;
}
public override int GetHashCode()
{
return value;
}
public static bool operator ==(Month left, Month right)
{
return left?.Equals(right) ?? right is null;
}
public static bool operator !=(Month left, Month right)
{
return !(left == right);
}
public override string ToString()
{
return value switch
{
1 => "January",
2 => "February",
3 => "March",
4 => "April",
5 => "May",
6 => "June",
7 => "July",
8 => "August",
9 => "September",
10 => "October",
11 => "November",
12 => "December",
_ => throw new Exception("Invalid month value.")
};
}
public Month Add(int months)
{
int result = (value - 1 + months) % 12 + 1;
return FromValue(result);
}
}
public class Month
{
public int Value { get; }
private Month(int value)
{
Value = value;
}
public static Month January { get; } = new Month(1);
public static Month February { get; } = new Month(2);
public static Month March { get; } = new Month(3);
public static Month April { get; } = new Month(4);
public static Month May { get; } = new Month(5);
public static Month June { get; } = new Month(6);
public static Month July { get; } = new Month(7);
public static Month August { get; } = new Month(8);
public static Month September { get; } = new Month(9);
public static Month October { get; } = new Month(10);
public static Month November { get; } = new Month(11);
public static Month December { get; } = new Month(12);
public Month Add(int months)
{
return FromValue(Value + months);
}
public static Month FromValue(int value)
{
if (value < 1 || value > 12)
{
throw new ArgumentOutOfRangeException(nameof(value), "Month must be between 1 and 12.");
}
return value switch
{
1 => January,
2 => February,
3 => March,
4 => April,
5 => May,
6 => June,
7 => July,
8 => August,
9 => September,
10 => October,
11 => November,
12 => December,
_ => throw new ArgumentException("Invalid month value.", nameof(value)),
};
}
public override bool Equals(object obj)
{
return obj is Month other && Value == other.Value;
}
public override int GetHashCode()
{
return Value;
}
public override string ToString()
{
return Value switch
{
1 => "January",
2 => "February",
3 => "March",
4 => "April",
5 => "May",
6 => "June",
7 => "July",
8 => "August",
9 => "September",
10 => "October",
11 => "November",
12 => "December",
_ => throw new InvalidOperationException("Invalid month value."),
};
}
}
まぁ、いいかな。
FromValueとToStringどちらにもswitchがあるのが気に入らないけど、しょうがないか。
感想
うまく使えば時短になるかな、と思いました。
通常会話でChatGPTを使う場合、同じ質問に対しても毎回回答が違うのと同じように、コーディングに関しても同じにはなってくれないことを認識しておくことが大事なようです。追加/修正部分だけを出力させるようにするとか、毎回質問に対象のコードを含める、などの工夫が必要かな、と思います。
これからもいろいろ試してみて、活用しようと思います。