プログラミング勉強中の人にオブジェクト指向とは何なのかを何となく伝えたい話
この文章について
OOP(オブジェクト指向プログラミング、オブジェクト指向パラダイム)について
プログラミング勉強中の大学生さんに説明する機会が何度かあったので、
自分の中で整理するために書きました。
中には適切でない説明もあります。ばっさり省いているところもあります。
詳細より イメージを掴んでもらうことを優先しているためです。
「それにしてもあんまりだなー」という表現がありましたらご連絡いただけると嬉しいです。
大学生さん
大学生さんたちはいろんな背景を持っています。
- プログラミングを始めたばかりの人
- 独学で Objective-C や JavaScript を書いた経験がある人
- Web やコンピュータの仕組みについてもこれから勉強する予定の人
使用言語
大学生さんたちはプログラミングの第一歩として JavaScript と PHP を使っています。ここでは説明に PHP のコードを使います。
PHP はクラスベースのオブジェクト指向を採用している言語です。
説明したいポイント
オブジェクト指向とはどんなものか
なぜオブジェクト指向を適用するのか
オブジェクト指向プログラミングに関するキーワード
オブジェクトに関するざっくりとした説明
コードを書いていると以下のような構文に出会います。
new
って何でしょう。
変数から出ている ->
の記号も気になります。
$user = new User(); $user->setName("nekoko"); echo $user->name;
ざっくり説明すると、 new User
の User
部分はクラス(定義)です。
new
という命令により、定義から実体を作っています。
上記のコードでは $user
にはその実体が格納されています。
また、クラスにはプロパティやメソッドが定義されています。
実体の持つプロパティやメソッドへアクセスするために使われる記号が ->
です。
まったくわけが分からない説明ですね(´・ω・`)
オブジェクト?
オブジェクトとはデータと処理の集まりです。
漠然とした集まりではなく、ひとつのテーマを持った集まりです。
上記のコード例では User
というものが出てきました。
一般的にユーザ情報にはどんなデータが含まれるでしょうか。
「名前」や「住所」、「電話番号」を持っているかもしれません。
それぞれが保持しているデータを状態と表現することもあります。
オブジェクトはこれらのデータ(状態)の他に振る舞いも持ちます。
振る舞いは自分自身に対する操作です。 オブジェクトに対して「名前を教えて」と伝えたときにオブジェクト自身が保持している名前を返す、などの動作を指します。
たとえば「鈴木さん」と「高橋さん」というユーザがいるとします。
この場合「鈴木さん」と「高橋さん」は別々の異なるオブジェクトです。
鈴木さんは「名前が鈴木である」という状態を保持していて、「名前を教えて」と問えば「鈴木」と答える振る舞いを持っています。
プロパティとメソッド
上の方で「クラスにはプロパティやメソッドが定義されている」と書きました。
プロパティはオブジェクトが保持しているデータ、状態、変数、
メソッドはオブジェクト自身に対する操作、振る舞い、関数のことです。
OOP におけるオブジェクトを構成するのは基本的にこのふたつです。
クラス?
クラスベースにおいて、クラスはオブジェクトの設計書(定義)です。
実体?
コンピュータ的には、メモリを確保した状態を指します。
実体のことをインスタンスと呼びます。
また、実体化することをインスタンス化といいます。
クラスとインスタンスの関係
家を建てる設計図がクラスで、設計図を元に建てた家がインスタンス。
たい焼きの型がクラスで、型を使って焼いたたい焼きがインスタンス。
家を建てるための設計図があるとします。
設計図を元に、同じ形の家をたくさん建てることができます。
設計図がただそこにあるだけでは家はできあがりません。
設計図を元に大工さんがトンカンすると家が建ちます。
設計図に書いてあるドアを開けることはできませんが、実際に建てた家のドアを開けることはできます。
たい焼きの型を元に、同じ形のたい焼きをたくさん作ることができます。
たい焼きの型だけではお腹は膨れません。
型に生地を流し込んで焼くことで食べることができます。
型にはあんこが含まれませんが、実際に焼いたたい焼きにはあんこが含まれるかもしれません。
プログラミングにおける実体化
プログラミングにおけるクラスも似たようなイメージです。
クラス(定義や設計図)を元に、実体化させる必要があります。
PHP では実体化のために new
キーワードを用います。
また、実体化することでインスタンスが持つプロパティやメソッドへアクセスできます。
実装例
たい焼きクラスを実装しています。
たい焼きは内部にあんこ $anko
を保持しています。
また、あんこの種類を答えるメソッド getAnko()
を持っています。
(たい焼き自身が、中にどんなあんこが入っているかを知っている)
class Taiyaki { // 内部にあんこを保持するためのプロパティ(変数)です // 定義の段階ではあんこを持っていませんし、どんなあんこが入るかも分かりません private $anko; // コンストラクタ // new したときに呼び出されるメソッドです // 引数としてあんこを受け取り、プロパティに入れています public function __construct($anko) { $this->anko = $anko; } public function getAnko() { return $this->anko; } } // たい焼きを実体化 `new` する段階で、引数としてあんこを渡しています // 各たい焼きにはそれぞれ異なるあんこを入れています $tsubuanTaiyaki = new Taiyaki('tsubuan'); $creamTaiyaki = new Taiyaki('cream'); $zundaTaiyaki = new Taiyaki('zunda'); // たい焼き自身にメッセージを送り、振る舞いを引き出してみます // それぞれのたい焼きが持つあんこの種類が返ってきます echo $tsubuanTaiyaki->getAnko(); #=> "tsubuan" echo $creamTaiyaki->getAnko(); #=> "cream" echo $zundaTaiyaki->getAnko(); #=> "zunda"
実体化は必須なのか
長々とここまで書いたけど、実体化は必須ではありません。
実体化させなくても、クラス内のプロパティやメソッドに直接アクセスさせることもできます。
インスタンスではなく、クラスに属するプロパティやメソッドもあるのです…。
このようなプロパティやメソッドは静的だと言われます。
クラスに含まれるプロパティやメソッドを静的に定義することもできますし、言語によってはクラスそのものを静的であると定義できます。
PHP では static
キーワードを使うことで、静的なプロパティやメソッドを実装できます。
なぜオブジェクト指向なのか
OOP という考え方があるということ、言語でどのように表現されるかについてはお話ししました。
ではなぜこのような考え方が必要なのでしょうか。
お任せするということ
負担を減らす
生徒がたくさんいる学校を想像してみてください。
いくつかの部活動があるとします。
生徒はそれぞれどこかの部に所属しています。
部活動の時間になりました。
教師が生徒一人一人の部活動を調べて「あなたは野球部だからユニフォームに着替えて校庭へ行きなさい」「あなたは吹奏楽部だから音楽室へ行きなさい」と指示をするのは大変ですね。
生徒に「部活動の時間ですよ」って伝えたとき、それぞれが自身の部活動に合った行動をとってくれれば教師の負担は軽くなります。
処理を複雑にさせない
プログラムでも同じことが言えます。
メインの処理がそれぞれのデータに対して細かく指示を出していると、処理が複雑になる傾向にあるのです。
上記の例を OOP に当てはめると生徒はオブジェクトであり、教師はそれらのオブジェクトを扱う処理に近いかもしれません。
複雑なプログラムはバグを生み出しやすく、また変更が難しくなります。
プログラムには変更されることが多いものです。変更に強い作りにすることで修正作業が楽になり、バグの発生を抑えやすくなります。
カプセル化
オブジェクトにお任せした以上、オブジェクト自身以外の誰かがオブジェクトに干渉しすぎてもよくないですよね。
プロパティ(状態)の変更についてはオブジェクト自身に任せた方がよい(任せるべき)という場合もあります。オブジェクトの外側から状態を操作できないようにするのです。
これを隠蔽、またはカプセル化と呼びます。
PHP では private
キーワードを使用します。
継承
同じような性質を持つオブジェクトが複数あったとき、同じ定義を何回も書くのは冗長ですね。似たようなオブジェクトをまとめられると楽そうです。
継承を使うことで実現できます。
実装例
たとえば部活動を表すオブジェクトがあったとします。
class BaseballClub { private $place = "ground"; // 活動場所 public function getPlace() { return $place; } } class BrassBand { private $place = "music-room"; public function getPlace() { return $place; } }
野球部と吹奏楽部はプロパティとメソッドを持っています。
他の部活動も同じような属性を持つとします。
PHP での継承には extends
キーワードを使用します。
class Club { private $place; public function getPlace() { return $place; } } class BaseballClub extends Club { private $place = "ground"; } class BrassBand extends Club { private $place = "music-room"; } $club = new BaseballClub(); echo $club->getPlace(); #=> "ground" $club = new BrassBand(); echo $club->getPlace(); #=> "music-room"
BaseballClub クラス、BrassBand クラスには getPlace メソッドが定義されていません。でもそれぞれのインスタンスから呼び出すことができています。
これらのクラスが Club クラスを継承しているためです。
オブジェクト指向のポイント
OOP を適用する際に気にしたいポイントについて。
この辺の話は OOP に限らず、ソフトウェア開発全般に言えることです。
凝集度と結合度
凝集度とはオブジェクトやモジュールが、自身のすべき処理(責任)にどれだけ集中しているかという尺度です。
自身が担うべきではない処理を含んでいたり、また責任がはっきりしない処理を含む場合、「凝集度が低い」と表現されます。
また、オブジェクトやモジュール、関数同士の結びつきを結合度と呼びます。
処理同士の結合度は低い方がよいとされています。
処理同士の結合度が高い場合、一方の処理を変更した際にもう一方に影響が出る可能性が高くなります。一箇所修正しただけなのに複数箇所を修正しなくちゃいけないなんてめんどくさいですよね。
凝集度と結合度は一緒に語られることも多いです。
処理同士の結合度が低い=各処理の凝集度が高いと言える場合も多いです。
概念、仕様、実装のレイヤ
ソフトウェア開発の考え方に、以下のようなものがあります。
3つの観点から捉えるというものです(これはとても好きな図です)
概念(conceptual)
- 概念を実装するソフトウェアとは切り離されたもの
- 責任
- 「私が何に対して責任があるのか?」
仕様(specification)
- ソフトウェアのインタフェース
- 振る舞い
- 「私はどのように使用されるのか?」
実装(implementation)
- 具体的な処理
- ソースコード、データ、演算処理
- 「私はどのようにして自信の責任を全うするのか?」
継承はどこで使うべきか
継承はオブジェクトを分類するための手段です。
「同じプロパティやメソッドを持っている」という実装寄りの理由で継承を使うべきではありません。
継承を使うべきかどうかを判断するときは実装ではなく、概念や仕様に着目します。同じ概念を持つクラスをまとめるために継承を使用するとよいです。
オブジェクト指向は万能ではない
OOP は現在のソフトウェア開発でも広く使われている考え方ですが、絶対的なものでもないですし、万能でもありません。
要件によっては別の考え方が適している場合もあります。
OOP を無理矢理適用することで、逆にシステムが複雑になることもあり得ます。
たくさんある考え方の中のひとつとして、OOP のことも知っておくといいんじゃないかなーと思います。
伝えるためにどうしたらよいか
ということを伝えるために、どうしたらよいのか考え中です。
オブジェクト指向の分かりにくさは一体何なのか
「OOP は説明を読んでもよく分からない」という話をよく耳にします。
分からないポイントみたいなものがあるんじゃないかなーと思っています。
自分が特に思うのは以下の二点。
- 用語
- なぜ必要なのか
1 ですが、人や文章によって「オブジェクト」という言葉の指すものが異なる場合があります。概念であったり、インスタンスであったり、定義であったり。
この辺が混ざってしまうと、説明を読んだり聞いている側は混乱するんじゃないでしょうか(というか自分が昔混乱してた)
さらに最初の頃に突然「クラス」や「インスタンス」と言われても何が何だか…
2 については何事においてもそうだと思うのですが、OOP に関してもやっぱり書いていかないと分からない、経験してみないと実感としてわかない部分が多いと思います。(概念を理解するのにコーディングは必須ではないかもしれませんが、一般的に)
設計、処理をクラス化するべきか否か、メソッドの粒度等。
また、思想や世界観を共有するというところから話を始めるのも大事だなーと思うことがあります。
教えるタイミングはいつがよいのか
まだ理解できないだろうから説明しなくていいのかというと、そうとも言い切れないんじゃないかなーと考えています。
理解できなかった概念を、コードを書いている中で理解できる瞬間があるからです。そしてその瞬間はとても気持ちのよいものだと思っています。
なのでプログラミング勉強中の大学生さんに対しても、「一度に理解してもらえるとは思っていないけど説明するよ」って言いながら話すことがあります。
プログラミングを勉強し始めた大学生さんに OOP について教えるときには、上記からかいつまんで説明しています。伝えるポイントの取捨選択はいつも悩むところ。もっと簡潔に、適切に表現できるようになりたい。
分かりやすい説明や体験談があったらぜひ聞いてみたいです。
TokyuRuby会議07で働き方について話してきました
TokyuRuby 会議07 で「仕事する時間や場所ってもっと選べてもいいんじゃないか」という主旨の LT をしてきました。
思いがけず LT 王の称号をいただいてしまってだいぶ動揺してしまいましたが、滅多にない機会なので素直に喜ぶことにしました。わーい(∩*´∀`)∩
賞品としていただいたTシャツとプレモル(の食品サンプル)は大事にします。
桜のお酒は飲むのがもったいないくらいかわいいです。
皆様ありがとうございました!
なぜこの話をしたかったのか
プログラマの仕事の中には PC と回線があれば場所を選ばずできるものも少なくないはずなのに、それを許容している会社さんって少ないよなーなぜなんだろうなーとよく考えています。
そんなに難しいことなのか?と。
自分が実際聞いた、リモート勤務やフレックスに否定的な方の意見は以下のようなものでした。
- 「同じオフィスにいた方が話が早いから」←わかる
- 「目の届かないところでは仕事しないかもしれないから」←うーん
- 「同じ時間帯に同じ場所へ出社しないと一体感がなくなる」←えっ(困惑)
今回は LT タイトルに育児を連想するようなキーワードを入れたのですが、育児中の人に限らず、事情がある人にも特別事情がない人にも、働き方の選択肢がひとつでも増えるといいのになーと思います。
話した内容について
1. 自分の経験談
要領悪い自分でも、働き方を変えたら働けたよって話です。
本当は自分の過去の話をするのは得意じゃないし、好きでもないです。
でもバックグラウンドを話さないと伝わりにくい気がしたので、少し時間を使って自分の話を聞いていただきました。
(悲壮感漂う話は極力端折ったつもりなのですが、しんどかった話とか端折りすぎても話す意味がなくなってしまうし難しいな……)
2. 転職活動の話
転職活動のときに「子供と一緒にごはんを食べられる働き方をしたい」という希望を出していて、協力しますって言ってくれる会社さんは意外とありましたよっていう話をしました。(そう言いつつ内情は……という話を聞いたこともありますが、そういう会社はごく一部だと信じたい)
発表後、クラウドワークスさんと tmix を運営している株式会社 spice life さんからも声をかけていただきました。
確かにクラウドワークスさんはコンセプトがド直球ですよね。
spice life さんが応相談なのは初めて知りました。tmix は素敵なサービスなので、もし求職中だったらぜひ一度お話を伺ってみたかったです。
弊社も勤務時間と場所のご相談、受けますよ!! #tqrk07
— igaiga (@igaiga555) 2014年3月29日
3. 子供の話
小学生になったら楽になるとか幻想だ!という話です。
乳幼児期に比べれば体も丈夫になり、自分で自分のことができるようになるのでその辺は確かに楽です。
実際一気に楽になるご家庭もあるかもしれません。
でも当たり前だけど親も子供も個人差があるんですよね。
さらに小学校高学年くらいになると思春期突入で難しくなるケースもあります。
あと学校行事な、これも当たり前なのですが平日のお昼前後にあったりします。
会社によっては午前休や午後休では対応できず、丸一日休みをとるか、学校行事に参加しないという選択になるんじゃないかと思います。
育児中の時短勤務なども3歳〜就学前までの会社が多い印象です。
4. リモート勤務の話
結論:やればできるよ!
もちろん個人の向き不向きもあるでしょうし、業務内容によっては難しいかもしれません。
Web 系のプログラマさんでしたら条件が揃えばリモート勤務自体それほど難しくないと思っていますし、条件を揃えるのも比較的難しくないのではと思っています。
LT 中にさらっと話したのですが、数年前に以下のような条件でお仕事させてもらっていたことがあります。
- 雇用形態は正社員
- 受託開発(顧客折衝やチームでの開発あり)
- 週4在宅勤務、週1出社(出社時は早く帰ってよい)
- 会議等、必要に応じて会社やクライアント先へ行く
- 勤務時間は自由(保育園送迎や行事等への参加、家事育児のため)
- 社員間の連絡は内線(SIP サーバを立ててもらい遠隔でも内線が使える状態に)
最初のうちはメンバー間でうまくやりとりできず、要件とズレたものを作ってしまったこともありました。
それでもリズムやコツみたいなものってやっていくうちに掴めてくるんですよね。
子供たちがインフルエンザにかかって1ヶ月まるっと在宅勤務だったこともありましたが、特に問題なく仕事を進めることができていました(と自分では思っている)。
この働き方が実現できたのは、周りのメンバーが協力的でいてくれたことが本当に大きかったです。
数年前と比べると現在はチャットやタスク管理などのツールも充実していますので、環境も整ってきているのではないかと思います。
リモート勤務の話(追加)
最後にリモート勤務の話を少しさせていただいたのですが、緊張しすぎて話したかったことの半分も話せませんでした。人前でお話しするって難しいですね。何回かさせてもらってるのですが未だにまったく慣れません。(皆さん内容も話し方も素敵でしたが、特に飯王の Kwappa さんは LT 3回ともぐいぐい聞かせる感じで改めてすごいと思いました)
ソニックガーデン倉貫さんの記事に私の言いたかった以上のことが書いてありますので、もしリモート勤務に興味があってまだ読んでいない方がいらっしゃいましたらぜひご覧になってください。
サイボウズさんが会社全体で働き方を考えている記事は以前にも拝見していましたが、この規模で実践できているのはすごいなー。
リモートワーク(在宅勤務)を導入するためのポイントと残された課題 | Social Change!
残業はエクスタシー!? イクメン経営者に学ぶ"働き方革命"──フローレンス駒崎代表×サイボウズ青野社長 | サイボウズ式
上の方にも書きましたが、私はプログラマとしても親としても足りない部分が多いです。
仕事でも日常でも周りに迷惑をかけてしまうことが多々ありますが、できることをやっていきたいと思っています。
TokyuRuby 会議って楽しい
最後に。
初めての TokyuRuby 会議でしたが本当に楽しかったです。
発表も食べ物もバラエティ豊かで、特に皆さん手作りのごはんの美味しいことと言ったら!どのお料理も美味しかった…!
プレモルもたくさん飲んでしまいました。
ビールは苦手だったのですがプレモルがきっかけで飲めるようになりました。
サントリーさんごちそうさまでした。
会場の VOYAGE GROUP さん、いつも勉強会などでお世話になっています。
発表するのも楽しいですね。
緊張しすぎて飲み過ぎたり話すことや息継ぎ忘れたりテンパってしまいましたがw
知り合いの方にお会いできたり、発表したことでたくさんの方に声をかけていただけたのも嬉しかったです。
スタッフの皆様、参加者の皆様ありがとうございました!
また次回楽しみにしています。
ハートキャッチプリキュア!の好きなところ
このエントリーは プリキュア Advent Calendar 2013 12月15日分の記事です。
前日のUemmra3さんの記事 はお父さん目線でのエントリーでした。せっかくなので自分も母親目線を交えつつ、ハートキャッチプリキュア!の好きなところについて書きます。
※一部ネタバレを含みます。
※黄色さんと紫さんに言及しちゃうと収集つかなくなりそうだったので今回は控えました。(2013/12/16 追記)