TECH PLAY

株式会社マイナビ デジタルテクノロジー戦略本部

株式会社マイナビ デジタルテクノロジー戦略本部 の技術ブログ

240

上記の動画では、 Figma Buzzを活用して「量産型バナー」を制作する方法 をご紹介しています。 「はじめての転職で何からはじめたらいいか分からない」というメッセージを軸に、テキストを差し替えた 50パターンのバナー を一括で生成しました。 テンプレートとスプレッドシートを連携させることで、効率的かつブランドに沿ったビジュアル制作が可能になります。 量産させたい基のバナーデザインがあれば、誰でも簡単に制作できるので、おすすめの手法です。 Figma Buzz 概要 Figma Buzzは、2025年のFigma Configで発表された、 非デザイナーでも手軽にブランドに沿ったビジュアルコンテンツを作成・管理・共有できる新機能 です。 特にマーケティングチーム向けに設計されており、効率的な制作を支援する多彩な機能が搭載されています。 現在はβ版ですが、誰でも無料で使用することができます。 主な機能 テンプレートベースの編集 ブランドガイドラインに沿ったテンプレートを活用し、誰でも簡単に編集・再利用可能。 テンプレートのロック機能 編集可能な部分だけを開放し、ブランドの一貫性を保ちながら安全にカスタマイズ。 AIによる画像生成 テキストプロンプトから画像を生成・編集できる機能を搭載。背景削除や色調補正も可能。 スプレッドシート連携による一括編集 CSVやExcelファイルを使って、複数のアセットを一括生成。SNS投稿や広告素材の大量制作に最適。 活用シーン Web・SNS向けの広告バナー イベント告知や社内報資料 誕生日カードや招待状などの個人向けコンテンツ Figma Buzzには様々な機能がありますが、今回は量産型バナーの制作方法について説明させていただきます。 量産型バナーの制作方法 ①マスターデザインの用意 まずは、Figma BuzzではなくFigma デザインで、量産したいバナーを作成します。 この段階で、今後一斉に変更する可能性がある要素(例:ボタンのテキストやカラーなど)がある場合は、この時にコンポーネント化( ⌥ + ⌘ + K )をしておいてください。これにより、後の修正や展開がスムーズになります。 ②Figma Buzzに移動 次に Figma Buzz を起動してください。 ホーム画面の上部には、各サービスのアイコンが並んでいるかと思いますので、そこから Figma Buzz を選択します。 Figma Buzzに移動すると、最初にテンプレート選択画面が表示されますが、こちらは画面右上の×で閉じることができます。 ③バナーをFigma デザインからFigma Buzzに移動 次にFigma デザインで作成したバナーを 切り取り でFigma Buzzに持ってきてください。 (コピーではコンポーネントが適用されないため) 2枚目のページ下部のナビゲーションをご覧いただくと分かるように、Figma Buzzでもデザインモードを使用することができます。 Figma デザインと比べると機能に制限はありますが、デザインの作成や編集は可能です。 なお、今回のバナーはFigma Buzzで直接作成することもできましたが、Buzzには コンポーネント機能が見当たらなかったため、まずはFigma デザインで作成する方法を選びました。 ④Excel形式のCSVファイルを用意 ここからは、バナーの量産作業に入ります。 まずは、テキストデータを管理するための CSVファイルをご用意ください。 CSVの構成は以下の通りです: ・1行目:任意のカテゴリ名(今回は「description」) ・2行目以降:実際にバナーに使用するテキストを記載 今回は「description」のみを使用しますが、例えば タイトルや画像もバナーに合わせて変更したい場合 は、列を追加することで、より柔軟な量産が可能です。 ⑤CSVファイルをアップロード データの作成が完了したら、Figma Buzzに戻ります。 1左側のナビゲーションメニューから 「 一括で作成 」 をクリックします(左下のグリッドアイコン)。 表示されたウィンドウで、先ほど作成した CSVファイルを選択し、「開く」を押してください。 データのインポートが完了すると、3枚目の画面のような一覧表示に切り替わるかと思います。 ⑥変更したいデータを選択 次に、バナーデザイン内で変更したい要素をクリックしてください。 今回は「はじめての転職で何からはじめたらいいか分からない」というテキストを編集したいので、まずはこのテキスト部分を選択します。 続いて、画面左側のパネルに表示されている 「description」 をクリックします。 これにより、バナー内のテキストとCSVファイル内の「description」列のデータが紐付けされます。 ⑦大量生成を実行 データの紐付けが完了すると、画面左側パネルの下部にある「〇〇件のアセットを作成する」というボタンが非アクティブからアクティブ状態に変わります。 このボタンをクリックすることで、CSVに登録されたデータをもとに、バナーが自動的に大量生成されます! 大量生成する前のデータの作成上の注意 テキストや画像の幅の設定について バナーを自動生成する際に、テキストの幅を設定していないと、改行されずに横に長く表示されてしまうことがあります。 そのため、マスターバナーを作成する段階で、テキストや画像の表示幅をあらかじめ設定しておくことが重要です。 一括変更をしたい箇所はコンポーネント化しておく バナーを大量に生成した後で、ボタンのテキストやタイトルなどを一括で変更したいというケースがあるかもしれません。 そのような場合に備えて、基のバナーの制作段階で、変更の可能性がある要素はコンポーネント化しておくことが重要です。 コンポーネント化しておくことで、マスターバナーを修正するだけで、生成済みのすべてのバナーにも自動的に変更が反映されます。 Figma Buzzを使ってみた感想 良かった点まとめ バナーの量産がとても効率的 CSVを使ってデータを流し込むことで、複数のバナーを一括で自動生成できるのは非常に便利でした。 手作業で1枚ずつ作成する必要がなくなり、作業時間と労力を大幅に削減できるかと思います。 先日参加したFigmaのイベント「Maker Collective Tokyo」でも、Figma Buzzを活用したバナーの一括生成が紹介されました。 そのデモでは、なんと 約2000枚のバナーをわずか数十秒で自動生成 しており、Figma Buzzの処理速度と実用性の高さに驚かされました。 Figmaらしい直感的な操作感 Figma デザインと同様のUIが採用されているため、初めて使った際も、迷わず操作できました。 データの紐付けが簡単 テキストや画像をCSVの列と紐付ける操作がとてもシンプルで、直感的に理解できました。紐付けが完了した後の自動生成もスムーズで、ストレスなく作業を進められました。 改善してほしい点 Buzzではコンポーネント機能が使えない? Figma デザインで作成したコンポーネントがBuzzでは編集できないようなので、量産したい基のバナーはデザイン側で行う必要があります。Buzz側でもコンポーネントが使えると、もっと便利になりそうです。 デザイン機能に一部制限あり Buzzのデザインモードは基本的な編集は可能ですが、Figma デザインほど自由度は高くない印象です。細かい調整は事前に済ませておくのがベスト。 Figma Buzzはまだβ版なので、上記については今後のアップデートに期待です!
GoでレイヤードアーキテクチャとDDD(ドメイン駆動設計)をどう実装しているかまとめます。 自分で考えて試している部分も多く、この構成でうまくいかない部分もあるかもしれません。その点ご認識ください。 レイヤードアーキテクチャについては下記が参考になります。 https://qiita.com/tono-maron/items/345c433b86f74d314c8d 例として部署情報(department)のCRUDについて書きます presentation層(interface) ├── presentation/│ ├── batch/│ │ └── job.go│ ├── external/│ │ └── client.go│ └── rest/│ ├── controller/│ │ ├── controllers.go│ │ ├── department.go│ │ └── router.go # openapi ルーティング定義 controllerとなっていますが、handlerでもいいと思います(この辺は好みです)。 controller実装例 package controllerimport ("main/application/usecase/department""main/presentation/rest/openapi""net/http""github.com/labstack/echo/v4")type DepartmentController interface {GetDepartment(c echo.Context) errorCreateDepartment(c echo.Context) errorUpdateDepartment(c echo.Context, departmentID int64) errorDeleteDepartment(c echo.Context, departmentID int64) error}type departmentController struct {departmentUseCase department.UseCase}func NewDepartmentController(departmentUseCase department.UseCase) DepartmentController {return &departmentController{departmentUseCase: departmentUseCase,}}func (ctrl *departmentController) GetDepartment(c echo.Context) error {ctx := c.Request().Context()departments, err := ctrl.departmentUseCase.GetAll(ctx)if err != nil {return echo.NewHTTPError(http.StatusInternalServerError, err.Error())}return c.JSON(http.StatusOK, departments)}func (ctrl *departmentController) CreateDepartment(c echo.Context) error {ctx := c.Request().Context()var req openapi.CreateDepartmentJSONRequestBodyif err := c.Bind(&req); err != nil {return echo.NewHTTPError(http.StatusBadRequest, "Invalid request body")}err := ctrl.departmentUseCase.Create(ctx, &req)if err != nil {return echo.NewHTTPError(http.StatusInternalServerError, err.Error())}msg := "Successfully created department"res := openapi.The200s{Code: http.StatusCreated,Message: &msg,}return c.JSON(http.StatusCreated, res)} APIの department/ に関するものはこのcontrollerにまとめています。 業務ロジックが大きい場合はAPI単位でcontrollerを分けてもいいと思います。 package名は集約または集約ルートごとに切る予定です。 DTOを使う場合はusecaseに渡す前に変換ロジックをここに書いてもいいですが、今回はopenapiで自動生成された型とDTOがほぼ同じだったのでopenapiの型をそのまま使っています。 ただし、usecase層がopenapi型に依存することになるので、DTOを設けてopenapi→DTOの変換を入れるのがベストです。 DDDは完璧にやりすぎると時間がかかるので、適宜調整が必要です あとエラーメッセージは後々まとめます application層 ├── application/│ ├── service/│ │ └── common.go│ └── usecase/│ └── department/│ ├── mapper.go # ドメインオブジェクト⇔DTOマッピング│ └── department.go 前のプロジェクトで、dto<->entityの変換ロジックを一ファイルにまとめると肥大化して分かりにくくなったため、マッピング用のファイルを設けています。 func ConvertCreateReqToEntity(req *openapi.CreateDepartmentJSONRequestBody) (*department.DepartmentEntity, error) {name, err := stringx.RemoveEmptySpaces(req.Name)if err != nil {return nil, err}return &department.DepartmentEntity{Name: name,}, nil} usecase実装例 package departmentimport ("context""main/domain/department""main/presentation/rest/openapi")type UseCase interface {GetAll(ctx context.Context) ([]*openapi.Department, error)Create(ctx context.Context, req *openapi.CreateDepartmentJSONRequestBody) errorUpdate(ctx context.Context, id int64, req *openapi.UpdateDepartmentJSONRequestBody) errorDelete(ctx context.Context, id int64) error}type useCase struct {departmentRepository department.Repository}func NewUseCase(departmentRepository department.Repository) UseCase {return &useCase{departmentRepository: departmentRepository,}}func (u *useCase) GetAll(ctx context.Context) ([]*openapi.Department, error) {entities, err := u.departmentRepository.GetAll(ctx)if err != nil {return nil, err}res := ConvertEntitiesToResponses(entities)return res, nil}func (u *useCase) Create(ctx context.Context, req *openapi.CreateDepartmentJSONRequestBody) error {entity, err := ConvertCreateReqToEntity(req)if err != nil {return err}err = u.departmentRepository.Create(ctx, entity)if err != nil {return err}return nil} CRUD処理は単一ファイルにまとめています。要件的に業務ロジックが少ないため肥大化しないと判断したため。 肥大化、大規模開発になる場合はCRUDごとにusecaseを分けるやり方もあります( 参考 )。 ですがこちらは作業量も増えるのでプロジェクトの要件や割けるリソースによると思います 今回はinterfaceを設けて単一ファイルにまとめています。 usecaseにはドメインロジックを書かないようにしています。 domain層 ├── domain/│ ├── department/│ │ ├── valueobject/│ │ ├── entity.go│ │ └── repository.go│ └── shared/│ ├── errors/│ │ └── domain_errors.go│ └── valueobject/│ ├── address.go│ └── money.go entity, valueobject, repositoryを集約ごとに配置。 複数集約にまたがるvalueobjectはshared配下に置いています。 repository interface package departmentimport ("context")type Repository interface {GetAll(ctx context.Context) ([]*DepartmentEntity, error)Create(ctx context.Context, entity *DepartmentEntity) errorUpdate(ctx context.Context, entity *DepartmentEntity) errorDelete(ctx context.Context, id int64) error} 基本的なCRUDはrepositoryのinterfaceとしてまとめています。 複数集約にまたがる検索等はCQRSを導入してquery serviceとしてまとめると保守性が高まります。 valueobject例 package valueobjectimport "fmt"type CategoryType uint8const (CategoryTypeUnknown CategoryType = 0 // 未分類 CategoryTypeA CategoryType = 1 // 種別A CategoryTypeB CategoryType = 2 // 種別B )func NewCategoryType(value int) (CategoryType, error) {categoryType := CategoryType(value)if !categoryType.IsValid() {return 0, fmt.Errorf("invalid CategoryType value: %d, must be between %d and %d", value, CategoryTypeUnknown, CategoryTypeB)}return categoryType, nil}func (t CategoryType) String() string {switch t {case CategoryTypeUnknown:return "Unknown"case CategoryTypeA:return "TypeA"case CategoryTypeB:return "TypeB"default:return "Unknown"}}func (t CategoryType) IsValid() bool {return t >= CategoryTypeUnknown && t <= CategoryTypeB} valueobject作成時にisvalidでバリデーションを強制しています。valueobject固有のロジックはここにおきます 例を挙げるなら文字数制限など valueobjectは複数あるのでフォルダを切りました。 複数集約にまたがる場合はdomain serviceにまとめるのが良いと思います。 entity例 package departmentimport ("time")type DepartmentEntity struct {ID int64 `json:"id,omitempty"`Name string `json:"name"`CreatedAt time.Time `json:"created_at"`UpdatedAt time.Time `json:"updated_at"`} DB駆動設計にならないよう、ドメインモデリングとテーブル設計は一致させないようにしています。 https://speakerdeck.com/pospome/liang-ikodonoding-yi-toshe-ji-neng-li-nobi テーブルはデータ保持のため、entityはコード上で使いやすいように最適化されるため、DBモデルとドメインモデルは分けて考えるべきです 例えば営業側から見た部署と管理者側から見た部署情報は違うため、entityを分けることも検討します こちらもわかりやすいと思います https://qiita.com/MinoDriven/items/2a378a09638e234d8614 entity固有のドメインロジックはこちらに書き足していきます infrastructure層 ├── infrastructure/│ ├── mysql/│ │ ├── conf/│ │ ├── db/│ │ ├── initdata/│ │ ├── migrations/│ │ └── department/│ │ ├── mapper.go # ドメインオブジェクト⇔ORMモデル変換│ │ └── repository.go ここにもmapperを用意し、ドメインオブジェクト⇔ORMモデルの変換関数をまとめています。 func ConvertModelToEntity(model *models.Department) *department.DepartmentEntity {if model == nil {return nil}return &department.DepartmentEntity{ID: int64(model.ID),Name: model.Name,CreatedAt: model.CreatedAt,UpdatedAt: model.UpdatedAt,}} repository (実体)実装 package departmentimport ("context""main/domain/department""main/infrastructure/models""gorm.io/gorm")type repository struct {db *gorm.DB}func NewRepository(db *gorm.DB) department.Repository {return &repository{db: db}}func (r *repository) GetAll(ctx context.Context) ([]*department.DepartmentEntity, error) {var models []*models.Departmentif err := r.db.WithContext(ctx).Find(&models).Error; err != nil {return nil, err}return ConvertModelsToEntities(models), nil} 依存性注入 package diimport ("main/application/usecase/department"departmentInfra "main/infrastructure/mysql/department""main/presentation/rest/controller""gorm.io/gorm")func Department(db *gorm.DB) controller.DepartmentController {departmentRepository := departmentInfra.NewRepository(db)departmentUsecase := department.NewUseCase(departmentRepository)return controller.NewDepartmentController(departmentUsecase)} 依存性注入を行うことにより各レイヤーが分離され単体テスト等がやりやすくなります wireを導入して自動でやるのもおすすめです CQRSやQuery Serviceについて 複数集約にまたがる検索や参照系の処理は、CQRSパターンを取り入れてQuery Serviceとして切り出すと保守性が高まります。 例えば「部署+ユーザー情報をまとめて取得し検索する」など、集約横断的な参照はdomain層のrepositoryではなく、application層のquery serviceで実装する方針です。 これにより、ドメインモデルの純粋性を保ちつつ、柔軟な参照要件にも対応できます。 最終的なディレクトリ構成例 backend/├── application/│ ├── service/│ └── usecase/│ └── department/│ ├── mapper.go│ └── department.go├── cmd/│ └── api/│ └── main.go├── configs/├── di/│ └── department.go├── domain/│ ├── department/│ │ ├── valueobject/│ │ ├── entity.go│ │ └── repository.go│ └── shared/│ ├── errors/│ └── valueobject/├── infrastructure/│ ├── models/│ ├── mysql/│ │ └── department/│ │ ├── mapper.go│ │ └── repository.go├── presentation/│ ├── batch/│ ├── external/│ └── rest/│ ├── controller/│ │ ├── controllers.go│ │ ├── department.go│ │ └── router.go│ └── openapi/ まとめ 業務ロジックやプロジェクト規模に応じて、controllerやusecaseの粒度を調整しています。 DTOやCQRS、Query Serviceの導入は、依存関係や保守性を考慮して適宜検討しています。 ドメインモデルとDBテーブル設計は一致させず、それぞれの役割に最適化するよう意識しています。 DDDは難しく、まだわからないことも多いです この構成は実際に試行錯誤しながら作ったもので、今後も改善していく予定です。 何かあればコメントの方よろしくお願いします 今すぐ「レイヤードアーキテクチャ+DDD」を理解しよう。(golang) - Qiita 役割駆動設計で巨大クラスを爆殺する - Qiita DDDはなぜ難しいのか / 良いコードの定義と設計能力の壁
はじめに マイナビジョブサーチのフロントエンド開発において、コードの可読性・保守性向上を目的としたリファクタリングを実施しました。本記事では、実際に行ったリファクタリング内容とその背景についてまとめています。 コンテナ・プレゼンテーションパターンを採用 これまでのコンポーネントは、UIとビジネスロジックが1つのコンポーネントに混在しており、1つのファイルのソースコード量が膨大であり可読性が悪かったです。その他にも、UIとビジネスロジックが同じファイルにあったため、UIとビジネスロジックをそれぞれ単体でテストすることが難しかったです。 そこで、メンテナンス性や拡張性を向上させるために、コンテナ・プレゼンテーションパターンを導入し、UIとビジネスロジックを明確に分離しました。 UI部分 Reactのコンポーネントで実装 ビジネスロジック部分 Reactのhooksや純粋関数で実装 /** Before */ export const Component = () => { const useHooks1 = () => { // } const useHooks2 = () => { // } const logic = () => { // } return ( <div> <h1>Component</h1> <p>Some content here...</p> <p>{ logic() }</p> </div> )}⬇️⬇️⬇️ /** After */ import { useHooks } from "./hooks/useHooks"import { logic } from "./services/someLogic"export const Component = () => {const { ... } = useHooks() return ( <div> <h1>Component</h1> <p>Some content here...</p> <p>{ logic() }</p> </div> )} このアプローチにより、1つのファイルあたりのコード量が減少し、可読性が高まりました。また、UIとビジネスロジックが明確に分離されたことで、各部分を独立してテストすることが容易になりました。 ディレクトリ構成の見直し ディレクトリ構成の見直しにより、各ディレクトリのルールが明確になり、ファイルの配置が整理されました。また、命名規則も統一することで、プロジェクト全体の可読性と一貫性を持たせるようにしました。 src/styles Before stylesディレクトリにグローバルで利用するスタイルのファイル(reset, variable, ...)と、一部コンポーネントのみでしか利用されないスタイルのファイルが混在していた After グローバルで利用するスタイルのファイルのみをこのディレクトリに置く 一部コンポーネントのみでしか利用されていなかったスタイルのファイルは、利用するコンポーネントフォルダに移動 /** Before */styles/ ├─ ComponentA ├─ ComponentB ├─ PageA ├─ PageB ├─ _variables.module.scss ├─ reset.scss ├─ ...⬇️⬇️⬇️/** After */styles/ ├─ _variables.module.scss ├─ reset.scss ├─ ... src/components Before 特定のファイルでしか利用されないコンポーネント、共通コンポーネント(ボタン、モーダルなど)として色々なファイルで使われるコンポーネントが混在していた After 共通コンポーネント(ボタン、モーダルなど)として色々なファイルで使われるコンポーネントのみをこのディレクトリに置く /** Before */components/ ├─ Button/ ├─ Modal/ ├─ Recruit/ ├─ JobDetail/ ⬇️⬇️⬇️/** After */components/ ├─ Button/ ├─ Modal/ src/features 今回のリファクタリングで新しく作成したディレクトリであり、Reactのアーキテクチャの1つである Bulletproof-react を参考にして取り入れました。 特定のファイルでしか利用されないコンポーネントをこのディレクトリに置くことで、共通コンポーネントと特定のファイルでしか使われないコンポーネントの棲み分けをした 機能(LayoutTop, JobDetail)フォルダ内に関連するコンポーネントを作成し、機能単位で管理する features/ ├─ LayoutTop/ ├─ Navigation/ ├─ index.tsx ├─ Navigation2/ ├─ index.tsx ├─ ... ├─ JobDetail/ ├─ JobDetail1/ ├─ index.tsx ├─ JobDetail2/ ├─ index.tsx ├─ ... src/apps 今回のリファクタリングで新しく作成したディレクトリ Before Pages Routerのpagesディレクトリにはtsxファイル(jsxファイル)以外は置けないため、スタイルのファイルやビジネスロジックのファイルが色々なディレクトリに置かれていた After src/appsディレクトリのコンポーネントはプレゼンテーションコンポーネントとして利用し、pagesディレクトリのファイルはコンテナコンポーネントとしてデータをpropsを通じて渡す pagesディレクトリに置けなかったスタイルのファイルやビジネスロジックのファイルを、コンポーネントとして必要なファイルをまとめて配置 /** Before */pages/ ├─ search.tsx styles/ ├─ search.modules.scss hooks/ ├─ useSearchHooks.ts⬇️⬇️⬇️/** After */apps/ ├─ Search/ ├─ hooks/ └─ ** ├─ services/ └─ ** ├─ index.tsx ├─ styles.modules.scsspages/ ├─ search.tsx // pages/search.tsx import { Search } from "apps/Search"const Page: NextPage<Props> = ({ props1, props2, props3}) => { return ( <Search props1={props1} props2={props2} props3={props3} /> );};export default Page; コンポーネントディレクトリの構成 コンポーネントのディレクトリ構成やファイルの命名がコンポーネントによってバラバラだったため、ファイルの配置や命名規則を統一しました。 Before 特定のコンポーネントのみでしか利用されない スタイルのファイルやビジネスロジックのファイルがコンポーネントディレクトリとは別ディレクトリに散らばっていた コンポーネントのフォルダに入っていたり入っていなかったりとバラバラ コンポーネントのファイル名とスタイルのファイル名がコンポーネント名になっていた After - コンポーネントフォルダをキャメルケースで命名し、その中にファイルを格納 - コンポーネントのファイル名を「index.tsx」、スタイルのファイル名を「styles.modules.scss」に統一 - UIとビジネスロジックを分離したため、ビジネスロジックを置くフォルダを新しく作成 - カスタムフックは「hooks」フォルダに置く - 純粋関数は「services」フォルダに置く /** Before */styles/ ├─ ComponentA.modules.scss components/ ├─ ComponentA.tsx ├─ ComponentB/ ├─ ComponentB.tsx └─ ComponentB.modules.scss⬇️⬇️⬇️/** After */components/ ├─ ComponentA/ ├─ hooks/ └─ ** ├─ services/ └─ ** ├─ index.tsx └─ styles.modules.scss ├─ ComponentB/ ├─ index.tsx └─ styles.modules.scss コンポーネントファイル(index.tsx)のルール コンポーネントの型指定 コンポーネントのPropsの型指定は、React.FCを使用し、Propsの名前を利用する場合はコンポーネント内でのみ使用する コンポーネントを定義する際はReact.FCを使用し、React.VFCは使用しないこと Propsの取得方法 Propsは分割代入を用いて取得する const Component: React.FC<Props> = ({ prop1, prop2, prop3 }) => { // } コンポーネントのエクスポート方法 コンポーネントのエクスポートは、default exportではなく、named exportを使用する export const Component: React.FC<Props> = ({ prop1, prop2, prop3 }) => { // } コードまとめ 以下は、上記のルールに従ったコンポーネントの例 export const Component: React.FC<Props> = ({ prop1, prop2, prop3 }) => { return ( <div> <p>{prop1}</p> <p>{prop2}</p> <p>{prop3 ? 'True' : 'False'}</p> </div> );} コンポーネントのビジネスロジックディレクトリ(hooks, services)の構成 ビジネスロジックディレクトリ(hooks, services)は、今回のリファクタリングで新しく作成したビジネスロジックを管理するためのディレクトリです。このディレクトリでは、ビジネスロジックを整理し、再利用性を高めることを目的としています。 hooksディレクトリ このディレクトリは、カスタムフックを管理する useHooks.tsとuse**.tsの分割 useHooks.ts 複数のカスタムフック(use**.ts)のビジネスロジックをまとめて管理し、将来的にビジネスロジックが増えることを考慮し、拡張性を持たせている インポートしたカスタムフックは、スプレッド構文を用いて返すことで、各フックのプロパティを一つのオブジェクトとしてまとめて利用している import { use**1 } from "./hooks/use**1"import { use**2 } from "./hooks/use**2"export const useHooks = (({param1, param2, param3}: Params or **Params)) => { return { ...use**1(), ...use**2(), };}; use**.ts use**.ts各カスタムフックは、ビジネスロジックが干渉しないもの同士で切り分けることによって、関連しているビジネスロジックが明確になる export const use** = (({param1, param2, param3}: Params or **Params)) => { // }; 引数の型指定 引数の型指定を行う際には、Propsという名前を避け、Paramsや**Paramsなどの名前を使用する // useHooks.ts export const useHooks = (({param1, param2, param3}: Params or **Params)) => {} // use*.ts export const use** = (({param1, param2, param3}: Params or **Params)) => {} 利用方法 useHooks.tsを、コンポーネントやページでインポートして利用する ├─ Component/ ├─ hooks/ └─ useLoading.ts └─ useRelaod.ts └─ useCalc.ts └─ useHooks.ts ├─ index.tsx import { useHooks } from "./hooks/useHooks"export const Component = () => { const { ..., ..., ...} = useHooks() return ( // // // )} useHooks.tsとuse**.tsに分割することで、各ファイルのコード量を削減できるだけでなく、ファイルごとにビジネスロジックが明確になるため、可読性と保守性が向上するようになりました。 servicesディレクトリ このディレクトリは、Reactの機能を利用しない純粋関数のビジネスロジックを管理する 利用方法 servicesディレクトリに作成した純粋関数のビジネスロジックをコンポーネントやページでインポートして利用する。 hooksディレクトリとは違い、1つのビジネスロジックのファイルにまとめて管理はしない ├─ Component/ ├─ services/ └─ calcUtils.ts ├─ index.tsx import { CalcUtils } from "./services/calcUtils.ts"export const Component = () => { return ( // // )} カスタムフックと純粋関数のビジネスロジックを分けることで、再利用性、テストの容易さ、依存関係が管理しやすくなりました。 まとめ 本記事では、マイナビジョブサーチのフロントエンド開発におけるリファクタリングの取り組みについて紹介しました。主なポイントは以下の通りです。 UIとビジネスロジックの分離 UIとビジネスロジックを1つのファイルから分離することで、コードの可読性が向上しました。これにより、各部分の役割が明確になり、理解しやすくなりました。 ビジネスロジックはカスタムフックや純粋関数として管理され、UI部分はReactコンポーネントとして実装されることで、各部分のテストが容易になりました。 コンテナ・プレゼンテーションパターンの導入 コンテナ・プレゼンテーションパターンを採用することで、UIとビジネスロジックを明確に分離し、メンテナンス性や拡張性を向上させました。このアプローチにより、コードの構造が整理され、各コンポーネントの役割が明確になりました。 ディレクトリ構成の見直し ディレクトリ構成を見直し、ファイルの配置や命名規則を統一することで、プロジェクト全体の可読性と一貫性が向上しました。特に、共通コンポーネントと特定のファイルでしか使われないコンポーネントの棲み分けができたことで、管理が容易になりました。 再利用性とテストの容易さ カスタムフックと純粋関数のビジネスロジックを分けることで、再利用性が高まり、テストの容易さが向上しました。特に、純粋関数は副作用がないため、単体テストが簡単に行えるようになりました。 管理の効率化 バラバラに置かれていたファイルをコンポーネントとしてまとめて配置できるようになり、開発者が必要なファイルを見つけやすくなりました。 このリファクタリングを通じて、コードの可読性、保守性、テストのしやすさが向上しました。 もし参考になる内容がございましたら、ぜひご活用いただければと思います。
「こんな機能があったなんて...」 Amazon Q Developerを使い始めて数週間。基本的な質問応答は慣れたけど、実はドキュメントに載っている便利な機能を見落としていませんか? 「もっと早く知っていれば、あの無駄な時間は何だったんだ...」 そんな後悔をしないために、便利機能を厳選してご紹介します。 /editor  : 複数行入力の救世主 /editor 効果: vim/VSCodeのエディタが起動! • マウス操作対応: クリックで自由にカーソル移動 • 複数行安心入力: 誤送信の心配なし • 快適な編集: コピペ、選択、削除が思いのまま • エディタ選択可能: 自分の好みに合わせてエディタを設定できます ( export EDITOR="code --wait" でVSCodeが利用可能) chat -r  : 昨日の続きから即座に再開 こんな経験ありませんか? •  昨日の作業の続きをしたい のに、前回の会話を忘れている • SSOの 認証が切れて突然ログアウト 、会話が消えた... • 引継ぎ用のメモを作るのが面倒 便利なオプション q chat -r 効果: 前回の会話の続きから作業開始!引継ぎファイル不要! 注意点: 会話履歴は 実行ディレクトリごと に保存されます。常に同じ場所でq chatを実行する習慣をつけましょう。 /compact  : 推論能力をリフレッシュ 「なんか最近、AIの回答が微妙...」 長時間の会話で推論能力が下がってきた?そんな時は: /compact さらに、要約方法も指定可能: /compact summary /compact key-points /compact action-items 効果: 会話をスッキリ整理して、AIの思考をリセット! /model  : 一瞬でAI性能アップ 旧モデル: Claude 3.7 高性能版: Claude 4.0 /model /context  : ファイルを明示的にコンテキスト追加 通常: ファイルの内容を毎回コピペ スマート:  /context で一発追加 /context add path/to/important-file.py メリット: • 大きなファイルも楽々参照 •  フォルダ単位での一括追加 も可能 • 複数ファイルの関連性を理解 • コピペミスを防止 !{command}  : ターミナル不要の魔法 チャット内の機能です。 従来: ちょっとコマンドを実行したい時 → ターミナルを開く 新しい方法: !ls -la !git status !npm install 効果: ちょっとしたコマンド実行のためにターミナルを開く手間が不要!チャット内で完結! まとめ /editor  → 長文入力が劇的に快適に chat -r  → 明日から継続作業が楽に /compact  → 長時間作業時の救世主 /model  → 即座に性能アップを体感 /context  → 大規模開発での必須機能 !{command}  → 作業効率の劇的改善 「知らないともったいない」機能たち これらの機能を活用しているかどうかで、開発効率に 大きな差 が生まれます。 今日から使い始めて、開発をもっと快適にしましょう! 「もっと早く知りたかった...」を「知っててよかった!」に変える、Amazon Q Developer活用術でした。
Q Developer 会話履歴継続を完全自動化 「また -r オプション忘れた...」 と思った経験ありませんか? 組織のSSO設定で認証情報が永続化できない環境では、毎回ログインが必要な上に、会話履歴の継続も忘れがちです。 そこで、チャットやログインの処理を expect で自動化、 qq コマンドを作成してみました。 •  -r  オプションを自動で付与、 会話履歴の継続忘れを防止 • ログイン時の エンター連打も完全自動化 • デバイス認証URLを 自動でブラウザオープン ※Ubuntuでのインストールが前提です。 ※組織固有のパラメータは <HOGEHOGE>  でマスクしています。 #!/bin/bash# =============================================================================# Q Developer CLI 自動セットアップスクリプト# # 目的: Q Developer CLIのログインとチャット起動を完全自動化# 課題: 組織の制約により認証情報の永続化が不可能なため、毎回ログインが必要# 解決: expectコマンドによる対話自動化とブラウザ自動オープン## 使用方法:# 1. このスクリプトを任意のディレクトリに配置# 2. 実行権限を付与: chmod +x qq# 3. PATHに追加してどこからでも実行可能にする:# echo 'export PATH="$PATH:/path/to/script/directory"' >> ~/.bashrc# source ~/.bashrc# 4. qqコマンドで実行# =============================================================================echo "🚀 Q Developer セットアップ中..."echo "📋 スクリプトバージョン: v5.3-dependency-check ($(date '+%Y-%m-%d %H:%M:%S'))"# 依存関係チェックecho "🔍 依存関係を確認中..."missing_commands=()# Amazon Q Developer CLI の確認if ! command -v q >/dev/null 2>&1; then missing_commands+=("Amazon Q Developer CLI (q)")fi# expect コマンドの確認if ! command -v expect >/dev/null 2>&1; then missing_commands+=("expect")fi# xdg-open コマンドの確認if ! command -v xdg-open >/dev/null 2>&1; then missing_commands+=("xdg-utils")fi# 不足しているコマンドがある場合は警告して終了if [ ${#missing_commands[@]} -gt 0 ]; then echo "❌ 以下のコマンドがインストールされていません:" for cmd in "${missing_commands[@]}"; do echo " - $cmd" done echo "" echo "📦 以下の方法でインストールしてください:" echo "" for cmd in "${missing_commands[@]}"; do case $cmd in "Amazon Q Developer CLI (q)") echo "• Amazon Q Developer CLI (q):" echo " 公式サイトでインストール方法を確認してください" echo " https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-installing.html" echo "" ;; "expect") echo "• expect:" echo " sudo apt install expect" echo "" ;; "xdg-utils") echo "• xdg-utils:" echo " sudo apt install xdg-utils" echo "" ;; esac done echo "インストール完了後、再度このスクリプトを実行してください。" exit 1fiecho "✅ 依存関係チェック完了"# エディタ設定# Q Developer CLIがファイル編集時に使用するエディタを指定# VS Codeの--waitオプションでCLIがエディタ終了まで待機するためexport EDITOR="code --wait"echo "✅ エディタ設定完了: $EDITOR"# ログイン状態を確認# 既にログイン済みの場合は不要な処理をスキップして効率化echo "🔍 ログイン状態を確認中..."if q whoami >/dev/null 2>&1; then echo "✅ 既にログイン済みです"else echo "🔑 ログインが必要です。Proライセンスでログインします..." # expectを使用して自動ログイン(最長URL選択でブラウザ自動オープン) # Q Developer CLIのログインは対話型で手動エンター入力が必要 # 組織制約により認証の永続化ができないため、毎回の自動化が必須 expect -c " # タイムアウト設定 # ネットワーク遅延やブラウザ認証待ちを考慮した十分な時間を確保 set timeout 120 # URL重複オープン防止フラグ # 複数のURLが出力されるため、デバイス認証URLを1回のみ開くため set url_opened 0 # Q loginコマンドを起動 spawn q login --license pro --identity-provider https://<HOGEHOGE>.awsapps.com/start --region ap-northeast-1 --use-device-flow expect { # エンター入力待ちパターンの自動処理 # ログイン過程で複数回のエンター入力確認があるため \"Press Enter\" { send \"\r\" exp_continue } \"continue\" { send \"\r\" exp_continue } \"Enter\" { send \"\r\" exp_continue } # URL検出とブラウザ自動オープン # デバイス認証URLを手動でコピペする手間を省くため -re \"(https://\\\\S*)\" { # 重複防止チェック # 複数のURL(ベースURLと完全なデバイスURL)が出力されるため if {\$url_opened == 0} { set current_url \$expect_out(1,string) # 最長かつデバイス認証URLのみを対象とする条件判定 # 不完全なベースURLではなく、完全なデバイス認証URLのみを開くため # URL形式の変化に対応するため、複数の判定条件を設定 if {[string length \$current_url] > 50 && ([string match \"*device*\" \$current_url] || [string match \"*user_code*\" \$current_url] || [string match \"*#/*\" \$current_url])} { puts \"🌐 ブラウザでURLを自動オープン: \$current_url\" # バックグラウンドでブラウザ起動 # ブラウザ起動でスクリプトがブロックされないようにするため exec xdg-open \$current_url & # フラグを立てて以降のURL処理をスキップ # 同じURLや他のURLの重複オープンを防ぐため set url_opened 1 } } exp_continue } # 正常終了処理 eof { puts \"ログイン処理が完了しました\" } # タイムアウト処理 # ネットワーク問題や認証遅延時の無限待機を防ぐため timeout { puts \"タイムアウトしました\" exit 1 } } " # ログイン成功確認 # expectスクリプトが正常終了してもログインが失敗している可能性があるため if q whoami >/dev/null 2>&1; then echo "✅ ログイン完了" else echo "❌ ログインに失敗しました" exit 1 fifi# Q Chat を再開モードで起動# 前回の会話履歴を継続して効率的な対話を実現するため# Claude 4 Sonnetモデルを明示的に指定して一貫した応答品質を確保するためecho "✅ Q Chat をClade4で起動します..."q chat -r --model claude-4-sonnet ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ もう「あ、また-rオプション忘れた」「エンター何回押すんだっけ」と悩む必要はありません。 qqと打つだけで、すべてが自動で完了します。 小さな自動化が、毎日の開発体験を大きく変えてくれるはずです。
弊社では、2024年10月からGitHub Copilotの導入を行いました。 本記事では、導入までの過程とその過程で調査した内容についてお伝えしたいと思います。 本記事でわかること 導入までにした作業内容 GitHub Copilot導入検討段階で何を調査したのか 導入までにした作業内容 まず、導入までのどのような流れで、作業を行っていたのかについて説明します。 主に以下の手順で進めました。 検証メンバーの招集 検証を実施し、導入可否を決定 運用に関するフロー作成とステークホルダーの洗い出し 費用に関わる請求先の整理 1.検証メンバーの招集 課長から課員に対して、検証プロジェクトについてお伝えしていただいて、そこで興味のある方をアサインしました。 2.検証を実施し、導入可否を決定 リスク調査から始め、GitHub Copilotを有効化して使用してもらい、感想や作業削減時間等を記録していただきました。その調査結果をもとに費用対効果をまとめて、導入可否を上司に報告する流れを取りました。 3.運用に関するフロー作成とステークホルダーの洗い出し 導入後は、利用申請フローの確立やCopilotのシート有効化フローについて手順を整理しました。 社内の決裁ツールでの利用管理方法を考え、決裁フローを作成し、これらの各フローを誰が担当するのかも整理しました。 4.費用に関わる請求先の整理 弊社の事情により、請求先を細かく設定したいという要求がありました。これについては、「 コストセンター 」を用いることで、GitHub Copilotの費用に関して、特定の請求先に紐づけるようにしました。 以上の内容が大まかに行った作業になります。 「2.検証を実施し、導入可否を決定」の作業は、どこの会社でも行われることだと思います。 ですので、次章ではその調べた内容について、記載します。 導入する際の課題 導入する前に検討する事項として、「リスク」と「費用対効果」があると思います。 リスクには、生成AIの問題点である著作権侵害やそれによる訴訟リスクなどがあります。 効果については、生成AIの導入費用が削減効果を上回っているかを判断します。 リスク 生成AIにはリスクがあり、導入する際には調べる必要がある項目があります。 弊社では、以下の5つの項目を調査しました。 著作権侵害 情報流出 脆弱性コード生成 海外保管 訴訟補償 調査の結果から、GitHub Copilot上の設定を適切に行えば、これらのリスクは避けられると考えております。 1.著作権侵害 著作権侵害は、「Suggestions matching public code (duplication detection filter)」を有効化することにより、生成を防ぐことができると考えております。 Public Code Suggestion Filterは、公開リポジトリに含まれるコードが生成された場合に補完や提案結果から排除してくれる機能です。 この機能が有効化されていれば、著作権侵害のリスクは低いと判断しました。 なお、この機能については、企業向けのプランであるCopilot BusinessとCopilot Enterpriseではデフォルトで有効化されています。 2.情報流出 情報流出は、GitHub公式ページにて「Copilot Business」と「Copilot Enterprise」プランではデータを学習に利用しないことが明記されていました。 3.脆弱性コード生成 脆弱性コード生成は、GitHub Copilotにフィルターが存在し生成されないようになっているようです。 こちらのページ に、「安全でないコードパターンをリアルタイムで防止するAIベースの脆弱性フィルタリングシステムが組み込まれている」と記載されていました。 4.海外保管 海外保管は、社内のセキュリティ部署に問い合わせた結果、社内の規定に則っていることを確認し問題ないと判断いたしました。導入する際には、貴社の規定を確認いただけますと幸いです。 5.訴訟補償 訴訟補償は、訴訟補償の対象となる条件として「Suggestions matching public code (duplication detection filter)」を有効化していることが条件でした。 Microsoft社に問い合わせを行い確認し、これらの条件を満たせば、訴訟補償の対象になるとのことです。(2024年8月:問い合わせ) 以上の調査結果から、リスクについては適切な設定を行えば避けられるとの結論に至りました。しかし、リスクについて避けられたとしても、ツールとして導入するためには、費用対効果が得られないものは導入できません。 次の節では、費用対効果を求めた過程についてお伝えします。 費用対効果 導入するためには、費用対効果を考慮する必要があります。導入にはお金がかかりますが、それを上回る効果があれば良いと考えられます。 弊社では、予測作業時間から実際にどの程度削減できたのかを記録しました。また、削減時間から削減コストを計算し、費用対効果があるのかを判断しました。 削減時間の記録は、以下の項目を調査者に記録していただきました。 プロジェクト名 作業内容:新規コード作成・テストコード作成・コードリーディング・設計の中から選択 使用言語 Copilotの機能で何を用いたか:コード補完・Copilot Chat等 作業時間 作業削減時間:特定作業において、予測した作業時間からどの程度削減できたのかを記載 以上の項目を1ヶ月間取得し、一人当たり2.2時間/月のコスト削減が見込める結果となりました。 具体的な記録内容については表に記載しております。 比較的定型な記述の多い、テストコード作成にて大きな効果を得られました。 作業内容 作業時間(分) 削減時間(分) 削減割合 新規コード作成 3,480 507 14.6% テストコード作成 1,385 282 20.4% コードリーディング 180 20 11.1% 設計 160 44 27.5% 以上の結果をもとに費用対効果を算出しました。 費用対効果を算出する方法としては、 他社さんの記事 を参考にさせていただきました。 具体的に算出した値については、以下の表に示した通りです。 算出項目 算出値 時給(仮定) 3,000円 削減コスト/人 2.2h × 3,000円 = 6,600円 統括部全体の削減コスト 6,600 × 92 = 607,200円 Copilot導入費用 270,940円 費用対効果 607,200 - 270,940 = 336,260円 削減効果としては、毎月30万円程度の削減が見込める結果となり、導入に至りました。 まとめ 本記事では、導入する際に調査を行った内容についてまとめました。 導入プロセスは、検証メンバーの招集から始まり、リスク調査を経て導入可否を判断。 その後、運用フローの作成や費用請求先の整理を行う流れとなりました。 リスク調査では、著作権侵害や情報流出、脆弱性コード生成などのリスクを評価し、適切な設定でこれらを回避できると結論づけています。 費用対効果の検討では、作業時間の削減を記録し、月あたり一人当たり2.2時間のコスト削減を確認されました。 結果として、毎月約30万円の削減効果が見込めることから、GitHub Copilotの導入を決定するに至りました。 最後に 最後までお読みいただき、ありがとうございます。 最後に私自身がこのプロジェクトを通して学んだことを記載します。 このプロジェクトでは、初めてリーダーとしての役割を担いました。 普段のエンジニアとしての経験とは異なる多くの貴重な学びがありました。 手順が未確定な状況で、自ら調査し手順を策定し、他のメンバーに指示する難しさ 調査結果を整理し、上層部への報告を行うこと 社外の方々に疑問を問い合わせたり、会議を設定し議論を進めること この経験を通じて、「物怖じせずに積極的に行動することの重要性」を学びました。 以前は、自分の意見を発言することが少なかったのですが、リーダーとしての役割を果たす中で、何か行動することに対する不安が軽減されました。この経験は、他のプロジェクトにも良い影響を与えていると感じています。 具体的には、ステークホルダーへの提案回数の増加や、アジャイルや技術について学んだことをチームと共有し、PMに意見を求める機会を自ら設けるようになりました。 このプロジェクトを通じて得た経験は、今後の成長に繋がる貴重な財産だと感じております。 今後もこの経験を糧に、さらなる成長を目指して邁進していきます。
こんにちは。UXデザイン1課のAです。 先日、Figma主催のオンラインイベント「Dev Modeベーシックウェビナー」に参加しました。 実際に参加してみて、Figmaの「Dev Mode」を活用することで、デザイナーと開発者の連携がよりスムーズになり、業務の効率化にもつながると感じたので、共有させていただきます。 イベント概要 先日参加したFigma主催のオンラインイベント「Dev Modeベーシックウェビナー」では、Figmaの新機能である「Dev Mode」の基本的な使い方や、デザインから開発へのハンドオフをよりスムーズに行うための実践的なヒントが紹介されました。 ※当日の内容は録画されており、後日YouTubeでも公開予定とのことです。 本記事で紹介する内容 実際にイベントへ参加してみて、Dev Modeを活用することでデザイナーと開発者の連携がよりスムーズになると感じました。本記事では、特に印象に残ったポイントをご紹介します。 デザイナーが完成したデザインを開発者に引き渡す際に活用できる「Dev Mode」について 開発者が受け取ったデザインをどのように扱うのか、その連携方法や活用のコツ Dev Modeの利用条件 まず、Dev Modeを使うための基本的な前提を整理しておきます。 利用できるプラン Dev Modeは Professionalプラン以上で利用できます。 ただし、開発者として招待されたユーザーは無料で利用できる場合があります(ファイルのオーナーやデザイナーが有料プランの場合)。 アクセス権限 対象のFigmaファイルに、閲覧権限または編集権限が必要です。 対象ファイル Designファイルのみで利用できます(※FigJamファイルは対象外)。 まずは、デザイナーが完成したデザインを開発者に引き渡す際に活用できる機能についてご紹介します。 ステータス管理と通知機能 デザインと開発の担当が分かれている場合、開発者側が「このデザイン、もう実装していいのかな?」と判断に迷うことがよくあります。 都度確認するのも手ですが、Dev Modeの「ステータス管理機能」を使えば、そのやりとりを少し減らせるかと思います。 Dev Modeでは、デザインごとに「開発準備完了」のステータスを設定でき、開発者が現在の進捗をひと目で把握できるようになります。ステータスを「開発準備完了」に設定しておくことで、そのデザインが実装しても問題ない状態であることを明示できます。 ※BusinessやEnterpriseプランでは、さらに「完了済み」「変更済み」などの詳細ステータスも設定可能です(今回は割愛します)。 ステータス変更の方法 Figmaの下部ツールバーの  </>  ボタンをクリック、または  Shift + D で Dev Modeに切り替え。 画面右上のステータスボタンから「開発準備完了」を選択。 デザインファイル全体だけでなく、各セクションごとにもステータスを設定できるため、ページ単位・画面単位での進捗管理や、一部だけ実装OKといった柔軟な運用も可能です。 また、ステータス変更時にはFigma内通知、メール、Slackなど外部連携ツールを通じて通知されるため、見落とし防止にもつながります。 測定値とアノテーションの追加 デザインにおいて「ここの余白、絶対見逃さないで!」というようなポイントを、視覚的に明示できるのがこの2つの機能です。 測定値(Measurement) 余白や距離、サイズ感などを開発者に伝えたいときに使用します。 使用方法 Dev Mode → ツールバーから「測定」を選択、または  Shift + M 。 レイヤーにカーソルを合わせ、測定したい開始・終点をドラッグで指定。 アノテーション(Annotation) 補足説明や重要な仕様を、付箋のようにデザイン上に直接記載できます。 使用方法 Dev Mode → ツールバーからアノテーションを選択、または  Shift + T 。 任意のレイヤーを選び、アノテーションを追加。 アノテーションで設定できる内容: カテゴリ(開発・インタラクション・アクセシビリティ・コンテンツ) 注釈文(例:「ホバー時にテキストが太字になります」) プロパティ(選択したレイヤーのスタイル情報など) このように「ステータス管理」や「測定値・アノテーション機能」を活用することで、 「ホバー時のフォントは太字になります」「この余白は絶対に守って!」といった情報のやりとりの軽減や見逃し防止につながるかなと思いました。 デザイン観点から大きく二つの機能を紹介させていただきましたが、 ステータス管理については、変更できるステータスが「開発準備完了」のみなので、 BusinessやEnterpriseプランに入っている人向けの機能かなと感じました。 次に、開発者がデザインを受け取った後、「Dev Mode」を活用してどのように扱うかについてご紹介します。 デザインスペックの取得 デザインファイルを Dev Mode( Shift + D ) に切り替えることで、Figma標準のサンプルコードから、実装に必要なさまざまな情報を簡単に取得できます。 サイズ・位置・余白(Spacing) 要素の幅・高さ・座標などの詳細を確認ができます。 他の要素とのマージンやパディングも視覚的に把握できます。 カラー・フォント・タイポグラフィ 使用されているカラーコード(Hex/RGB)が確認できます。 フォントファミリー、サイズ、行間、ウェイトなど、テキストスタイルに関する詳細情報も取得できます。 CSS・iOS・Android向けコードのスニペット 選択した要素に対応するコード(CSS、Swift、XMLなど)が自動生成されます。 色や余白、フォントなど、実装に必要なスタイル情報をコピー&ペーストでそのまま活用できます。 アセットのエクスポート アイコンや画像などのアセットを、SVG・PNG・PDFなどでダウンロードすることができます。 解像度やファイル形式も用途に応じて選択できます。 コンポーネントとインスタンスの関係把握 「メインコンポーネントと比較」機能により、メインコンポーネントとの違いや変更点を明確に確認できます。 Dev Mode × VS Code 連携のメリット Visual Studio Codeを利用している場合は、拡張機能「Figma for VS Code」を導入することで、Figmaのデザインとエディタを直接連携させることができます。 この拡張機能により、先ほどご紹介したデザインスペックの確認がVS Code上で可能となり、Figmaとエディタ間を何度も行き来する必要がなくなります。 また、Figmaのビジネスプランおよびエンタープライズプランをご利用の方は、Figmaのデザインコンポーネントと、GitHub上の実際のコードを紐づけて管理することができる「Code Connect」も使用できます。 Figmaは今後、このCode Connectの機能強化をさらに進めていく方針です。詳細は以下の公式ヘルプページをご確認ください:   Code Connectの詳細はこちら まとめ:デザインと開発をつなぐ「Dev Mode」の価値 今回のウェビナーを通じて、FigmaのDev Modeが**デザインから開発への“橋渡し”**を強化してくれるツールであると改めて感じました。 実装ミスの予防 開発スピードの向上 コミュニケーションコストの削減 これらに貢献するDev Modeは、今後さらに活用の幅が広がるのではないかと思いますが、 今後はさらにDev Modeを活用し、チーム全体で「デザインと開発の一体化」をどう進めていくかがポイントになりそうです。 また最近耳にすることが多くなってきたコード生成AIについては、特に今回のウェビナーでは、 触れられませんでした。 以上、Figma「Dev Modeベーシックウェビナー」からの学びをお届けしました。
TSKaigi2025 TSKaigi2025 「学び、繋がり、”型”を破ろう」をテーマに、TypeScript に関するあらゆるテーマを扱う国内最大級のカンファレンスとして、まさに「型破り」なイベントを目指し成長を続けるカンファレンスです。 朝から夕方までTypeScriptについての講演があり、事前に自分が気になるセッションを聞きに行く方式でした。 開催日 2025/05/23、2025/05/24 印象に残ったセッション SignalとObservable―新たなデータモデルを解きほぐす AI Coding Agent Enablement in TypeScript TypeScriptとは何であって何でなく、誰のもので、どこへ向かうのか TS特化Clineプログラミング Pragmatic Functional Programming in TypeScript 付録: TSKaigi2025の発表資料まとめ 内製開発業務にどのように活かすか 【難易度_易】Panda CSSは継続して採用していきたい マイナビでもLocusで採用されたPanda CSS、他者も業務レベルで使い始めている 補足① TailwindからPanda CSSへの完全移行ガイド 【I難易度_易】フルスタックTypeScriptの案件の比率を増やすのもあり GraphQLを活用しまずはサブシステムとして使い始めてもいい 【難易度_易】 type-challenges でTypeScript技術力養成 勉強会、もうこれでいいのでは 【難易度_中】 スキーマ駆動開発、はじめました の潮流でバックエンドテストも正していきたい(Railsならcommitteeなど) TSKaigiと言いつつスキーマ駆動の話があったので、内製採用率の高いRailsではどうやって行こうという観点 【難易度_中~高】部署間連携で生産性向上(例. Figma MCPなど) TSKaigiと言いつつFigmaMCPからのコード生成の話があったので、これやるなら生産性向上のためにUXDとかと部門間連携必要 本題 組織開発という目線でみたカンファレンスのレポート 2024年に産声をあげ、昨年同様大盛況のうちに幕を閉じたTSKaigi2025。 公式のカンファレンス概要に書いてある通り、TSKaigiは非常に若いカンファレンスイベントです。 RubyKaigiの第一回が2006年、PHPカンファレンスは2000年、GoConはちょっといつからか分からないですが2013年くらいからはあるはず。とまぁこんな感じで若いイベントです。 GOが2009年生まれTypeScriptが2012年生まれとほぼ同期なので、イベント発足が遅めなのが分かります。connpassのイベントを遡って調べてもまあ2015年くらいからチラホラとサブタイトル的にイベントがあったくらいです。 (*生まれの2012から自分が新卒で入るまでの時間軸で絞り込んだのと、npm trendsで2016年くらいをマウスオーバー。) 出典: connpass - エンジニアをつなぐIT勉強会支援プラットフォーム 出典: typescript | npm trends TypeScriptがここまでの一大勢力になったのは静的型付け機能もありますが、ReactやVueやAngularの勢力が後押ししているのは間違いないと思います。 これはどの言語でももしかしたら共通して言えることかもしれませんが、例えばRubyであってもRuby on Railsが勢力を持っていないかったらここまで愛されたかどうか…言語の生みの親が日本人なのでそういった意味ではパイは取れたと思いますが…。 余談で私が新卒で入った会社はRuby on Railsでの開発を強みにしてましたがRails5でCoffeeScript が標準サポートされてました。Rails6はwebpackが入ってきてそれなりにまだフロントも書いてましたが7系でwebpackが剝がされて「フロントどうするかな」で「reactだな」という流れがWebアプリ開発者界隈ではそれなりにいたのではないでしょうかね。他のバックエンドフレームワーク事情は知らないのですが。 話を戻します。 TSKaigiですが来場者数も多く話題もSNSでそれなりにトピック化してたのでエンジニア界隈では結構HOTだった印象で、実際に会場にも多くの学生が来ておりました。ただカンファレンスとしてはわりと緩くてTSKaigiでPHPトークをしたという話題でプチ炎上があるとかないとか。CFP要綱を読んでもそれは頷けます。 【TSKaigiのCFP要綱】 トークの条件は、TSKaigi 2024と同様に「TypeScriptに関係する話題であること」、これだけです。 以下はすべて例です。 ・言語特性やエコシステムに関しての話題 ・TypeScriptの言語機能 ・Compiler API、内部実装、型の理論、いわゆる型パズル ・TypeScriptでの利用に特徴あるライブラリ、フレームワーク、ランタイム ・ベストプラクティス、アンチパターン、それらを包括する議論や問題提起 ・エコシステムそのもの、言語そのものに関するその他なんでも ・多様な利用領域での活用事例、ノウハウ ・Webフロントエンド、バックエンドやインフラはもちろんOK ・スマートフォンアプリ、デスクトップアプリ、ゲーム、IoT、XR(VR, AR, MR) そのほか、ここに予想もしないものまで TypeScriptを使った開発に関する話題 ・チーム開発、CI/CD、テスト、デバッグ、モニタリング、デプロイ、運用 ・開発ツール、エディタ、IDE、ツールチェーン、ツールの開発、ドキュメンテーション ・うまくいったこと、うまくいかなかったこと こんな使い方もできるのか、TypeScript! という驚きを得られるような話題に出会えたら、と思っています。 高度で専門的な話でなくても構いません。あなたの経験や気づきを、ぜひ共有してください。 RubyKaigiとは雰囲気がだいぶ違うんだなという印象でしたが、そもそもRubyKaigiが特殊なだけと良く言われているのでTypeScriptの言語学的なセッションを期待していると歪みが起こりそうです。 実際、トークセッションの内容の6割以上くらいは生成AIの文脈は絡んできてた感じで、それ完全にもうLLM周りの話ではないのか?ともありました。 個人的にはLLMとの上手い付き合い方みたいな感じでも十分に学びになりましたが、純粋にオープニングキーを担当したAnthony FuさんのESLint ConfigみたいなTypeScriptエコシステムの内部仕様みたいな話を期待しているとやっぱり乖離ありです。 発表のあったLTセッションを参考に、マイナビの内製開発におけるTypeScriptの話をしてもウケそうだなとも思いました。マイナビでもフルスタックTypeScript構成の案件やorval、OpenAPIスキーマからTypeScriptクライアントコードを生成している案件やPanda.CSSを使った案件もあるのでTSKaigiの登壇にチャレンジしていきたいですね。 ではスポンサー枠の状況やメリットは何だろうか。 国内最大級のTypeScriptカンファレンス「TSKaigi 2025」、 スポンサー募集中です TSKaigi 2025 スポンサーの一次募集終了と御礼 資料によると、2024はオフライン+オンラインで2,400人くらいの参加だったが、今年は公式では計画段階で3,600人くらいのようでしたが、チケット完売も早かったのでオンラインの上振れ考えても、倍は見込んだとして5,000人は直接リーチはありそうです。(個人推論です) 協賛ボードはプラチナ150万円、ゴールド100万円、シルバー50万円、ブロンズ20万円です。 ブースやランチタイムLT枠はシルバー以上で応募可能になっており、ランチタイムLTは10分で10万円なので、登壇枠を買うなら最低60万円で可能です。 ブースは30万円でスタートアップからレバレジーズやサイバーエージェントやdwangoやfreeeなどの社会的な知名度がある事業会社もありました。 WEBエンジニアはカンファレンスボードをみて転職可能企業を見つけている部分もあるとは思うので、開発分野での組織的なブランド価値と求人広告周り出すよりはコスパはいいかもしれない。実際ブース出展からカジュアル面談にという経路もいくつかあるはず。 マイナビに限って言えば組織が大きすぎてカジュアル面談とかないかもしれないがまあ方法論はいくつかあると思います。 TypeScriptはトレンドすぎてカンファレンスに協賛しなくても新卒採用では当たり前のように興味持った学生がデジ戦に応募してくるかもしれないのですが、TSKaigiに限らず技術カンファレンスのスポンサーとかプロポーザル活動やっていきたいですね。 (RubyKaigiとかKaigi on RailsとかGoConとか)
こんにちは、新卒2年目でビジネスイノベーション統括本部ITD1-2-0のS.Hです。 今回、私が普段の業務で使用しているTypeScriptをテーマにした大型カンファレンス『TSKaigi 2025』の参加レポートを書かせていただきました! 研修後、現在の部署に配属されてからもうすぐ1年。ほぼ新人の視点から、TSKaigiに参加して感じた魅力などを発信していきます! TSKaigi 2025 カンファレンス概要 情報区分 カンファレンス詳細 イベント名 TSKaigi 2025 開催日 2025/05/23、2025/05/24 開催場所 ベルサール神田 都営新宿線小川駅から徒歩5分 ミッション 学び、繋がり、"型"を破ろう タイムテーブル Day1 10:00 開場 10:50 ~ 11:00 トグルルーム:オープニングトーク アセンドトラック:サテライト レバレジーズトラック:クローズ 11:00 ~ 11:40 トグルルーム 種別:招待講演 タイトル: The New Powerful ESLint Config with Type Safety 登壇者:Anthony Fu アセンドトラック:サテライト レバレジーズトラック:クローズ 11:40 ~ 11:50 休憩 11:50 ~ 12:20 トグルルーム 種別:セッション タイトル: checker.tsに対して真剣に向き合う 登壇者:Kaoru アセンドトラック 種別:セッション タイトル: 高度な型付け、どう教える? 登壇者:progfay レバレジーズトラック 種別:セッション タイトル: スキーマと型で拓く Full-Stack TypeScript 登壇者:Sohei Takeno 12:20 ~ 12:30 ランチ配布 12:30 ~ 13:30 トグルルーム 種別:スポンサーLT 撤退危機からのピボット:4年目エンジニアがリードする TypeScript で挑む事業復活  / 横沢 諒 推し活を支えるAngularアプリ量産体制  / Hayato Okumoto 生成AI時代にフルスタックTypeScriptの夢を見る  / matano AsyncAPIを使ってPub/Subを型安全にする  / 高橋 修平 アセンドトラック:ランチ レバレジーズトラック:ランチ 13:30 ~ 13:40 休憩 13:40 ~ 14:10 トグルルーム 種別:セッション タイトル: TypeScriptで実践するクリーンアーキテクチャ ― WebからもCLIからも使えるアプリ設計 登壇者:プログラミングをするパンダ アセンドトラック 種別:セッション タイトル: 静的解析で実現したいことから逆算して学ぶTypeScript Compiler 登壇者:Kazushi Konosu レバレジーズトラック 種別:セッション タイトル: SignalとObservable―新たなデータモデルを解きほぐす 登壇者:lacolaco 14:10 ~ 14:20 休憩 14:20 ~ 14:50 トグルルーム 種別:セッション タイトル: 堅牢なデザインシステムをつくるためのTypeScript活用 登壇者:takanorip アセンドトラック 種別:セッション タイトル: Language Serverと喋ろう 登壇者:ぴざきゃっと レバレジーズトラック 種別:セッション タイトル: TSConfigからTypeScriptの世界を覗く 登壇者:らいと 14:50 ~ 15:00 休憩 15:00 ~ 15:30 トグルルーム 種別:セッション タイトル: AI Coding Agent Enablement in TypeScript 登壇者:Yuku Kotani アセンドトラック 種別:LT 推論された型の移植性エラーTS2742に挑む  / elecdeer TSConfig Solution Style & subpath imports でファイル単位で型を切り替える  / kotori 主要ライブラリの実例に学ぶ、TypeScriptで実現する型安全な座標定義  / 原口 公輔 コンポーネントライブラリで実現する、アクセシビリティの正しい実装パターン  / たじまん レバレジーズトラック 種別:LT 学生でもここまで出来る!ハッカソンで爆速開発して優勝した話  / かわちゃん 『Python→TypeScript』オンボーディング奮闘記  / 龍野 卓己 転生したらTypeScriptのEnumだった件~型安全性とエコシステムの変化で挫けそうになっているんだが~  / やまのく URLPatternから始めるWebフレームワーク開発入門  / ryuapp 15:30 ~ 15:50 休憩 15:50 ~ 16:20 トグルルーム 種別:セッション タイトル: TypeScriptとReactで、WAI-ARIAの属性を正しく利用する 登壇者:ymrl アセンドトラック 種別:セッション タイトル: AWS LambdaをTypeScriptで動かして分かった、Node.jsのTypeScriptサポートの利点と課題 登壇者:Masaki Suzuki レバレジーズトラック 種別:セッション タイトル: TypeScriptエンジニアがAndroid開発の世界に飛び込んだ話 登壇者:yui_tang 16:20 ~ 16:30 休憩 16:30 ~ 17:00 トグルルーム 種別:セッション タイトル: TypeScriptとは何であって何でなく、誰のもので、どこへ向かうのか 登壇者:Sosuke Suzuki アセンドトラック 種別:セッション タイトル: fast-checkとneverthrowのPBT+Result型で堅牢なビジネスロジックを実現する 登壇者:上田慶祐 レバレジーズトラック 種別:セッション タイトル: Valibot Schema Driven UI - ノーコードWebサイトビルダーを実装してみよう! 登壇者:宮城広隆(@MH4GF) 17:00 ~ 17:10 休憩 17:10 ~ 17:40 トグルルーム 種別:セッション タイトル: Rust製JavaScript/TypeScript Linterにおけるプラグイン実装の裏側 登壇者:unvalley アセンドトラック 種別:LT Interface vs Types 〜型推論が過多推論〜  / omote Wasmを用いて他言語資産をTypeScriptで活用する  / 赤木 勇統 型パズルを好きになるために、競プロを型システムだけで解いてみることにした  / いまいまい タイプレベルリファクタリング奮闘記〜この「型パズル」は読めません!〜  / Yugo Yagita レバレジーズトラック 種別:LT Rust製JavaScript EngineのTypeScriptサポート  / yossydev TypeScript だけを書いて Tauri でデスクトップアプリを作ろう  / 小松 翔 (tris) 型安全なDrag and Dropの設計を考える  / yudppp GitHub ActionsをTypeScriptで作ろう!  / じょーし(上司陽平) Day2 9:30 開場 9:50 ~ 10:00 トグルルーム:オープニングトーク アセンドトラック:サテライト レバレジーズトラック:クローズ 10:00 ~ 10:40 トグルルーム 種別:主催者講演 タイトル: TypeScriptネイティブ移植観察レポート TSKaigi 2025 登壇者:berlysia アセンドトラック:サテライト レバレジーズトラック:クローズ 10:40 ~ 10:50 休憩 10:50 ~ 11:20 トグルルーム 種別:セッション タイトル: TypeScript Language Service Plugin で CSS Modules の開発体験を改善する 登壇者:mizdra アセンドトラック 種別:セッション タイトル: フロントエンドがTypeScriptなら、バックエンドはPHPでもいいじゃない 登壇者:富所 亮 レバレジーズトラック 種別:セッション タイトル: TypeScriptとVercel AI SDKで実現するLLMアプリケーション開発:フロントエンドからバックエンド、そしてChrome拡張まで 登壇者:加瀬健太(Kesin11) 11:20 ~ 11:30 休憩 11:30 ~ 12:00 トグルルーム 種別:セッション タイトル: 複雑なフォームを継続的に開発していくための技術選定・設計・実装 登壇者:izumin5210 アセンドトラック 種別:セッション タイトル: Pragmatic Functional Programming in TypeScript 登壇者:yasaichi レバレジーズトラック 種別:セッション タイトル: feature flag 自動お掃除のための TypeScript プログラム変換 登壇者:azrsh 12:00 ~ 12:10 ランチ配布 12:10 ~ 13:10 トグルルーム 種別:スポンサーLT バックエンドのコードファーストなOpenAPIスキーマ駆動開発 / 鳥居 雄仁 バランスを見極めよう!実装の意味を明示するための型定義 / 畑田祥太 PandaCSSでつくる、型で守られたスタイリング基盤 ~TypeScript × デザインシステム管理の実践アーキテクチャ~ / 田代 敬太 TSでシステムが堅牢になっていくさまをスポンサーになるたびに報告 〜型定義から始めるリファクタリング編 / 井上 心太 アセンドトラック:ランチ レバレジーズトラック:ランチ 13:10 ~ 13:20 休憩 13:20 ~ 13:50 トグルルーム 種別:セッション タイトル: 技術書をソフトウェア開発する - jsprimerの10年から学ぶ継続的メンテナンスの技術 登壇者:azu アセンドトラック 種別:セッション タイトル: 型システムを活用した ESLint カスタムルール開発入門 〜固有ドメインにおけるコーディング規約を開発する〜 登壇者:山梨 蓮 レバレジーズトラック 種別:セッション タイトル: Web Streams APIの基本と実践、TypeScriptでの活用法 登壇者:tasshi 13:50 ~ 14:00 休憩 14:00 ~ 14:30 トグルルーム 種別:セッション タイトル: ts-morphで、人間も編集できるコード生成を実現しよう! 登壇者:池奥裕太 / @yuta-ike アセンドトラック 種別:LT VueUse から学ぶ実践 TypeScript / ツノ 型推論の扉を開く―集合論と構造的型制約で理解する中級へのステップ / 栃川晃佑 TypeScript ASTとJSDocで実現するコードの自動削除 / 川野賢一 これは型破り?型安全?真実はいつもひとつ!(じゃないかもしれない)TypeScriptクイズ / 君田 祥一 レバレジーズトラック 種別:LT Result型、自前で書くか、ライブラリ使うか / majimaccho 型付け力を強化するための Hoogle のすゝめ / TAKASE Kazuyuki (@Guvalif) React19で変化したuseReducerの型から学ぶTypeScriptの型推論 / k8o クラサバ境界を失った現代 TypeScript コードベースに秩序をもたらしたい / Yo Iwamoto 14:30 ~ 14:40 休憩 14:40 ~ 15:10 トグルルーム 種別:セッション タイトル: 機能的凝集の概念を用いて複数ロール、類似の機能を多く含むシステムのフロントエンドのコンポーネントを適切に分割する 登壇者:NoritakaIkeda アセンドトラック 種別:セッション タイトル: Lookback TypeScript ESM support and what should we do now. 登壇者:Saji レバレジーズトラック 種別:セッション タイトル: 君だけのオリジナル async / await を作ろう 登壇者:susisu 15:10 ~ 15:30 休憩 15:30 ~ 16:00 トグルルーム 種別:セッション タイトル: TS特化Clineプログラミング 登壇者:mizchi アセンドトラック 種別:セッション タイトル: "良い"TSのコードを書く為のマインドセット 登壇者:Kei レバレジーズトラック 種別:セッション タイトル: TypeScript製IaCツールのAWS CDKが様々な言語で実装できる理由 〜他言語変換の仕組み〜 登壇者:k.goto 16:00 ~ 16:10 休憩 16:10 ~ 16:50 トグルルーム 種別:LT 型がない世界に生まれ落ちて 〜TypeScript運用進化の歴史〜 / 成原 聡一朗 Type ChallengesにPRを出して新しい問題を追加した話 / Kanon ProxyとTypeScriptのおいしい関係 / Motoki Shakagori / ほとけ Panda-CSS はどのように型安全にしているのか / 加藤貴裕 アセンドトラック 種別:LT 令和最新版TypeScriptでのnpmパッケージ開発 / odan コンパイルオプションで変わる型世界 / 池田敬祐 TypeScriptのmoduleオプションを改めて整理する / おおいし (bicstone) Project Referencesを活用した実行環境ごとのtsconfig最適化 / Toshiki Itai レバレジーズトラック 種別:LT ts-morph実践:型を利用するcodemodのテクニック / ypresto declaration mergingの威力:ライブラリアップデート時の書き換え作業を90%短縮するテクニック  / Yuma Takei バリデーションライブラリ徹底比較  / 田中勇太 Standard Schema: スキーマライブラリの統一規格とは何か  / Nozomu Ikuta 17:00 ~ 18:00 トグルルーム:懇親会準備 アセンドトラック:休憩スペース レバレジーズトラック 種別:現地参加者向け企画 タイトル:タイトル: OST (Open Space Technology) 18:00 ~ 20:10 トグルルーム:懇親会 アセンドトラック:クローズ レバレジーズトラック:クローズ セッション内容 TypeScriptネイティブ移植観察レポート TSKaigi 2025 登壇者: berlysia氏 セッション時間:2日目朝 株式会社ドワンゴでWebフロントエンドエンジニアをされているberlysia氏によるts-goの体験レポートです。 5/23深夜、つまりTSKaigiの1日目夜にMicrosoftから公開された tsgoのプレビュー に触れてみた観察者としての調査報告になります。 夜中に公開されたので、TSKaigi1日目を終えてそこから触り、登壇資料を作成されたみたいです。バイタリティとメンタルが素直に凄すぎます。 ts-go1番の特徴はMicrosoftが動画のタイトルにも取り上げられている 「A 10x Faster TypeScript with Ander Hejlsberg(10倍早いTypeScript)」 従来はTypeScriptで書かれた構文をNode.jsを用いて実行されていました。それらを全てfunction単位でGo言語に置き換えており、 Go言語の利点を十全に活かすことで10倍という圧倒的なパフォーマンスを実現するに至ったそうです。 具体的には ソースコードをその場で解釈して実行する Node.jsから、事前に機械語に翻訳されるGo言語へ変わったことによる処理速度の向上 (約3~3.5倍) Node.jsはシングルスレッドモデルの制約があり、単一の処理しかできなかったが、Go言語になったことで並列処理が可能になった (約3~4倍) 上記の2点が組み合わさったことで、本当にすぐに動くようになったとのことでした。 しかも、実行するプログラムの規模が大きくなるほど、その早さを実感するそうです。 「ts-goというものが話題になっている」ということはそれとなく把握していつつも、それが具体的に何なのか知らなかった自分でしたが、10倍という数値だけでもその凄さを容易に想像することができました。 処理速度が上がったことで、それまでのバージョンでは見送っていたライブラリなども採用されるようになり、より発展的で高度な技術力が求められるようになる、というのが私の所感です。 そして、そんなに凄いts-goをまだ私は触ることができていないので、このレポートを書き終えたら早速触ろうと思います。 OST(Open Space Technology) タイムテーブルにある通り、本当に多くのセッションがあり、学びが沢山ありました。 ですが、TSKaigiは登壇者だけが発信する場ではありません。2日目の最後には、セッションルームに集まった参加者が各々好きなテーマについて話し合えるOSTが設けられていました。 OSTはそのテーマについて熱く語りたいから参加する人はもちろん、ほとんど詳しくないけど、知見を広げたいから参加する人もいらっしゃいました。 自分はもちろん後者です笑 今回、TSKaigi中の募集を通して選出されたテーマは下記画像に記載された10個。皆さんはどのテーマに興味を惹かれましたか? 私は5番の「フロントエンドのディレクトリ構成、どう設計している?」に参加しました。 というのも、私の周りにはそういった開発理論について考えることが好きな同期がおり、この機を活かして『完全に理解した!』ぐらいの理解度を得てみたいと感じたためです。 結論からお伝えすると『だいぶん理解したかも??』ぐらいの理解度を得ることができました。 もう少し実際に試していくことで『完全に理解した!』の理解度を得られそうです。 今回のOSTで話題に上がった内容はFSDとBCDデザインの組み合わせです。 FSD まず、 FSD(Feature-Sliced Design) とは、機能単位で構造化する設計パターンで、公式では「Architectural methodology for frontend projects(フロントエンドのアーキテクチャ手法)」と定められています。 機能単位で構造化する、つまり機能ごとに責務を持たせることで、拡張性・保守性・可読性を高めることが可能になることがFSDの特徴です。 FSDは、レイヤーという役割の抽象的な区分と、そこから実際の機能単位で切り分けるスライス、そしてhookやUIなどの各機能を構成するセグメントで成り立っています。 出典: FSD(Feature-Sliced Design) 機能単位でディレクトリを構成することは多いと思いますが、そこから更に責務という名の「機能の持つ役割や義務」に着目して分類する手法がFSDなのです。 BCDデザイン 次にBCDデザインは株式会社ドワンゴ所属のmisuken氏が考案されたコンポーネントの分類手法です。 同期からの受け売りですが、 「BCDデザインとは Base(UI) Case(動作) Domain(対象)に着目してコンポーネント名を『何をどうするUI』の法則に則って命名すること」なんだそうです。 私なりの解釈で説明すると、誰でもそのコンポーネント名を見ただけで、役割が分かるようにする手法になります。 出典: misuken氏のBCDデザイン解説記事 例えば、ここにフィードバック専用のモーダル画面のコンポーネントがあったとしたら、どのような名前にしますか? 恐らく、多くの人が FeedbackModal.tsx という名前にするのではないでしょうか? それがBCDデザインの命名規則に当てはめると、 FeedbackSendModal.tsx になります。 フィードバックを編集する(Edit)でもなく、削除する(Delete)でもなく、送る(Send)ためのモーダル画面。それが誰にでも伝わる命名規則です。 ちなみに、この場合でも何のフィードバックなのかが不透明なので、DomainをDomainとCommon(抽象的対象)に分割するBCCDデザインというものもあります。 また、 misuken氏のBCDデザイン解説記事 では、「"命名" するのではなく "明名" すると考える」と表現されていました。 OSTまとめ FSD × BCDデザイン 「抽象的な責務で分類し、機能単位でディレクトリ構造化を図るFSD」と 「誰にでも伝わるコンポーネント明名手法のBCDデザイン」 この2つを組み合わせることで構造も名前もはっきりと定まった方針で分かりやすくフロントエンドのディレクトリ構成が実現できる、というのが今回のOSTに関する結論になりました。 今回のディレクトリ構成OSTには15名近くの方が集まり、その中でもFSDとBCDデザイン、それぞれの知見を深く持った方が2人ずついらっしゃったので、本当に濃い議論をすることができました。 個人的には、今回のBCDデザイン側に株式会社ドワンゴの社員さんがいらっしゃったことに一番衝撃を受けました。流石TSKaigi、一般参加される方も凄い。 企業ブース 私は今回のカンファレンスでブースを設けられていた企業様のイベントも目一杯体験してきました。 恐らく、会社から一緒に行った7人の中で最も詳しく企業ブースのレポートを書けると思うので、こちらも詳しく書かせていただきます! (各ブースで実施されたスタンプラリーを1日目で制覇しました) 流石に全ブースについて書くと時間が足りないので、今回は2つほど特に面白いと感じた企業様のブースを取り上げさせていただきます AVITA株式会社 AVITA株式会社は大阪大学の教授が代表を務めるスタートアップ企業です。 大学の研究室と企業、両方から特許申請を活発に行い、週に1回ペースで特許申請会議があるそうです。 "特許申請会議"。字面がとても強い 提供しているwebサービスは、 「フロント・バックエンドがフルスタックのTypeScriptで実装されたWebアプリ」 と 「Unity × TypeScriptで運用されているスマホアプリ」です。 色々お話をお伺いした中で、私が特に面白いと感じた点は真ん中のディスプレイで動いているトラッキング技術です。 これはディスプレイ上部のカメラから取り込んだ映像を元にフェイストラッキングとハンドトラッキングを同時に実行されています。 この処理には、Googleが提供している画像解析によるトラッキング専用ライブラリMediaPipeが利用されています。 その中でも面白いと感じた要素は、とにかくトラッキングの精度が高すぎる点です。 MediaPipeは機械学習によって手の状態を画像解析を行い、「恐らくこの辺りに手の関節があるだろう」といった判定を下します。そのため、動画のように連続してトラッキング対象が動く状況だと著しく精度が落ちます。 実際、以前に自分がMediaPipeを試したときは指関節がはちゃめちゃに暴れ回り、画面内に描写された手は見事に潰れていました。 それなのに、こちらのプログラムは滑らかに動く実物の手に追従して、関節座標も暴れることなくしっかり手の動きを再現していました。 Unityアプリの出来から垣間見えた開発者さんの膨大な努力に圧倒され、ものすごく興奮しました。 TypeScriptの話はできませんでした… お土産にシールやアクスタをいただきました笑 スパゲッティコード、マジックナンバー イラストはとても可愛いのにワードが全く可愛くない アクスタも作るぐらいIP展開にも力を入れ始めたらしいです。いつか販売されるのを楽しみにしています! 株式会社TwoGate TypeScriptベースのWebアプリフレームワーク"Angular"を使ったエンターテイメント領域向けに利用者専用にカスタマイズしたスマホアプリをリリースしている会社です。 1日目のお昼にLT登壇もされていました。 推し活を支えるAngularアプリ量産体制 こちらの企業から沢山お話を聞いた内容はサービスの根幹部分の「Core Library Repository」についてです。 TwoGate様はアーティストの要望に沿って推し活の専用アプリをリリースしており、開発エンジニア15名ほどに対し、リリースしているアプリ数は200個を超えています。 平均1人当たりアプリを15個ほど担当しているような状況でも成り立っている理由はリリースしたアプリ全てが「Core Library Repository」というこの企業独自のライブラリから作られているからです。 つまり、Core Library Repositoryがあれば、多少のカスタマイズをすることで誰でもチケット販売や整理券配布などの機能を持った専用アプリを作ることできる。そんなライブラリを作り上げ、それを元にサービスを提供しているとのことでした。 私たち開発エンジニアが普段活用しているようなライブラリを作り、その運用を事業として行なっている一風変わった企業様でした。 TSKaigiに参加して 今回、私は下記の2つのセッションに参加し、その上で実際にそれぞれの技術に触れてみたので、それぞれから感じた今後に対する所感をまとめさせていただきます。 PandaCSSでつくる、型で守られたスタイリング基盤 ~TypeScript × デザインシステム管理の実践アーキテクチャ~ TS特化Clineプログラミング CSSライブラリ - PandaCSS PandaCSSを知ったことをきっかけに、実際に個人で触れてみる中で、TailwindCSS以外のCSSライブラリにも視野を広げる良い機会になりました。使ってみることで、それぞれのライブラリが持つ特徴や考え方の違いも見えてきて、フロントエンドに対する理解が一段深まったように感じます。 一方で、実際にNext.jsのプロジェクトに組み込もうとすると、TailwindCSSのように簡単にセットアップできるわけではなく、PandaCSSは別途インストールや設定が必要です。その分、Dockerfileなどの構成にも工夫が必要で、開発や保守とはまた違った知識が求められる点には留意する必要があると感じました。 こうした経験から、CSSライブラリの選定には機能性だけでなく、導入のしやすさやチームの開発環境との相性も含めて検討することの重要性を実感しました。 コーディングエージェントについて 最近よく耳にする「コーディングエージェント」ですが、これまでは最低限のサポートツールとして使っている程度でした。実際のところ、補助的にコードを書いてくれる便利な存在、という認識しか持っていませんでした。 しかし今回、プロンプトをしっかり設計してAIとやり取りしてみたことで、印象が大きく変わりました。AIを効果的に活用するには、「どう指示するか(=プロンプト)」の工夫がとても重要で、これ自体が一つのスキルだと感じました。いわゆる“プロンプトコーディング”が、今後開発エンジニアに求められる新しい力になると思います。 また、個人的な気づきとして、会社でコーディングエージェントを活用していくには、プロンプトの作り方だけでなく、それをどう管理するかも大切になってきそうです。チームでの共有や再利用、更新のしやすさなど、コードと同じように「プロンプトの品質」も考えていく必要があると感じました。 TSKaigiの感想 私はTSKaigiに初めて参加し、本当に貴重な経験を沢山することができました。 今回のカンファレンスに対して、職場環境以外からのインプットを求めて参加をしました。 職場という技術的にも思想的にもある程度方針が固まっている環境以外からの発信に多く触れることで、技術研鑽というアウトプットに対するモチベーションへ繋げたいと考えていました。 実際、先ほどの章で触れた通り、これまで触れていなかった技術や概念に挑戦するきっかけとなりました。 その結果、壁にぶつかったことで新たな課題が見つかりましたが、それでもTSKaigiに参加しなかったら得られなかったものなので、職場環境以外からのインプットはとても価値のあるものだと実感しています。 まだ、技術スタック的に業務と直接交わることのないものですが、今後PJや状況が変化した先で繋がるタイミングがあると思うので、これからもアウトプットを続けていきたいと考えています。 また、今回の1日目は平日に開催されていましたが、外部研修の一環で公休の申請が降りたため、参加しやすい環境になっていた点がとても有難かったです。 同期や先輩を含め7人での参加は初めての経験だったこともあり、自分が見て回れなかったブースやセッションの話も聞くことができ、TSKaigiをより楽しむことができたと実感しています。 お弁当も美味しかったです おまけ TSKaigiでいただいたサプライ品が気に入りすぎて、社用にカスタマイズしました。 右のタグはTSKaigiで知り合った方に作り方を教わって作成した自己紹介タグです。 イベントで大活躍間違いなし!爆速相互フォローを実現するNFCタグキーホルダーを作ろう
システム開発における命名の重要性 「命名」について、考えたことはありますか? 命名とは、文字通り命を与えることです。つまり、システムの肝となりうるものということです。 したがって、不適切に命名されたシステムはその生命を十分に発揮することができません。 軽く考えられがちな「名前をつける行為」ですが、この行為の質がプロジェクト全体の健全性を左右すると言っても過言ではありません。 今回は、「命名」を「ドキュメンテーションにおける最も基本的な手段」にまで昇華させるために重要なことについて説明をします。 命名における関心とは 命名における関心 (Domain)とは、対象となるビジネス領域の本質的な概念や規則を反映する要素です。 これは単なる技術的な区分ではなく、実際のビジネスプロセスや業務知識に基づく分類軸を意味します。 関心は以下のような要素から構成されます。 ドメインエンティティ:業務上の主要概念 生徒 会員 商品 注文 ドメインプロセス:業務上の重要な処理 入会 退会 請求 集計 ドメイン状態:業務上の条件や状態 アクティブ 休会中 プレミアム 月次 ドメイン規則:業務特有のルールや制約 割引条件 承認フロー ドメインコンテキスト:適用される業務文脈 販売 マーケティング 教育 中核の関心 例えば、「プレミアム会員の月次利用統計」には「プレミアム会員」という顧客区分と「月次」という集計期間、「利用統計」という分析対象といったように複数の関心が含まれています。 しかし、この中でもっとも重要な関心は「利用統計」です。 このように、複数の関心が組み合わさっていてもその中にひとつ主軸となる「中核の関心」が存在することがわかります。 そして、命名において重要なことは、中核の関心と補助の関心(それ以外の関心)の境界を明確に理解し、関心を過不足なく表現しきることです。 また、分類においても中核の関心は重要なポイントとなります。 例えば、「プレミアム会員」、「月次」、「利用統計」というカテゴリーがあったとき、「プレミアム会員の月次利用統計」はどこに分類するべきでしょうか? ここまでの話から、中核の関心をもとに「利用統計」に分類するべきであることがわかるとおもいます。 関心を表現し切ることの重要性 よくある命名の失敗のひとつが、「関心を表現しきれていないこと」です。 例えば、「プレミアム会員の月次利用統計」の中核の関心は「利用統計」ですが、「プレミアム会員」と「月次」も重要な関心であることに変わりはありません。 しかし、命名する際に中核の関心以外の補助の関心が抜け落ちてしまうことがあります。 「プレミアム会員の月次利用統計」を英訳すると PremiumMemberMonthlyUsageStatistics となります。そして、これがそのまま関心名となっているべきなのです。 例えば、「プレミアム会員の月次利用統計を取得する関数」の命名は getPremiumMemberMonthlyUsageStatistics であるべきです( get が妥当かは別問題として)。 名前が長くなるのをおそれて、 getUsageStatistics のように関心を省略してしまうのは典型的なアンチパターンとなるため注意しましよう。 関心は後方一致でまとめよう 中核の関心は、関心名の最後に現れる状態にしましょう。 なぜなら、日本語の語順において中核の関心は最後に現れるためです。 例えば、「プレミアム会員の月次利用統計」の中核の関心は「利用統計」ですが、関心名の最後に現れています。 この「関心名の末尾に中核の関心が現れる状態」は認知上のパフォーマンスにおいて非常に重要となります。 日本語の語順のまま英訳しよう 実を言えば、日本語において中核の関心が名前の最後に現れるのは当たり前のことです。 というよりも、名前の最後に現れている関心が中核の関心であるといった方が正しいです。 ではなぜこのような話をしているのかと言うと、英語にした際にこの当たり前が崩れることがあるためです。 「契約プラン別のユーザ」を例にみていきましょう。 まず、「契約プラン別のユーザ」を直訳すると「Users by Contract Plan」となります。 そして、「契約プラン別のユーザ」の中核の関心は「ユーザ」です。 しかし、「Users by Contract Plan」の末尾についているのは「Contract Plan」です。 このように、日本語では問題なかった命名が英語にした途端問題が発生してしまうことがあります。 では、どのように英訳すればよかったのでしょうか? 重要なポイントは、「日本語の語順のまま英訳する」ことです。 英訳する際に、日本語の語順を保つようにすれば中核の関心を最後に持ってくることが可能となります。 私は英語の専門家ではないので、AIに頼ってみましょう(Claude 3.7 Sonnetを使用)。 Q: 「〇〇別のXxx」を、「Xxx by 〇〇」ではなく、Xxxの前方につく修飾語で表現できると嬉しいのですが、何か案はありますか? A: 修飾語による表現方法の提案 「〇〇別のXxx」を「Xxx by 〇〇」ではなく、前方修飾語で表現する方法としては、以下のようなパターンがあります: 一般的なパターン 形容詞形に変換する 例:「地域別の売上」→ "Regional sales" 例:「性別の統計」→ "Gender-specific statistics" 所有格を使う 例:「部門別の予算」→ "Departmental budget" 例:「季節別の計画」→ "Seasonal plan" 複合語を形成する 例:「年齢別の分析」→ "Age-based analysis" または "Age-group analysis" 例:「業界別のレポート」→ "Industry-specific report" 接頭辞を活用する 例:「国別のデータ」→ "Country-specific data" または "Per-country data" 例:「時間別の記録」→ "Time-segmented records" Q: このようなケースで使用できる前方修飾語をまとめてください。 修飾表現別の「示す基準」の比較 各表現が示す基準や関係性の違いを整理します: 分類・区分に関する表現 based: 「〜に基づいた」- 分類や区分の基準を示す 例: Age-based grouping(年齢に基づくグループ分け) 適した用途: データ分類、カテゴリ分け、客観的基準による整理 specific: 「〜に特化した」- 特定対象への限定性を示す 例: Industry-specific regulations(業界に特化した規制) 適した用途: 特定分野だけに適用される事柄、限定された適用範囲 segmented: 「〜で区分された」- セグメント化の基準を示す 例: Price-segmented offerings(価格帯で区分された商品) 適した用途: マーケティング分析、戦略的区分け classified: 「〜で分類された」- 分類のカテゴリーを示す 例: Skill-classified employees(スキルで分類された従業員) 適した用途: 階層化された分類、評価基準による区分 焦点・方向性に関する表現 focused: 「〜に焦点を当てた」- 注目点や重点を示す 例: Solution-focused approach(解決策に焦点を当てたアプローチ) 適した用途: 戦略や方法論、特に重視する側面の強調 oriented: 「〜志向の」- 方向性や傾向を示す 例: Result-oriented metrics(結果志向の指標) 適した用途: 思想的傾向、アプローチの方向性 centric: 「〜中心の」- 中心的要素を示す 例: User-centric design(ユーザー中心の設計) 適した用途: 設計思想、価値観の中心 対象・用途に関する表現 targeted: 「〜を対象とした」- 明確なターゲットを示す 例: Senior-targeted services(高齢者を対象としたサービス) 適した用途: マーケティング、サービス提供の対象指定 tailored: 「〜向けに調整された」- カスタマイズの対象を示す 例: Client-tailored solutions(クライアント向けに調整されたソリューション) 適した用途: パーソナライズされたサービス、個別調整された提案 dedicated: 「〜専用の」- 専用化・排他的用途を示す 例: Developer-dedicated tools(開発者専用のツール) 適した用途: 特定グループだけが使用するもの、専用設計された製品 観点・視点に関する表現 wise: 「〜の観点から」- 視点や観点を示す 例: Department-wise budgeting(部門の観点からの予算編成) 適した用途: 分析視点、複数の観点からの考察 AIの回答を表にまとめてみます。 修飾表現別の「示す基準」比較表 分類・区分に関する表現 表現 意味 例 適した用途 based 〜に基づいた Age-based grouping(年齢に基づくグループ分け) データ分類、カテゴリ分け、客観的基準による整理 specific 〜に特化した Industry-specific regulations(業界に特化した規制) 特定分野だけに適用される事柄、限定された適用範囲 segmented 〜で区分された Price-segmented offerings(価格帯で区分された商品) マーケティング分析、戦略的区分け classified 〜で分類された Skill-classified employees(スキルで分類された従業員) 階層化された分類、評価基準による区分 焦点・方向性に関する表現 表現 意味 例 適した用途 focused 〜に焦点を当てた Solution-focused approach(解決策に焦点を当てたアプローチ) 戦略や方法論、特に重視する側面の強調 oriented 〜志向の Result-oriented metrics(結果志向の指標) 思想的傾向、アプローチの方向性 centric 〜中心の User-centric design(ユーザー中心の設計) 設計思想、価値観の中心 対象・用途に関する表現 表現 意味 例 適した用途 targeted 〜を対象とした Senior-targeted services(高齢者を対象としたサービス) マーケティング、サービス提供の対象指定 tailored 〜向けに調整された Client-tailored solutions(クライアント向けに調整されたソリューション) パーソナライズされたサービス、個別調整された提案 dedicated 〜専用の Developer-dedicated tools(開発者専用のツール) 特定グループだけが使用するもの、専用設計された製品 観点・視点に関する表現 表現 意味 例 適した用途 wise 〜の観点から Department-wise budgeting(部門の観点からの予算編成) 分析視点、複数の観点からの考察 AIに質問したところ、上記のような前方修飾語に変換する方法をまとめてもらえました。 では、これをもとに「契約プラン別のユーザ」を英訳してみましょう。 「契約プラン別」というのは、分類・区分に基づく表現です。 そのため、今回のケースでは「based」が適切であると考えられます。 よって、「契約プラン別のユーザ」を英訳したものは ContractPlanBasedUser となります。 このように、中核の関心が後方一致になるように命名することが重要です。 Byは使用できないのか? すべての命名においてByが使用できないのかというと、そうではありません。 あくまでも、関心な名前として語順が崩れる場合に使用できないということに留意してください。 例えば、データベースからユーザIDでユーザを取得してくる関数の名前は getUserByUserId などと命名することが一般的だと思います。 このとき、関心は User であり、 ByUserId は関心ではありません。 したがって、このようなケースではByを使用することができます。 ただし、契約プランIDで契約プラン別のユーザ一覧を取得してくる関数の場合は getContractPlanBasedUsersByContractPlanId となります。 なぜなら、この場合の関心は「契約プラン別のユーザ(一覧)」であり、「契約プラン別」も関心に含まれているためByを避け日本語の語順を保つようにするためです。 後方一致であることのメリット 関心を後方一致でまとめることのメリットは、語順を保つことができる点です。 そして、語順を保つことのメリットは、一貫性と対称性を担保することができる点です。 一貫性 命名における一貫性とは、概念順序規則にしたがっていることです。 概念順序規則とは、「名前の要素を意味のある概念ごとに順序立てて配置する考え方」です。 例えば、 getUserByUserId を概念ごとで分けると get / User / ByUserId となります。 まず、 get は操作(動詞)です。他には、 find や remove 、 create など。 次に、 User は関心です。そして、 ByUserId は方法・条件です。 つまり、データベースの操作というパターンにおいて、その関数名は常に操作 -> 関心 -> 方法・条件という概念順序で命名されるべきであるということです。 この、概念順序規則にしたがって命名されている状態を一貫性が高いと表現します。 もちろん、パターンが異なればその概念順序も異なります。 例えば、コンポーネント名であれば、その概念順序は関心 -> 状況・状態 -> UIの型となります。 ここで重要なのは、同一パターン内では常に一定の概念順序規則にしたがっているという点です。 概念順序規則を遵守することで、命名の一貫性を向上させることができます。 対称性 命名における対称性とは、複数の命名を並べてみたときに、それぞれの概念が対応していることです。 例えば、コンポーネント名における概念順序が関心 -> 状況・状態 -> UIの型のとき、「記事を投稿するフォーム」が ArticlePostForm なら「コメントを投稿するフォーム」は CommentPostForm であるべきということです。 日本語において「コメント」という単語は名詞だけでなく「コメントする」という動詞的な意味も含まれがちですが、それに引っ張られて「コメントを投稿するフォーム」を CommentForm と命名するのは早計かもしれません。 もし、あとから「コメントを編集するフォーム」が必要になった場合、そのコンポーネントは CommentEditForm と命名されるでしょう。ところが、「コメントを投稿するフォーム」は CommentForm と命名されているのです。 これが対称性を崩す要因となります。  あとから類似のものが出てきた際に、対称性が崩れないかに注意して命名しましょう。 まとめ 今回の記事で重要なポイントは以下の4つです。 関心には、「中核の関心」と「補助の関心」が存在する。命名する際は「補助の関心」も含めて表現しきる必要がある 中核の関心が英語名の末尾になるように、日本語の語順のまま英訳する 命名は「操作 -> 関心 -> 条件」や「関心 -> 状況・状態 -> UIの型」など、概念順序規則に従うことで一貫性を保つ。 同じパターンの命名間で構造を揃えることで対称性を実現する。 これらのポイントを意識し、一貫性と対称性が高い命名ができていると、迷いが生じなくなっていきます。 なぜならば、名前自身がどうするべきか教えてくれるようになるからです。 例えば、適切に命名されたディレクトリ構造では、ファイルをどこにいれるべきか、どのようなファイル名・ディレクトリ名にするべきかに迷うことはなくなります。 命名は、コードにコメントを書くことと同様、もしくはそれ以上に「それが一体何なのか・何ではないのか」を説明することができます。 こうして「命名」は「ドキュメンテーションにおける最も基本的な手段」となっていくのです。
見事統計検定1級で撃沈してしまいました。 そこで2024年の問題で問われた「フィッシャー情報量」「クラメール・ラオの下限」について、整理し、メモを供養します。 ↓2024年統計検定1級 統計数理第1問 統計検定1級の過去問 https://www.toukei-kentei.jp/preparation/kakomon パラメータ推定 パラメータ推定の話を考えます。 母集団から得られたサンプルデータ群から、母集団の平均や標準偏差を推定することをパラメータ推定といいます。 特に、例えば「この母集団の平均値は1.4だ!」などのようにジャストでパラメータを言い当てることを「点推定」といいます。 実際には、実験して得られた標本(実現値)から、パラメータを推定することになるので、点推定は「標本から推定値を得るための関数を作り、その関数に実現値を代入して推定値を求める」ことになります。 数式的には、パラメータ θ を持つ母集団から得られるサンプルを X = ( X 1 , . . . , X n ) とおき、その関数 θ ^ ( X ) を構築します。 実験によって実現値 x = ( x 1 , . . . , x n ) を得られたとき、 θ ^ ( x ) が点推定値となります。 点推定の方法 最尤 さいゆう 推定法(MLE, Maximum Likelihood Estimation) 一番有名な点推定の方法かなと思います。理論上、最も良い推定量を得られることが証明されているようです。 サンプル X = ( X 1 , . . . , X n ) の同時確率関数を、パラメータ θ の関数として、 L ( θ ) = ∏ i = 1 n f ( x i | θ ) とします。つまり、サンプル中のデータ x i すべてに対して、それが得られる確率を計算し、すべて掛け合わせた関数です。 この関数のことを「尤度関数」と呼びます。 この尤度関数を最大にする θ を、最尤推定量(MLE)と呼びます。θ^のようにあらわします。 L ( θ ^ ) = max θ L ( θ ) 例 ある養鶏所にて、採取される卵の重さが正規分布に従うとして、平均値(母平均)と分散(母分散)がそれぞれ未知の値 μ , σ 2 であるとし、 μ を推定するケースを考えます。 n個の卵を採取し、その重さがそれぞれ X 1 , X 2 , . . . , X n だった場合、 L ( μ , σ 2 ) = ∏ i = 1 n N ( X i | μ , σ 2 ) この対数をとって、 μ について微分すると、 ∂ ∂ μ l o g L ( μ , σ 2 ) = − n σ 2 ( μ − n − 1 ∑ i = 1 n X i ) となるため、 μ = 1 n ∑ i = 1 n X i とすると対数尤度が最大になることがわかります。 したがって、標本平均 1 n ∑ i = 1 n X i は μ の最尤推定量となります。 ここで上げた以外にも、「モーメント法」や「ベイズ法」などの推定方法もありますが、 前述の「最尤推定法」が最も精度が良い推定法となります。 クラメールの下限とフィッシャー情報量 点推定における、推定量の「よさ」とはどのようなものでしょうか。 点推定を行うとき、気になるのは、その推定量がどの程度ブレがあるか、というところになると思います。なるべくブレの少ない推定量を使いたいですよね。 この推定量の「ブレ」についてすこし議論してみたいとおもいます。 結論から言うと、最尤推定法による点推定の方法が、最もブレを少なくする方法となります。 これを示すためには、 1.推定量の分散 V a r θ ( θ ^ ) の下限を求める つまり、その母数(母集団のパラメータ)を推定したときに、どこまでブレを抑えられるのかを求める 2.最尤推定量が1. の下限(クラメール・ラオの下限)に一致する この2つを示す必要があります。 1.を示したのが、「クラメール・ラオの不等式」となります。 ・クラメール・ラオの不等式 適当な正則条件のもと、パラメータ θ の推定量 θ ^ = θ ^ ( X 1 , X 2 , . . , X n ) が不偏推定量(実験を繰り返すことにより真値に収束していく推定量)であるとき、次の不等式が任意の θ について成り立つ V a r θ ( θ ^ ) ≥ 1 n I ( θ ) (証明は こちら 参考に) この不等式は、任意の母数 θ に対して、不偏推定量 θ ^ の分散が 1 / n I ( θ ) より小さくならないことを示しており、この右辺の値を「クラメール・ラオの下限」と呼びます。 で、この 式の中に含まれている I(θ)I(θ)が、「フィッシャー情報量」という関数になります。 フィッシャー情報量は、次のような式です。 I ( θ ) = E [ ( d d θ l o g f ( X | θ ) ) 2 ] = ∫ X ( d d θ l o g f ( X | θ ) ) 2 f ( X | θ ) d X (𝓧は𝑿の定義域) つまり、「対数尤度関数をパラメータ変数で微分したやつを2乗した関数の、観測値に関する期待値」 一方、2. のほうは、クラメール・ラオの下限を求めたうえで、最尤推定量の分散がそれに一致することを証明する必要があります。 例 先ほどの例の「卵の重さの平均」の例を考えます。 各データが、独立同一分布に従うとき、 I ( θ ) は、1つのデータについてのフィッシャー情報量を求めればよいので、 先ほどの例の(*)の式で、 n = 1 と置いて、2乗した関数をXについて積分すれば、フィッシャー情報量が求まります。 つまりどういうこと? ここまでくると数式を解釈しての理解は困難ですが、フィッシャー情報量が、クラメール・ラオの下限の分母に来ていることを考えると、 「フィッシャー情報量が大きいほど、推定量の分散を下げられる(ブレを抑えられる)」 といえそうです。 フィッシャー情報量は、「その母数を推定するための情報がどれだけ得られるか」と解釈してよいでしょう。 冒頭の「問1」に関しては、線形単回帰モデルの「回帰係数ββ」の不偏推定量をまず求めないと、フィッシャー情報量やクラメール・ラオの下限の話に行けないという構造になっていますので、どこかで線形単回帰モデルについても触れたいと思っています。
はじめに 今話題のMCPですが、WebデザインやUIデザイン向けツールのFigmaでもMCPが公開されました。 本記事では、下記をメイン書いています FigmaMCPを利用できるまで 簡単チュートリアル MCPとは AIモデルと外部サービス(システム)を連携するための「共通ルール(プロトコル)」です。 各社がこのルールに沿った「AI専用コントローラー(MCPサーバー)」を提供し、AIアプリ開発者(MCPクライアント)はそれを呼び出すだけで各種サービスと連携可能になります。 これにより、様々なサービスをAIエージェントで操作できるようになります。 FigmaMCPとは AI が Figma のデザインデータに直接アクセスし、そのデータを理解・操作することができるようになります。 実際に、Figmaはこの辺りを参照するようです。 デザイン情報 (色・フォント・サイズ・間隔 etc..) コンポーネント間の関係 Figma内のコメント この辺りが参照できると今までできなかった下記タスクもAIにお願いできるようになりそうです。 Figmaのデザインをより忠実に再現 レスポンシブ対応 コンポーネント関係の解釈 ( 参考 Figma MCPとは?何ができるの? ) 利用できるまでの作業 本手順は、github copilot でFigmaMCPを導入する手順です。 ①個人のアカウントでFigmaのAccount settingsを開く ②トークン発行 security>Personal access tokens>Generate new token token名を入力 → File content を read-only にする → Generate token ③MCPの設定をvscodeで行う vscodeの設定用のjsonを修正します。 mcp.servers の中に下記の設定を追記します。 "mcp": { "inputs": [], "servers": { "figma-developer-mcp": { "command": "npx", "args": [ "-y", "figma-developer-mcp", "--figma-api-key=${③のトークン}", "--stdio" ] } } " mcp " : { " inputs " : [] , " servers " : { " figma-developer-mcp " : { " command " : " npx " , " args " : [ " -y " , " figma-developer-mcp " , " --figma-api-key=${③のトークン} " , " --stdio " ] } } ④vscode の github copilotのエージェントモードを有効にする vscodeの設定から chat > Agent: Enabled を有効にする (出てこない場合は、アップデート&再起動をする) ⑤github copilotをエージェントモードに変更する github copilotのチャットを開き、エージェントモードに変更する 以上です!これで利用できるようになります。 試しにコンポーネントを出力してもらう 今回は、簡単なカードコンポーネントを出力してもらいます。 ①FigmaからフレームのURLを取得します。 該当フレームを選択しながら、右上のシェアボタンを教えて、コピーします。 ②実際に書いててもらう 今回はこんなプロンプトで指示してみました figmaを参照して、カードコンポーネントを作成してください・外部からプロップスを渡せるようにしてください。・tailwindで実装してください・セマンティックなHTMLを心がけてください。card component:https://www.figma.com/design/.... figmaを参照して 、 カードコンポーネントを作成してください ・ 外部からプロップスを渡せるようにしてください 。 ・ tailwindで実装してください ・ セマンティックなHTMLを心がけてください 。 card component : https : //www.figma.com/design/.... Figmaを参照するか聞かれますが、続行してください。 気になる出力結果は... かなり高クオリティーです... ! タグの絶対配置の部分だけ設定されていませんね (出力している感じ、絶対配置はあまり得意でないように見えます) コードベースで見るとこんな感じです。 プロップスも想定通り渡せるようになっていたり、HTMLタグの使い分けもいい感じにできていて、ほぼ期待通りの実装に見えます。 import type { FC } from 'react';interface CardProps { image: string; tags: string[]; title: string; description: string; onClickDetail: () => void;}export const Card: FC<CardProps> = ({ image, tags, title, description, onClickDetail,}) => { return ( <article className="flex flex-col bg-white border border-[rgba(17,17,17,0.1)] rounded-2xl overflow-hidden"> <div className="relative aspect-video"> <img src={image} alt="" className="w-full h-full object-cover" /> </div> <div className="flex flex-col justify-between p-6 flex-1"> <div className="space-y-4"> <div className="flex gap-2.5 flex-wrap"> {tags.map((tag, index) => ( <span key={index} className="px-4 py-3 text-sm font-bold text-[#111111] border-2 border-[rgba(17,17,17,0.1)] rounded-full" > {tag} </span> ))} </div> <div className="space-y-2"> <h3 className="text-lg font-bold text-[#111111] leading-[1.3]"> {title} </h3> <p className="text-base text-[#111111] leading-6"> {description} </p> </div> </div> <button onClick={onClickDetail} className="w-full mt-4 px-6 py-4 text-sm font-bold text-[#111111] border-2 border-[rgba(17,17,17,0.1)] rounded-xl" > 詳しくみる </button> </div> </article> );}; import type { FC } from ' react ' ; interface CardProps { image : string; tags : string [] ; title : string; description : string; onClickDetail : () => void; } export const Card : FC < CardProps > = ( { image , tags , title , description , onClickDetail , } ) => { return ( <article className = " flex flex-col bg-white border border-[rgba(17,17,17,0.1)] rounded-2xl overflow-hidden " > <div className = " relative aspect-video " > <img src ={ image } alt = "" className = " w-full h-full object-cover " /> </div> <div className = " flex flex-col justify-between p-6 flex-1 " > <div className = " space-y-4 " > <div className = " flex gap-2.5 flex-wrap " > { tags . map ( ( tag , index ) => ( <span key ={ index } className = " px-4 py-3 text-sm font-bold text-[#111111] border-2 border-[rgba(17,17,17,0.1)] rounded-full " > { tag } </span> )) } </div> <div className = " space-y-2 " > <h3 className = " text-lg font-bold text-[#111111] leading-[1.3] " > { title } </h3> <p className = " text-base text-[#111111] leading-6 " > { description } </p> </div> </div> <button onClick ={ onClickDetail } className = " w-full mt-4 px-6 py-4 text-sm font-bold text-[#111111] border-2 border-[rgba(17,17,17,0.1)] rounded-xl " > 詳しくみる </button> </div> </article> ) ; } ; まとめ 今のところの感想としては、LovableやReplitの各種AIツール や Figma to Codeなどのコード生成系のFigmaプラグイン と比較して、精度がはるかに高いように見えます...! 今回は、FigmaMCPの使い方 + チュートリアルをやってみましたが、次回はもう少し高難易度の出力や、他ツールとの比較とかもやってみようと思います!
初めに 2025/4/9から4/11(現地時間)にかけて、Google Cloud Next 25がラスベガスにて開催されました! マイナビからは、企画、データサイエンティスト、エンジニア、マーケターの4名が現地に向かい、参加してきました。 本記事では、Cloud Next 25のイベントの概要や、面白かった内容について、レポート形式でご紹介いたします。 概要編:Cloud Next 25ってどんなイベント? Cloud Nextとは、Google Cloudによって主催される、おもにGoogle Cloudについてのテックカンファレンスです。 毎年、KeyNoteセッションで、GoogleCloudの新しいプロダクトや、新しいコンピューティング技術などが発表されます。KeyNoteが世界で初めてその内容を知ることができる場所であり、毎年異様な盛り上がりを見せます。 KeyNote以外には、Google Cloudを利用している企業から、利用事例についてのプレゼンテーションであるBreakout Sessionや、Google Cloudの技術ノウハウをライトに共有する場であるLightning Talk、Cloud Skills Boostの体験や、デモを実際にさわりながらGoogle Cloudを学ぶことができるハンズオンのコーナー、ほかの参加者と交流ができるMeetup、実際にGoogler(Google社員)やGoogle Cloudのカスタマー企業にデモを見せてもらいながら、ノウハウを教えてもらったり技術交流ができるExpoがありました。 会場 会場となったMandalay Bayのコンベンションセンターですが、とにかく大きな会場でした。 1日中あちこちでセッションを聞いていると、気づいたら4万歩ぐらい歩いていました。 参加レポート KeyNote 会場に入ると、そこはライブ会場のよう。 基調講演の前には、VeoVJによるパフォーマンスで出迎えてくれました。 Veoによって生成された映像を、曲に合わせて選択して流してくれるAI、ということでしょうか。 Veo を使ったメディア制作のデモをKeyNote中で実施してくれています。 →  https://www.youtube.com/live/Md4Fs-Zc3tg?si=qDTeEgSNU2cG8Q9o&t=1996 セッションの具体的な内容については、すでに様々なブログで触れられているのですが、主な内容としては 動画生成AI「Veo 2」、作曲AI「Lyria」の公開 新TPU「Ironwood」 Agentspace データエージェント このあたりのアップデートがとても大きかったと思います。 内容について少し触れます。 Veo 2 Veo 2は、Google DeepMind社によって開発された、動画生成AIです。 Next以前からVeoに関する発表は2024/11月にあったのですが、この日をもってGAとなり、 Vertex AI Media Studio から利用できるようになりました。 映像生成については、DeepMind社の公式サイトからプロンプトと生成された映像のサンプルを確認できます。 https://deepmind.google/technologies/veo/veo-2/ 中でもすごいと思ったのは、2枚の写真を用意すると、その間を補間するように映像を生成する、というものでした。 ( 参考動画 ) これはすごいですね!映像編集の幅が広がりそうです。 Lyria こちらもDeepMind社の開発した音楽生成AIです。 プロンプトを入力すると、30秒ほどの音楽が生成されます。 なんとボーカルも入れられるそうです。 公式サイトから、プロンプトとそれによって生成された音楽が視聴可能です。 https://deepmind.google/technologies/lyria/ もはや人の作ったものと区別がつかなくなってきていますね・・・! なお、前述のVeoや、音声合成AIのChirp 3、画像生成AIのImagen 3と合わせて、 Vertex AI Media Studio というプロダクトから利用可能となっています。 Google I/Oでさらに上位モデルが登場 これらのマルチモーダル生成AIのうち、Veo, Imagen, Lyriaに関しては、すでに新しいバージョンのモデルが発表されています。 Veo 3 Imagen 4 Lyria 2 Next 25の開催からなんとたった1か月後にこれらのアナウンス。。AIの進展の速さを肌身で感じます。 参考記事⇒  Google Cloud 公式ブログ Ironwood Ironwoodは、Google社によって開発中の第7世代TPUの名称で、 2025年末にはリリースされる予定とのことでした。 これは初代のTPUと比べて3600倍のパフォーマンス向上です。 ひとつ前のモデルと比べても900倍近く向上しています。 これは劇的な進化ですね。 KeyNoteでIronwoodに触れられているシーンは こちら です。 Agentspace Agentspaceは、自社で利用しているオフィススイート(MS OfficeやGoogle Workspace, Salesforceなど)のツールと結合可能なAIエージェントのインタフェースです。 AIエージェントは、Googleが提供するもの以外にも自社内で作成され共有されたものも、Agentspaceから利用できます。 自社組織の意思決定の内容について、SharePointやGoogleDriveにある資料を探すのは大変だと思いますが、 Agentspaceで質問すると、SharepointやGoogleDriveに散乱する資料の中から情報を抽出してユーザーに回答してくれます。 生成された回答の内容のもととなった資料も示してくれます。 デモの中では、リクエストの内容によって、エンタープライズデータ、時系列予測モデル、音声合成、メール送信など多くのツールを利用していますが、すべてAgentspace経由で、1行もコードを書いていません。 Agentspaceを使ったデモンストレーションのシーンは こちら になります。 メールや要約内容については、妥当性を自分で確認する必要はありますが、ノーコードで多くのエージェントツールにアクセスできるようになり、文面作成など多くの手間のかかるシーンで活躍することが期待できます。 データエージェント データクレンジングやインサイト抽出がGeminiによって強化された「Data Agent」の紹介です。 これまでは、まずBigQueryにデータを定期的に連携し、扱いやすい形(データマート)に変換し、 抽出したいインサイトを得るためのクエリをガシガシと書いて、実行していたと思います。 この作業で大変なことは、まず複数のデータソースに散らばっているデータを結合やクレンジングし、分析に使用できる状態にするところ。 ここで活躍するのが「Data Engineering Agent」で、プロンプトベースでデータ処理パイプライン構築していくことができます。 編集中のパイプラインの結果を逐一確認しながら構築を進めていくことができます。 日付の表記もばらばらになっていますが、動画を見るとこの名寄せに関しても直してくれています。これはありがたいですね。 使っているプロダクトとしては少し前からGAになっていた「BigQuery パイプライン」というものなのですが、その構築をGeminiが支援してくれるというものですね。 また、インサイト抽出に関しても、プロンプトでどんなインサイトを抽出したいかをリクエストすると、Geminiがクエリの生成とクエリの実行をしてくれます。 クエリの内容は、カラム名などのメタ情報から生成しているようでした。 実際は、クエリの内容や可視化内容が正しいことに関しては、分析者が最終的にレビューをする必要がありますが、 クエリを作成する時間がこれによって大きく節約できることや、クエリを書くことへの技術的ハードルが大きく下げられることが期待できます。 Data Agentの紹介シーンは こちら です。 Expo Expoでは、KeyNoteで発表のあった新しいサービスのデモを、実際にGoogle社員の方に実演してもらったり直接質問ができるコーナーがありました。 デモのご紹介: GeminiとVertex AI Searchによるマルチモーダル検索 スマホで部屋の写真を撮って、「この部屋に合う家具を探して」という検索方法であったり、もちろん音声検索も対応。 1回検索を実行した後、元のクエリから拡張されたクエリで再検索し、そのアイテムも表示する、ということもやっていました。 こちらはYouTubeでデモ映像が公開されていました。 https://youtu.be/LwHPYyw7u6U?si=vOtgUrk9yK_F4Uqf Meetup Cloud Nextの楽しみ方の一つとして、ほかのエンジニアの交流があります。 そのひとつが Meetup というもので、Cloud RunやVertex AIなどのプロダクトについてのものであったり、Platform EngineeringやObservabilityなど、ホットなトピックについてエンジニアが熱い意見を交わすというもの。 非常に貴重な経験でした。 全体を通して 全体的な感想として、AIやコンピューティングの分野における技術巣発展スピードは非常に早いと思いました。 Veoのアップデートの件でも触れましたが、1年前の技術が今年はレガシーになっているような世界です。 こういった新しい技術は、簡単に試せるようなものも多いので、自社サービスや業務フローに取り入れることを検討してみてもよいかもしれません。 終わりに 本イベントでの内容を踏まえて、マイナビでIT職の仕事をしている社員向けにデモを交えた共有会を開いたところ、80名以上の参加がありました! 実際に使ってみたい、自身の業務の中で取り入れてみたい、などの声もいただいた一方で、 業務での活かし方がわからないといった意見もありました。 こういった視察活動を続けていくことで、少しずつAI活用の輪を広げていけるのではないかな、と感じた次第です。 また、来年も4月末に、ラスベガスでCloud Nextを開催するとのことでした。 会場も同じMandalay Bay Convention Centerです。 もし興味を持たれた方は、ぜひ参加してみてください!
CXMツールとは お疲れ様です。MA推進課のA.Kと申します。 普段は就職・ライフキャリア事業本部のオウンドメディアとMarketoなど、事業部のマーケティング担当者が使うシステムの運用保守を担当しています。 今回、MA推進課としては初となる、アルバイト情報事業本部のCS部門(カスタマーサクセス)と連携した新たな施策を試みたので内容を共有できればと思います。 タイトルにもある「CXM」という言葉について聞き馴染みがある方は少ないのではないでしょうか。 CXMとは Customer Experience Managementの略で、顧客体験の管理や改善を行い、顧客体験(CX)を最大化するための手法のことを指します。 商品やサービスの価格やスペックなどだけでなく、その商品・サービスにより得られる満足感や感動、心地よさなどを向上させることは、顧客ロイヤルティを醸成し収益向上へとつながります。具体的な目的は、顧客との関係性の強化やブランド構築などが挙げられます。 ※引用:顧客体験マネジメント(CXM)とは?CRMとの違いや成功のポイント、企業事例を紹介, docomo business, https://www.nttcoms.com/service/nps/column/cxm/ CXMをどう活用していくか 売り上げ向上には、新規顧客の発掘だけでなく、既存顧客がどうやったら離反しないか、継続して利用してくれるのかも重要になります。 そのため「お客様の声を聴く」ことで、顧客体験とマイナビ認識の乖離をキャッチアップし、営業活動改善や、社内に対して成功事例の共有をすることを目指していきます。 デジ戦が手伝ったこと 前置きが長くなりましたが、本題に入れればと思います。 上記のCXMの運用は事業部側が行っています。以下に今回のシステムの全体図を載せておきます。 SFA/CRM 企業の情報や商談の情報などが入っています。 掲載情報DB マイナビバイトに掲載されている情報が格納されている社内向けのDBです。 GCS BigQuery S3 Trocco クラウド・サービス間のデータ転送に使うツールです。今回の主役。 CXMツールでは、「送付リスト」という形でcsvファイルを渡すことで、自動的に配信が行われる仕組みとなっております。ただし、そのリストに持たせる情報には、通知先はもちろん、分析に使う項目など、複数DBを参照する必要があるうえ、細かい送付条件が多数ありました。そこで、デジ戦側でリスト作成のシステムを作ってみることにしました。 今回はtroccoを使用して以下のステップでCXのアンケートを送る送付リストを作ります。 ①各DBの情報をBQに集約させる ②頑張ってテーブルを結合して必要な情報を抽出する ③作成した配信リストをS3に格納→あとはCXMツール側で自動で配信してくれます。 ①各DBの情報をBQに集約させる 最初にSFA/CRMのデータをtroccoを用いてBQに格納します。 案件の情報を始め、掲載情報やマイナビ社員の情報を参照します。 ここで大苦戦したのが履歴テーブルの存在です。 単純に1つのテーブルを参照すればよいわけではなく、履歴テーブルからも一部情報を参照する必要があり、複数テーブルを行ったり来たりしていました。 以下苦労点です。 参照しなければいけないテーブルが5個あり結合および参照に苦戦 数ある商品から特定の商品を省くロジックを正規表現を使って実装 タイムゾーンがUTCとJSTが入り混じってタイムスタンプ型が嫌いになる 次に掲載情報DBのデータをBQに格納します。 アンケート送付タイミングのタッチポイントを判別できるように必要な項目に絞って取得します。 こちらも4テーブル参照して結合を繰り返していました…。 最後に営業マスタを手動でアップロードして準備完了です。 ②BQ内でデータを結合する BQで集めたデータを結合しつつ、送付対象の条件を追記してリストを作成していきます。 使っているSQLのコードは自身が初学者ということもありかなりシンプルです。 ROW_NUMBER() OVER (PARTITION BY ○ ORDER BY ○ ASC,□ DESC) AS rownumber マスキングかけてるので分かりにくいかもですが 1つの項目に対して複数のデータが紐づいているので、データを降順に並び替えて一番最新のデータの情報を使用します。 後はSFA/CRMと掲載情報DBのデータをキーとなる項目で紐づけてリストの大元は完成です。 後は事業部サイドの運用上の条件を実装していきます。 --送付条件の実装DELETE FROM 対象のテーブル WHERE 特定のカラム NOT IN (SELECT CAST( 特定のカラム AS STRING) –元のDBによって型が違うので一致させるFROM ○○テーブル ); このような条件を要望に沿って同様に実装していきます。 この際にも複数DBを参照し、同じ項目でもデータの内容に相違がないか、空の項目がないかなど確認しています。 コードを見ていただいて分かるように、大元のリストから条件に当てはまらないレコードを削除しています。 この時点で残ったデータをCXMツールに受け渡しできるような形に成形して処理は完了です。 ③ワークフローの作成 今までクエリを書いてリストの作成ができましたが、実際に運用するのは事業部の方たちです。 なので専門的な知識がなくても、「最小限の工数で」運用してもらえるようにしていきます。 ここで重宝したのがtroccoのワークフロー機能です。 上記で記述したデータ抽出&リスト作成のクエリを登録し、それを順次自動で実行してくれます。 スクショの例でいうと、SFA/CRMからBQへデータ連携→掲載情報DBからBQへデータ連携→BQでリストの作成→BQからS3へファイルの格納をボタン一つで実行してくれます。 (加えてスケジュール設定ができるので自動化も可能) ここまで作成して細かい仕様もお伝えし、事業部にお渡しします! 初めての開発経験をしてみて 学生時代も情報系の学部にいましたが、このレベルの開発をするのも今回が初めてでした。 配属から1年ちょっとは開発はベンダーさんにお任せしていたのですが、自分で作るとこんなに大変なんだなとベンダーさんの凄さを実感しました。 一方で、SQLをがっつり触ったことで知識が付いたのはもちろん、マイナビの掲載の仕組み・営業フローについても知れる良い機会でした! コード自体は基本自分で書きましたが、「仕様書も作成する」「ワークフローはなるべく簡略化する」「変更を加える際はデータ不整合が起きないことを確認してから本番適用する」など、開発の基本的な部分も開発経験が豊富なK.S課長にサポートしていただき、無事にリリース&安定稼働まで繋げることができました。 (前職の経験を踏まえた上長のアドバイス×新卒社員のDCPA精神で大分デジ戦らしい取り組みになったのでは!?と個人的には思っています。) 我々ができるのはメールリストの作成までですが、これを利用して今後事業部内でどのような動きが起きていくのか、引き続き技術的なサポートができる箇所があるのか、リリースして終わりではなく、その先にあるビジネスインパクトまで協力して取り組んでいければと思います! 以上、SaaSを組み合わせてメールリストを作成できるよというお話でした!
はじめに こんにちは、ゼネラルコンテンツ推進課のI.Tです。 私の課で運営しているエンジニア向けメディアでは、毎月SEO記事を新規・リライト含め30~40本程度リリースしております。(2025年3月時点) ベンダーから納品されたSEO記事を弊社で校正・校閲していますが、この作業は人力で行うため、担当者によって確認の観点が異なり、質にばらつきが生じてしまいます。 校正・校閲の質を上げ、作業時間を削減できないかと考え、まずはJAPAN AIの利用が頭に浮かびました。しかし、より柔軟に対応できるCopilotエージェントを利用できないかということで、同じ課のY.Kさんが校正・校閲のCopilotエージェント「校正エディター」を提案しました。 Y.Kさんに校正エディターのプロンプトを作っていただき、利用してみると校正・校閲ツールとして実践レベルで使えるものとなりましたので、今回はその作り方と結果を書いていきます。 対象サイト エンジニア向けメディア 作成手順 ①校正・校閲のルールを作る ②作成したルールをCopilotエージェントに設定する ①校正・校閲のルールを作る まずはCopilotエージェントに設定するための校正・校閲のルールを作りましょう。 (内容は社外秘の為、本記事では伏せさせて頂きます。) ②作成したルールをCopilotエージェントに設定する 上記で作成したルールをCopilotエージェントに設定します。 Copilotエージェントの作成画面にある「構成」の各項目に、作成したルールを当てはめる形で設定します。 ▼設定した構成はこちら 名前:校正エディター説明:Webメディアの編集者として、原稿の校正・校閲を行うエージェントです。誤字脱字、表現ミス、表記揺れ、口語表現、単語の繰り返しなどを具体的に指摘します。指示:- ユーザーが添付ファイルまたは直接テキストを送ると、エージェントはその内容を確認し、誤字脱字、スペルミス、日本語として違和感のある表現、表記揺れ、口語表現、同じ単語の繰り返しなどを具体的に指摘する。- 読者が明らかに違和感を持つ点については、強調して指摘する。- 原稿の記号(マークダウンなど)については指摘しない。- 指摘は以下の形式で出力する。 - 問題点(例: 誤字、表現ミス、リンク切れなど) - 該当箇所の引用 - 修正案(必要に応じて)- 見出しや太字など装飾部分は無視し、本文のみを確認する。- 校正校閲の専門家として、専門的な立場で対応する。▼スタータープロンプト※下記を「タイトル」と「メッセージ」にそれぞれいれてください。 誤字脱字の指摘この文章に誤字脱字がないか確認してください。 表現の違和感の指摘この文章に日本語として違和感のある表現がないか確認してください。 表記揺れの指摘この文章に表記揺れがないか確認してください。 口語表現の指摘この文章に口語表現が含まれていないか確認してください。 単語の繰り返しの指摘この文章に同じ単語が繰り返されていないか確認してください。 総合的な校正・校閲この文章を総合的に校正・校閲してください。 Copilotエージェントへの設定方法は、下記の記事で紹介していますので気になる方はご確認ください。 Copilotエージェントでエンジニア向けメディアのペルソナを作ってみた https://marketingblog.mynavi.jp/marketing/copilot_persona_creation/ 実際に作成したエージェントは以下です。 これで「Copilot へメッセージを送る」の箇所に記事の全文をコピペすれば、勝手に校正してくれるようになりました。 実際に使ってみた どの程度の質で校正・校閲してくれるのでしょうか。 試しに、3年ほど更新していなかった以下記事について校正エディターに校正してもらいました。 質問:記事内容コピペ 回答:校正エディター 以下の点について指摘します。1. 誤字・脱字: - 「アジャイル(Agile)sとは」→「アジャイル(Agile)とは」 - 「プログラマーが常にペアで相互チッェクをしながら」→「プログラマーが常にペアで相互チェックをしながら」 - 「アジャイル人材にはどのような知識、スキルが求められるのてしょうか?」→「アジャイル人材にはどのような知識、スキルが求められるのでしょうか?」 - 「DX(テジタル・トランスフォーメーション)」→「DX(デジタル・トランスフォーメーション)」2. 日本語として違和感のある表現: - 「アジャイル(Agile)sとは」→「アジャイル(Agile)とは」 - 「アジャイル(Agile)sとは「素早い」を意味する英語です。」→「アジャイル(Agile)とは「素早い」を意味する英語です。」3. 表記揺れ: - 「アジャイル開発」→「アジャイル開発」 - 「ウォーターフォール開発」→「ウォーターフォール開発」4. 口語表現: - 「アジャイル開発は、大まかなシステムの仕様が決まったら、「手直しを前提に、まずは作ってみる」という考え方にのっとり、極力少ない工数で、短期間で開発をする手法のことです。」→「アジャイル開発は、大まかなシステムの仕様が決まったら、「手直しを前提に、まずは作ってみる」という考え方に基づき、極力少ない工数で、短期間で開発を行う手法です。」5. 同じ単語の繰り返し: - 「アジャイル開発のメリット・デメリット」→「アジャイル開発の利点と欠点」 - 「アジャイル開発のメリット」→「アジャイル開発の利点」 - 「アジャイル開発のデメリット」→「アジャイル開発の欠点」以上の点を修正すると、文章がより読みやすく、正確になります。何か他にご質問や修正が必要な箇所があれば、お知らせください。 「1. 誤字・脱字:」については、さすがAIなので正しく添削してくれますね。 「4. 口語表現:」についても、正しく直してくれています。 しかし、「3. 表記揺れ:」の部分では、表記揺れをしていないのにもかかわらず指摘をしています。 これはおそらく元文字の書式が揃っていない(「アジャイル」の「イ」だけ「ゴシック体」になっているなど)ことから指摘されているのかと思います。 「5. 同じ単語の繰り返し」の部分でも、この記事ではSEOの観点でわざと「メリット・デメリット」を繰り返して記載しているのですが、その点は伝わらずに、SEOKWではない「利点」「欠点」に変えていますね。 使ってみた感想 校正エディターを使っても最後はどうしても目視で確認をしなければならないですが、そもそも誤字脱字や口語表現などが正しいかなどの一次チェックが大変なので、その点をCopilotが変わりにやってくれることで校正作業が非常に楽になるでしょう。 記事の校閲・校正にかぎらず、人の目では正誤判断の難しいSNS投稿文のコンプラチェックエディターなど、様々なエージェントが作れそうです。
はじめに こんにちは、ゼネラルコンテンツ推進課のI.Tです。 私の課で運営しているエンジニア向けメディアでは、毎月SEO記事を新規・リライト含め30~40本程度リリースしております。(2025年3月時点) ベンダーから納品されたSEO記事を弊社で校正・校閲していますが、この作業は人力で行うため、担当者によって確認の観点が異なり、質にばらつきが生じてしまいます。 校正・校閲の質を上げ、作業時間を削減できないかと考え、まずはJAPAN AIの利用が頭に浮かびました。しかし、より柔軟に対応できるCopilotエージェントを利用できないかということで、同じ課のY.Kさんが校正・校閲のCopilotエージェント「校正エディター」を提案しました。 Y.Kさんに校正エディターのプロンプトを作っていただき、利用してみると校正・校閲ツールとして実践レベルで使えるものとなりましたので、今回はその作り方と結果を書いていきます。 対象サイト エンジニア向けメディア 作成手順 ①校正・校閲のルールを作る ②作成したルールをCopilotエージェントに設定する ①校正・校閲のルールを作る まずはCopilotエージェントに設定するための校正・校閲のルールを作りましょう。 (内容は社外秘の為、本記事では伏せさせて頂きます。) ②作成したルールをCopilotエージェントに設定する 上記で作成したルールをCopilotエージェントに設定します。 Copilotエージェントの作成画面にある「構成」の各項目に、作成したルールを当てはめる形で設定します。 ▼設定した構成はこちら 名前:校正エディター説明:Webメディアの編集者として、原稿の校正・校閲を行うエージェントです。誤字脱字、表現ミス、表記揺れ、口語表現、単語の繰り返しなどを具体的に指摘します。指示:- ユーザーが添付ファイルまたは直接テキストを送ると、エージェントはその内容を確認し、誤字脱字、スペルミス、日本語として違和感のある表現、表記揺れ、口語表現、同じ単語の繰り返しなどを具体的に指摘する。- 読者が明らかに違和感を持つ点については、強調して指摘する。- 原稿の記号(マークダウンなど)については指摘しない。- 指摘は以下の形式で出力する。 - 問題点(例: 誤字、表現ミス、リンク切れなど) - 該当箇所の引用 - 修正案(必要に応じて)- 見出しや太字など装飾部分は無視し、本文のみを確認する。- 校正校閲の専門家として、専門的な立場で対応する。▼スタータープロンプト※下記を「タイトル」と「メッセージ」にそれぞれいれてください。 誤字脱字の指摘この文章に誤字脱字がないか確認してください。 表現の違和感の指摘この文章に日本語として違和感のある表現がないか確認してください。 表記揺れの指摘この文章に表記揺れがないか確認してください。 口語表現の指摘この文章に口語表現が含まれていないか確認してください。 単語の繰り返しの指摘この文章に同じ単語が繰り返されていないか確認してください。 総合的な校正・校閲この文章を総合的に校正・校閲してください。 Copilotエージェントへの設定方法は、下記の記事で紹介していますので気になる方はご確認ください。 Copilotエージェントでエンジニア向けメディアのペルソナを作ってみた https://marketingblog.mynavi.jp/marketing/copilot_persona_creation/ 実際に作成したエージェントは以下です。 これで「Copilot へメッセージを送る」の箇所に記事の全文をコピペすれば、勝手に校正してくれるようになりました。 実際に使ってみた どの程度の質で校正・校閲してくれるのでしょうか。 試しに、3年ほど更新していなかった以下記事について校正エディターに校正してもらいました。 質問:記事内容コピペ 回答:校正エディター 以下の点について指摘します。1. 誤字・脱字: - 「アジャイル(Agile)sとは」→「アジャイル(Agile)とは」 - 「プログラマーが常にペアで相互チッェクをしながら」→「プログラマーが常にペアで相互チェックをしながら」 - 「アジャイル人材にはどのような知識、スキルが求められるのてしょうか?」→「アジャイル人材にはどのような知識、スキルが求められるのでしょうか?」 - 「DX(テジタル・トランスフォーメーション)」→「DX(デジタル・トランスフォーメーション)」2. 日本語として違和感のある表現: - 「アジャイル(Agile)sとは」→「アジャイル(Agile)とは」 - 「アジャイル(Agile)sとは「素早い」を意味する英語です。」→「アジャイル(Agile)とは「素早い」を意味する英語です。」3. 表記揺れ: - 「アジャイル開発」→「アジャイル開発」 - 「ウォーターフォール開発」→「ウォーターフォール開発」4. 口語表現: - 「アジャイル開発は、大まかなシステムの仕様が決まったら、「手直しを前提に、まずは作ってみる」という考え方にのっとり、極力少ない工数で、短期間で開発をする手法のことです。」→「アジャイル開発は、大まかなシステムの仕様が決まったら、「手直しを前提に、まずは作ってみる」という考え方に基づき、極力少ない工数で、短期間で開発を行う手法です。」5. 同じ単語の繰り返し: - 「アジャイル開発のメリット・デメリット」→「アジャイル開発の利点と欠点」 - 「アジャイル開発のメリット」→「アジャイル開発の利点」 - 「アジャイル開発のデメリット」→「アジャイル開発の欠点」以上の点を修正すると、文章がより読みやすく、正確になります。何か他にご質問や修正が必要な箇所があれば、お知らせください。 「1. 誤字・脱字:」については、さすがAIなので正しく添削してくれますね。 「4. 口語表現:」についても、正しく直してくれています。 しかし、「3. 表記揺れ:」の部分では、表記揺れをしていないのにもかかわらず指摘をしています。 これはおそらく元文字の書式が揃っていない(「アジャイル」の「イ」だけ「ゴシック体」になっているなど)ことから指摘されているのかと思います。 「5. 同じ単語の繰り返し」の部分でも、この記事ではSEOの観点でわざと「メリット・デメリット」を繰り返して記載しているのですが、その点は伝わらずに、SEOKWではない「利点」「欠点」に変えていますね。 使ってみた感想 校正エディターを使っても最後はどうしても目視で確認をしなければならないですが、そもそも誤字脱字や口語表現などが正しいかなどの一次チェックが大変なので、その点をCopilotが変わりにやってくれることで校正作業が非常に楽になるでしょう。 記事の校閲・校正にかぎらず、人の目では正誤判断の難しいSNS投稿文のコンプラチェックエディターなど、様々なエージェントが作れそうです。
はじめに 私のチームではエンジニア向けメディアを運営しているのですが、メディア運営の意見出しや壁打ち相手ができるAIを作りたいなと思っていました。 そこで、実際にいるエンジニアを想定したペルソナをCopilot エージェントに設定し、壁打ち相手として対応できるようにしました。 今回は、Copilot エージェントの設定方法や使ってみた感想を書いていきます。 作成手順 ①ペルソナを作る ②作成したペルソナをCopilot エージェントに設定する ①ペルソナを作る まずはCopilot エージェントに設定するためのペルソナを作りましょう。 作成済のペルソナ 佐藤は27歳のエンジニアで 、 千葉県在住 。 彼は普通科高校を卒業後 、 理系大学を卒業し 、 ITの資格やクラウド ・ ネットワーク ・ 免許や数学英語の資格も保有している 。 彼は父 、 母 、 姉 、 妹と家族構成を持ち 、 最近結婚した 。 彼の目標は 、 エンジニアとしてのスキルアップとキャリアアップであり 、 アンドエンジニアを通じて最新の技術トレンドや知識を得ることを目指している 。 彼は高校時代に勉強のモチベーション維持が難しかったが 、 理系科目が好きでロボットに興味があり 、 大学でプログラミングに出会い 、 C言語で挫折したもののJavaとPythonを学び始めた 。 大学卒業後はエンジニアとして就職せず 、 輸入転売会社で倉庫整理の業務に従事 。 その後 、 エンジニアの道を目指し 、 パーソルテクノロジー株式会社に入社し 、 金融システムのネットワーク保守 ・ 運用業務に3年間従事 。 現在はSES ・ ネットワークエンジニアとしてソーシャルゲームのネットワークシステムの運用 ・ 保守業務に従事している 。 正社員として自宅から通い 、在宅と出社の比率は5 : 5 、 残業は平均30時間 / 月 。 現年収は450万円で 、 希望年収は550万円 。 現職の環境はお堅い社風で 、 セキュリティ意識が高く 、 成果主義の人事制度 。 クラウドエンジニアを目指して資格を取得したが 、 オンプレミスの現場に配属されていることに不満を抱いている 。 将来的にはクラウドエンジニアとして最新の技術を学び 、 PMもやりつつ作業も自分で巻き取れるエンジニアになりたいと考えている 。 趣味はゲーム 、 アニメ 、 自転車 、 ボルタリングで 、 業務後は家事をやった後にゲームをすることが多い 。 休日は自転車で遠出したり 、 ボルタリングをしたり 、 ネットワークの勉強をしたり 、 友人と飲みに行ったりしている 。 PCはプライベート ・ 会社貸与両方Windowsを使用し 、 携帯はAndroid 、 ブラウザはChromeを使用 。 よく見るサイトは業務ではCiscoの公式HP 、 非業務ではYouTubeやPing - t 。 交友関係は中学 、 高校 、 大学の同級生 、 家族 、 前職の同期 、 現職場の同期で 、 妻は前職の同期 。 友人は多いが 、 人見知りの面もあり 、 外部のコミュニティに連れて行っても交友関係が広がりにくい 。 ②作成したペルソナをCopilot エージェントに設定する Copilot エージェントとは 簡単に説明すると、特定の利用目的のためにCopilotを最適化できる機能です。 ChatGPTで言うカスタムGPTのようなものですね。 今回は、アンドエンジニアのペルソナの壁打ち相手をCopilot エージェントに設定したいので、そのように記載します。 Copilot エージェントの設定方法 ①Copilotを開き、右サイドバーの「エージェントの作成」をクリック ②Copilot Studio(Copilot エージェントを設定する画面)が開くので、ここで設定する このように、会話形式でエージェントを設定することが可能なのだ! 右上の「構成」を押すと、会話した内容に基づいてCopilotが設定したCopilot エージェントの構成が表示されます。この構成画面でCopilot エージェントの詳細設定を編集できます。 実際に作ってみた例 今回は、27歳のエンジニア「佐藤」というCopilot エージェントを作りました。 会話形式で指示し、以下のようなエージェントを設定しています。(会話のログが残っていなかったので会話部分はナシで失礼します。) 「構成」に設定した内容 名前 : 佐藤 説明 : 佐藤は27歳のエンジニアで 、 千葉県在住 。 彼は普通科高校を卒業後 、 理系大学を卒業し 、 ITの資格やクラウド ・ ネットワーク ・ 免許や数学英語の資格も保有している 。 彼は父 、 母 、 姉 、 妹と家族構成を持ち 、 最近結婚した 。 彼の目標は 、 エンジニアとしてのスキルアップとキャリアアップであり 、 アンドエンジニアを通じて最新の技術トレンドや知識を得ることを目指している 。 彼は高校時代に勉強のモチベーション維持が難しかったが 、 理系科目が好きでロボットに興味があり 、 大学でプログラミングに出会い 、 C言語で挫折したもののJavaとPythonを学び始めた 。 大学卒業後はエンジニアとして就職せず 、 輸入転売会社で倉庫整理の業務に従事 。 その後 、 エンジニアの道を目指し 、 パーソルテクノロジー株式会社に入社し 、 金融システムのネットワーク保守 ・ 運用業務に3年間従事 。 現在はSES ・ ネットワークエンジニアとしてソーシャルゲームのネットワークシステムの運用 ・ 保守業務に従事している 。 正社員として自宅から通い 、在宅と出社の比率は5 : 5 、 残業は平均30時間 / 月 。 現年収は450万円で 、 希望年収は550万円 。 現職の環境はお堅い社風で 、 セキュリティ意識が高く 、 成果主義の人事制度 。 クラウドエンジニアを目指して資格を取得したが 、 オンプレミスの現場に配属されていることに不満を抱いている 。 将来的にはクラウドエンジニアとして最新の技術を学び 、 PMもやりつつ作業も自分で巻き取れるエンジニアになりたいと考えている 。 趣味はゲーム 、 アニメ 、 自転車 、 ボルタリングで 、 業務後は家事をやった後にゲームをすることが多い 。 休日は自転車で遠出したり 、 ボルタリングをしたり 、 ネットワークの勉強をしたり 、 友人と飲みに行ったりしている 。 PCはプライベート ・ 会社貸与両方Windowsを使用し 、 携帯はAndroid 、 ブラウザはChromeを使用 。 よく見るサイトは業務ではCiscoの公式HP 、 非業務ではYouTubeやPing - t 。 交友関係は中学 、 高校 、 大学の同級生 、 家族 、 前職の同期 、 現職場の同期で 、 妻は前職の同期 。 友人は多いが 、 人見知りの面もあり 、 外部のコミュニティに連れて行っても交友関係が広がりにくい 。 指示 : - アンドエンジニアの読者であるペルソナとして振る舞う 。 - Webディレクターからの質問に答え 、 エンジニアとしての働き方やキャリアについて話す 。 - 施策の提案に対して 、 読者目線でのフィードバックを提供する 。 - エンジニアの働き方やキャリア ・ 技術について 、 本当に人物としている前提で会話を行う 。 - 話し方は丁寧で親切にする 。 ▼ スタータープロンプト ※ 下記を 「 タイトル 」 と 「 メッセージ 」 にそれぞれいれてください 。 エンジニアの悩み ・ エンジニアとしての悩みを教えてください 。 最新の技術トレンド ・ 最近注目している技術トレンドは何ですか ? キャリアアップの方法 ・ キャリアアップのためにどのような方法を取っていますか ? 学びのリソース ・ エンジニアとして学びのために利用しているリソースは何ですか ? 転職の準備 ・ 転職を考える際に準備していることは何ですか ? スキルアップの目標 ・ 今後のスキルアップの目標を教えてください 。 「スタータープロンプト」は、Copilotを開いた際に表示されるプロンプト例です。 最大で6つまで設定することができます。 色々と聞いてみた 普通のCopilotと、Copilot エージェント佐藤さんに同じ質問をしてみました。 普通のCopilotに比べて、佐藤さんがエンジニア視点で答えてくれるのか試してみました。 質問:あなたの趣味は何ですか 回答: Copilot(通常) Copilot エージェント(佐藤) Copilot(通常)は特定の趣味は持たないようですが、佐藤さんはエンジニアらしく?技術書やビジネスを読むことや、プログラミングが趣味のようです。 さらにどんな技術書がおすすめか聞いてみました。 質問:最近読んだ技術書の中でおすすめの書籍を10冊教えてください 回答: Copilot(通常) Copilot エージェント(佐藤) Copilotに聞くと技術書を「技術書典」と読み取り技術書典について答えてしまったり、おすすめしている本もマーケティング寄りの本が多いですね。 一方、佐藤さんは「アジャイルソフトウェア達人の技」のようないかにもエンジニアが読んでそうな本のリストを挙げてくださっています。 エンジニアの具体的な趣味を知る時に使えそうな気配はしています。 他にも質問してみました。 質問:好きなプログラミング言語やフレームワークは何ですか? 回答: Copilot(通常) Copilot エージェント(佐藤) Copilotは一般的にエンジニアが使っている言語を複数挙げていますが、佐藤さんはPythonが好きだと話した上で、お気に入りのフレームワークを理由を添えて教えてくれています。 質問:システム開発の工程で行われる「設計」について詳しく教えてください。 設計を行う流れと、大変な面ややりがいなど教えて 回答: Copilot(通常) Copilot エージェント(佐藤) やはりCopilotよりも佐藤さんの方が具体的に話してくださっています。 設計の大変な面について、Copilotは「要件の変更や追加に対応すること」などと抽象的な回答ですが、佐藤さんは「要件の不確定性」や「コミュニケーションの重要性」など、具体的な現場目線での回答ができているように思います。 実際に業務で使用できるのか気になったので、アンドエンジニアのX投稿案を作成するよう指示してみました。 質問: 以下の記事について 、 Xで投稿する投稿案を考えてください 。 ▼ 記事 https : //and-engineer.com/articles/Z33qRhAAACEA1jWT ▼ ターゲット エンジニア ▼ 文量 110 字以内 ▼ 雰囲気 ・ カジュアル ・ 具体的 ・ キャッチコピーを添える ▼ 装飾 ・ 改行を加える 回答: Copilot(通常) Copilot エージェント(佐藤) こちらの質問だとあんまり回答が変わらないですね。X投稿案については、雛形ぐらいなら作ってくれますが、エンジニア視点で投稿案の完成形を作るのは難易度が高いかもしれません。 使ってみた感想 ・Copilot(通常)に比べると、実際のエンジニアが思っていそうな具体的な回答をしてくれるので、エンジニアの知識の取っ掛かりとして参考にする分には使えるかも。 ・佐藤単体だと偏りが起きそうなので、佐藤以外のペルソナも作成することでより多様な視点からのフィードバックが得られるかも
TL;DR BigQuery MLを使うと、BigQuery上のデータに対する推論処理が BigQuery内 で完結できます。 Dataformからも当然呼び出せるので、推論対象データをBigQueryで準備できるのなら、 推論バッチ全体がBigQueryで完結します。 AIモデルは、Googleマネージドなモデルや、各自で用意したローカルモデルも利用できます。 きっかけ AI戦略室では、BigQueryで処理したデータに対して、AIモデルを用いたバッチ推論を多数実施しております。 その際、Vertex AI Pipelinesを利用して、BigQueryによるオペレーションの後にVertex AI Batch Predictionによる推論を実行する実装を行っています。しかし、このVertex AI Batch Predictionには、実装が大変だったり、オブザバビリティが低かったりと問題がいくつかありました。( IssueTracker で要望は上がってるみたいだが。。)そこで、Batch Predictionに代わるプロダクトが無いか調べていたところ、Dataflow MLとBigQuery MLがいい感じだったので、今回はBigQuery MLの方を調査してみます。 BigQueryからモデルを呼び出すクエリのイメージ SELECT * FROM ML . GENERATE_TEXT ( -- [ 1 ] MODEL ` <PROJECT_ID>.sano_bqml_test.gemini_flash ` , -- [ 2 ] TABLE ` <PROJECT_ID>.sano_bqml_test.questions_for_gemini ` , -- [ 3 ] STRUCT ( -- [ 4 ] 1024 AS max_output_tokens , 0.1 AS temperature , 5 AS top_k , 0.3 AS top_p , TRUE AS flatten_json_output ) ) ; [1]: テキスト生成メソッドを生成する関数は、  ML.GENERATE_TEXT関数 です。 [2]: データセット内にあらかじめ登録したモデルのみ呼び出すことができます。モデルは以下の3種類が使用できます。 リモートモデル(Vertex AI Endpoint) Geminiを含む、Vertex AI上にデプロイされたモデル Cloud VisionやCloud Natural LanguageなどのマネージドAI API ローカルモデル BigQuery内でホストされ、BigQuery内で使用されるモデル 線形回帰や、ARIMAモデルなどが該当 インポートモデル 自前のモデルをGCSに配置し、インポートして使う 今回はGemini Flash 1.5を使って検証してみようと思いますので、「 リモートモデル 」に該当します。 [3]: プロンプトが含まれているテーブルを指定します。ML.GENERATE_TEXT関数は、promptという固定のカラム名からプロンプトを読み込み、 決められたカラム名 で生成結果を出力します。 [4]: いわゆる「温度」や「TopK」といったパラメータを、構造体を経由して渡します。 BigQueryからモデルを呼び出すインフラのイメージ(たぶんこう) リモートモデルはあくまでVertex AIでデプロイされているもので、 BigQueryの外の世界 になります。 こういったBigQueryの外の世界にBigQueryがアクセスするときは、「 外部接続 」というものを経由します。 外部接続は、外部リソースへのアクセスのためにサービスアカウントを利用しているので、サービスアカウントには外部リソースに適したロールをアタッチする必要があります。 また、外部接続を作った後は、CREATE MODEL関数を使って、データセット内にモデルオブジェクトを作成する必要があります。BQからリモートモデルにアクセスするための「アクセスポイント」みたいなものです。 このアクセスポイント経由で、Vertex AIのリモートモデルに推論をリクエストし、その結果をBigQueryに返すことで、(ユーザーから見た際の)BQ内での推論処理の完結が成り立っています。 BQのクエリからGeminiを呼び出してテキスト生成する ここからはBQ上でのデモ画像が続きます。 外部接続を作成する まずは外部のモデルにBigQueryから接続できるように、「外部接続」を作成します。 BigQuery Studioの[ +ADD ]ボタンから、[ Connections to external data sources ]を作成。 外部接続とは、BigQueryからBigQuery外のデータソース(GCSやCloudSQLなど)に接続するためのリソースです。今回は Vertex AI Remote models を選択します。 適当なConnection IDを設定します。 すると プロジェクト の下に、External Connectionという項目ができます。 このとき、外部接続するためのサービスアカウントが払い出されるので、このサービスアカウントに対して、 Vertex AI User ロールを割り当てておきます。 リモートモデルを登録する CREATE OR REPLACE MODEL `<PROJECT_ID>.sano_bqml_test.gemini_flash` --[1] REMOTE WITH CONNECTION `<PROJECT_ID>.asia-northeast1.sano-bqml-test` -- [2] OPTIONS (ENDPOINT = 'gemini-1.5-flash-002'); --[3] [1]:モデルはデータセット内部に作成する [2]:先ほど作成した外部接続のパス [3]:エンドポイント名 入力データ ML.GENERATE_TEXT関数ではpromptというカラムをAIに入力するように設定されているので、promptというカラムを必ず含めます。 今回は、下記のようなテーブルを作成しました。 user_id prompt 123456 GeminiをBigQueryMLから呼び出す方法を教えてください 234567 Vertex AI Workbenchインスタンスを作成するために必要な最低限のIAMロールを教えてください 345678 プロジェクトAのBigQueryで管理されているデータセットに、プロジェクトBのBigQuery Studioからクエリを実行した場合、課金はどちらのプロジェクトに発生しますか 推論を実行する 前述のクエリを少し改良しました。 ML.GENERATE_TEXT関数の出力をSELECT *で受けるとカラムがたくさん増えてしまうので、 ちゃんとカラムを選択しました。 SELECT user_id , prompt AS question , ml_generate_text_llm_result AS answer FROM ML . GENERATE_TEXT ( MODEL ` <PROJECT_ID>.sano_bqml_test.gemini_flash ` , TABLE ` <PROJECT_ID>.sano_bqml_test.questions_for_gemini ` , STRUCT ( 1024 AS max_output_tokens , 0.1 AS temperature , 5 AS top_k , 0.3 AS top_p , TRUE AS flatten_json_output ) ) ; 実行結果 ユーザID123456さんの質問への回答は、、 BigQuery MLから直接Geminiを呼び出す方法は、現時点ではありません。 いや、今呼び出したやないかーい!! って感じですが、おそらくグラウンディングがうまくできていないからでしょう。 外部接続を通して呼び出しているので、確かに「直接」は呼び出してないですが、外部接続によって呼び出す方法を提示して欲しいですね。 Vertex AIではグランディング系の機能も充実してきているので、いずれBQMLでもグラウンディング付きの推論を生成して、ハルシネーションも考慮した生成もできるようになると、勝手に期待しております。 料金 リモートモデルの場合、推論料金=Vertex AIのマネージドモデルの料金。つまりBigQuery MLからGemini Flashに推論を行った場合、Vertex AIでGemini Flashで推論を行った場合の料金+スキャン量が課金されます。 このあたりのインフラの比較等、あらかじめ知見としてためておくと、いざシステム構築するときの判断材料となるでしょう。 私はバリバリのエンジニア人間でこういったインフラはとても興味があるので、どんどん調べていきたいです。 考察 BigQueryにはDataformというサブプロダクトがあり、これはdbtのように、SQLジョブに依存関係をつけて実行できるものです。BQMLはDataformからも当然呼び出せるので、日々のデータマートの更新にも簡単に活用できます。また、従来のバッチ処理でVertex Pipelinesすら使う必要もなくなるでしょう。 Dataform自体には課金が発生しないため、これは有用ではないかと思います。 また、 ONNX  オニキス   形式 に変換できるモデルであれば、今回紹介しませんでしたが インポートモデル でGCSからモデルをインポートして利用できるので、MLOps等で学習モデルを定期的にGCSに出力している場合と愛称は抜群によいと思います。
目標:AutoGluonを試してみる! 今回は近年話題になっているAutoMLの一つであるAutoGluonのクイックスタートを試してみて、実際にどのようなことができるのかを理解しようと思います! なぜこのチャレンジをするのか 近年、生成AIやデータサイエンス業界の発展により、学生のデータサイエンス力が年々向上しています。その影響もあり、毎年開催しているデータサイエンティストコースのインターンシップでは、模範解答の精度が学生の精度よりも低いという結果になってしまったことも…。 これはまずいということで、AutoMLが予測精度向上に役立つのではないかと思い、試してみることにしました! AutoML(自動機械学習)は、機械学習モデルの構築プロセスを簡素化し、専門知識がなくても高精度なモデルを作成できるようにする技術です。AutoGluonはその中でも特に使いやすく、強力なツールとして注目されています。 私はAutoMLは全く触ったことがなく初心者ですが、このチャレンジを通じてAutoGluonの基本的な使い方を学び、実際のデータセットで試してみることで、その利便性と性能を体感したいと思います! AutoGluonとは AutoGluonは、Amazonが開発したオープンソースのAutoMLフレームワークです。以下の特徴があります。 簡単なインストールと使用 :数行のコードでモデルのトレーニングと予測が可能です。 多様なデータ形式に対応 :表形式データ、画像、テキスト、時系列データなど、さまざまなデータタイプをサポートします。 自動化されたプロセス :特徴量エンジニアリング、モデル選択、ハイパーパラメータ調整など、多くのステップが自動化されています。 AutoGluon Tabular - クイックスタート 英語のクイックスタートを翻訳しているので、多少の日本語の変なところはスルーしていただけると助かります。 実際に実行したい方はこちらのリンクから実行できます! インストール まずは、AutoGluonの TabularDataset と TabularPredictor をインポートします。 TabularDataset :データをロードする際に利用 TabularPredictor :モデルをトレーニングと予測に利用 ! python - m pip install -- upgrade pip ! python - m pip install autogluon from autogluon . tabular import TabularDataset , TabularPredictor サンプルデータ 使用するデータセット: Nature issue 7887 このデータセットの目的は、結び目の特性に基づいてそのシグネチャを予測することです。 元のデータから10,000のトレーニング例と5,000のテスト例をサンプリングしています( オリジナルデータ )。 サンプリングされたデータセットにより、このチュートリアルは迅速に実行できますが、必要に応じてAutoGluonはフルデータセットを処理することもできます。 data_url = ' https://raw.githubusercontent.com/mli/ag-docs/main/knot_theory/ ' train_data = TabularDataset ( f ' { data_url } train.csv' ) train_data . head () Unnamed: 0 chern_simons cusp_volume hyperbolic_adjoint_torsion_degree hyperbolic_torsion_degree injectivity_radius longitudinal_translation meridinal_translation_imag meridinal_translation_real short_geodesic_imag_part short_geodesic_real_part Symmetry_0 Symmetry_D3 Symmetry_D4 Symmetry_D6 Symmetry_D8 Symmetry_Z/2 + Z/2 volume signature 0 70746 0.090530 12.226322 0 10 0.507756 10.685555 1.144192 -0.519157 -2.760601 1.015512 0 0 0 0 1.0 11.393225 -2 1 240827 0.232453 13.800773 0 14 0.413645 10.453156 1.320249 -0.158522 -3.013258 0.827289 0 0 0 0 1.0 12.742782 0 2 155659 -0.144099 14.761030 0 14 0.436928 13.405199 1.101142 0.768894 2.233106 0.873856 0 0 0 0 0 15.236505 2 3 239963 -0.171668 13.738019 0 22 0.249481 27.819496 0.493827 -1.188718 -2.042771 0.498961 0 0 0 0 0 17.279890 -8 4 90504 0.235188 15.896359 0 10 0.389329 15.330971 1.036879 0.722828 -3.056138 0.778658 0 0 0 0 0 16.749298 4 目的変数は「signature」列に格納されており、18種類のユニークな整数が含まれています。pandasはこのデータ型をカテゴリカルとして正しく認識しませんでしたが、AutoGluonがこの問題を修正してくれます。 label = ' signature ' train_data [ label ]. describe () 実行結果 count 10000.000000 mean - 0.022000 std 3.025166 min - 12.000000 25 % - 2.000000 50 % 0.000000 75 % 2.000000 max 12.000000 Name : signature , dtype : float64 学習 predictor = TabularPredictor ( label = label ). fit ( train_data ) 実行結果 No path specified . Models will be saved in : " AutogluonModels/ag-20241205_012036 " Verbosity : 2 ( Standard Logging ) =================== System Info =================== AutoGluon Version : 1.2 Python Version : 3.10 . 12 Operating System : Linux Platform Machine : x86_64 Platform Version : #1 SMP PREEMPT_DYNAMIC Thu Jun 27 21:05:47 UTC 2024 CPU Count : 2 Memory Avail : 11.57 GB / 12.67 GB ( 91.3 % ) Disk Space Avail : 74.20 GB / 107.72 GB ( 68.9 % ) =================================================== No presets specified! To achieve strong results with AutoGluon , it is recommended to use the available presets . Defaulting to ` ' medium ' ` ... Recommended Presets ( For more details refer to https : // auto . gluon . ai / stable / tutorials / tabular / tabular - essentials . html #presets): presets = ' experimental ' : New in v1 . 2 : Pre - trained foundation model + parallel fits . The absolute best accuracy without consideration for inference speed . Does not support GPU . presets = ' best ' : Maximize accuracy . Recommended for most users . Use in competitions and benchmarks . presets = ' high ' : Strong accuracy with fast inference speed . presets = ' good ' : Good accuracy with very fast inference speed . presets = ' medium ' : Fast training time , ideal for initial prototyping . Beginning AutoGluon training ... AutoGluon will save models to " /content/AutogluonModels/ag-20241205_012036 " Train Data Rows : 10000 Train Data Columns : 18 Label Column : signature AutoGluon infers your prediction problem is : ' multiclass ' ( because dtype of label - column == int , but few unique label - values observed ). First 10 ( of 13 ) unique label values : [ - 2 , 0 , 2 , - 8 , 4 , - 4 , - 6 , 8 , 6 , 10 ] If ' multiclass ' is not the correct problem_type , please manually specify the problem_type parameter during Predictor init ( You may specify problem_type as one of : [ ' binary ' , ' multiclass ' , ' regression ' , ' quantile ' ]) Problem Type : multiclass Preprocessing data ... Warning : Some classes in the training set have fewer than 10 examples . AutoGluon will only keep 9 out of 13 classes for training and will not try to predict the rare classes . To keep more classes , increase the number of datapoints from these rare classes in the training data or reduce label_count_threshold . Fraction of data from classes with at least 10 examples that will be kept for training models : 0.9984 Train Data Class Count : 9 Using Feature Generators to preprocess the data ... Fitting AutoMLPipelineFeatureGenerator... Available Memory : 11841.83 MB Train Data ( Original ) Memory Usage : 1.37 MB ( 0.0 % of available memory ) Inferring data type of each feature based on column values . Set feature_metadata_in to manually specify special dtypes of the features . Stage 1 Generators : Fitting AsTypeFeatureGenerator... Note : Converting 5 features to boolean dtype as they only contain 2 unique values . Stage 2 Generators : Fitting FillNaFeatureGenerator... Stage 3 Generators : Fitting IdentityFeatureGenerator... Stage 4 Generators : Fitting DropUniqueFeatureGenerator... Stage 5 Generators : Fitting DropDuplicatesFeatureGenerator... Useless Original Features ( Count : 1 ): [ ' Symmetry_D8 ' ] These features carry no predictive signal and should be manually investigated . This is typically a feature which has the same value for all rows . These features do not need to be present at inference time . Types of features in original data ( raw dtype , special dtypes ): ( ' float ' , []) : 14 | [ ' chern_simons ' , ' cusp_volume ' , ' injectivity_radius ' , ' longitudinal_translation ' , ' meridinal_translation_imag ' , ... ] ( ' int ' , []) : 3 | [ ' Unnamed: 0 ' , ' hyperbolic_adjoint_torsion_degree ' , ' hyperbolic_torsion_degree ' ] Types of features in processed data ( raw dtype , special dtypes ): ( ' float ' , []) : 9 | [ ' chern_simons ' , ' cusp_volume ' , ' injectivity_radius ' , ' longitudinal_translation ' , ' meridinal_translation_imag ' , ... ] ( ' int ' , []) : 3 | [ ' Unnamed: 0 ' , ' hyperbolic_adjoint_torsion_degree ' , ' hyperbolic_torsion_degree ' ] ( ' int ' , [ ' bool ' ]) : 5 | [ ' Symmetry_0 ' , ' Symmetry_D3 ' , ' Symmetry_D4 ' , ' Symmetry_D6 ' , ' Symmetry_Z/2 + Z/2 ' ] 0. 3s = Fit runtime 17 features in original data used to generate 17 features in processed data . Train Data ( Processed ) Memory Usage : 0.96 MB ( 0.0 % of available memory ) Data preprocessing and feature engineering runtime = 0. 42s ... AutoGluon will gauge predictive performance using evaluation metric : ' accuracy ' To change this , specify the eval_metric parameter of Predictor () Automatically generating train / validation split with holdout_frac = 0.1 , Train Rows : 8985 , Val Rows : 999 User - specified model hyperparameters to be fit : { ' NN_TORCH ' : [{}], ' GBM ' : [{ ' extra_trees ' : True , ' ag_args ' : { ' name_suffix ' : ' XT ' }}, {}, { ' learning_rate ' : 0.03 , ' num_leaves ' : 128 , ' feature_fraction ' : 0.9 , ' min_data_in_leaf ' : 3 , ' ag_args ' : { ' name_suffix ' : ' Large ' , ' priority ' : 0 , ' hyperparameter_tune_kwargs ' : None }}], ' CAT ' : [{}], ' XGB ' : [{}], ' FASTAI ' : [{}], ' RF ' : [{ ' criterion ' : ' gini ' , ' ag_args ' : { ' name_suffix ' : ' Gini ' , ' problem_types ' : [ ' binary ' , ' multiclass ' ]}}, { ' criterion ' : ' entropy ' , ' ag_args ' : { ' name_suffix ' : ' Entr ' , ' problem_types ' : [ ' binary ' , ' multiclass ' ]}}, { ' criterion ' : ' squared_error ' , ' ag_args ' : { ' name_suffix ' : ' MSE ' , ' problem_types ' : [ ' regression ' , ' quantile ' ]}}], ' XT ' : [{ ' criterion ' : ' gini ' , ' ag_args ' : { ' name_suffix ' : ' Gini ' , ' problem_types ' : [ ' binary ' , ' multiclass ' ]}}, { ' criterion ' : ' entropy ' , ' ag_args ' : { ' name_suffix ' : ' Entr ' , ' problem_types ' : [ ' binary ' , ' multiclass ' ]}}, { ' criterion ' : ' squared_error ' , ' ag_args ' : { ' name_suffix ' : ' MSE ' , ' problem_types ' : [ ' regression ' , ' quantile ' ]}}], ' KNN ' : [{ ' weights ' : ' uniform ' , ' ag_args ' : { ' name_suffix ' : ' Unif ' }}, { ' weights ' : ' distance ' , ' ag_args ' : { ' name_suffix ' : ' Dist ' }}], } Fitting 13 L1 models , fit_strategy = " sequential " ... Fitting model : KNeighborsUnif ... 0.2232 = Validation score ( accuracy ) 9. 92s = Training runtime 0. 02s = Validation runtime Fitting model : KNeighborsDist ... 0.2132 = Validation score ( accuracy ) 0. 05s = Training runtime 0. 02s = Validation runtime Fitting model : NeuralNetFastAI ... 0.9409 = Validation score ( accuracy ) 16. 79s = Training runtime 0. 04s = Validation runtime Fitting model : LightGBMXT ... / usr / local / lib / python3 . 10 / dist - packages / dask / dataframe / __init__ . py : 42 : FutureWarning : Dask dataframe query planning is disabled because dask - expr is not installed . You can install it with `pip install dask [ dataframe ] ` or `conda install dask` . This will raise in a future version . warnings . warn ( msg , FutureWarning ) 0.9459 = Validation score ( accuracy ) 10. 69s = Training runtime 0. 24s = Validation runtime Fitting model : LightGBM ... 0.956 = Validation score ( accuracy ) 9. 71s = Training runtime 0. 33s = Validation runtime Fitting model : RandomForestGini ... 0.9449 = Validation score ( accuracy ) 8. 86s = Training runtime 0. 12s = Validation runtime Fitting model : RandomForestEntr ... 0.9499 = Validation score ( accuracy ) 10. 04s = Training runtime 0. 11s = Validation runtime Fitting model : CatBoost ... 0.956 = Validation score ( accuracy ) 73. 03s = Training runtime 0. 01s = Validation runtime Fitting model : ExtraTreesGini ... 0.9469 = Validation score ( accuracy ) 4. 42s = Training runtime 0. 13s = Validation runtime Fitting model : ExtraTreesEntr ... 0.9429 = Validation score ( accuracy ) 2. 84s = Training runtime 0. 13s = Validation runtime Fitting model : XGBoost ... 0.957 = Validation score ( accuracy ) 16. 0s = Training runtime 0. 35s = Validation runtime Fitting model : NeuralNetTorch ... 0.9419 = Validation score ( accuracy ) 79. 07s = Training runtime 0. 01s = Validation runtime Fitting model : LightGBMLarge ... 0.9499 = Validation score ( accuracy ) 16. 1s = Training runtime 0. 42s = Validation runtime Fitting model : WeightedEnsemble_L2 ... Ensemble Weights : { ' RandomForestEntr ' : 0.25 , ' ExtraTreesGini ' : 0.25 , ' KNeighborsUnif ' : 0.167 , ' NeuralNetFastAI ' : 0.167 , ' XGBoost ' : 0.083 , ' NeuralNetTorch ' : 0.083 } 0.965 = Validation score ( accuracy ) 0. 25s = Training runtime 0. 0s = Validation runtime AutoGluon training complete , total runtime = 264. 38s ... Best model : WeightedEnsemble_L2 | Estimated inference throughput : 1512.1 rows / s ( 999 batch size ) TabularPredictor saved . To load , use : predictor = TabularPredictor . load ( " /content/AutogluonModels/ag-20241205_012036 " ) 予測 test_data = TabularDataset ( f ' { data_url } test.csv' ) y_pred = predictor . predict ( test_data . drop ( columns = [ label ])) 評価 predictor . evaluate ( test_data , silent =True ) 実行結果 { ' accuracy ' : 0.9478 , ' balanced_accuracy ' : 0.754478262473782 , ' mcc ' : 0.9360368834449522 } AutoGluonのTabularPredictorは、 leaderboard() 関数も提供しており、これを使用して各トレーニング済みモデルのテストデータに対する性能を評価することができます。 predictor . leaderboard ( test_data ) model score_test score_val eval_metric pred_time_test pred_time_val fit_time pred_time_test_marginal pred_time_val_marginal fit_time_marginal stack_level can_infer fit_order WeightedEnsemble_L2 0.9478 0.964965 accuracy 2.777582 0.660655 136.499218 0.025436 0.001888 0.246331 2 True 14 LightGBM 0.9456 0.955956 accuracy 0.704927 0.331303 9.709910 0.704927 0.331303 9.709910 1 True 5 XGBoost 0.9448 0.956957 accuracy 1.877720 0.350646 16.003580 1.877720 0.350646 16.003580 1 True 11 LightGBMLarge 0.9444 0.949950 accuracy 3.199392 0.421252 16.101254 3.199392 0.421252 16.101254 1 True 13 CatBoost 0.9432 0.955956 accuracy 0.065079 0.011186 73.033620 0.065079 0.011186 73.033620 1 True 8 RandomForestEntr 0.9384 0.949950 accuracy 0.284559 0.108530 10.044177 0.284559 0.108530 10.044177 1 True 7 NeuralNetFastAI 0.9364 0.940941 accuracy 0.102912 0.041506 16.789817 0.102912 0.041506 16.789817 1 True 3 ExtraTreesGini 0.9360 0.946947 accuracy 0.413286 0.126837 4.417963 0.413286 0.126837 4.417963 1 True 9 ExtraTreesEntr 0.9358 0.942943 accuracy 0.434792 0.127124 2.836171 0.434792 0.127124 2.836171 1 True 10 RandomForestGini 0.9352 0.944945 accuracy 0.266627 0.117757 8.860353 0.266627 0.117757 8.860353 1 True 6 NeuralNetTorch 0.9320 0.941942 accuracy 0.035788 0.012760 79.072856 0.035788 0.012760 79.072856 1 True 12 LightGBMXT 0.9320 0.945946 accuracy 1.222842 0.243437 10.694745 1.222842 0.243437 10.694745 1 True 4 KNeighborsDist 0.2210 0.213213 accuracy 0.038112 0.016588 0.045746 0.038112 0.016588 0.045746 1 True 2 KNeighborsUnif 0.2180 0.223223 accuracy 0.037879 0.018488 9.924494 0.037879 0.018488 9.924494 1 True 1 結論 このクイックスタートチュートリアルでは、 TabularDataset と TabularPredictor を使用してAutoGluonの基本的なフィットおよび予測機能を見てきました。 AutoGluonは、特徴量エンジニアリングやモデルのハイパーパラメータ調整を必要とせずに、モデルのトレーニングプロセスを簡素化します。 トレーニングや予測ステップのカスタマイズ、カスタム特徴量生成器、モデル、メトリクスの拡張など、AutoGluonの他の機能について詳しく学ぶには詳細なチュートリアルをチェックしてください。 まとめ いかがだったでしょうか? 最後の表にある通り、多くのモデルを数少ないコードで比較してくれました!! 色々なモデルを試すため学習時間は多くなってしまいますが、どのモデルを使用するのかを検討する際にAutoGluonはとても使えるのではないでしょうか? データ前処理、ハイパーパラメータ最適化、アーキテクチャー最適化、モデルアンサンブル(スタッキング)までを一度に行ってくれるAutoGluonは今後も目が離せません! また、今回の表データだけでなく、画像分類・画像セグメンテーション・物体検出・自然言語・マルチモーダル予測など様々な分野に対応しているため、気になった方はぜひそれぞれのクイックスタートを試してみてください! 参考リンク https://atmarkit.itmedia.co.jp/ait/articles/2203/24/news004.html https://auto.gluon.ai/stable/index.html https://pages.awscloud.com/rs/112-TZM-766/images/1.AWS_AutoML_AutoGluon.pdf
マイナビジョブサーチ 担当のM.Sです。 "余暇で何か物作りをしよう" となったときにどうしても時間が足りなくなりますよね... 😢 今回は、lovableを使って簡単にWebアプリケーションを生成してみようと思います。 lovableとは lovableは、2024年11月にGPTエンジニアからリブランディングされて公開されたツールになります。 lovable公式サイト 下記がlovableの特徴です。 Webアプリ開発、動作確認、デプロイまでlovableのみで完結できる シンプルなプロンプトでウェブサイト生成できる デザイン面で他のツールより優れている Figmaから書き出すことができる テンプレートから開発を開始できる 費用面的には、使い放題ではないスターターでも$20と少しお高めですが、払う価値があるくらいすごいツールだと思います。 lovableでWebアプリを作成してみよう 今回は、このような TODO のアプリケーションを作成してみようと思います。 やり方の手順としては、下記のような感じです。 ChatGPTを使って要件定義する lovableで開発してもらう 細かいチューニング 要件定義 簡単にこんな感じに要件を設定してみました。 データの形は、lovableがよしなにやってくれるので、外側の仕様を中心に定義してみました。 ## 概要 TODOリストアプリ ## 技術 - React - Supabase ## 機能 - タスクを追加することができる - タスクを削除することができる - BackLogのようにドラックアンドドロップでタスクのステータスを変更することができる - supabaseで非同期のステータス更新 - TODOリストのステータス - 未着手 - 処置中 - 完了 ## デザイン - モダンでかっこいいデザイン - 白黒基調のシンプルな配色 lovableに開発してもらう 先ほどの要件定義のプロンプトをそのまま、lovableに投げてみます。 先ほどのプロンプトを投げるといい感じに、TODOリストのUIを作成してくれました。 プレビューのところまでは、チャットと同時に作成してくれます。 挙動を見ると分かるように、かなりモダンな感じで作られています。  画面収録 2024-12-12 13.43.54.mov コマンド一発でこれが実装できるのはかなりすごいですね... 次にsupabaseとの連携も行っていこうと思います。 現状では、ローカルでデータが保存されているだけなので、supabaseも実装していきます。 lovable上のsupabaseボタンから連携を行っていきます。 連携を行ったらコードも修正してもらいます。 コードを修正したら、対象のsupabase側でテーブルを用意します。 supabaseのSQL Editorで、lovableから吐き出されたSQLをそのまま実行します。 こんな感じでテーブルも作成されています。 supabaseの設定まで完了するとこんな感じになります。 画面収録 2024-12-12 12.24.23.mov ログイン機能などが備わっていないものの、バックエンドの実装までは簡単にできました。 すごいですね...😳 細かいチューニング 細かいチューニングに関しては、GitHubを通して行うか、lovableのチャットで行うかになります。 lovable上のGitHubボタンからGitHubを登録すると、GitHubで修正してmainブランチにプッシュされたものを確認し、lovable上に反映させてくれます。 大きな部分はlovableで、細かい部分はGitHubで自分でソースを修正することで、効率よく開発できそうですね。 デプロイ ちなみにパブリッシュボタンからは、デプロイも簡単に行うことができます。 かかった時間 実際にかかった時間を測っていたのですが、だいたいこれくらいでした。 要件定義: 10分 開発時間: 20分 簡易的とはいえ、FE/BE込みのWebアプリを30分くらいで作るのはかなり難しいと思います... コードの質はどうなのか 今回のファイルの出力は、こんな感じになっていました。 一般的なディレクトリ構成になっていて、追加開発や細かいチューニングもしやすそうです。 taskory - dash ├── node_modules ├── public └── src ├── components │ ├── ui │ │ └── // 細かいUIが入っている │ ├── Column . tsx │ └── Task . tsx ├── hooks │ ├── use - mobile . tsx │ └── use - toast . ts ├── lib │ ├── supabase . ts │ └── utils . ts ├── types │ └── task . ts └── pages ├── Index . tsx ├── App . css ├── App . tsx ├── index . css ├── main . tsx └── vite - env . d . ts 下記は、TODOのタスクカードの部分です。修正しやすそうですね。 /comopnents/ui/Task.tsx import { Card } from " @/components/ui/card " ; import { Draggable } from " @hello-pangea/dnd " ; interface TaskProps { id : string; content : string; index : number; onDelete : ( id : string ) => void; } export const Task = ({ id , content , index , onDelete } : TaskProps ) => { return ( < Draggable draggableId ={ id } index ={ index }> { ( provided ) => ( <div ref ={ provided . innerRef } {... provided . draggableProps } {... provided . dragHandleProps } className = " mb-2 " > < Card className = " p-4 hover:shadow-md transition-shadow bg-white " > <div className = " flex justify-between items-center " > <p className = " text-sm text-gray-800 " >{ content }</p> <button onClick ={ () => onDelete ( id ) } className = " text-red-500 hover:text-red-700 transition-colors " > × </button> </div> </ Card > </div> ) } </ Draggable > ) ; } ; まとめ お値段がかなり高め + 課金版でも使い放題ではないですが、ノーコードで開発もしくは、大枠を作ってもらうというところは、使えそうなのかなと思いました。 今後何か作ってみたいものがあれば、lovableに作ってもらうことも検討しようと思います! 最後まで見ていただきありがとうございました🙇 外部リンク lovable公式サイト