#javapuzzlers以前日経ソフトウエア2013年9月号〜2015年3月号にて至極のJavaクイズという連載を、持ち回りにて執筆していました。Puzzlersを参考にしています。Tokyoなどのイベントでも過去に同様のセッションを行なっていました。このJavaパズラーの問題ができるまでを数年ぶりに振り返ってみます。問題ができるまで良問といえるのは、問題を正解できなかったとしても、なるほどと言える教訓が得られるものです。そのような問題は間違えたとしてもスッキリと気持ちよく教訓として読み進めることができます。Puzzlersにはそのような良問がたくさん掲載されています。逆に良問と言いづらいのは重箱の隅をつついたような違いを問題として表現したものです。そのような問題は、教訓が得られるというよりは「ふーん、そうなの。」ぐらいの感想しか得られないものです。知識だけを問う問題もあまり良問とは言えないでしょう。javax.timeのようなパッケージは問題を作りやすいのですが、インタフェースやクラス、メソッドもかなり多いので知識を問う問題になりがちです。出題する際には解説などで工夫が必要になります。出題範囲について、あまり一般的でないライブラリの仕様などを出題するのはためらわれます。SE標準ライブラリで、日常よく利用するであろう基本ライブラリです。ラムダ式など比較的新しい言語仕様も良いでしょう。パッケージで言えばjava.lang、java.utilあたりで出題できると良問の期待が高まります。java.io、java.nio、java.sqlなども範囲として良いですが直接これらのパッケージを利用するよりはフレームワークなどに処理を任せることが多いでしょう。出題する場合には多めに注釈を入れるなどで調整を進めます。個人的には問題を考えるには教訓から考えていきます。SEバージョンで変更された振る舞いや、FindBugsやCheckstyleなどのルールもよく参考にしていました。nullの扱いやequalsの振る舞い、評価順などにまつわる問題は作りやすい印象があります。Puzzlersでだいたいカバーされているので新規性のあるテーマを探すのはなかなか骨の折れる作業です。選択肢ができるまで回答は4択程度のなかから選ぶことになっています。4択でなければならない訳ではありませんが、2択だと大抵の場合回答があからさますぎるので、4択程度になるよう調整します。equalsと==の違いについて出題しようとした場合、ぱっと思いつく選択肢のパターンは次のようなものです。選択肢を考える上で、4つ目が「その他」となるのはできれば避けたいものです。ボツとなりやすいのは「その他」で全く別の例外が発生するようなケースです。equalsと==の違いから教訓を説明したいのに、別の例外が発生するというようでは出題意図がよくわからなくなってしまいます。時間の都合で妥協することもありますが、なるべくこだわりたい部分です。しても詰まってしまった場合は、あえて出題意図を変えて選択肢をすべて例外発生にしてみるというのも面白いでしょう。下記のような選択肢ではどうでしょうか。NullPointerExceptionが発生するStackOverflowErrorが発生するConcurrentModificationExceptionが発生するIndexOutOfBoundsExceptionが発生するIndexOutOfBoundsExceptionやConcurrentModificationExceptionがあるのでjava.util.Listなどに関連する問題と教訓にすれば面白そうです。StackOverflowErrorと迷うように再帰処理をいれてみるなどいろいろ試せそうです。このように最初equalsと==の違いを出題しようと考えていたものが、別の教訓を説明するような問題にどんどん変わっていくこともあります。問題のコードはequalsと==の違いを説明しようとしてそうなのに、実はjava.util.Listの振る舞いについての教訓だった。なれば読みがいがありそうです。問題コードができるまで問題コードができるまでにも紆余曲折があります。日経ソフトウエアのように紙面であれば40行程度あっても入ることがあるのですが、やはりあまり長いとテンポが悪くなるのでなるべく短く済ませたいものです。セミナーなどでプレゼンテーションとして出題する際にはスライドに選択肢まで入れた上で一画面に収まり、会場後ろの方にも見えるようフォントサイズはできるだけ大きくする必要があります。スライドテンプレートやレイアウトによりますが15行程度までがおおよその限度となります。このためあまり冗長な初期化処理はできませんし、教訓のコアとなる出題部分以外に必要となるクラス・メソッド定義については最低限に抑える必要があります。読みやすさを考慮しある程度改行も入れていく必要があり、インデントも不自然にならないよう工夫する必要があります。Java言語仕様などの制限を考えると実際に使えるのは20行程度と考える必要があります。どれだけ削っても収まりきらない場合は残念ながらボツ案となります。テーマを絞り込むなど教訓を考えるところまで手戻りとなります。掛け合い部分ができるまでイベントなどでプレゼンテーションする場合は2人のプレゼンターがあらかじめ出題者と模擬回答者として役割をきめておきます。SEバージョンに依存する場合や新仕様などをテーマにしている場合、模擬回答者がうまく出題者に質問するような格好で補足していきます。追加で模擬回答者は「これはひっかけですね」などと、いくつかのトリックを説明しつつ、あまり教訓の核心に触れないように打ち合わせておきます。理想的にはこのように掛け合いで説明できるようなトリックが教訓以外でも含まれていたほうが良いのですが、あまりいろいろ高望みすると締め切りがどんどん厳しくなります。教訓ができるまで問題と選択肢ができあがえれば作業のほとんどは完成です。あとは教訓をわかりやすく説明するのですが、そうは言っても紙面に収まるようわかりやすく手短に伝えようとするとなかなか難しいものです。タイトルができるまでタイトルはなるべく教訓や選択肢の特徴を表現しつつも、ヒントになりすぎないよう微妙な調整が必要です。教訓を知った上でニヤリとできるようなタイトルとなれば大成功といっていいと思います。問題を作ってみる数年ぶりに問題を作ってみました。}}プログラムを実行すると何が出力されるでしょうか。(小文字のオー)が何文字あるか合計を計算するプログラムです。isFutureやcountOにはあまり不審なところはありませんが、いかにも怪しいのは次の行です。Olympics")Cityクラスのインスタンスに文字列を連結しています。Olympics”が連結されます。CityクラスはtoStringをオーバーライドしていないためObject#toStringが呼び出されCity@2ed94a8bのようなクラス名とハッシュ値を使った文字列表現になります。(小文字のオー)は含まれませんから合計値は0となるというわけです。教訓toStringの実装は忘れずに。...問題のレビューさてではこのパズラー問題をレビューしてみましょう。先ほど怪しいとご紹介したこの行。Olympics”と追加するというのはかなり不自然です。できればこの不自然さをうまく消したいところです。APIを利用しているのにあまり特徴を活かせていないにのも改善したいところです。選択肢についても同様でうまく迷いを誘導できていないように見えます。Angelsで1ずつカウントされればそうなりますがちょっと考えにくい選択肢です。Angelsでどちらもoがカウントされたと考えるなら選択される可能性があります。「6」」はすべての都市名についてoがカウントされたと考えるなら選択される可能性があります(isFutureがうまく働かなかった)。レビューというサイクルを何度も繰り返すことでより良い問題が作成できます。本当にちゃんとした教訓となるような良問を作るのはなかなか難しいものです。(特に締め切りがある場合には。#jekyllこのサイトをJekyllに移行したことでメンテナンスはかなり簡単になりました。Pagesのホスティングを使っているのでJekyllで構築したサイトも自動生成してくれます。Pagesで利用できるJekyllプラグインには制限があり、利用したかったタグごとのページ生成プラグインや、ミニマイズのプラグインは利用できませんでした。Pages側でHTML生成してもらうのではなく、あらかじめ手元でHTMLを生成することにしました。Docker環境HTML生成のためにプラグインなどを導入済みのDocker環境を作っておきます。"/srv/jekyll/source"]なお、ディレクトリ構成は次のようなイメージです。必要に応じて読み替えてください。表示確認用にjekyllをserveで起動するには最後の行を下記のように変えたイメージを準備しておきます。"/srv/jekyll/source"]設定ファイル_config.ymlは共通のものと、表示確認用のもので分離しています。これはMinifierは実行にそれなりに時間がかかるプラグインを外したり、デバッグ用にURLを切り替えるなどしています。i7)で実行してMinifierがない場合と比べ1分程度の追加時間が必要となります。タグの有効化jekyll-taggingプラグインを利用します。プラグインの設定とjekyll-taggingへの設定は下記のようなイメージです。jekyll/taggingとスラッシュで区切ります。他のプラグインはだいたいjekyll-paginateのようにハイフン区切りなのでそれに倣ってしまいがちです。prettyあとはjekyll-taggingの説明にあるように_plugins/ext.rbへプラグイン指定追加、_layouts/tag_page.htmlを作成して完成です。BusinessではAPIを通じてチーム内のユーザーについてファイル・フォルダ一覧を取得したり、更新することができます。これは、マルウェア対策システムがファイルを検査・隔離するために利用したり、ワークフローや生産性向上ツールが自動的にファイルを仕分けするといった用途を想定していると考えられます。便利な一方、非常に強力な権限となるため取り扱い上の注意は管理者パスワードなどと同様厳重に管理する必要があることは言うまでもありません。access権限を用います。この権限を使うアプリケーションを作成する手順などは該当記事をご参照ください。チームメンバーのファイルやフォルダを操作するには大きく分けて二種類の方法があります。管理者として実行チームメンバーの代理として実行する方法では、指定したユーザーが所有しているファイルやフォルダ、参加している共有フォルダ・チームフォルダなどへアクセスすることができます。管理者として実行する場合にはチーム内すべてのファイル・フォルダへアクセスすることができます。使い分けとして、たとえばワークフローアプリケーションなどで承認されたドキュメントを所定フォルダに移動するといった用途であれば、承認者の権限で承認者が所有フォルダに移動するといった場合には代理での実行が適切でしょう。マルウェアのスキャンや監査といったチーム全体を対象としたい場合には管理者としての実行が適切でしょう。チームメンバーの代理として実行チームメンバーの代理として実行する場合にはまずteams/members/listでアカウント一覧を取得します。チームメンバーIDを追加すると、その該当アカウントとして処理が行われます。files/list_folderを代理として実行する場合には次のように呼び出します。'{"path":""}'チーム管理者として実行チーム管理者として実行する場合にはDropbox-API-Select-Userヘッダの代わりにDropbox-API-Select-Adminヘッダを用います。チームメンバーIDにはチーム管理者のメンバーIDを指定します。Dropbox-API-Select-Adminヘッダを用いた場合、チーム内のネームスペースすべてにアクセス可能となりますがAPIによって二つのモードがあり可視範囲が変わります。Teamと呼ばれるモードです。参照系APIが該当します。Team)と記載されています。Teamモードではメンバーのプライベートファイルを含むすべてのファイルにアクセスすることができます。Adminと呼ばれるモードです。更新系APIが該当します。Admin)と記載されています。Adminモードではメンバーのプライベートファイルにはアクセスできません。チーム管理者として実行する際の流れは大まかに次のようになると思います。各ネームスペースについて処理まずチームメンバーの代理として実行する場合と同様にteams/members/listでアカウント一覧を取得しチーム管理者のメンバーIDを取得します。アプリケーション用に専用のアカウントが用意できるようであればアプリケーションにあらかじめメンバーIDを設定しておくといった運用も可能でしょう。次にチームフォルダ一覧やネームスペース一覧を取得します。チームフォルダ一覧はteam/team_folder/list、ネームスペース一覧はteam/namespaces/listで取得できます。ワークフロー処理などチームフォルダ内で処理が完結する場合はteam/team_folder/list、チーム全体のファイルを監査するといった処理の場合はネームスペース一覧から処理を始めるとよいでしょう。処理したいチームフォルダやネームスペースのネームスペースIDを取得します。チームフォルダIDはそのままネームスペースIDとして利用できます。team/team_folder/listのレスポンスが次のような場合、ネームスペースIDは123456789となります。ネームスペースとパスの表現にてご紹介いたしました。こちらでご紹介したとおり、ns:ネームスペースID/パスといった形式でパス指定すれば通常のファイル一覧取得と同じようにファイル一覧を取得することができます。123456789)のトップフォルダからファイル一覧を取得するには次のように実行します。