<< 設計力の向上 | main | 「オブジェクトの設計力」 スキルアップ講座やります >>

オブジェクト指向プログラミングの教え方?

技術者仲間で話していたら、4月入社の新人に、オブジェクト指向プログラミングをどうやって教えたらよいか?、という話になった。

想定している言語は Java。

■動物・犬・猫モデルの説明から
■基本用語の説明から:「カプセル化とは」「継承とは」...
■サンプルコードから: System.out.println( "hello world" )
...

どのパターンでもうまくいかなかったので、今度の新人研修では何か工夫したいね、という話。
結論から言うと「これだ」というアイデアがでたわけではないが、話の内容は、いろいろ興味深かったのでメモ書き。

Java はオブジェクト指向の言語なの?


Java は、ある意味 C言語の仲間。ある側面はほとんど同じ言語。

・int, long (プリミティブなデータ型)
・配列操作
・if/for/return

ここだけ見れば、C言語のまま。つまり命令型、手続き型の言語。

public static void main( String[] args) なんかもオブジェクト指向というより C 言語風。

どうも、いきなり Java = オブジェクト指向 という教え方は間違いだろう、というのが一つの結論。

オブジェクト指向の前に基本が大切なのでは


たとえば、こんなアイデアがでた。

  1. まず命令的、手続き的な書き方に振り切って、プログラムを書いて動かす味を覚える。

  2. すこし大きめの課題に挑戦しながら、構造化プログラミング、特に手続き呼び出しの基本を学ぶ。メソッドの抽出リファクタリングは、この段階で教えてしまう。

  3. 次の段階で「複数」のクラスに分割してプログラムを作成することを教える。
    クラスの抽出のリファクタリングを実際にやって覚える。

  4. この段階では(本来のオブジェクト指向ではなく) getter/setter だけのデータ入れ物オブジェクトと、そのオブジェクトからデータを get したり set するという、データと処理を分離したスタイルで教える。

  5. その後で、データを get する側のオブジェクト(クラス)に書いてあるロジックを、データの入れ物オブジェクトに移動することを覚えてもらう。


この 5 を教えるときに、これが「カプセル化」であり「ロジックの移動」という「リファクタリング」である、という「言葉」もいっしょに教える。

この段階でも「これがオブジェクト指向である」という言い方(教え方)はしない。

あくまでも、

◎プログラムはメソッドやクラスに分割すること
◎データと関連するロジックは同じクラスにまとめたほうが良いこと

の2点を強調する。

あと、どんな簡単なプログラムでも「パッケージ」宣言は必須であると教えたほうが良い、という意見もでた。
なんでも public ではなく、基本はパッケージスコープということを最初から覚えたほうが良い。
複数のパッケージに分ける発想も早めに覚えたほうが良さそう。

基本的なリファクタリング

◎名前の変更
◎メソッドの抽出
◎クラスの抽出
◎ロジックの移動
◎データの移動
◎パッケージ間のクラスの移動

は手をどんどん動かしながら早い段階から覚えてもらうべき、という意見もでた。

「動いたら次の課題」を繰り返すと「動いた、OK」だけの技術者になってしまいそう。
そうではなく「動いた後」で、コード(設計)を改善するためにリファクタリングをすることまでがプログラミングである、と覚えてほしい。

カプセル化


教え方までは議論できなかったけど「カプセル化」は徹底的に体で覚えるべき、で意見が一致。

◎関連するデータとロジックをひとかたまりにすること。
◎データ構造は外には見せないこと(単純な getter/setter は書かないこと)

そうするのが「良いこと」という感覚をなんとか会得してもらう。

オブジェクト指向のプログラミングでは、プログラム全体のどこも見てもカプセル化が徹底しているのは、まちがいなく良いソフトウェア。

だから「カプセル化」=「良いこと」=「いつでもやるべきこと」を徹底的に教えておきたい。

「カプセル化」という言葉を使って説明すべきかは、賛否が別れた。

継承


Java は言語の仕組みとして、型継承(implements)と実装継承(extends)があり、この使い分けも含めて「継承」はもちろん重要な教育テーマ。

問題は「継承」をどう位置づけて、どのタイミングで、どう教えるか?

「カプセル化」は、プログラムのどこでもやるべきこと(良いこと)。

でも「継承」はそうではない。

プログラムのありとあらゆる場所が、型継承/実装継承だらけのソフトウェアは、どうみても良いソフトウェアではない。

少なくとも「オブジェクト指向らしいプログラミング」=「継承を使いまくる」=「よいプログラミング」という、刷り込みは絶対にすべきではない。

むしろ「継承」は「使いどころが難しいよ」ということを最初から強調したほうがよさそう。

だから研修の初期では「継承」はさらっと「そういう仕組みもあるけど、具体的には後で」という先送り。

業務アプリケーションでドメイン層を実装することに限定すれば、実装継承(extends)を使うべきケースはほとんどないと思っている。
共通のロジックは共通部品として「コンポジション」として実装するほうが業務の概念に合っていることが多い。

型継承(implements)も、あちこちで積極的に使うべき仕組みではない、と思っている。

開発の初期段階で発見した(つもり)の継承関係は、要件を深く掘り下げていくと、まちがった理解であることが多い。

経験上、ドメインの理解が表面的なプロジェクトの初期に、継承関係をあちこち設計・実装してしまうと、ドメインを深く理解できるようになったあとで、ドメインの本来あるべき構造と、実装してしまった継承構造が大きく捻じれていて苦労する失敗パターンばかりの気がする。

継承構造は、実装したクラスが増えてきて、ロジックやコードブロックで具体的な共通性を把握できてから、必要に応じて、段階的に、リファクタリングをしながら導入していくのが、実践的な良いやり方だと思う。

「継承」は「リファクタリング」の学習の中で覚えていくべき技術かもしれない。

ポリモーフィズム


大切であることは全員一致。
ただし、そのために「継承」を教える、というのは「なんか違う」というのが一つの結論。

そもそも「ポリモーフィズム」という「言葉」から教えたり、その実現手段として「継承」を強調するのは、ダメパターンだった、というのがいままでの経験。

もっと業務アプリケーションを書く上での具体例、必然的な例で「実装のやり方」という振り切り方で教えるのが良いのでは?

「ポリモーフィズム」という「言葉から入る」のではなく「if 文をなくすテクニック」という切り口で教えてみる。

if( value == null ) ...

という null チェック をプログラミングの基本のお作法として教えるのではなく、null object パターンあるいは簡単な strategy パターン を、かなり早い段階の研修内容に含める。
(パターンの名前そのものは使わない。コード例でのみ教える。簡単なクラス図は書いたほうがよさそう)

購入日オブジェクトがあるとして、

・正しい日付
・正しくない日付( 2月30日と入力された場合とか )
・不明の日付

を表示する場合、表示ロジックを if 文で書きわけるのではなく、

・購入日インタフェースでasText()メソッドを宣言

・有効購入日 (「年月日」を表示)
・無効購入日 (「年月日」を表示。「不正」の警告も表示)
・不明購入日 (「未記入」を表示)

の実装クラスごとに、個別の asText() メソッドを実装する。

こういう書き方を、if 文 を覚えた直後に教えてもいいくらいなのでは?

「ポリモーフィズム」という言葉を一切語らず、「if 文を減らすテクニック」をいろいろ教えることで、結果的に「ポリモーフィズム」を習得する、というのがいいんじゃないかと。

null オブジェクトパターン以外にも、

・boolean を enum に置き換える
・enum に振舞を持たせる
・Map を使った場合分け
・Set を使った場合分け

など、if 文の代替手段は、いろいろある。

「ポリモーフィズム」とは何か、なぜ必要か、という教え方でなく、「 if 文以外の条件分岐の書き方」という振り切り方で教えたほうが、実践的なんではないかと。

すくなくとも「これでわかった Java 入門」みたいな本をテキストとして使うより、はるかに効果的な教え方だと思うんだけどなあ。

コメント
大学でプログラミングを教えています.私が教えながらもやもやっとしていたことについて,この記事は1つの形を与えてくれました.このコンセプトを参考にしながら,教科書を書いてみようと思います!
  • ZACKY
  • 2013/12/04 9:50 PM
ZACKY さん

コメント、ありがとうございます。
少しはお役に立てたようですね。
こういうフィードバックは、ほんとうにうれしいです。

これからもよろしくお願いします。
コメントする









この記事のトラックバックURL
トラックバック
calendar
     12
3456789
10111213141516
17181920212223
24252627282930
31      
<< March 2024 >>
システム設計日記を検索
プロフィール
リンク
システム開発日記(実装編)
有限会社 システム設計
twitter @masuda220
selected entries
recent comment
recent trackback
categories
archives
others
mobile
qrcode
powered
無料ブログ作成サービス JUGEM