2011年9月26日月曜日

人にプログラミングを教えるときのポイント

最近では、人にプログラミングを教えることはほとんど無くなってしまったのですが。
学生時代、情報学科に所属していた頃は、よくクラスメイトや後輩にプログラミングを教える機会がありました。
その頃の経験を元に、人にプログラミングを教えるときのポイントを、まとめてみたいと思います。
実際に人に教えるときの参考にしてみたり。
また、逆の立場になって、プログラミングを教わる(or理解する)ためのポイントのヒントとしてご覧ください。

1.何が解らないのか?は直接聞かない。
「解らない」と言って聞いてくる人に対して、「何が解らないの?」と聞いた場合に「それも良く解らない。とにかく解らない」と返されるケースって良くあると思います。
また、実際に「ここが解らないんだけど」という相手に、その内容を説明してもいまいちピンと来ず、深く聞いてみたらもっと根元の部分の勘違いが原因だったりすることもあります。
「解らない」を具体的にするために、何が解らないのかを直接聞くのではなく、その人が理解しているところを順番に説明してもらう所からはじめてみましょう。
例えば、「C言語の配列が良く解んない」という相手の場合
・配列自体は理解できているけど、for等のループ構文の理解が甘く、配列を利用したコードの多くが理解出来ない。
・配列の添え字が0から始まるという事に慣れておらず、不正な添え字(10個の配列に対して10、とか)を書いてしまい、エラーになってしまう。また、エラー文の読み方も良く判っておらず、エラー文から原因のコードにたどり着けない。
・そもそも変数への代入から理解できていない。
等々、その人それぞれの理解度の違いがあるわけです。
同じ質問でも、各人が求める解答は違っています。
面倒でも、まずは「何処まで理解出来ているのか?」をよく聞きましょう。

2.例え話を過度に行わない。
プログラム言語の初期の頃には、よく、変数を名前のついた箱として教える事があります。
この理解をずーるずると引きずっていると、ポインタやオブジェクト指向のあたりで躓く可能性が高くなります。箱の実際の場所が、なんて言われても良く解らないですよね?
例というものはとても有効です。特に、プログラミングのように現実に形の無いものを表すためには、使わざるを得ない物です。
しかし、使いすぎると、例と実態のマッピングがうまく出来ず、理解出来ないという結果に繋がってしまいます。
「aって箱がこうなって、それで~、箱が~箱が~…がー!!!」なんて言って混乱しているような相手に対しては、一度、解り易くメモリ空間上での変数の扱いを説明してみると、氷が解けるように理解してくれる事があります。
変数以外にも、例で教わり例に固執している所為で、実際の実装が見えずよく理解出来ない事はよくあります。
相手の理解を踏まえつつ、タイミングを見計らって、実際の実装を説明してあげましょう。
もちろん、タイミングを見誤ると、相手の脳内はさらに混乱するので、よく注意してくださいね。

3.「何故」も説明する。
よく解んないけど出来る事を覚えるより、「これを覚えるとこういう事が出来る!」って物を覚えるほうが、理解が早いものです。
オブジェクト指向の説明で、犬クラスがどーのこーのだの、車クラスがどーのこーのだの聞いても、「実際に何が便利になるんだよ。読みづらくなるだけじゃねーか!」なんて不満を覚える人もたくさん居ます。
そういう人のために、「何故この技術が必要か?」「何故この技術が生まれてきたのか?」という何故もしっかり説明してあげましょう。
例えば、Javaのコレクションクラス周りは、利用頻度も高く、クラス設計の説明としても有意義だと思います。
実際にコレクションクラスを使ったコーディングをしながら、継承の利点、インタフェースの重要さを教えてあげると、実際に使える技術として納得してもらえます。
そのままIteratorパターン、更にはその他デザインパターンまで教えることが出来れば最高です!が、大抵の場合、時間と互いの体力がそれを許しませんね……。

4.優良なコードは最高の教科書。
どんな教科書やどんな授業も、優良なコードには適いません。
人に教えるときは、是非、コードベースで教えてあげてください。
コードを読むことを嫌う人は、良いプログラマにはなれませんし、良いコードを知る事は、読みやすさの重要さに気づ、良いコードを書くための第一歩にもなります。
いろいろなコードを例に挙げ、コードを読むコツを教えてあげましょう。
その時に、どれだけ「素晴らしいコード」を提示することが出来るか、というのが、解答者の力の見せ所にもなります。
自分で素晴らしいコードを書くことはもちろん、良いOSSプロダクトやサンプルコードの出所を沢山知っておくことが重要です。

5.答えには良いソースを添えて。
ソースというのは、ソースコードではなく、情報源の事です。
質問に対して答えるだけではなく、自分がその答えとなる知識をどこから学んだのか、プラスして教えるようにします。
例えば
「PHPでカンマ区切りの文字列を配列に分割するのって、どうやって書くんだっけ?」
と聞かれたときに、ただ「explode」と答えるのではなく
「explodeって関数で出来るよ。公式の関数リファレンスみてみ?探し方は……」
と教えるとか。
「MySQL使ってるんだけど、このSQL、もうちょっと早く出来ないかな?毎回処理が重くって……」
と聞かれたときには
「インデックスが綺麗に使えてないんじゃない?MySQLのインデックスはこれこれこうなってて……。……だから、こんな感じで書けると思う。MySQLのチューニングだったら、この書籍がオススメだね」
等、書籍を薦めるとか。
最近であれば、Google Groups等に数多く存在している、優良なコミュニティを教えてあげても良いと思います。
こうする事により、言葉では伝え切れなかった内容を、質問者が自分自身で補完することが出来るようになります。

最後に。
上記にあげた5つのポイントは、すべて、一つの目標のためのポイントになっています。
その目標は
「質問者が、自分自身で解決出来るよう、問題解決能力を身につける事。」

何が解らないのかを自分で理解できるようになれば、答えを調査する事がより容易になります。
例え話と実体へのマッピングが重要だと気づけば、実際の実装への関心がより深まり、誤解も少なくなっていくでしょう。
すべての実装に「何故そうなったのか?」があるという事に気づけば、コード・設計の意図を読む事が重要だと、気づくはずです。
コードリーディングの力がつけば、独学で沢山のコードの知恵を身につける事だって出来ます。
良い情報源に多く触れ、情報源を自分で調べる事ができるようになれば、良い情報、悪い情報の判断だって自分でつけれるようになります。

プログラミングに限らず、エンジニアの知識なんて、すぐに新しいものが必要になります。
自分の周囲の人が誰一人理解していないような事を、自分だけで調査して身につけなくてはいけない。そんな時がいつか必ずやってきます。
そうなったとき、ちゃんと自分の力で解決できなければ、長くプログラマ・エンジニアである事は出来ません。
そのための、独学で学んでいく力こそが、真にプログラマが身に着けるべき力だと思っています。

……何でもかんでも、自分に質問に来られると鬱陶しい。なんていう自分本位な考えも、もちろんありますが(苦笑)

学校ならともかく、業務中に質問を受けたときは、時間リソースの関係で中々しっかりと教えてあげる事は難しいかもしれません。
でも、時間が許すのであれば、相手のため、そしていずれ相手と一緒にコーディングをする事になるかも知れない自分のため、じっくりと教えてあげてみてください。
情けは人のためならず。いつかきっと、良い結果を導いてくれますよ。

2011年9月5日月曜日

zencoding.vim入れてみた

めもめも。

■インストール
http://mattn.github.com/zencoding-vim/
上記参照。
git使ってないよー。オフライン環境だから使えないよーって人は
http://www.vim.org/scripts/script.php?script_id=2981
ここから。

■使い方
基本的には、zen codingの記法に則った省略形を描いて、"<c-y>,"
詳細はやっぱり、上記ドキュメント参照

■設定
<html lang="en">を<html lang="jp">にする、等
Zen Codingの設定類は
~/.vim/autoload/zencoding.vim
の中に書いてあるので、適当に検索して置き換える。

TDDBC 1.7 行ってきた

と、いうわけで。
先日行われたTDDBC 1.7に参加して参りました。
え、もう先日じゃないって?ぅぅ、すいません……。

内容そのもののお話は、ほかの参加者の方々のblogで語りつくされていると思いますので
私は、自分視点の感想等々を書くことにします。
時系列別に、どういう内容だったか知りたい方は、主催の@shishi4twさんの記事をご覧ください。

■前提
参加時点での私のTDDに関する技術レベル(?)は
興味があってPHPUnit(あるいはJUnit)のサンプルソースを動かしたことはあるけど、業務等の実際の開発で使ったことは無い程度、です。
一応、「車窓からのTDD」をPHPで書き直すという予習は、事前にやってました。
ついでに言うと、勉強会自体、片手で数えられるほどしか参加しておらず、これほど少人数の勉強会は初だったのでガッチガチに緊張してました…。

■TDDそのものについて。
最初に基調講演を聴いて感じたのは、TDDにおけるテストコードは、自然言語の仕様と実際のコードの間をつなぐ中間言語なんだな、ということ。
元々、日本語の仕様があって、それを元にプログラマが頭の中で考えてコードに起こしていくのが、旧来のTDDではない開発手法。
で、その仕様書をいかにプログラマにわかりやすくするか?っていうので、たとえばUMLとかが出てきたように思うんですよ。
(UMLにはそれ以外にも色々な意味合いがあるので、一概にUMLの用途を決める発言じゃないです。念のため)
実際、授業でプログラミングを習った際には、一度アルゴリズムを文字で書くための簡易言語っぽいものが利用されてました。
・iに1を足す
■iが10になるまで繰り返す
  ・iを出力する
こんな感じの。
ただ、自然言語や図などの人間が解釈するための仕様だと、プログラムコードに直す際のギャップが激しい。
なんせ、すっごい曖昧じゃないですか。日本語が曖昧って問題もありますが、そもそも自然言語って時点で、白黒はっきりしないことが多い。
一番大切な土台となる仕様が曖昧な状態で開発をしてたわけですね。今までは。泥の上にいきなり家を建てるような感じ。
そこで、いきなり家を建てるのではなくて、基礎やったりコンクリで固めたりして、土台をしっかりさせる作業が、TDDにおけるテストケースを書くって事。
土台がしっかりしてるから、プログラマも安心して作業できるし、完成するものもちょっとやそっとじゃ倒れない。最高です。
さらに言えば、テストケースを書くためには、問題の粒度を細かくする必要がどうしても出てくる。すると、小さな単位から問題を片付けることが出来るようになって、開発の速度と制度もUPする。
良い事尽くめですね。

ただひとつ、問題としては、どうしてもその利点を他者に伝えるのが難しいということ。
特に、よく知らずに「テスト」という単語だけで否定している人も多いんですよねー…。
こればっかりは、自分がしっかりTDDできるようになって、実際の成果を見てもらうほか無いのかな、って感じたり。

■ペアプロについて。
ペアプロという単語をはじめて聞いたのが、よりによってこのページだったんですよねー!
http://www.eclipsewiki.net/eclipse/index.php?%A5%BD%A5%ED%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3
(Javaメインで使ってたころ、Eclipseのプラグインあさってたら見っけた)
Wikiからのリンクは死んでますが、配布元のページの製品とサービスあたりからたどると見れます。バーディ君…。

と、言う訳で、そこまで凄い物って印象はありませんでした。むしろ、割とキワモノなイメージが無意識のうちに…(苦笑)

実際やってみての感想ですが…。
開発中に出てくる小さな悩みの解決は、本当に早いです。
「正規表現のあの記法ってどんなんだったっけ?」「str_lenだっけstrlenだっけ?」等の文法的な話とか
「ここって別メソッドにしたほうがいいかな?そうでもない?」「この変数名何にしよっか?」等リファクタリング的なところまで。
特に、開発初期はこういうしょうもない部分で時間をとられたりするものですが、そういった事が無くサクサク進むのは凄くよかったです。

開発が熟すまでは定期的にペアプロを行うとイイカンジかな、と思いました。

ただ、私自身がすっごいガッチガチだったため、あんまり突っ込んだ話が出来なかったのが非常に申し訳無いです…。

■コードレビュー
1回目が私のペアでした。ただでさえ緊張してたのに…!
コードレビューをして思い出したのは、学生時代の部活動でした 。コンピュータ部だったんですよ。
ただのゲーム部というわけではなく、ちゃんとしたコンテストに参加することを目的とした部だったので
入部試験として、fizzbuzzでは無いものの、難易度的にはそれに近いコーディングのお題が出されるんです。
で、実装したコードを先輩の方々に見てもらって評価してもらう、と。
当時はコードレビューなんて単語も知りませんでしたが、やってることはまさにコードレビューですね。
(このお題の話については、そのうち書いてみようと思ってます。身元バレが怖いケド)

業務でも、たまにコードレビューが行われることがありますが、業務上のレビューは、上司に採点してもらうって形がほとんどなので、「ひとつのコードを叩き台にみんなで論議する」というタイプのコードレビューは本当に懐かしかったです。
また、何か機会があればやってみたいですね。

■ツール
「道具を大切に」「ひとつのツールをカスタマイズして使い込む」
という話が何度もありました。
が。
私自身、それとは対極に居る人間だったので、今回一番びっくりした事です。

学生時代、誰かにヘルプを頼まれそのまま人の環境で作業することが多かった身としては、自分用のカスタマイズされた環境じゃないと作業が出来ない、っていうのは避けたかったんです。
その経験を今になってもずるずる引きずっているため、開発環境はなるべくデフォルトで、ってやってました。

それも悪くは無いとは思うのですが、色々な人の環境(今回はVimが多かったです)に触れるにあたって、自分用の環境を1個持っておくのも悪くないと思いました。
TDDBC直後、職場の開発環境が吹っ飛んだので、これを期にってことでVim入れたりもしてます。
設定ファイルいじったり、小さいスクリプトを書くのには凄く便利です。
ただ、FW等の大きいソースコードを追う時は、どうしてもEclipseやNetBeansのほうが便利なので、そこは使い分けでやってます。

■お題について
最初のお題は、割と素直に解けるお題だったと思います。
TDDとしては、正規表現の確認のために、いちいちテスト用のコードを作って実行して確かめて、なんて手間がかからないのが楽でしたね。
テストケースを書くことによって、お題の中で言及されていない仕様(=の数が左右違う時、とか)に気づくことが多かったのも良い事でした。

2つ目のお題については、お題自体が複雑なのと、書きたいことも多くもう少し時間がほしいので、別にまとめ…る、予定です。

■その他いろいろ
箇条書きで。

  • 緊張しまくりでホントすいませんでした。小規模の勉強会への参加が初だったんですよー!っていう言い訳。
  • リストバンドほしかったけど、Mサイズがでかすぎて腕にはまらなかった…orz
  • PHP関係のいろんな人と知り合えた!良かった。でもSymfonyノータッチノーチェックですいませ…ん…。最近、Symfony2のチュートリアル触り始めました!
  • TDDを実務に組み込めるか?は悩ましい所。コーディング担当が自分のみってプロジェクトでは、やれそうだけど、そもそもオブジェクト指向メンドクセって人が居る環境なので、環境全体に浸透させるには壁が分厚いデス。
  • 懇親会は予定があったので行けませんでした。楽しかったようなのですごくうらやましいです。次の機会があれば参加したいですね。
  • Objective-cのOpenGL ESプログラミングを、一時期やっていたんだけど、さすがにああいう所だとTDDは難しそうだな、とか。
  • TDDは、グラフを描くために式を考えるんじゃなくて、先に重要なポイントの点をたくさん取っておいて、近似値のグラフを描いて、そっから式を逆算するようなイメージ。
  • キイロイトリの巨大なぬいぐるみ、家にあります(?)

とりとめも無くなってきたので、以上ということで!

2011年8月30日火曜日

Bitbucket利用してみる

ドキュメントがしっかりしてるので、詳しくはこちらを。

Bitbucketって何?
→gitでいうgithubの、Mercurial版。

Mercurialって何?
→最近(ってもだいぶ前からだけど)流行の分散型ソース管理システム。

■Mercurialのインストール
python-devが入ってなかったので、追加で入れた。
$ sudo apt-get install python-setuptools
$ sudo apt-get install python-dev
$ sudo easy_install Mercurial
正しく入ったかテスト
$ hg --version
Mercurial Distributed SCM (version 1.9.1)
(see http://mercurial.selenic.com for more information)

Copyright (C) 2005-2011 Matt Mackall and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ユーザ情報を設定
$ vi .hgrc
$ cat .hgrc
[ui]
username=名前<メルアド>
[web]
cacerts = /etc/ssl/certs/ca-certificates.crt
[web]の項目が無いと、HTTPS経由で作業しようとしたときに警告がたくさん出る。
Ubuntu以外の環境の場合、以下を参考に。

■Bitbucketに登録
bitbucketのサイトにアクセス。"Sign up free>>"という黄色いボタンをクリック。アカウントを作成する。
OpenIDにも対応しているので、Google等のアカウントを使うと楽。
登録時に求められるNameとPasswordが、Mercurialからアクセスするときに必要になる。
また、登録時に入力したメールアドレスに、確認メールが飛んでいるので、URLをクリックしてメールアドレスの確認を完了しておく。

■リポジトリ作成
bitbucketのRepositoriesからcreate repositoryを選択。
必要項目を埋める。Webとかはサイトが無ければ空欄でおk。
Nameの横の"Private"にチェックが入っている場合、プライベートなリポジトリとなる。
デフォルトでチェックが入っている。公開しない場合はそのままチェックONでいいと思う。

■一通り試す
以下適当な作業フォルダで。
$ hg clone https://bitbucket.org/ユーザ名/リポジトリ名
$ cd リポジトリ名
$ vi test.txt
$ cat test.txt
test
てすと
$ hg add test.txt
$ hg commit -m "にほんごテスト"
$ hg push
bitbucketのサイト上のリポジトリを確認しに行く。
Web上からソースを見ると文字化けが発生しているが、ソースをDLした場合に文字化けが発生していないので、OKとする。

SSHとかはまた今度。

2011年8月7日日曜日

VirtualBox上のUbuntu11.04にPHP開発環境

tddbc1.7参加にむけて、サブPCのEeePC 1215Nに、PHP開発環境を立てることになったので、作業メモ。
※仮想環境で作業してみた結果、サブPCのスペックでは快適に作業できなかったため、実際にはUbuntu11.04をデュアルブートで利用しています。
NetBeansのインストール以降の作業は、仮想・物理マシン関係なく行えるので、そのまま残しておきます。

■仕様
  • VirtualBox上のUbuntu11.04をメインにする。
  • Apache、PHPはゲストOS内で動かす。
  • ホストOSのブラウザからも、開発中のサイトの確認ができるようにする。
  • PHPUnitも動くように。
  • IDEはNetBeans7.0を選択。一応、Eclipseも動くようにはしておく。
■前準備
  • Ubuntu Japanese Teamのサイトから、日本語版のUbuntu Desktop 11.04のisoをDLしておく。
  • VirtualBoxは最新版をDL、インストールしておく。
■VirtualBoxにUbuntu11.04をインストールする。
  1. VirtualBoxで新規ボタンを押して、ウィザードにしたがって新規仮想マシンを作成。
  2. まずは設定で、
    システム→メインメモリ:1024MB,
    ディスプレイ→ビデオメモリ:128MB, 拡張機能:3D...にチェック,
    ネットワーク→アダプタ2を有効化、割り当てをホストオンリーアダプタに。
  3. 仮想マシンを起動。初回起動ウィザードにて、Ubuntu11.04のisoイメージを選択する。
  4. Ubuntuのインストールウィザードに従って、インストール。
  5. 再起動後、ログイン。クラシックモードでの起動になることを確認。
  6. アップデート・マネージャが起動すると思われるので、そのままアップデートを実行。
  7. Guest Additionsのインストール。
    VirtualBoxのメニューのデバイスから、Guest Additionsのインストールを選択。
    Ubuntu上でターミナルを起動し、GuestAdditionsインストールスクリプトを実行。
    完了後、再起動。
  8. テーマ崩れの調整。
    こちら[http://akira.matrix.jp/?p=393]を参考に、/etc/gdm/Xsessionを修正し、再起動。
  9. ccsmを入れて見た目を好みに調整。この辺はお好みで。
■NetBeans7.0.1のインストール
  1. NetBeansの公式サイト[http://netbeans.org/]から、インストーラをDLする。
    ダウンロードバンドルは、とりあえず「すべて」にしておく。
  2. ダウンロードしたインストールシェルスクリプトを、ターミナルから叩く。sudoつけて。
  3. ウィザードに従ってインストール。
    基本的には「Next」でOKだが、JUnitのインストールは行うこと。
  4. 文字を滑らかにする。
    /usr/local/netbeans-7.0.1/etc以下にあるnetbeans.confを開き、netbeans_default_optionsの最後に以下を追記。
    -J-Dawt.useSystemAAFontSettings=lcd
  5. NetBeansを起動。
    ヘルプ→更新の確認。更新があれば行っておく。今回は無かった。
■Apache+PHPのインストール。
  1. ホストOS→ゲストOSにpingが通ることを確認しておく。
    Ubuntu側でifconfigを実行し、eth1のIPアドレスを確認。
    そのIPアドレスにホストOSからpingを打つ。
  2. apacheのインストール。
    sudo apt-get install apache2
  3. apacheの起動確認。http://ゲストOSのIPアドレス/にアクセス。It works!と表示されればOK。
  4. PHPのインストール。
    sudo apt-get install php5
  5. 念のため、apacheを再起動。sudo /etc/init.d/apache2 restart
  6. ドキュメントルートの/var/wwwのパーミッションを変更。一般ユーザからかけるようにしておく。
  7. /var/wwwにphpinfo()を実行するだけのPHPスクリプトを配置し、ブラウザからアクセスする。
■PHPUnitのインストール
PHPUnitのマニュアル[http://www.phpunit.de/manual/current/en/installation.html]を参考にインストールを行う。
  1. pearをインストール
    sudo apt-get install php-pear
  2. pearのバージョンをあげておく。
    sudo pear upgrade PEAR
  3. pear channel-discoverにて、上記マニュアルに記載されている3つのチャンネルを登録する。
  4. PHPUnitをインストールしようとすると、いくつか足りないパッケージがあり失敗するので、都度インストールを行う。
    最終的には、以下のようになる。
    sudo sudo pear install channel://pear.php.net/Net_URL2-0.3.1
    
    sudo pear install channel://pear.php.net/HTTP_Request2-2.0.0RC1
    sudo pear install phpunit/PHPUnit
  5. phpunit --versionと叩いて、バージョンが表示されることを確認しておく。
■NetbeansとPHPUnitの連携を確認

  1. NetBeansを起動。PHPプロジェクトを作成。
  2. 適当なクラスを新規作成。
    空で良いのでメソッドを1個追加しておく。
  3. 「ツール→PHPUnitテストを作成」を実行。
  4. テストフォルダを選べと言われるので、参照ボタンを押してフォルダを選ぶ。
    プロジェクトフォルダと同一だと怒られるので、新規に"test"というディレクトリを作って、選択しておく。
  5. プロジェクトをテスト(Alt+F6)で、テストを実行。100%通ることを確認。