AIに相談しながら正規表現を考えると捗るという話

この記事は、フラー株式会社 Advent Calendar 2023の10日目の記事です。 9日目は、@Daiji256さんのAndroid で日本語でも色々なウェイトのフォントを使いたいでした。

はじめに

  • 本当は、AIチャット + 正規表現で別のネタを書くつもりでしたが、ある理由で没となってしまいました
  • そこらへんの供養を本記事の最後に書いておくので、気になる方は見てみてください

本題

2023年はGPTを始めとした生成AIの年でしたね。

会話用のChatGPTやら、イラストを生成するStable Diffusionやら、用途に合わせたAIがいろいろ出てきましたが、個人的に一番活用したのはGitHub Copilotでした。

github.com

というのも、私が勤めるフラー株式会社では、自社のorganizationでCopilotを契約しており、エンジニアの開発業務にて利用できるようにしています。

Copilotは、AIがリアルタイムにソースコードの提案をしてくれるサービスです。 AIはGitHub上のソースコードを参考にしているだけでなく、プロジェクト内のコードを参照し、既存の実装に合わせたコードを提案してくれます。 このコード提案がとにかく便利で、もうCopilotなしの開発には戻れないくらいです。 もし、今後転職するなら、業務でのCopilotや類似サービスの利用可であることが必須になるレベルです。

Copilotは、Copilot Chatという対話型のインターフェースも提供しています。 が、私はあまりCopilot Chatを利用していません。 理由としては、ChatGPTを触ってみた時に正しくないことをさも正しいかのように回答してくるので、わからないことを質問した時にそれが正しいのかを自身が正確に評価できないためです。

私のAIチャットに対するスタンスはそういう感じなんですが、自信をもってCopilot Chatに相談するトピックがあります。

それが、正規表現です。 理由として、以下が挙げられます。

  • 既にフォーマットが確立されており、AIが誤った情報に振り回されることがないため、回答の信頼度が高い(ように思える)
  • AIが出力した正規表現が望んだ文字列にマッチするかを確かめるためのツールが存在する

実際に一緒に考えてみる

ということで、私がCopilot Chatに正規表現を考えてもらう流れを実演したいと思います。

ですが、ここで問題があります。 Copilot Chatはベータ版であるため、プレリリース版ソフトウェアに該当します。ですので、プレリリース版の秘密保持に関して、以下の制限が適用されます。

GitHub Copilot プレリリース条件 - GitHub Docs

次のことは行わないでください。(i) 本条件および秘密保持契約の対象ではない者に本ソフトウェアを開示したり、またはそのような者とソフトウェアを共有すること。(ii) 個人のSNSページを含むオンライン プラットフォーム上で、あるいはそのようなプラットフォームを経由して、本プレリリース版ソフトウェアの写真や動画を投稿したり、または他者にそのような投稿を許可すること。(iii) GitHub による事前の明示的な許可なしに、オンライン プラットフォーム上で、またはオンライン プラットフォームを介して、本ソフトウェアの何らかの要素について説明またはディスカッションすること。

上記の(ii)によって、Copilot Chatとのやりとりを本ブログに載せることはできないので、ChatGPTに代役を担当してもらいます。

例1: メールアドレスにマッチする正規表現

まずは、文章中に出現するメールアドレスにマッチする正規表現を考えてもらいましょう。

率直に尋ねてみる

出力した正規表現がどのような構造をしているのかの説明までしてくれました。親切ですね。

末尾のトップレベルドメインが少なくとも2文字以上でないといけないというのは盲点でした。

正規表現チェックツールで動作確認する

Web上の正規表現チェックツールで、望んだ結果が得られるかを確認していきます。 私は以下のツールを使っています。

正規表現チェッカー | WWWクリエイターズ

文字列中のメールアドレスにマッチすることが確認できます。

メールアドレスくらいなら、フォーマットも一定なので回答の精度が高く、そのまま使用できそうですね。

次は、もう少し複雑そうな正規表現を考えてもらいましょう。

例2: 日本円表記にマッチする正規表現

文字列中の「○○円」という日本円表記にマッチする正規表現を考えてもらいましょう。 〇〇の中の条件は、以下とします。

  • 含まれる文字は0~9とカンマ(,)のみ
  • カンマは、nを1以上の正の整数とし、3n桁目と3n+1桁目の間にのみ含まれる
  • 先頭は0以外の数字とする
率直に尋ねてみる

|以前のパターンが桁間のカンマを考慮したパターンですね。 これだといずれの桁の間にカンマを入れてもマッチするので、もっと正確にしたいですね。

制約を追加して考えてもらう

カンマは3n桁目と3n+1桁目の間に入れることを伝えます。 |以前のパターン\d{1,2}(,\d{3})*円がかなりいいですね。 まず1~2桁の数字が並び、それ以降はカンマを先頭にした数字三桁のパターンが0回以上繰り替えされるというものですね。 先頭の\d{1,2}の部分は3桁でもいいので、正確には\d{1,3}ですね。ここら辺は手動で修正すればいいと思います。

先頭の桁には0は入れないようにしてもらいましょう。 [1-9]を先頭にすれば、0以外の数値が先頭ということになりますね。手動で直そうと思っていた「カンマ前は1~3桁」というのも併せて治ってました。

ということで、日本円表記にマッチする正規表現は以下が使えそうです。

[1-9]\d{0,2}(,\d{3})*円
正規表現チェックツールで動作確認する

例1と同じようにツールを使って、目的のケースにマッチするかを確認します。 よさそう

終わりに

いかがでしたか?

正規表現を考えてもらうというおススメのAIチャット活用方法のご紹介でした。

11日目は、@furusaxさんで、「サーバーサイドのオンボーディング課題と俺たちの果てなき戦いは続く」です。

没ネタ供養

本当は、AIの力を借りるとどれだけのバフが得られるのかを計測するために、以下の成否表現ゲームをAIチャットの力を借りてプレイして、人力のみの時からどれだけスコアアップするかを計測する、というのをやりたかったです。

www.regex-hunting.com

が、ゲームの回答までの制限時間が短く、AIに聞いてその回答をゲームに入力する前に制限時間が過ぎてしまい、逆にスコアが落ちてしまうという残念な結果となってしまいました...

人力で挑戦し、ステージクリア
AIチャットの力を借りて、ステージクリアできず

我々が真に必要とするのは、余裕、なのかもしれませんね...

React RouterでReact SPAのページ遷移時のスクロール位置を制御する

はじめに

この記事はフラー株式会社 Advent Calendar 202220日目の記事です。 qiita.com

19日目は @canacelさんで「canacel.net を開設しました」でした。

ReactでSPAを構築する際には、React Routerを使用します。 React RouterはURLに合わせてコンポーネントの出し分けを可能にするライブラリです。

import { createBrowserRouter} from "react-router-dom";

const router = createBrowserRouter([
  { path: "/", element: <Home /> },
  { path: "next", element: <Next /> },
]);

上記のコードでは、ルートURL("/")ではHomeコンポーネントが、/nextではNextコンポーネントレンダリングされます。 それぞれのコンポーネントが各ページの内容を描画するようにすれば、ページ遷移が実現できます。 今回はReact Routerを用いたページ遷移におけるスクロール位置の制御について検証します。

検証環境

React: v.18.2.0

React Router: v.6.5.0

デフォルトでは、前画面のスクロール位置が継承される

まずは以下のコードでの動作を確認します。

import { css } from "@emotion/css";
import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, Link, RouterProvider } from "react-router-dom";

const router = createBrowserRouter([
  { path: "/", element: <Home /> },
  { path: "next", element: <Next /> },
]);

function Home() {
  return (
    <div
      className={css`
        height: 200vh; // スクロールが発生するようにウィンドウ縦幅の2倍の高さに設定
        width: 100vw;
        padding-bottom: 200px;
        background: linear-gradient(
          blue,
          pink
        ); // スクロールがわかりやすいように背景をグラデーションにする
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        overflow: auto;
      `}
    >
      <h1>Home</h1>
      <Link to={"/next"}>Click to Next page.</Link>
    </div>
  );
}

function Next() {
  return (
    <div
      className={css`
        height: 200vh;
        width: 100vw;
        padding-bottom: 200px;
        background: linear-gradient(blue, green);
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        overflow: auto;
      `}
    >
      <h1>Next</h1>
      <Link to={"/"}>Click to Home page.</Link>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

実装内容を簡潔に図示すると下記のようになります。 縦長のページの下部に見出しと別ページへのリンクがあり、二つのページを行き来するアプリケーションです。 React Routerでのスクロールに関する制御は、何も行っていません。 以下のような挙動になります。 HomeからNextへ移る際、いきなりページ下部に配置された見出しやHomeへのリンクが見えているので、前ページのスクロール位置が継承されていることがわかります。 スクロール自体はHTMLのbody要素が制御していて、React Routerはbody直下のdivに含まれる要素の出し分けをしているからだと考えられます。

ScrollRestorationコンポーネントでスクロール位置をリセットする

ページ遷移ということになると、スクロール位置は一番上にリセットされてほしいですよね。 それを実現するために、React RouterのScrollRestorationコンポーネントを使用します。

ScrollRestorationはReact Routerのv6.4.0で導入されたコンポーネントです。

locationの変更時にスクロール位置を変更するコンポーネントとのこと。

This component will emulate the browser's scroll restoration on location changes after loaders have completed to ensure the scroll position is restored to the right spot, even across domains.

アプリケーションのroot routeでレンダリングすべきと書かれています。

You should only render one of these and it's recommended you render it in the root route of your app

routerの宣言を以下のように変更します。

const router = createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    children: [
      { path: "/", element: <Home /> },
      { path: "next", element: <Next /> },
    ],
  },
]);

function Root() {
  return (
    <>
      <ScrollRestoration />
      <Outlet />
    </>
  );
}

ルートURLではRootコンポーネントレンダリングされ、ScrollRestorationコンポーネントとURLに合わせたページ要素が並列にレンダリングされるようにしました。 ( routerにおけるchildrenはOutletコンポーネント部分にレンダリングされます)

この変更により、アプリケーションの挙動は以下のようになります。

ページ遷移時にスクロール位置が一番上にリセットするようになりました。

スクロール位置リセットの抑止

ScrollRestorationでアプリケーション全体にスクロールリセットを導入した状態でも、クリックでURL変更を行うLinkコンポーネントのpropsで一部のページ遷移ではスクロール位置のリセットを抑止できます。

<Link preventScrollReset={true} />

前ページのスクロール位置の記憶

アプリ内で以前訪れたページを再訪した際に以前のスクロール位置にいてほしいことありますよね。 ブラウザバックで前のページに戻る際はスクロール位置が復元されていますが、ナビゲーションメニューで以前のページを再訪する場合はデフォルトでは復元されません。

ScrollRestorationコンポーネントのgetKey propsを以下のように設定すると、ナビゲーションでの再訪時にもスクロール位置を復元できます。

<ScrollRestoration
  getKey={(location) => {
    return location.pathname;
  }}
/>

HomeからNextへの遷移は初訪問なのでスクロール位置が一番上になりますが、NextからHomeへの遷移時は再訪になるため、スクロール位置が下部になっていることが確認できました。

まとめ

今回は、React Routerにおけるページ遷移時のスクロール位置をScrollRestorationコンポーネントを用いて制御する方法を紹介しました。

以前、React SPAでページネーターを実装した際にスクロール位置をリセットすることができなかった経験があるので、このコンポーネントを用いてスクロール位置をリセットできるページネーターを作ってみたいです。

21日目は、@comi19さんで「社内で喋ったことあるやつ」です。Don't miss it...

US配列HHKBライクなカーソル操作のショートカットをmacで自作する

この記事は、フラー株式会社 Advent Calendar 2021の2日目の記事です。 (昨年のAdvent Calenderのためにブログを開設したものの、一年間放置してしまいました... ) qiita.com

昨日は@chooblarinさんの「今年のJリーグのBar Chart Raceをつくった」でした。 Bar Chart Raceは学生さんたちに人気らしいです。Youtubeとかでよく動画になってるからでしょうか? 見てると途中で頭の中にユーロビートが流れ出します。

US配列のHHKBのカーソル操作を他のキーボードでも実現したい

職場でのタイピングにはUS配列のHappy Hacking Keyborad (HHKB)を使用しています。HHKBの感想やレビューはネット上に山ほどあるので特に書きませんが、HHKBはUS配列だとカーソルキーがないんです

f:id:kanterbury:20211128211102j:plain
US配列のHHKB(上記リンク、PFU 公式通販より引用)
じゃあどうやってカーソルを操作するのかというと、fnキーを押しながら、[, ;, ', /のいずれかを押すことで、対応する方向にカーソルが動きます。 これだけだと、どういうことか分かりづらいので、図示すると以下のようになります。
f:id:kanterbury:20211129185113p:plain
fnキーを押しながらだと、各方向へのカーソル操作ができるようになります。
このカーソル操作、初めは戸惑いますが、慣れるとかなり快適になります。 カーソルキーってホームポジションからやや離れた位置にあるので、通常のキー配置だとカーソル操作のために右手の移動が必要になりますが、HHKBのこの方式だと文字のタイピング中でも小指がfnキーに届くので、ほとんど右手を移動させることなく、タイピングができるようになります。

でも、これに慣れると逆に困るのが

他のキーボードでカーソルキーを押すのが面倒になる

ということです。

なので、他のキーボードでも、何かしらのキーと[, ;, ', /(以下、記号キー)の同時押しでカーソルを操作するショートカットを実現できるようにしました。

なお、今回は主にMac OSでの実現方法について説明します。Windows OSでの実現方法についても、最後に少しだけ触れます。

Karabiner-Elementsに自作ショートカットを追加する

目的のショートカットを実現するために、Macキーバインド設定ができるKarabiner-Elements(以下、Karabiner)を使用します。 使用している方も多いと思いますし、解説記事もたくさんあるので、インストール方法は割愛します。

Karabinerでは、単純なキー割り当てを変更するだけでなく、有志の方が作成したショートカットコマンドが公式サイトに公開されていて、簡単にインポートできるようになっています。

さらに、有志の方が作っているようなショートカットを自作することもできます。 この自作機能を使って、目的のショートカットを実現します。

どういうショートカットにするのか

今回は、右シフト + 記号キーで各方向のカーソル操作ができるようにします。

なぜ右シフトを採用したのかというと、以下の理由になります。

  • HHKBのFnキーが右シフトのすぐ隣にあるので、位置が似ている
  • 右シフトはほとんどのキーボードにありそうだし、位置も変わらなさそう
  • 既存のショートカットとバッティングしても、左シフトがあるから既存のショートカットが使えなくなることがない

commandキーやfnキーも候補に上がりましたが、前者はVScodeなどで/との同時押しでコメントアウトのショートカットに使われており、後者はキーボードによって配置位置が違うため、落選となりました。

自作ショートカット用ファイルを作成する

適当なテキストエディタで以下のJSONファイルを作成します。名前は適当でいいですが、今回はright_shift_arrow_shortcut.jsonとします。 同一のファイルをGithubにも上げました。 https://github.com/kanterbury/karabiner_custom_modifications/blob/main/right_shift_arrow_shortcut.json

{
  "title": "Right Shift Arrow Shortcut",
  "rules": [
    {
      "description": "Right Shift + [ to Up",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "open_bracket",
            "modifiers": {
              "mandatory": ["right_shift"],
              "optional": ["left_shift"]
            }
          },
          "to": [
            {
              "key_code": "up_arrow"
            }
          ]
        }
      ]
    },
    {
      "description": "Right Shift + / to Down",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "slash",
            "modifiers": {
              "mandatory": ["right_shift"],
              "optional": ["left_shift"]
            }
          },
          "to": [
            {
              "key_code": "down_arrow"
            }
          ]
        }
      ]
    },
    {
      "description": "Right Shift + ; to Left",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "semicolon",
            "modifiers": {
              "mandatory": ["right_shift"],
              "optional": ["left_shift"]
            }
          },
          "to": [
            {
              "key_code": "left_arrow"
            }
          ]
        }
      ]
    },
    {
      "description": "Right Shift + ' to Right",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "quote",
            "modifiers": {
              "mandatory": ["right_shift"],
              "optional": ["left_shift"]
            }
          },
          "to": [
            {
              "key_code": "right_arrow"
            }
          ]
        }
      ]
    }
  ]
}

rulesの配列に各ショートカットを登録していくことになります。 fromに実際に押すキー操作のルールを、toの割り当てたいキー操作(つまり、方向キー)のルールを記載します。 今回のポイントはfromのほうです。

key_codeに押す英字や記号のキーを登録します。今回は各記号キーが相当します。

modifierskey_codeで登録したキーと同時押しする装飾キーを登録します。登録方法は2種類あります。

mandatory

必ず押すキーを登録します。今回は右シフトキーが相当します。

optional

同時に押すことを可能とするキーを登録します。 optionalに登録したキーも同時に押している場合、変換後のキーとoptionalのキーが同時に押されたように処理されます。

今回の場合は、左シフトキーを登録しています。これは、Shift + カーソル操作によるテキスト選択を自作したショートカットでも実現するためです。 例えば、右シフト + [に相当しますが、optionalである左シフトも同時押しすると右シフト + [ + 左シフト↑ + 左シフトと認識されるようになり、カーソルを上に動かしながらのテキスト選択という操作になります。

作成したルールをkarabiner-Elementにインポートする

作成したJSONファイルを以下のリポジトリにコピーします

/Users/[ユーザ名]/.config/karabiner/assets/complex_modifications

その後、Karabiner-Elementsの設定画面にて、Complex modifications → Rules → Add ruleを選択します。

f:id:kanterbury:20211129212218p:plain

別ウィンドウが開くので、その中から先ほど追加したルール群Right Shift Arrow Shortcutを見つけて、Enable Allをクリック。

f:id:kanterbury:20211129212335p:plain

これで、独自ショートカットの登録が完了です。右シフト + 記号キーでカーソル移動ができるようになりました!

使ってみて

右シフトの押下がやや重い

今回のショートカットの場合、私は右シフトを右手の小指で押下していますが、fnキーに比べると大きいのでやや重みを感じます。

もっといい組み合わせがありかもしれない

カーソル移動のショートカットを考えだすと、今回の右シフト + 記号キーよりもいいかもと思える組み合わせが浮かんできます。 私は右シフトを通常のタイピングで全くと言っていいほど使わないので、右シフト + WASDでゲームライクなカーソル移動にするのも良さそうです。

備え付けのカーソルキーを使用してしまう

ここまで書いてそりゃないぜという感じもありますが、使っているキーボードにカーソルキーがついているとどうしてもそちらを使用してしまいます。HHKBを使っている時は、何も意識せずにショートカットを使用しているのに...

Windowsでも同様のショートカットを適用したい

私はMicrosoft PowerToysというツールを使っています。 Microsoftが開発しているユーティリティツールで、ショートカットやキーバインド設定だけでなく、ウィンドウの並列配置などもサポートしてくれて、いろいろ遊べそうです。

github.com

まとめ

今回は、Karabinerへの独自ショートカットの追加機能を行って、カーソル操作のショートカットを自作してみました。 意気揚々と作ってみたはいいものの、使ってみると思ったほどでもないっていうのは、効率化あるあるだと思います。 でも、ショートカットが自作できるというのは、何かと応用が効いて便利なはずです。

皆さんの考えた最強の独自ショートカットをぜひ教えてほしいです!

参考

complex_modifications manipulator definition | Karabiner-Elements

Karabiner-Elementsの独自ルールの作成方法 – Webrandum

概念や理論を学ぶと技術が理解しやすくなるという話

この記事はフラー Advent Calendar 2020における9日目の記事です。

8日目の記事はいのりこさんのBlock Kitを用いたSlack通知をGoで実装してみるでした。 定期的な癒しの提供は、なによりも優先されるべき事項だと思います。

概要

今年9月にフラー株式会社に入社し、Webフロントエンジニアとして、React + TypeScriptで開発を行っています。 入社後一ヶ月のオンボーディング期間に、Reduxの学習を行いました。 その中で、概念や理論を学ぶことで技術の理解がしやすくなるということを体験したので共有します。

よくわからなかったけど動かせていたRedux

Reduxについては、入社前に独学でReactを学んでいた時に読んでいた書籍で使用していたため、触れてはいました。 しかし、「Reduxとは」といった概念についての説明が乏しく、「こう書けば動く」ということがメインでした。 当時はあまり理解しておらず、「ReduxってReducerとかDispatchとか登場する要素が多くてよくわかんないなぁ」と思っていましたが、書籍内の例を真似して書けば動かせるからいいやと思っていました。

Reduxの基本概念

オンボーディング期間で、Reduxの公式チュートリアルを一通り進めていきました。 その冒頭でのReduxの概念とコンセプトについての説明があり、Reduxを組み込むとアプリケーションがどういう振る舞いをするのかがとてもわかりやすかったです。 f:id:kanterbury:20201208110310p:plain (出典:Redux Essentials, Part 1: Redux Overview and Concepts)

  • Stateがアプリケーションにおける特定の時点の状態を表す。
  • Viewが現時点でのStateに基づいてUIを描画する。
  • ユーザーの操作に応じてActionが発行される。現在のStateとActionの内容によって、Stateが更新される。
  • Stateが更新されたことによって、ViewがUIを更新する。

State, View, Actionがサイクルを描くのが、Reduxの基本的な動き方です。

immutability

Reduxの公式チュートリアルには以下の様に記載されています。(引用元

Redux expects that all state updates are done immutably.

「Reduxはすべての状態の更新が不変に行われることを期待しています」

Google翻訳

ここで語られているimmutabilityとはどういったものなのか、 公式チュートリアルでも紹介している以下のサイトにて勉強しました。

Immutability in React and Redux: The Complete Guide

immutabilityはオブジェクトが持つ性質を指します。オブジェクトがimmutableであるということは、そのオブジェクトは生成された後に値を変更されないことを指します。 JavaScriptはmutableな言語なので、生成されたオブジェクトの値を変更することが可能です。ですが、immutableに更新を行うことができます。

immutableじゃない例

addAgeは第一引数のオブジェクトに第二引数の数値をAgeプロパティとして追加したオブジェクトを返す関数ですが、引数として渡されたオブジェクトにプロパティの追加という変更が生じているのでimmutableではないです。

ちなみに、既存のオブジェクトに変化が生じることを副作用といいます。

let person = {
    name: "kanterbury",
    bloodType: "A"
}

// personオブジェクトに年齢を追加する関数
function addAge(person, num) {
    person.age = num // 既存のオブジェクトに変化が生じてしまっている
    return person
}

person = addAge(person, 18)

immutableな例

一方、こちらのaddAgeでは、引数のpersonオブジェクトにageプロパティを追加したオブジェクトnewPersonを生成し、それを返り値としています。 既存のpersonはあくまでコピー元として使用されただけなので、変化はありません。 personはaddAgeの返り値であるageが追加されたオブジェクトに置き換えられるので、immutableに更新が行われています。

let person = {
    name: "kanterbury",
    bloodType: "A" 
}

function addAge(person, num) {
    let newPerson = { //引数のpersonを元に、新しいオブジェクトを生成
        ...person,
        age: num
    }
    return newPerson
}

person = addAge(person, 18) //addAgeで生成された新しいオブジェクトに置き換える

この例のように、Reduxでも、アプリの状態を表すStateを更新する場合は、Stateの値を変更するのではなく、新しいStateを生成し、それに置き換えるという操作を行います。

上記の二点を踏まえると

ここまで説明したReduxのサイクル、そして、状態の更新はimmutableに行うことを踏まえると、ReduxがReducerやDispatchなどに分かれているのは、「状態更新の不変性を保った上で、サイクルを実現するため」だということが理解できました。

  • Action Creater: ユーザーの操作や入力に応じたActionを生成する。
  • Reducer: 現在のStateとActionの内容から、次のStateを生成する。現在のStateの内容を変更するのではなく、新しいStateを生成するのが役割。
  • Dispatch: Action Createrで生成されたActionをReducerに渡して、新しいStateを生成させる。Stateは生成された新しいものに置き換えられ、更新される。

まとめ

結局なにが言いたいのかというと、技術を学ぶ際には、その技術の概念、つまり、どんなことをどのように実現しようとしているのかを理解することが肝要ということです。

概念を理解すると、

→ 技術の構成要素それぞれにどういった役割があるのかがわかる

→ 役割がわかると、なにをさせればいいのかわかる

→ なにをさせればいいかわかると、どうコードを書けばいいのかわかるようになる

ということを身をもって体感しました。

実際の開発においても、既存のコードの真似をすればある程度動くものは書くことができますが、きちんと概念を理解した上で使用していきたいと思います。