Windows 11 でローカルアカウントを作る方法

巷にいろいろな抜け道があるのですが、

  1. Windows 11 で Microsoft ID のアカウントでインストールする
  2. ローカルアカウントを作って管理者権限を付ける
  3. インストール時の Microsoft ID アカウントを消す

の手順が一番安全なはずです。

※ 抜け道を探す方法は、別のサイトを参照してください。

Announcing Windows 11 Insider Preview Build 26120.6772 (Beta Channel) | Windows Insider Blog https://blogs.windows.com/windows-insider/2025/10/06/announcing-windows-11-insider-preview-build-26120-6772-beta-channel/ によれば、SetDefaultUserFolder.cmd を使ってユーザーのフォルダーを設定します(これ、手軽かどうかは不明です)

以前は、インストール時に Administrator のアカウントが作成されていて、それにプラスする形でローカルアカウントを作っていました。これは Linux での root アカウントと同じで、消すと OS ごと死んでしまいます。なので、root アカウントや Administrator アカウントは外部からログインできないようにする(リモートデスクトップや ssh など)のが定番なのですが、Windows 11 の場合はそのあたりが曖昧になってしまっています。

会社のドメインやポリシーを使っている場合は、管理者権限のアカウントと社員が使うアカウントを区別します。しかし、家庭で使っているようなアカウントの場合は、もう少し緩くてもいいでしょう。さらに言えば、会社のようなポリシーをきつくした環境を作ってしまうと、家庭の PC ではオーバースペックでややこしいことになります。

実際、私の環境では Windows 11 Pro に Microsoft ID で作った PC に対して、リモートログインができません。おそらくドメインサーバーを入れればいいんですが、それはオーバースペックですよね。そういう、もともとのローカルネットワークでの環境に Windows 11 の Microsoft ID アカウントの強要は適していないということです。
(実際の原因はわからないのですが、度々発生するので、リモートデスクトップ用のローカルアカウントを作成しています。多分、Wi-Fi 等のネットワーク関係だとは思うんですが、ちょっとわからなすぎです)

で、先の手順で作る訳ですが、実は 3 の部分を実際にやったことがないのです。消せるはずなのですが、先に書いた通り「インストール時に使ったアカウントを削除すると、えらいことになる」ことが多かったので、最新の Windows 11 ではよくわかりません。

Microsoft アカウントで作成

最初のアカウントは通常の Microsoft アカウントを使います。新規に作ってもいいのですが、実験用メールを使いまわすのは大変なので、業務用のアカウントを用意しておくとよいです。OneDrive の同期や位置情報などをは切っておきます。

スマホの Authenticator で認証を通します。

「新しい PC としてセットアップする」を忘れないように。

Microsoft アカウントでログインできた状態です。

さて、powershell と立ち上げると、ホームディレクトリが「c:\Users\masud」になっていて、激おこなんですよ。後から、ディレクトリを変更することも可能なのですが、やめておいた方がいいです。せめての Microsoft アカウントの @ の前を取ってくればいいのですが、これが暫く放置されています(次のアップデートで、フォルダーが指定できるようです)。

バッチを作るときには環境変数 %USERPROFILE% を使えばいいのですが、wsl とかで指定したい場合にはもっと簡単にしたいですね。他にも自前のツールを使う時は、c:\users\masuda でもいいわけで、これは masud から masuda に変更したいです。

ローカルアカウントを作成

設定 → アカウント → その他のユーザーで、ローカルアカウントを作成します。

「このユーザーのサイン情報はありません」をクリック。

「Microsoft アカウントを持たないユーザーを追加する」で、ローカルアカウントを作ります。

ローカルアカウント「masuda」を作成します。

「アカウントの種類」で「管理者」に変えます。

「標準」なところを「管理者」に変えておきます。

あらためて、管理者 masuda で入り直します。

無事、c:\users\masdua のフォルダーができています。

Microsoft アカウントの方を削除

普段使いをローカルアカウントの masuda を使い、Microsoft アカウントは使いません。ただ、使っていないのに管理者権限のアカウントが残っているのはセキュリティ上、気持ち悪いですよね。OneDrive や Office 関係まわりもあるので、Microsoft アカウントのほうを消してしまいます。

ローカルアカウント masdua に入った状態で「設定」→「アカウント」→「その他のユーザー」で、Microsoft アカウントのほうを「削除」します。

実験用に入れただけなので空っぽにして大丈夫です。

念のために、再起動してローカルアカウントしかないことを確認します。

ローカルアカウントなので OneDrive の同期はありません。Windows Store は見ることはできるのですが、ダウンロードはできません(別途、Microsoft アカウントを入力する必要があります)。

Windows の Copilot は使えませんが、Edge にある無料の Copilot は使えます。

おそらく Micorosft 関係を使わない、GitHub や Node.js とかで開発する分にはこっちで十分だと思います。VS code でも大丈夫かもしれない。

あとは、Chrome 入れて Google アカウントで運用するとか、家庭用 PC であったり実験用に運用する場合はこっちでいいはずです。

カテゴリー: 開発 | Windows 11 でローカルアカウントを作る方法 はコメントを受け付けていません

C# のメモリーリーク現象の紹介(検証コード付き)

一連の C# dis から飛び火?したのか、Huomoto san のポストに、さまざまな「GC だとメモリリークしない」意見が飛び交っていますが、C# でもメモリリークしますよ、ってのを証左しておきます。

参照カウンタで制御しているから、GC(ガベージコレクション)が起こってメモリーリークはない、と思い込んでいると、実は GC のあるプログラム言語(Java も同じ)で「メモリーリーク関係の対策を見落とす」ことになるので危険です。普段使っているときには、あまり気にしないのですが、リアルタイム制御とか増減のある大量データを扱うときに、気にしておいてください。なんか、イイ感じにコードを高速化したと思ったら、その先でメモリーリークを起こすことになります。
当然、リークが発生してしまうこと自体が「設計ミス」というのは同意はしますが、リークが発生する可能性を否定しまうと、設計考慮の範囲外になってしまって、設計ミスにすら気づかないことになります。後知恵的に設計ミスや考慮不足をなじるよりも、境界値に近いパフォーマンスを得るようなときは転ばぬ先の杖、石橋を叩いて渡る気分でいきましょう。もちろん、普通の Web アプリを作る場合にはあまり必要ないのですが(実際には、Web サーバーのときは必要なんだけど、それは別の機会に)

リフレクションでオブジェクト生成時

検証コードを一から作るのは面倒なので、ベースは Copilot に作って貰います。Copilot の出した生コードは、そのままでは駄目なので、多少手を加えていますが、一応合格点は上げられると思います(考えているかも、という意味で)

プロンプトは、こんな感じ。手元の適当な生成AIチャットでも可能でしょう。

C# でメモリーリークをする、サンプルコードを作って。リフレクションを使って create object を大量にすると参照されるポインタがなくても、手動の GC を動かさないとメモリが解放されない状態になる

using System;
using System.Collections.Generic;
using System.Reflection;

namespace MemoryLeakDemo
{
    class LeakyClass 
    {
        public byte[] Data = new byte[1024 * 1024]; // 1MB
        public LeakyClass()
        {
            // ランダムにデータを初期化
            new Random().NextBytes(Data);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<object> leakyList = new List<object>();

            for (int i = 0; i < 5000; i++)
            {
#if false
                // リフレクションでオブジェクトを生成
                Type type = typeof(LeakyClass);
                ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
                object instance = ctor.Invoke(null);
#else
                // 通常の方法でオブジェクトを生成
                LeakyClass instance = new LeakyClass();
#endif
                // Finalizer を抑制(GC の対象になりにくくなる)
                // GC.SuppressFinalize(instance);

                // 明示的に参照を保持(GC が回収できない)
                leakyList.Add(instance);

                Console.WriteLine($"Created instance {i}");
            }

            Console.WriteLine("大量のオブジェクトを生成しました。GC を強制しない限りメモリは解放されません。");
            Console.ReadLine();

            // 解放する筈
            leakyList.Clear();
            Console.WriteLine("leakyList の解放");
            Console.ReadLine();

            // 手動で GC を動かすことでメモリを解放可能
            GC.Collect();
            // GC.WaitForPendingFinalizers();

            Console.WriteLine("GC を強制実行しました。");
            Console.ReadLine();
        }
    }
}

type.GetConstructor のように、DI を使うとメモリーリークが発生しやすいです。GC が追跡しにくくなるんですね。実は、このコードだと new LeakyClass() でもリークするので、検証コードとしてはいまいちなんですが、まあ、リークのサンプルコードということで。

  1. leakyList.Add(instance) で、参照を保持しているが、
  2. leakyList.Clear(); でメモリを解放していると思ったが、解放はされない
  3. 明示的に GC.Collect(); が必要

おそらくスコープの関係だと思うのですが、3 の時点で、GC.Collect() を実行しても解放はされません。

これは、.NET のガベージコレクションの解放が3種類あって、世代ごとに解放されるタイミングが違うからです。大量に取得した new LeakyClass のインスタンスは、leakyList.Clear() した時点で解放されるように見えますが、この瞬間では解放されません。メモリの状態や生存期間(lifetime)によっては、GC.Collect の呼び出し後も残ることが多いです。.NET の GC の場合、GC メモリが自動拡張されるために、物理メモリを圧迫してしまうリスクがあります。この場合は、コンソールで1つしか動かしていないのですが、Web サーバーでの内部処理やアプリケーションサーバーのような扱いをしているときは、このような不意なメモリ取得は他のプロセスに悪影響を与えてしまいます。

解決案としては、LeakyClass 専用のアロケーターを作ります。5000件ぐらいだと IDisposable を実装して内部メモリを外出しにするとか、リークの量を減らす方法も活用できます。ゲームサーバーだと 100万件とかが多いでしょうから、もう少し別な対処をする必要があるでしょう(ゲームの方は知らないので、調べてみてください)

相互参照によるメモリリーク

もうひとつ典型的なリークのパターンを紹介しましょう。リスト構造の中で、各オブジェクトが相互参照や循環参照になっている場合です。これは参照しているのだから、参照カウントで GC の対象にならないので合ってはいるのですが、このオブジェクト群を管理しているリストやルートノードを解放しても、その先のオブジェクトが解放されることはありません。
これは、GC の仕様で、解放の深度はそこまで追わないという設計になっているためです。追えないことはないのでしょうが、GC のためにそこまで実行時に時間を掛けるのは馬鹿馬鹿しいので、実装者のほうでメモリを管理してね、という「意図的なメモリーリーク」です。
なので、この意図的な GC の設計を知らないと、相互参照をさせてリークしてしまうんですね。つまりは「仕様です」というやつです。この GC 設計は .NET 特有なのか、JVM の GC にも使われているか私は知りません。

相互参照をしたオブジェクトのリストを作っておいて、おおもとの参照ポインタを消しても相互参照したオブジェクトが残ってしまう例を示して。
using System;
using System.Collections.Generic;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace CyclicReferenceLeak
{
    class Node
    {
        public Node Partner;
        public byte[] Payload = new byte[1024 * 1024]; // 1MB

        public Node()
        {
            // ランダムにデータを初期化
            new Random().NextBytes(Payload);
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Node> rootList = new List<Node>();

            for (int i = 0; i < 5000; i++)
            {
                Node a = new Node();
                Node b = new Node();

                // 相互参照を構築
                a.Partner = b;
                b.Partner = a;

                // rootList に追加(GC の対象外)
                rootList.Add(a);
            }

            Console.WriteLine("相互参照したオブジェクトを 1000 組作成しました。Enter で rootList をクリアします。");
            Console.ReadLine();

            // rootList をクリア → おおもとの参照が消える
            rootList.Clear();
            Console.WriteLine("rootList をクリアしました。GC を強制しない限り、相互参照のためメモリは解放されません。");
            Console.ReadLine();

            // GC を強制実行
            GC.Collect();
            GC.WaitForPendingFinalizers();

            Console.WriteLine("GC を強制実行しました。");
            Console.ReadLine();
        }
    }
}

これも Copilot に作って貰ったもので(つまりは、Copilot の codex のモデルには GC のメモリリーク関係の情報が入っているということですよ)、Node の a と b が相互に参照しています。保持リストとして rootList.Add を使っているのですが、rootList.Clear() の瞬間にはメモリは解放されません。これも GC の仕様です。そのあとに、GC.Collect() を実行しますが、以下のように、この PC ではメモリは解放されません。
この業務 PC は、先日メモリを豊富にしたばかりなので、10GB 程度ではびくともしないんですよね。もうちょっとチープなメモリ(8GBとか16GBあたり)で試してみると、OS ごとロックされるか、アプリケーションが固まるのが判別できるはずです。Windows 上でやると、Swap ファイルを食い尽くして C ドライブの SSD がいっぱいいっぱいになるので、やめておいたほうが良いです。OS が落ちる現象は、メモリーリークで落ちるのではなく、swap ファイルの食い尽くしで OS が利用するテンポラリファイルが作れなくなったときです。ブルースクリーンになりますね。

正しく検証したい場合は、Hyper-V で 8GB 程度の Windows 11 を作成して、その中で実験するとよいです。メモリを制限させると、swap ファイルを作成する様子がわかります。ただし、上記のようなプロファイルを見るために Visual Studio を入れないとけないのが結構手間ですね。仕事でやると 1,2 日がかりというところでしょうか。

参考書

「Garbage Collection」という洋書があって、これはほぼ唯一の GC の解説書です。他にも 「プログラミング .NET Framework」の本にも GC の章はあるのですが、あまり解説はない(GC.Collect あたりのざっとした解説)ので、まあ、これを買うしかないですよね(と言ってみるテスト)。

ただ、これを買ったのは15年程前なので、いまだといくつか出ていますね。GC の世代とか、マーク&スイープ方式の詳しい解説とか図つきであります。

余談ですが、java の場合は -vm でメモリサイズを制御できるので、.NET 環境のような swap を食い尽くすことがありません。ただし、java の場合は -vm のメモリを喰い付くしてしまってプログラムが不意に止まります。これ、どちらを優先するかにもよるのですが、運用時にアプリが落ちないことを優先=.NETの GC にするか、運用時に OS が落ちないようにするか= Java の GC ということです。今だとメモリが潤沢にあるので、Java の -vm を大き目に取っておくことができますが、サーバー運用のときは -vm を大きく取り過ぎると他のプログラム(他のプログラムも java だったりする)を圧迫してしまうので、.NET 方式が良かった時期もあるのです。これはどちらの方式も取れるといいんですが、今だとできるのかな。10年程前 .NET のほうで調べたときには、-vm 方式が使えないので、先の紹介したような独自アロケート方式で対応することにしたのです。

カテゴリー: 開発 | C# のメモリーリーク現象の紹介(検証コード付き) はコメントを受け付けていません

Linux + SQL Server + dotnet 環境を構築する(但し、Docker 上で)

おそらく、発端は次のポストだと思うのだけど、よくわからん…が、その後に続く「Mac でにインストールするときに~」が気になったので、備忘録として構築手順を残しておこう。

Linux で SQL Server が動くと言われた当初のころから、ちまちまと Linux に入れたみたことがあるのだけど、なかなかうまくいかない。当時は、Linux + dontet の環境が貧弱だったせいもあるし、SQL Server on Linux がまともに動いていなかったというのもある。じゃあ、今はどうなのか?というと、(かなりズルいが)Docker で構築するのがベストである。Docker 上ってのが Linux なのかが不明なんだけど(私としては、Docker 上ってのと Linux 上ってのを分けたい派なんだが、これは後述しよう)、ひとまず Docker ≒ Linux 上という意図?のもと、それだったら今ならなんとかなりますね、程度には何とかなる状態になっている。ちなみに、macOS 上はわからん。そもそも、macOS 上で開発環境ならばまだしも、実運用環境はあり得ませんよね(と暴言を吐いておく)。まあ、mac server を使うのもそれなんだけど、少なくとも現時点ではクラウド上と言えば Linux と一般的には決まっている(これも Azure 上では Windows Server が動いていることは伏せておく)。あくまで、一般的な SE やプログラマの範疇で、開発環境ないし運用環境を考えてみた結果、

  • 開発環境の構築は、いわゆる LAMP 環境の方が便利ではあるが、SQL Server も Docker を利用して手軽に構築できるまではできている。
  • クラウド運用環境としては、Azure, AWS と分かれる。AWS 環境では SQL Sever は自前で構築しないといけないので面倒がだが、Azure 環境では SQL Server が用意されているので、これを使うことができる。なお、Azure では、SQL Server のほうが MySQL を立てるよりも安いので「安価」という点でも有利となる。AWS の場合は、当然のことながら、MySQL や PostgreSQL が選択肢となる。
  • 運用環境において、レコードサイズが少ない(1億件以下)となると、MySQL や PostgreSQL でもよいのだが、10億件となると Oracle や SQL Server を考えざるを得ない。なお、NoSQL として key-value 型の分散データベースを考慮するのも必要ではあるが、ここは一般的なリレーショナルデータベース(生産管理や物流追跡など)を使いたい場合とする。実際のところ、生産分野では key-value 型だとちょっと困る(設計上の制約というのもあるだろうが)

製品の購入やランニングコスト、サポートやセキュリティ条件などがあり、どの構成を使うと良いという訳では必ずしもない。
ちなみに、クラウド上に 10 億件のデータを置く場合、データベース容量のランニングコストが並みではない。常にストレージとして 2TB ぐらいクラウド上に配置されてしまうので、この固定費が馬鹿にならない。また、データをアップロードするにしても 2TB のデータは容易ではない。その場合は、素直にオンプレの PC でデータベースを構築したほうがよい。今後の MCP サーバーとかは、オンプレ PC を使ったほうが安価になるはずだ。社内 DB の検索とかにいいんじゃないですかね?

ただし、端的に言えば

のように、Linux + SQL server + dotnet の環境はお薦めしない。止む無く、既存の SQL Server のデータをそのまま持って行きたい場合に限るだろう。運用を考えれば、

  • Windows Server + SQL Server + dotnet
  • クラウド上の Azure SQL Server + Azure Functions でマイクロサービス
  • テスト用バックエンドとして Azure 上に SQL Server + dotnet 環境で web api サービスあるいは MCP サービス

に限るだろう。

Linux + SQL Server + dotnet 環境を Docker 内に構築する

忘れられているが、Windows Server の Docker コンテナ(ホストではなく)というのがある。忘れ去られているが。それを使ったほうが SQL Server は安定するのではないか、と思うのだが、GUI がない場合 SQL Server の設定は結構面倒なので、素直に Linux Docker を使ったほうが便利です。

実は、構築の仕方は microsoft が出している。
Docker: SQL Server on Linux 用のコンテナーを実行する – SQL Server | Microsoft Learn https://learn.microsoft.com/ja-jp/sql/linux/quickstart-install-connect-docker?view=sql-server-ver17&tabs=cli&pivots=cs1-bash

出してはいるんだけど、なんかうまいかないんですよね。というか、この記事だけだと要件に足りないんですよ。機能しか載っていないので。

要件としては次を考えます。

# 要件定義
- Linux Docker で動作する SQL Server + dotnet 環境を構築する
- SQL Server と dotnet は Dockerfile で動かし、Docker compose を使う
- donet 環境では web api を提供する

という形になるので、SQL Server と dotnet(web api)の2つの Dockerfile が必要になります。
以前は、この環境を構築するのに Microsoft が提供する SQL Server 用の dockerfile と、.NET Core の Dockerfile を組み合わせてあれこれやらないけなかったのですが、いまだと Copilot に作って貰えます。

docker-compose.yaml

services:
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
container_name: sqlserver
environment:
SA_PASSWORD: "Zaq!2wsx"
ACCEPT_EULA: "Y"
ports:
- "11433:1433"
volumes:
- sql_data:/var/opt/mssql
networks:
- backend

dotnetapp:
image: mcr.microsoft.com/dotnet/aspnet:9.0
container_name: dotnetapp
build:
context: ./dotnetapp
dockerfile: Dockerfile
ports:
- "5000:80"
depends_on:
- sqlserver
networks:
- backend

volumes:
sql_data:

networks:
backend:

ディレクトリ構成

project-root/
├── docker-compose.yml
└── dotnetapp/
   ├── Dockerfile
   └── [your ASP.NET project files]

dotnetapp/Dockerfile

FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /app
COPY . .
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app
COPY --from=build /app/out .
ENTRYPOINT ["dotnet", "webapi.dll"]

おそらく cli codex とか claude code でも作れる筈です。

都合上、SQL Server のポート番号、.NET のバージョンを変えています。確か、以前やったときは .NET9 がうまく動かなくて .NET8 にしたのですが、現在 .NET8 がディスコンになったので .NET9 で動かないと不味いんですよね。果たして。

docker compose up -d

できあがったら、SQL Server Managemnet Stuido で接続してみます。

Docker 内のポートにつなげるので「localhsoat,11433」を使います。

無事接続できているので、SQL Server on Linux in Docker は大丈夫そうですね。このあとは、dotnetapp ディレクトリ内に dotnet new webapi とかして、Web API 用のプログラムを作ればいいわけです。

  • dotnet new webapi でプロジェクト構築
  • ddl.sql で各種のテーブル作成
  • ddl.sql に従って CRUD できる openapi.yaml を作成
  • openapi.yaml に従って、model クラス群を作成
  • oepnapi.yaml に従って、controller クラス群を作成

という手順になります。ddl.sql は create table の羅列でよいので、適当に copilot に作って貰います。その後は、好きな AI エージェントを使って、先の手順を動かせば ok です。これえひな形となる web api の .NET プロジェクトが作成できます。

Linux 上で SQL Server を使うメリットは?

先にも書きましたが、Linux 上で SQL Server を動かすメリットはほとんどありません。あるとすれば、

  • 10億件程度レコードがあるが、Oracle では高い(SQL Server もそこそこ高いが)
  • LINQ が使いたい(Laravel の Eloquent ではなく、Ruby の Acitve Reacord でなく、Node.js の comporess ではなく…)
  • SQL Server が手慣れていて、MySQL とか PostgreSQL だとよくわからない。
  • 既存の SQL Server のデータを移行しないといけない。カラム名が日本語の場合とか。これが一番多いと思われ。

って、ところですね。Docker で構築するのだったら、同じような手順で Linux + Laravel + MySQL という組み合わせも手軽にできるので、実は大差がありません。これも、自分にとって手慣れているか否かの違いです。開発環境として試験的に使いたいときは、MySQL や PostgresSQL よりも SQL Server + LINQ の組み合わせの方が早いです、という .NET 開発者向けです。

じゃあ、運用上どうなんだ?という話と、運用時に Docker 上でよいのか?という疑問があります。Docker イメージとしては microsoft 社が提供するる”mcr.microsoft.com/mssql/server:2022-latest” を使えば、インストールが簡単です。が、当然のことながらオンプレの PC などに直接入れる場合はここがハードルになります。ほかにも、10億件のレコードの場合 Oracle という選択肢があります。Oracle の場合も SQL Server と同じように Docker イメージが用意されています。

oracle/docker-images: Official source of container configurations, images, and examples for Oracle products and projects https://github.com/oracle/docker-images

実は Oracle の場合は古いバージョンの Docker イメージとか設定が用意されていて、移行とかに楽なんですよね。経験則ではありますが、Oracle の場合は設定ファイルが別口になっているので、データベースファイルが潰れたときにでも設定ファイルが残っているので、これを使ってデータの救出が可能なのです。このために昔は Oracle を使っていたものなのですが(Unix 上で SQL Server が動かないというのも理由のひとつですが)、いまはどうなんでしょう?

あと、SQL Server はクライアントからの接続にパイプを使っているときが一番高速で TCP/IP 経由だとちょっと遅いんですよ。それに、SQL Server のファイルアクセスは特殊で、このあたりは Windows Server に最適化されているのですが、Linux 版の場合はどうしても posix 経由になってしまうのでパフォーマンスが落ちがちです。が、そこまで気にするのもどうかと思うし、そこまでチューニングしないといけない環境の場合は、Windows Server + SQL Server を選びますよね。なので、Linux + SQL Server の組み合わせははどうしても中途半端な気がするのです。
そうでもあっても、.NET (特に LINQ)が使いたい場合には、dotnet + SQL Server の組みわせがよいので、運用パフォーマンスよりも、開発パフォーマンス(不具合修正なども含めた保守・改修のパフォーマンス)を優先する場合には、Docker 上でもアリかなと思うのですが、果たしてどうでしょうか。

カテゴリー: 開発 | Linux + SQL Server + dotnet 環境を構築する(但し、Docker 上で) はコメントを受け付けていません

キーエンス社の営業システムを再考察してその先へ

定期的にキーエンスの営業力の高さが流れてくるのだが、実際のところどういう情報は巷には流れているのかを、拾い集めてみる。いわば、「30台で、家か墓が立つ」といわれている K 社の噂は本当なのか?それを支えているものは何なのか?とか、以下は Copilot などを駆使して探してみる。

ビジネス視点で考えると、K社の方法はファブレスという工場を持たない営業特化に絞っているところが大きい。もちろん、顧客ニーズの取り込みとか、いろいろあるわけだが、外部からの分析としては、これがわかりやすい。

キーエンスの強さの源泉。最強の営業の型「PSS」とは | SFA JOURNAL
https://next-sfa.jp/journal/sales/pss/

既に名前をついている。おそらく、営業方式のカンファレンスとかで使われているんじゃないだろうか。PSS(Professional Selling Skills)で検索すればいくつも出てくる。

  • オープニング
  • プロービング
  • サポーティング
  • クロージング

他にも四段階をステップとして、営業活動を合理的に示して、横展開できる状況を作っているのが K 社の営業方法である。なので、上記のステップを営業している個人のみが使っていても K 社には追い付けないし、合理化の恩恵が受けられない。これが、K 社の営業として同じ形で横展開される形で浸透しているからこそ、同じスタイルを貫けるし、それが客先に対しても同じ品質(営業としての)が得られるという安心感(継続であろうが新規であろうが)があると思われる。

営業マンには服装ルールがあって「白シャツでジャケットを脱がない」が徹底されている。白シャツなので、赤シャツだったり柄物だったりしない。普通の会社の営業では個性を演出するためにネクタイやシャツなどを工夫するところだが、K社では「営業」という型を徹底するために、白シャツと決まっている。

キーエンスでは「シャツは絶対白」と決まっている – 日本唯一の経営者専門スーツ仕立て屋 イルサルト
https://ilsarto.net/blog/archives/21559

そのあたり、Java の方(型)ですね、と言いたくなってしまうプログラマでもあるが、まあ型なんです。実は、これは内勤の派遣や開発者にも適用されていて、白シャツとネクタイの色が制限されている。内勤の場合、外部から見えないからどうでもいいような気がするが、私服なんて持っての他。つまりは、アジャイル開発とかには適さない体制が内規として組まれている。

[246] 営業所に赴任してから教えられるキーエンスのルール⑪【当番とお昼休み】:元キーエンス(→アンリツ)社員の回想[246] | アンリツ | 東京・四ツ谷の経営コンサルタント 立石シゲオ中小企業診断士事務所
https://www.tateishi-smemc.com/2019/05/30/%ef%bc%bb246%ef%bc%bd-keyence-_-sales-office-rules%E2%91%AAresponse-for-lunch-time/

さらに言うと、K社では昼休みがは短い。たまに、着替えは勤務時間に入るのか否か、という話が X に流れることがあるが、K 社では昼休みは、午後1時に着席していないといけない状態になる。昼に外出禁止のところもあるようだが、外出は自由である。しかし、時間内に戻ってこないといけないので本社ビルのエレベーターは激混みである。時間通りに戻ってきては間に合わないので、少し前に戻らないといけない。当然、出社もそのようなエレベーターラッシュがあるわけだが、社員や長めの契約社員の方は普通である。ちなみに、遅刻をするとビル下の警備員ににらまれるのである。まるで、高校生のようだw

キーエンスの厳しい社内ルール4選を元社員に聞いてみた|キャリアスイート(ハイキャリア転職プラットフォーム)
https://note.com/career_suite/n/nedef4ac29cd9

あと、基本的に就業時間中は私語禁止である。どうも営業活動であっても内勤の会社であっても私語禁止なので、気が休まる時間がない。休憩所はあるにはあるのだが、ゆったりとした気分にはならない。休憩室に椅子とかはない。当然のことながら皆さん白シャツである。

一般的な IT 会社に比べると、K 社は厳しい社内ルールが敷かれていて、到底あたらしい社員が入らないんじゃないかと思われるが、なにせ2000万という年収は堅い(きちんと馴染めばの話だろうけど。営業のほうは、営業ノルマがあるので大変そうだが、技術者採用の場合は「作れ」ばいいので、比較的達成しやすい。ただし、技術者は 1/10 ぐらいなので狭き門である。もちろん、白シャツと私語厳禁には耐えないいけない。あと、技術者のほうは徹夜は当たり前なので、就業時間はあって、無きがごとしだ…と聞く)。このめに、年収につられてほいほいと新入社員がやってくる。まあ、年収と福利厚生ぐらいしか外側から見えないので、それもまた良いだろう。

で、営業力に戻ると、先の PSS(Professional Selling Skills)による合理化が徹底している。K社内で PSS と言っているかどうかわからないが(実は聞いたことがない…と聞いた)、営業システムなどを含めて数億円をかけてシステムを組み、営業への合理化をすすめている。合理化というとコストダウンのように見えるが違う。営業活動をするために、目標達成のための無駄を省き、達成のためには資金をつぎ込むという体制が K 社にはある。これは、営業ノウハウ自体を全社に横展開することで成り立っている。ゆえに、社員が白シャツであったりネクタイの色が揃っていたり、営業スタイルが皆同じであったりするのに通底しているのだ。

だから、それが悪いとは言わないし、実際に粗利は50%を越える営業成績を残しているし、実績がある。ただし、そこに再現性があると言えばどうだろうか?と悩むところでもある。

ちなみに、同じような営業スタイルは、他業種としてはパーソルやリコー(のリコピーの時代)やトヨタ(のトヨペットの時代)がある。徹底的に顧客の要望を分析してい、顧客の求めるものを掘り起こし、顧客の要求を素早く解決する、という方法を取っている。K 社がリコーとトヨタと異なるのは、いわゆるファブレスであり工場を持たないことだ。パーソルは工場を持たない(派遣社員だけを持つ)ので似たスタイルと言える。

余談だが、一方でラピダスがある。先日、NHK 特集で半導体復活の特集を組んでいた。

1兆円を託された男 〜ニッポン半導体 復活のシナリオ〜 – NHKスペシャル – NHK https://www.nhk.jp/p/special/ts/2NY2QQLPM3/episode/te/NWQKL47GY6/

ラピダスの場合は工場そのものである。しかし、80年代の半導体産業とは異なり、設計と生産ラインを一体化しない。ラピダスは生産ラインのみ持つという形式で、半導体設計はやらない。他社が設計したものを作るというスタイルを持つ。実は、きょうび、半導体の設計と量産を同時にやることはない。これは TSMC でも同じだ。ソフトウェアを駆使しての設計(ハードウェアの設計)と、ソフトウェアを駆使しての量産ラインの保持(ハードの製造)とは異なるという形になる。あえて、ソフトウェアを絡めるのは、ここにソフトウェア開発者としての余地があるためだ。もちろん、それぞれの専門知識(ドメイン知識)が必要なのであるが、ハード特化とは異なる形があるだろう。

と、ラピダスと K 社のアピール面は異なる。K 社の場合は、徹底的に合理化された営業スタイルとバックグラウンドにある営業システムに強みがある、今後もそうだろう。一方で、ラピダスの場合は(まだ成功しているわけではないが、あのロードマップを見ると、成功はしそうだ。少なくとも試作はできている)、専門知識を活用した上で、一点突破のスタイルで突き進む。まさに技術力と品質が営業力となっている。

もちろん、K 社が対象となる顧客は数万社であり、ラピダスの対象とする顧客は 10 数社というところだろうから、営業スタイルが変わっていても問題はない。逆に言えば、対象となる顧客の象が異なれば、K 社の営業スタイルを適用する必要はないということだ。まあ、パーソルのように逆も真ではあるのだけれど。

では、非 K社スタイルでの営業活動を Copilot と一緒に考えてみると、雑談や創造性を活用した形での「共感型営業」という単語が出てくる。K 社が顧客との「目的共有」というスタイルで進むのであれば、対抗する営業スタイルとして「共感共有」からはじめたらどうか、という提案だ。端的に言えば、アジャイル型で雑談を大切に、スタイルに引っ張ろうという私の意図的なものではあるのだけれど、合理化スタイルが苦手な場合は、別の方法を取ればよいんじゃないですか?ということです。別にK社と対抗したいわけではなく、K社ができない場所を取って行けばいいということですね。

おまけ

moonmile/omitt-chan: 見積もり依頼作成ツール
https://github.com/moonmile/omitt-chan

共感というか、見込み客自身が IT 屋に発注するために、自ら見積もりができるツールの試作です。非 IT 業者向けです。OpenAI API を使っているので、ローカルで動かしてみてください。参考サイトは https://omitt-chan.vercel.app/ にあります。そもそも、どう見込み客にリーチするかどうかは問題があるのでが(苦笑)、これ、AI エージェントを使って高速プロトタイプ作成をしたらどうなるのかの一環なので、そういう意味でのお試しです。ちなみに、この React コードは内部にあるプロンプトも含めて1日程度で出来ています。

カテゴリー: 開発 | キーエンス社の営業システムを再考察してその先へ はコメントを受け付けていません

仕様書の基本と仕組み 第14章 バイブコーディングの活用

先日、池袋のジュンク堂に行きました。最近では技術書も Kindle 版で買う事も多く、そうなると Amazon 一択になってしまって物理的な書店には行かなくしまったのですが、大量の本をざっと眺めて背表紙を見てピンとものを買ってくる、という楽しみはやっぱり書店でしか味わえないものなのです。エンターテイメントと言えますね。
さて、ジュンク堂のコンピュータコーナーを見て、自著があったりなかったりして最近の傾向を確かめます。私の場合、C# 系の本が多いのですが、ジュンク堂の C# コーナーは C 言語といっしょくたになる位に小さくなっていて「ああ、タイトルに C# って付くと、それだけで本屋では隅に追いやられそうだ」と思ってしまう訳です。同人誌界隈の技術書典には行かないので、その傾向はわからないのですが、一般的にはそう、ということです。
他に何が増えているかというと「AI」です。もう「ChatGPT」すら古くなっているようなコーナーではありますが、兎に角エレベーター直近にあるコーナーは AI で占められています。あまり流行を追わなかったジュンク堂ですらそうなのですから、一般書店ならなおさらでしょう(ちなみに、一般書店のコンピューターコーナーは相当縮小されてしまって、Excel 本とか、スマホアプリの使い方とかが多いですね。まあ、作る側には回らないのと、長く続く不況のせいもあるでしょうけど、MOS をはじめとする資格本が多くなっています)。ジュンク堂の場合は、MCP があったはずなのですが、飽きてしまったらしくオライリーのプロンプトエンジニアリングの本が平積みになっていました。生成 AI そのものから、AI エージェントによる自動化が話題になり、AI 駆動という触れ込みから、再び「プロンプトエンジニアリング」を見直そうという向きになっています。さて、プロンプトエンジニアリングとはいえ、初期の ChatGPT の頃に流行ったなっちゃんって本じゃなくて、論文級のオライリーの本が置いてあるのが好感が持てますね。私も PDF で持っています。

コンピューター本の執筆をしている者としては(テクニカルライターと言うと足を使って取材をしている人を示しそうで、私の場合、モニタ上でぽちぽちやっていることが多く「テクニカルライター」というと語弊がありそうで怖いのですよ。コードは書くから「プログラマ」だし、名詞的には「ソフトウェア開発者」にしてあります。エンジニアは工学的な専門家になるでしょうから、「エンジニア」を付けるのもちょっと、という訳で)、AI の本を出せば売れるんではないか?とか「AI の本を出しませんか?」という話を聞いたりも聞かなかったりもするのですが、いえいえ、AI の本や「AI 駆動」の本はみなさんが書き始めていて、年末前には出版されてしまうので、いまから執筆しても無理なんですよ。それに、まあ、AI 駆動というのは、ちょっと前のプロンプトエンジニアリングブームの響きもあって、私的には避けてきたいところですね。あえて「○○駆動」とう枠組みに入れない方がよさそうです。

とは言え、

図解入門 よくわかる最新 システム開発者のための仕様書の基本と仕組み[第4版]

が棚に平置きになっておりました。平積みは水平に本を置くのですが、私としては棚に平置きになっているほうが嬉しいです。表紙が目の高さにあるので、平置きに目線をしたに下げるよりも、目線を上げて探すことが多いです。さらに言えば、スペース的にお得ですからね。他の本も並べられます。
どうやら、AI エージェント絡みで「spec 駆動(仕様駆動)」というワードが広がっています。いわゆる、ドキュメントに従って AI エージェントを動かそう、という話です。なんのことはない、従来型のウォーターフォール型や計画駆動を AI エージェントに置き換えただけなのですが、どうやら、最近の若い人には「仕様書を書く」ということが馴染みがないようで、仕様書の書き方がわからない、そもそも仕様や設計をまとめて書き下すことができない、という風潮があるようです。ようです、と言っているのは、目の前にしたことがない(…ことはないのですが、これは企業秘密としておきましょう、まあ、40代ぐらいの人でもできないし、60代近い人たちも、人まねでやっているだけで、理論的なことを学んでいない人が多いので、あまり、要件/仕様/設計が出来ている人はいません。アジャイルというか、カウボーイコーディングの人が多いのです。あまり関わりたいくないのですが、私の向こうがコーディングされている場合は ok です。被害を被らないし)訳でもないのですが、そのような傾向がみられます。

ちなみに、知らないことは罪ではありません。知らないことにより回りくどいことをやって失敗してしまうこともあるでしょうが、まあ、それは子供ならば仕方ないですね、というところです。大人ならば、まあ、馘になってしまうかもしれませんが、それも仕方がありません。
なので、知らないならば、知ればよいのです。「無知の知」もそうですが、無知だと思えば、知っておけば良いのです。概略でも知って、おけば、知ったかぶりをして、知っている人との話もあうでしょう。

さて、仕様書の話に戻りましょう。AI 駆動あるいは、AI エージェントの活用の仕方は、この本には書いてありません。この本では、仕様「書」や設計「書」などのドキュメントをベースにして開発が進んでいきます。ドキュメントに焦点を当てたのは、片方で、要件定義とか PMBOK の本とかが既にあったからです。当時の企画段階で、既に知識ベースの本はでていたので、じゃあ「書」にターゲットを置いてやってみましょう、と企画を通したのがこれです。幸い、といいますか、このドキュメントベースというスタイルは一般的には受けがいいらしく、第4版となって長く続いています。「改版のために、何か付け加えることはできませんか?」と言われて、章を少しずつ追加して今に至っています。

開発プロジェクトとしては第9章ぐらいで完結しています。その後の章は版を重ねるときに無理矢理追加してものです。無理矢理とはいえ、無理矢理を押したのは私の頭脳に対してなので、全体を通してみればなんとなく意味のあるような章立てにしてあります。ご安心ください。

第14章 バイブコーディングの活用

皆さんご存じの通り、秀和システムが潰れて、秀和システム新社になりました。面倒なので、前者を旧社、後者を新社と呼び分けますが、この手の図解シリーズはどうなるんでしょう?といのが一般読者的に興味があるところです。図解入門シリーズは、結構専門的なモノが多く著者も大学関係の人や専門家が多いんですよね。

それは、さておき、今後版を重ねるかどうか不明になってしまったので、第14章を追加してしまいましょう。せっかくなので、AI 駆動の話を絡めていきます。先に書いた通り「AI 駆動」という言葉はバズワードになりそうなので、ここでは避けておきます。「バイブコーディング(vibe coding)」も消えそうなのですが、プロンプトエンジニアリングぐらいは残るんじゃぁないでしょうか。

以下、阿部さんが顧客、加藤さんが開発マネージャーでお読みください。

保守を請け負っていて月1には WEB ミーティングをしているのだが、阿部さんからちょっと相談ごとが来た。
阿部「加藤さん、ちょっと相談があるんだけど。実は、最近うちの会社でも AI エージェントというモノを使い始めたんですよ。お客への案内メールをいままで Excel の VBA マクロを使っていたのだけど、ちょっと自動化をしようと思って書き直しているところでね。AI 駆動というのか、そのあたりなんだけど、ええと、それでね、加藤さんのところは使っている?」
加藤「なるほど。最近は AI が流行っていますよね。チャットで相談を受けたり、AI エージェントを使ってコーディングをしたりして、うちでも便利に使っています。Google とか OpenAI とかいろいろな会社のものがあるので、好きなモノで大丈夫ですね。有償版もあるのですが、まずは無料からどんな感じで作るか試してみるのがお勧めですよ」
阿部「そうなんだ。それは安心そうだ。それで、ちょっと相談があってですね」
加藤「はい、なんでしょう?」
阿部「システムの話じゃないけど、いいかな?」
加藤「もちろん、どうぞ」

加藤は嫌な予感がした。システムの話じゃないから、受注という訳でもなさそうだ。でも、システムが不具合がでたわけでもないし、打合せは月1にやっているわけだし。まあ、「AI エージェント」とか「AI 駆動」という言葉出てくる時点で、何かにハマった感じがする。

阿部「実は、Excel VBA のマクロを打ちの若手が書き直しているらしいのだけど、どうも、クラウドが必要だとか、データベースが必要だとか言い出してね。単にメールの自動配信なのだから、クライドを使わないといけない訳でもないハズなんだが、やたらに詳しく説得してくるんだよ。AWS とか Google Cloud とか、Azure とか、いろいろなクラウドがあるけど、AWS 一択だというんだよね。理由を聞くと、AI がそう勧めてくるから、という話なんだが、どう思う?」
加藤「なるほど。AI エージェントを使って、クラウドを選定しているんですね。まあ、AI エージェントは、いろいろな情報を集めて、最適なものを提案してくれるので、便利ですよね」
阿部「そうなんだ。それで、ちょっと相談があってですね。理由を聞くと、AI がそう言っているから、の一点張りで、料金とかコスト面はきっちりと出てくるのだけど、ランニングコストがどうなのかとか、そもそもクラウドにする必要があるかどうか、の検討が全くないような気がして」
加藤「AI エージェントは、あくまでも提案をしてくれるだけですからね。うまくプロンプトを入れると、比較をしてくれますが、それは試してみましたか?」
阿部「ざっと、比較はしているらしいんだけど。それに仕様書は Word 文書で統一しているのだけど、どうも markdown 形式じゃないと駄目と言いだしてね。うちのシステムは加藤さんのところで Word に統一して貰って随分整理されているのだけど、ここに markdown という形式を混ぜても大丈夫なものかな?」
加藤「markdown 形式自体はテキスト形式なので問題はないですね。Word と書き方が違うので、相互に完全に変換することはできないですが、AI エージェントを使って仕様書を読み込む点ではどちらの形式を使っても問題ないはずです」
阿部「そうなんだ。それは安心そうだ。じゃあ、これはこれでいいのかな。コスト面が気になってしかたながいのだけど。若手1人でいけるのならば、いいんだけど、専任じゃないから、仕事の片手間にできるだろうか。ああ、ほんとうは加藤さんのところに発注すればいい話なのだけど、実は、そこまで予算がなくてね・・・」
加藤「ああ、予算面は別にかまいませんよ。現在のシステムの保守と運用が続いているだけでひとまず十分ですから。私が気になるのは Excel VBA マクロの移植というところですよね。確かにメール関係をクラウドに持って行くのは今後の拡張を考えればそうかもしれないのですが、素直に言って、そこまでスケールを広げる必要があるのか?というのは疑問ですよね」
阿部「そうそう、そうなんだよ。いま動いている Excel VBA で十分なのに、それをクラウドに持って行くのは無駄じゃないかと思うんだよね。AI エージェントは、そういうことは考えないのかな?」
加藤「いやぁ、考えないことはないのですが、AI エージェントは提案をしてくれるだけでから、そこの切り分けは人間が判断するしかないですね」
阿部「そうか、やっぱり、人間がやらなきゃだめだよね。で、ここが相談なんだけど、その AI エージェントの件をちょっと見てくれないかな。コードのレビューというか、設計書のレビューというか」

ああ、そういうことか、と加藤は思った。保守・運用を担当しているのだから、ちょっと位サービスをしてもよいけど、コードレビューをするにはやりすぎかなと思うし、さてどうしたものか。阿部さんの話を聞く限り、どうも「AI 駆動」に何か幻想を抱きすぎているという気がする。いや、阿部さんは解っているらしいのだけど、若手の人が問題だろう。ひょっとすると、生成 AI とか AI エージェントに過大な期待を抱いているのだろう。

AI がなんでも答えてくれるわけではない。「幻覚(ハルシネーション)」という言葉は随分一般に浸透しけど、最近の「AI 駆動」の中の spec 駆動には勘違いが多い気がする。そこは設計書や仕様書をまとめていない世代には仕方がないが。いっそんこと、AI ペアプロの形でコードレビューを AI に任せるとか、チケット駆動式に思いついた機能を少しずつ実装していくほうがいいのではないだろうか。まあ、若手のコーディングスキルがどの程度かわからないが、あまり細々としたものをこちらに持ってきてもらうよりも、内製できるツールは内製して貰ったほうがいいし、ここは、ちょっとだけ労力がかけますか。

と、加藤が0.1秒で思ったかどうかは定かではないが、ちょっとした沈黙の後に加藤は答えた。

加藤「そうですね。まずは、AI エージェントに渡したプロンプトを見せて頂けますか。AI 駆動方式でやっているのでしたら、claud..md とか requirements.md とか、そういうファイルがあるはずですから」
阿部「そうですね。助かります。じゃあ、後でメールで送るので、ちょっと待っててください」

今月の月1のミーティングが無事終わり、加藤は阿部からのメールを受け取った。claud.md だけじゃなくて、requirements.md も添付されている。spec.md もある。excel_mail.md もあるし。spec_test_pattern.md もある。結構、いろいろなファイルがあるな。ああ、なんとなくわかった。「この匂いは、ChatGPT を使って腐ってしまっている匂いだぜ」、と脳内の声が響いてから、加藤は実装担当のプログラマである長島さんに言った。

加藤「長嶋さん、ちょっと悪いのだけど、この阿部さんのメールの件を見て貰えるかな」
長嶋「ええ!、まあいいんですが、これ残業ですか?」
加藤「いや、残業じゃないよ。ちょっとしたサービスだよ。まあ、1時間ぐらいで終わると思うけど」
長嶋「サービスですか、まあ、阿部さんの頼みならば仕方ないですよね。残業にならないように1時間だけってことでいいですね」
加藤「そうそう、1時間だけね。1時間だけ。で、内容は、AI 駆動でクラウドを選定しているらしいんだけど、ちょっと過大な期待を抱いているようで、そこをちょっと見て貰えるかな。プロンプトも添付されているから、そこも見て貰えると助かるよ」
長嶋「あ、ああああ、ああ、ああああああ・・・、そういうことですか。わかりました。ちょっと見てみますよ」

どうやら、長島さんには何か通じたようだ。弊社では、数か月間から AI エージェントで GitHub Copilot を使っている。GitHub Copilot は、Visual Studio Code の拡張機能として動き、GitHub Pro に月10$ で加入できる AI エージェント入門編として…という宣伝文句はどうでもいいのだが、入口には Copilot がちょうどよい。一応、Claude Code もにも加入して貰って試験的に使っている。ただ、長島さんが言うには「夜中に動かすような大規模プロジェクトならば、確かにペイができるんでしょうが、うちぐらいの中小規模のプロジェクトとなると、昼間に流すことが多いので、あまり綿密な設計に踏み込まないほうが結果的に効率がよいですよね。色々ですが、いろいろ」とのことだった。

それはさておき、夜中に AI エージェントを動かして、翌日に結果をみたときにコーディングの出力が止まっていることが多いそうだ。できたとしても頓珍漢なものがでてくる。まるで、3D プリンターのもじゃもじゃのようだが、そういうこともあるだろう。仕方がない。markdown の設計書をきっちりと直して、何回か流すとできあがるらしいが、そこまで労力を掛けるものかどうかが疑問だ。

長島「加藤さん、できあがりましたよ」
加藤「おお、早いね。ええ、早いというか、数行しか経ってないのだけど、できた?」
長島「ええ、まあ、ざっと見た感じでは、というか、もとのファイルを見ても仕方がないんですけどね。*.md ファイルがたくさんあるところを見ると、細かく設計を煮詰めすぎです」
加藤「やっぱり…」
長島「AI エージェントとか AI 駆動の書籍を読むと、設計をきめ細やかにと書いてあるものが多くて、以前のウォーターフォール開発を思わせるものが多いのですが、そもそも、そんなにきっちりと設計ができる訳がないんです。というか、きちんとできないから、アジャイル開発やチケット駆動がでてきたわけで、そこを無視して、AI 駆動だけ設計をきっちりとやろうとしても無理があるんですよ」
加藤「同意見だ」
長島「専門家ならばまだしも、素人…と言っていは言い方が悪いのですが、設計書を書いたことがない若い人の場合には、もっと逐一動作確認をしながら AI コーディングを進めていったほうがいいですよ」
加藤「なるほどね。確かにね。まあ、そうだよね。で、どうする?」
長島「最初のプロンプトはこんな感じで大丈夫ですよ」

設計.md
```
# Excel VBA マクロの移行

# 目的

- 既存の Excel VBA マクロのメール配信を、Python を使って書き直す
- クラウドは使わない

# 機能

- Excel VBA マクロの機能を Python に移植する
- メール配信機能を実装する
- 配信先は、Excel シートに記述してある
- 配信元は、コード内に .env として記述する
- メール配信の結果をログファイルに残す

# 制約条件

- クラウドは使わない
- メール配信先は 100 件程度
- メール配信は一日一回程度
```

長島「このぐらいで、十分ですね。もとの Excel VBA マクロの量がわからないので、なんともいえないのですが、クラウドに移行する必要がないところを見れば、そんなに件数は多くないでしょう。Excel VBA から Python に移行するのであれば、AI の力が借りれるし、少しずつコードを移植すれば確実に終わると思います。さすがに、一晩でおわりというわけにはいかないでしょうが。1週間あれば形にはなると思いますよ」
加藤「ありがとう。まあ、そうだよね。じゃあ、これを阿部さんに早速送っておくよ」
長島「加藤さん、ちょっと送るのは待ってくださいよ。即レスしてしまうと、IT 屋の立場がなくなりますからね、もうちょっと寝かせておいて、今週末か来週の月曜日の夕方あたりに送るってのはどうででしょう?それなりに仕事をした風にして」
加藤「ああ、確かに、じゃあ、メールで、月曜日に午後に自動送信にしておいて設定しておいて、と・・・」

果たして、阿部さんのところの若手がうまくいったかどうかは、来月のミーティングで聞いてみよう。そこそこの規模があれば、こちらで受けるとしようか、と加藤は思った。

カテゴリー: 開発 | 仕様書の基本と仕組み 第14章 バイブコーディングの活用 はコメントを受け付けていません

ChatGPT を使いながら短編小説書くと碇シンジ状態になれば成功

筒井康隆が90歳になってしまったのかというのと、六本木に松本零士展にいってみて生原稿を見たのと(あと、士郎正宗の原画展もあって)、ちょっとつらつらと文章書きを再開してみる。

文章自体は、技術書を年2冊のペースで書き続けているので、それほど苦労はしないのだが、技術書とは異なり小説の場合は気概というか、何か構えたところがあって、長年復活できないでいた。というか、復活は諦めていたのだ。

書きたいものが無いわけではなく、言いたいことを書く場所が欲しいのは確かで、依頼にせよあるい意味で惰性にせよ技術書を書いているのはそういう意味もある。ただし、完全に自由に書けるわけではない。あたり前だが、技術書なのだから嘘を書くわけにはいかない(結果的に嘘になってしまった=間違ってしまった、ことはあるかもしれないが)。自分なりに検証をしているし、過去に人の本を読み「このコードは動かしていないな?」とイライラしたことがあったので、自分のコードは全て動作をさせている(これも、たまに原稿上で直してしまうことがあって、コードが足りないことがあったりするもすのだが…ごめん、そういう理由で動かないことがあったのね、と昔の著者さんには謝りたい)ので、当然のことながら嘘や現実とは異なることは書けない。

じゃあ、小説の場合は嘘ばかりかというとそうでもない。当然のことながら誤字脱字を直さないといけないし、登場人物の整合性はあわせないといけないし、時代背景やら時代考証が必要なときもある。SF 小説であっても、あまりにも頓珍漢な科学技術を描くわけにはいかない(とはいえ、横田順弥のハチャハチャSF があるんだから、科学的の整合性をあえて外すパターンもある)。それは、どのようなものを自分が書きたいか、に依るだろう。
最終的に小説が売れるか売れないか、という点に拘ってしまうと、読み応えのある長編やら読者層にマッチした流行を取り入れたものやら、が出てくるわけだが。なに、「売れる」と言うこと自体は、「書く」時点で決まっているわけではない。むしろ「売れる」という現象は結果論である場合が多いので(企画ものは違うだろうが)、一定以上になる場合にはそれなりの捨て駒気分が必要なるだろう。
ちなみに、企画が通った技術書を書く場合、ある程度の安定収入(原稿費用みたいなもの)が入る。もちろん、それで開発者なみの給与になるかといえば、そうはならない。そうはならないので、主に技術書は「ボランティア」で書かれてといっても過言ではない。大抵の技術書はそうだろう。お疲れ様です。ひるがえって、私の場合はどうかというと、長年(20年は書いているので、長年といって差し使えないだろう)書いているので、どれぐらいの時間を技術書の執筆に突っ込むか、はある程度決めている。

閑話休題

生成 AI を活用して書き進める

プログラミングをするときに、生成AI あるいは AI エージェントを日常的に使っている人は多いだろう。生成 AI の活用は、2年前の新人教育から使っているのが、質問事項はほぼ「AI に聞け」ということにしてある。文法を全体を網羅して覚えるよりも、基本的な書き方だけ学び、解らなかったら AI に尋ねるということが効率的である。

さらに、今年の6月頃からだったか、AI エージェントが一般的になってきた。生成 AI 単体ではなく、ファイルやプロジェクトの内容を書き変えてくれる AI エージェントの存在は、コーディングというものを一変させている。AI 駆動と言う形で、最初に細かな仕様や設計を決める向きもあるのだが、私の場合は AI ペアプロがお勧めである。AI ペアプロの話は、また別の機会にやるとして、ここでは、短編を書くときの AI 利用についてちょっと気付いたことを書いておきたい。

1時間程度でざっと書き下すのが自分の時間の使い方としては合っているっぽい(長いと、書き飽きてしまうので)。なので、小説としては、2000字ちょっとぐらいの短編あるいは掌小説と言う形になる。ちょうど、星新一のショートショートか筒井康隆の短編ぐらいの長さだ。私としても、この位の短編が好きだった時期もあるので、長くて読みごたえがあるものよりも、小さくまとまって気の利いたものがよい。

文章を最近は VS Code で markdown 形式で書いている。どうやら、この書き方に慣れて来た。最初は、QX で書いたり、Word に貼り付けたりしていたのだが、VS Code + markdown + GitHub Copilot という形で技術書を書いている中で、最近ではこれが効率が良い。なんといっても、Copilot が次の文章を書いてくれるのがよい。

AI のサポートは、わざわざ AI に尋ねるのではなく、文章の続きを AI が差し込んでくれるのがむいている。特に技術書のように書き方が決まっている場合は、巷の Web サイトにある Microsoft や Google の公文書のような文体を差し込んでくれるので丁度よい。私の場合は「ですます調」で技術書を書くことにしているので、Web サイトの解説を AI が学習してくれて、それを私の文章に差し込んでくれるパターンだと、文章が無個性になって丁度よいのだ。「無個性」と言う書き方をしたが、プログラミングの本としては、ポリシーとして筆者の思惑をあまり主張しないようにしている。他の著者さんは違うかもしれないが、技術書は基本読み飛ばしが多いので、あまり文章に個性が出てしまうと読みにくくなってしまう。さらに言えば、私の悪文(多分悪文w)を編集者の方が直してくれている。読点が多いのが特徴で、語るように書くのもそうなのだが、長い文章の中で主語と述語がずれてしまうことがある。これ、語り言葉の場合はそう思えないのだけど、文章になると目立つのだ。特に、”熟読” している読者がいると、目立つ。そりゃ、文法上おかしいのだから目立ちますよね。そんなんに熱心に読まなくても大丈夫ですよ。さらっと、読み飛ばしてください。

で、生成 AI の場合は、なんとなく主語や前の文章を書くと、先の文を続けてくれる。この方式は生成 AI の Transformer に依存するものなのだが、いわゆるトークンとパラメーターの近似状態だけできまる。端的に言えば、top-p と温度というふたつの要素だけで、次の文章を決めることができる。もちろん、ランダム性が加わるので、かならずしも同じ文章になるとは限らない。そこで、ランダム性を広くとって SF 小説などを書くサポートに生成 AI をつけるとよいのである。

それと同時に、小説家にはそれなりに文体がある。例えば、2ch(あるいは 5ch)であるような村上春樹風の文章やら、星新一風の文章であるやらがそれだ。同じテーマを与えて「夏目漱石風に書いて」ということも AI には可能である。実際にどう似ているかは読むと解るのだけど、想像するに

  • 「夏目漱石」というとトークンに近い単語を拾ってくる
  • テーマとなる、文章に近い単語を拾ってくる
  • 両者に近い単語を、コンテキストのパラメーター(近隣値)に合わせて選び出す

という手順でやっているに違いない。実は人間が文体模倣をするときには同じことやっている。夏目漱石の小説を何冊かよみ、文章の繋がりを覚える。元の参考となる文章に、夏目漱石の文章の繋がり(時に副詞、助詞の繋がり、単語の選び方)を加えて、夏目漱石の文体に近づけるわけです。

さて、ここからやっと本題です。

生成 AI は近隣値(ベクトル)が近い形でトークン(単語)を選択するので、先立つ文章に続く生成される文章は、当然のことながら、学習元となる Web サイトや既存の公開されている電子文書(特に論文)に近い方になります。論文を書くとか技術文書を書く場合にはそのほうがよいでしょう。しかし、小説を書こうとなるとこれが一変します。独自性を出す、自分なりの文体を構築しようとしたときに、生成 AI がサジェッションする文章をそのまま採用することはできあません。定番の推理小説ならばいいのでしょうが、ちょっと毛色の変わった自らの文体を作りたい場合は邪魔になります。いえ、寧ろ、生成 AI がサジェッションする文章はそのまま採用できません。

というわけで、独自っぽい文体で書くと、生成 AI はこのように暴走をし始めます。

これ、GPT3 の頃にもよく見た現象ではあるのですが(top-p や温度を調節すると意図的に出すことができます)、GPT5やGPT4.1 でも同じ現象がでますね。つまりは、近隣値(ベクトル)に適当なものがなく、先に書いた文章を続けるしかない、碇シンジ文体になってしまうわけです。

要は、この状態になれば、あなたの文体は学習されていません、の印になるわけです。

カテゴリー: 開発 | ChatGPT を使いながら短編小説書くと碇シンジ状態になれば成功 はコメントを受け付けていません

筒井康隆の世界(再放送)を見ての感想を

筒井康隆の世界 – NHK https://www.nhk.jp/p/ts/7JPPP2R737/

去年の放送なので、現在は91歳ということになる。訃報は聞いていないので、まだ夫婦で老人ホームにいることになる。

実は『敵』を買って以来(しかも未読)な状態で、最近はあまり追ってはいなかった。現在90歳ということは、30年ほど前に新宿の紀伊国屋に身に行った筒井康隆は60歳ぐらいだったのかと。自分と30ほど違うとは驚きでもある。握手して貰った。

先日、「百年の孤独」を買い直した。ガルシア・マルケスがノーベル賞を取ったときに買っては見たものの暫く放置の状態で、引っ越しの折にBOOK OFF に売ってしまったような覚えがある。引っ越すときに、3,000冊の本を2,000冊位に減らした時にまぎれてしまった訳だが。あまり本は捨てるものではない。とはいえ、最近は電子書籍が便利になったので、Kindleに2,000冊ほど入っている(漫画も含めてだけど)。物理本は1,000冊弱にはなったのじゃないだろうか。で、買い直したのは、先日「百年の孤独」の100分の解説だったかで、大江健三郎や筒井康隆に影響を与えたとことを知ったのである。実は「百年の孤独」は1967年の出版で、私が生まれる前だ。ああ、そんなに古い作品であったのか、というのと大江健三郎(たぶん、万延元年のフットボールか燃え上がる木あたり)に影響を与えたとか、筒井康隆(たぶん、バブリング創成期とか)に影響を与えたとかという話になると、もう一回読んでみないとあかんだろうということになる。そうなると井上ひさしの「吉里吉里人」もそうじゃないだろうか、と思う訳で。で、まだ、「百年の孤独」は読んでいないのだが。

筒井康隆の初期作品に「東海道戦争」(1965年)がある。戦争を眺めるというパターンなのだけど、「銀河鉄道999」(1977年)にも戦争を眺めて食事をするシーンがある。松本零士は筒井康隆の5つぐらい下になるが、ほぼ同世代といってよいだろう。筒井康隆が90歳で存命なわけだが、星新一、小松左京、藤子不二雄、手塚治虫、とこのあたりの SF 世代はみな鬼籍に入っていしまっている。まあ、そういう意味では、夢野久作とか沼正三とか押川春浪なんかは、さらに年上なのだけど。そういう SF の技法に沿った形で描けるのは筒井康隆しか残っていないと言える。

ただし、「朝のガスパール」や「ビアンカ・オーバースタディ」のような書き方、さらに「モナドの領域」が現在の SF 小説(ラノベも含めて)にない訳ではない。むしろ、異世界転生ものだったり、ゲーム世界の拡張であったりするストーリーはそういう「メタ」的な視点が多いに含まれているし、それを知っていることが読者/視聴者の前提知識であったりする。例えば、涼宮ハルヒシリーズであったり、Reゼロであったり、SSSS.GRIDMANであったり、このすばであったり。主人公は意図的にメタ世界を意識している。もちろん、特別な能力があったりなかったりするわけだが、そういう現実的な世界とは別の世界に居ることを前知識として知っているという仮想世界、という読者との申し合わせは済んでいる状態になる。そのあたりは、「朝のガスパール」の連載時点でも、漫画の中に作者が登場したり(Dr.スランプとか、ブラック・ジャックとか)するシーンもあり、駒からはみ出したりするシーンがある。もちろん、そこを小説/漫画内に組み込み始めたは、果たして「朝のガスパール」だったのか、それともそれ以前に漫画があったのかは定かではない。

メタ空間という意味では、松本零士の銀河鉄道999もメタ世界であり、ハーロックやエメラルダスの世界と繋がっている。ラノベの小説でもあっちの主人公がこっちの小説にちょっとだけ出てきたりする。そういう仕掛けも読者にも既におなじみになっていて、みな了解の域に達している。

改めて筒井康隆が凄いのは、このメタ世界の小説をいくつも発表しているところだ。シリーズもので一本だけ書くのではなく、思いつく限りたくさん書く。これが凄い。

そうだな。また、短編を書く練習を再開してもいいかもしれない。

カテゴリー: 雑談 | 筒井康隆の世界(再放送)を見ての感想を はコメントを受け付けていません

「図解即戦力 アジャイル開発の基礎知識」のソフトウェア開発のための追記

本書の扱いとして、ソフトウェア開発におけるアジャイル方式をスクラムに限定することなく解説しておく、というのが本筋だったので、ソフトウェア開発そのものではなくマネジメント(スクラムマスターとかプロジェクトリーダーとか)に焦点が当たっています。昨今のアジャイル開発本がスクラムを中心にしていたので、元々の「アジャイル憲章」からスタートして、スクラム以外のアジャイル開発(XP、チケット駆動)を用いるのと、アジャイル開発自体は決して非PMBOKではない、ことを取り入れたかったので、PMBOK 用語を使っているという事情があります。

まあ、端的に言えばスクラム開発については、「ケン・シェーバー著のアジャイルソフトウェア開発スクラム一冊で十分じゃないですかね?」ってところからスタートしたので、こんな感じになっています。

端的に言えば、Software Development 以外を記述した本(教科書的な)なので、ソフトウェア開発については SWBOK あたりを読め、という形になります。これをスタートラインとしているので、本書の範囲としては、右中央の「アジャイル開発型マネジメント」に絞っています。

中央にある、PMBOKや実装ノウハウはソフトウェア開発において基本知識としてあるものとして、実際にプロジェクトを動かす場合に、計画駆動型にするかアジャイル型にするかという判断があります。これはアジャイル憲章にも書いてある通り、ドキュメントを包括するのか動くソフトウェアを優先するのかという “選択” になります。実は、ドキュメントのほうを優先する場合もあります。宇宙開発や原子力開発、航空機関係のシステムなどの人命が掛かるものは「ドキュメント」に基づいて合意を取る等の厳しいルールが課せられます。そういう場合は、到底アジャイル開発という訳にはいきません。もっと厳密な形でプロジェクトを走らせることが求められます。逆に言えば、人命に関わらないものに関しては随時動きを確認するようなアジャイル形式でよいのです。スピードが要求される広告サイトや商品販売、あるいは一時期的なイベントで集客を見込むようなWEBサイトなどはリリースまでの期間は短期であるほうが優れていると言えるでしょう。なんせ、WEBサイトの動きがちょっとおかしかったとしても人命が失われることはありません。更に言えばほぼリアルタイムに修正が可能です。

このように、マネジメント自体を計画駆動にするのか、アジャイル開発にするのかという選択肢は、エコシステムとして(まさしく、「アジャイルソフトウェア開発エコシステム」に書かれていることになりますが)どちらがより金銭的に有利なのかという話になります。

ソフトウェア開発そのものに結び付ける道筋

実際のところ、コードの実装者から見れば、それが計画駆動であるかアジャイル開発であるかの違いはありません。端的に、コードを書く、単体テストをこなす、を繰り返します。コード書く前に紙のドキュメントの有無であったり、詳細設計 “書” に基づくべきなのか、チケット駆動のようにざっとした箇条書きによってコーディングを行うかの違いはありますが、少なくとも現代においては「コードを書く」「単体テストを行う」という XP のノウハウを利用したほうがよいです。さすがに、いまどき、コンパイルが通らない状態でコードを書くことはないでしょう。昔は、コンパイル自体が長かった、あるいは大型計算機の使用時間待ちであったこともあり、コンパイルなしでコードを書く時期もありました。しかし、今、そんなことはしないでしょう。そういう意味で、XP のテストコードを書くといのは実装工程においては必須になってきます(テストコードを先に書くか、後に書くかという違いはありますが)。

対象読者ですが「コードが一定の品質以上で書ける」ことが前提となっています。マネジメント層(スクラムマスター、プロジェクトマネージャー、オーナーなど)はコード自体はまあいいのですが、開発者が読む場合はこれが必要条件になります。

本書の章をピックアップして具体的なソフトウェア開発(主に実装工程)に結びつけると、こんな感じになります。

第2章 スクラムとXP
先に書いた通り、単体テストが必須です。単体テストサイクルは各 xUnit のツールに従います。継続的なコード改善やコードの共有化においても、単体テストが有効に働きます。これは計画駆動、アジャイル開発に限りません。最近ならば GitHub Action などを利用して、コミット前にビルドやテストコードの実行を強要すればよいでしょう。
ペアプロについては、リモートでのペアプロが可能になっています。VSCode などでコードを共有してもよいし、Teams で通話を繋ぎっぱなしでペアプロをすることも可能です。実際、新人教育などでは2,3時間繋ぎっぱなしで、相手のエディタを表示してもらって操作することもやります。

第3章 チケット駆動、第4章 バックログ、チケット
「チケット駆動」ということになっていますが、実際はチケットの扱い方です。
作業を分割する方法として、WBS/チケット/タスク/プロセスなどの様々な呼び方があります。これらのタスクについては、スケジュールを確定させたい計画駆動と、途中で顧客の要望を取り入れたい=チケットが増加する可能性が大であるアジャイル開発との違いがあります。
また、スクラムではスプリントという期間を決めるのに対して、チケット駆動ではそれほど期間を区切りません。
また、チケットを共有する手段として、Backlog(という製品)や GitHub の issue の利用があります。以前ならば、Excel で課題管理をしていたところですが、昨今では Web アプリを使って複数名で共有するのが当たり前になってきています。
コーディングをする上でのチケットの扱いは、完了を明確にすることです。これは本書でも書いてある通り「単体テストが通った」ことを明確にするとよいです。客観的に完成したことがわかる目安を作っておくことが重要です。

第5章 自動テスト
いわゆる再帰テスト(繰り返しテスト)のやり方です。
モックの作り方などの具体例がでていないのはプログラム言語や動作環境によって異なるためで、割愛しています。
ざっと言えば、Web システムでの単体テストを Controller, Service, Web API 経由という分割した形にする。Servcie 単位が望ましいのですが、外部から curl などを利用した Web API 経由でもよいでしょう。ただし、データベースの中身のチェックがちょっと面倒になります。
デスクトップアプリでは、ユーザーが操作する部分でテストするのは人力となってしまうので、これもロジック部分を切り出して自動テストが可能な状態にします。場合によってはモックが必要になりますが、コツとしては「モックを必要としない単体テスト」と「モックを必要とする結合テスト」に分割するとよいです。
ちなみにモックを必要とする結合テストであっても xUnit のノウハウが使えます。
組み込み系はモックが必須になる(I/Oを叩く、タイミング調節など)ので、これはロジックを分離する形で単体テストができるようにします。これは必須条件ですし、単体テストを利用すれば、少なくとも実装期間が半分になるのでお薦めです。

第6章 スタンドアップミーティング
アジャイル開発で、朝会などが有効となっていますが、新型コロナの影響や海外チームを組むことは “同じ場所に集まることはできない” ので、別な方法をとります、ということです。
最近は、出社が強制する世の中に戻りつつありますが、要は遅延したコミュニケーションをどこまで考慮するのか?ということです。逆に言えば、本当に即対応(命に係わる現象)以外は、遅延を許容したほうがうまくいきます。
アジャイル開発スクラムで「スクラムミーティング」が強調されるため、同じ時間に同じ場所にいるということが重要そうに見えます。しかし、それはスクラムを採用したときの話であって、XPやチケット駆動、あるいは計画駆動の場合には必須条件ではありません。そのあたりを間違えると、無闇な “朝会” を開発者に強要することになってしまいます。というか、最近なっていますが。

第7章 タイムボックス
第6章のコミュニケーションに関わるものとして、締め切りを明確にした「タイムボックス」制を使います。つまり、いつまで作ればよいか?を明確にして、その間にあれこれと言わないということです。皆さん、プログラマはプロなんですから、途中でサボったりしませんよね、ということとサボっても締め切りには間に合わせてね、ってことです。途中経過は問わないのです。結果が重要です、という話ですね。
逆に言えば、未知なる要素が多いとこきはタイムボックスが有効に働きません。経験上、とあるコードが何時間、何日で作れるのかというのは「勘」を働かせることもありますが、過去の経験との比較をするのがベターです。あと、自分の実力を知るために PSP をしておくとよいです。うまくいかなそうなときは、いったんタイムボックスを外して、調査時間を決めて(時間は無限ではないので)、どのくらいで調べられそうかをチェックします。これは AI エージェントを使ったコーディングでも同じことが言えます。途中で迷路に入ってしまった AI エージェントを “時間” を区切って引き戻します。前回のプロンプトを無しにして、もう一度やり直しをすれば ok です。

第8,9章は割愛。主にマネジメントよりなので。

第10章 継続的リリース
DevOps が入れたかったのと、ソフトウェア開発者はどのように休日過ごすべきだろうか?というのを書くために入れています。
いまとなっては Google がやめてしまった 20% ルールですが、日々の仕事の中でなんらかの学習や実験をしておくとは非常に有効です。それも、最新情報を常に追うのではなく、仕事をしながら、つまりは仕事が8割で、未来への投資が2割ということです。未来の投資がなければ、成長がありませんよね。自分への2割の投資をしてください。
執筆時、「プログラマは休日、どうやて過ごせばいいだろうか?最新技術の勉強でしょ」という雰囲気があったので、それの反動です。最新技術を追う時間は業務時間にやったほうがいいです。休日はもっと自由な技術の追い方(休憩も含めて)をしてみてください。仕事とはいえ楽しくやりたいし、ましてプログラマという仕事は好奇心を突き詰めることもできるので “楽しい” 仕事です。そのための、ちょっとばかし辛い勉強や作業があっても全然大丈夫ですよね。ってことです。

このあたりの開発者寄りの部分は、また機会を見つけて書いていきましょう。なお、実際にどうすればよいのかというのを、https://openccpm.com で準備中です。

カテゴリー: 開発 | 「図解即戦力 アジャイル開発の基礎知識」のソフトウェア開発のための追記 はコメントを受け付けていません

AI エージェントでプログラマ向けタイピング練習アプリの試作とアイデアマラソン

ひさびさに “アイデアマラソン” の一環です。最近は起き抜けにスマホで Copilot を開いて、何かアイデアをまとめておきます。まとめるというか、アイデアを少し具体的に AI に尋ねて思考実験(壁打ちとも言う)をしておきます。Copilot の場合、あれこれと具体的なツールを作ろうとするのですが、そこは完全に無視をして、ちょっと抽象的で要件定義的な話に留めておきます。あと、実際に作るとなったらどんな機能があるのかを箇条書にメモをしておきます。

要件と機能が数行程度で固まったら、readme.md に書き込んで、vscode + GitHub Copilot でコードを書いて貰います。

# プログラマ向けタイピングゲーム

- コーディングのための英単語をが出てくる
- コンピュータの専門用語が省略形だけじゃなく、フルスペルで出てくる
- プログラミングで出てくるコードの一部がでてくる

## 機能

- 単語単位ではなく文字単位でキーのチェック判定をする
- 制限時間内のタイピングを競う

あらかじめ、Next.js を使うことは決めておいたので、React のプロジェクトだけは作成しておきます。

このぐらいのアプリだと、まあ UI は程よくできてくるのですが、動きが変なところが出てきます。今回のアプリで言えば、

  • キー入力が効かない
  • キーを入力している間にタイマーが正常に動いていない
  • 間違ったキーを押したときに、正しいキーを入れるまでカーソルを止めて欲しい

のように、動かせば一発でわかるようなバグが出てくるので、テスター役としてアプリを動かします。

バグの修正の場合、元の readme.md を書き変えてもよいのですが、所詮使い捨てのプロトタイプになるので、プロンプトで指示を出しています。

そういう意味では、自動化された vibe coding ではないのですが、私の場合はこのような AI ペアプログラミングのスタイルで十分です。要件定義や機能を厳密にまとめる必要はありません。そもそも、厳密に記述する必要がないし、厳密に記述することは不可能です。未来を見通せないので、プロトタイプ開発をしているわけですから。

半日ほど面倒を見て(片手間に)から、ほどよく動いたので、Vercel に公開しておきます。

https://for-programmers-typing.vercel.app

Vercel の場合、React プロジェクトが手軽に公開できるのが便利です。本格的に使うといろいろとあるのかもしれませんが、GitHub にアップロード → Vercel で自動的に公開、という手順が用意されているので、雑に公開してみるのもよいでしょう。

コードのほうは、GitHub に public にしておきます。private な状態でも Vercel に公開ができます。

https://github.com/moonmile/for-programmers-typing

typingData.ts に、出題するランダムな単語が書いてあります。このランダムな単語や文字列自体も Claude Sonnet が作ったもので、適当に問題が追加できるようになっています。 ひとまず、実際に動かしてアプリの雰囲気を確認したいときに、この方法が便利じゃないでしょうか?

参考先

アイデアマラソン研究所
https://www.idea-marathon.com/

アイデアマラソンというのは樋口氏が提案した、毎日アイデアを出してノートにつづっておくという習慣です。2000年頃の会社時代でもやっていました。営業とかでないので、プログラマだとアイデアを出しても仕事に直結する訳ではないのですが、日々の検索や最新情報を追うだけではなくて、「自分で作ったらどうなるだろうか」という形でメモっていきます。以前だと、実際に動かすことはできなくて思考実験で終わっていたのですが、AI エージェントと組み合わせれば、プロトタイプ程度であれば結構できあがりますよ、ってことです。出来上がったものを実際に仕事とかに使うかどうかは別ですね。

紙のノートとか使い場合はこんな風になります。

アイデアマラソンをやってみる – sowdatabase
https://sowrealyou.hatenablog.com/entry/2024/06/17/%E3%82%A2%E3%82%A4%E3%83%87%E3%82%A2%E3%83%9E%E3%83%A9%E3%82%BD%E3%83%B3%E3%82%92%E3%82%84%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B

カテゴリー: 開発 | AI エージェントでプログラマ向けタイピング練習アプリの試作とアイデアマラソン はコメントを受け付けていません

.NET開発者じゃなくても利用できるタスクランナー fake の勧め

発端はこのポストから。

いわゆる、ビルドからデプロイ、テスト実行などを含めたタスクランナーですね。昔話をすると、いわゆる Makefile を使ったビルドが Java 環境で辛くなり始めたとき Ant が出てきて流行りました。中味は XML 形式で書かれていて、条件分岐や依存関係などが Makefile よりも書きやすいという触れ込みです。それを受けて、MSBuild が出来たわけですが、実は今となっては XML 形式というのは書きづらく、JSON 形式か YAML 形式(Docker など)が流行ったりしています。

一方で、Makefile を C 言語風に書くということで C++ 界隈では CMake が使われます。CMake は OpenCV などをビルドするときに外せない要素で結構複雑怪奇なのですが、関数形式であることと複数の Makefile をひとつにまとめられるという依存関係で重宝されています。

さらに傍流のところに Fake があります。Fake は F# 専用の(という訳でもないのですが)の Make ファイルで、ちょうど Ant/MSBuild の集約の仕方と CMake の依存関係をうまく吸収しています。とはいえ、F# 界隈でしか使われいないし、F# を使っていても実際のところは *.fsproj を使うので Fake を使うことは非常にまれです。と言いますか、今の今まで忘れていました。

https://fake.build/

fake コマンドをインストールする

いまひとつ、インストールの仕方が解り辛いのですが、以下のように dotnet コマンドで tool-manifest を作ってから fake-cli をグローバルにインストールします。npm でツールをインストールときと同じです。本来ならば、ローカルに入れたいところなのですが、パスを作るのが powershell では面倒なので -g でグローバルに入れたほうが楽です。

fake.build/guide/getting-started.html

dotnet new tool-manifest
dotnet tool install fake-cli -g

.dotnet/tools の中に fake.exe があります。fake.exe 自体は .NET 6 なんですが、まあ無視します。

PS H:\kitami\FolkBearsGroup\folkbears-android\FolkBears> gcm fake                                                                                            

CommandType Name Version Source
----------- ---- ------- ------
Application fake.exe 6.1.0.0 C:\Users\masuda\.dotnet\tools\fake.exe

バージョンはこんな感じです。

PS H:\kitami\FolkBearsGroup\folkbears-android\FolkBears> fake --version 
FAKE 6 - F# Make (6.1.3.0) (running on .NETCoreApp,Version=v6.0) (this line is written to standard error, see https://github.com/fsharp/FAKE/issues/2066)
FakePath: C:\Users\masuda\.dotnet\tools\.store\fake-cli\6.1.3\fake-cli\6.1.3\tools\net6.0\any\Fake.Runtime.dll
Paket.Core: 8.1.0

build.fsx を作成する

Makefile にあたるものを作成します。コマンドとしては dontet new fake でひな形が作成できるのですが、https://fake.build/guide/getting-started.html にあるコードをコピペしても構いません。

#r "paket:
nuget Fake.Core.Target //"
// include Fake modules, see Fake modules section

open Fake.Core

// *** Define Targets ***
Target.create "Clean" (fun _ ->
  Trace.log " --- Cleaning stuff --- "
)

Target.create "Build" (fun _ ->
  Trace.log " --- Building the app --- "
)

Target.create "Deploy" (fun _ ->
  Trace.log " --- Deploying app --- "
)

open Fake.Core.TargetOperators

// *** Define Dependencies ***
"Clean"
  ==> "Build"
  ==> "Deploy"

// *** Start Build ***
Target.runOrDefault "Deploy"

Target.create で、ターゲット名に従ってコマンドを書いてきます。大抵はShell.Exec でコマンドを実行します。依存関係が “Clean” ==> “Build” ==> “Deploy” のところで、ここではデフォルトで “Deploy” が実行されます。

実行するときは fake build のようにします。build は build.fsx のことなので、deploy.fsx とか setup.fsx とかも作れるはずです。

fake build

Android のビルドに使ってみる

では、手元の Android プロジェクトで使ってみましょう。手元の FolkBears プロジェクトは Kotlin で書かれているので、IDE エディタは Android Studio を使っています。コマンドラインからは gradlew コマンドを使いビルドができます。実機へのデプロイは adb コマンドを使います。

Gradle を利用してデプロイなどの機能を修正してもよいのですが、これを fake で作ります。

build.fsx

#r "paket:
nuget Fake.Core.Target
nuget Fake.Tools.Shell //"

#load "./.fake/build.fsx/intellisense.fsx"

open Fake.Core

Target.create "Clean" (fun _ ->
    printfn "Cleaning..."
)

Target.create "Build" (fun _ ->
    printfn "Building..."
    // gradlew でビルド
    Shell.Exec("./gradlew.bat", "assembleDebug") |> ignore
    // Shell.Exec("gradlew", "build")
)

Target.create "Default" (fun _ ->
    printfn "Default target実行中..."
    printfn "gradlewでAndroidアプリをビルドします"
    // gradlew でビルド
    let result = Shell.Exec("./gradlew.bat", "assembleDebug")
    if result = 0 then
        printfn "ビルド成功"
    else
        printfn "ビルド失敗"
        failwith "gradlewビルドが失敗しました"
)

// Android 実機にデプロイする
Target.create "Deploy" (fun _ ->
    printfn "Deploying to Android device..."
    Shell.Exec("./gradlew.bat", "installDevDebug") |> ignore
)

// 特定のデバイス(25041JEGR04165)にデプロイする
Target.create "DeployToDevice" (fun _ ->
    printfn "Deploying to device 25041JEGR04165..."
    // 環境変数でデバイスを指定
    System.Environment.SetEnvironmentVariable("ANDROID_SERIAL", "25041JEGR04165")
    let result = Shell.Exec("./gradlew.bat", "installDevDebug")
    if result = 0 then
        printfn "デプロイ成功 (25041JEGR04165)"
        printfn "アプリを起動しています..."
        // アプリを起動
        let launchResult = Shell.Exec("adb", "-s 25041JEGR04165 shell am start -n jp.mamori_i.app.dev/jp.mamori_i.app.screen.start.SplashActivity")
        if launchResult = 0 then
            printfn "アプリ起動成功"
        else
            printfn "アプリ起動失敗"
    else
        printfn "デプロイ失敗"
        failwith "デプロイが失敗しました"
)

// アプリを起動する(デプロイ済みの場合)
Target.create "LaunchApp" (fun _ ->
    printfn "Starting app on device 25041JEGR04165..."
    let result = Shell.Exec("adb", "-s 25041JEGR04165 shell am start -n jp.mamori_i.app.dev/jp.mamori_i.app.screen.start.SplashActivity")
    if result = 0 then
        printfn "アプリ起動成功"
    else
        printfn "アプリ起動失敗"
        failwith "アプリ起動が失敗しました"
)

open Fake.Core.TargetOperators
// 依存関係を削除して、Defaultが単独で実行されるようにする

Target.runOrDefault "Default"

色々と書いてありますが、これは vscode 上で GitHub Copilot + Claude Sonnet を使って書き足したものです。文法はは F# なので、既存の生成 AI のモデルに学習結果が含まれています。このために、Fake の書き方も的確に書いてくれます。

vscode の拡張には、Ionide.Ionide-fsharp を入れておくと便利です。

ビルド&実機へのデプロイを試してみましょう。

fake build -t DeployToDevice

無事、ビルドとデプロイが終わると次のところまで表示がでます。

警告が出ていますが、無視して大丈夫です。

Warning: Paket resolved a FSharp.Core with version '9.0.0.0', but fake runs with a version of '8.0.0.0'. This is not supported.
Please either lock the version via 'nuget FSharp.Core <nuget-version>' or upgrade fake.
Read https://github.com/fsharp/FAKE/issues/2001 for details.

どうやら現在の環境が .NET9 なんですが、fake が .NET8 のままっぽいです。バージョンを 8 のほうに揃えれば出なくなると思いますが、これは後で。

Shell.Exec でコマンドを羅列して戻り値を見るだけなので、結構使えるはずです。難点は文法が F# なところですが、Powershell や sh をちまちま書くよりはいいかもしれません。

これは Android 版なのですが、次は Xcode で Swift 版のほうのビルドをしたいんですよね。Swift 版のほうは macOS で動かさないといけないので、VNC 経由でやるか、mac mini 用のマウスとキーボードを使うとかという処で結構面倒なのです。ビルドとテスト実行ぐらいならば windows から ssh 経由でやりたいところなので、ここはもう少し試してみる予定。

カテゴリー: 開発 | .NET開発者じゃなくても利用できるタスクランナー fake の勧め はコメントを受け付けていません