忍者ブログ

5年ぶりのプログラミング

入社時以来、5年ぶりに開発へ凱旋。そのためにプログラムをひさびさにみてみるが・・・

[PR]

2024.05.11 Saturday 02:14

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

オブジェクト指向が仕様変更に強いわけ

2008.10.14 Tuesday 23:44

昔ながらのやり方で、下記のようなじゃんけんプログラムを作成した。

・プレイヤーは二人で、ジャンケンの様子を再現する
・ジャンケンは3回勝負
・3回勝負で勝った回数の多いプレイヤーが勝ち
・引き分けも1回の勝負
・3回勝負後の勝ち数が同じ場合は、引き分けとする

//ジャンケンプログラム

public class SimpleJanken {

public static final int STONE = 0; // グー
public static final int SCISSOR = 1; // チョキ
public static final int PAPER = 2; // パー

public static void main(String[] args) {
System.out.println("ジャンケン開始\n");

int player1WinCount = 0;
int player2WinCount = 0;

for(int cnt=0; cnt<3; cnt++)
{
// 乱数を格納する変数
double randomNum = 0;

// プレイヤー1が何を出すか決める
int player1Hand = 0;

randomNum = Math.random() * 3;

if (randomNum < 1)
{
// randomNum が 0.0以上1.0未満の場合、グー
player1Hand = STONE;
System.out.print("グー");
}
else if (randomNum < 2)
{
// randomNum が 1.0以上2.0未満の場合、チョキ
player1Hand = SCISSOR;
System.out.print("チョキ");
}
else if (randomNum < 3)
{
// randomNum が 2.0以上3.0未満の場合、パー
player1Hand = PAPER;
System.out.print("パー");
}

// プレイヤー2が何を出すか決める
int player2Hand = 0;

randomNum = Math.random() * 3;

if (randomNum < 1)
{
// randomNum が 0.0以上1.0未満の場合、グー
player2Hand = STONE;
System.out.print("グー");
}
else if (randomNum < 2)
{
// randomNum が 1.0以上2.0未満の場合、チョキ
player2Hand = SCISSOR;
System.out.print("チョキ");
}
else if (randomNum < 3)
{
// randomNum が 2.0以上3.0未満の場合、パー
player2Hand = PAPER;
System.out.print("パー");
}

// プレイヤー1の勝利
if ( (player1Hand == STONE & player2Hand == SCISSOR)
|| (player1Hand == SCISSOR & player2Hand == PAPER)
|| (player1Hand == PAPER & player2Hand == STONE) )
{
player1WinCount++;
System.out.println("\nプレイヤー1が勝ちました!\n");
}
// プレイヤー2の勝利
else if ( (player1Hand == STONE & player2Hand == PAPER)
|| (player1Hand == SCISSOR & player2Hand == STONE)
|| (player1Hand == PAPER & player2Hand == SCISSOR) )
{
player2WinCount++;
System.out.println("\nプレイヤー2が勝ちました!\n");
}
else
{
System.out.println("\n引き分けです!\n");
}
}
System.out.println("ジャンケン終了\n");

if (player1WinCount > player2WinCount)
{
System.out.println(player1WinCount + "VS" + player2WinCount + "でプレイヤー1の勝ちです!\n");
}
else if (player1WinCount < player2WinCount)
{
System.out.println(player1WinCount + "VS" + player2WinCount + "でプレイヤー2の勝ちです!\n");
}
else if (player1WinCount == player2WinCount)
{
System.out.println(player1WinCount + "VS" + player2WinCount + "で引き分けです!\n");
}
}
}




長々となってしまったが、少し更新しようとすると、あちこちの修正が必要になってしまう。そのために従来方式では、仕様変更に極端に弱いのだ。

オブジェクト指向では、下記のように役割を考える。

上記プログラムでは、3人の役者がいると考えられる。

・ジャンケンをするプレイヤー田中さんと山田さん
・ジャンケンの勝ち負けを判断する審判 鈴木さん


それぞれ3人の人物が行ったことは、ざっと下記のとおり。

田中さん
 じゃんけんをする
 自分の勝った回数を数える

山田さん
 じゃんけんをする
 自分の勝った回数を数える

鈴木さん
 じゃんけんの開始を宣言する
 勝ち負けを判定する
 どちらが勝ったか判定する


そうです。田中さんと山田さんというのは、本質的には同じなんです。名前が違うだけで。

そこで、出てくるのがJavaの考え方であるクラス。

田中さんと山田さんが所属しているのが、プレイヤークラス。
鈴木さんが所属しているのが、審判クラス。


機能としては、プレイヤークラスに、プログラムしておけば、プレイヤーの名前を変えようが、数が増えようが、大きな変更は不要になります。

田中さん、山田さんは、プレイヤークラスを実際に使う実体、インスタンス。ほら、Javaらしくなってきた。


なんか、ピンときた俺でした。




PR

続きを読んでくださって、ありがとうございます。

オブジェクト指向の必要性について

2008.10.14 Tuesday 23:26

さて、ジャンケンプログラムは無事作成完了しました。
さてさて、いよいよなぜ、オブジェクト指向が必要かについてです。

今回作ったジャンケンプログラムに、今度は改良せよと書かれています。

1.プレイヤー1という名前ではなく、○○さんというように具体的に名前をつけられるようにする
2.プレイヤーの人数を変更できるようにする
3.プレイヤーの手の出し方を、すべてランダムではなく、プレイヤーごとに変えられるようにする



改良て・・・1.は大したことないか、あーでも、完全にハードコーディングしてるから、名前を変える度に書き直しにはなるけど。変数つかって、その変数の値だけを変えるようにしてと・・・

2は、人数の変更か。けっこうメンドクサイな。勝敗の判定は、すべてIF文で、プレイヤー1が勝つときのパターンを書いてるから・・めんどくさ!

もう完全に本に書かれた通りの術中にはまってしまっています。


つまり、一度作成したプログラムに仕様変更などが入り、改良するというのはかなり大変で、一から作ったほうがいいんじゃないかのか。というレベルなのです。

これを改善するのがオブジェクト指向で、だから必要なのです。



ということらしいです。オブジェクト指向って。


でも、オブジェクト指向なら本当に仕様変更に強いのかね?そこがよくわからんな・・・




ようやくJavaのプログラミングにはいれた。

2008.10.14 Tuesday 22:47

Javaの環境作りだけでやたらと時間がかかった・・・。さて、元の道に戻ろう。Javaにつきものであるオブジェクト指向を学ぶのだった。

その学び方としては、オブジェクト指向の学ぶ本を使う。
なぜ、あなたはJavaでオブジェクト指向開発ができないのか。




まずは、オブジェクト指向の考え方を使わずに、プログラムを作成して、オブジェクト指向がどういう場面で必要に駆られるのかというところを説明している良書である。

オブジェクト指向を使わずに、じゃんけんプログラムを作れと書かれている。
じゃんけんといっても、下記ルールで作成する。

・プレイヤーは二人で、ジャンケンの様子を再現する
・ジャンケンは3回勝負
・3回勝負で勝った回数の多いプレイヤーが勝ち
・引き分けも1回の勝負
・3回勝負後の勝ち数が同じ場合は、引き分けとする




おし。作成だ。といってもJava未経験に近い俺には、創り方がまったくわからんので、
本に載っているやり方を完全に真似て、作成する。

そして、コンパイル。26個エラー。

まねしたつもりが・・

どこどこだ。


うーんほとんどシンボルが見つかりません。だな。
なんだろう・・・これ。


乱数作成で使っていた関数がramdomになってた・・。8個。
とりあえず修正して、再度コンパイル。

8個減って、残り18個。


のあ!

はさみを示す変数、SCISSORが、定義はSCISSORなのに対して、実際に呼び出すところでは、SCISSORSというように複数形にしてました。なんたることだ。


他にもいろいろでたが、同じようなもので、それらを修正して、コンパイル・・・

今度は、特にエラーもなく通った。

OK!


実行結果は、こんな感じ。

C:\tmp>java SimpleJanken
ジャンケン開始

チョキグー
プレイヤー2が勝ちました!

グーパー
プレイヤー2が勝ちました!

チョキグー
プレイヤー2が勝ちました!

ジャンケン終了

0VS3でプレイヤー2の勝ちです!





まあ、地味だけど、ええんや!Javaの勉強中なんや!




 

やっぱりjava実行、駄目でした・・・・その後原因判明

2008.10.14 Tuesday 19:02

C:\tmp>java C:\tmp\test.class
Exception in thread "main" java.lang.NoClassDefFoundError: C:\tmp\test/class
Caused by: java.lang.ClassNotFoundException: C:\tmp\test.class
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)



さっきのサイトでさらに調べる。

・名前が正しいか?(スペルが正しいか?)
・本当にファイルが存在しているか
・クラスパスが通っているか。



3点のうち、上2つに関しては問題がない。先ほどチェックしたので。
ということはやはりクラスパスのせいのか!?

クラスパスにファイルの存在するパスまで、きっちり書いてさらに実行してみる。


C:\tmp>java -classpath c:\tmp test












Javaプログラム作成中
















うごいたあああああああ!!


ええ?クラスパスのせいか!?
というか、まさか、ファイルに拡張子をつけなかったのがよかったのか!?





C:\tmp>java test
Javaプログラム作成中








ぎゃあああああああああああああああああ。それだけかよ!!!!!!!!!!!!!!!!




まだJavaが実行できない・・・NoClassDefFoundErrorの対処

2008.10.14 Tuesday 18:52

C:\tmp>java sample.java
Exception in thread "main" java.lang.NoClassDefFoundError: sample/java
Caused by: java.lang.ClassNotFoundException: sample.java
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)


WEBで適当に拾ってきたSampleをコンパイルして、実行すると上記のようなエラーになってしまいます。。。なぜなんでしょう。


NoClassDefFoundError:の対処ということで、検索してみる。



まず。sample.classというクラスが本当に存在しているかチェックをする。

んなもん、あるに決まっているやろうが!!







あれ?




あれれ?




sample.javaをコンパイルしたら、test.classになっていた。
なんとお!!


 

PREV1 2 3 4 | NEXT

忍者ブログ