写真 青い空と雲と建物と木々の緑

nishimotzの日記

  • すごい広島 #6 でテスト駆動開発の読書

    すごい広島とは 広島のエンジニアやウェブデザイナーが毎週集まって、 もくもくしたり Hackしたり 読書したり する場所です。
    先週は欠席したので、今週は第6回でした。
    「テスト駆動開発による組み込みプログラミング――C言語とオブジェクト指向で学ぶアジャイルな設計」という本を読み始めました。

    原著 Test Driven Development for Embedded C のページからサンプルコードをダウンロードして、make しながら読み進めました。
    組み込みの開発はするかも知れないし、しないかも知れないのですが、NVDA に組み込まれている eSpeak や libLouis のようなライブラリも、一種の組み込みソフトウェアとしてとらえています。
    この本で使われているツールは UnityCppUTest なのですが、ダウンロードしたサンプルコードの中にどちらも入っていました。
    VisualStudio のプロジェクトファイルも入っているのですが、Cygwin か Mingw で make all するほうがしっくりきます。
    著者は Eclipse の CDT で、ファイルを保存したときに自動的にテストが走るようにしているそうです。。
    著者のJames W. Grenningさんの講演は5月にアジャイルジャパン広島サテライトに参加して拝聴しました。講演の内容はプログラミングというよりも開発者の文化とか理念のお話でしたが、そのときにこの本が紹介されたのを、今頃になって思い出したのです。
    今日読んだのは最初の100ページくらいなのですが、テスト駆動開発の「王道」がきっちり実践されているので驚いています。
    C言語を教える大学の情報系カリキュラムで、アルゴリズムと並行してこういう実践をさせたら、すごいことになるんじゃないかと思ったり。。
    オブジェクト指向開発とかテスト駆動とかいう話は、たいていプログラミング言語と結びついて語られるわけです。そして、この本は、C言語でアプリケーションそのものをオブジェクト指向的に書いたりはしないようです。でも、テスト駆動開発に必要なエッセンスを、素材であるC言語で、どう実践したらいいのか、見せてくれます。
    しかも、律儀に、テストを書く、失敗させる、コードを書く、成功する、という繰り返しを読者にしつこく提示します。
    テスト駆動は「何を使うか」ではなくて「いかに実践するか」なのだなあと改めて思いました。
    ツールの仕様だけを覚えても、思想やスキルは身につかないということですね。。
    この本の面白いところは、バージョン管理ツールについて一切言及がないところです。
    これだけテスト駆動を実践すると、どこでコミットするかとかブランチを切るかとか、普通はやるんですけど。。
    ただ「継続的インテグレーション」の説明の中で、バージョン管理ツールとのつながりそのものは語られているので、おそらく、話題を発散させないためにわざと削ったのだと思えてきました。
    そんなわけで「C言語をカッコよく使いこなしてみたい」と思わせてくれる本です。

  • すごい広島 #4 で Twitter API の勉強

    すごい広島とは 広島のエンジニアやウェブデザイナーが毎週集まって、 もくもくしたり Hackしたり 読書したり する場所です。
    ということで、今週は第4回でした。
    NVDA の作業をしようかと思ったのですが、たまたま Twitter API 1.0 が今日終了したということで、あちこちでソフトやサービスが動かなくなったという話を聞き、久しぶりに Twitter API の勉強をしました。
    よく考えたら、Twitter API はなんどか使ったことがあるのでした。最初に勉強したのは Twitter4r という Ruby のライブラリでした。。
    まずは Apigee で Twitter API 1.1 を叩いてみます。OAuth 認証もやってくれて、JSON で情報が返ってきます。簡単ですね。。簡単すぎてつまらない。。
    The Qube というスクリーンリーダー対応の Twitter クライアントは Python で書かれていて Tweepy というライブラリに依存しているという話。
    なにかライブラリを試してみようか、ということで、調べたら Tweepy の他に Python Twitter というものが見つかりました。
    せっかくなので使ってみました
    が、タイムラインが取れて、ツイートができることは確認できたものの、GetFollowers などを使うと

    twitter.TwitterError: [{u’message’: u’Rate limit exceeded’, u’code’: 88}]

    になってしまい、うまくいかず。。
    そもそも Twitter で何をしたいのか深く考えてなかったので、久しぶりに音声対話アプリを書いてみました。
    書いたのはこんなコードです。
    Windows 8 でこのプログラムを起動して、「今日はWindowsで音声認識を使うプログラムを作りました」「コンピューターいまのをツイートして」といえば、Windows 内蔵の日本語音声認識と日本語音声合成で、下記のようにツイートができました。


    「コンピューターツイッターを読んで」といえばタイムラインを読んでくれます。
    Python でこういうライブラリを使うと HTTP も JSON も文字コード変換もほとんどお任せでいいから便利ですね。。
    静かな「もくもく作業の場」でひとりコンピューターに向かってしゃべり続けてしまい、すみませんでした。今度から突発的に音声認識アプリが書きたくなったときに備えて、常にヘッドセットを持参しようと思います。。
    最近は Mac OS X や Chrome ブラウザにも音声認識機能がついてたりしますが、Windows 8 はクラウドでなくコンピューターの中で音声認識と音声合成をしています。でも作ったものが Twitter アプリだから、やっぱりネットワークにつながってなくてはならないわけで、違いをアピールしにくいです。。
    今日は使いませんでしたが dragonfly – Python-based speech recognition framework – Google Project Hosting は SAPI と Dragon の音声認識APIラッパーらしいです。アプリケーションごとの音声コマンドのライブラリが充実している印象ですが、フレームワークがここまでやるとローカライズが大変かも。。
    ところで、今週土曜日にはNVDA広島勉強会を行います。よろしくお願いします。
    追記(6月14日)
    Twitter クライアントの Qube は無事に API 1.1 対応したそうです:

  • AngularJS と NVDA

    <htmlday> 2013 ということで AngularJS で遊ぼう という勉強会に参加しました。
    AngularJS は Web アプリケーション開発のフレームワークということで、簡潔に書けて保守性が高いのが特長、らしいです。
    しかし、生産性の高い開発手法という話を聞くと「それってアクセシビリティは大丈夫なの?」とつい思ってしまいます。
    そこで、angularjs.org のトップページのビデオで紹介されていた TODO アプリケーションのサンプルをスクリーンリーダー NVDA 日本語版 と Firefox の組み合わせで確認しました。
    書かれたマークアップは内部で標準的なHTMLに変換されているので、フォーカス移動などはちゃんとできるのですが、チェックボックスにフォーカスしたときに、その右側にある項目名を読み上げないので、何の操作をするチェックボックスなのかわかりません。
    ふと aria-labelledby でやればいいんじゃない? と思ったので、下記のように直したところ、うまくチェックボックスの項目名を読み上げるようになりました。
    最初は id をつけるために todos モデルに通し番号のプロパティを追加したのですが、後で $index という特殊プロパティがあることを教わったので、todo.js 側のコントローラーとモデルは書き換えないで実装できました。アクセシビリティのための処理が View だけで完結するのは素晴らしい。AngularJS なかなかよさそうなのでもうちょっと勉強してみたいと思います。
    <htmlday>とは、日本全国でWeb制作者/開発者向けのイベントを同日に開催することで、日本のWebを一層盛り上げようという「お祭り」だったそうで、私も貢献できればと思いブログを書きました。
    ちなみに広島市中心部は「とうかさん」というお祭りの季節です。。
    以下のソースでは bootstrap.cssUnderscore.js を使っています:

    <!doctype html>
    <html ng-app>
      <head>
        <script src="angular.js"></script>
        <script src="underscore.js"></script>
        <script src="todo.js"></script>
        <link rel="stylesheet" href="bootstrap/css/bootstrap.css">
        <link rel="stylesheet" href="todo.css">
      </head>
      <body>
        <h2>Todo</h2>
        <div ng-controller="TodoCtrl">
          <span>{{remaining()}} of {{todos.length}} remaining</span>
          [ <a href="" ng-click="archive()">archive</a> ]
          <ul>
            <li ng-repeat="todo in todos">
              <input aria-labelledby="label{{$index}}" type="checkbox" ng-model="todo.done">
              <span id="label{{$index}}">{{todo.text}}</span>
            </li>
          </ul>
          <form>
            <input type="text" ng-model="todoText"  size="30"
                   placeholder="add new todo here">
            <button ng-click="addTodo()"><i></i>Add</button>
          </form>
          <button ng-click="clearCompleted()"><i></i>Clear Completed</button>
        </div>
      </body>
    </html>
    // todo.js
    function TodoCtrl($scope) {
        $scope.todos = [
    	{text:'learn angular', done:true},
    	{text:'build an angular app', done:false}];
        $scope.addTodo = function() {
    	$scope.todos.push({text:$scope.todoText, done:false});
    	$scope.todoText = '';
        };
        $scope.remaining = function() {
    	var count = 0;
    	angular.forEach($scope.todos, function(todo) {
    	    count += todo.done ? 0 : 1;
    	});
    	return count;
        };
        $scope.archive = function() {
    	var oldTodos = $scope.todos;
    	$scope.todos = [];
    	angular.forEach(oldTodos, function(todo) {
    	    if (!todo.done) $scope.todos.push(todo);
    	});
        };
        $scope.clearCompleted = function() {
    	$scope.todos = _.filter($scope.todos, function(todo) {
    	    return !todo.done;
    	})
        };
    }