AI時代の開発者に求められるコードレビュー能力と変数の重要性
これまでの章で、あなたはAIに指示を出し、スプレッドシートの読み書きや一括処理を行うコードを生成させてきました。AIは非常に優秀な部下ですが、時に意図とは異なるコードを書いたり、修正が必要なエラーを含んだりすることがあります。この時、AIが生成したコードをただ眺めるだけでなく、その意味を理解し、的確な修正指示を出せるかどうかが、「ツールを使わされている人」と「ツールを使いこなす開発者」の分かれ道となります。そのコード理解の最初の一歩にして、最も重要な要素が「変数」です。
変数は、プログラミングにおいてデータを一時的に保存しておくための「箱」や「ラベル」のようなものです。AIが生成するコードを見ると、const、let、そして稀にvarという単語が頻繁に登場することに気づくでしょう。これらはすべて変数を宣言するためのキーワードですが、それぞれ明確に異なる役割とルールを持っています。AIは文脈に合わせてこれらを使い分けますが、AIの判断が常にあなたの意図した業務ロジックと合致しているとは限りません。例えば、後で値を変更したいのに変更不可能な設定で書いてしまったり、逆に固定すべき値を変更可能な状態で放置してしまったりすることがあります。本章では、これらの変数の宣言方法の違いを深く理解し、AIに対して「ここは値を書き換えるからletを使って」や「ここは定数だからconstで固定して」といった、エンジニアリング視点での具体的な指示が出せるようになることを目指します。これは、より堅牢でバグの少ないシステムを構築するための必須スキルです。
データの仮置き場としての変数の概念とExcelでの類似点
プログラミングにおける「変数」という概念は、数学の方程式に出てくる「x」や「y」とは少しニュアンスが異なります。GASを含む多くのプログラミング言語において、変数は「コンピュータのメモリ上に確保された、データを出し入れするための保管場所」を指します。スプレッドシートの操作においては、getValue()で取得したセルの値や、getValues()で取得した巨大な二次元配列データを、処理が終わるまで一時的に預けておくロッカーのような役割を果たします。もし変数がなければ、取得したデータを次の行で使うことができず、処理のたびにスプレッドシートにアクセスし直さなければならなくなり、処理速度が著しく低下してしまいます。
Excelを使いこなしているあなたであれば、「名前の定義」という機能をご存知かもしれません。セル範囲「A1:A10」に「売上リスト」という名前を付けておけば、関数の中で「=SUM(売上リスト)」と記述できるあの機能です。GASにおける変数もこれに非常に近い感覚です。「シートの3行目5列目の値」という複雑な所在地の代わりに、salesAmount(売上金額)という分かりやすい名前のラベルを貼った箱を用意し、そこに値を入れておくイメージです。これにより、コードの後半ではsalesAmountと記述するだけで、中身のデータを利用できるようになります。
AIにコードを書かせると、AIは文脈から推測して、例えばconst sheetやlet lastRowのように、人間が読んでも意味がわかる変数名を自動的に付けてくれます。しかし、その変数が「その後、中身が入れ替わる可能性があるのか(可変)」、それとも「一度入れたら二度と変わらないのか(不変)」によって、使用すべき宣言キーワード(constやlet)が変わります。この区別を理解することは、コードの安全性と可読性を高める上で非常に重要です。次節からは、それぞれのキーワードの特性について詳しく見ていきましょう。
現代のスタンダードであるconstとletの導入背景
かつて、JavaScript(GASのベース言語)には変数を宣言する方法としてvarしか存在しませんでした。しかし、varにはいくつかの仕様上の緩さがあり、大規模な開発においては予期せぬバグの温床となることがありました。そこで、より厳密で安全なコーディングを可能にするために、新しい規格(ES6/ECMAScript 2015)で導入されたのがconstとletです。現在のGASはV8ランタイムというエンジンで動作しており、この新しい構文を完全にサポートしています。
現代の開発現場、そしてAIが生成するコードにおいては、constとletを使用することが絶対的な標準となっています。AIに「GASでコードを書いて」と依頼すると、特段の指定がない限り、AIはこれらを使ってコードを生成します。もし、ネット上の古い記事や古い参考書を見てvarを使っているコードを見つけたとしても、それをそのままコピペするのは避けるべきです。なぜなら、現代の開発マナーにおいてvarは「非推奨」または「レガシーな書き方」と見なされることが多いからです。
開発者として意識すべきは、「可能な限り制限を厳しくする」という原則です。制限が厳しいということは、裏を返せば「想定外の使い方ができないよう守られている」ということであり、エラーの原因を特定しやすくなります。constとletはこの原則に基づいて設計されています。これらを適切に使い分けることで、コードの意図(この値は変わるものなのか、変わらないものなのか)を明確に表現でき、自分以外の人がコードを読んだ時や、数ヶ月後の自分がコードを見返した時の理解を助けることになります。AIもこの原則に従ってコードを生成しようとしますが、業務ロジックの細部までは理解していないため、最終的な判断は人間に委ねられます。
不変の誓い「const」:再代入禁止による安全性の確保
constは「Constant(定数)」の略であり、一度値を代入したら、その後二度と中身を変更(再代入)できない変数を宣言するために使います。イメージとしては、「中身を入れた瞬間に溶接されて開かなくなる透明なガラスケース」や「一度彫り込んだら書き直せない石板」を想像してください。例えば、消費税率のような固定値や、APIキー、あるいはそのスクリプト内で対象とするシートオブジェクトなど、処理の途中で変わってはいけない、あるいは変わるはずがないものを格納するのに適しています。
AIが生成するコードを見ると、変数の宣言の大部分がこのconstで書かれていることに気づくでしょう。例えば、const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();といった記述です。これは、「この処理の間、対象となるシート(sheet)は別のシートに入れ替わったりしない」という宣言でもあります。もし、コードの途中で誤ってsheet = "別の値"のように上書きしようとすると、GASは「Assignment to constant variable(定数への代入)」というエラーを出して停止します。
初心者は「後で書き換えられないと不便ではないか?」と感じるかもしれませんが、実はこの「書き換えられない」という制約こそが最大のメリットです。長いプログラムを書いていると、意図せず変数の値を上書きしてしまうミスが起こり得ます。constを使っていれば、そのようなミスを即座にエラーとして検知できるため、バグの混入を未然に防ぐことができます。開発者のマイルールとして、「まずは基本的にすべてconstで宣言する」と考え、どうしても値を変更する必要がある場合のみ、次に紹介するletに変更するというアプローチを取るのが、最も安全で推奨される開発スタイルです。
変化を受け入れる「let」:再代入可能な変数の役割
constに対して、letは値を何度でも書き換える(再代入する)ことができる変数を宣言します。イメージとしては、「ホワイトボード」や「付箋」のように、書いたり消したり、貼り替えたりできる柔軟な保管場所です。例えば、合計値を計算するために数値を足し合わせていく変数や、ループ処理で「1行目、2行目…」とカウントアップしていくカウンター変数などがこれに該当します。
AIが生成するコードの中でletが登場するのは、主にfor文などの繰り返し処理や、条件によって中身が変わる変数を扱う場合です。例えば、for (let i = 0; i < 10; i++)という記述では、変数iはループするたびに0, 1, 2…と値が変化していくため、必ずletが使われます。もしここをconstにしてしまうと、1回目のループが終わってiを1に増やそうとした瞬間にエラーになってしまいます。
また、let message;のように、最初は中身を空にしておき、その後のif文などの条件分岐によって、message = "合格"あるいはmessage = "不合格"のように値を決定する場合にもletが使われます。開発者としてコードレビューをする際は、letで宣言されている変数を見つけたら、「あ、この変数はこの後の処理で値が変化するんだな」と意識して読むことができます。逆に言えば、値が一度も変化していないのにletで宣言されている場合は、constに書き換えるべきだという判断ができます。AIは稀にこの判断を甘く行うことがあるため、人間が修正指示を出すポイントの一つとなります。
過去の遺物「var」とその危険性:なぜ使ってはいけないのか
varは、constやletが登場する前から使われていた古い変数宣言の方法です。現在でも動作はしますが、新規の開発で使用することは推奨されません。その最大の理由は、「スコープ(変数の有効範囲)」が曖昧で、予期せぬバグを引き起こしやすいという性質にあります。
varで宣言された変数は、非常に広い範囲から参照できてしまったり、同じ名前で何度でも再宣言できてしまったりするという、緩いルールを持っています。これは小規模なコードでは便利に感じることもありますが、コードが長くなると「どこで変数の値が変わったのか追跡できない」「意図せず同じ名前の変数を上書きしてしまった」というトラブルの原因になります。例えるなら、varは「壁を突き抜けて声が届いてしまうメガホン」のようなものです。隣の部屋(別の処理ブロック)で使っている変数のつもりでも、壁を越えてこちらの部屋の変数に影響を与えてしまうリスクがあります。
AIにコード生成を依頼する際、プロンプトで明示的に指示しない限り、最近のAIモデルはvarを使うことは少なくなりました。しかし、Web上の古い技術記事やサンプルコードを参考にしてプロンプトを作成した場合、AIがそれに引きずられてvarを出力することがあります。開発者としては、AIが出力したコードにvarが含まれていたら、「これは古い書き方だな」と認識し、constかletに書き換えるようAIに修正指示を出すか、自手で修正するリテラシーを持つ必要があります。
スコープの概念:変数が生きられる「部屋」のルール
変数には「スコープ」という、その変数が有効な範囲(寿命)が存在します。constとletは「ブロックスコープ」というルールに従います。ブロックとは、波括弧{ }で囲まれた範囲のことです。関数function() { ... }の中や、if文if() { ... }、for文for() { ... }の中が一つのブロックとなります。
これを「部屋」に例えてみましょう。constやletで宣言された変数は、その変数が生まれた「部屋(ブロック)」の中でしか生きられません。部屋の外からは、その変数を見ることも触ることもできないのです。これは「防音室」のようなもので、部屋の中で起きたこと(変数の値の変化など)は部屋の外には漏れ出さず、逆に部屋の外にある同じ名前の変数とも干渉しません。
例えば、if (condition) { const result = "OK"; }というコードがあった場合、変数resultはこの波括弧の中でしか使えません。波括弧を抜けた後にconsole.log(result);としても、「そんな変数は存在しない(not defined)」とエラーになります。これに対し、かつてのvarは、この「部屋」の壁をすり抜けて、関数の外側まで影響を及ぼすことがありました。ブロックスコープ(部屋のルール)を厳密に守るconstとletを使うことで、変数の影響範囲を限定し、コードの管理を容易にすることができます。AIが生成したコードで「変数が定義されていません」というエラーが出た場合、多くはこのスコープ(部屋)の外から変数を使おうとしていることが原因です。
AIコードにおける「Assignment to constant variable」エラーの対処法
AIを使ってGAS開発を行っていると、頻繁に遭遇するエラーの一つに「TypeError: Assignment to constant variable.」があります。これは直訳すると「定数変数への代入」、つまり「const(定数)で宣言したはずの箱に、別の値を無理やりねじ込もうとしましたね?」というGASからの警告です。
AIは文脈を理解しようと努めますが、完璧ではありません。例えば、最初は値を固定するつもりでAIがconst count = 0;と書き、その数行後に処理の流れでcount = count + 1;とカウントアップするコードを書いてしまうことがあります。これは矛盾しており、エラーになります。このエラーが出た場合、開発者が取るべき行動は二つに一つです。
一つ目は、「この変数は値が変わるべきものだ」と判断し、宣言部分をconstからletに書き換えること。二つ目は、「いや、この変数は変わってはいけないはずだ」と判断し、値を上書きしようとしている処理の方を修正することです。初心者はエラーが出ると焦ってしまいがちですが、このエラーは「安全装置が正しく作動した」証拠です。AIに対して「const変数への再代入エラーが出ているので、適切にletに修正して」と指示すれば、AIはすぐに修正版のコードを提示してくれます。
プロンプトエンジニアリング:AIに変数を適切に扱わせる指示
AIに対して、より高品質で保守しやすいコードを書かせるためには、プロンプトの中で変数の扱いについて指示を含めることが有効です。特に、チームで開発する場合や、将来的にコードを拡張する予定がある場合は、変数の命名規則や宣言方法を統一しておくことが望ましいです。
例えば、「変数は基本的にconstを使用し、再代入が必要な場合のみletを使用してください。varは使用しないでください」という指示をプロンプトに追加します。また、「変数名は具体的で意味がわかる英語名(キャメルケース)にしてください(例: targetSheet, userEmail)」と指示することで、aやbといった意味不明な変数名の乱用を防ぐことができます。
さらに、複雑な計算や処理を行うコードを生成させる場合は、「計算の途中経過を格納する変数を適宜用意し、可読性を高めてください」と指示することも有効です。AIは時として、変数を節約しようとして一行に複雑な処理を詰め込みすぎることがあります。変数を適切に使って処理をステップごとに分解させることで、人間が読んでも理解しやすく、デバッグもしやすいコードになります。
開発者の視点:可読性と保守性を高めるための変数戦略
本章の最後に、改めて「開発者」としての視点を確認します。コードは「書く」時間よりも「読む」時間の方が圧倒的に長いと言われています。エラーが起きた時、機能を追加したい時、半年後の自分や同僚がそのコードを読みます。その時、適切に名付けられ、適切にconst/letが使い分けられた変数は、コードの意図を語る道しるべとなります。
const taxRate = 0.1;と書いてあれば、「ああ、これは消費税率で、固定値なんだな」と一瞬で理解できます。しかし、単に0.1という数字がコードの中に埋め込まれていたら、それが何を意味するのか解読するのに時間がかかります。このように、意味のある名前を付けた定数(const)を活用することは、「マジックナンバー(意味不明な数値)」を排除し、コードの可読性を劇的に向上させます。
AIは動くコードを書いてくれますが、「読みやすいコード」や「未来の変更に強いコード」を書くためには、人間の開発者による指示とレビューが不可欠です。「動けばいい」という市民開発者の段階を卒業し、変数の意味とスコープを理解して、AIと共に「美しく堅牢なコード」を構築する。それが、この講座が目指すプロフェッショナルな開発者の姿です。次章では、この変数の知識を前提に、プログラムの強力な武器である「条件分岐」について学んでいきます。
