Magnolia Tech

いつもコードのことばかり考えている人のために。

WEB+DB PRESS Vol.136 最終号!---日本のソフトウェア技術を支えてくれた雑誌の休刊

表紙に「最終号」と書かれているのが、ちょいと悲しい。

技術雑誌の存在ってなんだろうなと考えてみると、一つ一つの記事の深掘りは当然単行本に比べると浅い。でもすべての技術にたいして専用の技術書が出る訳でもない中、ブログ記事などに比べると、編集者の目を通っていることと、一回あたりのページ数が少ない分だけ入りやすいことで重宝する。それに「今、こういう技術が話題になっているんだな」って、ざっと理解できるのも良い。目の前で使わない技術でも、いつか使う日がやってくる時に、「そういえば、ちょっと前に特集されていたなー」と思い出せるだけでも知識のインデックスとして有効に機能してくれる。

そんな雑誌が無くなってしまうのは、けっこう寂しいし、何か大きな穴が空いてしまった感じがする。でもそれを実感するのは今日・明日ではなく、ずっと先のことだと思うけど。


最終号だけど、記事の方は逆にいつも通りだったのが良かった。ただ、Perlをきっかけに読み始めた自分にとっては、Perl Hackers Hubの最終回が宮川 達彦さんで締められていたのが感慨深かった。

Perl Hackers Hub 【最終回】Carmelによる依存モジュール管理 ……CPANモジュールの更新を高速,安全に……宮川 達彦


過去、一度だけ記事を書いたことが有って、原稿料を時給的に評価すると厳しいというか、これだけで生活を成り立たせるのは難しいと思ったけど、自分の思考をまとめる、書いた文書を専門の人に評価してもらう、というのは貴重な機会だったし、学びがたくさん有った。

しかし、単著を1冊まるごと一人で書ける人はどんだけすごい精神力なんだろうかと思ってしまった。


初めて読んだのがいつだったのか、もう覚えていないけど(007年くらいかな)、毎号とまではいかないけど、けっこうな頻度で買って読んでいました。WEB+DB PRESSを読む、という行為自体が一つの訓練になっていたと思います。

本当に関係者の皆様はお疲れ様でした。

WEB+DB PRESS日本のソフトウェアの技術力の向上に寄与した功績はめちゃめちゃでかかったと思います。


120号までの総集編は2年前に出ているので、今のうちに買っておきましょう。貴重な歴史が詰まっています。

『なっとく!関数型プログラミング』は読者の理解度の進捗を先読みして作り込まれた”プログラミング入門”の良書

良い、買おう、読もう、(コードを)書こう、以上!

『なっとく!関数型プログラミング』は、2022年に出版された『Grokking Functional Programming』の邦訳版で、主にScalaを題材として関数型プログラミングを学んでいくための入門書("Grokking"は、完全に理解する、という意味)。あくまで関数型プログラミングの考え方、コードの書き方、良い設計の指針の解説が主眼に置かれているので、Scalaの言語機能の入門書ではない。Scalaの言語仕様を網羅的に解説するような内容ではない(それでもScala3ベースの文法はきちんと取り込まれている)。


まず、今まで読んだ関数型プログラミングの入門書として一番分かりやすい……というより、おそらく各種プログラミングの入門書(言語機能だったり、設計方法論だったり)としても過去に読んだ中でも群を抜いて分かりやすかった。とにかく解説の順序が考え抜かれていて、「きっと読者は、今このくらいの理解度だから、次はこの概念を教えた方が効果的、こっちは基礎的な機能だけど、今は解説しない、後にする」というふうに、解説されるテーマの交通整理がしっかりされているから、「さっき出てきたアレはどこ行った?」みたいな混乱無く読み進められる。

例えば従来の解説書でよくあるような「関数型プログラミングの基本は再帰です」とばかりに最初に再帰の解説が来たりしないところが特に象徴的だった。再帰が出てくるのは中盤を過ぎて、後半に入るくらいのタイミングで出てくる。それは再帰自体の学習の難易度から言って、他の概念を学んだ後に出てきた方が、その必要性が理解し易いと判断されているからだろうけど、関数型プログラミングの解説書で、再帰がこんなに後ろに出てくるんだ、と驚いた。

リスト操作の中でも分かり易いdropなんかもかなり後の方に出てくる一方で、あくまで関数型プログラミングの概念を学ぶための入門書なので、Scalaの入門書では出てこないようなcats-effectや、fs2といったサードパーティライブラリが中盤くらいに当たり前のように出てくる。


特に序盤のPart1 関数型ツールキットは本当によく考え抜かれていて(全体的にそうだけど)、Javaで書かれた命令型のコードから、Scalaで書かれた関数型のコードとの比較に始まり、その後の多くのページを割いて関数型のコードが守るべき純粋関数の3つのルールを守るためのコードはどうやって書けば良いのか?ということを徹底的に、詳細に、ステップを踏んで解説が進む。

ここで言う純粋関数の3つのルールは以下の通り。

  • 1つの値だけを返す
  • 引数に基づいて戻り値を計算する
  • 既存の値を変更しない

そして、一貫して「関数のシグニチャ」の大切さを説いていく。関数型プログラミングでは、関数のシグニチャから予想できない振る舞いをしてはいけない。

そうやって状態管理の排除や、関数を引数に取る関数、戻り値に関数を返す等を学んでいく。


続くPart2でようやくお馴染みのflatMapOptionなどが出てくるが、特に中盤のモデル化の重要性、直積型、直和型、ADT(代数的データ型)からのパターンマッチの解説の流れが特にどんどん知識が繋がっていく感覚が体験できて良かった。

個人的には第8章の「値としてのIO」まで学んだら、残りのPart2は一回飛ばしてPart3に行ってもいいかもしれないと思った(でも、第9章に再帰が来るから、そこは寄り道してもいいけど)。たいていの人にとって、ストリーム処理や、並列処理を学ぶより、どうやって現実のビジネスアプリケーションにおけるコードに、関数型プログラミングの考え方を導入するか?というテーマの方が身近な気がするので。

そして、Part3は改めてPart1, 2で解説された機能を踏まえて、関数型プログラミングではどのような設計の流れになるのか、テストはどうすれば良いのかといったテーマでの解説が続く。はっきり言ってめちゃめちゃ密度が凄いので、じっくり読んで、コードを実行しながら理解するように心がけていかないと、ささっと重要なことが通り過ぎていく。というか、テスト周りはテーマ的にも密度が濃すぎるので、これまたじっくり腰を据えて取り組んだ方が良い内容でした。最近自分が関心を持っているプロパティベースドテスティングもちゃんと出てきました。


さまざまなテーマをもとに関数型プログラミングを解説しているけど、一貫してビジネスドメインへの関心と、プログラムとして動かすために必要なさまざまな制御のための機能(エラー処理とか)をどうやって分離するのか、ということを実践的に説いている内容なので、特にビジネスアプリケーションの設計に携わっている人はぜひ読んだ方がいいでしょう。明日から突然関数型プログラミング言語を使ったプロジェクトに入る訳でなくとも、この考え方は絶対に有益なので。


あと、表紙のキャラクターがとにかく良い!(本文中には全然出てこないけど……代わりに謎のおじさん達が出てくる)

500ページ近くあるし、コード部分のフォントサイズが小さかったりと、詰め込み感が半端ないけど、夏休みみたいにまとまった時間が取れる時じゃないと読みづらい本だと思うので、今すぐ本屋へ買いに行って、夏休みの準備にしよう!

『ソフトウェアデザイン 2023年7月号』- 「GoFデザインパターン歴史探訪」がコンパクトにまとまってる有難い解説だった

今月のソフトウェアデザイン 2023年7月号、ちょっと興味深かったのは特別企画の「GOFデザインパターン歴史探訪」。

DDDとかもそうだけど、原典となる書籍が古くなって、特にアップデートもされていない場合、「原典だから」という理由で読むことをおすすめされても現代と状況が変わりすぎていて、コンテキストが合わず、どこを読めばいいのか分からない、みたいなことに遭遇する。

それが「周辺知識獲得のお勉強」であればまだいいのだけど、実務のためにサクっと「編集者の目を通った情報」を通じて理解したい時にこの手のまとめは凄く助かる。

GoFが生まれた時代的な背景から、そもそも想定されていた適用領域、現代における利用方法までコンパクトにまとまっていて分かりやすかった。

キャッチーなキーワードを「習得しなければいけないもの、知っていなければいけないもの」と必要以上に思わないってことが大事かな、と。


最後のページの広告が、『ちょうぜつソフトウェア設計入門』だったんですけど、こちらも現代におけるデザインパターンががっつり説明されているので、同じように理解する上での参考になると思います。

ScalaCheckを他のテスティングフレームワークと組み合わせる

blog.magnolia.tech

前回の記事の続き...

ScalaCheckで書かれたテストには、色々な起動方法が提供されていますが、他のテストと同じようにsbttestコマンドで起動できた方が便利です。

import org.scalacheck._

object ExampleTest extends Properties("String") {
  property("startWith") = Prop.forAll { (a: String, b: String) =>
    (a + b).endsWith(b)
  }
}

ScalaCheckには、sbtのtesting interfaceを継承したRunnerが提供されているので、Propertiesクラスを継承したテストクラスに、個々のテストをpropertyで定義しておけば、sbttestコマンドでテストが実行されます。

[info] + String.startWith: OK, passed 100 tests.
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 3 s, completed Jul 22, 2023, 4:27:10 PM

ただ、完全にScalaCheckだけでライブラリのテストが完結する、というシチュエーションはあまり無いので、既存のテスティングフレームワークの中でScalaCheckのテストを実行する方法が用意されています。

AirSpec

wvlet.org

wvlet.airspec.spi.PropertyCheckが、forAllのラッパー関数を提供しているので、そのままScalaCheckの記法と変わらず書けますし、独自のアサーションも使えます。

munit

scalameta.org

munit.ScalaCheckSuitepropertyのラッパー関数を提供しているので、そのままScalaCheckの記法と変わらず書けますし、独自のアサーションも使えます。


その他、specs2や、ScalaTestでもサポートされています。

specs2

etorreborre.github.io

ScalaTest

www.scalatest.org

ScalaCheckを使ってみた

いまさらだけど、ScalaCheckを使ってみた。

scalacheck.org

ScalaCheckは、HaskellのQuckCheckのScala版。

QuickCheck: Automatic testing of Haskell programs

Property Based Testingという考え方に基づくテスティングフレームワークで、汎用的に使われるライブラリに対して広範囲で網羅的なテストを書くために使われる。

例えば、以下のようなコードを書くと(この例のテストは必ず成功するので、意味はないけど)……

import org.scalacheck._

@main def propertyCheck = {
  numProp.check()
}

val numProp = Prop.forAll(Gen.choose(1, 10)) { n =>
  Prop.collect(n) {
    n == n
  }
}

以下のような結果が出てくる。

collectは実際に生成された値を確かめるための関数で、これでテストコードをラップしておくと実際に生成された値と、その割合が確認できる。

[info] running propertyCheck
+ OK, passed 100 tests.
> Collected test data:
14% 3
13% 7
12% 10
11% 2
10% 9
10% 4
10% 1
8% 5
7% 6
5% 8

ランダムに100個の1〜10までの数値が生成され、テストコードのインプットとなる。これにより自分で手作りしたParameterized Testingのパラメータより網羅度が上がる、という訳です。ただし、独自のデータ構造に適した、整合性が担保されたデータを自動生成するには、それなりのコード量を書くことになり、費用対効果を見てProperty Based Testingなのか、Parameterized Testingなのかを決めていくことになるでしょう。

この例では、日付や時刻のテストにScalaCheckを使っていますが、それなりにコード書くね、と。

dev.classmethod.jp


ちなみにcollect関数はSeq[T]に対して挙動がおかしくなる問題が有って、最もシンプルなList[Int]が上手く動かず、1時間くらい溶かしてしまった...

github.com

確実にに使うなら、引数に必ずtoStringで文字列に変換した結果を渡した方がいいかもしれない。


Functional Programming in Scala, Second Editionのサンプルコードが、1st Editionの時と違って、全面的にProperty Based Testingの独自ライブラリ(本の中で後半に出てくるProperty Based Testingのサンプル実装)で全体をテストするように書き直されていて、それはそれでいいけど、最初から用意されているテストコードを通るように、コードを書くだけだとちょっと理解が浅くなるなーと思って、同じものをScalaCheckで書き直してみたくなって使い始めたところ...でも、自動生成にハマり過ぎると、本末転倒感が有るので、使い方はほどほどに、という感じですかね。

www.manning.com

『ソフトウェア設計のトレードオフと誤り』を読んで、”日付や時刻”を扱うことの難しさについて考えた

ソフトウェア開発経験の最初の段階で「一つの機能には複数の選択肢が有って、メリット・デメリットがそれぞれ有り、それらはトレードオフの関係に有り、容易には決めることができない」という事実を教えてもらえる機会に遭遇できていれば、その人はとても幸運だと思う。

先輩や上司が一方的に、「一つの確かな方法」をただ伝える、みたいな場面(それが必ずしも一般的にはそうとは言えない方法であったとしても)も多いのではないでしょうか。

どんなに設計上の意思決定ができている人でも、その頭の中では「色々な選択肢の中で悩んで、ベストではないかもしれないけど、前の前の課題に対してよりベターな方法」を選んでいる。でもその思考の過程を見せてくれる人はとても少ない。

本書は、そんなトレードオフの思考の過程を丁寧に説明してくれる1冊。

デザインパターン(シングルトン)、コードの重複、エラーハンドリング、柔軟性、最適化......限られた開発期間の中でさまざまな意思決定をしていく中で必要なトレードオフ要素が解説される。その全てが実際に課題になるかはプロジェクトの状況次第だと思うけど、「正しいと言われていること」が常に最善・最適ではない、ということが分かれば、この本を読む価値はあるし、ある程度の経験があれば自然と判断してきたことが言語化されていることで、誰かに指導する時に役に立つに違いない。


ただ、実は自分はこの本を読んで「マジ最高!!」と思ったのは、「7章 日付と時間のデータを効率よく扱う」という章で、この章はあまりトレードオフっぽい話題ではなく、日付や時刻に関するライブラリの設計にあたって必要な知識がひたすら詰め込まれていて、いかに身近なテーマの裏には膨大なドメイン知識が必要なのか、ということがよく分かる章になっている。

歴史あるプログラミング言語では、日付系のライブラリが大きく作り直されていることが時々あるけど(JavaとかPerlとか)、なぜそんなことになってしまったのか......それは日付や時間を扱う上で考慮すべき要素がたくさん有って、それが初期のライブラリ設計の段階で十分に考慮できていなかった(考慮するためにはあまりに広範囲な知識が必要となる)のか......暦法、日付、時間、時間量、生年月日、年齢到達日......これでもか!と解説されるドメイン知識を見れば、「そりゃそうだよなー」という気持ちになることは間違いない。

そして、ライブラリの設計者だけでなく、日付/時間のライブラリを使う人が何を気をつけて使うべきかもしっかり書かれている。

そして更に大事なのが「7.2 日時情報を仕事で扱うための準備」という章で、もうこの章だけでも4180円を払う価値が有る、有りすぎる。

実際に日付や、時間/時刻の情報を元にビジネスロジックを組み立てる時に、あいまいな状態でもたらされる条件をコードに落とし込む際に考慮すべきポイントが列挙されていて、めちゃめちゃ役に立つ。

例えば、”顧客は3ヶ月以内は返品可能”と書かれた条件を実装する上で、どれだけ色々な条件を整理し、要求を出した人と合意しないといけないのか、一定の経験がある人が読めば必ず「分かる−」と叫ぶこと間違いなしです。

その後も日付や、時刻を扱うコードのテストに関する話など、お役立ち情報が満載です。

でも、これトレードオフでもなんでもなく、ただひたすら「これを考慮しないと死ぬ!」という知識、知恵の塊なので、ちょっと全体のテーマからは違和感が有るんですけど、とにかく読んで役に立つこと間違いなしです!!ぜひ読んでみて下さい!!

当然他の章もめちゃめちゃ有益なんですけど、この章の「今日、今すぐに役に立つ度」がずば抜けているので、紹介してみました。


というわけで、『ソフトウェア設計のトレードオフと誤り』、値段以上のお役立ち本なので、夏休みの課題図書に是非読んでおきましょう!

組織のコミュニーケーション速度について

「社長が言えばすぐにかわるんだろう?」みたいな発言をしている人を見たことがある。

つまり、何を重要視して組織の振る舞いが変わるか?みたいな問いかけに対して、「トップからの指示」が最も有効である、という価値観の元にある発言なんだな、と思った。

重要視していることが伝わらない、振る舞いが変わらないのだとしたら、いろいろな仕組みを変えていくしかないのだけど、そこに「どのくらいの時間軸でそれが達成されるか?」という視点が入ってくると、いろいろな要素が絡んでくる。

このことは、このくらいの優先度と、時間軸で伝わればいいよね?ということが、暗黙のうちに決まっていて、それが外部からの期待値と合わない時に外部からの評価は「変えられない組織」となってしまうのだけど、変えるまでの時間軸が合っていないだけだったりするし、合わないことがそもそもダメだったりもする。

ただ、そもそもその期待値は合っているんだっけ?という話がいつも置いていかれるんだけどね。