はてなキーワード: サブクラスとは
プログラミングできる気になった自称中級者は、ソースコードに共通のパターンが現れると決まって、その処理を関数などに共通化したがる。
たしかに、そうすることでソースコードは短くなるし、一見して保守性が上がったような気になるのだが、それは間違った作法だから止めろ。
細かいこと言っても伝わらない自称プログラマが読んでることを想定して、先に結論を簡単に書いておく。
なぜコードを共通化するのがいけないのか。理由は簡単だ。要するに、コードが似ているのは単なる偶然であって、それらは別の処理だからだ。
別の処理だから共通化するのはおかしいし、もし共通化した処理の一方のみ仕様が変わった場合、その修正は他方にも影響してしまう。つまり、保守性が下がっている。
たとえば、同じプロジェクトの中に、10%の消費税を加える処理と、10%の金利を加える処理があったとする。この2つの処理はともに元の金額を1.1倍する処理であり、全く同じ処理であるが、共通化してはいけない。
これらを共通化してしまうと、たとえば金利が8%に変更になったとき、金利計算の処理だけではなく、消費税を計算している箇所すべてを変更しなければならなくなる。
実際のアプリケーションでやりがちなのは、複数の処理の「事前処理」「事後処理」などを1つの関数にして、呼び出し毎に細かい挙動を引数で制御するようなパターンだ。
これは結局、改修を重ねる度に「事前処理」「事後処理」の内容が使用箇所によって全く異なるものとなり、それに対応するために
他にも、GUIアプリでユーザーの応答を待つDialogクラスなんてものを作って、使用箇所ごとにメッセージやボタンに割り当てる処理などを切り替えることがある。
これも間違いなく、プログラムが成長するにつれて破綻する。たとえば、ある場所のダイアログは、表示するメッセージがテキスト形式のみではなくなり、脇に画像を表示するかどうかのフラグをコンストラクタに渡したり、Dialogを継承させて表組みを表示するTableDialogサブクラスを作ったりすることになる。ボタンが「OK」と「キャンセル」の2種類の場合じゃなくなって、表示するボタンの数をコンストラクタに渡したり、ボタンに割り当てる処理をリスト形式で渡したりし出す。
こうして、最初は良い設計に見えたDialogクラスはどんどん複雑になる。こうなった原因は明らかで、本来は異なるものを共通化したからだ。おかしな色気を出さずに、素直に別々に実装しておけばよかったのである。
プログラミングをする上で「コードを共通化する」なんてことは意識しなくていい。それよりもプログラマがすべきことは、処理に適切な名前をつけることだ。そのプログラムにおいて「単なる変数の操作」を超えた意味のある処理には名前をつけろ。そして、同じ意味の処理なら同じ関数を使うし、違う処理なら違う関数を使う。それだけだ。コードが共通化できるかどうかなんて全く関係ない。
変数、関数、クラス、名前空間等が再利用のための機構だという先入観は一旦捨てろ。それらの真の意義は、「関心の分離」にある。つまり、実装を隠蔽し、その意図を抽象するために存在する。たまに勘違いしてる奴がいるが、別に1回しか使われない関数とか、1行しかない関数はあってもいい。というか、この原則にしたがって設計すると、ほとんどの関数(or メソッド)は数行になる。
上の消費税の例で言えば、「消費税を加える」「金利を加える」処理は、明らかに単なる算術演算以上の意味のある操作だから、関数化する。そして、それぞれの実装は当初の仕様では奇しくも全く同じになる。消費税を加える箇所では前者の関数を呼ぶし、金利を加える箇所では後者の関数を呼ぶ。
これはこう言い換えることもできる。消費税を加える関数を変更するのは、消費税の計算処理が変わったときのみであり、金利を加える関数を変更するのは、金利の計算処理が変わったときのみである。つまり、すべての関数は、それを変更する理由がただ1つになるように設計しろということだ。
こういうアプローチでプログラムを書くと、ソースコードはあたかもそのアプリケーションのドメイン特化言語で書かれたかのような見た目になる。
また、一つ一つの関数は小さく、理解しやすく、テストやデバッグも容易になる。そして、結果として再利用もしやすくなるし、プログラムの変更も容易になる。
https://nekogata.hatenablog.com/entry/2018/09/10/163206
この記事がはてブで大絶賛されてるが、個人的にはセンス無いなーと感じたので言語化してみる。
今回の仕様を図で書くと
みたいな感じになるとする。
すると、今回スライドで問題視しているのは矢印の右側の通知の部分が1クラスに共通化されている点。
しかし、オブザーバーパターンの出番は図の矢印の部分が絡まり合って処理が複雑になってしまった場合。
今回は1つのイベントから複数のリアクションが発生することは想定しないので
オブザーバーが不要なのは当然。選択肢に出てくるほうがおかしい。
そもそも問題認識(通知部分が問題)と解決策(矢印部分を解決)がズレてるから話がおかしな方向にいってる。
Notificationクラスのサブクラスを作ろう、ならまだ分かる。
確かに設計を言語化するのは大事だが、言語化というのは「それっぽいことは幾らでも言える」危険性がある。そもそもプログラミングというのは芸術であり文学なんだから、センス無いのに言語化を頑張っても「一見それっぽく聞こえるけど間違ってる説明」しか出てこない。
親衛隊さくっとつくった
反転の呪いはどっかで入手した秘伝書が1個あったからラハールちゃんに使った
うーんきゃらかい用アイテムはサブクラスマックスで9999にしたら戦闘時にサイコロ増やすのはもう捨てていいかもなあ
最初はすごろくめんどいとも思ってたけどまあこれはこれでいいのかもしれん掘っていくより早く終わるときもあるし
単純にマビ継承考えたらかなり楽だわ
3とか4はこれに比べたらやっぱわかりにくいよなあ・・・
4はかろうじてわかったっけかな
あとエキスでちょこっとドーピングしたら、ブレイブアップとマルチアタックなしのまちぇんじからのビッグバンで1ターンで終わるようになった
たまにかすりヒットで2ターンかかるけど、毎回マルチアタック。ブレイブアップする手間に比べたらたいしたことない
1時間で1000万ためられるな
でもまだ捕獲じゃなくてメガホンで投降に頼ってるだけだから捕獲できるようになったらもっと高速にできそう
んでふと思ったけどシーフをエキスの使うキャラに選んだの失敗だったなあ
あーあメタリカにしとけばよかった
まあ今更だな。。。
うーんでもあっというまに100h目前・・・やっぱディスガイアこわいわー
うーん効率化のためにあーしようこーしようって調べてるときは楽しいけどいざやるとめんどくさすぎてすぐいやんなっちゃうな・・・
とりあえず修羅ぷりにー大魔王倒してラハールちゃんのまびを3にしてマスブラスターやったらバフつきで★12くらいまで修羅練武4いけることは確認した(ステータスで2000万超えた)けど、
10人で修羅練武4★5だと一人あたりサブクラス★2つくらいしかたまらなかった
結局これだと何回か必要だし、★5から6までの間が結局たくさんいるから、特定のキャラに絞ってジオブラストのほうが効率よさげ
★12捕獲できたからスペシャルで絞ろうとしたけどまったく絞れなかった
メガネカレーしてるからHPで削らないといけなかったらしいなるほど
あとサルバトーレが絞る効率20%UPのマビもってるらしいから育てるかなあ
めんどいけど
キャラかいで勝てる程度だけどアサルトアタックとダブルアタックがあればとりあえずよし
ジオブラ要因以外はハンターチームにいれれば★20でもイノセントだけなら一撃しできるしな
まあのんびりやろう
マスブラスターをラハールちゃんに継承させようとしたら固有まびは継承できなかった・・・はずかちー
うーんアイテム界もぐることも考えたらいずれにせよどっかでランデマ要員のけんじゃを育てないといけないんだな
汎用キャラにもサブクラ設定できるようになったぶん最初よりかはだいぶらくになってるはずだし
しーふは9999にしてサブクラ稼ごうとしたらなんか修羅エクのジオブラ1発でMAXになりにくくなってて、あれレベル低い方がクラス熟練度たくさん入るんだったっけって思って転生させた
つーか転生時の有料での自動レベルアップするのと1から育てるのとだったら後者のほうが成長率いいのな
邪悪ちゃんもすぐ倒せる
でもキャラ会でめんどいのはメニューないにキャラ一覧がないから邪悪ちゃんがどこにいるのかわからんことだな
最低でも30回以上アイテムかいにもぐらないといかんのはめんどすぎる
しかし昨日80hくらいでトロコンしたってひとのブログみかけたけどとてもいけるきがしないわ
まだしゅらとらぺすらないのに
今調べたらいろいろ目からうろこだった
これでマスブラスター・アサルトアタックもラハールちゃん使えるかも!
あとサブクラスあげのめんどくささ、ジオブラストの方法は最初だけで、もう一人でもサブクラマスターしたようなやつがいて修羅練武4いけるやついるなら、それを使ったタワーでいけるんだって!
これなら複数人どうじにいけるなー
一人ひとりジオブラってのはめんどすぎだと思ってたからほんと助かる
いや、タワーでいけるよな?
早速ためしてみよう
※一般的な番組をスキル、アニメ等のオタ向け番組は特殊性が強いので回復スキル、韓流をPK用スキルとしています。
実装直後から現在に至るまで、華やかで攻撃的なスキルを揃え続け、その殲滅力の高さから最強厨に人気なクラス。
反面、非常に打たれ弱くちょっとした反撃ですら瀕死に陥ってしまう為、他クラスから見て「なんでそんなに必死になるのか」という行動をよく取る。
このゲームの人気に陰りが出始めた頃異動してきた新たな責任統括が、それまで狩り中心だったゲームを「金が搾り取れるから」という理由で、PK推奨ゲームに転換する方針に。攻撃が売りで最強厨御用達のこのクラスはガンガンPKスキルを増やして行き、PKの代表格というクラスに。しかしPKアレルギーのある多くのユーザーから猛反発を食らい、匿名掲示板等で集中して叩かれる存在になった。ただし、このクラスを選んでいるユーザーは最強厨が多い為、叩かれたら倍にして叩き返すという行動を取る者がほとんどで、ゲームは混沌とした状態になっていった。
また、規約違反や重度な迷惑行為で垢BANされたのが多いのもこのクラスの特徴。
基礎体力が高く、めったな事ではバテないクラス。
覚えるスキルは良くも悪くも安定感のあるものがほとんど。スキル実装直後にすぐテコ入れが入り、最終的には全く別物のスキルになっている事も少なくない。
他クラスと決定的に違うのがクラス固有クエストであり、感動を誘うのが狙いとするお涙頂戴シナリオが特徴。尚、クエストを進めるにあたり、ハンパなく長い移動を必要とする為にユーザーからは「マラソンクエ」と呼ばれている。
PKスキルはそこそこあるものの、CXほどの量があるわけでもなく内容も無難な為、叩かれる事はあまりない。というかCXが目立ちすぎて他クラスのPKスキルがあまり注目されてないのが現状である。
とにかく全てにおいて無難なクラス。ただし回復スキルは性能はそこそこだがMPコスパが悪い。
実装直後は強力なスキルを所持し、全クラス最強の能力だったが、アップデートが進む度他クラスが強化されるのに対し、過去のスキルと似たり寄ったりなスキルや、他クラスの劣化二番煎じのスキルばかりが増え、現在は最弱と称されるようになった仕様に泣かされたクラス。このクラス同士が会話すると、大抵は「あの頃はよかった」話になってしまう。所謂懐古厨が多い。
しかし、過去、重大な不具合を起こしたスキルに対し、急遽用意したやっつけ程度だった新たなバフスキルが、主婦プレイヤーの間で大ブレイク、以後このクラスの代表的スキルとして現在も愛され続けている。
最近、回復スキルの量を増やし、第2のヒーラーとしての役割を担わせるんじゃないだろうかというアップデートが多い。
戦闘用スキルよりもそれ以外のスキルを得意とするバックパッカー系クラス。特にギルド運営に役立つスキルを豊富に持つ事から、政治ゲーを楽しみたい人に選ばれやすい。
しかし時代の波には逆らえず、戦闘スキルがどんどん増え、それと同時に回復や非戦闘スキルは徐々に減っていった。
ある時期から戦闘力を上げる為に召喚スキルを増やし始める。この召喚スキルがなかなか強力で評判が良く、徐々に人気クラスへと変貌していく。しかしあまりにもサモンが強い為に「サモンが本体」「サモンのサモンによるサモンの為のクラス」と揶揄される事も。
PKの押し付けの時代に突入しても、サモンが強力すぎた為にPKスキルはあまり実装されなかった。今でもサモンに頼り切った戦い方が中心である。
ただ、あくまでバックパッカーとしての役割にこだわり、戦闘以外のことに集中するユーザーもまだまだ少なくは無い。
とにかく回復スキルが豊富なクラス。他クラスとは一線を画している。
しかしヒーラーとしての悲しき性か、戦闘スキルは貧弱で、尚且つ狩場を限定しているものだらけであり扱いづらく、このクラスを選んでるユーザーは少ない。
実装されてから全くコンセプトが変わらないのが特徴。ただひたすらにマイペースを突き進む。たとえどんな酷い状況でもヒールし続けるその姿は「それでこそ俺らのTX」と賞賛を浴びる。しかしマイペースというのは自己中心的という事でもあり、規約違反行為をする者も意外と多い。
PKの時もやる事は変わらない為、「PKなにそれおいしいの?」状態である。
「総合」「教育」「BS」と切り替えができるサブクラスシステムが導入されており、一人で何でもできてしまう為、ソロユーザーに好かれている。
実力はあるものの実装当初のスキルは独りよがりな上、とにかく地味で人気はイマイチだった。しかしアップデートが進むたびに、ユニークさを押し出したスキルが増え、一部のプレイヤーから熱狂的な人気を集めるクラスになった。戦闘、支援、回復スキル全てにクセがあって個性が強く、初見で「これはNHKだな」と一発でバレるくらいである。
実はPK押し付けブームの前からPKスキルを所持してたりする事は有名。現在はPKスキルをサブクラスに押し付けている。
ソロ向けクラスのはずなのに、何故か戦争クラスの集団対人戦にはめっぽう強いスキルを多数所持している。実は戦争好き。
このゲームは、超大型アップデートで画像が綺麗になったものの、過疎化が進み売り上げが落ちているのが、現在の運営の悩みである。
K&RのCで書かれたプログラムを渡された(もう少し正確に言えば、VisualStudioのWizardで作られたものにK&RのCでコーディングしてある(C++ですら無い)ので純粋なCでは無いが果てしなくK&RのCだ)。あと、これを作った人はどうにも「ポインタ」の概念が無いらしく、無駄に多次元配列だったり、配列のアドレス渡しとかが多用されている。
作業指示は、これを流用して、C++/CLIかつ.netFramework3.5使用かつ新規案件に対応せよ、との事。
個人的にはどう見積もっても3人で4ヶ月かかる量なんだが、予算が1人で1ヶ月、と言って来た。理由は「Cからの流用だから」。
参ったな。自分としては、C++/CLIはもはや別言語だと思っているんだが。
どうにも上司と顧客に説明出来ない。説明出来ないのは、自分が理解していないせいだ、と言われればそれまでなのだが、自分の感覚で言うと、高段者がうっている将棋や囲碁の一手を初心者に教える、とでも言うか、小学生に微分積分を教えるというか、そんな感覚がある。
いや、相手が、K&RやANSI、C++、C++/CLIを分かっている人間になら、説明は出来るのだが、相手のレベルに合わせて、説明が出来ない。
今回のこれに限らず、見積もりとかすると、「なんでこんなに時間かかるの?」とか「高い」とかよく言われるのだが、やっぱり説明が出来ない。デスマってるプロジェクトには、よくさらなる人員投入がされる事が多々あるのだが、デスマってる時点で負け戦だし、「混乱したプロジェクトに人を投入すれば、さらに混乱するだけ」と自分は思っているので、やめてもらいたいと思っている。
「あんたの小学生になる子供が、100人いたら、東大に合格するくらいの学力が発揮されるんですか?」と問いたい。
あれは、VisualBasic4が出た頃か。それまでWindowsプログラムというものをCまたはC++で書いていた自分には、驚異的な言語に思えた。そしてみんな言う。「VBで作れば簡単ですよ」
自分にはVBという言語はとてつもなく難しい言語に思えた(MFCは論外)。なぜなら「かゆいところに手が届かない」言語だったから。だから、皆が言う「VBなら簡単」の理由がさっぱり分からなかった。ちょっとした使い捨てツールや、極々Windows標準的な事しかやらないのであれば、VBは簡単な言語であったのは分かる。実際自分もそういう使い方をしていたから。
そして、うちの職場ではそんな製品を作る所では無く、仕様を満たすためにはサブクラス化とかWin32APIを使うとかしないと実現出来なかった。もちろん「VBで作れば簡単ですよ」と言っていた連中にサブクラス化など理解出来ようも無く、ただただ右往左往してデスマーチに突入していった。
その時も、お偉方や顧客に説明が出来なかった。「VBなら簡単」と言っていただろう、と言われるだけ。
まぁ、VBも.net時代になってから、だいぶマシになってきたと思うけどね。少なくとも、スレッドセーフになってくれただけでもありがたい。
まぁ、その辺はともかく、もしかして、デスマやIT土方とかなるのは「説明が出来ないから」なのではなかろうか?と思えてきた。必要な時間と予算を説明出来ないから、泥沼になるのではなかろうか、と。
説明が出来ない限り、プログラマーは永遠にIT土方であり、地位向上は望めないと思う。人月の神話じゃなく、ファンクションポイント法とか、なにか定量的に説明出来ればいいのだけど。ファンクションポイント法だって、それが分からない人には通じないわけで。「小学校に入学した児童にも分かるような」説明が出来ないとダメなんだろうなぁ。どうすればいいんだろ?
これは http://anond.hatelabo.jp/20110316202255 の続編です。
GTをやる前に改を書いてくれている人がいてとてもしっかりした内容なのでちゃんと勉強したい人はそっちを見てね!
d:id:ryoasai:20110317 - ドラゴンボールで学ぶオブジェクト指向 改 | 達人プログラマーを目指して
またオブジェクト指向については
d:id:m-hiyama:20080109 いまさらながらだけど、オブジェクトとクラスの関係を究めてみようよ | 檜山正幸のキマイラ飼育記
がとても詳しいです。合わせて読むとかなりしっかりと理解出来ると思います。
ホットエントリに行くとは思っておらず、皆様ありがとうございます。
「ドラゴンボールをオブジェクト指向にする」というコンセプトではなく、「オブジェクト指向を(無理矢理)ドラゴンボールで説明する」という遊びだったので
プログラマーの方々にはツッコミを受けてしまいましたがここは遊びだと思って楽しんで下さい…。
ドラゴンボールは小さい頃から大好きでしたが流石にうるおぼえ過ぎました。
それはさておき「説明する題材を決める→好きな漫画から無理矢理当てはまりそうな例を考える」という思考実験なので、気が向いた方は色々考えてみると楽しいと思います。僕は楽しかったです。
これは難易度が高そうです。
やっぱりドラゴンボールで例えると分かりやすいな!
無理がある!
デザインパターンとはドクターゲロが考えた「こうやって設計すれば色々捗るぞ」という例のことです。実際はGoFという人たちが考えたもので23個のよくあるパターンに名前を付けて整理してくれたわけですね。
23個の中にはブルマさんですらわからないものが多いので(さすがドクターゲロですね)良く使う、代表的な物をいくつか紹介します
Singletonは世界に一つだけしか存在出来ないようにする方法です。
balls = new DragonBalls(); //これでは誰でもドラゴンボールを作れてしまう! balls.callShenron();
クラスの中にはいくつかのメソッドがありますが、簡単に言うと外から呼べるもの、外からでは呼べないものの
二種類があります。そうやってメソッドを保護することで世界の崩壊を防ぐわけですね。
基本的な戦闘力をアップさせるには本人の努力が必要になり、外から簡単に挙げられてしまうとジャンプの三本柱が外れてしまいます。
ただナメック星の最長老や界王神などはかなり偉いので、本人の才能を引き出すことが可能でした。
現実には思いつきのような仕様を後から言われることが多々あります。困ります。
//地球上にひとつだけ存在するドラゴンボールをつくろう class DragonBalls{ private DragonBalls(){ //ドラゴンボールを作れないように生成メソッドを保護します。 } static function sagasouze(){ static singleton_dragonball; //ドラゴンボールを生成。 //DragonBallsクラスの中なので、保護してある「new DragonBalls()」を呼べます。 if(!singleton_dragonball)singleton_dragonball = new DragonBalls(); return singleton_dragonball; } }
地球のみんなは地球語しか話せませんが、ナメック星にいるクリリンを通して願いを叶える必要があります。
クリリンももちろん地球語しか話せませんが、ナメック語を話せるデンデがいるため、地球のみんなは願いを叶えることが出来ます。
class Kuririn{ private dende = new Dende(); function request( wish1, wish2, wisth3){ this.dende.request(wish1); this.dende.request(wish2); this.dende.request(wish3); } } kuririn.request( "ピッコロを生き返らせてくれ", "ピッコロをナメック星へとワープさせてくれ", "ナメック星にいる孫悟空とフリーザ以外を全員地球へとワープさせる" );
この場合のメリットはデンデが何をやっているかクリリンをプログラミングした人が知る必要が無いということです。
地球の人はナメック星にいるナメック星人が「デンデ」であることを知る必要もありません。
それでも願いは叶うんです。
本来であればデンデやクリリンは願いが叶うのを待つ必要がありましたが、地球の人は一気に伝えることが可能なように設計しました。
//デンデクラス。ナメック星人は英語でNamekianらしいです。 class Dende extends Namekian{ function translate(word){ namekian = *****//ナメック語に翻訳します。 return namekian; } function request(wish){ static polunga; if(!polunga){ polunga = DragonBalls.spell("タッカラプト ポッポルンガ プリピット パロ"); } polunga.ask(this.trasnlate(wish)); } }
大まかなアルゴリズムだけ決めておいて、実装はサブクラスに任せる設計がTemplate Methodです。
ナメック星に行く方法を考えた時いくつかの方法がありました。古い宇宙船を探してきて直して載せて…っていちいち書くより同じメソッドでナメック星に行けたほうが便利ですね。
abstract class WayToNamek{ abstract function prepareSpaceShip(); abstract function launchSpaceShip( ship ) ; function gotoSU839045YX( people ){ ship = prepareSpaceShip( ); //船を修理します ship.load(people); //人を載せます this.launchSpaceShip(ship); //船を出発します。 } }
ナメック星に行く方法を定義したので「ブルマ、クリリン、悟飯」組と「悟空」をそれぞれナメック星に連れて行きましょう。
way = new WayWithKamisamaShip(); way.gotoSU839045YX( buruma, kuririn, gohan ); way = new WayWithSaiyajinShip(); way.gotoSU839045YX( goku );
と簡単に方位SU83、距離9045YXまで乗員を連れて行くことが出来ます。
二つの方法を実装します。神様の船を修理して行く方法と、サイヤ人の船(悟空が乗ってきた船)で行く方法の二つです。
//神様の船で行きます。 class WayWithKamisamaShip extends WayToNamek{ function prepareSpaceShip(){ return new KamisamaShip(); //船を準備します。神様の船を使います。 } function launchSpaceShip(ship){ ship.inputByVoice("ナメック星に出発"); // } } class WayWithSaiyajinShip extends WayToNamek{ function prepareSpaceShip(){ return new SaiyajinShip(); //船を準備します。サイヤ人の船(フリーザの船?)を使います。 } function launchSpaceShip(ship){ //audio = new HighSpecAudio(); //ship.setAudio(audio); ship.turnOnCenterButton(); //真ん中のボタンを押すだけ } }
元になる船も違いますし、発射の仕方も違いますが同じ呼び出し方が出来ます。
オーディオの位置が決まりませんでしたが、今回の運用では不要とのクライアントからのご意見でしたのでだったので
せっかく用意したオーディオも無駄になりましたが、コメントアウトしてあります。
>http://www.geocities.co.jp/SiliconValley/8916/Macintosh/rimo.tv.screensaver.html>
rimo.tv.screensaverは、YouTube に掲載されている人気の動画から約1日おきに新しい番組プログラムを生成・配信する はてなのサービスである http://rimo.tvを表示するMacOSX用スクリーンセーバです。
<<
勝手にclass-dumpとstringsとotoolで調べたよ。概ね間違っていないと思う。