読者です 読者をやめる 読者になる 読者になる

ホワイトプログラマー

40歳からSEを辞めてプログラマになりました

QnA Makerでナレッジベースを切り替える方法

MicrosoftがプレビューリリースしたQnA Makerは簡単にAIを採用したFAQシステムが作成できる。 サンプル作りました的な情報を挙げてくれるサイトはいくつか存在する。例えば以下。

www.microsoft.com

ただ、実際に進めていて、サービス(ナレッジベース)の切り替えはプログラムからどうすればよいんだろうと少し悩んだのでメモしておく。今回はc#を利用。

1.Azureのbot serviceからQnA Makerを利用する場合、以下のようなサンプルプログラムが用意される。

    public BasicQnAMakerDialog() : base(

        new QnAMakerService(
            new QnAMakerAttribute(
                
                    Utils.GetAppSetting("QnASubscriptionKey"),
                    Utils.GetAppSetting("QnAKnowledgebaseId")
                )
            )
        )

2.QnAで新しくサービスを作成した場合はソースコードを修正するのではなく、AzurePortalからApplication Settingsを使用して変更する。

f:id:sabburo:20170118063926p:plain

3.アプリ設定にプログラムから利用できるキーが登録されているので、その値を修正する。 今回はQnAKnowledgebaseIdとQnASubscriptionKeyとなる。

f:id:sabburo:20170118064601p:plain

なお、登録するための値はQnA Makerログイン後の、画面上部のMy servicesから取得できる。 QnAKnowledgebaseIdとQnASubscriptionKeyの関係は以下の通り。 f:id:sabburo:20170118065035p:plain

以上

github→SlackへのWebhookを解析する

 背景

Javaを使って開発したSlack用のBotを運用している。
githubからメンションをすると特定のチャンネルに送信されるようになっているが、当社のSlackIDはgithubでは使用できないアンダースコアを採用しており、IDが不一致となるため、Slackではメンションとして有効にならない。

 対応

Githubからwebhookで送信される投稿を監視して、@Firsrtname-Lastnameの形式の文字列を @Firsrtname_Lastnameに書き換えて再投稿するBotを開発する。

監視して、再投稿すること自体は大した問題ではないが、最初にうまく投稿データが取得できずに困った。

 Githubから投稿されるjson

通常の投稿ではattachmentsは存在せず、オブジェクトのトップレベルの要素のtextに値が格納される。 しかし、Githubからポストされる値は、textが空欄なのである。 そこで、attachmentsキーに設定されているオブジェクト配列からデータを取得するように変更する。

{
    "attachments":[
        {
            "color":"C4E8B4",
            "mrkdwn_in":["text","pretext"],
            "pretext":"[aaa-bbb\/SandBox] New comment by ccc-ddd pull request<http:\/\/172.16.100.100\/aaa-bbb\/SandBox\/pull\/9#issuecomment-73|#9: hoge>",
            "text":"test @aaa-bbb",
            "id":1,
            "fallback":"[aaa-bbb\/SandBox] New comment by ccc-ddd pull request <http:\/\/172.16.100.100\/aaa-bbb\/SandBox\/pull\/9#issuecomment-73|#9: hoge>"
        }
        ],
    "subtype" :"bot_message",
    "source_team":"RRRTTTGG",
    "channel":"CWSADJ98K",
    "text":""
    ,"team":"T768HJUN",
    "type":"message",
    "user_team":"T768HJUN",
    "bot_id":"UJHDJK14",
    "ts":"1483007034.000140"
}

 変更後のjsonのパース部分のJavaソース

もともと、当該アプリではwssで取得したjsonのパースに org.json.JSONObjectライブラリを使用している。
attachementsオブジェクトは上記の通り、オブジェクト配列で回答されているが、このライブラリにはgetメソッドしか存在しない。
修正を始めた最初はどうやって、オブジェクト配列を取得するのか悩んだが、getメソッドをattachementsに対して実行するとJSONArray型を回答するということがわかった。
JSONArrayはArrayListなので、あとは取得したJSONArrayから内部のJSONObjectにアクセスし、textを取得することができた。  

念のため以下にソースを貼り付けておく

//bot(github)からのデータ取得
//attachmentsで取得するとJSONArrayが取得できる。その中にはJSONObejctが入っている。
//このJSONObjectからtextを取得するればよい。
JSONArray attachmentsArray = (JSONArray)obj.get("attachments");
JSONObject attachment = (JSONObject) attachmentsArray.get(0);      
//以下のtextはほかと異なり、Attachmentsの中のtextとなる
String text = (String) attachment.get("text");

この部分はパース前のjson次第で、上記ロジックがエラーになりかねないので業務でこのようなものを書く場合は、API仕様を決めて例外を許さないか、パースの際にチェックを行っておくことが大事かと思う。

Arquillianを使用したJavaEE7のユニットテスト(サンプル実装付き)

JavaEE

JavaEE7での単体テストと課題

Strutsなどのフレームワークにおいてはフレームワークと業務ロジックの実装が密結合であったため、単体テストが難しいと言われていた。それに比べてJavaEE7はCDI自体がPOJOであるため単体テストは容易であると喧伝されている。
果たしてそうなのか。たしかに、メソッドの単体テストやUtilをテストするにはJUnitとMockitがあればある程度記述できる。しかし、Injectされたオブジェクトを全てMockで書き始めると段々と、単体テストの意義が小さくなってくることに気づく。
大きなプロジェクトでは発注者は単体テストのコードや仕様をレビューせず、カバレッジしか気にしないことが多い。これもあって、SIerが開発するJavaEEのテストコードは動くコードができてから、それに対してMockだらけのテストコードを書くだけという結果が多く見られる。
最初からそのプロジェクトにおいて意味のあるテストコードが何なのかが議論できていないことからこの問題が発生する。

テストの対象を切り分ける

JavaEE7でもBeanValidationのテストはEnclosedやTheoryなどを使うことで、十分にテストの実施が可能である。ただ、悩ましいのはテスト対象のオブジェクトがInjectしているオブジェクトに対してどこまで実施するかだ。これはプロジェクトで事前に決めることが大事となる。

切り分けの範囲

何をまず決めるかというと、JavaEE7のコンテナ上で動かすテストとそれ以外である。 MVCS with DAOのよくあるパターンでアプリケーションを作成した場合に、コンテナを使用したテストであるArquillianをどのように利用するかを図解してみた。

f:id:sabburo:20161226114746j:plain

1.Serviceより下の層をArquillianを使用してテストする
    JUnit + mockit + Arquillian
2.Controllerより下の層をArquillianを使用してテストする
    JUnit + mockit + Arquillian + Drone
3.Controllerより下の層をArquillianを使用してテストする(ViewScopedも含める)
    JUnit + mockit + Arquillian + Drone + warp

サンプル実装として、1のサンプル実装を以下に紹介する。 Arquillianを使用する際は、@Deploymentの部分をどのように実装するかがポイントになるがサンプルでは、クラス、xhtml、pomで定義した依存ライブラリの全てをパッケージングする定義としている。

Arquillianを使用したUnitTestコード

参考URL

ArquillianでViewScopedのCDI管理BeanだけInjectできない - Challenge Java EE !

Arquillian用ArchiveへクラスとMaven Dependencyを楽に追加する - Kohei Nozaki's blog

Functional Testing using Drone and Graphene · Arquillian Guides

java - deploymentURL not injected into integration test with Arquillian Drone - Stack Overflow

HttpClient4.5をプロキシ配下で使用するサンプル

Proxy問題

多くの企業ではProxyサーバ経由でインターネットにアクセスする。これはセキュリティ上とても大事なことであるが、開発者にとっては極めて面倒な問題を引き起こす。Eclipse,Maven,Nugetなどの開発環境からアクセスや、開発したアプリケーションからの外部アクセスだ。

HttpClientを使用したProxy対処方法

今回、近くの人が困っていたのでとりあえずサンプルを書いてみた。 たしかに、Webでは古いバージョンのHttpClientの実装や、ProxyはあってもID/PWDを必要とする場合の記述方法がなかったので、何かの役に立てばと思い記載する。

利用ライブラリ:httpclient4.5.2

pom.xml

pom.xmlには以下を記述するだけで、HttpCompnentsに必要なライブラリは自動で落とされる。

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>

ソースコード

HttpClient4.5を使用してProxy配下からアクセスする

関数型言語としてのJavaScript(3)

JavaScript

実践的なJavaScriptを関数型を使ってを書いてみる

関数とは

以下の投稿でも記載したが最近のJavaScriptは関数を使用することが当たり前となってきている。
このことが他言語から乗り換えた時に「JavaScriptは多分簡単だからなんとなるだろう」というサーバーサイドプログラマの淡い期待を打ち砕く。 (これに気づいたときにはプロジェクトは炎上しているはず)
関数型言語としてのJavaScript(2) - サブローグ

できあいのWebフロントエンドを軽く修正するだけならば、コピー&ペーストでなんとかなるかもしれないが、「サーバーから欲しいデータで表示されない」などデータ加工の一手間が必要な場合、途端にハードルが高くなる。

関数型とはデータの受け渡しである

JavaScriptで実際に処理ロジックを記述する殆どはデータの変換である。もちろん最終的には画面に表示するための様々なテクニックが必要となるが、そこはそれぞれ有名なフレームワーク様がやってくれる。
SIerに必要なことは、そのフレームワークにデータを適切な形で渡すことだ。

データを適切な形で渡すためにはデータ構造を正しく理解する必要があるが、JavaScriptにはクラスという概念が基本的にはない(ECMAScript6以前は)のである。しかし、Javaなどのオブジェクト指向言語でサーバサイドを開発したシステムエンジニアは、クラスで解決しようとする。シンタックスとしてないものを作るということは、ソースコードのわかりづらさや、障害対応の困難さを生み出す。
さらに言うと、そういった特定クラスの処理を書くような分岐処理やループ文は汎用性がとても低い。(ほぼないとも言える)

JavaScriptではオブジェクト指向は一旦横において考えたほうが、物事をシンプルにできる。

データはオブジェクト配列でもいいし、ただの配列でもいい。それは最終的に画面表示に使うフレームワークに合わせればいい。
そういうデータ処理に最適なJavaScriptライブラリを紹介する。

Underscore.jsだ。
Underscore.js

Underscore.jsを使って記述してみた。

gistにサンプルをアップしているが、これはNode.js上で動作検証を行っている。
内部処理としては以下となる。

1.DB(postgresql)接続する
2.テーブルから全件を取得する(SQL)
3.データの形式は変わらないように特定の列からデータを取得する(JS)
4.データの形式は変わらないように特定の条件でフィルターを行う(JS)
5.グループ毎の件数を出力するため、特定の条件でカテゴリ化する(JS)
6.画面表示に必要な形式に変換する(JS)
7.特定の値でソートした結果で画面表示を行う(JS)

上記の処理を行ってもプログラムには一切ループ文は存在しない。また、それぞれの処理は関数化されているが、業務処理は入っていない。一部特定のカラムが入っているが、これもカリー化などの対応により外に追い出すことができる。
このように関数化するということは、具体的な業務処理を追い出して、処理を高度に抽象化する ということと同義である。抽象化された関数はプログラムのどのような場所でも利用可能となる。

是非とも、Underscore.jsを使って関数型プログラミングを行い、ロジックの抽象化ということを体験してほしい。

google adsenseにログインできない

とってもつまづきました。google adsense

私はgoogleのアカウントを2つもっており、これまで別のgoogleアカウントでgoogle adsenseを使用していました。ところが最近ブログを本格的に行うにあたり、前のGoogleアカウントの整理をしたかったので、新しいアカウントでadsenseを申請することにしました。

以前のadsenseを解約して、新しいアカウントで申請して、無事に以下のメールをもらいました。

Google AdSense によるお申し込み内容の審査が完了しました

そして、adsenseで自分のBlogに広告を貼ろうと思って、adsenseにログインしようとしたのですが、全くできない。。。

ログイン画面が出て、正しくログインできているはずが何度もログイン画面が表示される。

Cookieか?とおもって、スマホでやっても全く同じ事象。

かなり調べました。そして、最終的に以下のリンクからGoogleへ直接問い合わせできることがわかりました。

https://support.google.com/adsense/contact/cant_log_in?hl=ja&rd=2

問い合わせ後、30分ぐらいでメールがきました。内容はもう一回やってみろ的な内容です。

やってみた。。。

できた。ログインできた。ログインできたよ。

ということでハマった方は上記のリンクに問い合わせしてみてください。

ThinkStation(E31)にグラフィックカードを追加してゲーム方面を強化する

ThinkStation(E31)でゲームをしたくなったので、グラフィックカードを追加しようと思い立ち、成功したのでメモしておく。

ThinkStationE31の特徴

Lenovoが販売したデスクトップワークステーションSFFと呼ばれるサイズで、一般的に企業で使われているようなデスクトップサイズ。

ロープロファイルの拡張しか用意されていない。ただし、販売時のオプションでCADソフト向けにグラフィックカードの追加オプションがあるので、グラフィックカードがさせる状態にはあると考える。

購入したグラフィックカード

セットアップ

1.開封する

2.最初は普通のブラケットがささっているので、LowProfile用に変更する。

ここで、ドライバーとペンチが必要になるので準備しておくこと。

3.以下のような感じでE31に差し込む。 f:id:sabburo:20161223154126j:plain

4.Dsubをすぐしたに付けると干渉するので、以下のように一つあけてはめ込む。

f:id:sabburo:20161223154101j:plain

サマリ

難しいことは何一つなく、15分ほどで終了した。

最初にE31の中もあけずに、グラフィックカードを購入したがすんなりといってよかった。もともと、SSDに換装しているので動作に不満は全くなかったが、HDMIでつなぐことができるようになったのはとてもよかった。

これで楽しむゲームをこれから探そう。