nekoTheShadow’s diary

IT業界の片隅でひっそり生きるシステムエンジニアです(´・ω・`)

読書メモ:『作って学ぶ Spring Boot入門』

gihyo.jp

今年に入ってから、技術書の読書メモはブクログに残すようにしているのですが、本書については、よい意味で書きたいことが多く、ブクログの文字数では収まりそうになかったため、こちらに読書メモとして残しておこうと思います。

一応Javaエンジニアを生業にしていることもあり、Javaそのものや関連技術のキャッチアップはなるべく継続しています。とくにSpring関連は進歩が速いため、新しく出版される入門書には可能な限り目を通すようにしています。

また、最近の仕事ではJavaに関わる機会はあまりないのですが、新入社員教育に携わる中でSpringを扱う場面があり、最新事情をキャッチアップしておく必要がありました。

ここ数年で読んだSpring Bootの入門書では、『プロになるためのSpring入門』がかなりよかったのですが、出版が2023年ということもあり、少し情報が古くなってきています。そこで、何かよい本はないかと探していて見つけたのが本書です。

結論から言うと、ここ数年で読んだSpring関連書籍の中ではベストの一冊でした。Spring Bootにこれから入門したい人はもちろん、知識をアップデートしたい人にも、自信をもっておすすめできます。

補足しておくと、『プロになるためのSpring入門』も非常によい本です。とくにDI(依存性注入)など、Springを構成する基礎概念の解説については、これほど分かりやすい本も珍しいと思います。多少古くなったことを考慮しても、今なお読む価値のある一冊だと考えています。

本書のよいところは挙げ始めるときりがないのですが、手元のメモからいくつか紹介します。

まず印象的だったのが、開発環境としてPleiades All in One Eclipseを紹介している点です。Javaの環境構築は以前よりずいぶん簡単になったとはいえ、JAVA_HOMEやPATHなど、初心者がつまずきやすいポイントはまだ残っています。その点、Pleiades All in One Eclipseであれば、ダウンロードしてZIPファイルを展開するだけでSpring Bootの開発を始められるため、初心者にとても寄り添った選択だと感じました。

流行ということで、VS Codeを採用する選択肢もありますが、環境構築の段階でつまずき、肝心のSpring Bootを動かすところまでたどり着けない可能性もあります。その意味でも、この選択はとても好印象でした。

また、Spring Bootの入門書ではJPAを採用するケースが多いのですが、本書ではJPAをあえて扱わず、Spring JDBCのみを採用している点も個人的には高く評価しています。

もちろんJPAも優れた技術であり、いかにもフレームワークらしい便利さを味わえる技術だと思います。しかし、これは少し個人的な思想も入りますが、業務アプリケーションではSQLをきちんと書いたほうがよい場面も少なくありません。そのため、本書はかなり実務を意識して構成されているように感じました。

もちろん、ServiceクラスへJdbcClientを直接@Autowiredするような実装にはなっておらず、きちんとリポジトリパターンを採用しています。現代的なレイヤードアーキテクチャを意識した構成になっている点も好印象でした。

テストコードが充実している点も素晴らしいと思います。Springの入門書は、この部分が意外と省略されているものが少なくありません。しかし、実務でテストコードを書かないことはほとんどありませんから、しっかりページ数を割いて解説されているのは非常に好感が持てました。

また、学習の過程ではいくつかのWebアプリケーションを作成しますが、その中でREST APIの実装にもかなりのページ数が割かれています。この点も個人的には高く評価しています。

この手の入門書は、Thymeleafを使ったサーバーサイドレンダリングのWebアプリケーションを作って終わり、という構成が少なくありません。しかし実務では、Spring BootでREST APIを実装し、フロントエンドはVueやReact、あるいはモバイルアプリが担当するケースも多いため、REST APIをしっかり扱っている本書は非常に実践的だと感じました。

さらに、個人的にはSpring Securityについて知識をアップデートできたのも収穫でした。Spring Securityは設定方法や書き方が比較的よく変わる印象があるため、定期的に学び直す必要があると感じています。

ここまでよかった点をたくさん挙げてきましたが、不満があるとすれば、アプリケーションログについての解説が少しあってもよかったかな、という程度でしょうか。

また、Spring Batchについても触れられていればなおよかったとは思いますが、これは本書のコンセプトから少し外れてしまうので、ないものねだりかもしれません。

もう一つ細かい点を挙げると、falseの判定に== falseを使っている箇所がありました。これは単純に私の流儀との違いなのですが、例えば存在チェックで本書ではif (exists() == false) { ... }のような書き方が散見されます。個人的にはif (!exists()) { ... }と書きたい派です。もしかすると前者が最近のスタイルなのかもしれませんが、そのあたりは少し気になりました。

とはいえ、不満らしい不満はその程度です。

Spring Bootの機能を実践的な観点から一通り学びたい人、とくに実際に手を動かしながら写経形式で学習したい人にとって、本書は間違いなくおすすめできます。

今後、Spring Bootの入門書の定番の一冊になってもまったく不思議ではありません。それくらい完成度が高く、自信をもっておすすめできる一冊です。

令和8年5月最新:わが家のコーヒー抽出レシピ

はじめに

以前、自分のコーヒーの抽出方法について、備忘録もかねて紹介しました。

https://nekotheshadow.hatenablog.com/entry/2025/04/26/232829

このあともいろいろと試した結果、アップデートがあったので、以前と同じく備忘録がわりにブログにまとめておきます!

なお、ドリッパーは相変わらずHARIOのV60(樹脂製)を使っています。

ホットコーヒー

☕ 抽出レシピ

  • コーヒー粉:お湯 = 1:15

✍ 淹れ方の手順

  1. 下準備
    • ドリッパーにペーパーフィルターとコーヒー粉をセットします。(※ペーパーのリンスは行いません)
  2. お湯の準備
    • 沸騰したお湯をドリップケトルに移します。
  3. 蒸らし(20%)
    • 全体量の20%のお湯を回しかけ、30秒間蒸らします。
  4. 本抽出(20% ➔ 60%)
    • 蒸らしが終わったら、残りのお湯を2回に分けて注ぎます。
      • 注ぐ量: 残りのお湯を「20% ➔ 60%」の順で注ぐ。
        • ※ドリッパーが小さい場合や湯量が多い場合は、「20% ➔ 30% ➔ 30%」の3回に分けてもOK!
      • タイミング: 注いだお湯がほとんど落ち切ってから、次のお湯を注ぎます。
      • 注ぎ方: コーヒー粉全体に均等に回しかけるように注ぎます。

📊 具体例

コーヒー粉が 20g の場合(お湯 300g)

  • 1投目(蒸らし): 60g(20%)を注いで30秒待つ
  • 2投目: 60g(20%)を注ぐ
  • 3投目: 180g(60%)を注ぐ

コーヒー粉が 40g の場合(お湯 600g)

※量が多いので、3回に分けて注ぐパターンです。

  • 1投目(蒸らし): 120g(20%)を注いで30秒待つ
  • 2投目: 120g(20%)を注ぐ
  • 3投目: 180g(30%)を注ぐ
  • 4投目: 180g(30%)を注ぐ

アイスコーヒー

🧊 抽出レシピ

  • コーヒー粉:お湯 = 1:10

✍ 淹れ方の手順

  1. 下準備
    • ドリッパーにペーパーフィルターとコーヒー粉をセットします。(※ペーパーのリンスは行いません)
  2. 氷の準備
    • コーヒーサーバーに氷をなるべくたくさん入れます。
      • ※氷は冷蔵庫の製氷機で作ったものでOKです!
  3. お湯の準備
    • 沸騰したお湯をドリップケトルに移します。
  4. 蒸らし(20%)
    • 全体量の20%のお湯を回しかけ、30秒間蒸らします。
  5. 本抽出(20% ➔ 60%)
    • 蒸らしが終わったら、残りのお湯を2回に分けて注ぎます。
      • 注ぐ量: 残りのお湯を「20% ➔ 60%」の順で注ぐ。
        • ※ドリッパーが小さい場合や湯量が多い場合は、「20% ➔ 30% ➔ 30%」の3回に分けてもOK!
      • タイミング: 注いだお湯がほとんど落ち切ってから、次のお湯を注ぎます。
      • 注ぎ方: コーヒー粉全体に均等に回しかけるように注ぎます。

📊 具体例

コーヒー粉が 20g の場合(お湯 200g)

  • 1投目(蒸らし): 40g(20%)を注いで30秒待つ
  • 2投目: 40g(20%)を注ぐ
  • 3投目: 120g(60%)を注ぐ

コーヒー粉が 40g の場合(お湯 400g)

  • 1投目(蒸らし): 80g(20%)を注いで30秒待つ
  • 2投目: 80g(20%)を注ぐ
  • 3投目: 240g(60%)を注ぐ

読書メモ:『ミックの楽しいSQLパズル』の気になった問題について

はじめに

honto.jp

最近『ミックの楽しいSQLパズル』という本を読みました。めっちゃよい本だったので、いずれ全体の読書感想文は書きたいと思うのですが、気になった問題について、簡単にまとめておこうと思います。

その問題が「問題32 都市間の最短経路」です。ざっくりいうと、下記のような都市と都市のつながりとその距離が与えられているときに、New Yorkから各都市への最短距離を求めなさいというもの。

CREATE TABLE Routes (
  source_city VARCHAR(32),
  destination_city VARCHAR(32) , 
  distance INTEGER NOT NULL,
  CONSTRAINT pk_Cities PRIMARY KEY (source_city, destination_city)
);

難しいのは、閉路が含まれている点。本書ではPostgreSQLの配列機能を用いた回答が紹介されているのですが、別のRDBMSではどのように解けるのかを考えていきたいと思います。

ちなみに以下はPostgreSQL版のわたしの回答です。

WITH RECURSIVE CTE (city, distance, path) AS (
    SELECT 'New York'::VARCHAR, 0, ARRAY['New York']
  UNION ALL
    SELECT R.destination_city, CTE.distance + R.distance, CTE.path || R.destination_city
    FROM CTE
    JOIN Routes R ON CTE.city = R.source_city AND R.destination_city <> ALL(CTE.path)
)
SELECT city, MIN(distance) distance_from_new_york
FROM CTE 
GROUP BY city

Oracle Database

一番簡単なのがOracle 19cで、閉路検出機能(CYCLE)を利用すればよいです。

WITH CTE (city, distance) AS (
    SELECT 'New York', 0 FROM DUAL
  UNION ALL
    SELECT R.destination_city, CTE.distance + R.distance
    FROM CTE
    JOIN Routes R ON CTE.city = R.source_city
)
CYCLE city SET is_cycle to 'Y' default 'N'
SELECT city, MIN(distance) distance_from_new_york
FROM CTE
GROUP BY city

MySQL

次にMySQL 8.0ですが、まず思いつくのは、経路を区切り文字付きのCHARで管理する方法。

WITH RECURSIVE CTE (city, distance, path) AS (
    SELECT CAST('New York' AS CHAR(32)), 0, CAST('|New York|' AS CHAR(1000)) 
  UNION ALL
    SELECT 
        R.destination_city,
        CTE.distance + R.distance,
        CONCAT(CTE.path, R.destination_city, '|')
    FROM CTE
    JOIN Routes R 
      ON CTE.city = R.source_city
     AND INSTR(CTE.path, CONCAT('|', R.destination_city, '|')) = 0
)
SELECT city, MIN(distance) AS distance_from_new_york
FROM CTE
GROUP BY city

あるいは、JSONを連想配列として経路を管理してもよさそうです。

WITH RECURSIVE CTE (city, distance, path) AS (
    SELECT CAST('New York' AS CHAR(32)), 0, JSON_OBJECT('New York', true)
  UNION ALL
    SELECT 
      R.destination_city, 
      CTE.distance + R.distance, 
      JSON_SET(path, CONCAT('$."', R.destination_city, '"'), true)
    FROM CTE
    JOIN Routes R 
      ON CTE.city = R.source_city
     AND JSON_EXTRACT(path, CONCAT('$."', R.destination_city, '"')) IS NULL
)
SELECT city, MIN(distance) AS distance_from_new_york
FROM CTE
GROUP BY city

SQL Server

SQL Server 2019についても、MySQLの解法をSQL Server用に書き換えてやれば解けそうです。まずはpathを文字列にて管理するパターン。

WITH CTE (city, distance, path) AS (
    SELECT CAST('New York' AS VARCHAR(32)), 0, CAST('|New York|' AS VARCHAR(MAX))
  UNION ALL
    SELECT 
        R.destination_city,
        CTE.distance + R.distance,
        CONCAT(CTE.path, R.destination_city, '|')
    FROM CTE
    JOIN Routes R 
      ON CTE.city = R.source_city
      AND CHARINDEX(CONCAT('|', R.destination_city, '|'), CTE.path) = 0
)
SELECT city, MIN(distance) AS distance_from_new_york
FROM CTE
GROUP BY city;

JSONを利用する方法も一部の書き換えで動きそうです。

WITH CTE (city, distance, path) AS (
    SELECT CAST('New York' AS VARCHAR(32)), 0, JSON_OBJECT('New York':1)
  UNION ALL
    SELECT 
      R.destination_city, 
      CTE.distance + R.distance, 
      JSON_MODIFY(path, CONCAT('$."', R.destination_city, '"'), 1)
    FROM CTE
    JOIN Routes R 
      ON CTE.city = R.source_city
    AND JSON_PATH_EXISTS(path, CONCAT('$."', R.destination_city, '"')) = 0
)
SELECT city, MIN(distance) AS distance_from_new_york
FROM CTE
GROUP BY city

闘いの記録:CORSを理解するまでの調査メモ

この記事を一言でいうなら、「闘いの記録」です。ここ数ヶ月、とある大規模Webアプリの保守運用に関わっているのですが、その中でCORS対応にどっぷり浸かることになりました。 正直に白状すると、これまでの開発人生でCORSをあんまり意識してこなかったというか、中身についてはお恥ずかしながら詳しくなかったんです。そんなわけで、今回は基礎中の基礎から泥臭く調べ直しました。この記事はその時の「調査メモ」を自分なりに整理してまとめたものです。正直なところ、ネットにある情報を自分なりに解釈し直しただけなので、「わざわざ世に出すほどの内容かな?」と迷うラインではありました。でも、せっかく七転八倒してまとめたので、供養のつもりで公開しちゃいます。ちなみに、普段の技術ネタはQiitaに書くというマイルールがあるのですが、今回の記事はあまりに「自分用の格闘メモ」すぎるので、この個人ブログにひっそりと置いておくことにしました。


はじめに

Webブラウザには「同一オリジンポリシー」という基本的なセキュリティルールが実装されており、異なるドメイン間でのデータ通信が制限されています。

例えば、xxx.com上で動作するJavaScriptからyyy.comのAPIにPOSTリクエストを送信しようとすると、エラーが発生します。

しかし、実際の運用においては、異なるドメイン間で通信を許可する必要が生じる場合があります。これを実現する仕組みがCORS(Cross-Origin Resource Sharing)です。

概要

1. ブラウザによるプリフライトリクエストの送信

ブラウザは、クロスオリジンで「安全でない」とみなされるリクエスト(POSTやPUTなどGET以外のメソッド、カスタムヘッダー付きのリクエスト等)を送信する際、事前にOPTIONSメソッドによるプリフライトリクエストを送信します。

2. サーバーによるCORSレスポンスヘッダーの送信

サーバーはCORS関連のHTTPヘッダーを付与してレスポンスを返します(つまり、サーバー側で設定が必要になります)。

3. ブラウザによるレスポンスヘッダーの検証

ブラウザは、以下の条件を確認します。

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Methods
    • リクエストで指定したHTTPメソッド(例: POST、PUTなど)が許可されているか。
  • Access-Control-Allow-Headers
    • リクエストで使用するカスタムヘッダー(Content-TypeやAuthorization等)が許可されているか。

これらの条件がすべて満たされていれば、リクエストは許可されたと判断されます。条件を満たさない場合、リクエスト自体が送信されず、JavaScript側でエラーとなります。

4. 本来のリクエストの送信

ブラウザが条件をすべて満たしていると判定した場合、実際のリクエスト(GET, POST, PUTなど)が送信されます。

5. サーバーによるリクエスト処理とCORSレスポンスヘッダーの付与

サーバーは、リクエストが同一オリジンかクロスオリジンかに関係なく、通常どおりリクエスト内容を処理します。ただし、レスポンスにもCORS関連のヘッダーを付与する必要があります。

6. ブラウザによる最終判定とJavaScriptからのアクセス制御

ブラウザはレスポンスヘッダーを確認し、Access-Control-Allow-Originが自身のオリジンと一致していれば、JavaScriptからレスポンス本文にアクセスできます。一致しない場合、レスポンス本文へのアクセスはブロックされ、CORSエラーとなります。

発生条件

CORSは、JavaScriptによるクロスオリジンのAPIアクセス(fetch、XMLHttpRequest、画像の読み込みなど)に対するセキュリティ制約です。フォーム送信やリンククリックによるページ遷移には適用されません。例えば、JavaScriptでフォーム送信を実行した場合、CORS認証やプリフライトリクエストは発生しません。サーバー側でリダイレクトやエラーが返されることはありますが、CORSエラー(JavaScriptによるレスポンスのブロック)は生じません。

fetch APIにおけるレスポンス種別

fetch APIを利用してクロスオリジンリクエストを行う際、CORSの設定やリダイレクトの有無によって、返されるレスポンスの「種別(typeプロパティ)」が変化します。これにより、JavaScriptからアクセスできる情報の範囲が制限されます。

リクエストの状況に応じたレスポンス種別の判定フローは以下の通りです。

レスポンス種別の詳細

判定された各 typeによって、JavaScriptからアクセスできる情報の範囲が以下のように制限されます。

  • basic
    • 同一オリジンへのリクエスト、またはCORSを介さないリクエストで返されます。レスポンスボディ、ヘッダー、ステータスコードのすべてにアクセス可能です。
  • cors
    • CORSが正しく許可されたクロスオリジンリクエストで返されます。レスポンスボディと、特定の制限されたヘッダー(および Access-Control-Expose-Headers で許可されたもの)にアクセスできます。
  • opaque
    • no-cors モードで送信されたリクエストの結果です。セキュリティ上の理由から、レスポンスの内容(ボディやヘッダー)は一切読み取れず、ステータスコードも一律で 0 となります。
  • opaqueredirect
    • リダイレクト(3xx)が発生し、そのリダイレクト先がクロスオリジンである場合に返されることがあります。opaque 同様、内容へのアクセスは制限され、ステータスコード0 になります。

Tips

  • 異なるドメインへの通信でも、プリフライトリクエストが送信される場合と送信されない場合があります。詳細については、以下のURLを参照してください。
  • Chromeではセキュリティ上の理由から、開発者ツールのネットワークタブでプリフライトリクエストの内容を確認できません。プリフライトリクエスト自体が送信されているかどうかも確認できないため、専用ツールや拡張機能の導入が必要です。なお、Firefoxの開発者ツールでは確認可能です。
  • 本リクエストのレスポンスが3xx(リダイレクト)ステータスの場合、ブラウザはリダイレクト先に自動的にリクエストを送信します。リダイレクト先がクロスオリジンである場合、リダイレクト先のサーバーでもCORSヘッダーを返す必要があります。ヘッダーが返されない場合、ブラウザはそのレスポンスをブロックし、JavaScriptから結果を取得できません。

読書記録③『Python Django本格入門』『実務で役立つ ログの教科書』『システムの引き継ぎに失敗しないための本』『サイバー攻撃 その瞬間 社長の決定』

気づけば3回構成になってしまった読書メモの続きです。ここまで来たので最後までまとめておこう、という気持ちで書いている3回目です。


Python Django本格入門』

honto.jp

FWについては、定期的に勉強したいと思っていて、なかでもDjangoは少し気になっているFWだったので、そういう意味ではドンピシャの1冊でした。簡単なアプリケーションを実装しながら、Djangoの機能を一通り学べる内容で、Djangoのとっかかりにはよかったかと思います。写経スタイルなところも、個人的には好みでした。Type Hintをまったく取り入れていないこと、レスポンスがHTMLばかりで、JSONを返させる例がないこと。このあたりがややひっかかりましたが、全体的には満足ですね。

『実務で役立つ ログの教科書』

honto.jp

コンピューターにかかわっていて、ログというのは避けて通れないものですが、しかし、本としてまとまっているものは意外にないということで、発売直後に買って読んだ1冊です。教科書と名乗るにふさわしく、ログとは何かというところから、その活用法にいたるまで、ログにかかわるトピックを包括的に扱う内容になっています。ログといっても、PCのイベントログからWebシステムのアプリケーションログまで、さまざまな種類があります。活用法も千差万別。監査やマーケティング、あるいは、昨今はやりのAIにいたるまで、幅広い内容をぎゅっとまとめています。特殊なユースケースにすぐ適用できるような即効性がある内容にはなっていませんが、しかし、基礎的な部分を再度整理しなおすというところでは、読んでよかったと思いました。

『システムの引き継ぎに失敗しないための本』

honto.jp

システムを担当している担当者やベンダーがいなくなるというのがIT業界にいると意外にあることで、計画的に交代することもあれば、急にいなくなることも少なくないと聞いています。本書はそういうシステムのノウハウをまとめており、珍しい視点ではあるのですが、確実に需要のある本ではあります。内容も全体的に納得感のあるものとなっており、きわめて実践的・実務的であると感じました。自分はベンダー側の人間なので、どちらかといえば引き継ぐ側の人間ですが、引継ぎが発生した場合には、本書を参考によい引継ぎをしていきたいと思いました。

サイバー攻撃 その瞬間 社長の決定』

honto.jp

技術書ではないんですが、ITにかかわる本なので、読書メモを残しておきます。関通という物流会社がランサムウェアの被害にあったときのことを社長自らが記した1冊です。本として洗練されているとは言い難いので、若干読みづらさはありますが、攻撃を受けた側が何を考えて、どう行動したのかを当事者が記録しているというのは珍しく、目から鱗な話も多く面白く読みました。あとは、この本を紹介しているYoutube動画もおすすめです(というかこれに影響されて買った)

www.youtube.com

読書記録②『SQLアンチパターン 第2版』『分散システムのためのデザインパターン』『ソフトウェア設計の結合バランス』

最近読んだ技術書のメモを書いていたら、思った以上に分量がふくらんでしまいました。というわけで、前回に続いての2回目です。自分の備忘録も兼ねて、ゆるっと残しておきます。


SQLアンチパターン 第2版』

SQLアンチパターン 第2版www.maruzenjunkudo.co.jp

初版はむかしむかしに読んでいて、引っ越しの際に捨ててしまったのですが、新版が出ると聞いて、買いなおし&読み直しました。いわずとしれた名著なので、内容はいわずもがなよかったです。いろいろ経験したこともあって、昔読んだときより学びが深まったような気がします。SQLに触れるITエンジニアであれば必読でしょう。

『分散システムのためのデザインパターン

honto.jp

ここ数か月に読んだ技術書の中では、とびぬけて骨のある1冊でした。まず前半で、MongoDBやTiDBのような分散システムがどのように動いているのかについて、その概要・全体像を解説。後半では、前半で紹介した全体像をもとに、整合性をとりながら分散システムをうまく動かす仕組みをパターンとして紹介します。分散システムの専門家でもないので、全部を理解できたわけではないのですが、これまでのシステムエンジニア経験でいろいろ聞きかじってきたワードの概要ぐらいはわかったと思います。今後、仕事で何かかかわることがあったら、辞書的に開くことになりそうです。

『ソフトウェア設計の結合バランス』

honto.jp

これは面白かった!世の中にはモジュールを分割するテクニックはあふれていますが、しかし現実には、モジュールどうしを結合して初めてシステムというのは出来上がるわけです。本書はこのモジュールの結合について、深く議論した1冊です。そもそもの命題設定自体もかなり面白いですが、なかで展開される議論や尺度についても、あまり考えたことがなかったような斬新な視点ばかりで、これからのソフトウェアアーキテクチャやソフトウェア設計を語るうえでニュースタンダードになる気がします。よい結合・あるべき結合について、本書はわかりやすい結論のようなものを提示するわけではないですが、逆にそれも本書の価値をあげている気がします。システムアーキテクトを名乗る人はみな読むべき1冊だと思いました。

読書記録①『エンジニアのためのWord再入門講座 新版』『JavaScript/TypeScript実力強化書』『Exercise JavaScript』『型システムのしくみ』

最近読んだ技術書のメモを書いていたら、思ったより長くなってしまいました。というわけで、全3回に分けてまとめています。まずはその1回目として、ここしばらく読んだ本を簡単に振り返ります。


『エンジニアのためのWord再入門講座 新版』

honto.jp

仕事でWordをがっつり使うかもしれなかったので、読んだ本(結局使わなかった)。大学生の卒論以来、Wordをまともに使ったことがなかったので、Wordの思想や便利な機能を知れたのはよかったです。筆者がおすすめするWordテンプレートを配布してくれたらもっとよかったですね。

JavaScript/TypeScript実力強化書』

honto.jp

TypeScriptを利用する仕事に就くとなって、読んだ本になります。いろいろな著者が書いた雑誌の記事をまとめたものなので、内容やレベル感は正直まちまちではあります。初歩的な記事はともかくとして、やや発展的なトピックを扱った記事については、知らないことも多かったので、勉強になりました。自分のような初心者以上上級者未満向けの内容の本は珍しいので、貴重な1冊だと思いました。

『Exercise JavaScript

honto.jp

あんまり期待せずに読んだのですが、結構面白かったです。JavaScriptのニッチな仕様をクイズ形式で紹介するという、それはそれでニッチな需要に応えた本なのですが、なんとなくでJavaScriptに向き合ってきた自分にとっては、かなり勉強になりました。とくに巻き上げ関連の仕様はぜんぜん知らなかったので、この本を読んでいてよかったなと思いました。ページ数は少なめ、内容もぎっしり詰まっている感じではないので、自分のようなJavaScriptよわよわ勢にはおすすめです。

『型システムのしくみ』

型システムのしくみ TypeScriptで実装しながら学ぶ型とプログラミング言語www.maruzenjunkudo.co.jp

個人的にはここ数か月で一番のヒットでした。TypeScriptのサブセット言語の型検査器を自作することで、型システムの基礎を学ぶ1冊です。実際に手を動かすと、字を読んでいるより、ずっと実感がわいて、いいですよね。知的好奇心を満足させることもさることながら、TypeScriptを利用する仕事についているということで、仕事に直結しました。筆者はTAPLの入門書・副読本として読んでほしいとしていますが、自分のようにそこまで進まなくても、型のあるプログラミング言語の利用者であれば、かなり勉強になると思います。