2012年07月17日

Struts1のhtml:checkboxではまりました。。。2

ちなみにですが、Struts1のActionFormにはresetメソッドをオーバーライドすることで、一応はチェックボックスを一度初期化することができます。

よって、ブラウザからリクエストを受けたタイミングで一度チェックボックスの変数のみfalseにし、もしブラウザから値が送信されていればtrueに変更することで、チェックボックスの状態を扱うことはできます。
実装するとすると以下のようになろうかと思います。

・ActionForm

package com.sample;

public class Form extends ActionForm {

/** チェックボックス */ // ここはhtml:checkboxのproperty属性名と一致
private boolean check1 = false;

// setter/getterは省略

public void reset(ActionMapping mapping, HttpServletRequest request) {

check1 = false;
}
}


ですが、画面の仕様やフォームの仕様というものは変更されることがあります。
ActionFormは普通には画面の入出力情報を保持している入れ物と考えておくほうが非常に分かりやすく、その中に例外的にresetメソッドが実装されている状態ですと、仕様変更時にresetメソッドの実装修正が発生してしまい、バグに繋がる恐れがあります。

一応、もし実装と設計とそれぞれの相関を完全にデータとして保持し、影響調査により修正すべき箇所を洗い出すことができるならば、resetメソッドは有効に働くでしょう。

ですが、私の個人的な意見としてはresetメソッドやActionFormにはvalidateメソッドを実装できますが、それらはActionFormでオーバーライドしないほうが良いのではないかと考えています。
できる限りそうでない方法を検討し、各クラスや成果物の責務を明確かつシンプルにしておくことを心がけるべきだと考えています。

ちなみにですが、StrutsのJavadocでも理由はいくつかあげられていますが(チェックボックスを初期化するのが必要なら仕方なしとして)、オーバーライドしないことを推奨しています。特にセッションスコープに格納しつつ、複数画面で使いまわす場合には要注意です。

一応、忘れていないですよっていう意味も込めての補足で記載しました。
posted by Kiruahさん at 22:41| Comment(0) | TrackBack(0) | ノウハウ

2012年07月14日

Struts1のhtml:checkboxではまりました。。。

久しぶりにStruts1を見ました。。。理由はまぁ色々とありまして。。。

元々StrutsでCheckboxをどういうふうに処理すべきかなんていうのは覚えておりません。
ただ、ブラウザはWebサーバーにチェックされていないCheckboxについては値を送信しないことは知っていましたが、実際jcwebを使うとJavaの中から直接Checkboxの状態を取得できてしまいますし、仕事ではCheckboxはあまりつかわないようにしていたので考えたことがありませんでした。(これはダメですね。。。しかもJSFの他のOSSライブラリを使っていたり)。

で、聞いた話によると、どうもうまくStruts1でCheckboxは未だ難しいようです。
具体的には以下の場合です。
・2画面の画面遷移であり、共に同じActionFormを使う
・1画面目でとある条件(DB検索した結果を入れるだけですが)を満たすと、チェックを画面につけた状態にする
・そうでなければチェックしていない状態にする
・チェックがついている状態で表示された場合、チェックを外してサブミットしても、チェック状態と同じ状態でブラウザから値が送信されてくる

環境としては以下です。
・Windows 7 (無関係でしょうが)
・IE9
・JDK6 (無関係でしょうが)
・Tomcat 7.0.29 (無関係でしょうが)
・Struts 1.3.10
・画面はJSP (無関係でしょうが)


実際に私もデバッグしてみると、valueの値が送られるとかそういう感じでもなく、checkedの属性があればon、なければoffが送られるような感じの挙動でした(忙しかったのでcheckedの値とvalueの値がどうこうまでの検証まではしていません。ごめんなさい。)。
なので、特効薬としてこんな感じにしました。

・struts-config.xml







・ActionForm

package com.sample;

public class Form extends ActionForm {

/** チェックボックス */ // ここはhtml:checkboxのproperty属性名と一致
private boolean check1 = false;

// setter/getterは省略
}

ポイントとしては、型は必ずbooleanを使うところです。

・JSPの中身(抜粋)


チェック
送信



JSPについては、実は以下の実装の方がいいのかもしれません。ifで書いてますが、論理否定に変えた方が美しいでしょう。

・JSPの中身(抜粋)


チェック
送信


あとは、onclickの箇所を別functionにするとか、どのブラウザでも確実に動作するためにjQuery化するとか、色々と工夫の仕方はあるでしょう。

ちなみにですが、SyntaxHighlighterを使っておりますが、勝手にタグ部分が大文字になっております。ソース上は全部小文字で記述しておりますのでご注意ください。


なんとなくやってみて、なんとなく動作したものなので、もっといいやり方があればご教授ください。
posted by Kiruahさん at 19:23| Comment(0) | TrackBack(0) | ノウハウ

2012年07月12日

クラウドつながり。私が本当に使えると思うクラウドはSIer開発案件向け。

SIerは顧客にクラウド環境を売っています。
売れているかどうかはおいておいて。。。

社内ではよく、サーバーリソースが足りないとか、検証環境が足りないとか聞きます。
そして性能検証したい環境なんて、テストが終われば用済みであったりします。
逆に開発中は大規模にリソースが必要です。

また顧客の保守環境は、リリース前はきっちりとしておきたいけれど、リリースが終わればしばらくは縮退したい。でも保守期間中はきっちりと保存したいという要望があります。

そうです。これこそクラウド環境はもってこいの内容だと思いませんか?

ですが、弊社ではやっと考え始めた節がありますが、まだまだ本格的にどうにも使いにくいものです。
もっとメリットを前面に出して、いかに案件のコストが減るのかを明確にして、さらにSourceForgeやGithubのような機能や営業支援機能、営業情報管理、リリース管理、不具合管理、課題管理、ライブラリ管理、バージョン管理、Wiki、ブログ、掲示板、アラート機能、マニュアル、ドキュメントやソース全文検索機能、ナレッジベースとその統合化、構成管理、プロジェクト管理(コスト管理、スケジュール管理、メンバー管理、等など)、ユーザー管理、認証管理、テスト管理、承認管理、ビルドサービス(CI的なものなども)をあわせて、社内で売上を立てる部署を作るべきだと私は考えています。

今、その方向で何かできないか、実はこっそり考えています。

2012年07月11日

クラウドは失敗してもらいたい

今やどこでもクラウド、クラウドと言われています。
私が一番最初にクラウドという言葉を聞いたのは、2008年ぐらいに品川で行われたガートナー社の講演の中です。当時はまだ、クラウドという言葉がバズワードレベルで紹介され、これから定義をしていくという感じでした。

当然ガートナー社ですので、要は「ブームはこれから自分たちが作るものである」と言っても彼らにはいいのかもしれません。ただ、単純に当時、社内へその話を持って帰った時の上司達の反応は、「クラウドって何?」でした。私は「単純にいえば、仮想化です。ネットワークの先にあるサーバーリソースを隠して、使いたい時に使えるようにして、自社データセンターがなくてもコンピュータ資源を使えるようにするようです。」と話したら、「そんなのいらない」という回答を上司から得た記憶があります。

そんな弊社も今や、国内に何箇所もデータセンターを持ち、そしてクラウドサービスもやっています。一応は名も売れているようです。例に漏れず上司たちはクラウド、クラウドと叫んでいます。

今、クラウドは旬な状態から枯れる位置に移動しようとしています。

ですが、私が言いたいことは、そんなことではありません。


クラウドのメリットやデメリットは色々と営業として語られてきています。
でも、メリットの中には耐障害性だとか、運用コストが安くなる可能性があるだとか、そういう話があがります。もちろん、パブリッククラウドからプライベートクラウド、併用等も含め。。。

正直なところ、そんな話、今となってはウソでしかないのではないかと考えています。
あらゆるメリット・デメリットを検証してもし尽くせないのですが。。。ここで2つ見てみます。

1. データセンターを持つわけではない、DRやBCPサイトを別のクラウドセンターに用意すれば業務継続性に強い

これは本当にそうでしょうか?自社内においてもネットワークの切断があれば、社内システムは使えないわけです。それがさらに社外に及ぶネットワーク切断が発生する可能性があるわけです。
今ではSalesforceは日本にもデータセンターがありますが、一時はオンライン障害が発生するまでは日本にデータセンターはありませんでした。SaaS環境の上で営業売上を分析するシステムを構築していたとして、さて大地震で海外につながるあらゆるネットワークケーブルが切断されてしまったらどうしますか?衛星回線でも使いますか?衛星回線は高価です。常時のコストは安くとも、障害があった時の代替案としてはコストがかかり過ぎます。

結局どこにセンターを置いたとしても、TCP/IPとインターネットによるネットワーク網が冗長であることがどれほど謳われたとしても、SIerレベルではそれを営業が「本当に大丈夫なんです」と話すのはウソです。「100%大丈夫」はありえません。
私が社内でよく切り出す話題に、「伊豆半島にしか本社、支社がない会社があって、弊社の東京データセンターを利用している会社があったとき、決算期に富士山が爆発して伊豆半島だけ分離して流されたらどうしますか?」とインフラ担当者に聞くと、彼らは「そんなこと起きないよ」と返します。

SIerが考えている想定はつまりはその程度なのです。
SIerにとっては伊豆半島が離れることはないし、まじめに考える必要もないし、本当に離れてしまっても自分たちが困ることがないからまじめに考えないのです。

それでもクラウドって障害に強いのでしょうか? その強さを一度定量的に示してみてくださいとSIerに聞いてみれば分かります。弊社も若干某米国のサーバーにのっているクラウドもありますが、そのサーバーまでの地面に埋め込まれた回線数を全て把握していて、1時間で全て回答できないでしょう。もしできるようであれば、弊社を利用してくださっても問題ないかもしれません。。。


2. コストが安くなるという宣伝文句に騙されていませんか?
これはつまり、逆に言えば、今のコストは高くしているのですよと言われていることと等しいです。
安くなる=そこに弊社の中で営業努力やコストカット、効率化があって安くなっているという事実はありません。
遅ればせながら参入したから営業的に、クラウドにすると他社より安くしますよという言葉は言います。が、これは営業努力の結果でしょうか?

おもしろいことにSIerの素晴らしいところは、自社の顧客の業務をシステム化し、そして業務上発生するデータはデータベースにのせることはできるのですが、自分たちの業務はデータベースに表現できないと言うのです。また、他業種は自分たちがコスト削減や効率化をシステム化することで実現しているのに、私たちはそんなことを推進しているわけではありません。

同じ仕事、同じお金を稼ぐ作業、同じ何かをデータ化する作業。何が違うのか?

言いたいことは簡単です。クラウドだからコストが安いというのはウソなのです。
どちらにしてもデータセンターは運用しなくてはいけないのです。ただ、クラウドとしておけば、顧客がサーバーを使う際のSIer内のCPU時間やメモリ、運用コストを効率良く分配できそうだと考えているだけです。ただし、当然SIerの視点では正しい考え方です。
でも、顧客の決算期などの最繁期なんて業種が同じだったらどこの会社もほぼ同じ時期でしょう?
だから、データセンターで監視しする運用コストはそんなに変わらないはずなのです。。
ちょっとだけシステム化されているだけ。要は客寄せパンダのためのコスト表が提示されているのです。


さて、話題を変えさせてください。

今や禁止用語に近くなったP2Pという技術があります。また、P2Pとは少し違いますが、SETI@homeなんていうものもあります。

これらに共通して言えることは、みんなのPCを少しずつリソースを共有して、何か大きなことをしようというものです。
P2Pでは悪いイメージが先行していますが、業務で暗号化して利用してしまえば複数の社内PCに対してデータを社員が利用しているPCのほんの50GB(最近はHDDに500Gとか積んでいるので問題ないでしょう)を利用させてもらって、社内の業務情報を複数箇所に分散させて保存させるなんてことは考えたことがありますか?

ちょっと特殊なアプリケーションですが、業務の計算を社内に出社しているコンピュータを利用してその空きCPU時間を利用させてもらって業務計算させるということは考えたことはありますか?最近はデュアルコアどころか、クアッドコア(4コア)のCPUを積んでいたりします。
SIerで開発をやるようなところではなく、WordやExcel、PPT、ネットが見れてちょっとしたアプリが使えればいいような業種であれば1コア分を使わせてもらっても影響はそんなにないと思いませんか?

自社の社員のPCをクラウドのようにディスクスペースとCPUコアを分散して使う。
その社員が日本全国にいて、10支店ぐらいあって、500人いて、毎日彼らは出社してくるわけです。閑散期も最繁期も。そして、最近はWake On LANがありますので、夜間バッチ中にリソースが足りなくなるようであれば、パケットを飛ばして社内のPCを立ち上げることもできます。
CORBAなんて技術もHadoopなんて技術もあるので、社内の全部のPCを使えばいろんなデータをバックアップしながら複数人で分散し、いろんな社員のPCのCPUタイムを使えば十分なことができます。

ただし、前提として中小企業ではこれらは難しいかもしれません。。でもクラウドなんてものをやってみようなんて言うところは案外大企業が多いです。


言ってしまえば私の話なんて極論です。でも、自社の社員のPCに暗号化されているデータと、どこかのSIerという会社が「暗号化してますよ」といっているセリフ。私だったら前者の方が安心します。
耐障害性も、社内のLANが有効で社内のPCがしっかりワイヤーで固定されていたら、火事や津波ではダメかも知れませんが、外部とのネットワークが切断されていても社内のPCだけで業務を継続できませんか?


私は本当にクラウドが顧客が本当に期待する当たり前品質を満たせるのか、甚だ疑問です。
目先のコストだけで流行にのっているだけに見えます。それはSIerや顧客共にです。
今はまだ何も起きていないから、良い方にも悪い方にもどうとでも言えます。
でも、SIerの責務はどうとでも言えることを言うことでも、100%であるかどうかを検証もせず答えられもせず、「大丈夫です。」と言うことでもないと、私は考えます。


お客様の皆様にはどうか、本当にどうやって自社の資産を守っていけばいいのか、単純にSIerの営業トークを聞くだけでなく、疑って、検証して、こういう場合はどうなのかを問い詰めて、その上で答えを出して欲しいと切に思います。

-----
2012/07/13 分かりにくい表現を修正しました。

2012年07月10日

今、いろいろと作りたいもの

最近、とても物欲が強いのか、いろんなものが欲しくなってきてしまっています。困ったものです。そのほとんどはしかも、ほぼ実在しないような代物です。
今はすぐに作れるものなので、現在作成中のものは、javaの特殊なクラスローダーです。
すでにplay frameworkで実現はほぼできているのですが、ソースをコンパイルすることなく利用できるスクリプト言語みたいに利用できるjavaのクラスローダーを作りたいと思っています。

どうしても大企業病なのか、新しい言語は誰も習得できませんので、既存のgrooovyみたいなものが使えればいいのですが、そうもいきません。
そして結局コンパイルでデプロイミスも多く発生しています。
なので、デプロイはソースにして、あとからでも差分比較できるようにしたいといつも思っています。

また、それだけでなく、シェルスクリプトなどの運用コマンドやインストーラーなど、あらゆるものをjava一本にして行きたいと考えています。exewrapというものもあり、とても便利なのですが、今のところはWIndowsのみですし。。。
その一環でjcwebもまだ途中ですが開発しています。

道のりは遠いですが、何とか一本化できるよう、頑張りたいところです。
posted by Kiruahさん at 01:00| Comment(0) | TrackBack(0) | 日記

2012年07月09日

家族で東北に旅行へ行ってきました

今回は土日で家族で中尊寺、十和田湖、松島方面へ一泊二日で弾丸とラベルしてきました。
弾丸とはいえ、ちゃんとしたツアーです。最初は新幹線でしたが、途中からバスでいろいろと周ってきました。
東北地方は大学院時代に米沢に勉強に行ったぐらいしかなかったのでとても楽しかったです。

ちょっと初日はお天気が悪かったのですが、翌日は晴れてとても良かったです。
とても楽しい旅行でした。またツアーででも今年か来年にいけたらいいですね。
楽しみです。
posted by Kiruahさん at 21:17| Comment(0) | TrackBack(0) | 日記

2012年07月04日

kommons-lib 0.27に入れる予定の簡単な機能

現在kommons-lib 0.27を時間をかけて準備中です。
やはりteterの精度がよくなく、新規で作り直しているところです。
ただ、あまりにリリース時期が伸びており、また、poi2ccでもリリースして修正すべき不具合もみつかっているために、teterを省略してリリースしようかとも考えているところです。

どうでもよいのですが、どう考えてもやっぱいteterは「チーター」とは呼べないのでスペルを変えてしまいました。。。

さて、今回は少々話が代わり、kommons-lib 0.27に入れる予定の機能のうち、ブログで紹介するのにちょうど簡単なちょいプロみたいなものがあったので、早めに紹介しようと思いました。

本当に大それた機能ではありません。kommons-libを利用していますが、ファイル入力処理を記述すると以下のようになります。ただし、close処理は省略しています。


FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;

try {
fis = new FileInputStream("ファイル名");
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);

String text = null;

while ((text = br.readLine()) != null) {
// text処理
}
}....(省略)


ここで私があまり好きではないのが、whileの中の条件です。条件なのですが代入込みです。
この場合であれば、


try {
fis = new FileInputStream("ファイル名");
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);

for (String text = br.readLine(); text != null; text = br.readLine()) {
// text処理
}
}....(省略)

と、for文にまぜてしまえば、continueを利用しても副作用的なミスは起きにくいでしょう。
ですが、これもまだなんだか好みではありません。
できれば、もっと良い感じのロジックがいいなと思いました。
そこで、Holdというクラスを無駄に作成しました。Holdを利用すると以下のようになります。


try {
fis = new FileInputStream("ファイル名");
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);

Hold hold = new Hold();

while (hold.setEscapedNull(br.readLine()) != null) {
String text = hold.get();
// テキスト処理
}
}....(省略)


正直、無駄が増えたようにしか見えませんね。でも、個人的にはこちらのほうが好きです。単に好みの問題です。ただ、ポイントはHoldは拡張可能です。今現在のHoldクラスはカウンタがついています。よって、


try {
fis = new FileInputStream("ファイル名");
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);

String text = null;
int count = 0;

while ((text = br.readLine()) != null) {
count++;
// text処理
System.out.println(count + ":" + text);
}
}....(省略)

なんていうコードはHoldを利用すれば、

try {
fis = new FileInputStream("ファイル名");
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);

Hold<String> hold = new Hold<String>();

while (hold.setEscapedNull(br.readLine()) != null) {
System.out.println(hold.getCount() + ":" + hold.get());
}
}....(省略)

となります。ここまで来るとだいぶすっきりです。

最後にHoldのソースを記載します。参考までにどうぞ。kommons-libに入りますので、kommons-libと同じApache License 2.0となります。


package com.kiruah.kommon.jvalue;

/**
* 値を単純に保持するための仕組みを提供します。
*


* whileやforのループの中で以下の代入文が記述されることがあります。
*


* while ((v = func()) != null) {
* // 処理
* }
*

* これはwhileの中で代入処理と比較処理を同時に実行しています。意味や可読性、記述性の面で優れていますが、
* Kiruahは処理を分割したいため、以下のように記述させます。
*

* v = func();
*
* while (v != null) {
* // 処理
*
* // 次の処理
* v = func();
* }
*

* このように記述させることのメリットはあまりありません。単に好みです。
* ですが、funcの呼び出しが分断されるため、分断されないようにするため本機能を提供しています。
*

* Hold h = new Hold();
*
* while (h.set(func()) != null) {
* T v = h.get(); // そのままh.get()を利用しても良い
* // 処理
* }
*

* このクラスのメリットはありませんので、記述上同じ好みを持つ方が利用されることを想定しています。
*


*
* @param ジェネリクス型
* @since 0.27
* @author Kiruah
*/
public class Hold {

/** 保持する値 */
protected T value = null;

/** カウント */
protected long count = 0;

/**
* デフォルトコンストラクタ
*/
public Hold() {

}

/**
* 初期値を保持するコンストラクタ
*
* @param value 初期値
*/
public Hold(
T value) {

set(value);
}

/**
* 値を保持します。
*
* @param value 保持させたい値
* @return 保持させた値
*/
public T set(
T value) {

this.value = value;
count++;

return value;
}

/**
* 値を保持します。

* 値を保持しますが、不正な値の場合(例えばファイルリードの終わりがnullとなるようなケース)において、
* nullの場合カウント結果を累積させない場合に利用します。これはnullを利用する厳密なカウントアップ処理の
* 場合に有効に利用できます。
*
* @param value 保持させたい値
* @return 保持させた値
*/
public T setEscapedNull(
T value) {

this.value = value;

if (value == null) {
return null;
}

count++;

return value;
}

/**
* 保持させた値を返却します。
*
* @return 保持させた値
*/
public T get() {

return this.value;
}

/**
* カウント値を返却します。
*
* @return カウント結果を返却する
*/
public long getIndex() {

return count;
}
}

posted by Kiruahさん at 01:00| Comment(0) | TrackBack(0) | 日記

2012年07月03日

開発方式、処理方式、開発標準という夢物語

日本のSIerは過去、もしくは弊社では未だに現在進行形で、開発方式、処理方式、開発標準を考えるべきだということが叫ばれています。それがないから開発に失敗すると。
実際のところ、そんなものは弊社では立てられないと心のなかで分かっていながらも、私も「そうだ、そうだ」と叫んでいたこともありました。

そして、今現在進められている案件でもまだ、開発方式、処理方式、開発標準をどうするかだけでなく、各案件で開発方式、処理方式、開発標準が策定されている始末です。つまり、確定していないし、現在進行形でそれぞれの人達がそれぞれ開発方式、処理方式、開発標準を作っているのです。

が、はっきり言えば、日本のSIerが叫ぶ開発方式、処理方式、開発標準(以下、まとめて方式と呼びます)というものはいずれも、中身が無い空虚なものです。これができれば、開発が少しはうまくいく、効率化、省力化できるという夢が語られたりもしましたが、絶対にそんなことはありません。最近はそんな風に考え方が変わってきました。

これら方式とは誤解を恐れずに言えば、究極的に抽象化された、たった一つしか存在しない銀の弾でなければ作る意味はないでしょう。
でも、さすがに作れないため、現在では各プロジェクトごとになんとか銀の弾を作ろうとしています。それすらも結局作れずじまいです。
たったひとつ、全てを抽象化した完全な方式は存在するのでしょうが、存在しても作ることができないでしょう。できて規約までです。

規約はとても有効に働くでしょう。規約は反転すればチェックシートになります。チェックシートはそれを満たせば、成果物が規約の範疇を保証する強力な武器になり、チェックシートに記載された事柄が満たされなければ、突き返すことができる強力な防具にもなります。
そう、開発の現場では、規約とチェックシート、マニュアルやガイドさえあれば、実は十分開発を行うことができます。あえて事前に方式をたてる工数を作っても無意味なことがほとんどです。

それはなぜか。

その理由は案外単純です。方式とはある種現状では中途半端に抽象化されたレベルにしかならないため、実際にしようが固まれば固まるほど、方式の範囲を超えたどうしようも無い例外が発生するためです。結局、最初に立てた方式はなんとなく実現できそうでも、何時の間に苦しまぎれ例外が多くなります。これが後々の保守性を非常に低下させます。

例外ばかりで実装されたシステムほど、どう見たらいいのかわかりません。どう修正したらいいのかもわかりにくいのです。
であれば、中途半端な方式を立てるぐらいなら、まだ何もないほうが工数は無駄になりません。
ただし、もちろん事前に完全に抽象化された方式が立てられ、例外が出ない、もしくは方式に吸収可能なレベルを実現できるのであれば、あったほうがいいでしょうが、ここではそこまでのレベルのものはそもそも作ることができないという立場に立っています。


本当に使える方式を立てるにはどうしたらいいのか。

それは、全ての開発工程を今まで苦労も含めて経験し、そして技術も業務も管理も保守も運用も全て熟知した人間だけが、それらを俯瞰してあるべき姿、つまりべき論を導き出すことができます。

ですが、今現状、弊社で方式を立てようとしている方々は、いかに今わかっている仕様だけで自分の考えている方法論で作るかしか頭にありません。
そうではなく、本当に使う側に立った視点で見ていないのだから、作れないというのが私の意見です。
まずは、本当に各プロジェクトでどういうことがあったのか、分析するところから始め、上から目線をやめ、いろいろな工程の担当者から話を聞き、コミュニケーションを受け、真摯に耳を傾けなければ、真の方式はいつまでも夢物語でしょう。

では、具体的にどうすべきかについては、また順次記載して行きたいと思います。まだ、まとめきれていないので、ちょっと時間がかかりそうですが。

2012年07月02日

コミュニケーション能力とは何なのかな

よく言われるコミュニケーション能力。

いつも言われることは、飲みニケーションや趣味が充実していることが、最終的には営業としてうまく成約に結びつくという話です。彼らの言い分としては、飲みニケーションはコミニケーションを潤滑に行うために必要ということです。また、話の面白さもそういう面でコミュニケーション能力の一つだということが叫ばれています。
論理がおかしく、飲みニケーションはコミュニケーション能力の一部であるという主張をいいながら、それが全てでそれがなければコミュニケーション能力があるとは言えないと言い始めます。
話が常にそれぞれ独立して論理を展開するため、聞いている側は反論できないのがポイントです。
そして、それを発揮するから仕事が取れるという言い分をよく聞きます。
そうするから顧客から信頼が得られるとも主張されます。

さて、コミュニケーション能力とはどういう意味なのでしょうか。
普通に訳すと意思疎通でしょうか。Wikipediaによれば、「交流」であり、「生命体 (人間、動物、植物、微生物等)が、感情、意思、情報などを、発信受信応答、つまりは、相互連絡関係をもとうとすること。」のようです。
ポイントは相互に連絡関係がある状態であることでしょう。

意思疎通。意味は、自分の意思(考え、思い、感情、情報が主たるものでしょう)について、相手が疎んじている状態を通ずる状態にすることではないでしょうか。
疎んじている状態とは、理解が不完全であるということです。それを通ずるようにするということは相手に理解させるということです。

コミュニケーション能力は、会話の能力ではありません。相手に理解させる能力です。

確かに、英語において話すに関連する英語は、speak, talk, chat, lay on, conversation, open one's, tell, ask, have face等があります。これらは意味が異なり、speakとtalk(の半分ぐらい)は一方的な能力、askやtellは問い合わせる能力、chatやconversation、その他は会話や雑談のような意味です。では、理解はというと、comprehendやunderstandがありますが、これらは〜を理解するという意味です。
どこにもcommunicationが出てきません。ここでよく言われる飲みニケーションを考えると、確かにコミュニケーションを取る上で、話すということや理解するということはコミュニケーションの重要な要素、手段であることは確定できます。が、必ずなければならないというものでもありません。

なぜそんなことを言うのかといえば、私はコミュニケーションについての研究を学生時代担ってきたからです。
コミュニケーションには、大きくバーバルコミュニケーションとノンバーバルコミュニケーションがあります。この二つを発揮することがコミュニケーション能力を発揮するということです。
そして、バーバルコミュニケーションは、口頭でなくても手紙でもよく、むしろ飲み屋でなくても、面白い話でなくても、趣味が通じなくても良いものです。
ノンバーバルコミュニケーションは非言語コミュニケーション。つまり、仕草や表情といったものです。これらを駆使し、相手に自分の主張を理解させることができる能力をコミュニケーション能力というと私は考えます。ポイントは、バーバル、ノンバーバル両方もしくは片方を相手にあわせて適切に使いこなすことができ、その結果相手に主張を理解させることができることです。

以下は、とても失礼なことを言います。不快に思う方がいましたら、本当に申し訳ございません。ですが、言わせていただきます。
コミュニケーション能力がそのように定義されなければ、もし障害があることで話せなくなった方、耳が聞こえなくなった方はコミュニケーション能力を絶対に持てないことになります。
また、お酒が飲めない方、無趣味の方は相当な努力が必要になってしまいます。
元々の先天的、後天的な状況をもってしてコミュニケーション能力の有無を語ることは、本来の意味の達成とは異なるのではないかと考えました。

私はコミュニケーション能力とは、相手の理解のために努力すること、そのために言葉や表情、仕草、資料等をどこまで相手の理解のために用意でき、その用意を相手のために奉仕できるかではないのかという、思いやりの能力だと思いたいのです。
その結果、営業的に成約できるのは、誠意と信用が生まれた結果であって、決してコミュニケーション能力の有無とはまたこれらは関係ないとも思いたいのです。


最初の多くの主張である飲みニケーションはchatやconversationであって、communicationではないと思います。どこかでうまく、相手の中に信用を得ることができたり、探り探り相手の考えをくみとることができたり、もしくは本当にcommunicationが部分的に発揮できた結果、飲みニケーションで成果が得られ、それがいつの間にかコミュニケーション能力の一部と勘違いされたのではないかと思いたいのです。


コミュニケーション能力とはつまり、誰かが一部の人間のための能力ではないということを言いたく、また、有無について語ることは無意味だと思います。無いのではなく、思いやりや相手の理解への配慮が足りないだけだと考えたいと思うのです。


これらは完全に私の個人的な意見です。人の考え方についてどうこう言うつもりもありません。
ただ、よく言われる「あいつはコミュニケーション能力がない」というのは、もっと考えて私も発言したいと反省しました。これは、それ自体が相手とのコミュニケーション、つまり相手の状態への配慮が欠けた状態だからです。これは、そもそもの人間関係を醸成する行為の否定であって、自らアンテナを閉じた状態なのかと考えました。
ここから色々と考えて上述の思考にたどり着きました。

勝手ながら、きっと私たちは思いやりという面で、何か重要なものを忘れてしまったような、そういうことが感じられることが多く、私はもっと反省すべきと気づきました。という告白です。


余談ですが、社内で飲みニケーションが推奨される会社もあります。ポイントが発行されたりというところもあるそうです。それはコミュニケーションとは別としてもおもしろいと思いました。

2012年07月01日

JSF実装のELライブラリをスタンドアロン・プログラムの中で利用する

Javaによる画面アプリケーションでは、EL式と呼ばれるものがJSPやJSFに組み込まれて利用されます。
そのEL式は、やっぱり基本的にはWebアプリケーションサーバー上で利用することが前提でよく記述されています。一応EL式のライブラリ自体は切りだされていますが、いまいち使い方が分からないです。

例えばスタンドアロンアプリケーションを作り、その中で便利だからELだけ使いたいという場合。
そういう場合でもELのためだけにWebアプリケーションサーバーを導入したり、もしくはそのためにJSFライブラリ全体を持ってきたりするのは面倒です。
ApacheのJEXLApache Commons EL等のライブラリでも良いのですが、ELはGlassFish(mojarra)の実装がやはり一番速度が速いようなので、こちらを何とかして使いたいというかたも多いでしょう。でも、簡単に何もせず、APIだけで組み込むことができなくて苦労します。また調べても、すぐには何も見つかりませんでした(英語でも調べたんですが。。。)

なので、どうやったら簡単に自分のアプリケーションにEL式を組み込めないかなと考えていました。
(考えていただけで、家でのプログラムではEL式を利用するつもりは今のところないのですが)
色々と試してみましたが、スタンドアプリケーション用のELContextとELResolverを実装するしかないのかなぁという結論に至りました。
もっといい方法があるかもしれません。。。

参考までにソースを紹介しますので、ご自由にご利用くださいませ。Javadocコメントは若干適当です。

LocalELContext.java (ELContextと中で利用するELResolver実装です。)

import java.beans.FeatureDescriptor;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.el.ArrayELResolver;
import javax.el.BeanELResolver;
import javax.el.CompositeELResolver;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.el.FunctionMapper;
import javax.el.ListELResolver;
import javax.el.MapELResolver;
import javax.el.VariableMapper;

import com.sun.el.lang.FunctionMapperImpl;
import com.sun.el.lang.VariableMapperImpl;
import com.sun.faces.el.PropertyResolverChainWrapper;
import com.sun.faces.el.PropertyResolverImpl;

/**
* ローカル変数を起点としてELを実行するためのELコンテキスト
*
* @author Kiruah
*/
public class LocalELContext extends ELContext {

/** ELContext初期化済みかどうかを指定する */
protected static Boolean initialized = Boolean.FALSE;

/** ローカルEL解決者 */
protected static LocalELResolver resolver = null;

/** メソッド呼び出しマッパー */
protected static FunctionMapper functionMapper = null;

/** 変数取得マッパー */
protected static VariableMapper variableMapper = null;

/**
* 初期化処理
*
* @param object 取得対象のオブジェクト
*/
public LocalELContext(
Object object) {

if (initialized == false) {
initialize();
}

if (resolver == null) {
resolver = new LocalELResolver(object);
}
}

/**
* 初期化処理
*/
protected void initialize() {

synchronized (initialized) {

if (initialized == false) {
if (functionMapper == null) {
functionMapper = new FunctionMapperImpl();
}

if (variableMapper == null) {
variableMapper = new VariableMapperImpl();
}

if (LocalELResolver.compositeResolver == null) {
CompositeELResolver elResolver = new CompositeELResolver();

elResolver.add(new ListELResolver());
elResolver.add(new MapELResolver());
elResolver.add(new ArrayELResolver());
elResolver.add(new BeanELResolver());
elResolver.add(new PropertyResolverChainWrapper(new PropertyResolverImpl()));

LocalELResolver.compositeResolver = elResolver;
}

initialized = Boolean.TRUE;
}
}
}

/**
* EL解決者を取得する
*

*

(オーバーライドメソッド)


* @return EL解決者
* @see javax.el.ELContext#getELResolver()
*/
public ELResolver getELResolver() {

return resolver;
}

/**
* メソッド呼び出しマッパーを取得する
*

*

(オーバーライドメソッド)


* @return メソッド呼び出しマッパー
* @see javax.el.ELContext#getFunctionMapper()
*/
public FunctionMapper getFunctionMapper() {

return functionMapper;
}

/**
* 変数取得マッパーを取得する。
*

*

(オーバーライドメソッド)


* @return 変数取得マッパー
* @see javax.el.ELContext#getVariableMapper()
*/
public VariableMapper getVariableMapper() {

return variableMapper;
}

/**
* ローカルEL解決者
*
* @author Kiruah
*/
protected static class LocalELResolver extends ELResolver {

/** ネストされたEL解決者 */
protected static CompositeELResolver compositeResolver = null;

/** 探索対象のオブジェクト */
protected Object object = null;

/**
* コンストラクタ
*
* @param object EL実行対象のオブジェクト
*/
public LocalELResolver(
Object object) {

this.object = object;
}

/**
* 値を取得する
*

*

(オーバーライドメソッド)


* @param context ELコンテキスト
* @param base 探索対象
* @param property EL式
* @return 取得結果
* @see javax.el.ELResolver#getValue(javax.el.ELContext, java.lang.Object, java.lang.Object)
*/
@Override
public Object getValue(
ELContext context,
Object base,
Object property) {

if (base == null) {
return compositeResolver.getValue(
context,
object,
property);
} else {
return compositeResolver.getValue(
context,
base,
property);
}
}

/**
* 型を取得する
*

*

(オーバーライドメソッド)


* @param context ELコンテキスト
* @param base 探索対象
* @param property EL式
* @return 型
* @see javax.el.ELResolver#getType(javax.el.ELContext, java.lang.Object, java.lang.Object)
*/
@Override
public Class getType(
ELContext context,
Object base,
Object property) {

if (base == null) {
return compositeResolver.getType(
context,
object,
property);
} else {
return compositeResolver.getType(
context,
base,
property);
}
}

/**
* 値を設定する
*

*

(オーバーライドメソッド)


* @param context ELコンテキスト
* @param base 探索対象
* @param property EL式
* @param value 設定値
* @see javax.el.ELResolver#setValue(javax.el.ELContext, java.lang.Object, java.lang.Object, java.lang.Object)
*/
@Override
public void setValue(
ELContext context,
Object base,
Object property,
Object value) {

if (base == null) {
compositeResolver.setValue(
context,
object,
property,
value);
} else {
compositeResolver.setValue(
context,
base,
property,
value);
}
}

/**
* 読み取り専用か取得する
*

*

(オーバーライドメソッド)


* @param context ELコンテキスト
* @param base 探索対象
* @param property EL式
* @return 読み取り専用かどうか
* @see javax.el.ELResolver#isReadOnly(javax.el.ELContext, java.lang.Object, java.lang.Object)
*/
@Override
public boolean isReadOnly(
ELContext context,
Object base,
Object property) {

if (base == null) {
return compositeResolver.isReadOnly(
context,
object,
property);
} else {
return compositeResolver.isReadOnly(
context,
base,
property);
}
}

/**
* 特徴の説明情報を取得する
*

*

(オーバーライドメソッド)


* @param context ELコンテキスト
* @param base 探索対象
* @return 特徴の説明情報
* @see javax.el.ELResolver#getFeatureDescriptors(javax.el.ELContext, java.lang.Object)
*/
@Override
public Iterator getFeatureDescriptors(
ELContext context,
Object base) {

if (base == null) {
return compositeResolver.getFeatureDescriptors(
context,
object);
} else {
return compositeResolver.getFeatureDescriptors(
context,
base);
}
}

/**
* 共通のプロパティタイプを取得する
*

*

(オーバーライドメソッド)


*
* @param context ELコンテキスト
* @param base 探索対象
* @return 共通のプロパティタイプ
* @see javax.el.ELResolver#getCommonPropertyType(javax.el.ELContext, java.lang.Object)
*/
@Override
public Class getCommonPropertyType(
ELContext context,
Object base) {

if (base == null) {
return compositeResolver.getCommonPropertyType(
context,
object);
} else {
return compositeResolver.getCommonPropertyType(
context,
base);
}
}
}
}


この中では、ELライブラリで標準で実装されている
・ListELResolver
・MapELResolver
・ArrayELResolver
・BeanELResolver
・PropertResolver
のみCompositeELResolverにセットし包含しています。
ELはトップノードのアクセス時のみgetValueのbaseがnullとなりますので、その場合のみ指定のオブジェクトを探索するようにし、それ以外はbaseを利用するようにするという程度のものです。
初期化処理は冗長です。static {} を使えばいいのですが嫌いなのでこういう感じになっています。

利用する場合は以下の様な実装となります。

Main.java

import java.util.HashMap;
import java.util.Map;

import javax.el.ELContext;
import javax.el.ExpressionFactory;

import com.sun.el.ExpressionFactoryImpl;
import com.sun.el.ValueExpressionImpl;

/**
* EL組み込みのサンプル
*
* @author Kiruah
*/
public class Main {

/**
* メイン
*
* @param args コマンドライン引数
*/
public static void main(
String[] args) {

Map container = new HashMap();
container.put(
"hoge1",
"hogehoge1");
container.put(
"hoge2",
"hogehoge2");

String el = "${hoge1}";
Object value = get(
container,
el);

System.out.println(value);
}

/**
* EL式を利用して取得対象から値を取得します。
*
* @param target 取得対象
* @param el EL式
* @return 取得結果
*/
public static Object get(
Object target,
String el) {

ELContext context = new LocalELContext(target);
ExpressionFactory ef = ExpressionFactoryImpl.newInstance();
ValueExpression ve = (ValueExpression) ef.createValueExpression(
context,
el,
Object.class);

Object value = ve.getValue(context);

return value;
}
}


こうすることで、自前で用意しているコンテナがあれば、そこからEL式を利用して値を取得することができます。

ちょっと実装しなければならないとできなかったのが、自分の調査・スキル不足ならば、もっと勉強や自己研鑚が必要です。
頑張らねば。
posted by Kiruahさん at 01:00| Comment(0) | TrackBack(0) | ノウハウ