恥知らずのウェブエンジニア -web engineer, shameless

これは一歩を踏み出すことができない者たちのブログ

wifi無線ルーターをTP-Link Archer C7に買い換えて快適になった

以前は5、6年前に買ったバッファローの無線ルーターを使っていて、特に大きな不便もなかったのですが、amazon prime,netflixを見たり、アプリダウンロードが遅かったりでどうにかならないものかなと考えていました。

でもどれが良いかよくわかんないしなーっと思っていたところ↓のpodcastTP-Link Archer C7がいけてると紹介でありました。

cloudinfra.audio

https://www.amazon.co.jp/gp/product/B071D6H9NK

podcastの内容自体もすごく面白かったのですが、
box社のセキュリティがすごいというくだりでboxが使っているソフトウェアなら信用できるという話があり、それに習って情シスの人が言っているならと思い買ってみました。
ちょうどその時タイムセールにもなっており…

f:id:ogataka50:20170611162502j:plain

設定自体は専用のアプリを使うとすぐできました。
ブラウジング、動画の再生、ダウンロードなどなど体感的にわかるぐらい速くなりました!

というわけでよくわかっていないものに関してまずは専門家に従っていこうかとw

PSR-6(Caching Interface)を見ていく

要約ですので、所々省いている箇所あります。

オリジナルはこちら

www.php-fig.org

導入

  • キャッシングはパフォーマンス向上の一般的な手法です。キャッシングライブラリを実装することはフレームワーク、ライブラリの一般機能の1つです
  • これは複数のライブラリがそれぞれ独自のレベルの機能をもったキャッシングライブラリを持つ状態を招きます。これらの差異によって、開発者に必要/不必要に関係なく複数システムを学ばなければいけません
  • 加えて、キャッシングライブラリの開発者は、限られたフレームワークのみサポートするか、多数のアダプタクラスを実装するかの選択に迫られます。

  • キャッシングシステムの共通インターフェースはそれらの問題を解決します。ライブラリ、フレームワーク開発者は、希望する動作のライブラリを利用できます。

  • キャッシングライブラリ開発者は1つのインターフェースを実装するだけでよい。

ゴール

  • このPSRのゴールは、開発者がカスタマイズの必要なく、既存のフレームワーク、システムにキャッシングライブラリを統合できるようにすることです

定義

ライブラリ呼び出し

  • ライブラリ、コードはキャッシュサービスを必要とします。
  • ライブラリはこの標準インターフェースを実装することでキャッシングサービスを利用することができますが、キャッシングサービスの実装知識は必要ありません

ライブラリの実装

  • こにライブラリは、どんなライブラリにもキャッシングサービスを提供するためこの標準を実装する責任がある
  • 実装ライブラリは、Cache\CacheItemPoolInterfaceCache\CacheItemInterfaceを実装するクラスを提供しなければいけない
  • 実装ライブラリは、下記に記載する最小TTLを秒単位でサポートしなければならない

TTL

  • キャッシュアイテムの生存時間(TTL - The Time To Live)はキャッシュされてから失効するまで時間のこと
  • TTLは通常、intの秒数またはDateIntervalで定義する

有効期限

  • キャッシュアイテムが失効する時の時刻
  • これはキャッシュされた時刻に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
  • 全てのデータは実装ライブラリに渡された形のまま、型も含め返却されなければいけない

  • 実装ライブラリは、内部的にPHPserialize()/unserialize()を使って良い、これは必須ではない
  • なんらかの理由で正確な値が返却できない場合、実装ライブラリは破損したデータを返すより、キャッシュミスを返さなければいけない

Key Concepts

Pool

  • プールはキャッシュシステム内のアイテムの集合を表す。プールはすべてのアイテムが含まれる論理的なリポジトリ
  • すべてのキャッシュ可能なアイテムはプールからアイテムオブジェクトとして検索され、すべてのキャッシュオブジェクトはプールを介して対話する

Items

  • アイテムはプール内の単一のkey/valueのペアを表す。keyはアイテムのユニークな識別子で、不変でなければいけない。値はいつでも変更あってもよい

Error handling

  • キャッシングはパフォーマンスにとって重要ですが、アプリケーション機能の重要な部分ではありません。なので、キャッシュシステムのエラーはアプリケーションのエラーになるべきではありません
  • 実装ライブラリは、インターフェースで定義された以上のexceptionをthrowしてはいけません。そしてキャッシュシステムでのエラーをトラップして上げるべきではありません

  • 実装ライブラリはそのようなログはエラーをログに残すか管理者に報告すべきです

  • もし呼び出しライブラリが1つかそれ以上の削除済みか、プールがクリアさてれいるアイテムをリクエストされ、キーが存在しない場合でもエラーとしてはいけません

Interfaces

CacheItemInterface

  • CacheItemInterfaceはキャッシュシステム内のアイテムを定義
  • 各アイテムオブジェクトは特定のキーに関連付けられていなければなりません。通常はCache\CacheItemPoolInterfaceオブジェクトによって渡されます。
  • Cache\CacheItemPoolInterfaceはキャッシュアイテムの格納、検索をカプセル化します
  • どのCache\CacheItemInterfaceCache\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-7: HTTP message interfaces - PHP-FIG

PSR-4(Autoloading Standard)を見ていく

要約ですので、所々省いている箇所あります。

オリジナルはこちら

www.php-fig.org

概要

  • ファイルパスからクラスをautoloadingする仕様
  • PSR-0も含め、その他のautoloadingの仕様と相互運用可能
  • このPSRはautoloadingされるためのファイルを配置する場所も記述している

仕様

  1. classはクラス、インターフェース、トレイトなどの構造を指す
  2. 完全修飾クラス名は下記の形式 \<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
    1. 完全修飾クラス名は、vendor namespaceで知られるトップレベルのネームスペースを持っていないといけません
    2. 完全修飾クラス名は、1つ以上のサブネームスペースを持ってもよい
    3. 完全修飾クラス名は、最後にクラス名をもたないといけない
    4. アンダースコアは完全修飾クラス名の中で特別な意味を持ちません
    5. 完全修飾クラス名は大文字/小文字組み合わせてもよい
    6. すべてのクラス名は大文字/小文字区別します
  3. 完全修飾クラス名に対応するクラス名をロードする時は、
    1. 完全修飾クラス名の先頭のネームスペースとサブネームスペース(ネームスペースプリフィックス)がベースディレクトリに対応します
    2. ネームスペースプリフィックス以後のサブネームスペースはベースディレクトリ内のサブディレクトリに対応します。ネームスペースのセパレータはディレクトリのセパレータに対応します。サブディレクトリ名はサブネームスペース名に大文字小文字含め対応しないといけない
    3. 最後のクラス名は.phpで終わるファイル名に対応します。ファイル名は大文字小文字含め最後のクラス名に対応していないといけません
  4. オートローダーの実装では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-6: # Introduction - PHP-FIG

PSR-3(Logger Interface)を見ていく

要約ですので、所々省いている箇所あります。

オリジナルはこちら

www.php-fig.org

概要

  • ロギングライブラリの共通インターフェースのドキュメント
  • ゴールはライブラリが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\LoggerAwareInterfacesetLogger(LoggerInterface $logger)メソッドのみ含み、任意のインスタンスをロガーで接続するフレームワークで使用できます
  • Psr\Log\LoggerAwareTraitトレイトはどのクラスでも簡単に等価なインターフェースを提供します。$this->loggerでアクセスできます
  • Psr\Log\LogLevelは8個のログレベルを定数として持っています

色々composer経由で各種ライブラリを組み合わせて作るのが主流になっているので、その際個別にログ出力を実装しているとフォーマット、ディレクトリ等々バラけてしまいます。 またログレベルがバラバラだと環境別に出力の設定をしたい時個別にそれぞれしないといけません。

そこのインターフェース揃えれば、共通化できるし、差し替えも可能って感じかと!

PSR-4(Autoloader)へ続く・・・

PSR-4: Autoloader - PHP-FIG

PSR-2(Coding Style Guide)を見ていく

要約ですので、所々省いている箇所あります。

オリジナルはこちら

www.php-fig.org

要点

PSR-2はPSR-1を継承/拡張した基本的なコーディング基準

開発者間でのコードリーディング時の認識のズレを減らすためのガイドライン

ルール自体にではなく、ルールを共有することに意味がある

概要

  • “coding style guide” PSR [PSR-1]を守る
  • インデントは4スペース
  • 1行内の文字数は上限はないが、120文字以内、できれば80文字以内に収める
  • namespaceの宣言後には空行を、use宣言ブロックの後にも空行入れる
  • classの開きブレースは次の行に、閉じブレースはボディ最後の次の行に
  • methodの開きブレースは次の行に、閉じブレースはボディ最後の次の行に
  • property と methodには必ずアクセス修飾子を。abstractfinalはアクセス修飾子に前に、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
  • ファイル最後には空行を
  • ?>の閉じタグは不要

phpキーワード、True/False/Null

  • phpキーワード、true, false, nullは小文字で

methodの引数

  • 引数リストはの,の後にはスペースを
  • 引数にデフォルト値があるものは最後に
  • 引数を複数行にする場合は開き丸括弧の後に改行し、各行に1つずつ

PSR-3(Logger Interface)へ続く・・・ ここからが本番・・・

PSR-3: Logger Interface - PHP-FIG

PSR-1(Basic Coding Standard)を見ていく

諸々あってPSRを順番に確認していく・・・!

オリジナルはこちら

www.php-fig.org

概要

  • <?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と同義だと思われ。

Studly caps - Wikipedia

PSR-2へ続く・・・

PSR-2: Coding Style Guide - PHP-FIG

「英語は1年でマスターできる」を読んだ

最近、英語の勉強を本格的に始めてます。

海外旅行の時にローカルな所行きたい、海外カンファレンス行きたい、英語LTしたい、ワンチャン海外で働きたい、 そもそもgithub,ドキュメントとかさくっと読みたいとかとかが動機です。

まずは英語のpodcast聞いたり、英会話クラス行き始めています。

しかしそれだけだと明確な進捗が測りづらく計測の仕方を考えないといけないなと感じていました。少しずつ英語に慣れてきた気はするんですが・・・

そんな時に立ち寄った本屋に平積みされていた「英語は1年でマスターできる」を読んでみました。

概要

筆者はソフトバンク孫正義社長の秘書をしていた方です。

英語での交渉に同席した時、全く会話が理解出来ていない事で、「このままではクビにされる!」という所から1年で英語で交渉できるまで上達するまでに行ったことが紹介されています。

印象に残った事

  • 英語で何をしたいか明確にする
  • 勉強するのは、そのために必要なことのみに絞る
    • ex : 英語での交渉が目的なら、カジュアルな言い回し/雑談/発音/ライティングは切り捨てるなど
  • 意思疎通できればよいので、簡単な単語だけでよい。複数の言い回しは不要
    • 1000時間勉強すれば、必ず英語ができるようになる。だいたい1日3時間
    • そのために英語を勉強する時間が固定化してスケジューリング
  • リスニングは映画を英語テキストでシャドーイングが効果的
    • 映画は自分が英語でやりたいシーンに近いものを選び、1つのものを徹底的に

自分に置き換えて考えてみる

感想としては、かなり腹オチしました!

ちょうど英語を勉強し始めたものの英語力が上がっているかどうか、このままで上がっていくのか不安に感じていました。 なので、

  • 目的を絞る。それ以外は二の次
  • 意思疎通が目的なので、微妙な言い回しをする必要はない
  • 単語はすでに知っているもので事足りる

というのはかなり納得感がありました。

ちょうどrebuildでも細かい言い回しする必要なんてないよねっていう話も出ていました。

rebuild.fm

早速自分に置き換えて実践してみようと思います。

英語を学んで何をしたいか目的を明確にする

冒頭にある通り、英語でエンジニアリングの話ができるようになるっていうのが最大の目的です。 なので、フォーカスすべきはリスニング、スピーキングになります。

微妙な言い回し、ライティング、リーディングは切り捨て対象です。

スピーキング強化のために

この本を読む前からですが、ビジネスシーンを対象とした英会話クラスに申し込みました。

テキストを見る限り、面接/プレゼン/仕事の依頼の仕方などの時に使うフレーズが中心なので、 ちょうど本の中にもあった、「目的のシチュエーションに沿ったスピーキング」が経験できそうです。

リスニング強化のために

本にあった通り、自分の目標のシチュエーションに近い映画を、英語テキストでシャドーイングしまくるという事をやってみようかと。

エンジニア系の映画という事で真っ先思いついたのは「ソーシャルネットワーク」でした。 次に英語のテキストを手に入れようと手に入れようと、文中にもあったスクリーンプレイを見てみました。

www.screenplay.jp

しかし肝心の「ソーシャルネットワーク」のテキストがありませんでした><
ですが、ググると普通にpdfで公開されていましたw

http://flash.sonypictures.com/video/movies/thesocialnetwork/awards/thesocialnetwork_screenplay.pdf

とは言え、164ページ印刷するのは流石に億劫なんで英語字幕のあるもの動画で行うことにしました。

itunes,amazon primeは英語字幕が現時点では非対応でしたので、netflixを利用することにしました。 netflixは英語コンテンツも豊富で字幕設定/データのDLができます。 またiphoneだと10秒のみ巻き戻せるので聞き取りづらい所も繰り返し再生することができます。

なので、通勤時間を利用してリスニング、シャドーイングしていこうと思います。

www.netflix.com

まずはこれら実践してみます! そして一ヶ月後くらいに上記を振り返りしてみようかと!

余談

とにかく英語に触れる機会を増やそうということで、PCやサイトの言語設定を諸々英語にしてみました。

けっこうこれだけでも雰囲気変わるので意識付けとしていい感じです。

あとサイトによっては、
.jpではログインできるのに、英語設定だと.comにつながってログインできないものがあったりしました。アカウントの持ち方が別々なのかなーと。
これまで多言語対応したものを実装した経験がないので、自分だったらどう実装するかなーとか考えるきっかけになって面白かったです。