ラベル プログラミング の投稿を表示しています。 すべての投稿を表示
ラベル プログラミング の投稿を表示しています。 すべての投稿を表示

2010年7月8日木曜日

選択した文字をカーリルで検索するブックマークレット

全国の図書館の所蔵情報を一望できるサービス、カーリルで選択したキーワードを検索するブックマークレットです。
気になった事柄や、書評されていた本をさっと検索できるようにしたものです。

Firefoxのみテスト済み

ブックマークレット←ドラッグアンドドロップで追加

コード

javascript:(function(){window.open('http://calil.jp/search?q='+encodeURI(document.getSelection()));})()

2008年11月26日水曜日

はてブしている人がよく付けるタグを表示するグリモン

はてながリニューアルされたのを記念して?久しぶりにグリモンを書いてみた。
すんごい適当及び初心者書いているので汚いし、不効率だし、不具合あるかも。
tagにXSSとか仕込まれるとやばい?そんなことする奴いるかしらんけどw

はてブしている人がよく付けるタグを表示するグリモン
先日はてながリニューアルされてお気に入り機能が強化されました。
お気に入り機能は気に入ったブックマーカーを登録しておくことで、その人が登録したブックマークを追えるようになるんだけど、何を持ってお気に入りにするかって判断する基準が乏しいのでブコメのところにその人が付けているタグTop3を表示させてみました。
これで、ブコメチェックしつつ自分と似たようなタグを付けている人を探しやすくなるのでお気に入りに入れる判断の手助けになるかなっと思います。

以下ソース - (bloggerの機能で一部欠ける・・・需要合ったらjs上げるのでコメントください)

// ==UserScript==
// @name favoritetags
// @namespace jp.mamono.favoritetags
// @include http://b.hatena.ne.jp/entry/*
// ==/UserScript==
(function (){
var cloudStr = 'tag-cloud-size-';
var baseCloudsize = 9;
var overCloudsize = 11;
var maxTag = 3;

function Tag(tagElement) {
this.tag = tagElement;
this.getName = function() {
return this.tag.getElementsByTagName('a')[0].textContent;
}
this.getSize = function() {
return parseInt(this.tag.getElementsByTagName('span')[0].textContent.match(/\d+/));
}
this.getText = function() {
return this.getName() + this.tag.getElementsByTagName('span')[0].textContent;
}
}

function d() {
alert('test');
}

function addFavoriteTags(usertag) {
function onload(response) {
var result = new Array();
if (response.responseText != null) {
var tags = findTags(response.responseText).getElementsByTagName('li');
for (var i = 0; i < tags.length; i++) {
result.push(new Tag(tags[i]));
}
}
if (result.length == 0) return;
result.sort(function(o1, o2) { return o2.getSize() - o1.getSize(); });
var addTag = document.createElement('span');
addTag.setAttribute('style', 'font-size:80%');
for (var i = 0; i < result.length; i++) {
if (i >= maxTag) break;
addTag.textContent = addTag.textContent + result[i].getText();
}
usertag.parentNode.insertBefore(addTag, usertag.nextSibling);
}
GM_xmlhttpRequest({ method: "GET", url: 'http://b.hatena.ne.jp/' + usertag.text + '/', onload: onload });
}

function findTags(html) {
var result = new Array();
var sep = '\n';
var t = html.split(sep);
var addflag = false;
for (var i = 0; i < t.length; i++) {
if (t[i].match(/
    /i)) {
    addflag = true;
    }
    if (addflag && t[i].match(/<\/ul>/i)) {
    addflag = false;
    result.push(t[i]);
    }
    if (addflag) {
    result.push(t[i]);
    }
    }
    return (new DOMParser()).parseFromString('' +
    result.join(sep) + '', "application/xml");
    }

    var aTags = document.getElementsByTagName('a');
    for (var i = 0; i < aTags.length; i++) {
    if (aTags[i].getAttribute('class') == 'username') {
    addFavoriteTags(aTags[i]);
    }
    }
    })();


・苦労した点
はてブのページがそのままではDOMParserに通らなかったので自前でパースしたところ。
終了タグが付いてないのがいくつかあるっぽい・・・。
そういう場合どうすればいいんだろ?

・TODO
Top3タグにクリックするとタグページに飛ぶリンクを付加
お気に入り追加ボタンの挿入←できるのかわかんない

2008年10月28日火曜日

プログラミングの話

プログラミングの心構えエントリーの流れを受けてdankogaiが弾言してた。
ひさびさにdankogaiにちょ~同意。




How to Code などブロックをendで閉じるか}で閉じるかほどの意味しかないことを。



しかし、その差が気にならない人が良いプログラマーになるということもまずないのだけれども。



404 Blog Not Found:そろそろ3つのポイントについて「弾言」しとくか から引用


人のコード見てていつも思うのはほんとにこれ。
インデントをタブで行うか空白で行うか、改行を空にするかそんなのは意味が無い。
でもそれを気にしている人と気にしていない人は雲泥の差がある。
気にしない人はコードは書けるけどメタな視点では書けない。
ただそこで動いているだけのコードしか書けない。
他のコードへの影響を考えて無いからコードの流用もできない。

コードの差はわずかなのにここまで影響するのは不思議。
コードって結構人の内面を表してるからコードをポストして脳内メーカーみたいな結果を返すサービスっておもしろいかもw

2008年10月21日火曜日

SEとPGとキャリアパス

なかなかおもしろい考察の記事があがってたので感想でも。

下流から見たIT業界: SEとPG、どっちが頭がいい?(1)チャマニへ
下流から見たIT業界: SEとPG、どっちが頭がいい?(2)チャマニへ

SE(システムエンジニア)とPG(プログラマー)
うちの会社でもゆくゆくはSEにとかってよく言われます。
でも、自分的には生涯PGになりたいなどと思っていてSEねぇ・・・と鼻で笑っています。
正直SEって何する仕事か曖昧ですよね。
よく言われるのは要求定義から詳細設計を作るといった分野でしょうか。
しかしこれは上の記事によると昔PGが単純労働だった時代に行われていた手法なのだそうです。
その昔、PCが各自一台設置されていなかった時代には紙の上でプログラムを書いて
それを現場にある唯一のPCに打ち込むといったことが行われていました。
紙に書いたプログラムを打ち込むだけだからまさに単純労働ですね!
その印象を今まで引きずっているため、PGは単純労働者とみなされSEより下に見られるんですね。
でも現状は違います、まず各自がPCを持っているし、机上で書いたプログラムを打ち込むだけなんてしないんです。
ある程度の仕様を聞かされて、そこからソースコードを自分で考えて打ち込むのです!!
これが単純労働と言えますか?完璧に知的労働ですよね。
自分で考えて動かなければいけないことが沢山あるんです。
だから正直SEとPGって分けて考えるのは古臭いし、未だに将来はSEだ!なんて言っちゃてる人は
どんなけ時代錯誤だよ、現場わかってね~と言わざるを得ません。
他にも様々な背景があります、それは上記の記事に書かれていますので一度読んでみてください。
PG不遇の時代が早く終わるのを願っています。

2008年10月10日金曜日

グーグルリーダー+チャートマニアックス

とりいぞぎ

元コードはグーグルリーダー+はてブ数のグリモン
grb+-20061113.user.js - ヒビノキロク

これにチャートマニアックスのページに飛ぶリンクを追加しました。
時系列で見るとまた一味違った感じがしておもしろいですね~。
さすがamachangさん!!


// ==UserScript==
// @name GR+?B
// @namespace http://d.hatena.ne.jp/nozom/
// @description show ?B button and count in Google Reader
// @include http://www.google.com/reader/view/*
// @include https://www.google.com/reader/view/*
// ==/UserScript==

// original author is id:kusigahama
// see http://d.hatena.ne.jp/kusigahama/20051207#p1

(function() {
const user = 'mamotena';

var timerID = null;
var busy = false;
var urlCache = new Object();

function getUrlCache(url) {
if (typeof urlCache[url] == 'undefined')
urlCache[url] = new Object();
return urlCache[url];
}

String.prototype.htmlescape = function() {
return this.replace(/&/g, "&").replace(/</g, "<");
}

function findNode(root, xpath) {
var result = document.evaluate(xpath, root, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
if (! result.snapshotLength) return null;
return result.snapshotItem(0);
}

function getBookmarkCountSpan(node) {
return findNode(node, 'span[@class="hatena-bookmark-count"]');
}

function insertChartSBM(targetNode, url) {
var a = document.createElement('a');
a.setAttribute('href', "http://amachang.art-code.org/chart/?" + url);
a.setAttribute('target', '_blank');
a.appendChild(document.createTextNode('C'));

with (targetNode) {
appendChild(document.createTextNode(" ("));
appendChild(a);
appendChild(document.createTextNode(") "));
}
}

function insertBookmarkCount(targetNode, url, count) {
var a = document.createElement('a');
a.setAttribute('href', "http://b.hatena.ne.jp/entry/" + url);
a.setAttribute('target', '_blank');

var str = (count > 0 ? "" + count : "no") + " user" + (count != 1 ? "s" : "");
a.appendChild(document.createTextNode(str));

with (a.style) {
fontSize = "0.9em";
textDecoration = "none";
if (count >= 5) {
fontWeight = "bold";
backgroundColor = "#fff0f0";
color = "#f66";
}
if (count >= 10) {
backgroundColor = "#ffcccc";
color = "red";
}
}

with (targetNode) {
appendChild(document.createTextNode(" ("));
appendChild(a);
appendChild(document.createTextNode(") "));
}
}

function createBookmarkCount(url, count) {
var node = document.createElement('span');
node.setAttribute('class', 'hatena-bookmark-count');
if (count > 0) {
insertBookmarkCount(node, url, count);
} else {
node.appendChild(document.createTextNode(' '));
}
insertChartSBM(node, url);
return node;
}

function setBookmarkCounts(infoArray) {
for (var i = 0; i < infoArray.length; i++) {
var entry = infoArray[i].entry;
var url = infoArray[i].url;
var title = infoArray[i].title;
var entryContainerTitle = infoArray[i].entryContainerTitle;
var collapsedTitle = infoArray[i].collapsedTitle;
var entryActions = infoArray[i].entryActions;

var count = getUrlCache(url).count;
if (typeof count != 'undefined') {
if (typeof collapsedTitle != 'undefined') {
var node = createBookmarkCount(url, count);
collapsedTitle.insertBefore(node, collapsedTitle.childNodes[1]);
}
if (typeof entryContainerTitle != 'undefined') {
var node = createBookmarkCount(url, count);
entryContainerTitle.insertBefore(node, entryContainerTitle.childNodes[1]);
}
}
}
}

function callXmlrpc(requestbody, infoArray) {
const endpoint = "http://b.hatena.ne.jp/xmlrpc";
function onload(response) {
if (response.responseText.match(/<fault>/)) {
// clearInterval(timerID);
//setInterval(timerID, 15000);
//alert("xmlrpc call failed: " + response.responseText + "\n" + "request: " + requestbody);
} else {
var pattern = /<name>([^<]+)<\/name>\s*<value><int>(\d+)/g;
var m;
while (m = pattern.exec(response.responseText)) {
getUrlCache(m[1]).count = m[2];
}
setBookmarkCounts(infoArray);
}
busy = false;
}

// alert('xmlrpc call :' + requestbody);
GM_xmlhttpRequest({ method: "POST", url: endpoint, data: requestbody, onload: onload });
}

function createAddBookmarkIcon(url, title) {
var a = document.createElement('a');
a.setAttribute('href', 'http://b.hatena.ne.jp/add?mode=confirm&is_bm=1&title=' + escape(title) + '&url=' + escape(url));
a.setAttribute('target', '_blank');

var img = document.createElement('img');
img.setAttribute('src', 'http://b.hatena.ne.jp/images/append.gif');
img.setAttribute('alt', 'add bookmark');
img.setAttribute('title', 'add bookmark');
with (img.style) {
borderWidth = '0px';
}
a.appendChild(img);

var node = document.createElement('span');
node.setAttribute('class', 'hatena-bookmark-icon');
node.appendChild(a);

return node;
}

function createBookmarkIcon() {
var img = document.createElement('img');
img.setAttribute('src', 'http://www.hatena.ne.jp/images/user_bookmark.gif');
img.setAttribute('alt', 'bookmarked');
img.setAttribute('title', 'bookmarked');

var node = document.createElement('span');
node.setAttribute('class', 'hatena-bookmark-icon');
node.appendChild(img);

return node;
}

function addBookmarkIcon(currentEntry) {
var entryContainerTitle = findNode(currentEntry, './/div[@class="entry-container"]//h2');
var entryActions = findNode(currentEntry, './/div[@class="entry-actions"]');
if ((entryContainerTitle == null) || (entryActions == null)) return;

var link = entryContainerTitle.firstChild;
var title = link.firstChild.textContent;

function onload(response) {
if (response.responseText != null) {
var responseXML = (new DOMParser()).parseFromString(response.responseText, "application/xml");
if (responseXML != null) {
var channel = responseXML.getElementsByTagName('channel')[0];
if (channel != null) {
var items = channel.getElementsByTagName('items')[0];
if (items != null) {
var lis = items.getElementsByTagName('li');
if (lis.length > 0) {
getUrlCache(link.href).bookmarked = true;
entryActions.appendChild(createBookmarkIcon());
} else {
getUrlCache(link.href).bookmarked = false;
entryActions.appendChild(createAddBookmarkIcon(link.href, title));
}
}
}
}
}
}

var bookmarked = getUrlCache(link.href).bookmarked;
if (typeof bookmarked == 'undefined') {
getUrlCache(link.href).bookmarked = 'loading';
var url = 'http://b.hatena.ne.jp/' + user + '/rss?url=' + escape(link.href);
GM_xmlhttpRequest({ method: "GET", url: url, onload: onload });
} else if (bookmarked == 'loading') {
// skipped
} else if (bookmarked) {
entryActions.appendChild(createBookmarkIcon());
} else {
entryActions.appendChild(createAddBookmarkIcon(link.href, title));
}
}

function timerHandler() {
if (busy) return;

var entries = document.getElementById('entries');
if (entries == null) return;

var currentEntry = document.getElementById('current-entry');
if (currentEntry != null) {
if (findNode(currentEntry, './/span[@class="hatena-bookmark-icon"]') == null) {
addBookmarkIcon(currentEntry);
}
}

busy = true;

var infoArray = new Array();
var reqUrlArray = new Array();
var reqUrlHash = new Object();
for (var i = 0; i < entries.childNodes.length; i++) {
var entry = entries.childNodes[i];
var collapsedTitle = findNode(entry, './/div[@class="collapsed"]//h2');
var entryContainerTitle = findNode(entry, './/div[@class="entry-container"]//h2');

var link = null;
var title = null;
if (entryContainerTitle != null) {
link = entryContainerTitle.firstChild;
title = link.firstChild.textContent;
} else if (collapsedTitle != null) {
link = collapsedTitle.parentNode.parentNode.firstChild;
title = collapsedTitle.textContent;
}

if (link != null) {
var info = { entry: entry, url: link.href, title: title };
if ((collapsedTitle != null) && (getBookmarkCountSpan(collapsedTitle) == null)) {
info.collapsedTitle = collapsedTitle;
}
if ((entryContainerTitle != null) && (getBookmarkCountSpan(entryContainerTitle) == null)) {
info.entryContainerTitle = entryContainerTitle;
}
if ((info.collapsedTitle != null) || (info.entryContainerTitle != null)) {
infoArray.push(info);
if ((getUrlCache(link.href).count == null) &&
(! reqUrlHash[link.href])) {
reqUrlHash[link.href] = true;
reqUrlArray.push(link.href);
}
}
}
}

if (infoArray.length == 0) {
busy = false;
return;
}

if (reqUrlArray.length == 0) {
// all items are found in the cache
setBookmarkCounts(infoArray);
busy = false;
} else {
// avoid xmlrpc call failure in 'too many params' error
reqUrlArray = reqUrlArray.splice(0, 50);

var request = '<?xml version="1.0"?>\n<methodCall>\n<methodName>bookmark.getCount</methodName>\n<params>\n';
for (var i = 0; i < reqUrlArray.length; i++) {
var url = reqUrlArray[i];
request += "<param><value><string>" + url.htmlescape() + "</string></value></param>\n";
}
request += "</params>\n</methodCall>\n";
callXmlrpc(request, infoArray);
}
}

// be careful not to be too busy
timerID = setInterval(timerHandler, 15000);
})();

2008年9月5日金曜日

grb+のちょっとした部分の修正

grb+の作者nozomさんには足を向けて眠れないくらい使い倒してるんですが、
はてブ数からはてブに飛ぶリンクのurlがエスケープされてなくて(はてダで#含まれてるページとか)
うまく表示されない時があったので直してみました。
元スクリプト→grb+-20061113.user.js - ヒビノキロク

// 47行目
a.setAttribute('href', "http://b.hatena.ne.jp/entry/" + escape(url));

太字部分のurlを上記の通りescapeメソッドエスケープしてやるだけです。
もしかするとエスケープしちゃうとダメなページもあるかもしれないのでダメなページがあったら教えてください。
作者のnozomさんはたぶんこのスクリプトに関心が無いっぽいですけど、いつも使わせてもらってありがとうございます><
クロなんとかっつーgoogleの超速のブラウザとかでましたがこのグリモンがあるかぎり移行することはないでしょうw

一応要望としては、読売のRSSの様にページのリンクに余計なURLパラメータが付いている場合ちゃんとはてブ数を拾ってくれないので
特定のページはURLパラメータをはしょるような処理が欲しいなと思います。
ただ、URLパラメータ付きでブクマされてるページもあると思うので難しいかな・・・。
暇があったら追加して公開してみたいと思います。(ていうか改変公開は問題あるか・・・)

関連リンク
Ahead one step: GoogleReaderにはてブ数を表示するグリモンが止まってしまう問題の応急処置

2008年8月30日土曜日

熱い技術者の見ているもの

今日は初めて勉強会というものに参加してきた。
勉強会はjrubyのプラグインrubeusとrailsを使ったものでRubyBusinessCommonsが主催する勉強会。
内容としてはrailsのプロジェクト作成からdbの設定、dbを使ったrubeusで動く簡単なGUIの作成を10時から18時までみっちりと一日かけて行いました。
やってる内容としてはめちゃくちゃ初歩的なことかな。
最近GAEをちょっと触ってpythonやjythonをいじいじしてたのでほとんど理解はできました。
正直いって自分としては物足りなかったんですが、"初歩"という内容でみればかなり充実してたんではないでしょうか。
簡単なセットアップと100行にも満たないコードを編集するだけでdbを経由したアプリを作れてしまうのだから、rubyやrailsの開発のしやすさという点はよく伝わってきた。
問題はここからどう昇華していくかだと思う。
勉強会では用意されたツールや手順をただなぞるだけだったのだが、実際開発するにはドキュメントの見方や調べ方、そもそも使えるツールの探し方などが必要で、こんな簡単にはいかないのだから。
なので今の状態では地に足がつかないというか一歩踏み出すのはもう少し労力がいる。
ただ、rubyのプラグインやフレームワークなんかはドキュメントとかまとめられたものがほとんど存在しないという話は出てた。
だからこういうノウハウは調べるだけで一つの仕事になってしまいそう。
ま、その辺はやってみないとわかんないけど、今日からrubyをいじってみます(でもドキュメントの見方もわからんし不安なのだ)。
pythonはどうにも日本語の処理が甘くてうまくいかないことが多くイライラしてたんで。
GAEも他の言語にそのうち対応しするし、その中にはrubyが入ってたと思う。別にgoogle様じゃなくてもいいし。

代表の方はとても熱い方でたくさんの情熱のこもった言葉を語ってました。
その中で「技術はトレンドを追いかけるべき」だという言葉がニッチ好きな天の邪鬼としてはとても心に響きました。
web2.0とともにロングテールなんてバズワードが流行ったけど、確かにトレンドの需要は超えることはできないんだよね。
こないだカンブリア宮殿でキョウデングループ会長が需要が合って競争が激しいからこそあえてそこで勝負するって言ってたのを思い出した。
当たり前っちゃ当たり前なんだけどもみんなが使ってる物を使っていくほうがいいんだよね、windowsみたいに。
rubyは名古屋ではまだトレンドとは言えないかもしれないけど、この熱い言葉達を聞くとトレンドになることは間違いないと確信しました。
そして、そのトレンドは押さえておくべきだとも。

っと、超零細Sierで働く俺が思いましたとさ。
初めて勉強会参加しましたが、ぶっちゃけ敷居というか技術力の差がありすぎだよ、うちの会社と比べると。
こんな会社にいてのほほんとしてる自分が頭おかしいと再認識しますた!!!

がんばろっと。

2008年7月15日火曜日

今日のブックマークてすと

以前言ってた言及したブックマークのみ取得して整形するコードを書いてみた。

Ahead one step: 今日のブックマーク(仮)

pythonじゃなくてjavaで。。。pythonはどうしても日本語エンコードができない;;
とりあえずテスト出力。もう少し整形したら公開してみよう。




asahi.com(朝日新聞社):「燃料高もう限界」20万隻休漁へ 東京でデモも - ビジネス
でも、デモしても値段下がらない気がすると思うんだが・・・補助金狙い?/よく読んだら補填を要求してるのね

「よっちゃんイカ」に100円硬貨、混入経路不明(読売新聞) - Yahoo!ニュース
よっちゃんイカを買いにいったついでに100円をいれてきたのか

2008年6月6日金曜日

GoogleReaderにはてブ数を表示するグリモンが止まってしまう問題の応急処置

はてな民でGoogleReager愛用者には無くてはならないグリモンといえばid:nozomさんが公開されているGoogleReaderにはてブ数を表示するグリモンです。



id:kei-sさんのGoogle Readerでfaviconを表示させるGreasemonkeyスクリプト公開に触発されて、Google Readerにはてなブックマーク件数とブックマークアイコンを表示するGreasemonkeyスクリプトをバージョンアップした。



grb+-20061113.user.js



grb+-20061113.user.js - ヒビノキロク から引用

はてブ数とコメントが気になってしょうがない僕にはめちゃくちゃ便利でこれ無しではもうRSSのチェックはやってられないんですが、たまにダイアログが出て動作が止まってはてブ数が反映されなくなってしまって困ってました。
で、あまり深くは追ってないですが、対処法を書いておきます。

スクリプトをエディターで開いて106行目

if (response.responseText.match(/<fault>/)) {
// この中をコメントアウト
// clearInterval(timerID);
//alert("xmlrpc call failed: " + response.responseText + "\n" + "request: " + requestbody);
} else {

callXmlrpc()関数内のif文の処理をコメントアウトするだけです。
elseブロックはそのままにしておきます。
どうも、はてなAPIに問い合わせの返答に<fault>タグが混じっていた場合に更新を止めて、alert()で知らせているようなんですが、更新を止めてるのでここに来た以降はてブ数が表示されなくなります。
僕はそんなにJavaScriptに詳しくなくて何故こうなってるのかはわからないので、この修正で別の問題が起きる可能性がありますが、今のところはてブ数を加える処理が止まるということは無くなりました。
とりあえずこれで直るっぽいですが何が起きるかわからないので自己責任でお願いします><

追記 - 20080905
Ahead one step: grb+のちょっとした部分の修正

2008年5月29日木曜日

デートカフェとプログラマカフェ

東京でデートカフェが摘発されましたね。ふっつ~に高校生が制服でいたり、ほとんど売春宿化してたり、まったくうら、・・・け、けしからんです!



マジックミラー越しにくつろぐ女性。それを食い入るように見つめて物色する男性。つぎつぎと“カップル”が成立しては、街に消えていく。「市場」とも「水族館」ともいえる異様な空間がそこにはあった。



異様な空間…法のすき間で「男の水族館」堂々営業 (1/3ページ) - MSN産経ニュース から引用

名古屋でも名駅前で女の子無料でーすとか、ハデハデな車であからさまに宣伝してたりするのを見かけたので存在は知ってたけど、場所だけ提供とかうたってるだけで、実質売春クラブだよなぁとは思ってました。

でね、話は変わるんだけど、いやそんな変わらないけど、はてなのid:dropdbがプログラマーカフェとか作るって言ってて、



カフェ開発やりたいけど、一般的なカフェは無線使い放題じゃないし、電源も借りられなーい!だからといってネットカフェじゃ居心地悪いし、気がつけば漫画を読んじゃう!そもそもお洒落な感じがいいのですー!ってプログラマのためにカフェをやるとしたらどうなるんだろう?



カフェをオープンさせたいッ! - $ dropdb 人生 から引用

おもしろそうだなぁと思ったんだけど、プログラマカフェも技術を示したいGeekとかが無料でケーキとか食べてのんびり過ごしてて、それを悪をたくらむクラッカーたちがGeekたちをマジックミラー越しに品定めしてて、「君、スタイル(コーディングの)いいね。5万(5万は安いかw)でどう?」みたいに誘われて、超絶ウィルス作っちゃって、それを世界に蔓延させちゃう危険性があるから危ないとおもいます><

2008年4月25日金曜日

Javaでprivateなインスタンス変数にアクセスする方法

よくJUnitなどを使ってテストのテストケースでprivate変数の値をテストしたい場合があるけど、テストのためにクラス設計を変更するはあんましよくないし、回りまわって得られた結果でおkとするのもめんどくさいと思うことがよくあります。
そんなときはアクセス権を動的に変更して、private変数に直接アクセスしちゃいましょう!
こちらを参考にしました。

クラス Field
リフレクションの学習

サンプルコード:

// Test.java
public class Test {
public static main(String[] args) {
PrivateVariable pv = new PrivateVariable();
// System.out.print(pv.himitu);
// ↑このコードはprivateの変数を呼び出してるのでコンパイルエラー
  Field field = pv.getClass().getDeclaredField("himitu");
// ↑対象のオブジェクトからクラスをとってgetDeclaredField()を使ってprivate変数を取得しています。渡している文字列は変数名です。
field.setAccessible(true);
// ↑取得したFieldオブジェクトのアクセスチェックするしないの指定。
//trueを渡すとアクセスチェックが抑制され、private変数も呼び出せるようになる。
System.out.print(field.get(pv));
// ↑Fieldオブジェクトにprivate変数があるオブジェクトを渡して値を取得する。
}
}

// PrivateVariable.java
public class PrivateVariable {
private String himitu = "実は俺・・・";
}


上記のコードを実行するとコンソールに「実は俺・・・」と表示され、PrivateVariableクラスのprivate変数himituにアクセスできたことがわかります。
これでいちいち回りくどいユニットテストを書かずに、private変数にアクセスして単純なテストケースを書けるようになりました!

※注意事項
private変数にはアクセサ(private変数にアクセスするメソッド。要するにゲッター、セッター。)が用意されている場合この方法ではなくてアクセサを通して得た値でテストをしてください。アクセサのなかにはテストしたいオブジェクトの状態を持つprivate変数の値に影響を与えている物もあるからです。

2008年4月21日月曜日

pythonブートキャンプ4日目

HeadFirstのオブジェクト指向分析設計を買いました。
例題をpythonで書き直したりしつつ進めていきたい。
その前にチュートリアルを終わらせなければ!っということで4日目。

前回に続いてチュートリアルやってきます。
まだまだなぞってるだけなので参考にならないかも><
でも、初心者がつまずくところを挙げれればと。


ちょっとチュートリアル入る前に前回最後に言及した
ドキュメントの見かたを調べたのでどぞ。
パイソンのドキュメントはpython.exeの入っているフォルダのDocってとこに入ってます。
windows版だとPython25.chmが入っていました。
当然英語ですが、ネットで探せば日本語版も落ちてます。
http://www.python.jp/doc/nightly/
とりあえず、簡単に各項目の説明を。
・Tutorial - チュートリアル
・What's New in Python - 最新版の変更点
・Global Module Index - 索引
・Language Reference - 言語仕様
・Library Reference - 各クラスの機能
・Extending and Embedding - C/C++プログラマのためのチュートリアル
・Macintosh Module Reference - マック用
・Python/C API - C/C++プログラマ向けのリファレンス
・Installing Python Modules - 管理者向け
・Documenting Pyhon - ドキュメントの著者について
・Distributing Python Modules - 開発者とパッケージャーについて
・Documentation Central - ネット上のドキュメントの最新版が見れます
・Python How-To Guides - ネット上のハウツー

ん!?C用のチュートリアルとかあるんだ・・・Cが組み込めるの?Cに組み込めるの?
Javaしか知らない僕にはとりあえずは関係なさそうかな?
で、自分が見たかったJavaのAPIのようなのはLibrary Referenceで見れました。
チュートリアルで少し触ったStringクラスのメソッドについては
3.6.1のString Methodsに詳しく載っています。
Javaのように1ページに説明からクラスメンバーまで全部載せるんじゃなくて
別になっているようです・・・すごい違和感。慣れって怖いなぁ><


それじゃ~チュートリアルへ。
今日は3.1.3 Unicode 文字列から。

Unicode文字列の作成

>>> u'Hello!!'
u'Hello!!' #出力に小文字のuがついてたらUnicode
>>> u'Hello\u0020!!' #\uでユニコードをそのまま使える
u'Hello !!'


Unicodeのrawモードは'ur'
rawモードはエスケープを無効に。ただしこの場合Unicodeは変換される。
http://aheadonestep.blogspot.com/2008/04/python.html

word = ur'Hellow\u0020!!\n world'
print word
Hellow !!\n world #ユニコードは変換されてるけど\nは変換されてない


最初間違って'ru'ってつけててエラーに。エラー表示は
SyntaxError: invalid syntax
最初何が間違ってるのかわかんなかった・・・。
エラー処理しっかりしてるってドキュメントに書いてる割に表示は微妙だ・・・。


組み込み関数unicode()はUnicodeへエンコードおよびデコードするための使える。
Unicodeの印字やファイル書き出しstr()の変換はデフォルトはASCII
Unicode文字列.encode()で8ビット文字に変換(普通の文字列とは違うので注意!!
.encode('[エンコード型]')エンコード型は小文字推奨


str(u"あいう") #これはASCIIに変換できないのでエラーとなる

u"あいう".encode('utf-8') #utf-8形式に変換
"あいう".encode('utf-8') #デフォルトはASCII型なのでできないとエラーになる

unicode('hentai', 'utf-8') #Unicodeへ変換


文字列はここでとりあえず終わりのようですね。
Webサービスを作ってみたいと思っている身としては文字列の扱いには
慣れておかないといけませんね。あとは通信系か。


3.1.4 リスト

リストはカッコ内にカンマで区切って宣言。シンプル!
インデクスはもちろん0からで文字と同じように[]で。スライスも使える。
→文字列のスライス


list = ['hello','Hentai',4]
print list
['hello','Hentai',4]

print list[1]
Hentai
print list[1:]
['Hentai',4] #単一だと中身で複数だとちゃんとリストの切り出しなのがすごい


文字列型は変更不可でしたがリストはここの要素を変更できる
スライスの代入を行うことでサイズ変更もでき要素の除去や挿入ができる。
文字列型と同じようにlen()でサイズもみれる。
#これはlist.len()じゃないとオブジェクト志向とは言えないよねー


list = ['hello','hentai',200,4649]
list[1] = 'do' + list[1]
print list[1]
dohentai

list[:2] = [] #最初の二つの要素を除去
print list
[200,4649]

list[0:1] = ['hentai','hello'] #最初に挿入
print list
['hentai','hello',200,4649]

list[0] = ['hentai', 'hello'] #要素指定だとそれがリストに入れ替わる
print list
[['hentai', 'hello'],'hello',200,4649]

list[0:] = ['hentai','hello'] #0以降なので全部入れ替わる
print list
['hentai', 'hello']

list = ['hello','hentai',200,4649]
print len(list) #要素数の表示
4


リスト内リストのとこで参照の話が触れる程度でてきます。
Javaは参照だらけなのでこの辺の考えは大丈夫。

次からようやく各種構文が出てきてプログラミングらしくなりそう!

2008年4月9日水曜日

初心者がつまづくPython 三日目

前回に追記
隣り合った文字列はそのまま連結→隣り合ってるのがリテラルの場合のみ

word = 'hello'
print word 'hello' #これはダメ

print 'hello''hello' #これはいける
hellohello

三日目からはスクリプトファイルを作って実行する
対話モードはちょっとした事を調べるのに便利ってこと
スクリプトファイルの実行
→python test.ph

TeraPadの設定
実行ファイル:cmd
コマンドパラメータ:/K CD %d && python %n


文字列の抜き出し
文字列変数[最初のインデクス:最後のインデクス]
インデクスはもちろん0から


word = 'hello'
print word[1:3] #2文字目から3文字目まで
el


インデックスのデフォルト値
何も入れないとそれまで、それ以降


word = 'hello'
print word[:4] #4文字目まで
hell
print word[2:] #3文字目から最後まで
llo


その他の数値
無理そうな数を入れてもエラーにならない!!


word = 'hello'
print word[100:] #何も出力されないがエラーも出ない
print word[-2:] #マイナスを入れると・・・
lo #最後の2文字が
print word[-2:4] #lohelloを期待したけど・・・何も出力されない


C言語のように文字列の変更はできないが要素同士の組み合わせは便利


word = 'hello'
word[0] = 'x' #エラーとなる

word = 'x' + word #これなら代入なのでいける
print word
xhello

print word[1:] + 'world'
helloworld


スライス文字の不変式


word = 'hello'
print word[2:] + word[:2]
hello


前述したが無理のあるインデクスでもうまくいく
大きすぎるインデクスは文字列のサイズに置き換えられる
負の数字は右から数えるが"-0"は0と一緒で右からじゃなく1文字目
ただし、インデクス指定ではエラーがでる。


組み込み関数len(文字列)は文字列の長さを返す


word = 'hello'
len(word)
5


Unicode文字列はシーケンス型

三日目まとめ
チュートリアル中に出てくる関数を調べる方法がわからない><
Javaだとクラスを元に探せるけど、Pythonはオブジェクト指向といっても
クラスベースじゃないってことかな?
なんにせよドキュメントの見かたって新しい言語を覚えるのに大切な事だと思います。

2008年4月5日土曜日

Python初心者の二日目

新しいPCの環境も整ってきてPythonも入れて少し勉強した。
とりあえずチュートリアルを一通りやろうとpdfをダウンロード。

Python チュートリアル (PDF)
http://www.python.jp/doc/pdf/nightly/tut.pdf

が、開けない。アドビリーダーがインストールできないっ・・・!!
vistaやってくれる、そこにしびれる憧れない。
インストーラーを実行してもうんともすんとも言わない。
検索すると以下のような記事が。



 1)AdobeのDownLoad Manegaerが起動

 2)ダウンロードが完了すると下記フォルダにファイルが展開される

   C:\Users\hogehoge\AppData\LocalLow\NOS\Adobe_Downloads



   展開されたファイルは

    Setup.exe、setuo.ini、Data1.cab、AcroReader.msi、abcpy.ini



となりましたので



 3)上記フォルダ内のファイルを全て別フォルダに退避。

 4)セットアップを中断し、PCを再起動。

 5)退避させたsetup.exeのプロパティ→互換性→「視覚テーマを無効にする」にチェック

 6)setup.exeを起動しインストール



Adobe Reader8.1 のインストール ネットワーク管理者というお仕事 から2008年4月6日に引用

とりあえず視覚テーマを無効にすればできました。AdobeはVistaに対応したと書いてるけどしてないという罠。いや、仕様ですか・・・><
これでチュートリアル読めるようになったので本題に入ります。

今日のPython(今日のわんこ的な意味で)


まだまだ初歩的です。間違った理解してる箇所があるかもしれませんのでご了承ください><

起動->python
終了->import sys;sys.exit()かControl-Z
sysはシステムクラス?importはJavaといっしょ

python -c [command]でコマンド実行
python -c print "Hello world"→×
-c オプションのあとはすべて""で囲む。エスケープは\
正解は→python -c "print \"Hellow Woerld\""

コメントは#で始まる

>>> = 一次プロンプト
... = 二次プロンプト

対話モードでは代入した変数が保持されてる


>>> width = 10 #エンター押しても表示されないが代入はされてる
>>> width #変数を入力すると値が表示
10
>>> print width #も同じ結果
10


浮動小数点は完全にサポート

>>> 7/2 #整数の演算は切り捨てだが
3
>>> 7.0/2 #7を7.0にして割ると
3.5
>>> 7.0/3 #無理数も
2.3333333333333335


複素数もサポート(複素数=2乗すると-1になる数字)
よくわからん


対話モードでは最後に印字された式が変数が"_"に代入される
文字列は×この変数は読み込み専用として使うべき
→print を使わずに直接""で囲んで表示させると文字列も_変数に入る

>>> 3+3
6
>>> _
6
>>> print "10" #文字の10を印字
10
>>> _ #式のみなので最後の6が表示される
6
>>> "Hello" #直接印字
'Hello'
>>> _ #'Hello'が入っている
'Hello'


文字列は''で囲う
文字の末尾をバックスラッシュにすると改行してかける
(理論的にはつながっている)
出力はprintを使わないとそのまま表示される

>>> hello = "こんにちは\
... はじめまして"
>>> print hello
こんにちははじめまして
>>> hello
'unicode...'


文字リテラルに"raw"(未加工)

>>> r"test\n\
... tetest!!"
'test\\n\\\ntetest!!"
>>> print r"test\n\
... tetest!!"
test\n\
tetest!!


"""もしくは'''を使うと行末エスケープが不要になる

>>> t = """test
... te
... testtttt"""
>>> print t
test
te
testtttt


文字列の演算

>>> t = "test"
>>> e = "exam"
>>> te = t + e #+は結合
>>> print te
testexam
>>> print te*10 #*で繰り返し
testexamtestexamtestexamtestexamtestexamtestexamtestexamtestexamtestexamtestexam

隣り合った文字列はそのまま連結する


今日は以上です。
Pythonの徹底的にシンプルに書ける文法にはまりつつあります。
モチベーションのために何か簡単なサービスを考えて目標としたいところ。

2008年3月23日日曜日

Python初心者が最初につまづくあれこれ

最近ようやくプログラミングと言うもののおもしろさが分かってきたので、Pythonを始める事にした。何故Pythonなのかよくわかんないけど、とりあえず蛇でかっこいいのと(実際はモンティ・パイソンが元ネタ)、レア言語ってかっこいいじゃん?みたいな感覚です。括弧がいらないってのもおもしろいところ。Lispの反対で天邪鬼っぽいとこがいいでしょ?

  • 導入編
FrontPage - Pythonのお勉強
http://python.rdy.jp/
インストールはここの最新のダウンロードの項からお好きなOSの物を

Python Japan User's Group
http://www.python.jp/Zope/

Instant Hacking
http://www.python.jp/Zope/intro/instant_hacking_jp
とりあえずインストール終わったら、チュートリアルこなそう。演習をちょいちょいっとね。

Python 2.4 ドキュメント - June 27, 2006
http://www.python.jp/doc/nightly/
あとはリファレンス見てお好きなように。

  • 初起動編
最新バージョンをインストールしたらPython Command Lineを立ち上げていじくってみる。

Hellow world!!


print "Hello world!!"


  • とりあえず詰んだ編
いきなりループ制御で詰んだ。for文は"for var in range(1,100)"みたいな感じなので"Hellow world"を10回表示させようとすると・・・


for num in range(1,10) :
print "Hello world!!", num;

IndentationError: expected anaindented block


IndentationErrorなるものが出て詰んだ。Indentation??インデンテイション・・・インデント!!そうです、for文内の命令ということを表すために、インデントを入れないとだめ。インデントで怒られるとかなんか新鮮です。以下のように治して実行。


for num in range(1,10) :
print "Hellow world!!", num;

実行結果:
Hello world!! 1
Hello world!! 2
Hello world!! 3
Hello world!! 4
Hello world!! 5
Hello world!! 6
Hello world!! 7
Hello world!! 8
Hello world!! 9


ちなみにインデントはタブでもスペースでもいいみたい。
とりあえず飽きなければ自分がつまづいた部分を晒していこうと思います。つづく・・・?

2008年3月18日火曜日

OCL:defでコレクション型属性を定義する方法

OCLで新たに属性を追加するにはdefを使って定義するが、コレクションの属性を定義する場合はコレクションの型と要素の型も指定する。

def : Collection(OCLType //コレクション内部の型) = expression //コレクションを返す式


EclipseのOCLプラグインだとこうなる

OCL ocl = OCL.newInstance(ECoreEnviromnmentFactory.INSTANCE);
OCLHelper helper = ocl.createOCLHelper();
helper.defineAttribute("collection : Collection(Integer) = OrderedSet{1,2,3}"); //OrderedSet型で要素が1,2,3が作られCollection(Integer)型のcollectionという変数が定義される
//helper#define*で定義された属性や操作はこのhelperから作られたQueryでしか有効にならないので注意


属性だけじゃなく操作も定義できるのですっごい複雑なOCLを毎回書くのが面倒な場合でかつ、モデルに直接持たせるほどでもない属性であった場合、エイリアスとして定義して使うことができる。

でも、渡されたオブジェクトがCollection型であるか調べる方法がわからなず。

// 上の続きでcollectionはInteger型が入ったコレクション
collection.oclIsTypeOf(OrderedSet(Integer)) // これはダメだった

Collectionとして見るよりは、要素の集合として見てて、要素の属性もそのまま使えるから、Collectionの型を意識する必要は無いのかな?

ところで、この辺りを触ってて、OCLHelper#defineOperation()で二つ以上パラメータを持った操作を定義しても、すべてのパラメータの値が必ず最初のパラメータになるバグに遭遇して困っている。
Bugzillaで検索しても出てこず、最新版でも直ってなかったので気付いてないのかなぁ?
どなたかBugzillaで発見したら教えてください。