wifi無線ルーターをTP-Link Archer C7に買い換えて快適になった
以前は5、6年前に買ったバッファローの無線ルーターを使っていて、特に大きな不便もなかったのですが、amazon prime,netflixを見たり、アプリダウンロードが遅かったりでどうにかならないものかなと考えていました。
でもどれが良いかよくわかんないしなーっと思っていたところ↓のpodcastでTP-Link Archer C7がいけてると紹介でありました。
https://www.amazon.co.jp/gp/product/B071D6H9NK
- 出版社/メーカー: TP-LINK
- 発売日: 2016/02/16
- メディア: Personal Computers
- この商品を含むブログを見る
podcastの内容自体もすごく面白かったのですが、
box社のセキュリティがすごいというくだりでboxが使っているソフトウェアなら信用できるという話があり、それに習って情シスの人が言っているならと思い買ってみました。
ちょうどその時タイムセールにもなっており…
設定自体は専用のアプリを使うとすぐできました。
ブラウジング、動画の再生、ダウンロードなどなど体感的にわかるぐらい速くなりました!
というわけでよくわかっていないものに関してまずは専門家に従っていこうかとw
PSR-6(Caching Interface)を見ていく
要約ですので、所々省いている箇所あります。
オリジナルはこちら
導入
- キャッシングはパフォーマンス向上の一般的な手法です。キャッシングライブラリを実装することはフレームワーク、ライブラリの一般機能の1つです
- これは複数のライブラリがそれぞれ独自のレベルの機能をもったキャッシングライブラリを持つ状態を招きます。これらの差異によって、開発者に必要/不必要に関係なく複数システムを学ばなければいけません
加えて、キャッシングライブラリの開発者は、限られたフレームワークのみサポートするか、多数のアダプタクラスを実装するかの選択に迫られます。
キャッシングシステムの共通インターフェースはそれらの問題を解決します。ライブラリ、フレームワーク開発者は、希望する動作のライブラリを利用できます。
- キャッシングライブラリ開発者は1つのインターフェースを実装するだけでよい。
ゴール
- このPSRのゴールは、開発者がカスタマイズの必要なく、既存のフレームワーク、システムにキャッシングライブラリを統合できるようにすることです
定義
ライブラリ呼び出し
- ライブラリ、コードはキャッシュサービスを必要とします。
- ライブラリはこの標準インターフェースを実装することでキャッシングサービスを利用することができますが、キャッシングサービスの実装知識は必要ありません
ライブラリの実装
- こにライブラリは、どんなライブラリにもキャッシングサービスを提供するためこの標準を実装する責任がある
- 実装ライブラリは、
Cache\CacheItemPoolInterface
とCache\CacheItemInterface
を実装するクラスを提供しなければいけない - 実装ライブラリは、下記に記載する最小TTLを秒単位でサポートしなければならない
TTL
有効期限
- キャッシュアイテムが失効する時の時刻
- これはキャッシュされた時刻にTTLを足すことで計算されるが、明示的に
DateTime
オブジェクトで定義してもよい - 実装ライブラリは有効期限前にキャッシュを失効してもよい
- もし有効期限が指定されない場合は、デフォルト値を使っても良い。デフォルト値が設定されていな場合は、無期限にキャッシュしなければならない
キャッシュキー
- キャッシュされたアイテムを一意に識別する1文字以上の文字列
- 実装ライブラリは、UTF-8エンコーディングで最大64文字の
A-Z, a-z, 0-9, _, .
で構成されるキーをサポートしなければならない - 実装ライブラリは追加で、その他の文字列/エンコーディング/文字列長をサポートしてもよいが、少なくとも最小限はサポートしなければいけない
- ライブラリはキーストリングスを適切なエスケープをする責任がありますが、オリジナルの未変更のキーストリングスを返せるなければいけません
{}()/\@:
これらの文字列は将来の仕様変更に備えて予約されていので、サポートしてはいけない
Hit
- 呼び出すライブラリからのキーでアイテムをリクエストされ、キーにマッチする値が見つかり、有効期限ではなく、なんらかの理由で失効になっていない時にキャッシュヒットが起こります。
- 呼び出すライブラリは、すべての
get()
コールで、isHit()
を使って確認すべきです
Miss
- キャッシュミスはキャッシュヒットの逆
- リクエストされたキーにマッチするものがない、有効期限が切れている、なんらかの理由で無効になっている時はキャッシュミス
- 有効期限切れの値はキャッシュミスにならなければいけない
Deferred
- 遅延キャッシュは、アイテムがプールによってすぐに永続化されないことを意味します
- プールオブジェクトはいくつかのストレージエンジンでサポートされているバルクセットを利用するためキャッシュを遅延してもよい
- プールは遅延されたアイテムを最終的に永続化し、ロストさせてはいけない。そして呼び出すライブラリが永続化リクエスト前に保持してもよい
- 呼び出すライブラリが
commit()
を読んだ時はすべての遅延キャッシュを永続化させなければいけない - 実装ライブラリは、
save()
、タイムアウト、max-itemsチェックやその他適切なロジックで遅延アイテムを永続化してよい - 遅延キャッシュされたアイテムがリクエストされた時は、永続化されていなくとも遅延されたアイテムを返却しないといけない
Data
実装ライブラリはシリアライズできるPHPデータすべてをサポートしないといけない
- Strings
- Integers
- Floats
- Boolean
- Null
- Arrays
- Object
全てのデータは実装ライブラリに渡された形のまま、型も含め返却されなければいけない
- 実装ライブラリは、内部的にPHPの
serialize()/unserialize()
を使って良い、これは必須ではない - なんらかの理由で正確な値が返却できない場合、実装ライブラリは破損したデータを返すより、キャッシュミスを返さなければいけない
Key Concepts
Pool
- プールはキャッシュシステム内のアイテムの集合を表す。プールはすべてのアイテムが含まれる論理的なリポジトリー
- すべてのキャッシュ可能なアイテムはプールからアイテムオブジェクトとして検索され、すべてのキャッシュオブジェクトはプールを介して対話する
Items
- アイテムはプール内の単一のkey/valueのペアを表す。keyはアイテムのユニークな識別子で、不変でなければいけない。値はいつでも変更あってもよい
Error handling
- キャッシングはパフォーマンスにとって重要ですが、アプリケーション機能の重要な部分ではありません。なので、キャッシュシステムのエラーはアプリケーションのエラーになるべきではありません
実装ライブラリは、インターフェースで定義された以上のexceptionをthrowしてはいけません。そしてキャッシュシステムでのエラーをトラップして上げるべきではありません
実装ライブラリはそのようなログはエラーをログに残すか管理者に報告すべきです
もし呼び出しライブラリが1つかそれ以上の削除済みか、プールがクリアさてれいるアイテムをリクエストされ、キーが存在しない場合でもエラーとしてはいけません
Interfaces
CacheItemInterface
CacheItemInterface
はキャッシュシステム内のアイテムを定義- 各アイテムオブジェクトは特定のキーに関連付けられていなければなりません。通常は
Cache\CacheItemPoolInterface
オブジェクトによって渡されます。 Cache\CacheItemPoolInterface
はキャッシュアイテムの格納、検索をカプセル化します- どの
Cache\CacheItemInterface
もCache\CacheItemPoolInterface
から生成され、必要なセットアップとユニークキーとオブジェクトを関連付けます Cache\CacheItemInterface
はどのデータ型でも格納、検索できなければいけません呼び出しライブラリは自身で、アイテムオブジェクトを生成してはいけません
- プールオブジェクトの
getItem()
メソッドからリクエストされるべきです - 呼び出しライブラリはあるライブラリから生成されたアイテムオブジェクトが他のライブラリと互換性があると想定すべきではありません
CacheItemPoolInterface
Cache\CacheItemPoolInterface
の優先目的は呼び出しライブラリからキーを受け付け、Cache\CacheItemInterface
オブジェクトを返却することです- キャッシュコレクションと対話することも重要ポイント
- プールの設定、初期化は実装ライブラリに任されます
CacheItemInterface
<?php namespace Psr\Cache; /** * CacheItemInterface defines an interface for interacting with objects inside a cache. */ interface CacheItemInterface { /** * Returns the key for the current cache item. */ public function getKey(); /** * Retrieves the value of the item from the cache associated with this object's key. */ public function get(); /** * Confirms if the cache item lookup resulted in a cache hit. */ public function isHit(); /** * Sets the value represented by this cache item. */ public function set($value); /** * Sets the expiration time for this cache item. */ public function expiresAt($expiration); /** * Sets the expiration time for this cache item. */ public function expiresAfter($time); }
CacheItemPoolInterface
<?php namespace Psr\Cache; /** * CacheItemPoolInterface generates CacheItemInterface objects. */ interface CacheItemPoolInterface { /** * Returns a Cache Item representing the specified key. */ public function getItem($key); /** * Returns a traversable set of cache items. */ public function getItems(array $keys = array()); /** * Confirms if the cache contains specified cache item. */ public function hasItem($key); /** * Deletes all items in the pool. */ public function clear(); /** * Removes the item from the pool. */ public function deleteItem($key); /** * Removes multiple items from the pool. */ public function deleteItems(array $keys); /** * Persists a cache item immediately. */ public function save(CacheItemInterface $item); /** * Sets a cache item to be persisted later. */ public function saveDeferred(CacheItemInterface $item); /** * Persists any deferred cache items. */ public function commit(); }
パフォーマンスアップには、各種キャッシュが欠かせません。
しかし、そのキャッシュの処理がライブラリごとにバラバラだと何かと面倒なことが起こります。
また共通化がされていないと、キャッシュに使うサービスもmemcached,redis,fileなどなど切り替えたりするのも面倒です。
そこでインターフェースを合わせましょうっていう流れかと。
目標的にはPSR-3(Logger Interface)と同じような感じですね!
しかしざっと主要なフレームワークを見ると現状は必ずしも実装されているわけではない模様・・・
ぱっと見symfonyぐらいでしょうか。。。
GitHub - symfony/cache: [READ-ONLY] Subtree split of the Symfony Cache Component
単にkey/valで欲しいだけなので、pool -> item obj -> valはちょっと遠回りな印象
これの簡略版がPSR-16(Simple Cache)として提案されています
PSR-16: Common Interface for Caching Libraries - PHP-FIG
次はPSR-7(HTTP Message Interface)へ・・・
PSR-4(Autoloading Standard)を見ていく
要約ですので、所々省いている箇所あります。
オリジナルはこちら
概要
- ファイルパスからクラスを
autoloading
する仕様 PSR-0
も含め、その他のautoloading
の仕様と相互運用可能- このPSRは
autoloading
されるためのファイルを配置する場所も記述している
仕様
class
はクラス、インターフェース、トレイトなどの構造を指す- 完全修飾クラス名は下記の形式
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
- 完全修飾クラス名は、
vendor namespace
で知られるトップレベルのネームスペースを持っていないといけません - 完全修飾クラス名は、1つ以上のサブネームスペースを持ってもよい
- 完全修飾クラス名は、最後にクラス名をもたないといけない
- アンダースコアは完全修飾クラス名の中で特別な意味を持ちません
- 完全修飾クラス名は大文字/小文字組み合わせてもよい
- すべてのクラス名は大文字/小文字区別します
- 完全修飾クラス名は、
- 完全修飾クラス名に対応するクラス名をロードする時は、
- オートローダーの実装では
exceptions
をthrowしてはいけない。どのレベルのエラーも出してはいけない。戻り値も返すべきではありません
Examples
FULLY QUALIFIED CLASS NAME | NAMESPACE PREFIX | BASE DIRECTORY | RESULTING FILE PATH |
---|---|---|---|
\Acme\Log\Writer\File_Writer | Acme\Log\Writer | ./acme-log-writer/lib/ | ./acme-log-writer/lib/File_Writer.php |
\Aura\Web\Response\Status | Aura\Web | /path/to/aura-web/src/ | /path/to/aura-web/src/Response/Status.php |
\Symfony\Core\Request | Symfony\Core | ./vendor/Symfony/Core/ | ./vendor/Symfony/Core/Request.php |
\Zend\Acl | Zend | /usr/includes/Zend/ | /usr/includes/Zend/Acl.php |
- PSR4を実装したクラス例
Example Implementations of PSR-4 - PHP-FIG
- cakephpは↑のをほぼそのまま使っている模様
cakephp/ClassLoader.php at master · cakephp/cakephp · GitHub
- Codeigniter4のPSR4を実装したAutoloader
CodeIgniter4/Autoloader.php at develop · bcit-ci/CodeIgniter4 · GitHub
その昔PEARなどはライブラリを中央ディレクトリにイントールして使用していましたが、composerの登場により各プロジェクトごとにパッケージとして使うようになりました。
また名前空間のなかった時代の名残としてクラス名に'_‘で区切って擬似的に名前空間を作っていたり煩雑になったのを共通化しようよって感じかと!
PSR-5(PHPDoc Standard)はDRAFTなので、次はPSR-6(Caching Interface)へ・・・
PSR-3(Logger Interface)を見ていく
要約ですので、所々省いている箇所あります。
オリジナルはこちら
概要
- ロギングライブラリの共通インターフェースのドキュメント
- ゴールはライブラリが
Psr\Log\LoggerInterface
を受け入れることでログ出力をシンプルかつ共通化を行う - フレームワーク、CMSは必要によってインターフェースを拡張してもよいが、インターフェースを遵守しなければいけない
- こうすることでサードパーティライブラリでもログを集約することができる
仕様
基礎
LoggerInterface
は8個のメソッドを提供し、レベルは8個(debug, info, notice, warning, error, critical, alert, emergency)- 9番目のメソッド
log
は第一引数にログレベルを受け取る。ログレベル定数の一つを受け取ったメソッドの結果は、各レベルごとのメソッドの結果と同じでなければならない - 定義されていないレベルを引数として受け取った場合、
Psr\Log\InvalidArgumentException
をthrowしなければならない - ユーザはカスタムレベルを使うべきではありません
メッセージ
- 各メソッドはメッセージとして
string
か、__toString()
を持つオブジェクトを受け取る。 - 実装者はオブジェクトを何らかハンドリングしてもよいですが、そのケースではない時は、
string
にキャストしなければいけません - メッセージは配列の値から置換できるプレースホルダーを含んでもよい
- プレースホルダーの命名は配列のキーと一致しなければならない
- プレースホルダーは
{}
で囲まないといけない。囲んでいる中にホワイトスペースを入れてはいけない - プレースホルダーは
A-Z, a-z, 0-9, _, .
だけを使うべき。それ以外は今後のプレースホルダー仕様変更用に予約されています - 実装者は、プレースホルダーを表示用にエスケープ、翻訳してもよい。ユーザは事前にプレースホルダーの値をエスケープすべきではない。
プレースホルダーの例
/** * Interpolates context values into the message placeholders. */ function interpolate($message, array $context = array()) { // build a replacement array with braces around the context keys $replace = array(); foreach ($context as $key => $val) { // check that the value can be casted to string if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { $replace['{' . $key . '}'] = $val; } } // interpolate replacement values into the message and return return strtr($message, $replace); } // a message with brace-delimited placeholder names $message = "User {username} created"; // a context array of placeholder names => replacement values $context = array('username' => 'bolivar'); // echoes "User bolivar created" echo interpolate($message, $context);
Context
- 各メソッドは、配列をコンテキストデータとして受け取る
- これはストリングでは表現できない補足情報を持たせることを意味します
- 実装者はコンテキストデータを出来る限り寛大に扱わなければいけない
コンテキストデータによって、exceptionをthrowしたり、エラー、ワーニング等々を出してはいけない
もしExceptionオブジェクトがコンテキストデータで渡された時、それは
exception
キーの中になければいけない- exceptionのロギングは共通パターンにすることで、実装者はexceptionからスタックトレースを抽出することができます
- 実装者はexceptionキーの値が実際に
Exception
か検証しなければいけません
ヘルパークラスとインターフェース
Psr\Log\AbstractLogger
クラスを継承することで簡単にLoggerInterface
と、汎用のlog
を提供します- 同様に
Psr\Log\LoggerTrait
を使うことで実装がするのは汎用のlog
メソッドだけです - しかしtraitsはインターフェースを実装せきないため、この場合は
LoggerInterface
を実装する必要があります Psr\Log\NullLogger
はインターフェースと共に提供されます。これはユーザによってログがいらない場合にブラックホール用のインターフェースを提供します。しかしコンテキストデータの生成コストがかかる場合は条件付きロギングの方が良いですPsr\Log\LoggerAwareInterface
はsetLogger(LoggerInterface $logger)
メソッドのみ含み、任意のインスタンスをロガーで接続するフレームワークで使用できますPsr\Log\LoggerAwareTrait
トレイトはどのクラスでも簡単に等価なインターフェースを提供します。$this->logger
でアクセスできますPsr\Log\LogLevel
は8個のログレベルを定数として持っています
色々composer経由で各種ライブラリを組み合わせて作るのが主流になっているので、その際個別にログ出力を実装しているとフォーマット、ディレクトリ等々バラけてしまいます。 またログレベルがバラバラだと環境別に出力の設定をしたい時個別にそれぞれしないといけません。
そこのインターフェース揃えれば、共通化できるし、差し替えも可能って感じかと!
PSR-4(Autoloader)へ続く・・・
PSR-2(Coding Style Guide)を見ていく
要約ですので、所々省いている箇所あります。
オリジナルはこちら
要点
PSR-2はPSR-1を継承/拡張した基本的なコーディング基準
開発者間でのコードリーディング時の認識のズレを減らすためのガイドライン
ルール自体にではなく、ルールを共有することに意味がある
概要
“coding style guide” PSR [PSR-1]
を守る- インデントは4スペース
- 1行内の文字数は上限はないが、120文字以内、できれば80文字以内に収める
namespace
の宣言後には空行を、use
宣言ブロックの後にも空行入れる- classの開きブレースは次の行に、閉じブレースはボディ最後の次の行に
- methodの開きブレースは次の行に、閉じブレースはボディ最後の次の行に
- property と methodには必ずアクセス修飾子を。
abstract
とfinal
はアクセス修飾子に前に、static
はアクセス修飾子の後ろに - 制御構造の後には1スペース、メソッド呼び出しの場合は除く
- 制御構造の開きブレースは同じ行で、閉じブレースはボディ最後の次の行で
- 制御構造の開き丸括弧の後にはスペースを置かない、閉じ丸括弧の前にはスペースを置かない
例としてはこちら
<?php namespace Vendor\Package; use FooInterface; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class Foo extends Bar implements FooInterface { public function sampleMethod($a, $b = null) { if ($a === $b) { bar(); } elseif ($a > $b) { $foo->bar($arg1); } else { BazClass::bar($arg2, $arg3); } } final public static function bar() { // method body } }
全般
ファイル
- 改行は
Unix LF
- ファイル最後には空行を
?>
の閉じタグは不要
行
- 行末、空行にスペースは不要
- 1行に複数のステートメントは持たない
phpキーワード、True/False/Null
- phpキーワード、
true
,false
,null
は小文字で
methodの引数
- 引数リストはの
,
の後にはスペースを - 引数にデフォルト値があるものは最後に
- 引数を複数行にする場合は開き丸括弧の後に改行し、各行に1つずつ
PSR-3(Logger Interface)へ続く・・・ ここからが本番・・・
PSR-1(Basic Coding Standard)を見ていく
諸々あってPSRを順番に確認していく・・・!
オリジナルはこちら
概要
<?php
と<?=
タグのみ使用。閉じタグはなし- UTF-8 BOMなし
- シンボル(クラス、関数、定数)を宣言するファイルと副作用のあるもの(出力、iniの変更など)は分ける
namespace
,クラス名は“autoloading” PSR: [PSR-0, PSR-4]
に従う- クラス名は、
StudlyCaps
(単語の先頭文字を大文字。UpperCamelCase
?)で定義(ex:FooBarHogeClass
) - クラス定数は大文字で、区切りはアンダースコアで定義
- メソッド名は
camelCase
で定義
ちょっと気になったもの
- シンボル(クラス、関数、定数)を宣言するファイルと副作用のあるもの(出力、iniの変更など)は分ける
例としては下記のようなものが上げられていました。
副作用あるもの、設定と実装は分けましょう的な感じかと
<?php // side effect: change ini settings ini_set('error_reporting', E_ALL); // side effect: loads a file include "file.php"; // side effect: generates output echo "<html>\n"; // declaration function foo() { // function body }
↓
<?php // declaration function foo() { // function body } // conditional declaration is *not* a side effect if (! function_exists('bar')) { function bar() { // function body } }
- クラス名は、
StudlyCaps
(単語の先頭文字を大文字。UpperCamelCase
?)で定義(ex:FooBarHogeClass
)
StudlyCaps
は元々?は大文字小文字が入り乱れるようなのですが、ここでは実質UpperCamelCase
と同義だと思われ。
PSR-2へ続く・・・
「英語は1年でマスターできる」を読んだ
【新書版】海外経験ゼロでも仕事が忙しくても「英語は1年」でマスターできる (PHPビジネス新書)
- 作者: 三木雄信
- 出版社/メーカー: PHP研究所
- 発売日: 2016/12/17
- メディア: 新書
- この商品を含むブログを見る
最近、英語の勉強を本格的に始めてます。
海外旅行の時にローカルな所行きたい、海外カンファレンス行きたい、英語LTしたい、ワンチャン海外で働きたい、 そもそもgithub,ドキュメントとかさくっと読みたいとかとかが動機です。
まずは英語のpodcast聞いたり、英会話クラス行き始めています。
しかしそれだけだと明確な進捗が測りづらく計測の仕方を考えないといけないなと感じていました。少しずつ英語に慣れてきた気はするんですが・・・
そんな時に立ち寄った本屋に平積みされていた「英語は1年でマスターできる」を読んでみました。
概要
英語での交渉に同席した時、全く会話が理解出来ていない事で、「このままではクビにされる!」という所から1年で英語で交渉できるまで上達するまでに行ったことが紹介されています。
印象に残った事
- 英語で何をしたいか明確にする
- 勉強するのは、そのために必要なことのみに絞る
- ex : 英語での交渉が目的なら、カジュアルな言い回し/雑談/発音/ライティングは切り捨てるなど
- 意思疎通できればよいので、簡単な単語だけでよい。複数の言い回しは不要
- 1000時間勉強すれば、必ず英語ができるようになる。だいたい1日3時間
- そのために英語を勉強する時間が固定化してスケジューリング
- リスニングは映画を英語テキストでシャドーイングが効果的
- 映画は自分が英語でやりたいシーンに近いものを選び、1つのものを徹底的に
自分に置き換えて考えてみる
感想としては、かなり腹オチしました!
ちょうど英語を勉強し始めたものの英語力が上がっているかどうか、このままで上がっていくのか不安に感じていました。 なので、
- 目的を絞る。それ以外は二の次
- 意思疎通が目的なので、微妙な言い回しをする必要はない
- 単語はすでに知っているもので事足りる
というのはかなり納得感がありました。
ちょうどrebuildでも細かい言い回しする必要なんてないよねっていう話も出ていました。
早速自分に置き換えて実践してみようと思います。
英語を学んで何をしたいか目的を明確にする
冒頭にある通り、英語でエンジニアリングの話ができるようになるっていうのが最大の目的です。 なので、フォーカスすべきはリスニング、スピーキングになります。
微妙な言い回し、ライティング、リーディングは切り捨て対象です。
スピーキング強化のために
この本を読む前からですが、ビジネスシーンを対象とした英会話クラスに申し込みました。
テキストを見る限り、面接/プレゼン/仕事の依頼の仕方などの時に使うフレーズが中心なので、 ちょうど本の中にもあった、「目的のシチュエーションに沿ったスピーキング」が経験できそうです。
リスニング強化のために
本にあった通り、自分の目標のシチュエーションに近い映画を、英語テキストでシャドーイングしまくるという事をやってみようかと。
エンジニア系の映画という事で真っ先思いついたのは「ソーシャルネットワーク」でした。 次に英語のテキストを手に入れようと手に入れようと、文中にもあったスクリーンプレイを見てみました。
しかし肝心の「ソーシャルネットワーク」のテキストがありませんでした><
ですが、ググると普通にpdfで公開されていましたw
http://flash.sonypictures.com/video/movies/thesocialnetwork/awards/thesocialnetwork_screenplay.pdf
とは言え、164ページ印刷するのは流石に億劫なんで英語字幕のあるもの動画で行うことにしました。
itunes,amazon primeは英語字幕が現時点では非対応でしたので、netflixを利用することにしました。 netflixは英語コンテンツも豊富で字幕設定/データのDLができます。 またiphoneだと10秒のみ巻き戻せるので聞き取りづらい所も繰り返し再生することができます。
なので、通勤時間を利用してリスニング、シャドーイングしていこうと思います。
まずはこれら実践してみます! そして一ヶ月後くらいに上記を振り返りしてみようかと!
余談
とにかく英語に触れる機会を増やそうということで、PCやサイトの言語設定を諸々英語にしてみました。
けっこうこれだけでも雰囲気変わるので意識付けとしていい感じです。
あとサイトによっては、
.jpではログインできるのに、英語設定だと.comにつながってログインできないものがあったりしました。アカウントの持ち方が別々なのかなーと。
これまで多言語対応したものを実装した経験がないので、自分だったらどう実装するかなーとか考えるきっかけになって面白かったです。