クラスなどの名付けで抽象的にするか具体的にするかで悩んだら

OperationServiceとするかSomeSpecificOperationServiceで悩んだらSomeSpecificOperationServiceを選びます。

ここって、確かに迷いがちなところですが、抽象度が高い名前をつけると責務が大きくなりすぎる傾向が強いので、具体的な名前をつけるほうが私は好みです。

  1. 具体的な名前をつける
  2. いろんな実装を進める上で他にもやらせたいことが増えてきて名前が不適切になる
  3. (1)で作ったクラス名を適切なものに改名するか、(それが思いつかなければ?)具体的な別の名前のサービスを定義するか考える

みたいな順番で考えることが多いです。

これも制約を強めるか弱めるかの選択肢の話に通じるものがあるのですが、

より具体的な名前 ⇒(用途の)制約が強い より抽象的な名前 ⇒(用途の)制約が弱い

と、私は考えています。

制約が弱いものを強めるのは後からやり辛いので、その2択で結果に大差がなさそうなら制約が強い方を選択するという原則(自分でかってに言ってるだけのやつ)に従って、より具体的な名前をつけておく、という選択になる感じです。

私のコードレビュー観点について

仕事でまとめる機会があったので、ブログに残しておきます。

私が考えるレビュー観点は以下の4点に分類できます。

  1. 仕様
  2. 内部品質
  3. セキュリティ
  4. パフォーマンス

1. 仕様を満たしているか

  • 仕様の漏れがないか
  • 仕様の誤りがないか

2. 内部品質

  • 変数名・関数(メソッド)名・クラス名に関してニュアンスを捉えた英単語を選択しているか
  • コメントに嘘がないか
  • 可読性を考慮できているか
    • 込み入った処理の場合は、説明的変数や説明的メソッドを用いるなど
    • ifやswitchを使わない、使っても深くネストしない(せいぜい2つまで)
  • 使用している言語のイディオムや慣習に従った書き方ができているか
  • パフォーマンスよりも可読性を優先してかけているか
    • 可読性が高いコードであればボトルネックを突き止めるのは簡単なため、パフォーマンスの問題が起きてから最適化すれば良い、という考え方。
  • 適切なデザインパターンを適用できているか
  • typoがないか

3. セキュリティ

  • パスワードの類の情報をハードコードしてたり設定ファイルに書き込んでいたりしないか
  • 脆弱性のあるライブラリやフレームワークのバージョンを指定していないか
  • メンテナンスが止まってしまっているライブラリやフレームワークを採用していないか

4. パフォーマンス

  • 無意味に処理が遅くなる書き方をしていないか(Javaのfor文の中で+を使って文字列を結合する、とか)
  • thread safeにも関わらず毎回インスタンスを生成していないか
  • full scanになってしまうSQLになってないか
  • 必要に応じてテーブルのINDEXを定義できているか

超簡単な内容ですが、簡潔にまとめるとこんな感じです。

Spring BootでMVCを自己署名証明書(オレオレ証明書)を使ってHTTPSでListenさせる方法

オレオレ証明書を使ってSpring Bootをhttpsで起動させてると、macがcatalinaでブラウザがchromeの場合にアクセスしてもERR_CERT_REVOKEDと表示されて先に進めない(警告を無視するオプションが提示されない)事象に出くわして4時間溶けました。

めちゃくちゃハマって辛かったので未来の自分と同じことにハマってる誰かのために記事を残しておきます。

何が起きていたか

macOSがCatalinaでブラウザがChromeだと動かないという事象が起きていました。

Spring BootでMVChttpsをlistenさせる方法はググるとたくさん出てくるので簡単だと思っていたのですが全然そんなことありませんでした…。

どうも、Catalinaになったタイミングでセキュリティが厳しくなった?っぽいです。

keytoolのオプションの組み合わせや設定値をいろいろ工夫してもうまく動かず途方にくれていました。

ググるこんなのが出てきたりします。mojaveじゃ起きないらしいですが、私は試していません。

回避方法がないかkeytool localhost certificate chrome ”ERR_CERT_REVOKED"あたりのキーワードでいろいろググってると、海外のどっかの会社のなにかのプロダクトで同じ問題がおきていたらしく、そのコメントのやり取りの中にこのコマンドで再作成すれば動くようになったぜ(超意訳)!ってのを見つけて、動かすために必要なkeytoolのオプションを特定することができました。

Spring Bootで自己署名証明書オレオレ証明書)でHTTPS通信を受け付けるための設定

というわけで、それを踏まえた上で設定手順を書き出していきます。

動作確認環境

  • Spring Boot 2.1.2
    • 2.x系なら同じ設定で動くと思います。
  • macOS Catalina 10.15.2
    • mojaveなら再現しないっぽい…

自己署名証明書作成手順

以下のコマンドで作成できます。

$ keytool -genkey -alias localhost -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore /pass/to/your/keystore.p12 -dname "CN=localhost" -storepass yourpassword -ext ExtendedKeyUsage=serverAuth -validity 825

ポイントは次の2点です。

  • 有効期限を825日以下にする
  • -ext ExtendedKeyUsage=serverAuthのオプションを追加する ※X.509 証明書の拡張機能

この2点を突き止めるのにすごく時間がかかりました。1

なお、対話モードをスキップするために-dnamestorepassも入ってますがここはお好みです。

また、storetypeはPKCS12を指定していますが別にJWSでも問題なく動きました。

Spring Bootの設定内容

server:
  port: 8443 #任意のポート番号で良い
  ssl:
    enabled: true # sslのセクションがある時点でtrueがデフォルトなので省略可
    key-store: /path/to/your/keystore.p12
    key-store-password: yourpassword
    key-store-type: PKCS12
    key-alias: localhost

たったこれだけでhttpsでlistenするように変わっているはずです。

おまけ

httpsでlistenする場合、加えてhttpsのみ通信を許可する設定をいれたくなるかもしれませんが、1.x系で存在していたsecurity.require-ssl=trueが2.x系では削除されているのでJavaで書く必要があります。


  1. ググっては試すの繰り返し。証明書の仕様に詳しくないのでtry & errorが早いと判断した

ReactとVueのどちらを採用するか

掲題について、とりとめもなくメリット・デメリットなどを考えているので、メモを残しておきます。

執筆時点ではReactは経験が非常に浅く、事実や経験というよりはほとんどが思い込みや予想です。

React

メリット

  • フロントエンドをうまく作るために頭が良い人たちが考えた設計や技法を効率良く学べそう
  • シェア一位のため事例が多く、かつFacebookTwitterといった大企業も採用しているため、大抵のことは解決方法が存在していそう
  • React NativeがあるのでNativeアプリ作りたくなったときにReactのノウハウを流用できるはず

デメリット

  • 位置づけがライブラリということもあり、react単体で実現できないことは別ライブラリと組み合わせて実現する必要があり、技術選定のための審美眼とどう組み合わせるかの設計スキルが必要(になりそう)
  • 正しい設計や技法を知らないうちはそれを学ぶまでの学習コストを払う必要があるため、とりあえず動かすまででも相当な時間がかかりそう

イメージ

  • フロントエンド専門あるいはフロントエンドからキャリアをスタートしているツヨツヨな人たちが好んで使ってる
  • 同じデザインかつコンポーネントの分割方針も同じだったらコードも似てくる気がしている
  • React書ける人ならVueとかAngularは楽にキャッチアップできそう
    • Reactを使いこなせる人はつよつよなフロントエンジニア

Vue

メリット

  • とりあえず一通り動かせるようになるまでの学習コストが低い
  • htmlベースベースでSFCを書けるため、HTML/CSS/JSの基本的な知識がある人には書きやすい
  • Vuex,Vue Routerといったコアライブラリを公式サポートしているので技術選定で迷いにくい
  • Nuxt.jsというたいていのアプリでは使われる(コア)ライブラリが全部入りになってる便利なフレームワークがあるので技術選定や設定に割く時間を節約できる
    • 本当にかなり使いやすい
    • RubyでいうRailsのような位置づけだと思ってる

デメリット

  • とりあえず動かせちゃう方法がたくさんあるせいで、正しい設計にたどり着くまでのコストが高い。またそれが故に設計スキルが身につくまでに時間がかかりそう。
  • TypeScriptとVuexの相性がイマイチ(らしい)
  • 事例は増えてきているが、まだシェアが低い
  • 個人(Evan You氏)がメインで進めているため、何らかの理由で彼が突然リタイアした場合に、その後のメンテが止まる可能性がある

イメージ

  • デザイナあるいはバックエンドといったような隣の領域からフロントエンドに手を伸ばしてきた人たちに好まれる
  • 同じ画面デザインかつコンポーネントの分割方針も同じでも、書く人によって全然違うコードになりそう
  • Vueの経験があるだけでは、ReactもAngularをすぐキャッチアップ出来るとは限らない
    • 意識的に設計スキルを磨いている人は別

どちらを採用するか

まず、大前提としてフロント開発自体の経験がない場合は、何を選んでも時間の試練に耐えうるものは作れないと思っています。

そのため、その状況だと何を選んだとしても割とすぐに捨てることになると思っています。

なので、敷居の低さを理由にまずはVueを採用するのがいいんじゃないかと考えています。

まずはVueで手早く価値を生み出せるものを作りつつ経験を積むべきな気がしています。

一通り作り終わればフロント開発の経験値がそれなりになっているはずなので、もう一度Vueで書き直した場合に今の課題を解決できるなら作り直すかどうかはおいといてVueを継続すればよいでしょう。

Reactでしか解決できないのであればReactで作り直すのが良いかと思います。

逆にフロント開発に強い人がチームにいるなら、好みで選んでしまって良いような気はしています。

価値を生み出すようになったアプリを、その後にフルスクラッチで書き直せる勇気や資金や時間が湧くかどうかはまた別のお話だと思ってます…

以上、私的メモでした。

レガシーをぶっつぶせ。現場でDDD!2nd 「インプット<アウトプット!」の参加レポート

レガシーをぶっつぶせ。現場でDDD!2nd 「インプット<アウトプット!」の一部二部に参加してきました。

過去に多くの勉強会に参加してきましたが、その中でも特に学びを得られた強い実感がありました。間違いなく上位に入る満足度です。

学んだことを反芻して、記憶やスキルとして定着化を図らねばもったいないと感じたのでまとめたものを記事に残しておきます。

全体的に期待していたこと

DDDは(軽量かもしれませんが)自分なりにいろいろと実践してきており、実践と内省のループから考え方がなんとなく固まってきたので新しいブレイクスルーを得るために他の人の考え方を取り入れたいと思って参加しました。

あるいは自分の考え方があっているかの答え合わせができればそれはそれで自信が持てるといいなとも期待して参加しました。1

システム設計の中でのドメインモデルの役割を体感する

このセッションの内容とされていたこと

公式のタイムテーブルより引用します。

このワークショップでは、ドメインモデルをどのように実装に落とすかではなく、 業務フローやユースケースドメインモデルがどのように関わり、 それらの変更がどのように伝搬するか、という全体の繋がりに焦点をあてます。

当日は、仮想的なシステム(の一部分)を題材として、 業務に変更が生じた際に何が変わるのかを、 モデルに対して付箋で変更を加えながら体験していただく予定です。

その場でワークショップを体験していただくだけでなく、持ち帰って、 自分たちのチームで実際の業務を対象にして試していただけるようにしたいと考えています。

この説明文を読んで私は『業務分析からそのモデリングまでの一連の流れや手法が知れること』と『それを現実に近い例で訓練できること』を期待して参加しました。

そして、その期待はドンピシャでした。

実際にやったこと

以下のようなことでした。

  1. カスタマージャーニーに似ているらしい手法(一般に通じる名前はつけられてなさそう)を用いながら、現状の業務をヒアリングしフロー図に落とし込む。
  2. そのフローで出てきた単語(概念)や操作(振る舞い)を概念モデルとして図に表していく。

これだけ書き出してみると単純かつ簡単な工程で大した意義がないように思えますが、フロー図作成で得られた気づき・見落としをモデルに反映する、あるいはその逆というフィードバックループが存在しており、概念モデルに現実の例を当てはめても通用するような表現力が育っていくような印象を持ちました。2

また、そんな印象を持てるほどの表現力を持ったモデルであれば、その後の実装はだいぶ楽になるだろうとも思いました。

感覚的な話ですが、『気づいていなかったことに気づく、それが可視化される。それが単純に楽しい/嬉しい』という成功体験が『他にも同じようなものを見つけてアハ体験したい』というモチベーションに繋がり、正のループが回っていたように思えます。

今まで業務でやってきたことを振り返る

私は今まで業務分析では開発チームでドメインエキスパートにヒアリングし、その中でそれぞれが構築したメンタルモデルを(何らかの方法論を用いて共有しあう事をすることなく)それぞれがすぐにコードに落とし込む、というようなことを繰り返してきました。

しかし、フロー図とモデル図に表すことでタンジブルにし、他の開発メンバーの意見を聞きながら足りていなかった「何か」を相互に教えあい、それぞれの図に反映していくことでコードを書くよりも低いコストで先に合意に達しておく手段があるとしることができました。しかもそれが現実的にも可能そうな感触を得られることができました。

これに気づけたのはとても有意義なことでした。

今までは、フロー図やモデル図を書けるほど具体的なイメージが持てているのであれば、動かせるコードを書いてそこからフィードバックをもらったほうが早いと言う考えでしたが、図を用いてチーム内で合意を形成していたほうが認識のすり合わせコストが減り時間的トータルコストとしては下がるのかもしれない、また他人の力を借りてより高速に正解に近いメンタルモデルを構築できるのではないかという考え方に変わりつつあります。3

概念モデル/ドメインモデルは実装に素直に落ちるらしい

ところで、『概念モデルとドメインモデルは実装に素直に落ちる』4という意味にとれる説明がセッションの冒頭にありました。

これは私が仮説として持っている考え方だったので聞いたときは『お、おおぉっ?おまおれ?やっぱそうなんや!』と嬉しくなった瞬間でした。

概念モデルをコードに写し取る例考えて、登壇者に質問しに行きましたが、『ありえる実装だと思いますよ!』と言って頂けて少し自信が持てました。

成果物

f:id:kogayushi:20191215100946j:plainf:id:kogayushi:20191215100741j:plain
一部成果物

得られたこと

  • 図の作成のための議論の中で自分が持つメンタルモデルと他の人が持つメンタルモデルは当然ながら違うという再認識ができた
    • そして、概念モデルの時点でもなかなか合意に至らないのに、それをやらずにコードを書いてしまえばそりゃみんなバラバラな書き方するよなと納得した
  • 概念モデルなどの図を作るコストを払ったほうがいきなりコードを書くコストを払うより低く済む可能性を感じられた
  • 概念モデルがうまく構築できていれば実装にも素直に落とし込めるという考え方を持っている人が他にもいることが知れた

その他の振り返り的なこと

あとから考えて面白かったのはかなりクラス図に近いものをドメインエキスパートに見せながら、多重度の話をしたり、関連の線をつなげたりして認識合わせをしていたことです。

今回私のチームの担当をして頂いた方はデザイナさんでしたが、デザイナである彼にこういう話し方が通じるのであれば完全なビジネスサイドの人にも教育すれば同じやり方が出来るのではないかという可能性を感じました。

一緒に仕事しているビジネス側担当者はPlantUMLを書いてみちゃうくらいこっちよりの感覚がある方なので、ぜひこれも試してみたいと思いました。

アクションプラン

フロー図とモデル図を試す

  1. (元になっているかもしれない)カスタマージャーニーを研究する
  2. このワークショップでやったことも踏まえて(1)を実践する(必要性を感じたら先にカスタマイズもする)。
  3. 現場で試す
  4. (3)で得られたフィードバックを元に、辞めるかカスタマイズ(を繰り返しながら)して運用を継続する。
  5. 繰り返し

概念モデルを使ってビジネスサイドと会話してみる

  • ビジネスとの認識合わせにモデル図っぽいものを使ってみる
    • そのために教育もちょっとだけ頑張ってみる

モデリングワークショップ 〜割り勘ドメイン編〜

このセッションの内容とされていたこと

これも公式のタイムテーブルより引用します。

"飲み会 会計時の割り勘をテーマにモデリングワークショップを行います。支払合計金額を人数で割る「割勘」は単純です。しかし上司なら比率多め、後から来た人や学生なら少額といった多少面倒な計算が伴います。また、幹事は負担ゼロか、同様に支払うのかのオプションもあります。

今回はこういった具体例でモデリング力を鍛えることが目的です。実際には、想定しているユースケースに対してドメインモデルを考え、すぐにコード上の型を作り(処理は後回し)チームメンバーと議論し、ワークショップを体験していただきます。

追記(11/21): 対象言語は時間的な都合で効率的にサポートできるJavaに限定させてください。Javaの言語的なサポートはスタッフが行います。不明な点はスタッフに確認してください。 また、当日はお題の公表と共に、モブプログラミング形式で5チームに分かれていただきます。その際にJavaが分かる方がドライバーとして必ずチームに含まれるように調整しますので安心してください。当日利用するテンプレートプロジェクトは運営側で用意したものを配布させていただきます。

追記(12/10): お題とひな型となるソースコードこちらです。詳しくはREADME.mdをご覧ください。当日は2時間しか時間ないのでできれば事前にドメインについて考えてきてください。 ※スタッフのほうでもPCは持ち込みますが、ワークショップ参加予定の方々はPCはご持参ください。"

この説明文を読んで私は、書かれていること通りに『モデリング力を鍛える』体験が得られることを期待して参加しました。

期待したそのものではありませんでしたが、『モデルと実装を行き来することでモデルもコードも育つ』ことが現実にあることだという実感を得ることができました。

この強烈な体験が余韻として残っています。

実際にやったこと

以下のようなことでした。

  1. 想定している割り勘の文脈を登壇者よりざっくり教えてもらう
  2. (1)をもとにチームで用語(概念)の洗い出しと相互の関連やそれぞれの属性と振る舞いを洗い出す
  3. (2)を見ながら実装する

ちなみに、(3)のフェーズではドライバーを務めました。

が、『お前ファシリテータか?』と思われるくらいコードを書きながらペラペラ喋ってしまいました。

役割に徹することができず、ちょっとでしゃばっちゃったなと少し反省しています…けど楽しかったですw

今まで業務でやってきたことを振り返る

一部で書いたことと重複しますが、図で示す前にコードを書いていました。

コードを書いている途中で当然新しい気付きはありましたが、それを図にフィードバックしていなかったため、新しい概念を獲得したことを強く実感することなく、それにより別の箇所を改善できる可能性にきづけることもなく5コードをひたすら書いていた気がします。

しかし、モデルで可視化&共有し合うことを知ったため、コードで得られた気づきをモデルに反映する、あるいはモデルで得られた気づきをコードに反映する、そういったそれぞれで得た気づきを反映し合うループを試しつつチームで共有する有意義さを体験できました。

成果物

ドメインモデル

f:id:kogayushi:20191215101128j:plain
二部成果物

ソースコード

github.com

得られたこと

  • モデル図とコードを行き来することでそれぞれの足りないところを補完できる、それを複数人で実施することで足りない観点を補え合える、という体験ができた
  • モデリング時には見落としていた概念が、実装の中で浮かび上がってくるという体験ができた
    • モデルとコードを行き来する価値や醍醐味を知ることができた

アクションプラン

  • 開発チームでモデル図を作成する
  • コードを書いてフィードバックが得られればそれをもう一度モデル図に反映する

まとめ

  • 今回の開催意図である『アウトプットをするほうが学びになる』の通り、ワークショップでアウトプットすることで学びとその強烈な体験を得られました。
  • 個人的には、他の人の考え方を取り入れたい、あるいは答え合わせをしたいという期待で参加しましたが、そのどちらも満たせました。
  • 学んだことを研究しつつもなるべく素直に現場で実践して行きます。

  1. 具体的なことは特に触れませんが、どちらも達成できました。

  2. 印象だけの話で現実ではこの短い時間だけでは足りず、どう少なく見積もっても2倍か3倍の時間は要するだろうと、振り返りながら思っています。

  3. そして二部でコードによるフィードバックの体験を得て、相互に行き来することが最強という結論に至ります。

  4. あとで質問しに伺ったところ、言い切ってしまうと少々語弊があり、実際はいろんな実装手段があるだろうと訂正されていました、私は実装を連想しやすいという意味で「素直に」という言葉の選択は間違ってないと思います。

  5. コードは詳細なので全体が俯瞰しにくくなかなか気づけない

Qiitaでも記事を書き始めました

ちゃんと検証した技術記事は今後Qiitaに投稿するようにしようと思います。

このブログはアイディアや、検証結果・内容に自身がない技術ネタなどを低頻度で更新していきます。

ちなみに、最近Qiitaに投稿したのはこの2つの記事です。

Spring MVCのRestControllerのRequestParamで任意のEnumをコードなどの別の値で受け取る方法 KotlinでDoma2のEnumドメインクラスを実現する方法

以上です。

ログ収集基盤の(再)設計

はじめに

個人的に考えていることのメモです。真似してやけどしても責任持てません。

データサイエンティストに聞いてわかったデータ分析基盤アーキテクチャの勘所ってのを以前書きましたが、その続きのようなポストです。

おことわり

現在関わっている案件の要件を前提とした設計です。常にこれが正しいとは思えないので、参考程度にどうぞ。

前提(非機能要件的なもの)

  • ログは可視化したいし、ビジネスサイドが気軽にそれを参照したい
    • Elasticsearchにつっこんで、kibanaで可視化しておく。
    • それをビジネスサイドに共有しておけば気軽に参照してもらえる(はず)
  • 生ログは全件残す
    • つまり、S3に未整形のまま全件をputしておく必要がある
  • Elasticsearch Serviceに高いお金は払いたくない(というか払えない)
    • Indexを細かく分けて不要なログは一定期間経過後にローテートすることで容量を落としてコストを削減する
      • syslogとappのindexはわけておいて、syslogは1週間程度残しておく(障害調査用)、appはずっと消さない、とかをやりたい。

思いついたもの

この非機能要件を満たすアーキテクチャで思いついたのは以下の2つです。

fluentd -> S3 + elasticsearch形式

アーキテクチャ

f:id:kogayushi:20191002113525p:plain
fluentd -> S3 + elasticsearch

ETL

  • fluentdでログの仕分けをしてindexにわける
    • pod-{namespace}-{application name}-YYYY.MM.DDあたりのindex名にすればいいんじゃなかろうか
      • istio関係のログはnamespaceで仕分けられるので、culatorでローテートできるようになるはず
      • kube-system関係のログも同上
  • syslogの取得を忘れずに
    • syslog-{tag}-YYYY.MM.DDあたりのindex名にすれば良いんじゃなかろうか
    • fluentd-elasticsearchのhelm chartのconfigmaps.yamlが参考になりそう
      • ただ、この例だとsyslog全部は取得しているわけではない(特に/var/log/dmesgがないのが気になる)っぽいけど、それで良いのかはわからない

メリット

  • シンプル
  • fluentdさえ理解していれば全体像が把握できる

デメリット

  • fluentdを理解して、設定ファイルを作り込む必要がある
  • ログデータの永続化先が増えたときにfluentdの設定ファイルを更新する必要があり、設定が肥大化&複雑化していきそう
  • バックプレッシャーが効く箇所がfluentdだけのため、ログ欠損の可能性が高いかもしれない。またスケールしないかもしれない。かもしれないだけで、規模が小さければ問題にならないかもしれない。

fluentd -> kinesis形式

アーキテクチャ

f:id:kogayushi:20191002113556p:plain
fluentd -> kinesis

ETL

  • やることはログの中身に応じてindex名を動的に決める
    • つまりfluentd -> S3 + elasticsearch形式と同じことをlambdaで必要がある

メリット

  • ログデータの永続化先が増えたとしても、lambdaを拡張していけばいい
    • lambdaから別のlambdaを読んだりできるので、好きなようにできる
  • kinesis streamsでバックプレッシャーが効くしスケールするサービスなのでアクセスがいくら増えても捌ける(はず)
    • 今の案件だと将来も含めて大量アクセスされることはまずないけど…

デメリット

  • 利用するサービスが増えるので全体像の理解に苦労しそう
  • lambdaの箇所でコケると詰まるかも?検証したほうが良い。
  • lambdaでindexを動的に指定したり、elasticsearchが解析できるように構造化してあげたりと、実装が大変そう