はじめに
こんにちは。株式会社divxの後藤です。
皆さんは開発において、コードの可読性をどの程度意識していますか?
アプリが動けば問題ないと考え、コードの可読性を無視した適当なコーディングをしている可能性はありませんか?
この記事では、コードの可読性の重要性と、AIを利用して効率的に可読性を向上させる方法を自身の体験を交えて解説いたします。
可読性の高いコードとは
一般論的な可読性の高いコードの概要
読んで字のごとく、読みやすさ、わかりやすさを指しており、プログラムのソースコードを人間が読んだときの、その目的や処理の流れの理解しやすさを指しています。
ただし、わかりやすさは主観的な指標であり、可読性の高いコードが何かを明確に理解するのは難しいことがあります。
そのため、この記事では企業によって公開されていて、一般的に使われているコーディング規約(PEP8やCode Conventions for the Java Programming Languageなど)で定義されているいくつかの内容から抜粋し、以下の項目がきちんと設定されているものが可読性の高いコードとしたい定義したいと思います。
- インデント、改行、空行
- 命名規則
- 1行の桁数(80文字以内)
- コメント
可読性の重要性
コードの可読性はコード内容の理解速度の向上、工数短縮により、実装の時間を長く取れることでバグの発生率などの確認に時間を使うことで精度の高いコードの作成につながります。
チームでの開発の際や、他の方の作業の引き継ぎを行う際などでコードを作成する場合、自身で作成したものでないため、全体のコードの把握は必須になります。その際、可読性の低いコードであった場合、コードリーディングに時間がかかり、実装時間が減少し、精度の高いコードを提出できなくなる可能性や、期間内での完成が難しくなる可能性が高くなります。
実際の体験として、他の開発者が作成したページを修正する際、どのコードがどの機能を担っているのかを確認する必要がありましたが、result1、result2などように何の結果を意味しているのかわかりにくいコードがあったり、同じ意味の変数なのに、ファイルごとに名称が異なったりするなどして、修正内容と関係ない部分のコードリーディングまで行うことになり、コーディングに時間がかかってしまった場合があります。また、可読性の部分も修正することになり、修正に通常の1.5倍も時間がかかりました。
また、逆に長いコードであったのにコメントなどでどの機能の記載を行っているかを説明していたり、わかりやすい名称をつけられていたため、すぐに理解でき、実装に着手ができたこともありました。
しかし、プログラミング初心者にとっては、全てのコードが同じように見え、名称程度で読みやすさが変わるのか?と思う方もいるかもしれません。なのでさらに具体的な例を用いて説明します。
以下のようなコードがあります。名称から辛うじて計算を行うことはわかりますが、実際にどう使われるのかがわかりません。
public class BadNamingExample {
public void doSomething() {
int result1 = calculateA();
int result2 = calculateB();
int result3 = calculateC(result1, result2);
display(result3);
}
このコードを以下のように改善すると、どうでしょうか?
public class GoodNamingExample {
public void doSomething() {
int numberOfPeople = calculateNumberOfPeople();
int amount = calculateAmount();
int revenue = calculateRevenue(numberOfPeople, amount);
display(revenue);
}
numberOfPeopleは人数に関する計算、amountは金額に関する計算、revenueは収益に関する計算であることが予想ができます。そのため、もし、人数に関する部分で問題が起きていたらcalculateNumberOfPeopleの関数を修正すればいいとすぐに気づくことができ、実装に着手できます。
このように、可読性の高いコードは、コードリーディングの工数を大幅に削減し、作業効率を向上させます。それにより、実装に時間を使うことができるようになります。
AIを用いて可読性の向上を行えるのか
可読性はプログラムを行う上で重要だということをこれまで説明しました。
しかし、プログラミング初心者の方などはそこまで考慮することは難しいと思われます。そこでAIを使うことで可読性向上を行います。
ここからは、実際にAIによる可読性の向上がどれだけできるのかを実例を交えて説明していきます。
まず最初に以下の条件によって"Hello World"を出力するコード(コード1)をAIに読み込ませ、「可読性を向上させて」と命令してみます。
public class a {
public static void main(String[] args) {
boolean Abc = true;
if (Abc) {
System.out.println("Hello World");
}
}
}
結果としては以下のコードができました。
public class HelloWorld {
public static void main(String[] args) {
boolean isGreetingEnabled = true;
if (isGreetingEnabled) {
System.out.println("Hello World");
}
}
}
変更点を確認すると、
- 空行、インデントの追加
- 変数名やクラス名の変更(命名規則はキャメルケースで統一)
- コメントを追加
のように変更しており、最初に挙げた、可読性の高いコードと言われる要件を満たしたコードになっています。この結果から、可読性が向上していることが確認できました。
次に、長めのコードの修正を行います。以下の条件によって"Hello World"だけでなく、さまざまな文字列を出力するコード(コード2)をAIに読み込ませ、可読性を向上させてと命令してみました。
public class Helloworld {
public static void main(String[] args) {
String r = request.getResultValue();
String vaLue = "exampleValue";
if (r.equals(vaLue)) {
System.out.println("result is equal to value");
System.out.println("Hello World");
} else {
System.out.println("result is not equal to value");
if (r.length() < 10) {
System.out.println("result has less than 10 characters");
} else {
System.out.println("result has 10 or more characters");
}
if (vaLue.equals("value")) {
System.out.println("However, value is still value");
System.out.println("Hello World");
} else {
System.out.println("But value is not value");
}
}
if (r.startsWith("some")) {
System.out.println("result starts with 'some'");
}
if (r.length() > 10) {
System.out.println("result is long");
} else if (r.length() > 5) {
System.out.println("result is medium");
} else {
System.out.println("result is short");
}
}
}
結果は以下のようになりました。
public class HelloWorld {
public static void main(String[] args) {
String result = request.getResultValue();
String expectedValue = "exampleValue";
checkResultEquality(result, expectedValue);
evaluateResultLength(result);
checkResultStartsWith(result, "some");
}
private static void checkResultEquality(String result, String expectedValue) {
if (result.equals(expectedValue)) {
System.out.println("Result is equal to the expected value.");
System.out.println("Hello World");
} else {
System.out.println("Result is not equal to the expected value.");
evaluateValueEquality(expectedValue);
}
}
private static void evaluateValueEquality(String expectedValue) {
if (expectedValue.equals("value")) {
System.out.println("However, expected value is still 'value'.");
System.out.println("Hello World");
} else {
System.out.println("But the expected value is not 'value'.");
}
}
private static void evaluateResultLength(String result) {
if (result.length() < 10) {
System.out.println("Result has less than 10 characters.");
} else {
System.out.println("Result has 10 or more characters.");
}
if (result.length() > 10) {
System.out.println("Result is long.");
} else if (result.length() > 5) {
System.out.println("Result is medium.");
} else {
System.out.println("Result is short.");
}
}
private static void checkResultStartsWith(String result, String prefix) {
if (result.startsWith(prefix)) {
System.out.println("Result starts with '" + prefix + "'.");
}
}
}
可読性が上昇していますが、一部のコードが別の関数に置き換えられています。
長いコードを細かく分けることも、コードの可読性を向上させる要素の一つですが、今回の記事の可読性の高いコードの定義には当てはまりません。また、今回の例では以前と変わらない挙動をしますが、複雑なコードでは前のコードとは実際の挙動が異なってしまう場合があります。
以上の2つの結果から、長いコードだと不安な部分は残りますが、短いものだとAIを用いるとすぐに可読性の向上ができることがわかります。
AIを使用して可読性を向上させるためのコツ
前項目で、AIを用いることで可読性の向上ができること、長いコードであると可読性の向上に加えてコードに変更が入り、動作が変わる可能性があることを説明しました。
本項目では、長いコードでも動作が変わることなく可読性の向上ができるようにするために個人的に使用しているコツを紹介していきます。
具体的な命令にする
先ほどのコード2の修正例ではあくまで、可読性を向上させてという簡易的な命令でした。しかし、どのように修正してほしいのかを具体的に書くことで、特定の部分のみの修正を行うことができます。
以下の部分に関して修正を行い、可読性を向上して
- インデント、改行、空行
- 命名規則
- 1行の桁数(80文字以内)
- コメント
という具体的な命令にして、再度コード2を修正しました。以下は、修正後のコードの結果です。
public class HelloWorld {
public static void main(String[] args) {
String result = request.getResultValue();
String expectedValue = "exampleValue";
if (result.equals(expectedValue)) {
System.out.println("Result is equal to expected value.");
System.out.println("Hello, World!");
} else {
System.out.println("Result is not equal to expected value.");
if (result.length() < 10) {
System.out.println("Result has less than 10 characters.");
} else {
System.out.println("Result has 10 or more characters.");
}
if (expectedValue.equals("value")) {
System.out.println("However, expectedValue is still 'value'.");
System.out.println("Hello, World!");
} else {
System.out.println("But expectedValue is not 'value'.");
}
}
if (result.startsWith("some")) {
System.out.println("Result starts with 'some'.");
}
if (result.length() > 10) {
System.out.println("Result is long.");
} else if (result.length() > 5) {
System.out.println("Result is medium.");
} else {
System.out.println("Result is short.");
}
}
}
関数などへの置き換えがなく、空行やコメントの追加や変数の名称変更といった該当の部分のみ修正されていて、可読性の上昇が確認できました。
このように、どこを変更したいか、変更したくないかが明確なものは命令に記載し、具体的な命令にするとより良い結果の回答に繋がります。
同じコードで数回実行を行う
基本的に可読性のみに重点を置いた場合、似たようなコードが返されることが多いですが、最初に実行した時とは違う部分の問題を修正しているコードが返され、同じ質問でも変化がある場合があります。
例としては以下の通りです。以下はコード2を可読性を向上させてのみで命令した場合の別パターンの返答になります。
public class HelloWorld {
public static void main(String[] args) {
String r = request.getResultValue();
String value = "exampleValue";
if (value.equals(r)) {
System.out.println("result is equal to value");
System.out.println("Hello World");
} else {
System.out.println("result is not equal to value");
if (r.length() < 10) {
System.out.println("result has less than 10 characters");
} else {
System.out.println("result has 10 or more characters");
}
if ("value".equals(value)) {
System.out.println("However, value is still value");
System.out.println("Hello World");
} else {
System.out.println("But value is not value");
}
}
if (r != null && r.startsWith("some")) {
System.out.println("result starts with 'some'");
}
if (r != null) {
if (r.length() > 10) {
System.out.println("result is long");
} else if (r.length() > 5) {
System.out.println("result is medium");
} else {
System.out.println("result is short");
}
} else {
System.out.println("result is null");
}
}
}
vaLueの方の変数名は修正されていますが、String r = request.getResultValue();の部分の名称の方は修正されておらず、分かりにくいままとなっています。
このように同じコードでも異なる結果が出るため、複数回繰り返すことで、全ての可読性の問題を見つけることができ、理解しやすいコードへの修正が行えます。
どこに問題があるのか質問形式にして、修正は手動で行う
長いコードになると、AIに任せた場合、名称のみの変更の場合でもどこが変わったのかというのがわかりにくくなる時があります。そして、追加で実装を行う際にその変更に気づかず、齟齬が発生し、コードのチェックからやり直すことになる可能性が存在します。
そのため、長すぎるコードはAIに任せるよりも、問題点を認識し、自分で修正する方法がより早く実装を行える時があります。
実際にコード1とコード2でこのコードは可読性に問題がないか、問題がある場合は指摘をしてほしいと命令して結果を見てみます。
このコードにはいくつかの可読性の改善点があります。以下に指摘を挙げます。
クラス名の命名規則: Javaのクラス名は一般的に大文字から始めるべきです。a というクラス名は意味が薄く、またJavaの命名規則に従っていないため、より意味のある名前に変更することをお勧めします(例えば、HelloWorld など)。
変数名の命名規則: Abc という変数名も可読性に欠けます。変数名はその役割を明示するものであるべきです。ここでは isActive や isGreetingEnabled など、より説明的な名前にすることが推奨されます。
インデントや空白の使用: コードの可読性を高めるために、インデントや空白の使い方も重要です。このコードは簡潔ですが、規模が大きくなった際には適切なインデントを維持することが大切です。
コメント: 異常な場合やロジックの意図を説明するために必要に応じてコメントを追加すると、将来のメンテナンスが容易になります。
変数名の一貫性:
vaLue という変数名は、value とすべきです。変数名を一貫して明確にすることで理解しやすくなります。大文字と小文字の使い分けは一般的に避けるべきです。
意味の不明瞭さ:
r という変数名は、何を表しているのかが非常にあいまいです。変数名は、変数の役割や内容がわかるようにするべきです。たとえば、result などの名前にすることで、何を保持しているのかが明確になります。
コメントの追加:
コードの意図や処理内容を説明するためのコメントを追加すると、他の人がコードを読みやすくなります。特に、複雑なロジックや条件分岐についてコメントがあると良いでしょう。
条件文の整理:
if-else ステートメントのネストが深くなっている部分があります。特に、else の中で再度 if を使う場合、条件が本当に別のケースを表しているのかを再考することが重要です。一部の条件は整理してフラットにすることができるかもしれません。
メソッドの分割:
main メソッドが長くなっているように感じます。機能ごとにメソッドを分割することで、再利用性が高まり、テストも容易になります。また、各メソッドが何をするのかが明確になり、可読性が向上します。
問題点を指摘されました。このように、質問形式にすることで、コードそのものでなく、問題点を記述してくれます。
また、この部分でも、具体的にすることで該当の部分のみの問題点を洗い出せます。
コード2についてを以下のようにして命令します。
このコードは
- インデント、改行、空行
- 命名規則
- 1行の桁数(80文字以内)
- コメント
の部分の可読性に問題がないか、問題がある場合は指摘をしてほしい。
インデント、改行、空行
インデントは基本的に適切ですが、一部の条件文の間に空行がないため、視覚的に区切りが不十分です。条件文のブロックの間に空行を追加すると、コードが読みやすくなります。
メソッドやクラスの定義とメインメソッドとの間に一行の空行があっても良いです。
命名規則
クラス名 Helloworld は、Javaの命名規則に従うと、HelloWorld とすべきです(パスカルケースを使う)。
変数名 vaLue は、後半の大文字が一貫性のない表記(小文字と混在)となっています。value に修正するべきです。
変数 r は短すぎて、その目的が不明です。より明示的な名前(例: result)にすることを検討してください。
1行の桁数(80文字以内)
現在のコードは80文字を超える行はありませんが、今後のために、読みやすさを保つために1行を80文字以内に抑えることをお勧めします。
コメント
コメントが全くありません。コードの意図やロジックを説明するために、適切な場所にコメントを追加すると良いでしょう。特に条件分岐が含まれる部分には、何を意図しているのかを書くとより理解しやすくなります。
上記が返ってきた結果となります。該当の部分のみの指摘がされました。
このようにして、AIによって作成されたコードが不安な人や、長すぎるコードを扱う場合は、問題点の洗い出しをAIによって行い、手動での修正を行うのをお勧めします。
結論
まず、AIを用いた可読性の高いコードは可能であり、実用可能であると言えます。
しかし、「可読性の向上を行って」程度の簡単な命令では長いコードの場合、AIによって勝手にいくつかの関数に分けられてしまうなど、既存のコードから形式が大幅に変更される場合があります。そして、形式だけでなく、実際の挙動も変わってしまう場合があります。
その際は、しっかりと動作チェックを行い、変わったコードに問題がないかを確認し、問題があれば、その変更を破棄し、具体的な可読性の向上を行ってほしい部分を記述した命令にすることで自身の望む変更を行うことが大切になります。
可読性というものはプログラミングをやる上で必ず念頭に置くべき部分です。可読性に心配がある場合はAIを使用をしてみてコードの精査を行うのも良いと思います。方法も、具体的な内容が浮かばなければ、「可読性の向上を行って」程度の短い命令でもある程度の解消が行えます。ぜひ参考にしてください。
参考文献
https://www.oracle.com/java/technologies/javase/codeconventions-contents.html (コーディング規約:Code Conventions for the Java Programming Language)
https://pep8-ja.readthedocs.io/ja/latest/ (コーディング規約:PEP8)
お悩みご相談ください