著者アーカイブ 杉浦

著者:杉浦

ソースコード間の関わりをシンプルにするFacadeパターン

Facade パターン – Wikipedia
 Facadeパターンはプログラミングのデザインパターンの一つです。Facadeは建物の正面を意味する語で、Facadeパターンは建物全体でなく正面だけを見ればよいようにコーディングを行う方法です。もし多数のクラス、関数、データが協調するプログラムを記述する際、すべてを同等に扱ったり散らかったままにすると、どこから何をどの手順で取ってくるのが良い方法か分かりにくくなります。ひどいことに、このクラスを呼ぶ前にはこの関数とあの関数をあらかじめ使っておき、データをどうこう加工しておく必要がある、なんてことにもなります。そういった事態を避けるために、モジュール間のやり取りをシンプルにする窓口を作るというのがFacadeパターンです。次の図は増補改訂版Java言語で学ぶデザインパターン入門に載っているFacadeパターンのクラス図です。ClientがシンプルなFacadeクラスという窓口を介することでClassA~Dを楽に扱えます。
 
 Laravelにはファサードという仕組みがあります。
ファサード 5.7 Laravel
 このファサードの中身を見ていくとFacadeパターンを体現しています。例えばAuthファサードは次です。雑多なAuth関連クラスである@see以下の4つをまとめ上げて、21の関数のアクセス方法を見せています。これを使うことが出来ると大変わかりやすく、便利です。これを使わず雑に、@see以下を読んでは継承で上書きしてテスト、読んでは上書きしてテスト、を繰り返すコーディングをするとあっという間に難解なコードになり後の修正やリファクタリングがとても面倒になります。

/**
 * @method static mixed guard(string|null $name = null)
 * @method static void shouldUse(string $name);
 * @method static bool check()
 * @method static bool guest()
 * @method static \Illuminate\Contracts\Auth\Authenticatable|null user()
 * @method static int|null id()
 * @method static bool validate(array $credentials = [])
 * @method static void setUser(\Illuminate\Contracts\Auth\Authenticatable $user)
 * @method static bool attempt(array $credentials = [], bool $remember = false)
 * @method static bool once(array $credentials = [])
 * @method static void login(\Illuminate\Contracts\Auth\Authenticatable $user, bool $remember = false)
 * @method static \Illuminate\Contracts\Auth\Authenticatable loginUsingId(mixed $id, bool $remember = false)
 * @method static bool onceUsingId(mixed $id)
 * @method static bool viaRemember()
 * @method static void logout()
 * @method static \Symfony\Component\HttpFoundation\Response|null onceBasic(string $field = 'email',array $extraConditions = [])
 * @method static null|bool logoutOtherDevices(string $password, string $attribute = 'password')
 * @method static \Illuminate\Contracts\Auth\UserProvider|null createUserProvider(string $provider = null)
 * @method static \Illuminate\Auth\AuthManager extend(string $driver, \Closure $callback)
 * @method static \Illuminate\Auth\AuthManager provider(string $name, \Closure $callback)
 *
 * @see \Illuminate\Auth\AuthManager
 * @see \Illuminate\Contracts\Auth\Factory
 * @see \Illuminate\Contracts\Auth\Guard
 * @see \Illuminate\Contracts\Auth\StatefulGuard
 */
class Auth extends Facade
著者:杉浦

Date.prototype.getDate()と動的な日付候補を持つプルダウン

Date.prototype.getDate() | MDN
 Date.prototype.getDate()はDateオブジェクトの日を返します。これだけならば便利な関数で終わるのですがJavaScriptのDateオブジェクトの持つ月日の形式の特徴によりもっと便利な使い方が出来ます。
 JavaScriptのDateオブジェクトは月日を循環する形で持ちます。これは下の画像の様に最終日、最終月をまたぐとまた1から始まるというものです。

 この循環を用いると次の様に1の一つ前である0を指定することで月ごとの最終日を取得できます。

 この最終日を取得する方法によって次の様に任意の日付のリストを取得できます。

    /**
     * 現状態の年月のselect用日付リストをゲット
     * @return {{day: *, selected: boolean}[]}
     */
    getDays: function() {
      const days = [null]; // 未選択状態を定義
      // 最終日、転じてその月の日数
      const daysNumberOfMonth = new Date(this.selectedYear, this.selectedMonth, 0).getDate();
      // 選択候補の配列を作成
      for (let i = 1; i < daysNumberOfMonth + 1; i++) {
        days.push(i);
      }

      // select用に{day: *, selected: boolean}の形に加工
      // 現状態で選択されている日が新たな年月でも選べるならば選択状態を維持
      return days.map((day) => {
        return {day, selected: days === this.selectedDay};
      });
    },

 このコードと現状態に合わせて描画を変更するイベントを用いることで次のプログラムの様に選択された年月によって日の選択範囲を動的に変更するプルダウンが作れます。

著者:杉浦

多様な言語のチートシートページDevhints

Devhints — TL;DR for developer documentation
 Devhintsは様々な言語、プログラムの基本的な書き方の例文が載っているページです。開発中の「あれはこの言語であっただろうか」「何かいい感じの書き方用意されてないか」「忘れた」といった時にチラっと見ることのできるヒント集になります。DevhintsにはC++の例文、vimの操作方法、firefoxの過去バージョンへのリンクなど様々ありますが、大体役に立つのはプログラミング言語の例文とCLIの操作例です。
 Devhintsに載っているコードはいかにもヒントな印象で簡易なものです。次はVue.jsに関するチートシートの一部です。

new Vue({
  data: { ... }
  props: ['size'],
  props: { size: Number },
  computed: { fullname() { return this.name + ' ' + this.lastName } },
  methods: { go() { ... } },
  watch: { a (val, oldVal) { ... } },
  el: '#foo',
  template: '...',
  replace: true, // replace element (default true)

  // lifecycle
  created () {},
  beforeCompile () {},
  compiled () {},
  ready () {}, // $el is inserted for the first time
  attached () {},
  detached () {},
  beforeDestroy () {},
  destroyed () {},

  // options
  directives: {},
  elementDirectives: {},
  filters: {},
  components: {},
  transitions: {},
  partials: {}
})

 とても端的です。これを最初に読むには説明がまるで足りていませんが、思い出す時、調べるきっかけになる何かの機能の名前を知りたい時にはあっという間に読める文量のこれぐらいが便利です。

著者:杉浦

Vue.jsのライブラリ集Vue.js Examples

Vue.js Examples
 Vue.js ExamplesはVue.jsのライブラリ集です。npmやgitからvue関連のライブラリをまとめています。特長はデモへのリンクと絞り込まれたタグです。
 検索結果の時点で画面がやかましいくらいのgifデモとデモページが用意されていた場合そこへのリンクがあり、どんなライブラリなのか簡単にわかる様になっています。

 npmにもタグ相当のキーワードはありますが雑多でなかなか上手く絞り込めません。Vue.js Examplesならばあらかじめ用意されたカテゴリにから探せばよく、目当てのものにたどり着きやすいです。また、各カテゴリの件数は多くとも100件程度なので使用するライブラリの調査もそう辛くないです。
 
 Vue.js Examplesから辿れるライブラリ等はnpmに負けず劣らずピンキリな出来で、思わぬ副作用あり、バグ疑惑あり、英語ですらないドキュメントのコードというのが少なくないです。そのため都度ソースコードを探る必要がありますがそう悲惨なことにはなりにくいです。多くはコンポーネントレベルのライブラリであり、コンポーネントレベルのものならばVueの恩恵を受け小さいコードで仕上がっているためです。

著者:杉浦

ダミー画像表示サイトlorempixelの紹介

lorempixel – placeholder images for every case
 lorempixelはurl指定するとダミーの画像を表示してくれるサイトです。urlの指定の仕方は次の画像の通り。urlを指定すればするほどオンリーワンな画像が表示されます。例はhttpプロトコルですがhttpsでもアクセスできます。

 例えば、https://lorempixel.com/400/200/animals/5/msgならば次の様に、横幅400px、縦幅200px、カテゴリanimalsの5番目の画像の左下にmsgの文字を入れた画像が返ってきます。

 webページを制作した時の画像確認においてカテゴリ分けが特に便利で仮のそれらしい画像をいくつも作る手間が省かれます。
 PHPのダミーデータ作成ライブラリfzaninotto/Faker: Faker is a PHP library that generates fake data for youにはlorempixelが組み込まれています

// Image generation provided by LoremPixel (http://lorempixel.com/)
imageUrl($width = 640, $height = 480) // 'http://lorempixel.com/640/480/'
imageUrl($width, $height, 'cats')     // 'http://lorempixel.com/800/600/cats/'
imageUrl($width, $height, 'cats', true, 'Faker') // 'http://lorempixel.com/800/400/cats/Faker'
imageUrl($width, $height, 'cats', true, 'Faker', true) // 'http://lorempixel.com/grey/800/400/cats/Faker/' Monochrome image

 Fakerが組み込まれているLaravelならばダミーデータ作成機能ファクトリに次の様にランダムURL生成を定義できます。

use Faker\Generator as Faker;

// あらかじめ使用する予定のカテゴリを定義
$category = ['abstract', 'animals', 'business', 'cats', 'city', 'food', 'nightlife', 'fashion', 'people', 'nature', 'sports', 'technics', 'transport'];
/* @var \Illuminate\Database\Eloquent\Factory $factory */
$factory->define(App\Models\Post::class, function (Faker $faker) use ($category) {
    $word = $faker->word; // 画像に記述する文字列をランダム生成
    return [
        'img_url' =>
            $faker->imageUrl(640, 480, $faker->randomElement($category), false) // https://lorempixel.com/640/480/{$categoryのどれか}/
            . $faker->numberBetween(1, 10) . '/' . $word, // 末尾に、1~10のいずれかと書き込む$wordを追加
    ];
});
著者:杉浦

オンラインPlantUMLエディタのPlantTextの紹介

PlantText UML Editor
 PlantTextはPlantUMLのオンラインエディタです。PlantUMLはUML図を容易に作図するための言語です。UMLとはUnified Modeling Language、統一モデリング言語の略でありUML図はUMLの記法に従った図です。フローチャート、クラス図、シーケンス図、状態遷移図などの様にモデルがどの様な構造でどの様にふるまうかを一定の規則でわかりやすく示します。次の図はあるイベントに参加するか否かのフローチャートのUML図です。

 長方形は処理、ダイヤは分岐、黒は処理のない始点、終点、通過点とわかれており、矢印はフローの方向を示し、UMLに従って作図するだけでわかりやすく仕上がります。UML図は便利ですが作図という性質上、まともに箱を書いて、丸を書いて、矢印を作って、と繰り返しているととても手間で面倒です。PlantUMLはUML図を容易に作図するために文字列だけを用います。
 PlantUMLの実行環境は様々です。大体IDEや多機能エディタには初期装備かプラグインかであります。PlantText UML EditorはPlantUMLのオンラインエディタです。先ほどの図は次の様に記述することで作図しました。

 画像右下のリンクにある様に画像として出力、テキストとして出力もできます。Editはコードの共有用です。先ほどのコードならばPlantTextの様にEditから飛ばされる先のリンクで共有できます。
 PlantUMLはUML用ですがER図もかなりそれらしいものが記述できます。下のリンクは読みやすかったPlantUMLの書き方です。
PlantUML Cheat Sheet – Qiita
PlantUML で ER 図(ERD)を描く(似非ではないです) – Qiita

著者:杉浦

任意のJSONを返すサーバーを簡単に作るJSON Serverの紹介

json-server – npm
 JSON ServerはJSONファイルに書いた内容をそのままJSONとしてレスポンスしてくれるHTTPサーバを簡単に立てるパッケージです。使い方は簡単。

npm install -g json-server

 でjson-serverをインストール。必要があればglobalでなくしてプロジェクトに入れておきます。次に、任意の場所に適当なjsonファイルを置きます。例えばdb,jsonというファイル名で次の内容が記述されたものをC:\tmpの中に入れておきます。

{
  "profile": { "name": "typicode" },
  "spot": [
    {"id":1, "X":-140987.23691179, "Y":-71607.046446965, "lat":34.726604791, "lng":137.718115230},
    {"id":2, "X":-140987.23691179, "Y":-71607.046446965, "lat":34.726604791, "lng":137.718115230}
  ]
}

 この状態で

json-server --watch C:\tmp\db.json

 とコマンドを打てば、これでjsonレスポンスを返すサーバーが立ちました。こうすると次の様な画面になります。

 Resourcesに定義したjsonへのURLが記述されています。この通りにアクセスすると次図の様にjson形式のレスポンスが返ってきます。

 watchというコマンドから連想できるようにjson-serverはjsonファイルを監視しています。記述を変える度に再起動する手間も必要なく便利です。APIに関連するテストモックなどでよく使えます。

著者:杉浦

バグの記録の仕方とテスト駆動開発

 プログラミングをする上でバグの発生は避けることが非常に困難な現象です。ほとんどの場合においてバグは発生したならば直す必要があります。バグが直ったことを確かめるためにはバグが再現する条件を見つける必要があります。バグが再現しなくなってようやく、ある条件において発生していた意図しない動作は発生しなくなった、と言えます。そのためバグの発見時の記録には、バグが再現するための条件、バグが直った場合の動作、がわかるための手がかりとなることが求められます。Matt Doar著のバグレポートの使い方には次の様にあります。

  • バグの再現方法(できるだけ詐しく)と発生頻度
  • 本来の仕様(バグがない場合の望ましい動作。こうあるべき、という自分の意見でかまわない)
  • 実際の動作(完全でなくても、自分の記録した範囲で詳しく書く)

 なぜバグが起きるのか、どうすれば直ったと言えるのかに必要な情報がまとまっています。テスト駆動開発という手法ではこれを元に自動テストを書き、それを適宜通すことで再発を防ぐ方法が唱えられています。これは3ステップで、まず、バグが再現する操作を再現して、本来の仕様ならばテストが通るテスト関数を作り、それが常にレッド(テストが通らない状態)であることを確認。次いで、無理やりにでも直して常にグリーン(テストが通る状態)であることを確認。最後に、リファクタリングでコードをきれいにし、かつ常にグリーンであることを確認する。といった具合です。これを繰り返すとバグらないきれいなコードが残ります。

著者:杉浦

メソッドからコンストラクタへのパラメータの移動によるリファクタリング

 このリファクタリングはあるオブジェクトの複数のメソッドで同じパラメータを渡している場合に有効です。コンストラクタでパラメータを定義することによって、インスタンス化された際にあらかじめ何度も渡されるはずだったパラメータを定義することによってコードをシンプルにします。
 次は期限が1日になる様にのAPIトークンを更新するメソッドの呼び出しです。これを行う箇所が複数のコードファイルの中で何度も出てくると仮定します。その場合[‘expired_at’ => now()->addDay()->format(‘Y-m-d H:i:s’)]も何度も出てくるということです。この状態でAPIトークンの期限を3時間にしたいという要求が来た場合、変更箇所が複数に渡り少々面倒なことになります。(置換で対処しようにも妙な変数名や何やらで失敗するかも)そうでなくとも単に行が長くなりがちです。

/** @var ApiToken $api_token */
$api_token->fill(['expired_at' => now()->addDay()->format('Y-m-d H:i:s')]);

 これをApiTokenクラスのコンストラクタに記述し、fillの度に呼び出すことで改善します。

class ApiTokens extends Model
{
    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        $this->new_expired_at = now()->addDay()->format('Y-m-d H:i:s');
    }
    public function fill(array $attributes)
    {
        $attributes['expired_at'] = $this->new_expired_at;
        return parent::fill($attributes);
    }
}

 こうするとクラスApiTokenからインスタンス$api_tokenを定義するたびに更新用の新たな期限が$api_tokenのプロパティに設定され、fill()に新たな期限の値を渡さずともfill()は新たな期限をトークンに設定します。例では1つのメソッドでのみプロパティを扱いましたがこれが複数のメソッドになってくるとなお効いてきます。

/** @var ApiToken $api_token */
$api_token->fill();
著者:杉浦

ブラウザ毎のHTML5対応件数を確認できるHTML5test

HTML5test – How well does your browser support HTML5?
 HTML5testはブラウザがHTML5にどれほど対応している確認できるサイトです。ここでいうHTML5とはW3C HTML5仕様で定義されている機能のみならず公式のHTML5仕様、HTML5に関連する仕様、およびHTML5の拡張のことです。詳しくはページ自体を参照します。
 indexページではindexページを見ているブラウザがどの程度HTML5に対応しているかの内容が見えます。画像はバージョン71.0.3578.98のGoogle ChromeでHTML5testを開いたときの画面です。

 compare->differenceと移動したページでは各ブラウザが対応しているHTML5関連の機能の差分が読めます。下図はHTML5testに記録されている各ブラウザの最新バージョンであるChrome 68、Firefox 60、Opera 45、Edge 18、Internet Explorer 11のHTML5対応スコアです。満点は555点です。webページ開発者の多くがIEを嫌う理由がわかります。私もIE対応は特別めんどくさい気持ちになります。

 意外だったのはEdgeの対応具合です。FireFox、OperaはほぼChromeの下位互換ともいえる対応でした。下図はOperaのみですがFirefoxも似たような形でほぼChromeが対応済み、Firefoxは未対応でした。

 対してEdgeは独特な対応具合でした。スコアに出るようにChromeの方がHTML5対応機能が多かったのですが、Edgeは映像、音楽関連においてChrome未対応の機能を対応済みとしていました。

 Safariは477/555点。Edgeと似た傾向のHTML5機能対応が多いブラウザでした。