プログラミング習得の法則
もうすぐ6月も終わります。この記事は4月から入社して、新入社員研修で初めてプログラミングを学んだ方へのメッセージです。
はじめに
プログラミングメンター(指導者)の仕事をしていると、プログラミングの習得には3つのステップがあることに気づきます。
- 覚える
- わかる
- できる
ここでは覚える、わかる、できるの違いについて考察します。
ステップ1:覚える
初めてプログラムを学ぶとき、変数や配列、if文やfor文といった様々なルールを覚えないといけません。プログラミング習得の第1歩は「覚える」ところからスタートします。たとえばJavaプログラミングを習得する場合は、次のようなプログラムを書くところから始まります。
public class Main { public static void main(String[] args) { System.out.println("Hello World"); } }
これはHello Worldプログラムという有名なものですが、学び始めの頃は、publicってなんだろう、staticってなんだろう、voidって?という状態です。最初の頃は一つひとつのキーワードを無理して読み解こうとせずに、まずはこのとおり書けば動くということを「覚える」ところが大切です。「ぱぶりっくすたてぃっくぼいどめいん・・・」と何度も読んで(ときには復唱して)覚えます。「覚える」ためには読む、聞くといったインプット作業が中心となります。
ステップ2:わかる
コードの書き方を「覚えた」として、次の段階に進むには「覚える」から「わかる」へステップアップする必要があります。それでは「覚える」と「わかる」の違いはどこにあるのでしょうか。
System.out.println("Hello World");
たとえば上記のコードを見て「標準出力へHello World文字列を出力している」とか「Systemクラスのstatic変数outのprintlnメソッドを呼び出している」とか、自分の言葉でコードを解説できる人は「わかっている」人です。「覚える」と「わかる」の違いは単純で、自分の言葉で説明できるかどうかです。
「覚える」から「わかる」の段階へステップアップするためには、覚えたことを自分の言葉で説明する練習をすれば良いのです。自分の言葉で説明する場合、説明した内容を評価してくれる相手が必要です。相談できるメンターや共に学ぶ仲間の身近にいることはプログラミングの理解を深める大事な要素になるでしょう。
自分の言葉で説明するとは、話すという動作に限定するわけではありません。このブログのように文章にしてみるのも、自分の言葉で説明する練習の一つです。自分の言葉で説明するとは覚えた知識をアウトプットすることなのです。
ステップ3:できる
野球やサッカーのようなスポーツ、ピアノやギターといった楽器もそうですが「わかる」と「できる」は別物です。ギターを例に考えてみましょう。6本の弦を左手で抑えて、右手で弦を弾けば音が鳴る、というのは多くの人がわかります。またCコードやGコードといったコード進行について理解のある方もいるでしょう。しかし、当たり前のことですが、ギターの弾き方はわかったとしても、必ずしも上手にギターが弾けるというわけではありません。
プログラミングの世界においても同じで「わかる」と「できる」は大きく違います。プログラムの「わかる」人はコミュニケーションに参加することはできますが、コンピュータに向き合ってプログラミングできるとは限りません。
「わかる」から「できる」の段階へステップアップするには実践練習しかありません。つまり、コンピュータに向き合って、キーボードをタイプしてプログラミングする時間を作らなければなりません。「できる」ようになるためには疲れやストレスを伴う反復作業が必要なのです。これは楽器やスポーツの習得と同じです。繰り返しますが大事なのは反復練習です。プログラミングの習得の早い人の多くは、学んだことを丁寧に復習する人です。
「僕はスポーツの練習じゃなくて”武井壮を動かす練習”をしている」
武井壮さんの「僕はスポーツの練習じゃなくて”武井壮を動かす練習”をしている」という話があります。
プログラミングも同じで、頭の中でイメージしていることと、実際に体を使って表現することの間には乖離があって、それを埋めるためには質の良い練習をしないといけません。
「1万回のキックを1度だけ練習したものを恐れないが、ひとつのキックを1万回練習したものを恐れる」
ブルース・リーの名言も引用しておきます。
プログラミングの反復練習は丁寧に時間をかけてやりましょう。練習の前にコーヒーを準備しておくくらいの余裕があると良いかもしれません。
ブルームの法則
教育の世界には「ブルーム分類学」というものがあります。
ブルームの6分類法とは、技術を人間が習得するときの、人間の発達段階と、各段階における学習目標を示したものです。レベルの低い方から、記憶、理解、応用、分析、評価、創造、と続きますが、基本的に学習は、この順序で、各段階の目標をクリアしながら進めていかなくてはいけません。
ブルーム分類学では6つのレベルで学習目標を分類しています。
- 記憶
- 理解
- 応用
- 分析
- 評価
- 創造
個人的にはこの分類はよくできている(凄い)と思っています。ただ初見だと、難解に感じるので、6段階の上位3つ(分析、評価、創造)はひとまず置いておいて、最初の3つ(記憶、理解、応用)だけに絞って学習目標を考えるとわかりやすいです。
プログラミング習得の法則
まとめです。プログラミング習得の法則は3つのステップを踏みます。ブルームの分類も添えておきましょう。
- 覚える(=記憶)
- わかる(=理解)
- できる(=応用)
各ステップでの具体的な学習方法を織り交ぜると次のようになります。
- 覚える(記憶)
- 読む、聞くといったインプット作業
- わかる(理解)
- 自分の言葉でアウトプットする練習
- できる(応用)
- 手を動かしてアウトプットする練習
本を読んでいるだけではプログラミングはできるようになりません。学んだことを言葉やコードにしてアウトプットする習慣を身につけましょう。
そのためにはGitHubのようなサービスを上手く使えるようになるといいですよ。
Vagrant+VirtualBoxでUbuntuを起動する
何をするのか
WindowsとかMacの中でLinux(Ubuntu)を起動します。
Linuxの学習にもオススメです。
手順
1. VirtualBoxのインストール
VirtualBoxはORACLEの提供する仮想化ソフトです。VirtualBoxを使えば現在実行中のOSの上で、別のOSを起動できます。たとえば、Macの中でLinuxを動かすみたいなことができます。
ちなみにパソコンに直接インストールしているOSをホストOS、仮想化ソフトによってインストールされたOSをゲストOSと呼びます。
VirtualBoxは以下のサイトからダウンロードします。
インストールはウィザードに従って進めましょう。
2. Vagrantをインストール
VagrantはVirtualboxのような仮想化ソフトを便利に扱うためのツールです。Vagrantをインストールすると、コマンドライン上でvagrantコマンドを利用できるようになります。vagrantコマンドを使えばゲストOSイメージのダウンロード、ゲストOSの起動、ゲストOSへの接続といったあらゆる操作を実行できます。
Vagrantは以下のサイトからダウンロードします。
こちらもインストールはウィザードに従って進めましょう。
3. ターミナルソフトをインストール(Windowsのみ)
ターミナルソフトというのは、ホストOSからゲストOSに接続するためのものです。WindowsだとPuttyか何かで良いと思います。
4. VagrantでUbuntuを起動する
VagrantはゲストOSのイメージをBoxという単位で扱います。UbuntuやCentOSといった一般的なBoxは以下のWebサイト(Vagrantbox.es)で公開されているので利用すると便利です。
ここでは以下の手順でゲストOS(Ubuntu)を起動します。
- VagrantにBoxを追加する
- Vagrantfileを作成する
- VagrantfileからゲストOSを起動する
VagrantにBoxを追加する
Vagrantbox.esで公開されているUbuntu(Precise 32bit)を追加します。
$ vagrant box add precise32 http://files.vagrantup.com/precise32.box
Boxのダウンロードには数分かかります。ダウンロード完了後、追加済みのBox一覧を確認できます。
$ vagrant box list
Vagrantfileを作成する
任意のフォルダに移動してVagrantfileを作成します。
$ vagrant init precise32
上記のコマンドでカレントフォルダにVagrantfileが生成されます。
VagrantfileからゲストOSを起動する
Vagrantfileが作成できたので、Ubuntuを起動してみましょう。
$ vagrant up
数秒待つとUbuntuが起動します。
5. Ubuntuに接続する
Macの場合はターミナル上で以下のコマンドを実行します。
$ vagrant ssh
Windowsの場合は、Puttyを起動して以下のとおり接続します。
ゲストOSを停止するには
ホストOS上で次のコマンドを実行します。
$ vagrant halt
EC2にDockerをインストールしてRedmineを起動する
EC2(Amazon Linux)上にDockerをインストールして、Redmineを起動するまでのまとめです。たぶん9分くらいでできます。
Dockerのインストール
詳細は公式のドキュメントに載ってるとおり。
Docker Basics - Amazon EC2 Container Service
要点だけ抜粋すると、
yumのアップデートして
[ec2-user ~]$ sudo yum update -y
Dockerのインストールして
[ec2-user ~]$ sudo yum install -y docker
Dockerサービスを起動する。
[ec2-user ~]$ sudo service docker start Starting cgconfig service: [ OK ] Starting docker: [ OK ]
あとはec2-userをdockerグループに追加すればOK。
[ec2-user ~]$ sudo usermod -a -G docker ec2-user
ここで一旦ログアウトして再度ログインする。先のグループ権限を有効にするため。
docker infoコマンドでインストールを確認する。
[ec2-user ~]$ docker info Containers: 2 Images: 24 Storage Driver: devicemapper Pool Name: docker-202:1-263460-pool Pool Blocksize: 65.54 kB Data file: /var/lib/docker/devicemapper/devicemapper/data Metadata file: /var/lib/docker/devicemapper/devicemapper/metadata Data Space Used: 702.3 MB Data Space Total: 107.4 GB Metadata Space Used: 1.864 MB Metadata Space Total: 2.147 GB Library Version: 1.02.89-RHEL6 (2014-09-01) Execution Driver: native-0.2 Kernel Version: 3.14.27-25.47.amzn1.x86_64 Operating System: Amazon Linux AMI 2014.09
以上でDockerのインストールは完了です。
Redmineのインストール
DockerでRedmineをインストールします。ここではDocker Hubで公開されているsameersbn/redmineにお世話になります。
docker pull sameersbn/redmine:latest docker pull sameersbn/mysql:latest docker run --name=mysql -d -e 'DB_NAME=redmine_production' -e 'DB_USER=redmine' -e 'DB_PASS=password' sameersbn/mysql:latest docker run --name=redmine -it --rm -p 80:80 --link mysql:mysql sameersbn/redmine:latest
ここではMySQLとRedmineのDockerイメージをPULLしています(これには数分かかります)。
Dockerコンテナが起動した後、ブラウザでアクセスすると初期アカウントadmin / adminでログインできます。
EC2の起動時間は無視するとここまでで4分くらい。EC2の起動時間合わせても9分でいける、、かな。
バックグラウンドでRedmineを起動するには
先のやり方だと、Redmineのコンテナがフォアグラウンドで起動しているので、バックグラウンドで起動したい場合は、一回止めて次のように起動します。
docker run --name=redmine -d -p 80:80 --link mysql:mysql sameersbn/redmine:latest
起動中のコンテナの中でごにょごにょしたい場合はdocker execコマンドを使います。
docker exec -it redmine /bin/bash
参考
Dockerエキスパート養成読本[活用の基礎と実践ノウハウ満載!]
- 作者: 杉山貴章,大瀧隆太,Yugui(Yuki Sonoda),中津川篤司,前佛雅人,松原豊,米林正明,松本勇気
- 出版社/メーカー: 技術評論社
- 発売日: 2015/06/30
- メディア: Kindle版
- この商品を含むブログを見る
CronでMySQLのデータをエクスポートしてS3にアップするまで
MySQLのデータをエクスポートしたいで。
Cronの登録するで。
たしかcrontabコマンドは気をつけなあかんで。
Cronで動いたで。でもダンプファイルあれへんで。。
次はコマンドラインでS3にアップしたいで。
s3cmdよさそうやで。使い方調べるで。
シークレットキーがいるやで。
awsのs3を操作する為のaccess keyとsecret keyを取得する(IAM)
、、とりあえず警告は/dev/nullや、、で。
ApacheでLaravel5アプリケーションを動かす
Laravel5を使ったWebアプリケーションを開発しています。
開発時はビルトインサーバで開発して、運用時はApacheでということがやりたかったのでまとめです。OSにはUbuntu14.04を使っています。Vagrantも使ってます。
開発時 - ビルトインサーバの起動
開発時はphp artisan serveでビルトインサーバを使ってます。手軽で便利です。
$ php artisan serve
IP指定で起動することもできます。
$ php artisan serv --host 192.168.33.10
運用時 - Apacheで動かすには
基本的にはApacheでLaravelアプリケーションのバーチャルホストを定義するだけ。Laravelアプリケーションのpublicフォルダをドキュメントルートに指定します。
バーチャルホストの定義
Apacheにバーチャルホストの定義を追加します。
Ubuntu14の場合、/etc/apache2/sites-available/ディレクトリにバーチャルホストの定義ファイルを新規作成します。
ここでは/etc/apache2/sites-available/myapp.confを次のように作成します。
<VirtualHost *:80> ServerName myapp.com ServerAdmin webmaster@localhost DocumentRoot /var/www/myapp/public ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory "/var/www/myapp/public"> AllowOverride All </Directory> </VirtualHost>
ここでは/var/www/myapp/にLaravelアプリケーションが存在するものとしています。
DocumentRootにはmyapp/publicを指定します。 またLaravelは.htaccessを利用するので、myapp/publicディレクトリにAllowOverride Allを定義します。
/etc/apache2/sites-available/に作成したmyapp.confはこのままではApacheにロードされません。そのため、/etc/apache2/sites-enabled/からシンボリックリンクを定義します。
$ cd /etc/apache2/sites-enabled/ $ sudo ln -s ../sites-available/myapp.conf
変更を反映するためにApacheを再起動します。
$ sudo service apache2 restart
Apacheの実行ユーザを変更する
Vagrant上で開発している場合は、Apacheの実行ユーザをvagrantに変更します。Ubuntu14のApacheにはenvvarsというファイルで実行ユーザを変更できます。envvarsは環境変数を管理するファイルのようです。
$ sudo vi /etc/apache2/envvars
envvarsを以下のとおり変更します。
export APACHE_RUN_USER=vagrant export APACHE_RUN_GROUP=vagrant
.htaccessが機能しない問題
Laravelアプリケーションにはpublicディレクトリ下に.htaccessファイルが用意されています。.htaccessファイルではmod_rewriteによるURLの書き換えが定義されています。
ちょっとはまったのは、デフォルトのApacheだとmod_rewriteが無効になっていた件です。そのため、URLの書き換えが機能せず、以下のような問題に遭遇しました。
laravel 4 all routes except home result in 404 error
Laravelアプリケーションのルートディレクトリ以外は404になってしまうという。。 このときの現象として、以下のURLでログイン画面にアクセスしたいのに404になってしまいます。
http://myapp.com/auth/login
その代わり、次のURLでアクセスできるという。。index.phpて。。
http://myapp.com/index.php/auth/login
この場合、mod_rewriteを有効にすると解決します。
$ sudo a2enmod rewrite
Apacheの再起動も忘れずに。
$ sudo service apache2 restart
Laravelアプリケーションの設定
Laravelアプリケーションに特に変更箇所はありませんが、Gitのようなバージョン管理システムからコードを取得して来た場合、composer isntallを叩いて、それから.envファイルを作成する必要があります。
$ composer install
このへんは必要に応じてsudoするかんじで。
$ cp .env.example .env
.envに定義するAPP_KEYはphp artisan key:generateで取得できます。
$ php artisan key:generate Application key [0wzwvICe8xa0vJ7RUpOM1z7F03NeZxxx] set successfully.
もう1つアプリケーションのログファイルを生成しておく必要がありました。
$ touch /var/www/myapp/storage/logs/laravel.log
これくらいでたぶん動くはず。
補足
Apacheのインストール
$ sudo apt-get install -y apache2
sudo apt-get updateもさきにしとくように。
PHPのインストール
sudo apt-get install php5-common libapache2-mod-php5 php5-cli php5-json php5-sqlite php-pear php5-dev
SQLiteならこんなかんじでいけます。
Composerのインストール
$ curl -sS https://getcomposer.org/installer | php $ mv composer.phar /usr/local/bin/composer
ログファイル
Apacheのログは/var/logs/apache2/error.log
Laravelのログは/var/www/myapp/storage/logs/laravel.log
DigitalOceanでやるときのメモ
とりあえずDigitalOcean(rootユーザ)で環境構築するときは、Laravelアプリケーションの所有者をApacheユーザ(www-data)にしていおいた。
$ chown -R www-data:www-date /var/www/myapp
Apache 2.4の場合
パーミッションの設定でエラーが出る。
AH01630: client denied by server configuration
<VirtualHost *:80> ServerName myapp.com ServerAdmin webmaster@localhost DocumentRoot /var/www/myapp/public ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory "/var/www/myapp/public"> AllowOverride All Require all granted </Directory> </VirtualHost>
JAX-RS 非同期処理 Asynchronous Services
JAX-RSの非同期処理の実装サンプルです。
参考記事
JerseyのTutorialを参考にしました。
Asynchronous Server API
まずはベタな実装から。こんなふうにするとサーバースレッドはすぐに終わるので再利用できる。
- @Suspendアノテーションを付与したAsyncResponse引数を用意する
- 別スレッドの処理終了時にasyncResponse.resume(response);でレスポンスを返す
タイムアウトの設定は次のように実装する。
Asynchronous Server-side Callbacks
非同期処理のコールバックメソッドを作る場合は次のように実装する。
- asyncResponse.registerでコールバックを登録する
- このサンプルではCompletionCallbackを実装して登録している
- CompletionCallbackのonCompleteメソッドはThrowable型の引数を受け取る(正常な場合はnull)
ちょっとだけはまったのが、別スレッドでWebApplicationExceptionのような例外をスローすると引数に代入されないところ。
Interface CompletionCallbackを参照すると、引数Throwableにはunmapped exception instanceが代入される的なことが書いている。
コールバックには以下の2種類がある。
- CompletionCallback リクエスト終了時に呼び出される(正常でも、異常でも)
- ConnectionCallback クライアントコネクションがクローズされるときに呼び出される(正常なクローズの場合は呼ばれない)
Servletの非同期処理
JAX-RSの非同期処理を実装しようと思ったけど、そもそもServletの非同期処理を実装したことなかったのでそっちの復習から。
参考記事
こちらの記事を参考にしてみました。
ちなみに参考にしたページではServletContextListenerでThreadPoolExecutor作ってる。要るのかわからんのでひとまずなしで。
動作確認
Tomcatを起動してブラウザでこんなかんじでアクセスする。
http://localhost:8080/async_servlet/AsyncLongRunningServlet?time=3000
この場合処理に3秒かかるわけですが、サーバのコンソールをみるとサーブレットスレッドがすぐ終了してるのがわかる。
AsyncLongRunningServlet Start::Name=25::ID=25
AsyncLongRunningServlet End::Namehttp-nio-8080-exec-3::ID=25::Time=13ms.
ちょっと疑問
サーバのコンソールを見ると、StartとEndの出力でスレッド名が変わってるんだけどこういうもんなのかな。