サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
デスク環境を整える
scrapbox.io/kawasima
2025/4/24に開催した #アーキ部 『丁度ええ! ロギング』の内容を編集したものです。 ロギングにまつわる問題の構造 ロギングにまつわる現場でよく見られる問題には以下のようなものがあります。 ロギングガイドラインを定義して、開発者に周知し実装してもらったが、実際運用してみると、役に立たないログが多すぎる。 担当者が異なると、ログ出力する粒度が微妙に異なり、解析に時間がかかる。 ログの形式や内容が統一されておらず、分析ツールでの活用が難しい。 ロギングベストプラクティスは探すといくつか見つかります。 https://www.dataset.com/blog/the-10-commandments-of-logging/ https://betterstack.com/community/guides/logging/logging-best-practices/ https://new
バリデーション解体新書 2025/4/8に開催した #アーキ部 『バリデーション解体新書』の内容を編集したものです。 バリデーションとは何か? 広義には、 何らかの処理を実施するにあたって、入力データが想定する条件を満たすかを検証する行為 と言える。 この定義で、アプリケーションのどこでバリデーションをしているのかを考えると、以下のように各層にそれが見られる。 このように実装される場所が散らばるので、「バリデーション」や「入力チェック」を分類して開発ガイドラインを作ることが多い。 例えば、大規模Java開発向けのTERASOLUNA開発ガイドラインを見てみると、 ユーザーが入力した値が不正かどうかを検証することは必須である。 入力値の検証は大きく分けて、 1. 長さや形式など、文脈によらず入力値だけを見て、それが妥当かどうかを判定できる検証 2. システムの状態によって入力値が妥当かどうか
飛べない鳥問題がオブジェクト指向設計における継承の誤った例として度々挙げられる。 https://qr.ae/pYOBqZ ハトやカラスは鳥であり、鳥は空を飛ぶのでfly()という振る舞いを持つ。 code:mmd classDiagram class 鳥 { fly() } class ハト { fly() } class カラス { fly() } 鳥 <|-- ハト 鳥 <|-- カラス ところが、新たにペンギンを加えようとした時に問題が起こる。ペンギンは明らかに鳥であるにもかかわらず飛べない。これは、どう対処したら良いか? code:mmd classDiagram class 鳥 { fly() } class ハト { fly() } class カラス { fly() } class ペンギン { fly() //飛べない!! } 鳥 <|-- ハト 鳥 <|-- カラス 鳥
このSpring Bootを使ったクリーンアーキテクチャの例は、データの詰め替え過剰にみえる。 https://www.baeldung.com/spring-boot-clean-architecture これだけのモデルと詰め替えが必要なのだろうか? 『Get Your Hands Dirty on Clean Architecture 』にこのマッピング戦略(詰め替え戦略)が書かれている No Mapping (レイヤ間でモデルを共有し、詰め替えをしない) 2-way Mapping (各レイヤで独自のモデルを持ち、レイヤを跨ぐ呼び出しは上位レイヤが詰め替えの責務を負う) Full Mapping (各レイヤで独自のモデルを持ち、レイヤを跨ぐ呼び出しには専用のモデルを使う) またこの戦略のどれを選ぶかの基準は『Balancing Coupling in Software Design
2024年7月13日の大吉祥寺.pmで発表した「古典ドメインモデル(パターン)の解脱」のスライドログです。 この2冊で書かれているドメインモデルパターンを「古典」の対象にします。 ドメインモデルパターンは「複雑さに対処するため」と述べています。が、古典では次の2点が課題となっていると考えます。 これら2点について個別に見ていきます。 まずドメインモデルパターンから。 Patterns of Enterprise Application Architecture(以降PofEAA)ではこのように定義されています。 PofEAAのドメインロジックの章で使われている「収益認識」の例を取り上げます。 ContractやProduct, RecognitionStrategyなどといったクラスが作られて、これらのインタラクションでビジネスロジックが実現されると説明されています。 では、これらのドメイ
#WIP 柔軟性とは… 既存のコードを修正する(壊す)ことなく、機能追加できること と定義する (『Software Design for Flexibility』より) また、必要以上の汎用性があると柔軟性が高いとされる。 柔軟な設計とされることもあるが直結しないもの テーブルに予備カラムを持たせておく 予備カラムをハンドリングするコード修正が必要になるので、柔軟性を達成するものではない ALTER TABLE ADD COLUMNの実行コスト(作業者の工数含む)が非常に高い場合のコストの前払い メッセージに予備フィールドを持たせておく 予備フィールドをハンドリングするコード修正が必要になるので、柔軟性を達成するものではない 固定長メッセージのような以下なる変更も、破壊的変更となってしまう場合の対策としてこの手段が一応理に叶うことがある。 DSLで書ける 既存コードは修正しないが、DSL
#アーキテクチャ大全 設計のポイント 付与率の計算 顧客ランク (ロイヤルティ) 還元率アップキャンペーン 期間限定 店舗限定 ポイント付与のタイミング 即時 後日 キャンセル可能なアクションを伴うポイント付与は、キャンセルできなくなるタイミングまで実際の付与を遅らせる。 ただし、付与予定としてユーザに見せるケースがある。 ユーザがキャンセルした場合は、付与予定を取り消す。 有効期限 固定(dポイント型) 使うたびに延びる(ヨドバシ型) 期間限定ポイント キャンペーンとして有効期限の短いポイントを対象ユーザに一斉に付与する。 ↑の有効期限が使うたびに延びるタイプでも、期間限定ポイントは固定の有効期限を持つ。 参考資料 https://it-koala.com/point_system-814#i-4 https://engineering.reiwatravel.co.jp/blog/ne
数学の用語では全域性と呼ばれる code:f f = x => y 関数fの定義域xの取りうる値すべてに対応する値域yが存在することである。 全域性を持たない関数の例として代表的には割り算がよく取り上げられる。 code:divide.ts type Divide = (a:number, b: number) => number const divide: Divide = (a,b) => b !== 0 ? a/b : NaN 割る数に0は取りえないので、このdivide関数は全域性が無いことを意味する。 全域性を持たせるためには、3つのアプローチがあるとされる。 1. 定義域にデフォルト値を返す。 2. 戻り値にエラーケースを含める。 3. 引数(定義域)を全域性担保できる範囲に限定する。 1はこれが出来る場合と出来ない場合がある。上記例のように割り算の場合、どんな数字をデフォルト
ソフトウェア開発におけるContinuous 〇〇を収集する。総じて作業負荷、心的負担が大きくなるバッチ処理的に溜めて一度にやっていたプロセスを、日々のライフサイクルの中に組み込むことが目的である。
統計情報が取得できておらず、SQL実行時間が長くなったりデータベースのリソースを喰ってしまったりする。
日本語だとどちらも「複雑」を意味するが、英語だと「Complex」と「Complicated」の2つの単語が該当する。 両者は明確な違いが無いともされるが、使い分けられるケースもある。Complicatedの方が頑張れば解消可能とされ、「複雑」じゃなく「込み入った」という訳語があてられることもある Cynefin Frameworkにおける使い分け Complicated: 分からないことは分かっている。理解するのは難しいが、時間と労力をかければ最終的にはわかる Complex: 分からないことが分からない。 英語ぷらすでの説明 Complicated: 関係性や状況が複雑。物理的でなく心情的・観念的にややこしい Complex: 構造や手順が複雑。物理的な複雑さ 対義語から Complexの対義語としてSimpleが使われるが、Complicatedの対義語としてはあまり使われない。 C
NULL絶対ダメ論や現実的には無理だから上手く付き合っていくしかないんだよ論など見られるが、せっかくCodd博士が上図の分類を提示しておられるので、これを元にもっと詳細化して考えてみよう。
マーチン・ファウラー命名のドメインモデル貧血症は、ドメイン層っぽいデータをもつクラスを作りながらも、フィールドのGetter/Setterだけをつものを指す。そうしちゃうとドメインオブジェクトに業務知識が実装されず、それを使う側に任されることになる。
会員のドメインモデルを考える。属性としてemailAddressを持っていて、これは通知メールを送るのに使われる。
コンテンツサイトの「記事」を、あらかじめ掲載開始予定日を設定しておき、その日がきたら記事が公開される、また掲載終了予定日を設定しておいて、その日がきたら記事が非公開になる、というモデルを考える。
Domain Modeling Made Functionalで紹介されているドメインのドキュメンテーションのためのミニ言語です。
ドメインモデルには、完全性と純粋性、そしてアプリケーション性能の3つ全てを同時に満足させることは難しい場合があるという話。
JavaScript syntax defines several native data types that are not included in the JSON standard: Map, Set, Date, Error, Regular Expression, Function, Promise, and undefined.
このツールは、全体的な傾向を把握するためのもので、意図的に不正確な指標になっている。そのため個人の仕事のパフォーマンスを評価するために使ってはいけない。
#アーキテクチャ大全 ここでは画像やPDFなどの文書ファイルをアップロードし、別のWebページで画像を表示するのに使ったり、別のユーザにアップロードした文書ファイルを見せたりダウンロードさせたりする用途を考える。 ExcelやCSVなどのデータをシステムに取り込むためのアップロードに関しては、別途記す。(至高のファイルアップロード みたいなやつ) 設計のポイント アップロードさせるファイルの種類 ファイルアップロードダイアログで拡張子制限できる。 バリデーションとしては、Mime-typeだけでなく、ファイルに含まれるマジックナンバーをチェックしておくとだいぶ安心感がでる(もちろん完全ではないので、ウイルスチェックも併用すること)。 https://medium.com/the-everyday-developer/detect-file-mime-type-using-magic-num
Eberhard Wolffさんのこのプレゼンの要約です https://www.youtube.com/watch?v=B3O-qYM-Kkw 共通のデータモデル 共通のデータモデルを通信に使う 各サービスで必要となるデータの内部モデルは異なるかもしれない データモデルが、共通ライブラリと同じ意味合いになる すべてのサービスが、最新のライブラリを使わなくてはならない 共通データモデルの変更は、す
型駆動設計から始まるフォーマルなアプローチもカバーしているが、フォーマルな方法の簡単な紹介も含まれているもの。
論理的なLayerは、コードを整理するための手段にすぎない。典型的なレイヤーはプレゼンテーション層、ビジネス層、データ層であり、従来の3-Tierモデルと同じだ。だが、Layerはあくまでもコードの論理的な構成の話だ。これらのLayerが同一マシンの同一プロセスで実行されるのか、異なるマシンで実行されるのかには何も言及しないし、制約もない。
https://github.com/ddd-crew/ddd-starter-modelling-process/raw/master/resources/ddd-starter-modelling-process.jpg
サイトの検索導線からも全部見えるようになったようです。 マスタリング・イーサリアム ―スマートコントラクトとDAppの構築 https://www.oreilly.com/library/view/-/9784873118963/ 初めてのGraphQL ―Webサービスを作って学ぶ新世代API https://www.oreilly.com/library/view/-/978487311893
データベースの検索メソッド(リポジトリとかDAOとか呼ばれる責務のもの)をどう設計するかは、選択肢が多く考えられる。それぞれの例と判断基準について検討してみよう。 例えば、このカルーセル(carousel)みたいなものを考える。現在のRoomClipのカルーセルは、その日に投稿されたフォトを10件程度選択する仕様である。
#WIP アプリケーション設計者視点で、どうログ設計するか? についてまとめます。 使途別 異なる用途で使われるので、それ毎にファイルやトップカテゴリで分類する。 トレーシング 世の中のロギングライブラリの主な想定用途はこれである。必要な箇所やレベルに応じて出力制御をするために、ログカテゴリやログレベルが存在する。 目的 アプリケーションの性能をモニタリングする トラブル時に何のメソッドが呼ばれたかを追跡する 必要項目 タイムスタンプ リクエストID Microservicesのようにインスタンスをまたいでトレーシングしたい場合は、上流で発行されたリクエストIDを引き渡して、それをログに出力する。 メソッド名 手段 AOPでメソッドのEnter/Exitで自動的にロギングされるように設定する。 モニタリング メトリクスAPIやヘルスチェック用のエンドポイントを用意するのが当たり前になった現
「テストコードがなくて品質が良くないんですよ…」というシステムのソースコードを覗くと、いろんなロジックがコントローラの中に書かれたファットコントローラだったり、ビジネスロジック層と定義はされているけれども中身はただのDAOだったりということが多くあります。 そういうファットコントローラだと書けるテストは、以下のように入力値のバリデーションエラー1つテストするだけでも、コントローラの依存関係を解決し呼び出す必要があり、テストコード書くにもモックライブラリの知識が要求されるようになるし、書いたテストも実行速度が遅くなりがちです。さらにアサーション対象はコントローラの戻り値、すなわちテンプレートに渡す変数であったり、JSON化するためのオブジェクトで、この例のようにバリデーションエラーの場合は、ユーザに表示するためのメッセージ文しかないこともあり、アサーション書くのも一苦労だし、メッセージを修正
POSAでの定義 レイヤードアーキテクチャを、体系だって書いたのは「Pattern-Oriented Software Architecture, Volume 1, A System of Patterns」だろう。まずはその原典に立ち返って、レイヤードアーキテクチャとは何かをみてみる。 コンテキスト ソースコードの変更がシステム全体に波及させたくない。それが1つのコンポーネントに閉じられ、他に影響を与えないようにすべきだ。 インタフェースは安定している。標準化団体によって規定されている場合もある。 システムの一部は交換可能である。コンポーネントはシステムの他の部分に影響を与えることなく、実装を入れ替えることができる。 現在設計しているシステムと同様の下位レイヤの課題をもつ他のシステムを、将来構築することがあるかもしれない。 理解のしやすさと保守性のために同じ責務はグルーピングしておきた
次のページ
このページを最初にブックマークしてみませんか?
『scrapbox.io』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く