よーぐるとのブログ

技術ネタを中心。私的なことを徒然と綴っていきます。

過労で腕を痛めた話と治した話 

突然ですが、腕を痛めました。。。 診断結果は疲労による上腕骨外側上顆炎と上腕骨内側上顆炎。文字からだとわかりずらいですが肘の周りです。通称テニス肘と言われるそうですね。

ソフトウェアエンジニアという仕事の性質上よくある話なのかもしれません。が、実際になってみると結構きつかったです。幸いなことに一ヶ月程度で良くなってきたので、ここでは腕を痛めるまでと痛めてから治すまでにやったことを書いていきます。

※ 前提として(そして会社の名誉のためにも)、いわゆる長時間労働が続いていたということはありませんでした。ごく普通に働いており、見た目上なんら問題のなさそうな生活をしていました。

発症一週間前

「なんか右腕がヒリヒリするなあ」というのがきっかけでした。普通にしている分には問題ないんだけど、仕事をしていると夕方〜夜にかけて肘の辺りに違和感が出てくる。なんとなくヒリヒリする。

特に心当たりもなかったのと、仕事ができないほどの痛みではなかったので、あまり気にせずいつもどおり仕事をし、いつもどおり生活をしていました。このくらいの痛みならそのうち消えるでしょ、という気分で。

そう、来週その痛みがさらに悪化するとも知らずに....(怖い話風)

翌週

腕に抱えている違和感が明確な痛みに変わり始めました。え、痛い。本当に痛い。 仕事でタイピングをしていると痛いし、Macbookトラックパッドをいじいじしているのも痛い。

肘の辺りだけ痛かったのが、手首のあたりも痛くなり、挙げ句の果てには指がつりそうになる始末。

当たり前のことなんですが腕が痛いというのはすごく不便で、仕事はもちろん私生活にも支障をきたしました。家でPC触ることができない、ゲームが遊べない、くらいならまだいいですが、何気ない動作が全て辛い。食器を洗うのがつらい、歯磨きがきつい。何もしてなくても痛いので何をする気にもなれない。利き腕だったので余計にそう感じたのかもしれません。

「これはまずい」と思ってお休みを取り、以前腱鞘炎になった知り合いが勧めてくれた手の専門外科へと行きました。

診断結果

お医者さんには「ジョウワンコツガイソクジョウカエン、ジョウワンコツナイソクジョウカエン。疲労だね。」と言われました。耳で聞いたときには何を言っているか全く変換できなかったのですが、漢字に直すと上腕骨外側上顆炎と上腕骨内側上顆炎。最初にも書きましたがいわゆるテニス肘だそうです。別にテニスなんてしないのになーと調べてたら「スマホ肘」「PC肘」という呼び方も見つけました。ある意味現代病の一種で、普段の生活で疲労が溜まって肘周りの筋肉が炎症を起こしている状態とのこと。

f:id:yoghurt1131:20190331222630j:plain:w500
痛めた箇所。僕の場合は外側だけでなく内側も痛めていた。

https://www.saiseikai.or.jp/medical/disease/lateral_humeral_epicondylitis/

肘の周りは手首や指につながる筋肉が集まっているため、ここを痛めるといろんな箇所に影響が出るのだとか。実際悪化したあとは手首や指、前腕全体がきしむような痛みを覚えました。インフルエンザにかかると関節が痛くなりますが、あの感覚に近いです。

治すためにやったこと

治すためにいくつかのことを行いました。

この中のどれが一番効いたとかは正直わからないです。全部やってみた結果良くなったのかもしれません。

もちろん、個人の経験ですのでやったことが完全に他の人に合うとは思いません。あくまで参考程度に。

1. 働き方を変える

腕を痛めたあと上長に相談する機会があったので、正直に話をして新規の開発などコーディングが増える作業を減らしてもらいました。 負荷をかけすぎない、ということに重点をおいて業務調整をしてもらい、主にコードレビューや運用周りのタスクをメインにこなすようになりました。

また、弊社はフレックス制度があるため通常の勤務より早めに上がることもできました。朝一番は問題ないけど、6〜7時間程度で腕の限界が来るので、チームメンバーと相談して仕事を調整しつつ、短めの勤務とさせてもらっていました。

2. 治療、リハビリ、ストレッチをする

病院からはロキソニン湿布を処方されてたのでそれを毎日上腕部分に貼っていました。

病院に勧められて超音波治療も行っていました。1回5〜10分程度で診療とは別で行ってもらえるので待つ必要がなかったのも嬉しかったです。週2〜3の頻度で通いました。

また、テニス肘に効きそうなストレッチも行いました。医者からはストレッチをするのは問題ないと言われていたので[*1]、「テニス肘 ストレッチ」で調べて出てきたものを試していました。

www.youtube.com 実際にやってみるとたしかに肘周りの筋肉が伸びている感じがする...

3. キーボードを変える

働き方とは別でもう一個、働く環境を変えました。具体的にはMacbookのキーボードが辛かったので自宅からキーボードを持ってきました。 Kinesis Freestyle 2 という左右分離式のキーボードです。

f:id:yoghurt1131:20190331220700j:plain:w500
kinesis-freestyle2
https://kinesis-ergo.com/shop/freestyle2-for-pc-us/

3ヶ月ほど前に肩こりの改善を目的に自宅用に購入し使っていたのですが、会社に持ってきて使うようになりました。左右が別れているので腕のポジションが自然なままタイピングができるのと、サポートキットによって手の角度を水平ではなく少し傾けた状態で使えるので、通常のノートPCをタイピングするより疲れにくいのが圧倒的なメリットです。

会社のPCゲーマーな同僚には「こんなキーボードで絶対にゲームしたくない」と酷評されましたが、コーディングをする分にはこちらの方が良いと思います。長時間デスクで作業をしたあとの腕から肩周りの疲れが違います。(だんだん宣伝ぽくなってきましたが)おすすめです。

追記: 効かなかったもの - サポーター

診断を受けたときに「どうすればいいでしょう?」と聞いたら「仕事をしないわけにもいかないだろうし、サポーターを付けるとかがいいかなあ」とお医者さんにぼやかれたんで肘周りのサポーターを購入しました。

が、これは僕にとってはあまり良くなかったと思います。たしかに仕事中の痛みは軽減できるんですが、痛みが軽減している分無理に働くことができてしまい、仕事が終わってサポーターを外したあとにすごく痛むということが何度かありました。ドーピングのような感じで自分には良くないなと思ったんで、何回か使ったあとはサポーター無しで生活し、痛くなってきたらきちんと休む、という方向に倒しました。

まとめ: 良くなってきた(気がする)

上記のような取り組みを並行して進めた結果、二週間程度で日常生活が送れるほど腕の痛みはやわらぎ、一ヶ月経った現在痛みはほとんどなくなりました。もちろん長時間コーディングをするなど負荷をかけるとやや違和感を感じる〜ヒリヒリする程度にはなってしまいますが、一番痛かったときと比較すると大きな改善です。

もともと身体が硬かったり医者からストレートネックだと言われたりと、疲労が溜まりやすい & 身体に出やすい体質なので、これからも無理をせず気をつけて働きたい(働きたくない)と思います。


*1:腱鞘炎など症状によっては「ストレッチをすることで悪化する」ケースもあるそうなので医者とよく相談をしたほうがいいです

Clean Architectureを読んだ話

「Clean Architecture 達人に学ぶソフトウェアの構造と設計 」を読んだので感想をば。

Clean Architecture 達人に学ぶソフトウェアの構造と設計 (アスキードワンゴ)

Clean Architecture 達人に学ぶソフトウェアの構造と設計 (アスキードワンゴ)

どういう本か

名前通りアーキテクチャに関する本ではあるが、この本の特徴は「良いアーキテクチャとはこういうものだ」というトップダウンな説明ではなく、「意識するべき原則は常に同じであり、それをどのように適用していくか」というボトムアップ方式でコアとなる考え方を丁寧に伝えているところだと思います。

どんな種類のシステムでもソフトウェアアーキテクチャのルールは同じ。ソフトウェアアーキテクチャのルールとは、プログラムの構成要素をどのように組み立てるかのルールである。構成要素は普遍的で変わらないのだから、それらを組み立てるルールもまた、普遍的で変わらないのである。

序文にこう書かれているように、本書前半ではSOLID原則に始まり、様々なソフトウェア設計の原則を丁寧に説明していきます。これらの原則は後半の本題であるコンポーネントアーキテクチャの話の中で具体例を交えながら何度も出てくるため、読者は基礎と応用の結びつき方が自然と理解でき、「なぜ」がすっと頭に入ってきます。

原則の説明→具体例の紹介→抽象化というサイクルが本書の中でうまく回されており、読んでいく中でエンジニアとして一段上の視野が拓けるようになると思います。

どういう人が読むとよいか

もちろんソフトウェアエンジニアリングに関わるいろんな人に読んでもらいたいですが、個人的にはプログラマとしてそれなりの経験があり、設計も含めて一からサービス開発にチャレンジしたことのある人が自身の経験と照らし合わせて読むと大きな気付きが得られるのではと思います。もちろんそれだけではなく、SOLID原則やデザインパターンアーキテクチャの原則に関する基本的な知識はあるものの、実践でうまく活かせないというモヤモヤを抱えている人にとっても非常にためになるような本だと思います。

また、ビジネスロジックの扱いなどドメイン駆動開発(DDD)の考え方について理解するにも良い本でした。いわゆるDDD本はそれはそれで素晴らしいのですが、挫折してしまった人、理想だと割り切って読んでしまった人にとってこの本は理想と現実を繋いでくれることでしょう。

個人的に良かった点

僕がこの本を読んだタイミングは、中長期かけて取り組んでいた新サービスの立ち上げが終わったタイミングでした。自分の中で色んな葛藤や反省を抱えていた時期だったので、それをうまく言語化し次に活かしていくのに非常に刺さりました。

印象に残った文章

一番印象に残ったのは以下の文章です。

そもそもソフトウェアアーキテクトはプログラマである。(中略)ソフトウェアアーキテクトは最高のプログラマであり、継続してプログラミングの仕事を引き受けながら、生産性を最大化する設計にチームを導いていく。(15章アーキテクチャとは? より)

これは非常に大事で、プログラマだろうとアーキテクトだろうと忘れてはいけないことだと思います。そもそも良いアーキテクチャを作るのは自己満足のためではなく、プロダクトの保守性を向上させ、ビジネス価値を高めていくためです。プロダクトの保守、改善が容易というのは既存のコードに手を入れやすいことと同義で、具体的な実装の積み重ねが良いアーキテクチャを構成していきます。上記の文章はなんとなく自分が思い描いていたアーキテクト像と近かったのでとても響きました。

現実に立ち向かう方法を教えてくれる

冒頭にも書いたようにこの本では非常に多様な具体例をもって目指すべき道筋を示してくれます。また、全体を通して「プロジェクトの現状やステータスによって最適解は常に変わる」というスタンスで書かれているため理論の押し付け感がなく、自分たちの現場と照らし合わせて読みやすいというのも本書の特徴です。多くのエンジニアに自分が持っている武器と、その使い方を教えてくれる本だと思います。

おまけ

付録としてついている「アーキテクチャ考古学」は、OSもファイルシステムもなかった時代からエンジニアとして活動してきた筆者の自著伝です。こちらも読み物としてとても面白いのでぜひ読んでみてください。

2019年の抱負

今更ですが明けましておめでとうございます! 2018年の簡単な振り返りと2019年の抱負です。

2018年

2018年は社会人になって2年目の年になりました。去年から都内でエンジニアとして働いていますが、大きいプロジェクトにアサインされ設計からリリースまでに携われたのは非常に学びが多かったです。また、DevOpsやコンテナ技術に興味を持って、勉強したり遊んだりとたくさんの新しいものに触れた年でもありました。

一方で仕事に比重がよってしまいそれ以外のことが徐々に疎かになってしまっていったのを感じたので、今年はこうやって文章に残しておきたいと思います!

2019年

去年もおおよそ同じだったのですが、2019年大事にすることは健康、技術、英語の3つです。

健康は生活習慣を改善すること、運動を継続することの2点。生活を豊かにしたいです。去年前半に自分の睡眠の質が悪いことに気がついて生活習慣の見直しを測り、一時期非常に良い朝型生活が送れていたんですが気がついたら戻っちゃっていました。生活習慣を変えることで非常にコンディションがよくなる感覚はあったのでなんとか維持していきたいです。

技術についてはインプットとアウトプットの量を増やすことを目指します。技術は日々進歩しているので、最前線との距離感や自分が経験したことの概念化、言語化をしっかりとしていきます。

英語はリーディングとリスニングを重点的に取り組みます。ここ二年間で英語でニュースを読んだり技術カンファレンスの講演を聞いたりするのは抵抗なくなってきたので、それがよりスムーズに速くできるよう慣れていきたいと思います。

AlexaスキルとAWS Lambda, Slackを使って我が家の買いもの管理を便利にした話

やったこと

ライフハックです。Alexaに買うものを伝えるとSlackの買い物チャンネルに伝えたものが追加されるシステムを作りました。 仕組みとしてはシンプルで、Alexaに「〇〇を追加して」と伝えると、Alexaのスキル、AWS Lambdaの関数が呼び出されSlackのチャンネルに〇〇がポストされるというものです。

f:id:yoghurt1131:20181223150520p:plain

買い物管理

同居人と生活をするにあたって、買いもの、特に洗剤やシャンプーなど日用品類の買い物管理をどうしようかという話題がありました。「XXを買っておいて」「〇〇はもう買ったんだっけ?」というコミュニケーションは仕事などで疲れているときにはコストが高いですし、買い忘れが発生して喧嘩する、みたいなのも避けたい。なんとかいい感じに解決したい、という思いを二人共モヤモヤ抱えていました。

ちなみに「Alexaで全部注文しちゃえばいいじゃん」というのはなしで。そういう案もあったのですが、お互い家にいない時間が多くマンションに宅配ボックスもないためボツとなりました。あくまでどちらかが買い物をしなきゃいけないという状況に対する取り組みが今回の記事です。

この課題を解決すべく、まずはSlackに買い物チャンネルを作り必要なものはそこにポストして管理する、というルールを決めました。やることは簡単で

  1. 買わなきゃいけないものがあったらその名前を書いてポストする
  2. ポストされたものを買ったら「済」スタンプをつける

というものです。 ルールを決めたことで「誰が何をいつ買ったか」が明確になり、お互い暮らしていく中で非常にストレスのない買いもの生活が送れるようになりました。

f:id:yoghurt1131:20181224165411p:plain

Alexaを用いた買うもの投稿機能

上記のルールで買いものの管理は便利になったものの、別の課題が出てきました。 それは「買わなきゃいけないものは日常生活をしている中でふと現れる」ということです。食器洗い、洗濯、掃除といった家事に取り組んでいる最中に「あれ買わなきゃ」と思っても、やっている最中にスマホを取り出してSlackに投稿するのは面倒だし(そもそも家事の途中は手が空いていないことの方が多い)、一段落ついた頃には忘れてしまうことだってあります。

そう、「Slackに買うものを投稿する」の自体がそもそもハードルが高いのです。

そこで、Alexaが代わりにSlackへの投稿をしてくれる簡単なアプリケーションを作成することにしました。声で伝えるのであれば手が埋まっていてもできるし、思いついたその場で登録しやすいですよね。 今回はAWS Lambdaと簡単なAlexaスキルを作成してVoice UIでの買い物登録を実現させました。

システム構成

最初に載せた図の再掲ですが。

f:id:yoghurt1131:20181223150520p:plain

ユーザがスキルを呼び出し、Alexaに向かって話しかけます。その発話から必要な情報(今回は「買うもの」)が取り出され、AWS Lambdaに登録した関数が呼び出されます。関数の実態はSlack APIを叩くだけのNode JSスクリプトです。Alexaから受け取った情報をもとにSlackの特定チャンネルにボットで投稿を行います。

Alexaスキルの作成

AlexaスキルはAmazon Alexaの開発者登録を行い、Alexa Developer Consoleから簡単に作成することができます。 アプリではインテントと呼ばれる発話意図を登録することで、特定のアクションを受け付けられるようになります。インテントには発話のパターンが登録でき、各発話パターンの中に「スロット」と呼ばれる枠を用意することで、「{りんご}を追加して」「{みかん}を追加して」といった発話によって変化する単語を入れることが可能になります。

f:id:yoghurt1131:20181224235329p:plain:w250

今回は「買うもの」に当たる部分を{things}という形でスロットにしました。また、買うものを追加する時に言うであろういくつかの発話パターンを登録します。

f:id:yoghurt1131:20181223151010p:plain
alexadevconsole

AWS Lambdaへの関数登録

AWS Lambdaには上述したように、Alexaスキルから連携される情報を受け取りSlackに投稿する関数を登録します。デフォルトのインテントや、定義したインテントを受け取るHandlerを定義することで、Alexaから連携される発話に対する処理を記述できます。

下記に買いものの処理をする部分のコードを載せます。let things = this.event.request.intent.slots[SLOT_NAME].value;の箇所が、実際にAlexaスキルから連携されているスロットを受け取っているところです。

SDKのバージョンが古いため、最新バージョンだとこの書き方では動かないかもしれません。

// Slack Webhook URL
const WEBHOOK_URI = process.env.WEBHOOK_URI;
// Alexaから受け取るスロット
const SLOT_NAME = 'things';
const handlers = {
    ...
    // 買いものリスト追加処理
    'ToBuyIntent': function () {
      let func = this;
      // thingsスロット(=買うもの)を取得
      let things = this.event.request.intent.slots[SLOT_NAME].value;
      // Alexaの発話
      const speechOutput = things + 'ですね。わかりました。';
      func.response.speak(speechOutput);
      func.emit(':responseReady');

      // Slackに投稿するためのパラメータ
      let options = {
        method: 'POST',
        uri: WEBHOOK_URI,
        body: {
          text: things
        },
        json: true,
        headers: {
          'content-type': 'application/json',
        }
      };
      // Slackに投稿
      requestPromise(options).then(function(body) {
      }).catch(function(err) {
        console.log(err);
        func.response.speak('エラーが発生しました');
        func.emit(':responseReady');
      });
    },
    ...
};

exports.handler = function (event, context, callback) {
    const alexa = Alexa.handler(event, context, callback);
    alexa.APP_ID = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

苦戦した部分

あとはAlexaスキルのエンドポイントにAWS Lambdaの関数を登録し、Alexaで呼び出す際のスキル名を設定すれば完成となります。

が、ここで一つ罠がありました。 買い物リストなんていうありふれた機能はすでにAlexaにデフォルトスキルとして実装されているのです。

f:id:yoghurt1131:20181224164032p:plain:w200f:id:yoghurt1131:20181224164036p:plain:w200

最初、スキル名を「買い物リスト」としいたんですが、そうすると自作したスキルではなくデフォルトのスキルが呼び出されてしまうのです。これでは使えない。。。

スキル名は「アレクサ、<今日の星占い(スキル名)>を開いて双子座の運勢を占って」のようにAlexaへの指示の中に織り交ぜて使われます。そのため、発話にいれて違和感のあるスキル名や極端に長いスキル名などは設定したくありません。 デフォルトのスキルが呼び出されず、かつAlexaへの呼びかけとして不自然じゃないスキル名を検討した結果、以下のようになりました。

f:id:yoghurt1131:20181224164658p:plain

これだ!!

「Alexa、スラックを開いてゴミ袋を追加して」

f:id:yoghurt1131:20181224165147p:plain:w200

きっちりとSlackに投稿されています。これならまあ及第点でしょう。やったね。

まとめ

AlexaスキルとAWS Lambdaを使って買いもの管理を便利にしてみました。 やはり音声による入力というのは手入力よりはるかにストレスがないらしく、もはやスマホでSlackを開いて買うものを投稿するという場面はほとんど見なくなりました。こういったライフハックを積み重ねて生活をどんどん便利にしていきたいですね。

資料とか

GitHub - IshinFUKUOKA/waht-i-buy: Alexa skill's application posting message to slack channel

スライド - 20180711-alexa-yoghurt1131.pdf - Google ドライブ

Knife-ZeroによるRaspberry Pi3の構成管理

お題

Raspberry Piの構成管理をChefで行いたい。 細かい環境構築やセットアップなどをコード化したい。

環境

・OS: Mac OSX Yosemite ・Chef: 14.5. ・ラズパイ: Raspberry Pi 3 ・ラズパイOS: Raspbian GNU/Linux 9 (stretch)

Knife Zeroのインストール

Knife-Zeroのサイトに記載されている方法に従ってknife zeroコマンドをインストール Installation · Knife-Zero

以下のようにknife zerと打ってUsageが出てくればOK。

$ knife zero
FATAL: Cannot find subcommand for: 'zero'
Available zero subcommands: (for details, knife SUB-COMMAND --help)

** ZERO COMMANDS **
knife zero apply QUERY (options)
knife zero bootstrap [SSH_USER@]FQDN (options)
knife zero chef_client QUERY (options) | It's same as converge
knife zero converge QUERY (options)
knife zero diagnose # show configuration from file

Rasbbian用の設定ファイル用意

bootstrap時には-tオプションで実行したいテンプレートを指摘できる。 以下のサイトにRaspbian用のテンプレートがおいてあったのでそれを利用する。

GitHub - dayne/raspbian_bootstrap: chef bootstrap for raspberry pi

bootstrapの実行

$ knife zero bootstrap -t raspbian-jessie-gems.erb --ssh-user pi --sudo 192.168.11.15
(中略)
ERROR:  Error installing chef:
  ohai requires Ruby version >= 2.4.
Starting the first Chef Client run...
sh: 112: chef-client: not found

よくみると先程ダウンロードしたテンプレート内に以下の記述が。

RUBY_VER=2.3.3

2.4.0に書き換えてあげる

RUBY_VER=2.4.0

別のエラー OpenSSL::OpenSSLError: password must be at least 4 bytes

knife.rbに以下を書き加えてあげる

ssl_verify_mode  :verify_none

bootstrapまではなんとか成功した。

mavenプロジェクトでフォーマッターを使う

技術Tipsです。

概要としてはmavenを利用しているspring bootプロジェクトにおいてコードフォーマットを行う方法、及びそれをIDE(Eclipse, IntelliJ)に適用する方法になります。

背景

コードフォーマッターが必要になった経緯です。

最近は仕事でSpring Bootを使ってWebアプリの開発をしています。Javaの開発であればEclipseIntelliJなど優秀なIDEがあるため、コマンド一発でフォーマットしてくれます。便利ですよね。

なので、個別にフォーマッターを入れる必要は開発時点ではなかったのですが、CI/CD時にフォーマットチェックを入れたいという話になり、Githubなどに上げたあとの環境でフォーマットをかける必要が出てきました。

今回はmavenでプロジェクトを作っていたためmavenでのフォーマッターの導入の話、IDEと共通のフォーマッターを使用する方法などを書きます。

使用するフォーマッター

formatter-maven-pluginというのを利用します。が、公式らしきサイトのUsageを試していてもうまくいかず、少し自分で調べる必要がありました。

利用方法

公式サイトの方ではpom.xmlに書くpluginと、実行方法は以下のようになっていました

pom.xml

<project ...>
    ...
    <plugins>
      <plugin>
        <groupId>net.revelc.code.formatter</groupId>
        <artifactId>formatter-maven-plugin</artifactId>
        <version>2.0.2-SNAPSHOT</version>
      </plugin>
    </plugins>
    ...
</project>

実行方法

mvn java-formatter:format

しかしこの方法ではフォーマットはおろか、プラグインの実行すらされません。 というかそもそもmvn java-formatter:formatで実行しているjava-formatterプラグインのprefixから検索しているのにプラグインのartifactIdがformatter-maven-pluginだし。。。

色々調べたり試したりしたところ、下記のプラグイン指定と実行方法で行けました。

pom.xml

<project ...>
    ...
    <plugins>
      <plugin>
        <groupId>net.revelc.code.formatter</groupId>
        <artifactId>formatter-maven-plugin</artifactId>
        <version>2.0.1</version>
      </plugin>
    </plugins>
    ...
</project>

実行方法

mvn formatter:format -Dconfigfile=formatter.xml

formatter.xmlは下で説明しますが、フォーマット用の設定ファイルです。

フォーマットチェックとフォーマット

対象ファイル

確認のため、あえてフォーマットが崩れているファイルを用意しました。main関数を1行で記述しています。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MavenFormatterDemoApplication{
    public static void main(String[] args){ SpringApplication.run(MavenFormatterDemoApplication.class, args);}
}

設定ファイルの取得

上で述べた設定用のxmlファイルですが、今回はSpring bootで標準的に使われているらしいxmlファイルを落としてきて入れました。formatter-maven-pluginではeclipseのフォーマット用のxmlが設定ファイルとして使え、検索するといくつかヒットします。

github.com

設定の例

下記は今回使用した設定ファイルの一例です。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="12">
<profile kind="CodeFormatterProfile" name="Spring Boot Java Conventions" version="12">
...
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
...
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="90"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
...
</profile>
</profiles>

設定項目はたくさんありますが、<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="90"/>(改行する文字数)のように比較的理解しやすいものが多いです。

とはいえ直接編集するのは骨が折れるので、カスタマイズするなら後述するEclipseの設定を用いてxmlを生成するのがよいでしょう。

フォーマットチェックとフォーマット

設定したxmlファイルのフォーマットに従っているかどうかをチェックするには以下のコマンドを実行します。

mvn formatter:validate -Dconfigfile=formatter.xml

先程のようにフォーマットが崩れているファイルがプロジェクトに存在すると、mavenがエラーを吐きます。

> ~/maven-formatter-demo> mvn formatter:validate -Dconfigfile=formatter.xml
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building maven-formatter-demo 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- formatter-maven-plugin:2.0.1:validate (default-cli) @ maven-formatter-demo ---
[INFO] Using 'UTF-8' encoding to format source files.
[INFO] Number of files to be formatted: 2
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.130 s
[INFO] Finished at: 2017-10-01T19:57:48+09:00
[INFO] Final Memory: 13M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal net.revelc.code.formatter:formatter-maven-plugin:2.0.1:validate (default-cli) on project maven-formatter-demo: File '~/maven-formatter-demo/src/main/java/com/yoghurt1131/mavenformatterdemo/MavenFormatterDemoApplication.java' format doesn't match! -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

では、これをフォーマットしていきます。先程のmvnコマンドでvalidateとしていた箇所をformatに変えるだけです。

 mvn formatter:format -Dconfigfile=formatter.xml
> ~/mave-formatter-demo> mvn formatter:format -Dconfigfile=formatter.xml
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building mave-formatter-demo 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- formatter-maven-plugin:2.0.1:format (default-cli) @ mave-formatter-demo ---
[INFO] Using 'UTF-8' encoding to format source files.
[INFO] Number of files to be formatted: 2
[INFO] Successfully formatted:          1 file(s)
[INFO] Fail to format:                  0 file(s)
[INFO] Skipped:                         1 file(s)
[INFO] Read only skipped:               0 file(s)
[INFO] Approximate time taken:          0s
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.129 s
[INFO] Finished at: 2017-10-01T20:00:00+09:00
[INFO] Final Memory: 14M/79M
[INFO] ------------------------------------------------------------------------

フォーマット成功ファイルの数、失敗したファイルの数、スキップされた(すでにフォーマットされていた)ファイルの数などがでます。

実際に確認してみると、きちんとフォーマットがされています。

フォーマット前

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MavenFormatterDemoApplication{
    public static void main(String[] args){ SpringApplication.run(MavenFormatterDemoApplication.class, args);}
}

フォーマット後

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MavenFormatterDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(MavenFormatterDemoApplication.class, args);
    }
}

IDEでの利用

作成したフォーマッターを使えば、PaaS環境などのIDEが無い場所でもフォーマットチェックやフォーマットが行えるようになりました。とはいえ、IDEのフォーマッターとmavenで使用するフォーマッターが違ってしまうと、開発環境でかけたフォーマットがpush先で通らないといった事故が起きる可能性があります。

ここでは、作成したフォーマッターを各IDE(eclipse, IntelliJ)に読み込む方法を書きます。

eclipseでの利用

Eclipse->Preferences(設定)->Java->Code Style->Formatterに設定項目があります。

f:id:yoghurt1131:20171001202002p:plain:w500

ここでxmlファイルをimportすることができます。

また、Newから独自のフォーマット規約を作成することができます。これはxmlファイルとしてExportすることができるので、既存のがイマイチで自分でフォーマッターを作りたいという場合はこれを利用してオリジナルのフォーマッターを作成するのがいいかと思います。

IntelliJでの利用

IntelliJでも利用方法はほとんど同じです。

IntelliJ->Preferences->Editor->Code Style->JavaからImport Schemeをすることで設定ファイルを導入することができます。

注意点としては、IntelliJにはIntelliJ独自のコードフォーマット(IntelliJ IDE code style XML)があることです。

Eclipseとの互換性はあるため、Eclipseで作ったxmlファイルをIntelliJで利用することはできますが、逆はできません。開発時にIntelliJの設定でフォーマッターを作成した場合はそのままmavenで使用することができないのでご注意ください。

リンク・参考

エンジニアのための時間管理術を読んだ

オライリー出版のエンジニアのための時間管理術を読みました。ここではその感想と、最近感じてる時間の使い方について書こうと思います。

store.shopping.yahoo.co.jp

エンジニアのための時間管理術

原題はTime Management for System Administratorsなので厳密には「システム管理者のための時間管理術」なのだけれど、多くのエンジニアにはもちろん、非エンジニアである人でも参考になるような良書です。

この本が魅力的なのは、著者の語り口によるところが大きいです。この本は著者の経験談や悪戦苦闘の歴史に基づいて書かれており、あくまで「自分はこれでうまく行った」という書き方で押し付けがましさがありません。

また、ユーモア豊かに書かれており翻訳もとてもチャーミング。例えば4章にはこのような文章が出てきます。

SAは、一般に頭の切れる人々です。あなたは賢いし、筆者も賢いのです。皆が賢いのです。

・・・最高じゃないですか?ところどころこんな感じで進んでいくので、読んでいてすごく楽しかったです。

内容をかいつまんで

この本は、タイムマネジメントの考え方や、その実践方法についてこと細かに書かれています。 とはいえそれを全て書くのは不可能なので、印象に残った部分をいくつか挙げていきます。

TODOは全て外部記憶に頼ろう

(他の仕事も多くはそうですが)エンジニアは頭脳労働です。仕事の際には仕事に集中できる環境を整えておく必要があります。 この本では集中して仕事に取り組むため、何か気になることや、やることがある場合は全て外部記憶(TODOリストやその他の記録ツール)に書き出すことを勧めています。人間は忘れる生き物です。「明日Aさんに電話する」でも「今日牛乳を買いに行く」でも、何かを覚えておくことは多かれ少なかれ頭脳に負荷がかかります。それらを外部に書き出すことで、より眼の前の仕事に集中できるとしています。

決断の回数を減らそう

この本では、上で書いた「やらなきゃいけないことは外部記憶に頼る」以外に「決断の回数を減らす」ことについてもその重要性が主張されています。 本当かどうかわかりませんが、かのアルバート・アインシュタインは同じスーツを7着持っていたと言われています。日常の些末な(人によっては違うかもしれませんが)決断に労力を割かないことで、自分の能力を全て学問に捧げることができたと。

我々の脳の容量は限られています。この本では、本当に大事なところで能力を発揮するために、日常における決断の回数を減らすべきであると述べられています。

何回もやる作業はルーチン(習慣)化する

では、実際に決断の回数を減らすにはどうすればいいか。著者はそれに対する回答はルーチン(習慣)を作成することであると述べています。習慣化しているということは、考えずにその行動が行えるということに近いです。 ルーチンとは「一度だけ考え、何度も実行するための手段である」と定義されています。これはプログラマならよく理解できることだと思います。プログラムは、一度書いたら何度でも実行できるものなのですから。

僕自信が最近作成したルーチンの例を紹介します。それは、「財布や家の鍵などの外出時に持ち歩くものは全て、自室の小箱にしまう」というものです。これを定める以前は、財布や家の鍵の場所が帰宅したときによって変わってしまい、家を出る時に鍵がない、財布がない、といった事態は多々ありました。そこで、「財布や定期券、家の鍵、イヤフォンなどの外出時に持ち歩くものは自室の小箱に全て置く。帰宅したらまずそこにそれらのアイテムをしまう」というのを習慣づけました。これによって、出かけるときに必要なものを探す必要はなくなり、結果として時間の節約になっています。

時間を上手く使うために

社会人になって、日常の自由時間がかなり少なくなったと感じます。しかし一方で、生活サイクルが定まることによってより日常の行動が最適化され、空きの有意義な時間が増えたような気持ちにもなっています。 学生の頃は、生活サイクルなんてかけらもありませんでした。目が覚めたときに起きる、眠くなったら寝る、研究が忙しければキリがつくまでやる。全てを自分の裁量でさばけるという意味では自由でしたが、「いつお昼を食べよう」「いつ帰ろう」といった些細な考え事が常に頭のなかに合ったと思います。そういったことを考えているだけで時間がすぎ、貴重な時間を無駄に消費していました。 働くようになってご飯を食べる時間、寝る時間、起きる時間はほぼ固定になりました。これによって自分の空き時間を自分がやりたいことに純粋に使えるようになったと感じています。別にアインシュタインになりたいわけではないですが、学ぶにしても遊ぶにしても「時間を無駄にしていない」という感覚は非常に気持のいいものです。 これからも良い習慣を作っていきたいなと思った次第です。