ナカザンドットネット

それって私の感想ですよね

プログラミングを始めてからこれまでどこにフォーカスしてきたか振り返ってみる

mhidakaが建てたAdvent Calendar 2の8日目です。テーマ性なさすぎてほんと狂ってんなこのカレンダー……

adventar.org

というわけで何書いてもいいらしいので、サクッと書ける割に独自性の出やすい、自分の経験を振り返る系記事にしてみようと思います。

コンピュータサイエンスの大学に2005年に入学した人間としてはお恥ずかしいところなのですが、コードを書こうと思ってコードを書くようになったのは大学5年目の2009年だったので、僕の主観では2023年現在がようやくプログラマー15年目という感じです。節目っぽい感じがするので、それぞれの年で思い出深いテクノロジーを思い出していこうと思います。

それ職務経歴書じゃね?と思わなくもないですが、もうちょっとライトかつミーハーな感じでなんとかしたい。やっていきましょう。

2009年(22歳)

プログラマーとしての自我を持ち始めたのはこの年でした。なんとか卒論を書くのに必要な単位が溜まって、さて何を書こうかなと思っていたところに、担当教員から「なんかAndroidとかいうのが日本にも来るらしいじゃん?HT-03A?とかいうの買ってあげるからやってみない?」と言われて、卒業研究がAndroidになったのでした。

研究室は医療系、特にバイタルサイン系に強みがあり、さらにモバイルデバイス(当時はガラケーが主流)との連携が得意な、ちょっと特殊なところでした。そこで何をすることになったのかというと、Nonin社のパルスオキシメーターとAndroidをBluetoothで繋いで、SPPで送られてくるバイナリのストリームをいい感じにAndroidで処理できる形に落とし込むやつです。

blog.nkzn.net

これのやばい話としては、当時のAndroid 1.6って、Bluetoothが非公開APIだったんですよね。がんばってリフレクションしてBluetoothのAPIを引っ張り出しながら無理やり使ってました。当時、「すれちがったー」のesmasui先生には大変お世話になりました……

そんなわけで、2009年にフォーカスしていたテクノロジー分野はこんな感じでした。

  • Android SDK(Android 1.6)
  • Bluetooth
  • 血中酸素飽和度(SpO2値)計測

2009年当時だと、SpO2値は喘息持ちの方は知っていることが多いものの、一般的にはややマイナーなバイタルサインでした。そのため、卒業研究を他の人に説明するときに「ふーん……?」というピンと来ない感じの反応をされることが多かったです。

それが、2023年現在では、もう少し有名な指標になりました。COVID-19に罹患した際の体調の指標として、SpO2値が参照されるようになったため、計測器であるパルスオキシメーターともども、僕が研究していた分野が広く一般に知られるようになったのです。何が起こるかわからんもんじゃ。

2010年(23歳)

2010年の春に大学を卒業して、地元にUターンして就職しました。就活していた2008年の時点ではプログラミング苦手マンだったので、人柄で採ってもらえるところに拾ってもらいました。サークル活動で日本中回ってたり、サークル自治会の会計職やったり、原付で新潟県を縦断してたり、無駄にアクティブな学生生活を送っていたので、面接で「キミ営業職で入る気はない?」と訊かれてしまったのは良い思い出です。

お仕事としてはB2BのWeb系受託みたいなことをやりつつ、学生時代にご縁ができたAndroidコミュニティと関わりを持ちながら、新潟市でAndroidの勉強会を開催したりしていました。

2010年のキーワードはざっくりこんな感じでしょうか。

  • Java 1.4
  • JBoss
  • ASP.NET + HTML + CSS
  • VB.NET
  • Android 2.x
  • Android Maps

これまでの人生で、ちゃんとお仕事で.NETを触ったのはこの時期だけです。趣味でC#も触ってみましたが、言語としては全然違うのに、VB.NETとほとんど同じ標準ライブラリがちゃんと触れるのはすごいなあと感動したのを覚えています。当時メインでやっていたJavaでは、言語とランタイムの距離が近いので、言語とランタイムを分けて考える発想がなかったんですよね。今考えるとAndroid Javaというランタイムは普通のJVMとは似ても似つかない感じだったのですが、それを切り分けて考えられるきっかけになったのは、.NETの経験でした。

そういえば、大学の卒業前にGClue社でアルバイトをすることになり、Android 1.6のマップ上でGeofencingの自前実装みたいなことをするアプリを作っていました。当時の勉強会で、Android Mapsについて喋っていたのが見つかりました。

www.slideshare.net

僕のGIS元年は2010年だったようです。

2011年(24歳)

この年の9月に転職して、約10年ほど農業ITをやることになりました。それまでの期間は、Webサイトを作っていましたねえ。お仕事でWordPressを触るよりも先にConcrete 5を触るという不思議な経験をしました。結局年末には転職先でWordPress製の自社サイトをメンテしていたのを思うと、CMSと距離が近い年だったのかもしれない。

2011年のキーワードはこんな感じ。

  • Android 2.x〜3.x
    • Android Maps
    • ActionBarCompat
  • Concrete 5
  • WordPress
  • Corona SDK / Lua言語
  • Git

僕が携わることになった農業ITシステムは、現在の語彙でざっくり言えば農業向けのGISだったので、主に戦う相手はAndroid Mapsになりました。ActionBarCompatのコードリーディングをしたりもしてたようです。Android 2.x〜4.0の過渡期のあれこれに悩まされていたような気がします。

他に、当時からモバイル向けクロスプラットフォーム開発への関心があったのもあって、友人が取り組んでいたCorona SDK(現在のSolar2D)という、Lua言語でアプリが書けるフレームワークの布教もしていました。電子書籍ではありますが、人生初の本も出しました。

tatsu-zine.com

この本、本名で出しているんですよね。それまでは匿名でインターネッツをやっていましたが、こういった功績はちゃんと現実世界の自分のキャリアに寄与するべきだという意識もあったので、腹を括って本名で活動することにしました。この方針のおかげもあってか、今のところ「中川幸哉」という同姓同名の中では日本一有名な中川幸哉になれているのではないかと思います。

そういえば、現在も技術書典の運営でご一緒しているtakahashimさんと初めて会ったのはこのときでしたし、Gitを初めて触ったのもこの本を書くためでした。ReVIEWにも一瞬だけ触れた気がしますが、基本的にはMarkdownで執筆して、takahashimさんがReVIEWに書き直してくれるワークフローだったような気がします。ちゃんとReVIEWを書くのはもう少し後の話。

2023年から見ると、これが前回の卯年だったわけですが、「せっかくの年男なので、2011年は飛躍の年にしよう」と意気込んでいたのが飛躍しすぎた年でした。

2012年(25歳)

ゴリゴリとアプリを作っていた時期です。

  • Android 4.x
  • JSON
  • Google Maps Android API v2
  • Git

すでにWeb版があるサービスのモバイルアプリ版を整備していくのが主なお仕事だったので、JSON色付け係として粛々とやっていました。当時から思ってたけど、JSONってJavaScript以外の言語で使うと不便じゃないですか?

大きめのトピックとしては、なかなか使い勝手の悪かったAndroid Mapsが刷新され、Google MapsのAPIがちゃんと整備されたのがありました。当時、そこら中で喜びを伝えていたような記憶があります。

2011年と比べて薄味じゃないかって?この記事を書くのに飽きてきたのもあるけど、2011年が濃すぎたんだよ。

2013年(26歳)

お仕事的には農業機械メーカーとの協業が始まった時期です。キーワード的にはこんな感じ。

  • Android
  • Maven
  • Google Maps Android API v2
  • 農業機械(トラクター・コンバイン・田植え機)
  • オフライン機能
  • ReVIEW

こうして並べるとだいぶ濃いですね……

本業では主に、農業機械とモバイルアプリで通信して、擬似的に農業機械をインターネットとやりとりさせるやつを作ったりしていました。今振り返ると、2010年代後半にIoTという名前で流行ったやつでした。うーん先進的。Webサービスやモバイルアプリ開発の面では私たちが貢献しましたが、それ以外の部分については農業機械メーカーさんのプロダクト開発力やサービス構成力に驚かされるばかりでした。

AndroidらしいAndroidな分野としては、2013年当時だとまだ珍しかったオフライン動作にチャレンジし始めていました。AlermManagerで頑張って定期データ同期を実現する荒削りな方式を考案して、なんとかしていたような気がします。データベースを扱う機会が増えたので、OrmLiteを使ったりもしていました。そういえばパッケージマネージャとしてMavenを使うのも取り組んでた気がする。非公式な分野だったので苦しみもあったけど、jarファイルを直接扱う世界から解放されたのは嬉しかった。

他に大きいところとしては、2010〜2012年にAndroid×Googleマップの情報発信をしていたのをmhidakaさん🐏が見てくれていたようで、TechBoosterの巨大合同誌、Effective Androidに誘ってもらいました。ReVIEWをちゃんと書いたのはこのときが初めてだったと思います。

tatsu-zine.com

ちなみに、現職のCTOであるid:gabuchanも参加しています。ご縁って怖いなあ。

2014年(27歳)

このへんはあんまり本業の記憶がない……興味を持って取り組んでいたらしいのはこの辺。

  • Android
  • Android Studio
  • Gradle
  • Robolectric + JUnit
  • オフライン動作(Sync Adapter)
  • ActiveAndroid
  • Kotlin(not Android)

そうだったそうだった。Android StudioとGradleでの開発環境がいい感じになってきたので、会社のアプリのビルド環境をMavenからGradleに移行したりしていました。

Robolectricで自動テストを書きやすい環境もできてきていたので、JUnitとも仲良くなり始めていた頃です。JUnit実践入門は今でも名著だと思ってるよ。

gihyo.jp

2013年に引き続き、オフライン動作については研究を続けていました。50 Android Hacksを参考に、Sync Adapterを頑張って実装すれば割とそれっぽくなることがわかったり。当時はドキュメンテーションが全くなくて、コミュニティベースの手探りで実装方法を探っていました。

SQLiteの管理をもっと改善できないかと悩んで、ActiveAndroidを触ってみた時代もありました。最終的にはこなれているO/Rマッパーはないな、という結論になってしまい、直接SQLを書く形になりました。

ちなみに、なぜかこの頃に一度Kotlinに触っています。

www.slideshare.net

うーん先見の明はあったはずなんだけど、結局Kotlinコミュニティには全く爪痕を残せていないので、今生では強い縁がないのだなという感じ。

2015年(28歳)

ちょっとキャリアの風向きが変わってきたのがこの頃。

  • Android Lint
  • Ionic Framework + AngularJS
  • React Native

本業は相変わらずAndroidアプリ開発だったのですが、だんだんとiOSプラットフォームでも動くものを作らないといけない圧力が高まってきていました。素直にiOS SDKを学ぶ方向に行けばよかったのですが、昔からクロスプラットフォームに憧れがあったのもあって、Ionic Frameworkを試したり、当時まだ出たばかりで眉唾感のあったReact Nativeのソースを読んだりしていました。

新人教育の文脈でAndroid Lintが結構活用できるなあ、と気づいたのはこの年でした。

DroidKaigiの第1回が行われたのもこの年でしたね。2013〜2014年に取り組んでいた、Androidアプリのオフライン動作についての発表を行いました。この時点での僕はもう2年くらいずっとオフラインのことを考えていたので、アプリをオフラインで動かすのはよくある話なんだと思っていましたが、発表してみたら全然そんなことなかったのでバイアスって怖いなと思いました。

watercelldev.hatenablog.jp

2016年(29歳)

ようやく折り返しです。サクッと書けるとか言ったの誰だよ!!!!!

この年はだいぶ尖ってます。

  • Cordova
  • webpack
  • React
  • Material-UI
  • Firebase
  • React Native
  • Clean Architecture

この年は大きく分けて3つほどサービスを作っていました。

  • Cordova+React+Material-UIのiOSアプリ
  • 現場用のAndroidアプリと事務所用のWebアプリのデータ保存先としてFirebaseを使うやつ
  • React Native製の掲示板アプリのプロトタイピング

手広くはあるのですが、全体的に軸足がWebに寄ってきたなという感じがありますね。

それはそうと新規アプリが多かったのがあって、アーキテクチャ周りのトライアンドエラー経験を大量に稼げた時期でもあります。クリーンアーキテクチャをカーゴカルト的に導入して爆死したケースがたくさんあったってことだよ言わせんな恥ずかしい!

たくさんの失敗を経て、設計に関する解像度が少しずつ上がり始めた時期ではありました。特に大きかったのは、↓の発表を見て、PDS(Presentation Domain Seperation)の概念を獲得したことです。

speakerdeck.com

MVCとかMVPとかMVVMとか何が違うのか混乱していたところに、「まずはPresentationとDomainを分離するのが一番大事で、Presentationの中身をどう分けるかは、View-ControllerでもView-PresenterでもView-ViewModelでも、プラットフォームごとの特性に合わせて好きにしたらよい」という指針を与えられて、頭の中がだいぶ整理された覚えがあります。

2017年(30歳)

この年も新規サービスに携わることが多かったです。

  • GPSトラッキング
  • Kotlin + GeoJSON
  • React Native
  • React Native for Web
  • TypeScript

自社のAndroidアプリでGPSトラッキングを行い、田畑への入出場履歴を自動で生成し、労務管理に役立てるような機能を作っていました。デバッグのためにそこら中を歩き回ったのはいい思い出です。田畑のポリゴン情報と人間のポイント情報を比較して入出場を検出するために、各位置情報をGeoJSON表現に変換しつつ、Kotlin製の自作ライブラリでGeoJSONオブジェクト同士の位置関係を比較できるようにするようなことをやっていました。GISっぽーい。

また、少人数で複数プラットフォームに対応する案件が立て続けに来ていたので、片っ端からReact Nativeで薙ぎ倒していきました。ちょっと面白かったのは、プロトタイピング段階でAndroid/iOS/Webの3プラットフォーム向けに作ったとしても、運用を検討してみると、B2B分野では最終的に「Webだけあればよくね?」に収束することが多かったのでした。ちょっと写真を撮りたいくらいならブラウザで事足りますしね。

2018年(31歳)

この年はReact Native路線が強めでした。

  • React Native
  • Expo
  • React Native for Web
  • Create React App
  • TypeScript
  • Reactと相性の良さそうなアーキテクチャの研究
    • Layered Architecture
    • Atomic Design
  • SOLID原則

単純に2017年のプロジェクトが2018年も続いていた感じです。

だんだんと「実は無理にAndroid/iOSアプリを作らなくても、Webだけあればいい分野は結構ある」という認知が育ってきたのはこの年でした。React NativeでAndroid/iOSアプリも少しだけ作りましたが、最終的にはWebアプリばかり作っていたような気がします。

また、生のReact Nativeを使うのは割と疲れてきて、Expo経由しか勝たんな……みたいな顔をし始めたのもこの頃でした。技術書典4で作ったかんたん後払いアプリもExpo製です。

設計分野では、Atomic Designが流行っていた頃で、性懲りも無くカーゴカルトして爆死していました。React + Layered Architectureの実験をしていたのもこの頃ですね。

github.com

この頃には、Layered ArchitectureやClean Architectureを形だけ模倣しても実用的にはならないことは理解しており、Dependency Inversion Principle等の各種原則を場面に合わせて有効に組み合わせることができれば、教科書通りの形を守る必要はないことを実感し始めていました。

原則との付き合い方、みたいなのも意識するようになってきていたように思います。DRY原則なんかは一見扱いづらいのですが、何でもかんでも共通化すると「似てるけどちょっと違うユースケース」が入ってきたときに死ぬことがわかっていましたし、YAGNIも既に確定している将来の課題に対して無策でいることへの免罪符には使えません。SOLIDの各原則は知った時期も影響しているかもしれませんが、濫用しづらくて扱いやすいなあ、という印象がありました。

2019年(32歳)

この頃はもうほぼフロントエンド屋さんです。

  • Create React App
  • Babel
  • webpack
  • GraphQL
  • WebDriverIO
  • Appium

本業でもモバイルWebのサービスを作っていましたし、技術書典Webのサイト構築を担当し始めたのもこの頃です。

Reactと相性の良い設計については、Apollo Clientのおかげで少し進展がありました。上層のコンポーネントと通信を直接繋げてしまうのが良さそうなことがわかってきました。Layered Architectureのように通信の詳細を隠蔽するのではなく、Fragment Colocationによって、コンポーネントひとつひとつのためにFragment Colocationによって専用のデータ型を用意するのです。GraphQLの特性として、Infrastructure層相当の責務の一部(複数リソースの取りまとめ)をAPIサーバーに移管できる特性があるのですが、これのおかげで、階層をグッと減らしても実用上の問題がほとんど起こらなくなったのです。Clean Architectureの呪縛から解き放たれ、守破離が成ったときでした。

会社でモバイルアプリのE2Eテストの機運が高まっていたので、Appiumにも少しだけ手を出していました。Cordova製のアプリもあるので、WebDriverIOを経由してWebViewの操作をする方法の研究をしてたりもしました。

2020年(33歳)

COVID-19が来て、リモートワーク中心になった年です。

  • Wear OS
  • Create React App
  • Babel
  • webpack
  • GraphQL

フロントエンドな関心は続投しつつ、お仕事でWear OSアプリを作る機会があったので、あれこれキャッチアップしていました。

2021年(34歳)

10年ぶりの転職です。スキルセットがガラッと変わりました。

  • Next.js(Pages Router)
  • Ruby on Rails

まさかの完全未経験のフレームワーク×2の環境に放り込まれました。事業とチームだけ見て、使用テクノロジは全く見ないで入社したからね!仕方ないね!

一応前職でもAPIサーバーがRailsだったので、読むだけなら読めたのですが、自分で操作してみると全然感覚が違いました。ActiveAndroidの出来がそんなによくなかったのもあって、ActiveRecordインスパイア系ライブラリには忌避感があったのですが、本家本元を触ってみると、かなり使用感が良くて、驚きました。規模が大きくなってくると難しさが出てくるのは承知していますが、0→1フェーズなら現代でもRailsは良い選択肢のひとつなのだろうなと感じています。

2022年(35歳)

昨年です。ここまで来れば記憶も新しいかと思いきや、意外と何も思い出せません。

  • XState
  • Remix

仕事で診断アプリのようなものを作っていたときに、XStateによるステートマシン定義を試したりしていました。なかなかよかったので、CodeZineさんで持っている連載の中で取り上げたこともありました。

codezine.jp

また、筆者の中でエポックメイキングだったのがRemixでした。あの悪名高いReact Routerのチームが作っているということで、最大限の警戒をしながらキャッチアップしたのですが、思いのほか良いものでした。React Routerを拡張する形で、高度に通信とルーティングが統合された環境は快適でしたし、Web標準に則ることをベストプラクティスにすることで教育コストの効率を上げる方針にも好感が持てました。ブラウザ側で非同期通信をする機会がほとんどなくなったことで、脳にかかる負荷が格段に減ったのは、本当に素晴らしいことです。

2023年(36歳)

というわけで、今年です。また卯年になりましたが、24歳のときとは違ってゆるゆるとやっています。

  • Remix
  • Next.js(App Router)
  • Terraform

App RouterはRemixにインスパイアされて生まれたもの(要出典)なので、好ましい点が多いです。非同期通信は減る方向の時代なんだなーという気持ちが高まって、↓のような記事も出しました。

zenn.dev

あとは、社内で「自分のチームのことは自分でやる」という機運が高まってきたのもあって、重い腰を上げてTerraformを使ったGCPの構成にもチャレンジしています。Memorystore for RedisをCloud Runに繋ぎ込んだり頑張ってるんじゃよ。

まとめ

サクッと書けるとか言ったの誰だよ!!!!!(2回目)

後半は疲れてきて明らかに解像度が下がってた気がするので、そのうち元気な時に何か追記するかもしれませんが、ひとまず今はこれが精一杯!

うーん、なんかこういろんなことをやってきたんだなあという感じですね。小並感です。

最近EMになったので、技術の比重がやや下がってくるような気もするし、そうでもないような気もする。これからの5年間もいろんなことをやっていきたいなあ。

それでは!

トキブルワリーはいいぞ

Beer Advent Calendar 2023 - Adventarの3日目です。今回はトキブルワリーさんについて紹介します。

トキブルワリー

トキブルワリーは佐渡ヶ島のマイクロブルワリーです。

t0ki.beer

元フラー社CTOの藤原さん(@wutali)がやっており、新潟でソフトウェアエンジニアをやっている筆者としては、かなり身近に感じられるブルワリーです。

名前が独特

ソフトウェアエンジニアが作っているビールということで、名前も独特です。

今年のゴールデンウィークに、新潟明訓高校*1の隣にある亀田公園で行われていたバルイベントで飲んだのは、「BOOT」という名前でした。

BOOT v2.0-b.YQH-1320

t0ki.beer

また、11月には新潟駅南口近くのアマリロさんで、「SSL」というビールを飲む機会もありました。

SSL v1.0

t0ki.beer

暗号化されていない爽やかなお味でした。

どうやらP2B Hausさんで色々と飲める機会もあったようです。

ソフトウェアエンジニアなら、思わずクスリとしてしまうような名前のビールばかりです。

もちろん味も試行錯誤が繰り返されていて、美味しいものばかりですよ!

見かけた際はぜひ飲んでみてください。

*1:ドカベンのあそこです

3分投資診断の思い出

モニクルAdvent Calendar 2023の2日目です。昨日はCTOのがぶちゃんによる「エンジニア10人を超えて複数チームになった開発組織でCTOとして最近やっていること」でした。

gabu.hatenablog.com

2日目の今日は、筆者(@Nkzn)が入社直後に開発に携わった「3分投資診断」というサービスの思い出話をします。

3分投資診断とは

3分投資診断は、モニクルグループのワンマイルパートナーズが運営している、はたらく世代のお金の診断・相談サービス「マネイロ」が提供するサービスのひとつ*1です。

moneiro.jp

年齢や年収、現在の資産形成の概要、老後の過ごし方などを入力していくと、老後までにあとどのくらい資産形成が必要で、そのためにはどういった施策が有効そうなのかを、ざっくり診断してくれます。

3分投資診断の診断結果の例

思ったより反響があった

オウンドメディアのモニクルプラスでも話したことがあったのですが、思った以上の反響がありました。

plus.monicle.co.jp

実は、筆者は計算エンジンの部分を2021年の秋ごろに実装し終えたあたりで開発から離脱しており、その後にこだわりのUI開発戦記があった時期については別のプロジェクトをやっていました。運用周りも当時のグロース関連のチームに任せてしまったので、あまり数字を追いかけることもしていませんでした。

そんな筆者が驚くことになるのは、ちょうど一年前、昨年の12月に上記のインタビューを受けたときです。創業者の泉田さんから「3分投資診断すげーことになってるよ!めっちゃ使われてる!」と教えてもらって、そんなことになってんの!?と驚いた記憶があります。

診断結果を受けてもっと詳しい対策を知りたくなったお客さんが、診断後にマネイロの相談サービスを申し込んでくれるケースも診断数に応じて増えているらしく、マネイロの2022年の成長を強力に後押ししたとのことでした。

筆者からすると、入社から半年も経たないうちに作っていたものということもあり、がむしゃらに取り組んだいくつかの施策のうちのひとつ、くらいの感覚でした。入社から1年半経った頃に、1年越しに大ヒットを知らされて、やってきたことは無駄じゃなかったんだなあ、としみじみしたものでした。

ドメインエキスパートとの共同開発で気をつけたこと

あまり表舞台で開発の話をしたことがなかったので、少しだけ開発の思い出話もしようと思います。

基本的には役員の皆さんがドメインエキスパートとして仕様をまとめてくれていました。大量のスプレッドシートに根拠資料や計算式が並んでいるイメージです。

筆者は計算エンジンの作成担当だったので、簡単なUIだけを用意して、基本的には数字のインプットとアウトプットが正しそうかどうかをドメインエキスパートと擦り合わせていく作業を行っていました。

ここで特に意識したのが「正しさの確認しやすさ」です。プログラマーではないドメインエキスパートから「○○の項目のアウトプットが怪しい気がするんだけど、動作確認してる時はどんな数字が出てた?」と聞かれたときに、ソースコードを見せながら議論するわけにもいきません*2。次善策として、できるだけテストコードの処理結果で各種の途中計算の結果が見えるようにしてみました。例えば、年金の算出のために必要な「厚生年金対象勤務期間」や「標準報酬月額」の算出の自動テストでは、次のような実行結果が表示されます。

PASS  hoge/services/index.test.ts
  「厚生年金対象勤務期間」の算出
    ✓ 退職年齢65歳、勤務開始年齢24歳、未加入期間5年の場合、厚生年金対象勤務期間は432ヶ月である (1 ms)
    ✓ 退職年齢75歳、勤務開始年齢23歳、未加入期間10年の場合、厚生年金対象勤務期間は504ヶ月である
  「標準報酬月額」の算出(令和3年3月データによる検証)
    ✓ 年収が0万円のとき、標準報酬月額は88000円である
    ✓ 年収が468万円のとき、標準報酬月額は380000円である
    ✓ 年収が720万円のとき、標準報酬月額は590000円である
    ✓ 年収が1000万円のとき、標準報酬月額は650000円である
    ✓ 標準報酬月額表を検索できる(表はテストデータで代用) (2 ms)

これなら、ドメインエキスパートに見せたり、検算してもらったりするのも、ある程度は容易です。最終的に数百件のテストケースを作成しましたが、ほぼすべてのテストケースをこのノリで作り、順次ドメインエキスパートに確認してもらいながら開発を進めていきました。

こういったテストの作成においては、JUnitで学んできた*3Parameterized Testの考え方が役立ちました。今回はテスティングフレームワークとしてJestを採用していましたが、 test.each() を用いると、次のように簡単にParameterized Testが書けるので、重宝しています。

describe("「標準報酬月額」の算出(令和3年3月データによる検証)", () => {
  test.each([
    [0, 88_000],
    [468, 380_000],
    [720, 590_000],
    [1000, 650_000],
  ])(
    "年収が%i万円のとき、標準報酬月額は%i円である",
    (yearlyIncome, standardMonthlySalary) => {
      const actual = calcStandardMonthlySalaryYen(yearlyIncome)
      expect(actual).toBe(standardMonthlySalary)
    }
  )
  test("標準報酬月額表を検索できる(表はテストデータで代用)", () => { ... })
})

「読みやすいテストケース」というのは、かなり認知負荷を下げるのがわかったので、無理に慣れない英語でテストケースの名前を書いて、書いた人も読んだ人もパッと意味がわからないものになるくらいなら、躊躇わずに日本語で書いていくのがよいと思います。

宣伝:マネイロの広告を探せ!

12月1日から、東京メトロにマネイロの広告を掲出しています。

答えはマネイロの3分投資診断で!(ワンマイルパートナーズUさん撮影)

新潟からフルリモートで働いている筆者はなかなか見る機会がないので、もし見つけた人は #マネイロ のハッシュタグと共に @Nkzn まで「見つけたよ!」のリプをいただけると、めちゃくちゃ喜びます。

中旬には筆者もモニクルグループの全社納会へ参加するために東京へ行く予定なので、そのときに探してみようと思っています。

明日は新潟メンバー仲間の@circled9です。よろしく!

*1:他にも、オンラインセミナーや相談サービスなどもあります

*2:ドメイン駆動設計の本来の精神に則るならば、ドメインエキスパートが読めるようなプロダクトコードを書くべきではありますが、あれは英語が母語な人たちだからこそ成り立ってる部分もあると思うので、今回は勘弁してください。日本語でコードを書けばたぶんできるんだけど、そこまではやってられない。

*3:そろそろ自分でも忘れかけていますが、Android Java出身エンジニアなんですよ僕

至高を越えたボロネーゼは自分へのご褒美として作る最高のご馳走

12月といえばアドベントカレンダーの季節! そして、昨年に引き続き、やります! バズレシピアドベントカレンダー!

adventar.org

言い出しっぺということで、1日目をやらせていただきます。

今年も色々と作ってきて、子供ウケが良かったレシピも時短に効いたレシピも色々とあったのですが、今回は「筆者個人が自分で食ってて一番美味かったやつ」というシンプルかつ最も重要なところを紹介します。

至高を越えたボロネーゼ

筆者の中で、バズレシピオブザイヤー2023はこいつでした。 「至高を越えたボロネーゼ」 です。

www.youtube.com

今年のパスタレシピは、冷製パスタ焼きスパゲティのような例外を除いて、ほぼ全レシピがワンパンパスタだったと思います。昔のパスタレシピをリゾッタータ(ソースでパスタを茹でて煮詰める手法)で再構築しつつ進化させることでネタ切れを防いでいた側面があったような気もします*1

そんな中で、筆者が今年本当に食べていて幸せだったのが、この至高を越えたボロネーゼです。

至高を越えたボロネーゼ

2020年に出ていた至高のボロネーゼのワンパンバージョンとなります。材料としてもそんなに変わらないはずなのですが、至高の〜よりも圧倒的に好みです。別茹でせずに煮詰めて作っているからか、ソースが麺にめちゃくちゃ絡むんですよねえ。動画ではコラボ相手として使っていた赤ワイン「ジェイコブズ・クリーク」は近所に売っていないので、適当な赤ワインを買ってきて作っていますが、全然美味しいです。一緒に飲むとマリアーーーーージュ🍷になります。

動画の出始めのときには週3で食べてましたが、今は「ここぞというときの自分へのご褒美」として作るようになりました。ちなみに↑の写真は、11/12の技術書典15オフラインイベントと、11月16日の4年半ぶりの新刊脱稿を乗り越えた自分へのご褒美として作ったやつでした。

デメリットはパスタとして食うしかないこと

このレシピは、たぶん来年以降もプチハレの日のレシピとして鬼リピすることになるのですが、一点、ただ一点だけ、旧作である「至高のボロネーゼ」のほうが優れていると筆者が思っている点があります。

至高のボロネーゼは、ソースだけを別の料理に転用可能なのです。白米に乗せて、ボロネーゼ丼を作ってみてください。旨すぎてトビますよ。

至高を越えたボロネーゼは、良くも悪くも煮詰めることでパスタとソースが一体化し、ソースだけの状態が存在しないレシピです。そのため、ボロネーゼ丼を作る余地がほとんどありません。ごく稀に、食べるのが下手くそすぎて麺に具を絡めきれずに、食べ終わった皿にソースがそこそこ残っているという事態はありますが、これは直後にシメとしてボロネーゼ丼を食べるようなことはできても、冷蔵庫に保存しておいて後日リメイクしましょう、という話にはならないですよね。

というわけで、パスタ以外にもボロネーゼの楽しみ方を模索したい場合は、至高を越えたボロネーゼは向いていません。至高のボロネーゼや、シン・ボロネーゼのほうが向いています。

ワンパンパスタ最高!

ワンパンパスタシリーズは、やっぱり洗い物が少ないという最高の利点があるんですよね。まな板と包丁とフライパン(+α)あたりがあれば大体作れてしまうので、時間があまりない昼食にも重宝しました。

リュウジさんがいつまでワンパンパスタを擦り続けるつもりなのかは分かりませんが、2024年も楽しみですね!

2日目を書いてくれる人を募集中です

ところで、このアドベントカレンダー、2日目に誰が書くのか決まってないんだけど、どうしようかなあ。誰も書かなかったら僕が最高傑作カルボナーラの話をしますが、欲を言えば誰か書いて欲しいなあ。12/2は会社のアドベントカレンダーの担当なので、他に書きたくないんじゃよ。誰か頼む……

*1:これの別茹で版を作ったことある気がする、みたいなレシピが多かった

書評:これからはじめるReact実践入門

明日、2023/9/28に発売する「これからはじめるReact実践入門」を献本いただきましたので、簡単に目を通した感想を書こうと思います。

これからはじめるReact実践入門

目次

かなり網羅性が高い

パラパラと読んでみて感じたのは、かなり手広く、それでいて一定の深みもある本だということです。出版社のサイトにある目次を見てみましょう。

Chapter 1 イントロダクション
1-1 ReactとJavaScript
1-2 Reactアプリを開発/実行するための基本環境
1-3 モダンJavaScriptの基本

Chapter 2 Reactの基本
2-1 はじめてのReact
2-2 サンプルアプリの内容を確認する
2-3 JSXの基本

Chapter 3 コンポーネント開発(基本)
3-1 コンポーネントを支える基本概念 – PropsとState
3-2 条件分岐と繰り返し処理
3-3 Props/Stateの理解を深める
3-4 より高度なイベント処理

Chapter 4 コンポーネント開発(フォーム)
4-1 フォーム操作の基本
4-2 Stateにおける構造化データの更新
4-3 検証機能の実装 – React Hook Form

Chapter 5 コンポーネント開発(応用)
5-1 組み込みコンポーネント
5-2 コンポーネント開発でのスタイル定義
5-3 コンポーネントのその他の話題

Chapter 6 Reactライブラリの活用
6-1 典型的なUIを実装する – MUI
6-2 コンポーネントの見た目/動作をカタログ表示する – Storybook
6-3 外部サービスからデータを取得する – React Query

Chapter 7 フックの活用
7-1 コンポーネント描画/破棄時に処理を実行する – 副作用フック
7-2 さまざまな値への参照を準備する – useRef関数
7-3 状態と処理とをまとめて管理する – useReducer関数
7-4 コンポーネントの複数階層で値を受け渡しする – useContext関数
7-5 ステート管理ライブラリ「Recoil」
7-6 関数、またはその結果をメモ化する – memo/useMemo/useCallback関数
7-7 優先順位の低いState更新を区別する – useTransition関数
7-8 フックの自作

Chapter 8 ルーティング
8-1 React Routerの基本
8-2 ルーター対応リンクの設置
8-3 ルーター経由で情報を受け渡しする手法
8-4 Routeコンポーネントの属性
8-5 ルーティングに関わるその他のテクニック

Chapter 9 テスト
9-1 単体テスト
9-2 E2Eテスト

Chapter 10 TypeScriptの活用
10-1 TypeScriptの基本
10-2 ReactアプリへのTypeScriptの導入

Chapter 11 Next.jsの活用
11-1 Next.jsの基本
11-2 App Routerの基本を理解する
11-3 応用アプリ「Reading Recorder」を作成する
11-4 アプリの実装を読み解く
11-5 Vercelへのデプロイ

668ページの本なので、そこそこ長いです。

全体の構成としては、次のようにまとめられるでしょうか。

  • Chap 1〜3:基本理念の解説や、言語の文法やReactの基礎文法について解説
  • Chap 4〜5:React単独でできること
  • Chap 6:ライブラリを組み合わせると、更にできることが広がる
  • Chap 7:組み込みフックの解説と、フックを活用したライブラリの紹介、そして自作によって、関数コンポーネントをより柔軟にシンプルに扱う
  • Chap 8:シングルページアプリケーションを成立させるための画面遷移
  • Chap 9:品質保証
  • Chap 10:Reactで一通り何ができるのかわかったところで、型の支援を受けて実用レベルの使い方を知る
  • Chap 11:ここまで読めば、ある程度大きい概念も理解できるようになってきているはずなので、デファクトスタンダードなフレームワークであるNext.jsを学ぶ

私もReactの学習については頭を悩ませたことがあるのですが、大筋としては良い流れで書いてあると思います。TypeScriptは現代の開発では事実上必須ではありますが、慣れていないうちにReactやReact関連ライブラリの解説をTypeScriptで行なってしまうと、今学んでいるものがReactなのかTypeScriptなのか、読者は混乱してしまうでしょう。思い切ってTypeScriptの解説を終盤の応用編として収録したのは、英断だったと思います。著者の山田さんと私は編集者と著者という関係で記事を一緒に作ることが多いのですが、やはりTypeScriptの登場タイミングの匙加減について話し合うと、お互いに「悩ましいけど、本気でライブラリの解説にフォーカスしたいなら、最後にちらっと解説するか、いっそTypeScriptに触れないか、ですよねえ」という結論になりがちなので、「最後にちらっと解説」の一例として、納得感のある構成になっていると思います。

また、膨大なページ数を使っているだけあって、一つ一つの項目がかなり丁寧です。よそのプログラミング入門書には、初心者向けだからと詳細な説明を省いている残念な本も多いのですが、この本では細かい点まで親切に解説されています。おそらく、React歴3年目くらいまでの人が読んでも、初めて見る基礎的な知識が多く記載されていることでしょう。

多くのページが実際に手を動かして、手元で動作を確認しながら読み進められるものになっています。そして、そのとき何が起きているのか、どんな仕組みで動いているのか、といった背景にも存分に触れているので、楽しみながら読み進められると思います。

足りない情報があったら

この本は「広く・やや深く」という感じで進行していくので、物足りなさを感じる場面というのは少ないのですが、もっと深く知りたいな、と思った場合には、専門の書籍をあたると良いと思います。

P264のコラムでは参考書籍が紹介されていますが、直接的な深掘りができるタイプの本が紹介されていないのが気がかりなので、この場を借りて、少し紹介しておきます。

プロを目指す人のためのTypeScript入門

まずは、相対的にちょっと浅めになっている、TypeScriptを深掘りしたい場合の本ですが、これは@uhyoさんのブルーベリー本で良いでしょう。

gihyo.jp

Next.jsについて、次に読む本はありますか?

ぶっちゃけこれはかなり難しいです。現行のNext.jsの本は、大半がPages Routerを前提にしており、App Routerの使い方を書籍として取り上げた本がまだほとんどないはずです。商業出版の紙の本としては、本書が日本最速では……?くらいのレベルです。

とはいえ、本書に記載されたNext.js(のApp Router)の使い方は、「よくできたチュートリアル」くらいのものなので、もっと深い情報も欲しいですよね。

2023年9月現在では、「公式ドキュメントを読んでくれ……!」が一番誠実な回答かなという感じはしています。

nextjs.org

一応、私も↓でApp Routerの連載を行っていますが、少しずつしか進んでいないので、たまに読んでいただければ、くらいのものです。

codezine.jp

App Router前提で、広く深くNext.jsについて扱った書籍が今後出てくることを期待したいですね〜。

補足したいところ

全体的にはよくできているのですが、細かいところで気になったところがあるので、補足情報を書いておきます。嘘が書いてあるわけではないので、本書の内容そのままに読み進めていただいても問題ありませんが、2周目を読み始めたあたりで気にしてみると面白いかもしれません。

Create React Appを使わない選択肢もある

本書の中で、Next.jsの話題が登場するまで、一貫してReact製アプリケーションの環境構築&ビルドツールとして解説されているCreate React Appですが、現代では役割を終えたものとして、開発がほぼストップしました。最新のReact公式ドキュメントでも、プロジェクトのセットアップに使うツールにCreate React Appは登場しません。

react.dev

業務レベルのプロジェクトを作成するのであれば、Next.jsやRemixといったフレームワークを利用したほうが、より高度に通信と画面遷移が統合された、快適な開発体験を得ることができます。ただし、Create React Appと比べると、プロジェクトの最低限のファイル数は多くなりますし、一定の複雑さがあることは否めません。

入門書での取り回しがいいのは、確実にCreate React Appなので、本書の選択は正解だと思います。ただ、本当に業務で実践できる内容に持っていこうと思った場合は、やはり本書の最後の章で解説されているNext.jsを導入したほうがよいでしょう。

ちなみに、公式ドキュメントではほんの微かな言及しかありませんが、Create React Appと近い規模感&使用感でプロジェクトを扱えるツールとして、Vite(ヴィート)があります。

ja.vitejs.dev

ほんの少しクセの強さはあるものの、こちらは活発に開発が続いていますし、一定の人気もありますので、場合によっては本書のサンプルをViteで作成・動作させてみても面白いかもしれません。

Recoilさんは開発状況がちょっと心配

Recoilは人気はあったものの、リポジトリ名がfacebookexperimental/Recoilだったことからも分かるとおり、Meta社内でも実験的なプロジェクトでした。社内ライブラリをちらっとカンファレンスで発表してみたら、思ったよりも反響があって、みんなが使い始めてしまった、くらいの流れだったと思います。

さて、そんなRecoilですが、残念な話がありました。

残念ながら、2022年10月にRecoilの主要メンテナの@drarmstr氏がMeta社の一斉レイオフで解雇された

Jotaiで快適フロントエンド開発 | 株式会社ヌーラボ(Nulab inc.)

主要メンテナの解雇というのは、まあまあの事故ですよね……

移行先のライブラリとして考えられるのは、上記の記事でも紹介されている「Jotai」です。

jotai.org

元々Recoilにインスパイアされて生まれたライブラリとのことなので、Recoilのいいところはある程度受け継いでいます。本書のサンプルとしては、まずRecoilを使ってみるのがいいと思いますが、少し慣れてきたら、Jotaiで書き換えてみるのも、いいエクササイズになるかもしれません。

React Routerの知識が活きるアプリケーションフレームワークもある

本書では、シングルページアプリケーション(ブラウザ上だけで動くアプリケーション)の中で画面遷移を行うために、React Routerの利用方法が70ページに渡る大ボリュームで解説されています。

しかし、残念なことに、その3つ後ろの章で解説されるアプリケーションフレームワークはNext.jsであり、React Routerで学んだ知識の大半はそのまま使うことができず、Next.jsのルーティングの癖を改めて学ぶことになります。

Next.jsは世界で最も使われているReact向けのアプリケーションフレームワークですので、本書の選択は間違っていません。間違ってはいないのですが、もし幻のChap 12があったとしたら、ぜひ解説してほしかったアプリケーションフレームワークがあります。

それはRemix(リミックス)です。

remix.run

Remixは、React Routerの開発チームが作った、ルーティングと通信をより快適に統合させながらブラウザとサーバーの通信をスッキリさせるためのフレームワークです。現在は開発チームが丸ごとShopifyに買収され、RemixはShopifyの公式フレームワークHydrogen v2のベースとなりました。

shopify.dev

Remixをおすすめしたいのは、なにも開発チームが同じだから、という理由ではありません。Remixのルーティングは、React Routerによって実現されているので、Remixの画面遷移にはReact Routerの知識がとても役に立つのです。

URLのパスを決定する方式だけはNext.jsとそっくりな、ファイルとフォルダによる仕組みを使っていますが、それ以外の部分はかなりReact Routerらしい機能が露出しており、React Routerを学んだ人には親しみ深く感じられることでしょう。 useHistory()useParams() といったフックを利用する際には react-router-dom からインポートしますし、階層構造になっているルート*1では <Outlet /> をプレースホルダーとして配置します。

一通り本書の内容を実践した上で「React Routerの空気感もいいなあ」と思われた方がいらっしゃいましたら、Remixのチュートリアル(英語)にチャレンジしてみていただけると、Remix推しとしてはちょっと嬉しいです。

remix.run

remix.run

これは宣伝ですが、本書著者の山田さんに編集してもらいながら、CodeZineにRemixの記事を連載しているので、興味があればこちらもお読みください……!!!

codezine.jp

まとめ

本書の内容は実際よくできており、Reactの初学者だけではなく、React 3年生くらいのジュニアエンジニアであっても多くのことを学べる良書に仕上がっていると思います。ちょっと分厚くてお高いですが、それを補って余りある基礎知識を得られますので、ぜひ読んでみてください。

おまけ

実は、なんで献本をもらえたのか全くわかっていませんw

普段、著者の山田さんが主宰しているWINGSプロジェクトでReact関連の記事を書かせてもらっていて、山田さんには編集者として忌憚のないご意見をいただいているので、その辺の経験がこの本に活きたりしたのかなあ、そうだといいなあ。

2023.9.28 10:36追記

P264の参考書籍のコラムに、僕のRemix連載を載せてくださっていました!ちゃんと僕とご縁のある本だった!ありがたい!

codezine.jp

参考書籍にRemix連載を記載していただきました!

*1:RemixではNested Routesと呼びます

JavaScriptとDIについての雑文

JavaScriptでDIコンテナってどうなの?という話題について雑に書きます。↓の話題について意見をくれと某所で言われたのでざっくり意見を書きます。

mond.how

DIコンテナ(≒依存性注入自動化フレームワーク)の発祥の地といってよさそうなJavaでは、DIコンテナでも使わないと依存性注入がやりづらいという言語上の制約があったために、DIを実現するためにはDIコンテナが事実上必須だった、みたいな雑な認識をしています。

しかし、JavaScriptのように関数が第一級市民として扱われる(関数を値として引数に渡せる)言語では、依存性の注入や差し替えが概ね容易であることが多い(DIコンテナがなくてもDIを実現しやすい)ため、DIコンテナ的なフレームワークを導入する旨みはJavaと比べると薄めなのかなと思います(ふわっとした発言)。実際、DIコンテナを内蔵しているNestJSを使ってみると、規模次第では便利っぽいけど、規模次第では煩雑さが目立つ(exportsやprovidersを登録するのめんどい)なあという印象です。

素朴なDIについて想いを馳せる

僕がDIでやりたかったこと(だと自分では思っている)を素朴に思い出してみます。

例として、次の fnA()fnB() への依存性を持っており、モックが原則不可能です*1

/* 依存性がある関数A */
import fnB from './b.ts';

export function fnA(a: number) {
  const b: Date = fnB(a);
  b.setDate(1);
  return b;
}

/* 使い方 */
const dateA: Date = fnA(1); // fnBの挙動をモックできない

一方、次の fnC() は↑と同じ処理を表していますが、 fnB() への依存性を持っていません。

/* 依存性を注入している関数C */
export function fnC(a: number, fnX: (a: number) => Date) {
  const b: Date = fnX(a);
  b.setDate(1);
  return b;
}

/* 使い方 */
import fnB from "./b.ts";

const dateC: Date = fnC(1, (a) => fnB(a)); // 第二引数を差し替えることでfnBをモック可能

fnC では、第二引数で fnB() 相当の関数 fnX() を外から注入しています。これも依存性の注入=DIと呼んで差し支えないでしょう。上記の例では fnB() がそのまま実行されるだけですが、テストコード等では次のような書き方もできます。

const actual: Date = fnC(1, (a) => new Date('2023-01-15')); // fnXの挙動を固定する

expect(actual).toBe(new Date('2023-01-01'));

fnX() が内部的に fnB() を利用しない形に差し替え、常に固定の結果を返すようにしました。これで fnB() の実装を気にせず、 fnC() 固有の挙動のテストに集中することができます。

これは素朴な例です。もっとDIコンテナが欲しくなるような複雑なケースもあるかとは思いますが、少なくとも僕は欲しいDIはこの素朴な例を少し複雑にした程度に収まることが多めです。

まとめ

DIという概念で僕が最低限やりたいことは、前述のように素朴なものです。もっと複雑なケースではDIコンテナが必要になるケースもあるかもしれませんが、素朴なケースでDIコンテナを持ち出すのは嫌だなあと思います。

用法容量を守って、必要なDIを必要な分だけやっていきましょう。

*1:webpack等でimport元を差し替えてテスト用モジュールに差し替えるようなハックはできますが、テスト用途で気軽に使うには実装コストが見合わないように思います

ビアリー IPA STYLEを一番のヤツで作った至高のビール煮で飲む

Beer Advent Calendar 2022 - Adventarの19日目とバズレシピ Advent Calendar 2022 - Adventarの20日目を一緒にやっちゃいます。

バズレシピ19日目を読んで、僕もそろそろリュウジが使ってるおろし金を買おうかなあという気持ちになりました。

さて今回は、バズレシピのビール煮(ちゃんとビールで作ったやつ)を食べながらビールテイスト飲料を楽しむという倒錯的な食事を楽しみました。

ビール煮でビアリーIPAを飲む

ビアリーIPA STYLE

ビアリー IPA STYLEは、ビールテイスト飲料ビアリーの10月に発売された新味です。

www.asahibeer.co.jp

たまたまスーパーで見かけたので飲んでみたのですが、これがまたびっくりする旨さでした。

しっかりした苦味があって、ビールテイスト飲料とは信じられないくらいです。ビアリーは普通にビールを作った後でアルコールを抜く製法なので、ほぼビールな味が出しやすいのかもしれませんね。

ビアリー IPA STYLE

原材料を見ると、酒類ではないのをいいことに(?)麦芽がモリモリと使われている様子が窺えます。もしかしてホップもまあまあ入っているのでは……?

麦芽とホップがモリモリ

そして重要なのは、ゼロカロリーは目指していないので、それなりにカロリーや糖質が入っているということです。やっぱり旨みは脂肪と糖から生まれるので、これは仕方ないですね(遠い目)。

至高のビール煮

めちゃくちゃ旨いビアリー IPA STYLEをより美味しく飲むためにはどうしたらいいのか、私は考えました。

ビール(テイスト飲料)に合うのはやはりビール! ということで、ビールで作る最高の料理を作ることにしました。

www.youtube.com

材料は次の写真の通りです。近所のスーパーで豚肩ロースブロックが安く売っていて助かりました。

至高のビール煮の材料

飲むのはビールテイスト飲料ですが、料理の材料には妥協しません。一番のヤツ!(C.V.大蛇丸)です。

肉に焼き色をつけて〜

焼き色をつける

飴色玉ねぎとコンソメとビールを入れて煮込んだら〜

煮込む

あらヤダ美味しそうヤダー

小一時間煮込んだやつ

実食

というわけで冒頭の写真になったのでした。

マリアージュ!

ビールの旨みが染み込んだ肉を、ビールの旨みを忠実に残したビールテイスト飲料で流し込む! 美味しくないわけがないでしょう!

ちなみに僕は夕食の後にも仕事をすることが多いのですが、ビアリーなら飲んだ後でも仕事に支障がなくていいですね。晩酌要員として優秀です。

まとめ

というわけでバズレシピとビールという二つのアドベントカレンダーを繋いだテーマでやってみました。

ビール好きのみんな!飲みたい気持ちはわかるけど、ビール煮も旨いから作ってみてくれよな!