Murga

個人的に言いたいコト・主張・気持ち。

フロントエンドアプリで CRUD する時の命名規則に迷っている

Rails の Scaffold 機能みたいな要領で、SPA なライブラリの中で、あるリソースの CRUD を行う画面を作りたいとする。その時のクラス名、ディレクトリ構成、メソッド名などのベストプラクティスがイマイチ見つからないので、自分なりに検討してみた。

Rails Scaffold のおさらい

Rails で Scaffolding した時に生成されるリソースは以下のようになる。

Verb URI Pattern Action 備考
GET /users Index 一覧表示
POST /users Create 新規登録 (ID 自動採番)
GET /users/new New 新規登録画面を開く
GET /users/:id Show 照会画面・1件取得
GET /users/:id/edit Edit 編集画面を開く
PUT /users/:id Update 全体更新
PATCH /users/:id Update 一部更新
DELETE /users/:id Destroy 削除

読み方は、左から、HTTP メソッド「Verb」で「URI Pattern」にアクセスした時、UsersController の「Action」メソッドを実行する、という形。

例えば、新規登録画面を開くのは /users/new という URL で、UsersController#new メソッドで登録画面の初期表示用の処理を行う。その登録画面から「登録」ボタンを押した時は、/users という URL に POST 通信して、UsersController#create メソッドで新規登録処理を行う、といった形だ。

フロントエンドアプリの場合

フロントエンドアプリ、ココでは主に Angular を想定しているが、React や Vue.js でも変わらないだろう。要するに API サーバは別にある、SPA なフロントエンドアプリの場合だ。

この場合、API サーバ側の URL は一旦考えなくて良い。RESTful な API 設計がなされていれば、大体以下のような URL パターンになっているはずだからだ。

Verb URI Pattern 備考
GET /users 一覧取得
POST /users 新規登録 (ID 自動採番)
GET /users/:id 1件取得
PUT /users/:id 全体更新
PATCH /users/:id 一部更新
DELETE /users/:id 削除

コレに加えて、もしかしたら /users/:idPOST を作っているかも?でもそれって PUT と変わらないはずだから基本はこうかな?

で、コレとは別に、フロントエンドアプリはどういう構成にしようか、というのが今回の話。

俺が考えた構成

先に「ぼくのかんがえたさいきょうの構成」みたいなものを紹介する。自分が一人で作る時は以下のような構成にしている。Angular 寄りな人間なので、Angular 的なクラスも書いているが、他の SPA フレームワークでも通じると思う。

app/
└ users/
   ├ users.module.ts
   ├ users-routing.module.ts
   ├ user-list/
   │ └ user-list.component.ts
   ├ user-detail/
   ├ user-new/
   └ user-edit/

ルーティングの構成は以下のとおり。

URL コンポーネント名 (クラス名) ファイルパス
/users/index UserListComponent ./users/user-list/user-list.component.ts
/users/show/:id UserDetailComponent ./users/user-detail/user-detail.component.ts
/users/new UserNewComponent ./users/user-new/user-new.component.ts
/users/edit/:id UserEditComponent ./users/user-edit/user-edit.component.ts

削除に関しては、一覧表示 (Index・List) か照会 (Show・Detail)、編集 (Edit) 画面のいずれかから実行すれば良いかと思うので、「削除画面」は用意していない。

基本方針

  • リソースのまとまりを表現するディレクトリは複数形:この場合だと ./users/ ディレクトリは複数形。
  • 各画面を構成するコンポーネント名では単数形:user-detail のように、扱うデータが1つであることを示す。
    • いきなり「IndexComponent」「EditComponent」などと作ってしまうと、「Users」以外の (例えば「Products」など他の) リソースに対する CRUD を作った時に同名のクラスが登場して区別しづらくなるから、単数形のリソース名を接頭辞のように付与している。
  • URL については Rails Scaffold や REST API 設計の真似。

迷っていること

ココまで考えたものの、まだ色々と迷っている。

  • 一覧:URL を /users のみとするか /users/index とするか
    • /users/users/index にリダイレクトすることにしていたりするのだが、最初から /users だけでも良いだろうか。
  • 一覧:コンポーネント名を UserListComponent とするか UsersComponent とするか
    • Angular 公式のチュートリアルでは hero-list.component.ts というクラスが出てくるので、UserListComponent としたが、複数リソースを扱うことを表現するなら、単語を複数形にして UsersComponent でも良いのかも。
  • 照会:URL を /users/show/:id とするか /users/:id とするか
    • Rails Scaffold や REST API の URL 設計だと後者なのだが、それは HTTP メソッドで GET を指定しているから区別が付きやすいのであって、SPA のルーティングの中だと区別が付きにくい気がする。だから URL に show/ を含めるようにしたが、微妙か?照会に関しては後者にしてもいいのかも。
  • 登録:NewCreateRegister (Registration)・Add あたりの単語のどれを使うと、コンポーネント名としてしっくりくるか
    • URL に関しては /users/new で良いと思うのだが、UserNewComponent がどうかなーと思っている。UserCreateComponent だと、そのコンポーネントを呼んだ時にユーザを生成しちゃいそうな気がするし、UserRegisterComponentUserAddComponent は動詞なのが違和感。
  • 更新:URL を /users/edit/:id とするか /users/:id/edit とするか
    • Rails Scaffold の場合は後者だが、Angular のルーティングで :id/edit というルーティングを作ると「ルートパラメータ」として :id が渡せないので edit/:id とした。users/1/edit のように URL 文字列を作ってしまえば遷移はできるものの、ルートパラメータとして指定したいので…。

Rails Scaffold で違和感がないのに、Angular コンポーネントにすると移植しづらいのは、オブジェクト指向で考えた時に、動詞と名詞を変換しないといけないからだろう。Rails の場合は UsersController#show (User を Show する) というように 「Show」という動詞が使えるが、クラス名・コンポーネント名にしようとすると、UserShowComponent もしくは ShowUserComponent というように、落ち着きが悪い。そこで UserDetailComponent というように、「Detail」という名詞を使うようにしたのだが、この変換がしっくりこない箇所がある。特に登録…。

皆様はどうしていますか?ご意見ください。

参考文献

ココまでの内容を考える際に参考にした文献。

Ruby on Rails 5の上手な使い方 現場のエンジニアが教えるRailsアプリケーション開発の実践手法 (Web Engineer's Books)

Ruby on Rails 5の上手な使い方 現場のエンジニアが教えるRailsアプリケーション開発の実践手法 (Web Engineer's Books)

  • 作者: 太田智彬,寺下翔太,手塚亮,宗像亜由美,株式会社リクルートテクノロジーズ
  • 出版社/メーカー: 翔泳社
  • 発売日: 2018/01/24
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

プログラミング中に使う英語、コレだけ気にしておけば英語ができない人も大丈夫、だと思う話

英語ができない人が書くコードは、とにかく物事の関係性が無茶苦茶だ。主述はハッキリせず、クラスの役割もグチャグチャで、オブジェクト指向を理解していないように見える。それはきっと、「概念的な理解」が弱いからだと思っている。物事を適切に抽象化する能力がないのだ。

そんな奴には早いところ仕事を辞めてもらいたいものだが、何故かいつまでも居座りやがるので、マシなコードを書いてもらうために注意してもらうことを考えた。

すなわち、コレから話すことだけ気にしておけば、英語ができない人もそれなりなコードが書けるようになるだろう、というコツだ。

英単語の品詞を必ず確認する

英語ができない奴に限って辞書を引かない。辞書の読み方を知らないからだろう。ホントどうやって成人したんだろう。

これから書こうとする英単語は、Google 検索から Weblio 辞書あたりを使って必ず辞書を引いて、品詞を確認すること。品詞とは、「動詞」「名詞」「形容詞」など、単語の種類を示すものだ。まずはその単語の品詞を知る。

例えば、register は動詞だ。日本語にするなら「登録する」であって、「登録」という名詞ではないのだ (register of と使えば名詞だが)。辞書を引くと分かると思うが、名詞形の単語で「登録」というなら registration だ。

この「品詞」を知っておくと、次に紹介する「文型」に当てはめて、単語を正しい順番で組み立てて文章を作れるようになる。

文型を覚える

英文章の構造は主に5つの「文型」で表せる。

  1. SV
  2. SVC
  3. SVO
  4. SVOO
  5. SVOC

主にこの5つだ。S や V は、大雑把に以下のように覚えておけばいい。英語のできない連中はどうせこれに当てはまらない難易度の単語や言い回しはできるはずがないのでコレでいい。

  • S:主語 … 名詞 (「人 or 物 は」)
  • V:述語 … 動詞 (「〜である」や「〜する」で終わる単語)
  • O:目的語 … 名詞 (「誰に」「何を」に当てはまる)
  • C:補語 … 名詞 (S もしくは O とイコールになる内容で、それをより詳しく説明する単語)

形容詞だとか副詞だとか、コレ以上の細かい文法要素は、プログラミングにおいては覚えなくて良い。

プログラミングにおける文型をオブジェクト指向からおさらいする

コレで、使用したくなった英単語の種類と、英文章の一般的な組み立て方が理解できるようになる。

次は、コーディング時にどのようにコレを当てはめていけばいいか、をおさらいする。ココではめちゃくちゃシンプルに。

  • クラス名 … S (主語) に当たるので「名詞」
  • メンバプロパティ (そのクラスが持つフィールド変数) 名 … コレも S (主語) に当たるので「名詞」
  • メソッド名 … V (述語) に当たるので「動詞」
  • メソッドの引数名 … O (目的語) に当たるので「名詞」

基本は名詞。メソッド名、関数名だけが動詞、と覚えていい。これに則って命名を決めていくと、以下のようになる (TypeScript コードを例にした)。

// User クラス:クラス名は名詞
const user: User = new User();

// 対象の User の名前を知る:メンバプロパティ name は名詞
// 例えるなら「the name of this user」なイメージ。「user の name は…」という作り。
console.log( user.name );

// 対象の User の年齢を設定「する」:メソッド名は動詞 (set) をベースにする
// この場合、「年齢を」(Age) は目的語、引数の値は「〜歳と」と表現できるので補語、つまり全体で SVOC の構造だ。
user.setAge( 25 );
____ ---___ ----
 S    V (O)   C
  • クラスは「何 or 誰」= 名詞。
  • フィールド変数はそのクラスの属性を示す物なので「何」= 名詞。
  • メソッドはそのクラスが行う動作のことなので「〜する」= 動詞。
  • メソッドの引数はその動作の詳細を示すので「〜を」に当てはまることが多い = 名詞。

というワケだ。

これから作ろうとする処理を何という単語で表現するか考える時に、辞書を引かずに英単語を導き出すのはバカがやること。辞書を見て、単語の品詞を確認して、文型に当てはめるのだ。辞書を引かなくて良いのは、単語の品詞を覚えきっているときだけ。僕は今でも毎回辞書を引いて正しい情報を再確認している。

ローカル変数なども原則名詞。何かを「行う」変数、となると、その変数に関数を代入した時ぐらいだろう。結局その変数はメソッドのショートハンドとして命名するので、それが動詞になるのは分かるだろう。

名詞は基本は単数形

ところで、名詞は基本は単数形で使う。複数形を用いるのは、「複数のリソースを扱う場合」。

例えば「ユーザ一覧」は userList と表現しても良いけど、あまり list という単語に意味がないし、実装上の ArrayList を表現しているなら、型で言えば良いので変数名には不要。だから users で良い。

「複数のリソース」というのは、「機能のまとまり」を表現する時にも使える。REST API の URL 設計と同様に、「ユーザ登録画面」「ユーザ編集画面」みたいなコンポーネントのまとまりを表現するディレクトリ名も users と表現すると良い。

言語・用途別にベストプラクティスを調べまくる

「プログラミング 命名規則 メソッド名」などという風に検索すると、良いメソッド名のサンプルが見つかる。例えば「登録」に近い単語で言うと、以下のようなものが出てくる。

  • register
  • add
  • create
  • new

盲目的に「登録 = register」としか思っていないと、この辺のボキャブラリーが貧弱で、全部 register と書いたりする。それぞれの単語の違いや、使うタイミングを考えると、

  • DB に Insert するなどリソースを新たに「生成」する場合は createnew
  • 配列や一覧情報に何かを「追加」する場合は add
  • これらの細かな「登録業務」全体を表現したい場合は register

みたいな使い分けが見出だせるようになる。

で、コレ以外に「こういう場合はこういう言い回しをよくする」「CSS の場合はこういう命名規則をする」みたいなモノがあるので、それらは言語別・用途別に調べてメモしておく。

例えば、「対象データの登録者」「登録日」などの情報を、よく「registerUser」なんて表現したり、「名詞にしなきゃ」と思ったのか、存在しない単語「regist」を使って「registDate」とか書いてたりする。コレは極上のバカだが、ニホンノエスイーでは残念ながらよく見かける。

世界的に一般的な表現の仕方は、createdBycreatedAt だ。コレはオブジェクト指向が理解できていれば、容易に読みやすいコードになることが分かる。つまり、フィールド変数名とその値がイコールで結べるというワケだ。

// 商品情報 ProductItem クラスのデータの登録者を設定する
productItem.createdBy = '山田太郎';  // 「誰が作ったのか?」=「この人が作った」の図式が出来上がる

// 商品情報 ProductItem クラスのデータの登録者を調べる
console.log( productItem.createdBy );  // → 「登録者名」が得られる

こうしたベストプラクティスは、1度調べて1つの文献を見れば十分、というワケではなく、「良いとされているもの」のサンプル数、そしてその信憑性 (= 複数の文献で同じように言われているか) を自分の中で増やしていかなくてはならない。


バカほど調べないで「自分の考え」に固執しがちで、繰り返し文献を読むということを怠り、そのうち「自分の考え」が一般常識から乖離していくのだ。

必ず辞書を引け。毎回同じことを Google 検索しろ。出典のある情報を利用しろ。

ITエンジニアが覚えておきたい英語動詞30

ITエンジニアが覚えておきたい英語動詞30

英語で学ぶプログラミング

英語で学ぶプログラミング