Hatena::ブログ(Diary)

m2

2015-07-20

Roslyn Analyzer でコメントをコンパイルエラーにする

f:id:miya2000:20150719155955p:image

日付っぽい文字列と「START」って書いてあるコメントをエラーにする Roslyn アナライザを書きました。
コンパイルエラーといってもビルド&実行できるので、見た目エラーっぽい警告くらいの感じです。

ソースはこちら
https://github.com/miya2000/CommentAnalyzer

つまりはコードレビューがプログラミングできるということですね!
こんな感じで ウンコードマニア のいくつかはアナライザで実装できるかなーと思います。書こう!Roslyn アナライザー

--

8/23

nuget に登録しました。
https://www.nuget.org/packages/CommentAnalyzer/

今日のコミットでテストを実装してたり、日本語環境の場合はメニューが日本語になったりしています。
これをベースにまた別のを書く予定。

2015-03-06

// i をインクリメント

コードレビューに疲れたのでだれかコレに名前付けてくだしあ

2014-10-15

Visual Studio のひどい訳について

はてな記法が忘却の彼方。


さて、善意のひどい訳についてに刺激を受けて、Visual Studio のひどい訳をさらしてみます。

まず「プレビューおよび変換」です。

f:id:miya2000:20141015204344p:image

英語版では「Preview Transform」となっています。

f:id:miya2000:20141015204342p:image

この機能は環境に合わせて設定ファイルの内容を変換する機能の変換結果をプレビューします。こんな感じ。

f:id:miya2000:20141015204345p:image

なんですが、この画面は「プレビュー」機能であって「変換」機能ではありません。「および」はどこから出てきたのでしょうか(私は「変換」ボタンを必死に探しました)。機能そのものはとても素晴らしいだけに残念です。


ちなみに Visual Studio の規定の言語を変更するには 対象の言語パックインストールして、Devenv コマンド ライン スイッチ/LCID を指定します。

devenv /LCID 1033

日本語に戻す場合は「1041」です。

頻繁に切り替えるならショートカットを作っておくと便利。

f:id:miya2000:20141015204341p:image


面倒なので次で最後になりますがマージツールの「右へ」。

f:id:miya2000:20141015204346p:image

もうこの時点でおかしいと気付くでしょうか。
英語版では「Take Right」。

f:id:miya2000:20141015204343p:image

左右に並べられたファイルの異なる部分のうち、右使う、という意味ですが、「右へ」だとどちらかというと逆の意味に思えます。

おそらく WinMerge なんかの「右へコピー」と勘違いしちゃったのですかね。どちらにしろ意味は逆ですが。

f:id:miya2000:20141015213801p:image


以上です。
きっと一度もその機能を使ってない人が翻訳しているのだし、翻訳元も文章でなく「Take Right」みたいな数単語では誤訳も致し方のないことなのでしょう(テストも書けないし)。
気付いたら「ヘルプ」→「フィードバック」→「問題点、改善点の報告」するとよいかもしれません。元記事にあるように Github で管理して pull request が送れる形になればより良いですね。

あと Visual Studio の新機能を日本語で紹介するような方であれば、記事の投稿時にちょっとだけこのあたり意識していただけるとありがたいな、と思います。


蛇足ですが、このマージツールは「横表示」で縦に、「縦表示」で横に並べて表示することができるので、もはや「右」とか「左」とか関係ありません。訳を直すにしてもいったいどうすれば...

f:id:miya2000:20141015212535p:image

2012-08-05

認証情報付きアドレスに対するブラウザの挙動の比較 (location.href の話)

先日、夏のちょっと怖い話としてlocation.hrefの盲点という文章が公開されました。

デスクトップでこの影響を受けるのは Safari5 (Windows または Snow Leopard 以前の Mac) くらいのもので、対象者は少ないんじゃないのかなーと予想しますが、

残念なお知らせがあります。Safari Mobile/Androidの標準ブラウザもこの動きをするのです。

さらに、Androidの標準ブラウザは@付きURLにアクセスする時に警告も出しません。

今この情報を出した一番の理由として、このモバイルの問題をどうやっても早急に解決できないことがあげられます。モバイル端末のアップデートは機種によりまちまちで、提供されるかもわかりません。そんな現状で、このような潜在的な問題が早く修正されるとは思えません。アプリケーション開発者で対応するしかないでしょう。

http://masatokinugawa.l0.cm/2012/08/safari-location.href.html

とのことなので、モバイル利用者の方々には Opera Mobile などの、Mobile Safari を使用していないブラウザをお勧めする*1とともに、開発者の方々には影響の調査と修正をお願いしたいところです。

たいていは同じオリジンリソースの読み込みにはホスト名以降の相対パス(../js/hoge.js とか /static/hoge.js とか)が使われるかと思いますけれども、location.href からアドレスを組み立てるなどしている箇所があれば、そこに今回の問題があるかもしれません。

以前であれば外部リソースを読めるのは SCRIPT 要素を使った js (JSONP) 位のものでしたが、XHR level2 によってサーバーが許可していれば XHR でも読み込めるようになりました。「XHR で読み込めたんだから同じオリジンのはず」という状況ではなくなっていますので、SCRIPT にしろ XHR にしろ、外部リソースを読み込む場合はそのサーバーがリクエスト時に意図したサーバーなのか、というのは注意が必要でしょう。
(詳しくは jQuery MobileのXSSについての解説 - 金利0無利息キャッシング ? キャッシングできます - subtech 等)


さて、本稿では今回問題になった「認証情報付きアドレス」を各ブラウザがどのように扱っているのかというのを比較してみます。

テストページとして http://jsrun.it/miya2000/2Lyx を用意しました。jsdo.it を使用させていただいています。
[ユーザー名] と [パスワード] を入力して実行すると、http://[ユーザー名]:[パスワード]@jsrun.it/miya2000/2Lyx?dummy というアドレスを生成して iframe に設定し、その location.href を確認します。ついでに a 要素の href プロパティについても確認しています。


私のほうで確認できる環境のテスト結果は上記のテストページに貼り付けました。各ブラウザで違いがあって面白いですね。
以降はテスト結果に対するまとめになります。


「認証情報付きアドレス」についておさらい

(後で書く)

(もう書かない)

*1Sleipnir は Mobile Safari を使用しているようです

2012-03-20

Java の List の indexOf, contains, remove がなぜかタイプセーフじゃなくて軽く死ねる件 (Map#get(Object) も)

いやーそんなはずはないと思って今まで確認すらしてませんでした。

http://java.sun.com/javase/ja/6/docs/ja/api/java/util/List.html#contains(java.lang.Object)

どういうことかというと、これがコンパイルエラーにならないということです。

import static java.util.Arrays.*;

public class Hoge {
    public static boolean isHogehoge(Integer hogeType) {
        return asList("1", "3", "5").contains(hogeType);
    }
}

コンパイルエラーにするにはジェネリックなメソッドを作って、そちらを使用します。

import static java.util.Arrays.*;

public class Hoge {
    public static <E> boolean contains(E value, java.util.List<E> list) {
        return list.contains(value);
    }
    public static boolean isHogehoge(String hogeType) {
        return contains(hogeType, asList("1", "3", "5"));
    }
}

これで isHogehoge のパラメーターを「Integer hogeType」にすると、ちゃんとコンパイルエラーになります。

しかしまたつまらぬ static メソッドが増えてしまった。
Object#equals(Object) もそうだけど、基本的に Java プロジェクトでは一つ static メソッド集的なものを作って、オブジェクトメソッドでなくそちらを使うようにすると問題が減らせると思います。

こんなの絶対 OOP じゃないよ!

--

(追記)

Map#get(Object) も同じようです。

java List contains typesafe」なんかで検索してもそれっぽい情報が見つからなかったのですけど、なるほど Map の方が問題になるケースが多そうで、「java Map get typesafe」で検索するとそういった記事や議論が見つかりました。

Recently I have encountered a bug in a production code when dealing with a simple (really simple) usage of a Map.

...

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

public class EmployeeDataLookup2 {
    // A map storing relation between employee ID and name.
    private Map<Long, String> employeeIdToName;
...
    // Lookup method for finding employee name for given employee ID.
    public String findEmployeeName(int employeeId) {
        return employeeIdToName.get(employeeId);
    }

...

The problem is that after introducing generics, probably due to backward compatibility, some of the methods in Collection and Map interface have not been changed and still do not perform type checking. One of them is Map.get(Object) which have caused the bug in the code above.

JavaBlogging » Type safety in Java Set and Map

As mentioned by people above, the reason why get(), etc. is not generic because the key of the entry you are retrieving does not have to be the same type as the object that you pass in to get(); the specification of the method only requires that they be equal. This follows from how the equals() method takes in an Object as parameter, not just the same type as the object.

...

  1. Then why is V Get(K k) in C#?
    -> Differents specifications.
java - What are the reasons why Map.get%28Object key%29 is not %28fully%29 generic - Stack Overflow

an object of one type can be .equals() to an object of another type. get() only requires that the object that you give it be .equals() to the key you are getting

Java Generics: Why Does Map.get%28%29 Ignore Type? - Stack Overflow

A popular myth is that it is stupid and evil, but it was necessary because of backward compatibility. But the compatibility argument is irrelevant; the API is correct whether you consider compatibility or not. Here's the real reason why.

...

Let's say you have a method that wants to read from a Set of Foos:

    public void doSomeReading(Set<Foo> foos) { ... }

The problem with this signature is it won't allow a Set<SubFoo> to be passed in (where SubFoo is, of course, a subtype of Foo).

...

    public void doSomeReading(Set<? extends Foo> foos) { ... }

Perfect!

But here's the catch: if Set.contains() accepted type E instead of type Object, it would now be rendered completely unusable to you inside this method body!

...

Static analysis plays an extremely important role in the construction of bug-free software.

smallwig: Why does Set.contains%28%29 take an Object, not an E?

最後に引用した Kevin Bourrillion さんの post に全部書かれてますね。

僕が書いた contains の実装はワイルドカードに対応できません。そのまま使うとコンパイルエラーになります。

    static class Foo {
    }
    static class SubFoo extends Foo {
    }
    public void doSomeReading(List<? extends Foo> foos) {
        if (foos.contains(new SubFoo())) { // API仕様通り
            // 
        }
        if (contains(new Foo(), foos)) { // <- コンパイルエラー
            // 
        }
    }

えー、じゃあ contains をこんな感じにすればどうかなーと思うわけですが。

    public static <E> boolean contains2(E value, java.util.List<? extends E> list) {
        return list.contains(value);
    }

こんな結果に。元々何がやりたかったかわけわかんなくなります。

    public void doSomeReading(List<? extends Foo> foos) {
        if (contains2(new Object(), foos)) { // えっ
            // 
        }
    }

f:id:miya2000:20120321210131p:image


(あとで書く。結論としては FindBugs でOK。)

2012-01-15

Twitter のユーザータイムラインからリンクを抽出して RSS にする Yahoo Pipes を作りました

暇なときによく 1470.net注目URLRSS リーダーで読んでいたのですが、今月の頭あたりから 1470.net のホストから RSS が配信されなくなりました。代わりに Twitter@recenturl へのリンクがありましたので、今後は Twitter で配信するようです*1

そうすると Twitter から提供されるユーザータイムラインRSS を購読すればいいように思いますが、それだと RSS のリンクが TwitterTweet へのリンクになってしまうので、読みたい記事があった時に、

  1. TwitterTweet のページを開く
  2. Tweet に含まれる短縮URLをクリックする

と二度手間になってしまいます。

また、見たいページのサーバーは問題ないのに Twitter サーバーが落ちていると閲覧できないなどといったことも起こりえますから、非常に不便です。

というわけで、Twitter のユーザータイムラインRSS からリンクを抽出して別の RSS に仕立て上げる pipes を作成しました。

細かい仕様は pipes にも書いていますが以下のような感じです。

  • 本文の先頭がアカウント名と同じ場合、それを削除します。
  • 本文の末尾もしくは先頭が t.co の場合、t.co を展開したアドレスを RSS のリンクにします(末尾の方を優先します)。
  • t.co の展開には http://ux.nu/ を使用しています。
    ux.nu が「安全でない」と判断した場合は RSS のタイトルに [unsafe] を付けます。
  • デフォルトでは URL を含まない Tweetフィードに含めません。「ignore no url tweet」を「on|yes|true」以外にすると含めます。

@recenturl は先頭に URL がありますが、末尾の URL にも対応しているので、同じように botURLTweet するようなものにも使えるんじゃないかと思います。


f:id:miya2000:20120115201731p:image

いい感じになりました。

感想

TwitterRSS ではすべてのアドレスが「t.co」になるので、短縮URL展開部分はそれほど複雑にならずに済みました。

それと ux.nu は素晴らしいですね。untiny.me が t.co を bit.ly に展開した時はズッコケたんですが、ux.nu はリダイレクトが多段になっていても最終的なアドレスを返してくれるので、とても助かりました。ありがとうございます。

http://ux.nu/hugeurl?url=http%3A%2F%2Ft.co%2FKxXrbCV2&format=plain

が、なぜかドメイン部分が含まれずに

/post/15835992847/fotoshop-by-adobe-by-jesse-rosten-brilliant?aa5fb790

を返すみたいです。

2012/1/17 追記

http://1470.net/recenturl.xml 1470.netの話題のURLフィードを復活させました。@recenturlにも流していますが、RSSリーダーとかでチェックしたい人はこちらをどうぞ。

http://twitter.com/#!/ishinao/status/159129373503520769

あらあら。ありがとうございます。

*1:@ishinao さんに Twitter で聞いてみたんですが、回答いただけませんでした。。。

2011-12-30

重みをつけて乱択する (バイナリサーチ版)

せっかく書いたのでバイナリサーチ版のっけときます。

http://jsfiddle.net/t58Vv/6/

// algorithm - 重みをつけて乱択する http://blog.livedoor.jp/dankogai/archives/51761113.html
// バイナリサーチ版
var make_random_picker = function(picks){
    var i, l = picks.length, t = 0, choices = picks.concat();
    for (i = 0; i < l; ++i) { choices[i][1] = (t += choices[i][1]); }
    for (i = 0; i < l; ++i) { choices[i][1] /= t; }
    return function() {
        var r = Math.random(), head = 0, tail = l - 1;
        while (head <= tail) {
            var sum = head + tail;
            var mid = (sum <= 0x7fffffff) ? (sum >> 1) : Math.floor(sum / 2); 
            if (r < choices[mid][1]) {
                if (mid == 0 || r >= choices[mid-1][1]) {
                    return choices[mid][0];
                }
                tail = mid - 1;
            }
            else {
                head = mid + 1;
            }
        }
        return null; // never.
    };
};

2011-12-21

僕たちプログラマーは、プログラミングに、Excelを使います!

なんとかカレンダー 21日目 id:miya2000 です。こんばんは!

低級テキストエディタでせっせとコーディングしているあなた!そろそろ手がが疲れてきていませんか?

そんなあなたは、この記事で紹介する Excel コーディングをぜひ覚えてください。

わずか数秒で世界が変わります!

元ネタ

めんどうな作業がわずか数秒に!新人デザイナーが 知らないと一生後悔するExcelを使ったHTML生成 | Webロケッツマガジン
http://webrocketsmagazine.com/entry/20111209/html-code-generation-using-excel.html

Excelを使った高級コーディング

とにかく Excelコーディングを行った画面を見てみましょう。今回は Javaコーディングをやってみます。

f:id:miya2000:20111221231556j:image

どうでしょう? 画面を見るだけでどれだけ恩恵があるかお分かりになるでしょうか。

画像にも書いていますが、パッと思いつくだけで以下のメリットがあります。

  • インデントをセルの幅で行うことで 2tab 4tab 戦争が終結!
  • 行頭以外を縦にそろえるのも列を揃えてあげれば簡単!
  • 「連続データ」機能で簡単入力!
  • コメントが別レイヤになり、ソースの邪魔にならずスッキリ!
  • マクロ機能で様々な機能を追加可能!

インデントや文字の位置揃え等、プログラムの本質以外の部分で時間を使う時代は終わりました!
そしてコメントは視覚的にもコメントらしくなり、「長文コメントのせいでソースが縦に長くなってスクロールめんどい」なんてこともありません!


ソースコードはテキストファイルである必要はなかったんや〜」

「な、なんだってー!」


でも、コンパイルも実行もできなんでしょう?

Excelコーディングしてもコンパイルも実行もできない… そんなふうに考えていた時期が俺にもありました。

とはいえシートからコードを抽出してファイルに出してコンパイルすればいいだけなので、その程度のことはマクロで書いちゃいましょう。

クラスパスは「.classpath」のシートに列挙してそこから読み出すようにしました。

f:id:miya2000:20111221231557j:image

実行引数も「.args」のシートに列挙。値の列挙も Excel が得意とする部分です。

f:id:miya2000:20111221231558j:image

あとは「開発」→「マクロ」からマクロを実行します。

f:id:miya2000:20111221231559j:image

結果はこんな感じです。ちゃんと実行できましたね!

f:id:miya2000:20111221231600j:image


Excel コーディングの目玉! 「連続データ」機能!

「連続データ」機能の威力をお見せしましょう!

現在 data10 まであるプロパティを datra15 まで増やしたいとします。
やり方は簡単で data10 のセルの右下の部分を右クリック→下へドラッグするだけ!

D

ドラッグ後に表示されるコンテキストメニューで「連続データ」を選択すると、ホラ! 「data10」の数字部分が 10 からの連番になってセルが埋められるんです!

まとめ

以上、id:miya2000 でした!

2011-07-24

最近のブラウザで flash に半透明 div を被せたらどうなるか

flash に「wmode="opaque"」つけると HTML 要素を被せられることは flash 上でマウスジェスチャーできるようにする user.js (wmode="opaque") - m2O - チーム俺等で書きましたが、最近のブラウザでどうなっているのかというのを試してみました。

サンプルとして使用したのは以下の動画です。

FF6オペラを(opera)ボーカロイドで(vocaloid)ver高音質(high-quality)‬‏ - YouTube

このページを開いて以下のブックマークレットを実行しました。

javascript:void(document.body.appendChild(document.createElement('div')).style.cssText='position:absolute;zIndex:9999;top:50px;left:100px;width:300px;height:300px;background:rgba(255,255,0,0.5)')

Opera10.10

f:id:miya2000:20110724213610j:image

私が今でも愛用している Opera10.10 です。

古いブラウザですので、前述のように「wmode="opaque"」を付けないと z-index に関わらず上に被せることができません。

「wmode="opaque"」を付けると上に被せることができて、被せた部分が半透明になり、下の動画が見えるようになります。

f:id:miya2000:20110724221331j:image

Opera12 (alpha)

f:id:miya2000:20110724213611j:image

Opera の現在の開発バージョンである 12 です。

被せている部分の動画は見えず、白く(動画の下の要素が)見えています。これは現在の安定バージョン(11.50) と同じ動きです。

Opera さんはほんとに奇妙な実装をしますね。

画像は省略しますが、Opera10.10 と同じように「wmode="opaque"」を付けると上に被せることができて、被せた部分が半透明になり、下の動画が見えるようになります。

Firefox 5

f:id:miya2000:20110724213609j:image

Firefox 最新バージョンの 5 です。

Opera10.10 と同じです。

こちらも画像は省略しますが、「wmode="opaque"」を付けると上に被せることができて、被せた部分が半透明になり、下の動画が見えるようになります。

Google Chrome 12

「wmode="opaque"」をつけなくても、被せた部分がきちんと半透明になり、下の動画が見えています。期待通りの動きです。

こちらも Firefox5 と同じでした。

まとめ

Opera12 での挙動が奇妙だったので他のブラウザも調べてみたら、

Google Chrome が期待通りの動きをしてくれて驚きました。

が、他のブラウザを見ると

まだまだ HTML 要素を重ねて使用したい場合は wmode をつけた方が良いようです。

wmode については 日本語入力が行えなくなる などの不具合が言われていましたが、最近の flash プレイヤーではどんなんですかね? その辺は調べてません。

2011-07-07

Connection: close