Effective SQL 読書会(4)に参加
- 作者: John L. Viescas,Douglas J. Steele,Ben G. Clothier,株式会社クイープ
- 出版社/メーカー: 翔泳社
- 発売日: 2017/12/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (3件) を見る
冒頭で書籍紹介。SQLパフォーマンス詳解
- 作者: Markus Winand
- 発売日: 2015/09/14
- メディア: ペーパーバック
- この商品を含むブログを見る
インデックスなどの説明が詳しい他の本。
様々な実装のインデックスなど日本語で説明している本は少ないとか?
MySQLはnested loop結合しかない
中間一致の条件を使うとBTreeが使えない
like '%ELLE%'
- 主キーのインデックスはリーフノードに値を持つ
- 主キー以外のインデックスはリーフノードに主キーの値をもつ
- セカンダリーインデックス
- 多量のデータを検索する場合はインデックスが使われないものもある
- 実装にもよるけど、数10パーセントの量とか
MySQLでは、インデックス宣言のASCキーワードとDESCキーワードは無視される
とあるが、MySQLは8.0から対応している
MySQLのchange buffer(index更新の最適化)
冗長なインデックスの例
- index(col1)
- index(col1,col2)
- というインデックスがある場合は、前者は冗長なので消すこと!
- indexのrebuildは
- 参照整合性のことをDRI(Declartive Referential Integrity)と書いてあるのは初めて見た
- check制約
- トリーが、ストアドルーチンに可搬性はない
- PostgreSQLはBSDライセンスのため派生が作りやすい(たくさん)
- 書籍データベースリファクタリングではデータ移行の段階としてトリガーをフル活用する
- パーティション分割は必ず早くなるわけではない
- 適当なWHERE句が必要。
- インデックスのフィルター化
- MySQLでは使えない
- データに寄せる(寿命の長い方に設計を寄せる)
- ストアドなどはオプティマイザが見ない?
- MySQLは大文字小文字を区別している
- FS依存
- 他のDBは区別しない
- 最近はNULLS FIRST,NULLS LASTをサポートしているDBは他にもあるはず
- MSQLとSQLServer以外は最近はサポートしている
- UNKNOWNリテラルは存在する。
- SQLパフォーマンス詳細の作者が書いているブログが面白い(luke!indexを使え!)
- SQL2016の詳解など
余談ですが初参加。スケジュールに調整がつかなかったり、体調が悪かったりして参加ができていなかった。 ちなみに今日も1時間しか寝ていないので死ぬほどしんどい。
C言語で美咲フォントを扱う4
前回から引き続き、美咲フォントという8*8ピクセルのサイズで第二水準の漢字までが扱えるビットマップフォントをC言語で扱うプログラムを作っています。
ソースはここにあります。
処理は結構完成していて、呼び出し側から使うAPIの仕様などが固まってきました。
//文字のデータ。"美しい美咲フォントの世界" char test_letters[12][2] ={{0x94,0xfc}, {0x82,0xb5}, {0x82,0xa2}, {0x94,0xfc}, {0x8d,0xe7}, {0x83,0x74}, {0x83,0x48}, {0x83,0x93},{0x83,0x67}, {0x82,0xcc}, {0x90,0xa2}, {0x8a,0x45}}; for(int i=0;i<(int)sizeof(test_letters)/2;i++){ char test_letter0[2]; //多次元配列もう少しスマートにコピーしたいなぁ test_letter0[0] = test_letters[i][0]; test_letter0[1] = test_letters[i][1]; //独自定義型。実態はchar[8] font_data print_test; //フォントを取得する get_font_data(test_letter0,&print_test); //取得したフォントをコンソールに表示。 print_font(print_test); }
print_font
はutil的なものですが。bmpで扱いたかったりvramにデータを描く場合は呼び出し側に何か便利な関数が欲しいですね。
00100100 11111110 01111100 00010000 11111110 00010000 11101110 00000000 00100000 00100000 00100000 00100000 00100000 00100010 00011100 00000000 00000000 10001000 10000100 10000010 10000010 01010000 00100000 00000000 00100100 11111110 01111100 00010000 11111110 00010000 11101110 00000000 00010100 11100000 10111110 10101000 11111110 00001000 00110110 00000000 00000000 01111110 00000010 00000010 00000100 00001000 00110000 00000000 00000000 00000000 00001000 01111100 00011000 01101000 00011000 00000000 01000000 00100000 00000010 00000010 00000100 00001000 01110000 00000000 00100000 00100000 00100000 00111000 00100100 00100000 00100000 00000000 00000000 00111000 01010100 10010010 10100010 01000100 00011000 00000000 01010100 01010100 11111110 01010100 01011100 01000000 01111110 00000000 01111100 01010100 01111100 01010100 01111100 10101010 01001000 00000000 01010100 11101110 01111100 11111010 11110100 01000010 01110100 00000000
適当に見やすく置換して見ました
爨 爨 爨爨爨爨爨爨爨 爨爨爨爨爨 爨 爨爨爨爨爨爨爨 爨 爨爨爨 爨爨爨 爨 爨 爨 爨 爨 爨 爨 爨爨爨 爨 爨 爨 爨 爨 爨 爨 爨 爨 爨 爨 爨 爨 爨爨爨爨爨爨爨 爨爨爨爨爨 爨 爨爨爨爨爨爨爨 爨 爨爨爨 爨爨爨 爨 爨 爨爨爨 爨 爨爨爨爨爨 爨 爨 爨 爨爨爨爨爨爨爨 爨 爨爨 爨爨 爨爨爨爨爨爨 爨 爨 爨 爨 爨爨 爨 爨爨爨爨爨 爨爨 爨爨 爨 爨爨 爨 爨 爨 爨 爨 爨 爨爨爨 爨 爨 爨 爨爨爨 爨 爨 爨 爨 爨爨爨 爨 爨 爨 爨 爨 爨 爨 爨 爨 爨 爨 爨爨 爨 爨 爨 爨 爨 爨 爨爨爨爨爨爨爨 爨 爨 爨 爨 爨爨爨 爨 爨爨爨爨爨爨 爨爨爨爨爨 爨 爨 爨 爨爨爨爨爨 爨 爨 爨 爨爨爨爨爨 爨 爨 爨 爨 爨 爨
このライブラリのtodoとしてはヘッダの整理とライブラリとしてのコンパイルでしょうか。 あとエラー処理を一切考えていないので、それも必要かもしれません。
CC本読み会第11回に参加
Concurrency Control and Recovery in Database Systemsという本を読む読書会に参加しました。なお11回からの途中参入になります。
p77の3.10 distributed two phase lockingから読みました。
本書について
Concurrency Control and Recovery in Database Systems
- 作者: Philip A. Bernstein,Vassos Hadzilacos,Nathan Goodman
- 出版社/メーカー: Addison-Wesley
- 発売日: 1987/02/01
- メディア: ハードカバー
- この商品を含むブログを見る
データベースの基礎理論を扱う古典になります。
私が今ポチったからアマゾンのマケプレの在庫1個になっちゃいましたwwww
と希少品を自慢したいところですが、ご安心ください。こちらから書籍と全く同内容のPDFがダウンロードできます。
内容ですが、本当に「基礎」という感じです。
超絶技術を扱っているわけではありませんが、簡単という意味でもありませんが、 データをどう保護するか、という点で非常に本質的な知識だという印象です。
私に限らずどうしても昨今のエンジニアはツールとかフレームワークに関心が言ってしまい,こういう「基礎」の部分ががいい加減になりがちですね。
感想
11回目から初参加になります。こちらは分散システムの読書会と違って、
- DBという自分の得意分野である
- 分散本ほど周りの参加者が読み込んでいない
- 分散本は36回もすでに経過しているところに途中参入した。
などの点から案外ついていけるのでは?と思っていましたが、
本書の扱うテーマはRDBMSの内部構造のものがテーマななので全くの専門外でした。
そのため非常に難しかったです。私が得意だったDBの知識というものはあくまで業務システムから利用する側の知識でしかなかったり、
そもそもの知識量が資格の勉強やここ1年くらいで頑張って身につけたものに過ぎなかったのです。*1
ちょうど1年前にこんな記事
を書いている程度の状態だったので、周りの参加者のレベルを考えるともっと精進する必要があります。
トランザクション設計はもちろん業務システムの要件として確認しますが、 ミドルウェアが担保しているトランザクションというのが自分には全く知識外でした。
質問をしましたが、「自明!」という感じの回答が帰ってきたので、本書の前のパートに書かれているのかもしれません。しっかり復習して次回は挑みたいと思います。
ライブロックも単語は知っていますが、内容は知りません。
ノート
global serializable
- local serializable
- localのものを足し混んでgrobalのserializableになるような単純なものではない。
- local serializable
global なserializableを保証するのは難しい
- 2pcにして2plにする必要がある
- corvaはこの使用
- https://ja.wikipedia.org/wiki/Common_Object_Request_Broker_Architecture
- RMIとIIOPの対立
- GoogleのGRPC
- protocol buffer
- corvaはこの使用
- 2pcにして2plにする必要がある
Effective Javaに乗っているJavaのSerializationの代替
- 私がこの記事で書いている内容を話して見ました。
protcol bufferでも遅い
-
- 神林さんが詳しいらしい
- Object指向のDBで使う
CorbaではJavaなどのserializeなどの意味でマーシャライズという言葉を使う
- トランザクションのserializableという語句と被るから
2PLと2PCはいまだに進歩していない
- 分散合意が関わってくるから
- 2PCのまま
- 人類に分散システムは早い
3-4の章で普通のdeadlockはやっている(きちんと復習すること!)
The global waits-for graph, WFG, is the union of the local WFG,s.
- global dead lockはabortの際にvictimを選ぶ必要がある。
- その情報が必要
- がその情報は送信コストが大きくならないようにpiggybackで送る
- その情報が必要
廃止判断としてp58掲載の
The amount of effort that has already been invested in the transaction. This effort will be lost if the transaction is aborted.
The cost of aborting the transaction. This cost generally depends on the number of updates the transaction has already performed.
The amount of effort it will take to finish executing the transaction. The scheduler wants to avoid aborting a transaction that is almost finished. To do this, it must be able to predict the future behavior of active trans- actions, e.g., based on the transaction’s type (Deposits are short, Audits are long}.
The number of cycles that contain the transact~iion. Since aborting a transaction breaks all cycles that contain it, it is best to abort transac- tions that are part of more than one cycle (if such transactions exist).
のどれを送るかを選択する必要がある 最悪トランザクションそのものを送る羽目になる
- Mysqlはこのような検知はせずにタイムアウトさせる
globalなWFGは見たことがない
分散システムのdead lockの検知は難しいらしい。(タイムアウトがメイン)
今後の分散システムはmany coreが潮流になる。
マルチノードでやっている仕組みをラックの単体のサーバーに持ってきてもうまくいかない
業務要件に依存しないトランザクションの設計?実装?などがあるのか?
- トランザクションマネージャーを自分で書く必要がある
grobalのロックは使わずにlocalのロックを使う
コンカレントな処理由来のバグはベンダーに持っていってもわからないことが多い
- シナリオが複雑
- ハードウェアの障害
- ECCがついているからメモリのビットエラーではない
- Long型がひっくり返って6兆円?
パケットが増えたバグ
ハードウェアのエラーはソフトウェアに変な形ででる
Phantom Deadlock
- delayのdeadlock
- 哲学者の食事のやつ
- ほとんどのWFGの長さは2
For typical appIications, over 90% of WFG cycles are of length two.
90%の数値は計算できる?みたいな話になった。 ここは何を言っているのかさっぱり
- livelock
cyclic restart
タイムスタンプをつけてpriorityにしてlivelockを防ぐ
wait-die
Wait-Die: if ts( T,) < ts( Ti) then T, waits else abort T,. Wound-Wait: if ts( T,) < ts( T,) then abort Tj else T, waits.
- どっちがいいか度々議論になる
- wait-die一択?またはno wait(ここにはない)
no waitが潔い。最近はno wait一択
- たまにwait-dieの実装がある
- Wound-Waitの実装は見たことがない
タイムスタンプはいずれにせよいる
- idでも良い
タイムスタンプはよくカウントアップする
- 5分に一回くらい
- 64bitにすれば良い
- 32bit cpuの時は
- カウントアップに対応した理論の論文がある
- ラウンドアップ?とかいうらしい
論文の査読の話題になりました。(流派で暗黙の前提があるなど)
次回は「3.12 LOCKING PERFORMANCE”」から!
*1:たまに評価されることもありますが、流石に倍以上のエンジニア歴を持っていて、本当のテクニカルな分野でシビアなものが必要とされる世界で生き残ってきた人には到底叶いません
プログラマのためのSQL 読書会(25)に参加
28.4の計算列によるグルーピングからを読みました
- MySQLではGroup By句にASC,DSCが書ける(一同驚き)
- 安定ソート、非安定ソートは具体例がないとわかりにくい
- Order Byで指定すると安定ソートになる。
- Group By句では非安定ソート、安定ソートが保証されない
- InnoDBでは主キーに関して、安定ソートの動きになる
- Group By句では非安定ソート、安定ソートが保証されない
- Order Byで指定すると安定ソートになる。
- Order By句に列番号を各機能は20年以上前から非推奨?廃止予定らしい。
- その場限りのクエリを描くときは便利だから使う。
PostgreSQL,MySQLはorder by句に0がかけない。
- MySQLは0を指定するとエラー。-1を指定すると変な動きになる
- 正の整数以外を指定すると、基本的におかしな動きになる。
集約関数にDISTINCTが書ける。
- 数年前にこれを知って驚きました。知らない人はぜひ試して見ましょう。
SELECT COUNT(DISTINCT shohin_bunrui) FROM Shohin;
- デフォルトでALLが使われている。(明示することもできるが結果は変わらないので、意味はない)
countのなかにdistinct複数名が書けるか?
- 検証したところ、かけない
count以外の集約関数は引数がNULLの場合は空集合を返す
- countのみ0を返す。
- 小数点
近似値について話題になりました。 https://qiita.com/y-ken/items/b8601092d0261c3a556d http://d.hatena.ne.jp/hnw/20171221
計算誤差をきにするならdouble,floatではなくdecimal型を使うべき。
中央値をだす関数は標準SQLではない
そういえば統計詐欺といえば日本人の貯蓄ですよね。。。という話から以下のリンクが話題に上った。
- https://www.mitsui-seimei.co.jp/joyful/money/041/index.htm
- 平均貯蓄額は高いけど、中央値が0の層もあるね。
SQL ServerのTOPは色々指定できる。
- 上級者の方でも引数に与えられるのは数値しか知らなかったらしい。
難解なSQLの出典はなんなのか?
- 昔のCompuServeというニュースグループというものらしい
- https://ja.wikipedia.org/wiki/CompuServe
- 使い方のマニュアルが1万円もするらしい
- そんな時代もあったんだね。
次は29.4.3 複数の基準の極致関数から!
分散処理本第37回に参加
Distributed Computing: Principles, Algorithms, and Systems
- 作者: Ajay D. Kshemkalyani,Mukesh Singhal
- 出版社/メーカー: Cambridge University Press
- 発売日: 2011/03/03
- メディア: ペーパーバック
- この商品を含むブログを見る
本書の概要
CHAPTER 10 Deadlock detection in distributed systems
から
10.5 Knapp’s classification of distributed deadlock detection algorithms
までを読みました
- 広く浅く学べる大学院の教科書的な本らしいです。
- これを手引きに論文を引いて実装するのが良い。
- 余談ですが、読書会の参加人数は対数線形で減っていくらしい
感想
「待ちグラフ」って名前はDBスペシャリスト試験などで何度も出てくるから知っていますが、 具体的にどのようなものか知りませんでした。DBの実装経験があるような方々もおられたため、実際に実装するならこういうアルゴリズムでやる、など会話をしているうちに、机上の理論だったものが実際のイメージに落ちていく感覚がとても面白かったです。
研究職やミドルウェアを作っておられるような本物の技術者のような方が中心なので、レベルの差を感じるものがありました。強い
勉強会ノート
雑でまとめきれていませんが。一応書いたのでブログに乗せます。
- 分散システムではデットロックの検出は基本的にできない、という結論になりそう?
There is only one copy of each resource.
- それぞれのコピーは一個しかない、的な慣用句
Wait-for graph
- 待ちグラフの実装は面倒
- グラフ処理は行列処理でやる。
待ちグラフは効率が悪い
deadlockの対処
- prevention:非効率
- avoidance:(分散システムでは)実用的ではない
- detection:これが良い(本書ではここを掘り下げる)
This is the main reason why many deadlock detection algorithms reported in the literature are incorrect.
- とあるが、分散システム界隈では論文記載のデッドロック検出アルゴリズムが不完全というのは一般的な認識なのか?
- 論文が不完全というのは常識ではない。
想定が甘い、というのはある。
10.4.2のANDモデルの例が適切ではない?
- デッドロックを起こしているものがAndモデルの例として適切でない(複数のリソースを要求しておらずどのプロセスも一つの要求しか出していない)
Orモデルの場合のデッドロックの検出条件
- 1.Each of the processes in the set S is blocked.
- 2.The dependent set for each process in S is a subset of S.
- 3.No grant message is in transit between any two processes in set S.
knotの定義がわからない?
- 分散システムでも一般的な概念ではない
- サイクルとの違いがわからない
- サイクルよりも強い
- サイクルとの違いは
- サイクルよりも強い
In the OR model, the presence of a knot indicates a deadlock [19]. In a WFG, a vertex v is in a knot if for all u :: u is reachable from v: v is reachable from u. No paths originating from a knot shall have dead ends.
- 参加者の方が論拠の論文をサクッと読んで定義を説明まとめてくれました(すごい)
この例だと(緑色の遷移はないものとして)
- {c,d}はknot
- {a,b},{c,d}はcycle
こちらのサイトがわかりやすい
http://cse.csusb.edu/tongyu/courses/cs660/notes/deadlock.php
そのノード以外に到達できないような集合がknotでは?
ノットにしか到達できないグラフはORモデルのデッドロック!
現段階ではデータベースは全てシングルリソースべき
- ORモデル ANDモデルはない?
マルチマスターでのデッドロックの検知はそんなに優しくない
- 従来の検知手法が使えない
- knot以外へのリソース要求がないことを証明しないといけない。
- タイムアウトするしかないのでは?
- AWSはマルチマスターをやっているらしい(無謀?超絶技術?)
- pqモデル?
- 定義だけで証明はまだ示されていないが最強?
- knotはグラフ理論では既約多項式とか言った気がする
- 最後にknotの定義を調べてやろう、ということで神林さんが別室から鈍器のようなグラフ理論の本を持ってきた。
Java読書会「現場で役立つシステム設計の原則」を読む会 第1回に参加
現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法
- 作者: 増田亨
- 出版社/メーカー: 技術評論社
- 発売日: 2017/07/05
- メディア: Kindle版
- この商品を含むブログ (4件) を見る
本の概要
投票の結果こちらの本になりました。 ペース的に4回くらいになりそうです。 前回の投票でもKotlinの本に続き2位だったそうです。かなり人気な本だと思います。
正誤表:
サポートページ:現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法:|技術評論社
賛否
賛否のある本だと思いますが、思っていたより批判が激しい感じでした。
というのも「現場で役立つシステム設計の原則」というタイトルですが、現場として次のものが暗黙的に想定されていると思います
- WEBシステムである
- モダンなJavaでSpringのようなフレームワークが使える
- バックエンドはRDBを使う
- 国内向けのシステムで内製ができる(アジャイルが可能な現場)
- 超大規模ではなく、国際化対応などはしなくて良い
著者が想定しきれていないほど多様な「現場」の方が参加されているので、業界が違う技術者に「原則」として著者の経験や考えが読み上げられてしまうと異論が湧き出るだろうなという印象です。
全体的にこのアマゾンレビューのスタンスな方が多い印象です。
この業界に溢れた、「オレのやり方がナンバーワンだ」の本の域からは出ていないように思います。「変更が容易」の判断基準や根拠が極めて定性的なまま、著者の考えにそぐわない既存の設計手法を「誤り」と断じる論調にはだんだん首をかしげてしまいました。 著者は『ドメインモデルのコードの中に、すべてのビジネスルールを凝集させてしまいたい』派なのだと思います。オブジェクトを第一に考えている、という点で確かにオブジェクト指向には違いないです。が、DBやUIとのミスマッチをどう埋めるか?という話に関しては論理に雑な印象を受けました。ストアドやリッチクライアントなど、ビジネスロジックを散在させる要素はそこかしこにあるわけで、「あくまでドメインモデルのコード内に閉じ込めるのが正しく、そうできないのはやりかたが悪いから」なスタンスは、現実から目をそらした排他主義に見えます。著者が「正しい」とする方法が、果たして本当にどこまで経済的にメリットのあるやり方なのかは疑問に感じました。 本書は「こういう考え方もあるのか」の視点で読める人には良書と思います。しかしながら、初心者が最初に読むには全くお勧めしません。著者の考えに強く賛同する人であったとしても、この本に「正しい」と書かれていることを妄信すべきではない、と思いました。
一方的に批判がでる箇所もあり、主催の高橋さんがバランスを取って何度かフォローされていますが、DDD界隈の方が参加されていい感じの反論が聞けたら面白いのになと思っています。
感想
オブジェクト指向やJavaを極めるとDDDに行き着くと思っていましたが、そうでも無いようです。実装が好きな人、モデルが好きな人、ドメインが好きな人、という感じに(もっと多いかも)枝分かれするようです。
ベテランの方が多いので、全員「ドメイン駆動設計」のファンだと思い込んで参加したのですが、そういう方がいなかったので衝撃的でした。*1
私自身はDDDの「プログラミングの対象領域を大事にする」という考え方は結構好きです。設計はあまりわかっていないので、勉強になるところも多かったです。
以下読書会ノートです。
オブジェクト指向とは何か
設計とプログラムどっちのことを言っているのかわからない
モデルとプログラムは一致するか?
- 最近のシステム開発は紙ベースの業務を置き換えるだけではない
- まだ世の中にないビジネス。どうやってITで作る?
文字数制限の話
文字数たくさん使ってわかりやすい単語で作れ的な本だが、 長い命名を使うことにも問題がある
- パス名が255文字を超えるとzipなど解凍できない不具合がある
- ミドルウェアやツールが持っている文字数制限に引っかかる
ShipingCostの設計について
class ShippingCost { static final int minimumForFree = 3000; static final int cost = 500; int basePrice ; //メソッドの実装略 ShippingCost(int basePrice); int amount(); } int shippingCost(int basePrice) { ShippingCost cost = new ShippingCost(basePrice); return cost.amount() ; }
- 重複をなくすだけならstatic methodにくくり出すだけで良い
- このクラス設計はいけてない。最近だとロジックとしてラムダ式とかを渡す?
計算の対象になる値が異なれば、別のオブジェクトに分けるのがオブジェクト指向らしい設計です
- この意見は局面による
- 直接newしたものを使うべきではない。(interfaceを使う例が後に出てくる)
- 結果を知りたい側(amountが欲しい呼び出し側)がbasePriceを知らない場合は、こんな設計もあり
- ライフサイクルが長いから送料クラスが意味を持つ
- 好意的に解釈するとプライムな変数ではなく、独自定義型を使うというのはOK
- intは使うな
- int型の最大値は21億だが、その規模の額を扱わないシステムでもカードなどで端数の扱いの違いがあるのでintは危険
- 国境を超えるシステムでは送料計算はめちゃくちゃ大変。
- エリックエヴァンスの本に貨物を輸送する例が出てくる
- DDD界隈の人達は貨物を輸送する例を好む傾向がある
- 著者はDDD界隈の人
- このへんからドメイン駆動設計への誘いを感じる。
エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)
- 作者: エリック・エヴァンス,今関剛,和智右桂,牧野祐子
- 出版社/メーカー: 翔泳社
- 発売日: 2011/04/09
- メディア: 大型本
- 購入: 19人 クリック: 1,360回
- この商品を含むブログ (131件) を見る
業務構造とプログラムを一致させる
業務の構造とプログラムの構造が一致していれば
int itemPrice = (basePrice + shippingCost) * taxRate();
- 例えば上記は軽減税率などが入ると、税金計算の際に、料金だけでなく、明細が必要になってくる
- そうなると破綻する
- 一致させるのは大変難しい
DBとタイムゾーン
- PostgreSQL
- (Localの情報をデフォルトで持たない)
- タイムゾーン情報を持つ必要がある
- MySQL
- (2038年問題がある)
ロケールを明記していないと、タイムゾーン情報が消える(必ずUTCになるわけでない) この辺はサマータイム対応が難しい、ということになる。
- タイムゾーン対応のため+-9などを入れているコードは書くな
可視性について
class Customers { List<Customer> customers; ... List<Customer> getList() { return customers; } }
List<Customer> customers;
はprivateスコープにすべきでは?とはという話が出た- DDDをする上で可視性などは些細な問題なのでは?
List
への参照をそのまま外部に渡すと、要素の追加や削除がCustomersクラスの外部からできてしまいます。`
- だとしてもこのような前提があるならば、可視性はこだわってサンプルコードを作成するべき
- 可能な限りpackageスコープにする。という記述がある。その方針に沿っているのでは?
“関連性の強いクラスは同じパッケージに集めます。そして、クラスやメソッドのスコープ(参照範囲)は、可能な限りパッケージスコープにします。”
- デフォルトで可視性をpublicにする風潮は如何なものかと思う*2
- Java9で入ったモジュールは難しい
- それだけを扱っている本が3冊くらい出ている
この著者は防衛プログラミング反対派
まだこの章に到達していませんが、懇親会などで結構話題に上がりました。
ゼロ除算を防ぐのは叩く側の責任!!!!って書いてあって草も生えない。なんだこの本。
— Yoichiro Shimizu (@budougumi0617) January 21, 2018
確かに「契約による設計」と「防御的プログラミング」の両方を勘違いしている説明になっていますね。不正な値や不正な呼び出し順序に対する振る舞いもきちんと「契約として設計」し、その契約を守った呼び出しであるかを防御的にプログラミングしないと、無駄なデバッグ工数が発生するだけですからね。
— Yoshiki Shibata/柴田芳樹 (@yoshiki_shibata) January 21, 2018
メイヤーは、呼び出す側が必ず契約を守ることを前提にしてコードを書くスタイルを重視して、それを契約による設計と名付けたと思います。契約の表明は実行用のコードとは別にすべきだと。
— 増田 亨. (@masuda220) January 21, 2018
私の理解はこの回答に近いですね。https://t.co/XEKToVvMcb
本でうまく説明できていないかもしれませんが。
もちろん、すべてがすっきりうまくいっているわけではなく、契約による設計を重視した設計スタイルの実践で、いろいろ試行錯誤をしていることも事実です。また、本の中で、入力値の検証の扱いとかもきちんと記述できていないのは、私の力不足ですね。(ほんとうは、もう少し書きたかった)
— 増田 亨. (@masuda220) 2018年1月22日
実践の観点ではmeyerがどう言及しているかではなくて、防御的プログラミングが役に立つか否かで判断すればいいわけだけど、私の見解は「役に立つ」です #javareading
— quiver2k (@quiver2k) August 18, 2018
Javaの互換性
Java Day TokyoでJava 11に向けて大きなクラス削除などが予定されていることなどが発表された
- https://qiita.com/neriudon/items/44d4d3a2b8da4d09c0f8
- corbaはSEではなく最初からEEに入っておくべきだった
- https://ja.wikipedia.org/wiki/RMI-IIOP
- java applet
- java web start
- https://qiita.com/neriudon/items/44d4d3a2b8da4d09c0f8
外部ライブラリとして持ってこれば良い。
コレクションオブジェクト
class Customers { List<Customer> customers; ... Customers add(Customer customer) { List<Customer> result = new ArrayList<>(customers); result.add(customer); return new Customers(result); //return new Customers(result.add(customer));👈誤植間違い } }
- コピー先のCustomersでも参照先のcustomerオブジェクトは変更できるがいいのか?(シャローコピー、ディープコピーの話)
- ここまでの文脈的にCustomerはimmutableなオブジェクトなのでは?
- 少し後ろに説明が書いてある
“unmodifiableなListでも、個々の要素のオブジェクトの内容は変更できます。コレクションの要素を値オブジェクトにすればこの変更も防げます。”
- コンストラクタの説明がない
- list
行間の下の...に書かれているのでは
Listオブジェクトのファクトリメソッドについて
- List.of() 変更不可能なクラスを返す。可変長引数のみ。コレクションを引数を取ることはできない
- Arrays.aslist() 固定サイズのlistを返す
- Collections.unmodifiableList 変更不可能なクラスを返す
- Collectors.toList() ストリームとかで使う?
技術者の人種
モデル屋さん
- モデルを作るのが目標
- 自動生成とかやりたがる
- プログラミング言語が追いついていない
- 別の設計関係の本の読書会で意見が合わないことがあった
ドメイン屋さん
- 実装屋さん
- この読書会の大半の人?
https://ja.wikipedia.org/wiki/モデル駆動型アーキテクチャ
- プログラマ不要説は度々流行るが、結局流行らない
- if文やfor文を違う表現で出してるだけ。
- caseツール
※モデル屋さんとドメイン屋さんが来ておらず、偏った議論になっているのでは?と感じた。
自インスタンスを返すメソッドの意味は?
以下のコード。なんの意味があるのか?という質問が出た
class Customers { List<Customer> customers; ... //👇これ Customers add(Customer customer) { List<Customer> result = new ArrayList<>(customers); return new Customers(result.add(customer)); } }
- メソッドチェーンができる
- 標準ライブラリのimmutableなオブジェクトも大体この仕様
サブストリングにおけるStringPoolの扱い
最近はやってない
Strng.Classのソースを確認したところ、確かに
substring(int beginIndex, int endIndex)
StringLatin1.newString(value, beginIndex, subLen)
new String(Arrays.copyOfRange(val, index, index + len), LATIN1)
こんな感じで新たなインスタンスが作られるようになっていました。
public String substring(int beginIndex, int endIndex) { int length = length(); checkBoundsBeginEnd(beginIndex, endIndex, length); int subLen = endIndex - beginIndex; if (beginIndex == 0 && endIndex == length) { return this; } return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen) : StringUTF16.newString(value, beginIndex, subLen); }
なぜラッパークラスを使っているのか
- Booleanではなくbooleanを使うべき
private Boolean isChild() { return customerType.equals("child"); }
- Object.equalsはboolean型を返すが?
- 無駄なBooleanクラスを使ってる
- Booleanを使っている意図がわからない
- 執筆にワードを使って書いてる説
- customerTypeの値はメソッド内に持たなくて良いのか?
- ちょっと変えてストラテジーパターンに落ち着くいつものパターンでは?
Reservationクラスは不変クラスにしなくていいのか
- addFeeでオブジェクトの状態を変えられるけどそれはいいのか?
class Reservation { List<Fee> fees; //大人と子供の内訳は不明 Reservation() { fees = new ArrayList<Fee>() } void addFee(Fee fee) { //大人でも子供でも追加できる fees.add(fee); } Yen feeTotal() { Yen total = new Yen() // 合計ゼロ円 for( Fee each : fees ) { total.add( each.yen() ); } return total; } }
- 現実的には徹底的にやる必要はない。どこかで線引きが必要
- 徹底的にやると目指せhaskellになってしまう。
enum
enum FeeType { adult( new AdultFee() ), child( new ChildFee() ), senior( new SeniorFee() ); private Fee fee; // Feeインターフェースを実装したどれかのクラスのオブジェクト private FeeType(Fee fee) { this.fee = fee; // 料金区分ごとのオブジェクトを設定する } Yen yen() { return fee.yen(); } String label() { return fee.label(); } }
型引数
Set nextStates = EnumSet.of(承認済,差し戻し中); // 状態のグルーピング
- Setの宣言時に型引数を使うべき
日本語の定義名
- Enumの定義名が日本語でわかりやすくて良い
enum State { 審査中, 承認済, 実施中, 終了, 差し戻し中, 中断中 }
EnumMapを使うべきか?
class StateTransitions { Map<State, Set<State>> allowed; { allowed = new HashMap<>(); allowed.put(審査中, EnumSet.of(承認済, 差し戻し中)); allowed.put(差し戻し中, EnumSet.of(審査中, 終了)); allowed.put(承認済, EnumSet.of(実施中, 終了)); allowed.put(実施中, EnumSet.of(中断中, 終了)); allowed.put(中断中, EnumSet.of(実施中, 終了)); } boolean canTransit(State from, State to) { Set<State> allowedStates = allowed.get(from); return allowedStates.contains(to); } }
- HashMapではなく、EnumMapを使うべき
- 「終了」をセットしていないので、終了で呼ぶとぬるぽで落ちる
- バグでは?
- EnumMapを使った場合もぬるぽが発生する
- EnumMapを使うメリットは?
データクラスと機能クラス
UtilとかCommonな便利クラスを作るなという恒例のアレ
- 悪い共通クラス
- RXJavaが共通ライブラリの最たる例。
- メソッドが多すぎる。それでも使うけど。
Javaのルーツ(ちょっとざわついた)
オブジェクト指向設計の基本
ロジックの置き場所やクラス名/メソッド名の改善を続け、より良い設計を見つけていくのが、オブジェクト指向設計の基本です。
これはリファクタリングだと思う。
- 「オブジェクト指向設計の基本」とは言えない
- 多態性を説明していた箇所らへんはオブジェクト指向設計っぽい
- 「オブジェクト指向設計の基本」とは言えない
- このほんに書かれている「設計」は設計ではなくプログラミングだと思う
- OODではなくOOP
凝集度
“このように、関連性の強いデータとロジックだけを集めたクラスを凝集度が高いと言います。”
- モジュール設計のことを書いて凝集度を説明するのは、少し説明不足な気がする
- そもそも凝集度なんかは本を読んでもよくわからない。
- 実際に手を動かして作ってみるべき。
- そもそも凝集度なんかは本を読んでもよくわからない。
データと処理を同じクラスに置く(分離させない)
“データとロジックを一体にして業務ロジックを整理する”
時間の流れ?
時間軸に沿った業務の基本の流れを軸に、業務ロジックの関係を整理します。
- この手法は初めて聞いた
- 注文と出荷は非同期。同期する必要はない(溜め込めばいい)
パッケージ間の参照
図3-3
出荷する時に顧客は見ないのか?
- has a関係のようなものでは?
- クラス単位の参照関係のようなものでは?
パッケージの関連では?
モジュラー屋さんはよくこのようなUMLを書く
- 矢印がないからと言って、本当に参照しないという意味ではないのではないか。
技術選定などのフェーズが抜けている
Spring,Javaありきで技術選定などのフェーズが抜けている
- グランドデザインができてしまっている
- どうしてもWEBアプリケーションで成り立つ理論になる
- 大企業の調達システムなどでは通用しない考え方
動き(設計)を想定しながら分析する
- 最初に習ったオブジェクト思考設計は確かにこんな感じ
分析と設計と実装を一人の人間がやるのは小規模でないと難しい
この本は実装者に結構寄り添っている
- モジュラー屋さんほどコードから離れていない
- モジュラー屋さんはプログラミング実現性みたいなものを全く考えない。
- ものごとは綺麗なツリーにはならないので、多重継承*3の形で分析することもある
- 以下の本がそんな感じらしい。
- 作者: 児玉公信
- 出版社/メーカー: 日経BP社
- 発売日: 2011/05/26
- メディア: 単行本
- 購入: 6人 クリック: 23回
- この商品を含むブログ (6件) を見る
- 以下の本がそんな感じらしい。
次回Chapter 4の“なぜドメインモデルだと複雑な業務ロジックを整理しやすいのか”から
C言語で美咲フォントを扱う3
あまり進捗良くありませんが、とりあえずバイナリデータのどこにフォントがあるのか確認できるようになりました。
$ echo "犬" |nkf -s|hexdump 0000000 8c a2 0a
まあこんな感じでSjisのコードを調べた後、そのデータの配列を作成し、
char test_letter[2] = {0x8c,0xa2}; int block_index= block_potition(header.block,test_letter); //文字が存在しているブロックの先頭まで、何文字あったか確認する int base = count_letters_untill_block(block_size,block_index); //ブロックの先頭から何番目めに文字があるのか確認する int offset = char_2B_hex_minus(test_letter,header.block[block_index].start_code); int tmp =HEADER_SIZE + tablesize * (sizeof(bloack_table_entry)) + (base+offset) * (sizeof(font_data)); printf("tmp is %d\n",tmp);
こんな感じのコードを書くとFONTX2形式ファイル中の文字データの位置がわかります。 それをバイナリエディタで抜き出した後、適当に置換して見ました。*1
// 憂憂 憂 // 憂憂 憂憂憂 // 憂 憂憂憂憂憂 // 憂憂 憂 憂 // 憂憂憂 憂憂 // 憂 憂 // 憂 憂憂憂憂憂 // 鬱 鬱 鬱 // 鬱鬱鬱 鬱鬱鬱 // 鬱鬱鬱鬱鬱 // 鬱鬱鬱鬱鬱 鬱 // 鬱鬱鬱鬱 鬱 // 鬱 鬱 // 鬱鬱鬱 鬱 // 犬 犬 // 犬 // 犬犬犬犬犬犬犬 // 犬 // 犬 // 犬 犬 // 犬犬 犬犬 //
憂鬱と犬のデータ場所を探して見たけど、憂はなんか違う感じがする?
もしかして憂ではなく優を出している? と思い優を確認して見たところ、こっちの方が優っぽい。
優優優優優 優 優優優 優優 優優優 優優優優優優 優優優 優優 優 優 優優優 優優
bmpファイルにしたりすると、わかりやすいのかなぁ。
*1:もちろんいまは手作業でやっているがいずれこの部分もプログラムにするつもり