個人ブログ

インフラ、アプリケーションまわり

Composerが分らなかったから触ってみた.part1

背景

よく開発のときにcomposer installして、必要なパッケージを手元に落としてきたりします。

しかし、このコマンドを打って実際に何が起きているのか分かりませんでした。

そこで、Composerを軽く触ってみて、挙動について調べてみました。

そもそもComposerとは

Composerは「パッケージ管理ツール」という呼ばれ方をされます。

たとえば、Aというパッケージを利用したいとしましょう。

このとき、Aに属するファイルを1つ1つ手動でインストールする、という方法もあります。

しかし、 A を利用するために B というライブラリが必要だった場合はどうでしょうか?

手作業の場合は、依存関係があるファイルも1つ1つ収集する必要がありますが、これは面倒ですね。

Composerでできること

しかし、Composerを使えば、このような依存関係を自動的に解決してくれます。

1つ1つインストールする必要はなく、コマンド1つで、パッケージを利用するために必要なファイル群も含めてインストールしてくれるわけです!

さっそく使ってみる

簡略のため、あらかじめComposerがインストールされているものとします。

まず、適当なディレクトリを作成。

そのディレクトリ内でcomposer initを実行します。

$ mkdir composer_p
$ cd composer_p
$ composer init

対話形式でいくつか設定を加えることになりますが、一旦すべてスキップで構いません。

すると、ディレクトリ内にcomposer.jsonというファイルが作成されます。

ファイルをみると"require": {}という箇所があるかと思います。ここに、下記の記述をしましょう。

{
 省略,
 "require": {
        "nesbot/carbon": "^2.21"
 }
}

今回は、PHPで日付処理を簡単に扱うことのできるライブラリ、Carbonをインストールしてみます。

qiita.com

Composerでは、インストールすべきパッケージは、composer.jsonのrequireキーの配下に列挙していきます。

パッケージ名は、Packagistから確認できます。

nesbot/carbon - Packagist

それでは、列挙したパッケージをインストールするために、同じディレクトリ内で下記コマンドを実行しましょう!

$ composer install

するとvendorというフォルダが作成されます。Composerでインストールしたパッケージ群が、すべてこのフォルダ内に放り込まれます。

またcomposer.lockというファイルも作成されました。composer.lockは、先ほどcomposer.jsonに列挙したパッケージを取得するために、実際にどのファイルをインストールしたのかをひとまとめにしたものになります。

実際にパッケージが利用できるか確認

さて、Composerによってインストールしたライブラリ、Carbonが実際に利用できるか確認してみましょう。

Carbonを利用するためのtest.phpを作成し、下記を記述します。

<?php

require 'vendor/autoload.php';

use Carbon\Carbon;

$dt = Carbon::now();
echo $dt. "\n";

Carbonの詳しい使い方については、上にも貼ったリンクなどを参考にしてみてください。

冒頭でrequire 'vendor/autoload.php';という記述をしています。

Composerを用いてパッケージをインストールした際、vendor配下にautoload.phpというファイルが生成されます。

上記ファイルをrequireすることによって、vendor配下のファイルをオートロードすることができます。

そのため、namespaceをuseすることによって、Carbonインスタンスの使用が可能になります。

結果

$ php test.php
2019-07-28 11:29:31

想定通り、Carbonインスタンスによる現在時刻の出力ができています。

lsコマンドの機能を、LaravelとPHPで実装してみた ver.1

下記記事を読んで、bashコマンドと同じ機能を実現する練習をしようと思いました。

まずは、記事にも書かれているbashのlsコマンドでやってみます。

qiita.com

そもそもlsコマンドって?

lsコマンドの使い方と覚えたい15のオプション【Linuxコマンド集】

この辺りを参考にしてみてください。

今いるディレクトリ(or 指定したディレクトリ)に存在するファイルやフォルダをずらっと一覧表示してくれるあれです。

さっそく実装

実現したい機能としては、以下の通りです。

  • ディレクトリを指定した場合、そのディレクトリのファイル・フォルダを表示
  • ディレクトリを指定しなかった場合、カレントディレクトリ(今いる場所)のファイル・フォルダを一覧表示
  • 指定したディレクトリにファイルが存在しなかった場合は「指定のパスにファイルは存在しません」というメッセージを出力し、処理を中断

コンソールから自作のコマンドを叩くために、今回はLaravelのArtisanコンソールの機能を使いました。

Artisanコンソール 5.5 Laravel

下記コマンドを叩くと、新しいコマンドクラスが自動で生成される優れものです。

php artisan make:command LsCommand

下記記述により、コマンドからディレクトリのパスを指定できるようになります。

protected $signature = 'dir:get
                        {path? : 表示させたいパスを入力してください}';

protected $description = 'lsコマンドをLaravelに書き換えています';

処理の本体

コマンド実行時に呼び出されるのは、すでに記述されているhandleメソッドです。 この中に、行いたい処理の本体を記述していきます。

一旦今回は、PHPのDirectoryクラスを用いて実装していきます。Directoryクラスについては、下記のマニュアルに詳細が記載されています。

上記を参考に、以下を記述。

    public function handle()
    {
        // 表示するpathを取得。入力がない場合はカレントディレクトリを返す。
        if ($this->argument('path')) {
            $path = $this->argument('path');
        } else {
            $path = '.';
        }

        // 不正なpathが入力された場合に、エラーを返す
        if (!is_dir($path)) {
            $this->error('指定のパスにファイルは存在しません');
            return;
        }

        // 実行
        // falseになるディレクトリ名("0"など)で処理を止めないために、一度$fileに値を格納した上で、falseと比較している
        try{
            $directry = dir($path);
            while (($file = $directry->read()) !== false) {
                if ($file != '.' && $file != '..') {
                    $this->line($file);
                }
            }
            $directry->close();
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
    }

try-catch文の中のネストが深くなってしまっていますね。この辺りは改善する必要がありそうです。 あとは、エラーで返ってくる返り値についても、深く考えずに!を使って書いてしまっているので、ここも要確認ですね。

結果

実行コマンド

php artisan dir:get hoge
php artisan dir:get 
php artisan dir:get /

上記コマンドを叩くと、指定したLaravelのディレクトリに存在するファイル・フォルダが出力されました。

「理解する」ということについて考えてみる

背景

プログラミング研修をずっと行なっている。Webのオンライン教材を使ったりしながら、学習を進めている。その中で1つ困ったことがあった。

分かったつもりになっていても、実際には理解できていない、ということだ。

知らない言語を学ぶから、初見では意味が理解できない。ひとまず写経。動作が確認できて「なんとなく」ロジックが分かったら次に進む。時間的制約もあり、細かい部分の理解はおざなりにしていた。ただ、このような形で学習を進めていると、その日はよくても翌日になると、

  • 昨日分かった箇所が、分からなくなっている
  • 結局理解できていない

ということが続いていた。

忘れても良いけど、理解は必要

前記事にも書いたが、記憶しているかどうかは重要ではない。 ttkoni.hatenablog.com

忘れても、検索して使える状態になっていればそれで良い。だけど理解ができていないと、そもそも調べることができない。「何がわからないか分からない」という、非常にどうしようもない状況に陥ってしまうのだ。

知識を使える状態にするには、一度理解するというプロセスが必要だ。内容を飲み込んで、疑問点が残らないように消化していく。この過程を通して、使える技術が増えていくんだと思う。というわけで、理解するということについて考えてみた。

理解するために必要なこと1:自分の言葉で置き換える

書かれてあるコードを読んで「ふんふん、なるほど」と読み飛ばしてはいけない。その瞬間は理解したつもりになっていても、それは錯覚。ただ文字を追っていくだけでは、内容に踊らされてしまう。そこで必要になるのが「自分の言葉で置き換える」という作業だ。

まず内容をざっと読む。ある程度まとまったブロックごとに読んでいくのが良い。次に、内容を自分の言葉で置き換えていく。ここで重要なのが、論理的つながりを意識すること。「これはこうだから、こう」という風に、流れに落とし込んでいく。

なぜ流れに落とし込んでいくのか。それは「ロジックは一度可視化しないと見えない」からだ。もちろん、書かれてある文章(特に教材)はたいていの場合、論理的だ。だけど、その論理を目で追うだけだと、せっかくの内容も意味のない文字列と化してしまう。どういう論理なのか、文章の流れを「見える化」することで、文字列はロジックへと変わり、理解も進んでいく。

理解するために必要なこと2:疑問点を言語化、それを解消する

「よく分からないけど、まあだいたい理解できたし先に進もう」

ではなく、まずは疑問点を言語化すること。分からないことを放ったらかしにした先に、未来はない。最初は、何となく分からずモヤモヤした状態だと思う。ここで逃げずに、モヤモヤを言葉に置き換えること。すると、何が分からないのか、なぜ分からないかが見えてくる。

何が分からないのかを把握した上で、分かるために必要な情報を収集する。ネット検索したり、分からなければ人に聞いても良い。ただし、人に聞く= 他人の時間を奪うことだから、その点には注意が必要。聞きたいことを端的に整理した上で、何が疑問なのか伝わるように質問する。

ここで得た情報・知識は、自分で動いて獲りにいった情報だ。能動的に獲得した知識と、受動的に獲得した知識では、定着度が圧倒的に異なる。理解を深めるためには、このアクティブラーニングの機会を増やすことが超重要だ。その意味で、疑問点は能動的に学ぶチャンスだともいえる。だからむしろ、疑問点は自分から積極的に作りにいく姿勢が大切だ。

まとめ:手を動かすこと

上の両者に共通する点。それは手を動かすということ。やっぱり、アクティブラーニングは超重要だ。疑問点を調べることもそうだし、プログラミングだったら、自分でサービスを作ったり、読んだコードを自分なりに書き換えてみることなど。手を動かして、そして情報は自分で獲得する。

すると「何のためにこの情報が必要か」が見えてくる。これは、理解をより速く・深くする上でめちゃくちゃ大切だ。自分が今学習している情報は、どこにつながるのか。なぜ自分はこの情報が欲しいのか。その根っこの部分は常に見えていないといけないし、それは手を動かすことでしか見えてこない領域なのだ。

エンジニアとして成長するために必要な考え方

背景

エンジニア研修を進めるにあたって、先輩エンジニアの方から助言を頂いたのでメモ。

研修内容

5月いっぱいを使って、エンジニア研修(プログラミング研修)を行っている。

中旬までは、外部サービス・書籍などを使って学習。 業務で使う言語はもちろんのこと、Git、HTTPプロトコルなど、Webエンジニアとして必要な基礎を網羅的に学ぶ。

その後、研修の総仕上げとして、擬似的なサービスを実装してみる。 「インプット → アウトプット」の流れ。

自分が行っていた学習

関数・モジュール・ライブラリなど、逐一暗記しようとしていた。 なんのことだかチンプン・カンプンだったから、ひとまずインプットしようという発想。

だが、暗記に時間を書けすぎて、タイムロスが多かった。 また、キャパシティオーバー気味でもあり、結局学習内容が身についていない状態だった。

助言内容1:暗記は必要ない

たとえば関数・ライブラリの文法などについて、逐一暗記する必要はない。

ネットを探せば、情報は無限に転がっている。 それらを調べて、使える状態にしておくことが大切だ。

「知っている」ではなく「調べて使いこなせる」を達成レベルにおくと良い。

たとえば、ある機能を実装したいとする。 その時に「あの関数使えるかも」という発想に至るかどうか。 そこが重要だ。

「知識にフックをかけておく」とも表現できる。 このケースであれば、あの関数・ライブラリが使えたかな? と考え、インターネットの引き出しから情報を引っ張り出せる力を身につける。

助言内容2:完成図をイメージし、仕様に落とし込む力

たとえば「動くサイコロを実装してほしい」という要望があったとする。(適当)

まずは、完成図をイメージする力が必要になる。 どの手段を用いれば、最適にゴールできるのだろうか?

次に、そのイメージを仕様に落とし込み、機能ごとの実装を考える。

こういう機能を実装したい。だったらこの言語の、この関数・ライブラリを使えばいいんじゃないか。

ここで初めて、知識が登場する。

もちろん、ただ知識を使うのではない。 使いたい知識のフレームを思いつくことが一番大切だ。 日頃の技術研鑽は、この思いつきを作るために行えばいい。

どうすれば思いつくか。 一例をあげると、

-技術を実際に触ってみること

-手を動かして、自分の体を通過させること

-なぜその技術があるのか。その背景を考え抜くこと

これらを意識したい。

助言3:強いエンジニアとは

強いエンジニアとは、引き出しが多いエンジニアだ。 たとえば、とあるゴールがあった時に、 その地点に到達するための道筋・手段を多く提供できるという事だ。

そのために必要なものの1つは、上にも書いた「知識にフックがかかっている」状態。 問題の解決手段に応じて、適切な知識を採択できる力だ。

もう1つは、技術の根っこを理解していること。

どの言語にも汎用できる、共通項がある。 クラス・モジュールの概念だとか、より深いレイヤーでいうと、 HTTPプロトコルTCP/IP、などの部分。

これらについて深く理解していること。 理解の到達レベルとしては、 その分野について詳しくない人にも伝わる説明ができる というところ。

意識して鍛えていきたい。

日々意識したいマインド

昨日の自分を超える

昨日の自分と比べて、何ができるようになったのか。 毎日言語化する。

できる事の積み重ねが人生を変える

と、某著名編集者も言っていたし。

自分が今何を疑問に抱いているのか、明確に言語化

自分の疑問を言語化できないのは、ボキャブラリーが少ないからだ、 と先輩エンジニアの方も言っていた。 ボキャブラリを増やす努力は毎日しよう、、、

加えて、技術的に詰まる部分があれば

-何に詰まっているのか

-なぜ分からないのか

-何が分かれば、疑問が解消できるのか

に立ち返って、疑問点の浮き彫りを行う。 解決方法をログ・健忘録に残しておけば、さらなる成長に寄与できるかも。

自分自身の現状を俯瞰する

どちらかというと、自分は視野が狭くなる傾向がある。 だけど、自分自身のキャリア・現状を考えた上で、 今行うべき行動を組み立てたい。 そのために「鷹の目」を持ち自分を俯瞰するマインドが超重要になる。

ゲームの主人公を見るかのごとく、自分を見る。

「まぎれもない自分自身が人生の主人公だ」

と、某有名作家も言っていた(多分)

センスを磨く

これは別記事に詳しく書く。

まとめ

がんばる。