家族や友人と写真のコンテストを開催できるアプリ「PixPick」をリリースしました!

はじめに
家族や友人と写真のコンテストを開催できるアプリ「PixPick」をリリースしました!
本記事では「PixPick」の使い方や開発の振り返りなどを書いています。
サービスURL pixpick.jp
自己紹介
うにお(@unikounio512)と申します。
4歳の息子と5歳の飼い猫が大好きです。
前職では地方公務員として防災や都市計画に携わっていました。
現在は会計系書籍の校正に携わりつつ、Webエンジニアを目指して、2023年2月末からフィヨルドブートキャンプ(以下「FBC」)でプログラミングを学習しています。
アプリの概要
家族や友人と一緒に、みんなが一番良いと思った写真を簡単に選び出せるアプリです。
特徴
簡単に写真を共有できる
PixPickでは、「コンテスト」という単位で、参加者間に写真を共有します。
このコンテストは、招待用リンクを共有するだけで他のユーザーを簡単に招待できます。
写真を登録したコンテストを家族や友人に共有しましょう。自分のペースで評価できる
コンテスト参加者が各自で写真に点数をつけることで、みんなの意見を反映します。
自分のペースで写真を評価しましょう。評価した写真をランキング形式で表示
投票期間内におけるみんなの評価を集計して、ランキング形式で表示します。
写真ごとにどの程度の支持を得ているのかがいつでも簡単に確認できます。
開発のきっかけ
我が家には4歳の息子と猫がいて、毎日たくさんの写真を撮っています。
これらの写真を現像してアルバムを作ったり、写真コンテストに応募する際には、使用する写真を選び出す必要があります。
しかし、この選定作業では、夫婦間の意見のすり合わせに毎回多くの時間を要していました。
この問題を解決して、写真を用いた活動をもっと楽しくするために、「PixPick」を作りました。
使い方
PixPickの始め方は「コンテストの主催者になる場合」と「招待されたコンテストに参加する場合」の2種類があります。
コンテストの主催者になる場合
コンテストを作成する
トップページからGoogleアカウントでログイン後、まずは主催するコンテストを作成します。

写真をエントリーする
作成したコンテストに評価したい写真をエントリーします。

写真を評価する
サムネイルを選択して、エントリーした写真に点数をつけます。


コンテストに他のユーザーを招待する
コンテストに他のユーザーを招待することで、エントリーした写真を家族や友人と共有し、一緒に評価することができます。
コンテストに他のユーザーを招待するには、コンテスト編集画面を開いて「新しい参加者を招待する」ボタンを押します。

表示されたURLを家族や友人に共有することでコンテストに招待することができます。

ランキングを確認する
コンテスト参加者間の評価を集計し、ランキング形式で表示することができます。
みんなで選んだ写真を確認しましょう!

招待されたコンテストに参加する場合
招待されたコンテストに参加する場合は、家族や友人から共有された招待用URLからログインしてください。

ログイン後の操作はコンテストを主催する場合と同じです。
開発について
技術スタック
- バックエンド
- Ruby 3.4.1
- Ruby on Rails 7.2.2
- フロントエンド
- テスト
- データベース
- CI
- デプロイ
- ストレージ
こだわったこと
評価方法
サムネイルから点数がわかる
写真のサムネイルにも点数を表示するようにしました。
この機能のおかげで未評価の写真もすぐに把握することができます。
また、写真の評価を進めていくと、ある写真の点数が他の写真と比べたときに適当でないように見えることがあるので、このような場面での調整でも活躍する機能です。
写真をロード中でも点数をつけられる
写真の評価画面では、画像ファイルのロード中でも点数をつけられるようにしました。
これにより、通信速度が低い環境でも、快適に評価を進めることができるようになりました。
シンプルなデザイン
写真を評価する際、デザインが判断に影響を与えないよう配慮し、極力シンプルなデザインにしました。
装飾を控えめにし、写真そのものが主役として際立つよう、直感的でノイズの少ないデザインを心がけました。
レスポンシブ対応
写真を扱うサービスである以上、スマホ対応は必須だと考えていました。
一方で、私自身はPCを使って写真の整理を行うことが多いため、PCとスマートフォンの両方で快適に利用できるよう工夫しました。
特に、写真をエントリーする機能では、PCではドラッグアンドドロップで簡単に登録できるようにし、スマートフォンではボタンを押してファイルを選択する形式を採用しました。
これにより、どちらのデバイスからでもスムーズに写真が登録できるようになりました。
苦労したこと
使用予定だったAPIの仕様変更
Google Photos Library APIの仕様変更
当初はGoogle Photos Library APIを使用して、Googleフォトの共有アルバム機能を利用してコンテストを開催する予定でした。
しかし、開発を開始して間もなくAPIの仕様変更が発表されました。
仕様変更によるアプリの設計への影響は色々あったのですが、その中でも特に困った点はユーザー間での写真の共有に関する点でした。同APIを仕様変更後も使用する場合、コンテスト参加のたびに招待するユーザーをGoogleフォト側で共有アルバムに追加する必要があり、深刻なユーザビリティの低下を招く恐れがあると判断したため、写真の保存に関する設計を変更することにしました。
Google Photos Picker APIの検討
設計変更にあたり、まずはじめにGoogleから代替手段として提示されているGoogle Photos Picker APIでの実装を検討しました。
しかし、このAPIでは共有アルバムの操作方法が提供されていないため前述の問題を解決できません。
Google Drive APIの検討
次に検討したのが、利用するサービスをGoogleドライブに切り替え、Google Drive APIを用いて実装する方法です。
こちらは技術検証の結果、ユーザー間での写真の共有に関する課題も解決し、やりたいことが一通り実現できそうでした。
実際に開発を進めて、全ての機能を実装することもできました。そうして課題解決に対する安堵とともにリリース準備に入ったところで、大きな問題が浮かび上がりました。
PixPickの機能実現に必要なOAuth 2.0スコープを使用するためには審査が必要だったのですが、この審査内容について改めて調査したところ、審査通過に必要なコストが想定を遥かに上回っていたのです。
リリースを目前にして、またしても設計変更を余儀なくされました。
オブジェクトストレージの利用へ
度重なる設計変更により、ユーザーが外部サービスに自身のアカウントで保存したデータを共有する設計に限界を感じたため、オブジェクトストレージを利用することに決めました。
一連の設計変更については、実装を急ぐあまり調査が不十分だったことが、さらなる設計変更を招いた一因だったと思います。
今後設計変更を行う際には、一度実装の手を止めしっかりと地に足をつけて、サービスの必須要件に関する情報は徹底的に確認・整理した上で進めようと心に決めました。
HEIC形式への対応
画像ファイルの取り扱いは自分にとって難しいことだらけだったのですが、中でもHEIC形式への対応には苦慮しました。
HEIC形式はApple以外のブラウザではほぼ非対応なので、多くの場合より汎用的なJPG形式などに変換して使用します。
しかし、PixPickでは写真をエントリーする際のプレビュー処理をクライアントサイドで行っており、画像のフォーマットはサーバサイドで行っているため、上記の変換処理ができませんでした。
これに対応するため、HEIC形式だけはクライアントサイドでもJPG形式へ変換できる機能を追加しています。
この他にもフォーマットや圧縮など、HEIC形式には何度も悩まされましたが、諦めずにその都度調査・検証を重ねることでなんとか解決することができました。
新しい技術の習得
Hotwire、ActiveJob、RSpec、TailwindCSS、CI構築にアプリケーションのデプロイ、そして各APIの仕様の理解と操作方法の習得など、本アプリをつくるにあたって初めて触れる技術がたくさんありました。
これらの新しい技術の学習を通して、公式ドキュメントやソースコードなど、できるだけ一次に近い情報にあたることの大切さを改めて実感しました。
加えて、Hotwireは猫でもわかるHotwire入門 Turbo編、 RSpecはEveryday Rails - RSpecによるRailsテスト入門が理解の大きな助けになりました。
参考にさせていただいた資料は細かいところまで挙げていくと膨大な量になってしまうので割愛させていただきますが、いずれも資料としてまとめてくださった先人がいらっしゃり、そうした方々のおかげでリリースまでたどり着くことができました。資料を作成された皆様には感謝が尽きません🙏
今後取り組みたいこと
エントリー機能の非同期化
現状では写真を選択してエントリーボタンを押してからコンテスト画面へ遷移するまでの間に、画像のアップロード処理等のため、エントリー枚数に応じた待機時間があります。
これらの処理をバックグラウンドで行う機能を追加して、待機時間をなくしたいです。
この機能は実は一度Active Jobを用いて実装しているのですが、現在の自分の技術力では不安定な機能になってしまったため、削除しました。
技術力を磨いてリベンジしたいです。
ランキング画面の写真を選択した際に拡大画像を表示する
ランキング画面では順位に対応する写真のサムネイルを表示しているのですが、このサムネイルを選択した際にモーダルを開いて拡大画像を表示できるようにしたいです。
この機能があれば、みんなで選んだ写真の良さをより感じられるようになり、写真選びの楽しさが増すのではないかと思います。
サムネイルのロードを最適化
現在のコンテスト画面では、エントリーされたすべての写真のサムネイルを一度に表示しています。そのため、写真の量が多い場合、サムネイルのロードに時間がかかることがあります。
無限スクロールや「さらに読み込む」ボタンなど、必要な分だけサムネイルをリクエストできる機能を追加することで、ロード時間の短縮や通信コストの削減を図りたいと考えています。
おわりに
APIの仕様変更以降、設計変更が相次ぎ、作り切れるのか不安になる場面もありましたが、無事にリリースすることができました。
アイデア出しからデザインまで開発全体を通してたくさんのアドバイスをくださったmachidaさん、リソースとDBの設計を丁寧にレビューしてくださったmaedanaさん、コードレビューをご担当いただいたことに加えAPIの仕様変更時を含め困ったときに的確にアドバイスをくださったkomagataさん、毎日一緒に作業していただきたくさんのご助言とともに精神的にも支えてくださった受講生・卒業生・メンターのみなさん、本当にありがとうございました🙏
PixPickは今後も改善を続けていきますので、お気づきの点やご意見・ご感想があれば、ぜひお聞かせください!
フィヨルドブートキャンプで『🍅もくもくポモドーロ会』というゆるイベントをやってみた
この記事は、「フィヨルドブートキャンプ Part1 Advent Calendar 2024」の13日目の記事です!
昨日はnicole2525さんの「フィヨルドブートキャンプを卒業しました!」でした。
また、フィヨルドブートキャンプ Part2 Advent Calendar 2024も開催中です。
昨日はKassy0220さんの「ActionCableのコネクションのIDについて」でした。
今回は、私がフィヨルドブートキャンプ内で定期イベントとして開催している「🍅もくもくポモドーロ会」についてお話ししようと思います!
もくもくポモドーロ会とは
「もくもくポモドーロ会」は、ポモドーロテクニックを使ってみんなで作業をするオンラインの作業会です。
毎週火・水・金曜日の10:00~11:30にフィヨルドブートキャンプのDiscordサーバー内で行っています。
作業内容はなんでもOK!みんなの前で発表するようなこともありません!特に準備するものはありませんし、発言やカメラのオン/オフも自由です。とにかく参加のハードルが低いです!!他の受講生さんとのコミュニケーションのきっかけに是非ご活用ください!!!
ポモドーロテクニックとは
ポモドーロテクニックとは、「25分作業 + 5分休憩」を繰り返すことで集中力を保つ時間管理術の一つで、効率的に学習や作業を進めるための方法です。
ポモドーロテクニックの魅力は、短い作業時間に集中し、定期的に休憩を取ることで疲労を防ぎつつ効率を上げる点です。
プログラミングをしているとついつい時間を忘れて熱中してしまい、気が付いたら他のことに取り組む気力や体力が残っていない…なんてことありませんか?(私はあります😅)
この作業法を用いればそういった事故(?)を防止することができるのです!なんと素晴らしいのでしょう!
会の流れ
1. 10:00 作業スタート(25分)
主催者がタイマーをスタートします。
このタイマーにはtimer.teamというWebアプリを使用しています。
2. 5分休憩
作業後はリフレッシュタイム!
過ごし方は自由ですが、みんなで雑談していることが多いです。
3. 作業と休憩を繰り返す
時間内で合計3サイクルほど繰り返します。
きっかけ
フィヨルドブートキャンプのDiscordサーバーには「もくもく部屋🍅」というチャンネルがあって、私が入会したころ、このチャンネルでは卒業生の方がつくった「ポモる」というDiscord Botを用いて他の受講生と一緒にポモドーロテクニックを用いた学習ができました。
入会した直後、この機能が他の受講生さんとのコミュニケーションのきっかけになり、オンラインスクールでも孤独じゃないんだなと感じたことを覚えています。
現在ではポモるがクローズとなっているためこの機能を利用することはできませんが、同じような体験が共有できればいいなと思い、「🍅もくもくポモドーロ会」を始めました。
やってみて感じたこと
今日までポモドーロ会を続ける中で、次のようなメリットを感じました。
仲の良い受講生が増えた
オンライン学習では一人での作業が多くなりがちですが、定期的にお話させていただくことで自然と仲の良い受講生さんが増えました。相談できる場所が増えた
仲の良い受講生さんが増えたこともあり、作業中に困ったことを気軽に相談できる場にもなっています。
日々助けていただいている参加者の皆さんに感謝です。モチベーションを保ちやすくなった
参加されている方々の作業に関するお話が良い刺激になり、「自分もがんばろう」と思えます。 また、日々の作業開始時刻にもリズムができ、作業に入りやすくなりました。新しい知識が入ってきやすくなった
他の受講生さんが取り組んでいる内容について伺ったり、時には雑談の中からも、新しい視点や技術を知るきっかけをいただいています。
今後のこと
私がポモるで学習していたときに感じたように、この会を続けていくことで誰かの孤独を和らげることができたらいいなと思います。
しかし、現在の開催日時では、転職後に同じペースで続けるのは難しいかもしれません。
開催日時を変えれば調整できるかもしれませんが、繰り返し参加してくださる方もいらっしゃるので、できるだけ今のまま続けられたらいいなと思っています。
そんなわけで、ポモドーロ会をどなたかに引き継いでいただくことなんかも考えています。
この会がバトンを渡しながら長く続き、より多くの人にとって「安心できる場所」になっていくことを願っています。
この記事が、ポモドーロテクニックやオンライン学習の新しい楽しみ方を知るきっかけになれば嬉しいです!
明日は先日ご卒業されたばかりのmotohiro-mmさんです🎉🐻❄️🎉ぜひお楽しみに!
2024年2月を振り返る
3月になりました!
まだまだ肌寒い日はありますが、少しずつ春の暖かさを感じる日も増えてきましたね🌸
皆さんいかがお過ごしでしょうか。
私は2月の初めに体調を崩し、思うように作業に取り組めない日々が続いています😅
これに伴い、1月の終わりまで書いていた週報も途切れてしまいました。
そんなわけで、その後の学習について月報としてまとめることで、この期間の活動を振り返ってみようと思います。
年間目標の確認
2024年の目標は大きく次の3つです。
- プログラミングスキルの向上
- 家族の幸せに貢献する
- 健康維持
詳しくは年初の記事(2024年の目標 - Neco Coder)をご覧いただくとして、
ここでは、これらの目標達成に向けて現状で取り組むべきことと、2月の成果、反省点を振り返ります。
プログラミングスキルの向上
エンジニアとしてのスタート地点に立つために、まずは開発実務の現場に入る!
そのためにFBCの卒業!
ということで、ここではFBCでの取り組みについて振り返ります。
取り組んだプラクティス
- Contextを使ってグローバルなstateを管理する
Reactのより高度な機能の一つであるContextを使用し、アプリケーション全体でのstate管理の方法を学びました。
Contextをカスタムフックと組み合わせることで、より強力な武器になったことが印象に残っています。 - Webセキュリティ
セキュリティリスクだらけの呪われたブログをサンプルとして、一つずつ呪いを解いていくことで、楽しみながらWebセキュリティに対する理解を深めることができました👻
レビュアーさんから自分の理解について説明するよう問うていただいた箇所があり、該当箇所については特に理解が深まったよう感じました。 - アジャイル開発/スクラム
アジャイル開発とスクラムに関する資料を読み、理解したことを自分なりに説明する資料をつくりました。
つい詳しく書きすぎてしまうので、どこまで説明するかの線引きが難しかったです。 - チーム開発
現在はFBCで実際に利用しているWebアプリをチームで開発するプラクティスを進めています!
まだまだ始まったばかりで単純なIssueしか担当していませんが、自分の作業が反映されたアプリをいろんな方が使ってくれているんだと思うと嬉しさがこみあげてきます😄
プラクティス外の活動
合同企業説明ドリンクアップへの参加
FBCと縁のある企業様から同社についてご説明いただくとともに、企業の担当者様と交流させていただきました。目覚まし会の開始
生活リズムの改善を目指し、受講生同士でその日の目標を共有する目覚まし会を立ち上げました。
始めてみると、日々の生活リズムが整うのはもちろんのこと、学習に取り組むモチベーションも朝イチから高めることができています🌞
家族の幸せに貢献する
2月は子どもの体調不良から始まり、その感染によって私と妻も体調不良で動けない期間が続きました。
家族のケアと自身の療養でその他のタスクに回せる時間が少なかったので、平常時以上に優先順位を意識した月でした。
毎月の目標としては、
- 月に1回息子と一緒に図書館へ行く
- 月に1回家族で半日以上外出する(図書館とは別に)
の2つがあり、どちらも実行することができました。
図書館では、息子が読み切れない数の本を借りて、嬉しそうに保育所の先生に見せていました📚✨
行けてよかったなと思います。
月末には家族でちょっと遠めの和食屋さんに行き、道中も含め、楽しい時間を過ごすことができました。
妻と子の笑顔から、やはりこうしたイベントを設けることは大切なんだろうなと実感。
体調不良は必ずしも歓迎できるものではありませんが、必然的に多くの時間を家族で過ごすことになったことで、思いがけず家族の絆が深まりました。
こうした環境で過ごした時間は、家族が一番大切という自分の価値観を再確認させてくれました。
健康維持
体調不良が続いたことで、健康の重要性を改めて実感しました。
エントリーしていたマラソン大会にも出れず😭
運動習慣の継続は難しい状況でしたが、健康維持のための意識は高まりました。
3月の目標
年間目標と2月の振り返りを踏まえて、3月の目標を立ててみました。
- 体調を完全に回復させる✨
- 運動習慣を再度身につける💪
- プログラミングに関するイベントの企画💻
- プログラミングに関するイベントへの参加🚶
- 技術記事を書く🗒️
- 家族でお出かけ!👪
抽象度高めです。
具体的な取り組みについては長くなってしまうので、3月の月報でお伝えしたいと思います。
最後に
年間目標について書いた年初の記事では、2024年のテーマについても書いています。
「成長と調和」
改めて見ると万博みたいなテーマだなと思いました。
来年はもう少し自分らしい言葉にしようと思います😅
とはいえ、引き続き年内は「成長と調和」を達成するため、学習と家族、健康のバランスを取りながら、充実した日々となるよう努力したいと思います。
まずは猫を吸うところから🤥🐈スゥーーー

それではまた👋
週報2024.1.22〜28
早いもので、1月も終わりが間近ですね。
第4週の週報です。
FBCで取り組んだこと
【プラクティスの進捗】
- 修了:0
- 提出:2
- 進行中:2
Reactでメモアプリをつくった
先週から取り組んでいたReactのメモアプリを提出できた。
リーダブルコードでコメントについて学習していることもあり、今回はコーディング時に積極的にコメントを活用するようにしてみた。
CSSがひどいことになっている気がするけど、ここからはメンターさんのお力を借りつつ仕上げていきたい。

SWRを使ってみた
Reactプラクティスの一環でSWRを使ってロード画面を実装した。
これを学習したことで、今後Webサイトやゲームなどを見るときの目が違ってきそう。
また少し、世界が広がった。

Reactプラクティスの終わりが見えてきた。残りの課題もすぐに提出できそうなところまでは進めてある。
来週にはチーム開発の準備完了まで持っていけるといいな。
リポジトリパターンの実装
後学のために進めていた修了済みプラクティスの改善が完了した。
メンターさんに改善案をいただいたので進めていた作業だ。
プログラミングは、何かをラップすることで飛躍的に使いやすくなることが多いなと感じる。
この視点は大事にしたい。
リーダブルコード輪読会に参加
参加者が多めの輪読会なので、質問するといろいろな角度で意見をいただけるし、話が広がりやすくて楽しい。
池に石を投げて広がる波紋を眺めているような感じだろうか。なんかえらそうな例えだな…
この輪読会に限らず、今後もできるだけ石を投げるようにしたいなと思う。
- 無理にコメントする必要はない
- コメントについて学習したからといって、無理にコメントする箇所を探すようなことをしては本末転倒だ
- 変数やメソッド等における具体と抽象のバランス
- 熟練者は4単語を超えてくると長いと感じる方が多い?
- メソッドであれば、処理が単一であるかを確認すべき。 単一でなければメソッドを分けることで具体的で短い名前にできるかも。
- 定数には値の設定根拠をコメントするといい
- 例えば値の計算に関連した箇所が変更されると、その定数も変更すべきことが後から読んだ人にもわかる。
- この本を読まなければ、「定数名から値の意味はわかるからコメントはいらない」と考えたままで止まっていたかもなと思った。
- 慣例から外れるようなコードを書く場合はその意図をコメントすべき
- 細かい動作を知らない人が使ってしまうと使い方を誤ってしまいそうな動作は、その点コメントすべき
- 「読む人がビックリするようなコードを書かない」というのは学んできたけど、仕様通りでもビックリさせてしまうケースはあって、その点も想像力を働かせる必要がある
目覚まし会の企画
朝起きられるようになってきて、明らかに生活全体が良い方向に向かっている。
この生活を続けたいと思ったので、目覚まし会を立ち上げることにした。
Discordで共同主催者を募ったら、すぐに複数の方が手を挙げてくださった。ありがたいことだ。
来週には始められるようにしたい。
週間目標
学習時間
実績44.5h / 目標40h = 達成率111%
目標の達成状況
今週はすべて達成!やっほー!!パフパフー🎺
達成
- Reactのアウトプット系プラクティス課題を2つ提出する
- JSメモアプリを改善する(必達)
- ベンチプレスに3日取り組む
- 晴れの日はすべてランニングする
- マラソン大会にエントリーする(必達)
- 毎日10秒瞑想する
- 毎日猫を吸う
- 1/30までに週報を公開する
未達成
なし
来週の目標
- チーム開発までのプラクティスをすべて提出以上の状態にする
- 目覚まし会を開始する
- ジムでベンチプレスに3日取り組む
- 毎日自宅から出て走る(小雨決行)
- うち2日は3km以上走る
- 毎日10秒瞑想する
- 毎日猫を吸う
- 2/6までに週報を公開する
今まではベンチプレスと書きつつ、自宅でダンベルプレスをしていた。
そろそろ習慣化してきたのでもうひと手間かけて、ジムまで行くようにしたい。
その他近況とか
目覚まし会に関する部分でも触れたが、少しずつ体力が戻ってきて、生活全体が良い方向に向かっている。年始からちょこちょこと筋トレしていたおかげだろうか。
細かく挙げれば学習に関する影響もたくさんあるんだけど、わかりやすい部分だと「一日を通してモチベーションを維持しやすい」というものがある。
一日のどの時点を切り取っても、学習時間を確認したときに「うわっ!もうこんなに学習したのか」と思える。自己肯定感が上がれば意欲も湧いてくる。成功のループに入る。
直接的には体力でなく朝型生活のおかげだ。しかし、これには「体力がつく→自制心が強くなる→夜更かしをしなくなる→朝型生活になる」という繋がりがある、はず(体感)。
今後も少しずつ運動量を増やしていこうと思った。
最後に
うだうだと書きましたが私の布団に息子が入ってくるようになったので最高の週でした(代わりに猫が妻の布団に入るようになりました)。

来週も最高の週になるでしょう。
それではまた!
週報2024.1.15〜21
1月第3週の週報です。
FBCでの取り組み
今週は…
- 自作npmを開発した
- Reactの公式ドキュメントに取り組んだ
- リーダブルコード輪読会に参加した
自作npmを開発した
先週公開して、メンターさんにレビューをいただいていた自作npmが完成した。
完成したnpm
首都名クイズのCLIアプリをつくった。
【工夫した点】
- 大陸ごとに解答できるようにした
問題のソースとして用いたnpmパッケージが大陸ごとに国を整理していたので、その点も活かして解答できるようにした。 - 英語・日本語の2か国語対応
npmパッケージは世界に公開するため基本は英語としてつくった。
しかし、実際に私のnpmパッケージに辿り着く可能性が高いのは(つまり想定利用者が)日本人だと思ったので、日本語表示も可能とした。 - View機能をつけた
予習・復習を可能とするために、国ごとの首都名を一覧できるView機能をつけた。
こちらも大陸ごとに表示可能であり、日本語対応している。
【苦労した点】
- npmパッケージサイトへの公開自体は先週行った。
しかし公開時点では、READMEに示した方法でプログラムを実行できないという重大なバグがあった。
レビューの際にメンターさんからご指摘をいただいて発覚した。このバグはファイルの読み込みに相対パスを使用していたことによる。
原因がパスなので、自身の開発用PCではエラーが出なかったことで見逃したようだ。手持ちの別PCでも確認していればこのようなバグは防げたはず。
外部に公開するプログラムは必ず開発用PC以外(できる限りユーザに近い環境)で確認するようにしようと思った。
もちろん現在は修正済みである。 - i18n対応を最後にしたところ、アプリケーション全体に影響が出たので大変だった。
とはいえベースとなるロジックが固まっていたからこそ対応できた部分もあると感じるので、開発当初から並行して進めるべきだったのかはわからない。
翻訳作業はどうしたって作業量も多くなるし、取り組む際には覚悟が必要だと感じた。
【終えてみて】
もっと単純なアプリ(例えば首都名一覧が見れるだけとか)にすればプラクティス修了は早かったろうとも思う。
「できるだけ早く卒業する」という目的からすればそちらの選択が理には適っている。
だけど、そうしなかったおかげで今の自分的にはそこそこ満足できるものができた。
ものづくりってやっぱり楽しいと感じた。この感覚を得られたことも大きな収穫だ。
Reactの公式ドキュメントに取り組んだ
先週に引き続きReactの公式ドキュメントを読んだ。
先週は飽きがきたと書いたが、その後は(特にStateの理解が進んでからは)結構楽しんで進めることができた。
印象に残っているのは、エフェクトについて学んだとき。
「あ゛あ゛~~難しい〜~〜!!」と頭を抱えながらなんとかチャレンジ問題を解ききり次のページに進んだところ、見出しにドカンと「エフェクトは必要ないかもしれない」と書いてあった。
なんとなく、穴を掘って埋めるだけの刑罰を思い出した。
Reactのエフェクトとカスタムロジックに関する学習メモ
このメモはReact公式ドキュメントから読み取った内容ではありますが、本記事は技術記事ではありません。
故にこのメモには未検証の部分を含んでいます!
ご覧になる際はこの点ご留意願います。
エフェクト
useEffectはレンダー結果が画面に反映し終わまで、コードの実行を遅らせる。- 第1引数で渡した関数をレンダー後に実行する
- 第2引数には依存関数を渡す
- ここでいう依存というのは、コールバック関数の判断の軸になっている要素のこと
- 第2引数がない場合、毎回のレンダー後に実行される
- 第2引数が空配列[]の場合、マウント時(コンポーネント出現時)のみ実行される
- 第2引数が[a, b]の場合、マウント時と、a か b の値が前回のレンダーより変わった場合に実行される
- つまり、依存値として指定されるのは、レンダー間で変わる可能性があるもののみ。
- 原則として
refは依存値に指定する必要がない。 useStateが返すset関数も同じく、依存値として指定する必要はない。refもset関数も「必要ない」だけであって、含めても問題はない。- 毎回同一であれば必ず省略できるわけではない。リンタがはっきりと判断できる必要がある。
マウントとクリーンアップ
マウントとは、画面に初めて表示されるときに対象のコードを実行するよう指示すること
- 大規模アプリにおけるコンポーネントはマウント・アンマウントが頻繁に発生する。
- 第2引数に[]を指定するだけでは、最初のマウント時に実行した処理を正しく終えていない場合、重複して処理がなされることになる。
- この問題に気づきやすいよう、Reactは初回マウント時だけもう1度マウントする(初回マウントはすぐにアンマウントされ、2回目のマウントが行われる)。
- これはStrict Modeの機能であり、Strict Modeを外せばこの挙動は起きない(非推奨)。
- 再マウントされても正しく動作するようエフェクトを修正しない限り問題の根本解決にはならない。
- これはStrict Modeの機能であり、Strict Modeを外せばこの挙動は起きない(非推奨)。
- クリーンアップ関数を返すようにすると解決する。
- クリーンアップ関数とは、useEffectのコールバック関数内に
return 関数の形で書かれる関数であり、コンポーネントがアンマウントされる際に実行される
- クリーンアップ関数とは、useEffectのコールバック関数内に
- この問題に気づきやすいよう、Reactは初回マウント時だけもう1度マウントする(初回マウントはすぐにアンマウントされ、2回目のマウントが行われる)。
- レンダーによって引き起こされるべきではないものをエフェクトにしてはいけない。
- 逆にいえば、
useEffectに渡す処理は、レンダーによって引き起こされるべきものに限るということだ。
- 逆にいえば、
- フェッチをエフェクトにする場合、クリーンアップ関数としてフェッチの中止、またはその結果を無視する必要がある。
- ここでは、結果を無視する方がより確実な方法となる。なぜならフェッチの中止をしても、その後に非同期ステップが連続する可能性があるから。
エフェクトの要否
- 外部システムの関与
- あり 同期したい場合はエフェクトが必要。
- なし エフェクトは不要。
- 不要なエフェクトを書かないことによるメリット
- 可読性の向上
- 実行速度の向上
- エラーが発生しにくくなる
- エフェクト不要となる場合2つ
- 既存の
propsやstateから計算できるものはstateに入れない。レンダー中に計算すべき。stateの章でも同じことが書いてあったはず。
不要なエフェクトの削除方法
- 重たい計算をキャッシュ・メモ化 (memoize)するには、
useMemoフックでラップする。- 依存関数が変更されない限り、中の関数を再実行しないようReactに指示するもの
- ラップするのは純関数である必要
props が変更されたときにstate を変更する
- すべての
stateをリセットする - 一部の
stateを調整する
どこにロジックを保持させるか
- エフェクトを使ってイベントハンドラ間のロジックを共有するとバグの原因になる。
- コンポーネントがユーザに表示されたために実行されるべきコードにのみエフェクトを使用すべき
- なぜそのコードが実行されるのかを考える
- コンポーネントがユーザに表示されたために実行されるべきコードにのみエフェクトを使用すべき
- イベントハンドラとエフェクトのどちらにロジックを入れるべきか選択する際には、ユーザの観点からそれがどのようなロジックなのかを考える。
計算の連鎖
- 原則として、他の
stateに基づいてstateの一部を調整するエフェクトを連結させてはならない。- 非常に効率が悪い
- コードが発展するにつれ、書いた「チェイン」が新しい要件に適合しないケースが出てくる
- レンダー中に計算できるものはそこで行い、イベントハンドラで
stateの調整を終わらせるべき - イベントハンドラ内で次の
stateを直接計算することができない場合は、エフェクトを連鎖させることが適切となりえる
アプリケーションの初期化
アプリが読み込まれるときに一度だけ実行されるべきロジックの配置
- 2 つの異なる state 変数を同期させたいと思ったら、代わりに
stateのリフトアップを試すべき- 全体として考える必要のある
stateが少なくなる
- 全体として考える必要のある
- 親と子が同じデータを必要としているのなら、親コンポーネントが取得して子に渡すべき
- これによりデータの追跡・予測可能性を高める
エフェクトのライフサイクル
- エフェクトのライフサイクルは、コンポーネントのライフサイクルとは異なる。
- エフェクトのライフサイクルについて考える上では、エフェクトの開始/終了という1サイクルのみにフォーカスすべき
- コンポーネントがマウント中なのか、更新中なのか、はたまたアンマウント中なのかに注目するのはややこしくなりやすいので❌
- エフェクトがクリーンアップ関数を返さない場合、空のクリーンアップ関数が返されたものとして扱う
- コード内の1つのエフェクトは、1つの独立した処理を表すべき
- あるエフェクトを削除しても、他のエフェクトのロジックが壊れない場合、それらのロジックは分割すべきである
- コンポーネント内のすべての値(props、state、コンポーネント本体の変数を含む)はリアクティブである
- リアクティブな値は再レンダー時に変更される可能性があるため、エフェクトの依存配列に含める必要がある
- リアクティブな値とは、その値が変更されたときに自動的に関連するコードやUIが更新されるような値のことを指す
- state変数は常にリアクティブである
- ミュータブルな値や、この値から導出される値は依存配列に含めることはできない
refは依存配列に含めることができるが、ref.currentは含めてはならない- ただし、
refは依存配列から省略できる
- ただし、
- リンタに引っかかる場合は次の3点を確認する
- エフェクトが1つの独立した同期の処理を表しているか
- 非リアクティブな部分を分離できないか
- オブジェクトや関数を依存配列に含めていないか
- リンタの提案に従ってバグが発生したとしてもリンタを無視すべきではない
- ルールを守りつつバグが発生しないよう修正すべき
- リンタを抑制する記述が既になされていないかどうかもチェック
エフェクトから依存値を取り除く
依存値を削除するには、それが依存値である必要がないことをリンタに「証明」する必要がある
- 例:対象の値をコンポーネント外へ移動する
依存配列を変更したい場合は、まず周囲のコードを変更する
- 周囲のコードの変更に合わせて、リンタが依存値の変更を指摘してくれる
ある値を依存値に含めることで問題が発生する場合、エフェクト内でその値を読み取らないようにし、代わりに更新用関数を渡す
- 更新用関数は、
setA(a => a + 1)の形で、処理中のstateの値を受け取りそこから次のstateを導出する
- 更新用関数は、
変更に反応せず値を読み出したいだけの場合、当該ロジックをエフェクトイベントに移動する
- 安定版では未リリースの機能なので、現在のところは基本的に使えないと考えておく
オブジェクトや関数が依存値に含まれていて、かつ、親コンポーネントがレンダー中にそれらを作成している場合、親コンポーネントの再レンダーのたびに、エフェクトによる再接続が発生してしまう
- エフェクトの外側でオブジェクトや関数から情報を読み取っておけば依存値から取り除けるので、この問題を回避できる
- できればオブジェクト型や関数型が依存値となること自体を避けるべき
カスタムフックでロジックを再利用する
カスタムフックとして、アプリケーションの要求に合わせて独自のフックを作成することができる。
- ロジックをカスタムフックに抽出することのメリット
- フックの名前は
useで始めて大文字を続ける必要がある(LCC) - 内部でフックを呼び出さない関数はフックである必要はない
- フックでない関数に
useプレフィックスを使ってはならない(Reactがフックを判断する基準なので当然) - フックを呼び出さない関数もフックにすることはできる(非推奨)
- フックでない関数に
- カスタムフックは重複したロジックをまとめるが、カスタムフックを使用するコンポーネントごとに
stateは独立している- カスタムフックは、
state自体ではなく、stateを扱うロジックを共有できるようにするためのもの
- カスタムフックは、
- カスタムフックも純粋である必要がある
- 複数のエフェクトに同一の処理がある場合でも、それらが独立した処理であるならば、統合することはできない。このような場合、カスタムフックはエフェクトごとの独立性を保ちながら重複する記述を削除できる
- エフェクトをカスタムフックに抽出する(隠す)ことで不要な依存値の追加を防げる
- カスタムフックは具体的かつ高レベルのユースケースに対して使うべき
- つまり、特定の目的に特化されているが、同時に複雑な処理や高度なロジックを含んでいるような場合に使えということ
- 良いカスタムフックとは、動作を制約することで呼び出し側のコードをより宣言的にするもの
- 【カスタムフックにエフェクトをラップするメリット】
リーダブルコード輪読会に参加
今週はコメントに関する内容が特に大きな学びになった。
書籍の例示に対して、「コメントする前にもっと変数化すれば読みやすくなるんじゃ?」という箇所があった。
この点について参加者の方々と話してみたところ 「変数が多くなるようならそのまま繋げて書いてコメントを付した方が読みやすくなる」という学びを得られた。
これまではコメントをつけずに読みやすいコードを書くことを意識していたが、そうするとどうしても変数が多くなってしまっていた。
しかし、変数定義が多くなれば
- 縦に長くなってしまい、それはそれで可読性は損なわれる
- 幾分かメモリを使う
というデメリットが生じる。
これらはいずれも輪読会参加者の方にご指摘いただいた。
縦の長さについては実際にコーディング中に考えたことがある。
しかし、その時はデメリットを認識するだけで終わってしまっていた。
上記の学びは、書籍の例示を読んだタイミングで気づかせていただけたから得られたのだと思う。
素晴らしい参加者の方々に感謝🙏✨
週間目標
学習時間
実績54.25h / 目標40h = 達成率136%
目標の達成状況
概ね順調。マラソン大会とJSメモアプリがやるやる詐欺になりつつあるので来週は必達とする。
達成
- Reactのインプット系プラクティスを修了する
- ベンチプレスに3日取り組む
- 毎日10秒瞑想する
- 1/23までに週報を公開する
- 毎日猫を吸う
未達成
来週の目標
- Reactのアウトプット系プラクティス課題を2つ提出する
- JSメモアプリを改善する(必達)
- マラソン大会にエントリーする(必達)
- ベンチプレスに3日取り組む
- 晴れの日はすべてランニングする
- 毎日10秒瞑想する
- 毎日猫を吸う
- 1/30までに週報を公開する
ベンチプレスは来週くらいからもう少し具体化してもいいかも…?
その他近況とか
つまらない質問
FBCには関係者用のDiscordサーバーがある。
その中には雑談部屋というものがあるんだけど、最近よくそこにメンターさんがいらっしゃる。
学習の合間に入ってみると、雑談部屋の名の通り、なんとはない雑談にも応じていただける(もちろんまじめな話にも)。
日頃からそのような距離感で接していただけるおかげで
- 「Discordのあのスレッドって生徒が書いてもいいんですかね?」
- 「Twitterにどんなこと書けばいいかわからんすわHAHAHA!!」
みたいなつまらない内容でも気軽に相談できて非常に助かっている。
FBCにはいろんな形で質問・相談できる制度があるが、「ちょっと気になるけど質問するほどのことでもないな」と流してしまうこともちょこちょこある。
でも、そういった問題が解決すると日々のストレスが予想以上に減ったりして、ひょっとすると集中力にも影響する。
そんなわけで、雑談部屋にメンターさんがいてくださるというのは、本当にありがたいことだなと感じている。
子どもがいるから
週初めの出だしが遅れがちである。月曜朝にだらだらしがち。
子どもがいると(そして組織で仕事をしていないと)どうしてもリズム維持が難しい部分があるけど、だからこそ学習時間を確保する工夫の考案と実践を怠ってはならない。
最近、ちょうどFBCで朝活に関する話題が上っていた。
メンターさん含め、子どもがいる方は寝かしつけ時に一緒に寝ることで朝型生活を身につけた方が多いらしい。
子どもがいるからこそ整えられるリズムもあるのだ。楽しんでいこう。
最後に
なんだかんだと書きましたが、猫が脚の間に入ってくるので最高の一週間でした。

来週も最高の一週間になるでしょう。
それではまた!
週報2024.1.8〜14
年明けから早くも最初の月が折り返しますね。
第2週の週報です。
やったこと
FBC
自作npm開発
自作npmをnpmリポジトリに公開した。
できあがったものを妻に見せていたら早速バグに気づいたので急いで修正した。
プログラムの公開は慎重に…とは思うものの、ほどほどにしなければ及び腰になってしまうと思う。 商用でなければ気負わないようにしたい。そういうライセンス(MIT)だし。
来週には修了できるといいな〜
Reactを学ぶ
Reactのインプットプラクティスとして、公式ドキュメントを読み進めている。
スタートガイドがなかなか頭に入ってこなかったので心配だったけど、Reactを学ぶは読みやすくてひと安心。
とはいえ、そう簡単なプラクティスではないようだ。
公式ドキュメントが長い
初学者からすると公式ドキュメントが長すぎるのである。これではどうにも飽きてしまう(私が飽き性なだけかもしれないが)。
公式ドキュメントをしっかり読んでからアウトプットに取り組んだ方が効率は良いことは確かだ。
しかし、ドキュメントの読込も集中できずに取り組んでいては効率も理解度も下がってしまう。
とはいえ、長いものは長いのである。
長くて嬉しいのは猫と恵方巻きだけだ。
それにしても猫という生き物はなぜあんなに長いのだろうか。伸びた状態の猫は明らかに平常時より体積が増えている。物理的な法則を無視しているのである。猫というのはこの世の理に縛られない魔法使い、あるいは宇宙の法則を超越した存在なのだ。「ネコと和解せよ」という言葉もある。そう、猫は古来より信仰の対象となってきたのだ───────
話が逸れた。
要するに「公式ドキュメントが長い!飽きる!効率落ちる!」という話。
対策として、具体的なアウトプットに取り組みながら公式ドキュメントを読むことにした。
なお、このようにごちゃごちゃ言わずしっかりとドキュメントを読み進めてからアウトプットに取り組み、素晴らしい結果を出している受講生もいることを申し添えておく。
チャレンジ問題が難しい
ドキュメント内で出題されるチャレンジ問題のクリアもプラクティスの修了要件となっており、これが初学者にはなかなか歯ごたえのあるものとなっている。
歯ごたえはあるが(だからこそというべきか)、理解への貢献度も高い問題となっているよう感じる。
このチャレンジ問題を解きなおすだけでも初学者として最低限の理解は得られそうなので、チーム開発に入ったあたりでもう一度取り組もうと思う。
リポジトリパターンの実装
メンターさんから改善案をいただいたので適用を進めた。プラクティス自体は修了しているので、この件は少しずつ進めていこうと思う。
DBに保存する形式だったアプリをCSVでも保存できるようにするとともに、これらの保存先を切り替えやすい構造になるよう改善を進めている。
調べてみるとこの構造はリポジトリパターンに似ているよう(あるいはそのもの)だった。
世界一流エンジニアの思考法を読みはじめた
「理解には時間がかかる」という金言を得た。 業界のトップランナーでさえもそうなのだ。
ちょうどReactの基礎を学んでいるので、丁寧に押さえていこうと思った。
リーダブルコードを読み進めた
輪読会に出ようと思って読み進めたのだけど、やっと予定が合ったと思ったら寝坊してしまい途中参加と相成った。
途中からだったのでラジオ参加(基本的に参加者のやりとりを聴取するのみの参加形式)だったのだけど、一人で読んでいてよくわからなかった部分をチャットに書いたら参加者の方々が拾ってくださり、不明点をクリアにできた。
素晴らしい輪読会メンバーに感謝🙏✨
昨年の輪読会でも同じ箇所が議題に上がったりしていたようなので、「難しい本」として、一読じゃわからないのが当たり前だと思いながら読み進めていこうと思う。
生活
近所のおいしいお店を開拓
妻が休暇を取得した日に近所のお蕎麦屋さんを開拓した。
お店の雰囲気もよく、お蕎麦も天ぷらもとてもおいしくて「良い店を見つけたね~」と妻と喜びあった😄✨
そば粉のたい焼きなるものもあって、これもおいしかった🐟
そば茶が飲み放題なのも◎🍵
息子を図書館へ連れて行った
家族で隣町の図書館に行った。
息子はとても喜んで、読み切れないであろう冊数の絵本を借りていた。
行って良かったな。
週間目標
学習時間
実績48.25h / 目標42h = 達成率115%
目標の達成状況
主なものは達成できました。
達成
- JSメモアプリを改善する(レビュー指摘事項対応)
- Reactのインプット系プラクティスを半分以上進める
- ベンチプレスに3日取り組む
- 毎日10秒瞑想する
- 息子と一緒に図書館へ行く
- 1/16までに週報を公開する
- 毎日猫を吸う
未達成
- 書籍「世界一流エンジニアの思考法」を半分以上読む
- マラソン大会にエントリーする
来週の目標
- Reactのインプット系プラクティスを修了する
- Reactのアウトプット系プラクティス課題を1つ提出する
- JSメモアプリを改善する(レビュー指摘事項対応)
- ベンチプレスに3日取り組む
- マラソン大会にエントリーする
- 毎日10秒瞑想する
- 毎日猫を吸う
- 1/23までに週報を公開する
その他近況とか
プログラミング学習による日常生活の変化
最近、日常生活の中でプログラムの動きについて考えることが多くなってきたように感じる。
Reactについて学んでから一層その傾向が強い。「このバグの動きはStateの問題なのかもな~」という感じで。
フロントエンドの学習は特にこういうことが起こりやすいのかもなと思った。
あらゆるものがプログラムで動いている時代だからこそ、プログラムについて学ぶと世の中の見え方が大きく変わるのかもしれない。
改めて、プログラミングって楽しいなと思った。
ミクロネシア連邦とミクロネシア諸島
今週のどこかの日、
👶「これはミクロネシア連邦!」
👩「これはミクロネシア諸島の国旗だよ~」
という旨の会話が浴室から聞こえてきた。
壁に貼っている世界の国旗が学べるポスターを見て会話していたらしい。
対象の国旗には確かに「ミクロネシア諸島」と書かれていた。が、調べてみたところ、ミクロネシア諸島は国家ではなく、当然国旗はない。
正しくは息子のいうとおり、ミクロネシア連邦の国旗だった。
「ミクロネシア諸島」という名称は、おそらく地域としてのミクロネシアを指す言葉で、ミクロネシア連邦や小笠原諸島などが含まれるらしい。
教材を過信せず、子どもが正しい知識を得られるよう注意したいと思った。
最後に
色々と書いたけど、毎日猫が布団に入ってきたので最高の一週間だった。

来週も最高の週になるでしょう。
それではまた!
週報2024.1.1~7
今年から週報を書いていこうと思う。
せっかく年間目標を宣言したので、ブレイクダウンした目標を報告することで実現に近づければいいな。
やったこと
FBC
JSのクラスプラクティスを修了した
JSでクラスを学ぶプラクティスの課題として提出したメモアプリについてレビューしていただいたので、指摘事項に対応した。
その後OKをいただきプラクティス修了となったが、更なる改善事項をご指導いただいた。来週中には対応して、理解を深めたいと思う。
課題要件以上の範囲についても、(修了という線引きはした上で)しっかり学びを与えていただけるのがFBCの素晴らしい点のひとつだと思う。
以前別のメンターさんにレビューしていただいた際も、修了後に追加で質問したら快く回答してくださった。
メンターさんが自身のブログで書かれていたと思うが、「良いプログラマを増やしたい」という目的がメンター業の第一にあるとのこと。
言うは易しだが、メンターさん方とやり取りする中でその思いを感じることがしばしばある。
エンジニアを目指す上でロールモデルになる方々と交流できる機会を得られる点も、FBCの良いところ。
自作npm開発
自作npmをつくるプラクティスの課題制作を進めた。
市役所に勤めていた時は長らく防災担当であり、社会的にも防災に関する意識が高まっているタイミングであったため、初めは防災関連のアプリを考えていた。
しかし、CLIツールという形で防災に関するものの需要があるとは思えなかったので取りやめた。CLIでなくてもいいのかもしれないが、自分の技術力でつくるには時間がかかりすぎる(あるいはつくれない)。
結局クイズアプリをつくることにした。
シンプルだしすぐにできるだろうと思っていたが、つくっているうちにやりたいことは増えてくるもので、結局それなりの作業量になった。
とても楽しかったし、やっぱりものづくりが好きだと感じた。
エンジニアを志したのも、これまでの仕事でものづくりをした際に楽しいと感じたことが理由の一つにある。
この気持ちを大切にしたいと思った。
生活
親戚回り
お正月なので親戚回りの時間が多かった。
今年は、コロナ禍でしばらく中止になっていた会も開催されたので、それなりに忙しかった。
行く先々で息子にたくさんのかわいいをいただけて嬉しかった。
家族の時間
息子の希望で近所の公園に行った。
息子のこうした要望はよくあるんだけど、なんだかんだで対応できないことも多い。
意識的に家族時間を確保していくためにも、こうした場で報告していくことを心掛けたい。
(「誰が知りたいんだ」とは思うけど🫠)
週間目標と学習時間
学習時間
実績43.5h / 目標33h = 達成率132%
年始ということで親戚回りで忙しい週だった割には学習できたかなと思う。
その他の目標の達成状況
達成
- 1日1回猫を吸う
吸ってました🤥🐈✨
未達成
- 自作npmの提出
- 毎日10秒瞑想する
- 息子と一緒に図書館へ行く
- 家族で半日以上外出する(図書館とは別に)
自作npmは見通しが甘かった。目標設定ミス。
瞑想は達成しなきゃいけなかったと思う。意識が低すぎた。習慣化アプリを設定して解決を図る。
その他生活系の目標は今月中に1回達成できればヨシ!としているけど、意識しないとズルズルいきそうなので、来週中にはどちらか達成しようと思う。
来週の目標
- JSメモアプリを改善する(レビュー指摘事項対応)
- Reactのインプット系プラクティスを半分以上進める
- 書籍「世界一流エンジニアの思考法」を半分以上読む
- ベンチプレスに3日取り組む
- マラソン大会にエントリーする
- 息子と一緒に図書館へ行く
- 毎日10秒瞑想する
- 1/16までに週報を公開する
まとめ
つらつらと書いたけど、猫が膝に乗ってきたのでつまるところ最高の週だった。

来週も最高の週になるでしょう。
それではまた!