ふるてつのぶろぐ

福岡在住のエンジニアです。

写真提供:福岡市

Udemy講座つくりのすすめ - バージョンアップに対応する

今日すること

こんにちは😊ふるてつです。

f:id:tetsufuru:20220129224434p:plain:w300

新しいシリーズを開始しました。
昨年 Udemy の講座を公開したので、そのお話をすこしずつしていきたいと思います。
最初の1回目はフレームワークのバージョンアップに講座を対応させる方法についてお話しします。

1. 公開した講座はこちら

わたしが公開したのは Angular の講座です。
こちらになります。
www.udemy.com

2. ポイント

バージョンアップの難しいポイントを挙げてみます。
① 旧バージョンを学習している受講生がいる中で新バージョンがリリースされる
② 新バージョンがリリースされた後なにもアナウンスしないと新規受講生は新バージョンを使い始める
③ 動作を確認できるまで新バージョンを使ってほしくはない
④ 動画は同時に2つのバージョンには対応できない
⑤すぐに動画はバージョンアップできない(わたしは2~3週間かかる)

そこでわたしは新バージョンのリリース後、新規の受講生にはしばらく旧バージョンを使うようにアナウンスします。
そしてその間に動作を確認して動画を修正して新バージョンに対応させます。
ここまでおわったら旧バージョンを使うようにしていたアナウンスを解除します。
これでこのあとから新規受講生は新バージョンを自然と使うようになります。
そして旧バージョンを学習中の受講生にはバージョンアップの手順動画を用意します。

では具体的にどういったことをしているか下に書いてみます。

3. 事前の作業

まずは事前の準備作業です。
Angular のバージョンが上がる時期が近づいてきたら、上がる前にレクチャーを一つ増やします。
テキストのレクチャーで以下のような感じです。
Angular のプロジェクトを作るときのコマンドをバージョン指定して流すようにアナウンスします。
f:id:tetsufuru:20220129025747p:plain

具体的には今回はV13に上がるタイミングなので、ひとつ前のV12を指定してインストールするようにアナウンスします。

// アナウンス前は最新バージョンが入るコマンド
npm install -g @angular/cli

// 上のコマンドをV12指定するようにアナウンス
npm install -g @angular/cli@12

そして受講生がV12を使っている間に、V13の動作確認をして修正があれば資料や動画を修正します。
わたしはある程度余裕をもってバージョンアップの1ヶ月後くらいまでに講座の内容を最新化しています。

4. 今回の作業

a. 自分の環境をバージョンアップ

まずは自分の環境でバージョンを上下てみます。
Anglar の場合はコマンドでバージョンを上げます。
詳しくはこちらの過去ログを参照ください。
tetsufuru.hatenablog.com

b. 自分の環境でソースを修正

今回 Angular Material 絡みで見た目が変わりました。
そこでソースを一部修正しました。
詳しくは同じく上記のわたしの過去ブログを参照ください。👉こちら

c. バージョンアップ作業動画の作成

バージョンアップの手順がわかったところでV12で学習中の受講生向けにバージョンアップ方法を教える動画を作成します。
あとソースも修正箇所があったのでそのやり方も動画にしました。

d. 動画の修正

バージョンアップ作業動画を作る以外に、すでに公開中の動画の内容も修正します。
①これまでに動画で公開したコードの内容をわたしはファイルに残しています。
まずはそのファイルをGrep検索して修正が必要な箇所を探し出します。
②あと話す内容もファイルに残していてそこでも修正が必要な個所を探し出します。

下はわたしが使っている動画編集ソフトの画面で一つのレクチャー分になります。
赤枠で囲んだところが動画を修正した部分で、黄色の枠が話す内容(音声)を修正した部分です。
こういった動画/音声の修正は今回10本ありました。
f:id:tetsufuru:20220129233444p:plain

e. 動画と添付資料を差替え

動画や添付資料の修正が全部終わったところで夜中に一気に差替えます。
Udemyのプラットフォームには一気に差替える機能がないので、ひとつひとつ順々に手作業で行います。
あと新規で作ったバージョンアップ作業動画も公開します。

5. 終わりの作業

a. 事前作業で追加していたレクチャーを「非公開」にする

動画や添付資料をすべて差替えたら最新バージョンで動かして良くなります。
最初に書いた「2. 事前の作業」で追加していたテキストのレクチャーはもう必要ないので非公開にします。
削除はしません、Angularのバージョンアップは年2回あるので、また次のバージョンアップで使うために非公開にするだけです。

これで最新バージョンをインストールするコマンドを受講生はそのまま実行するようになります!

// アナウンス前の最新バージョンをインストールするコマンド
npm install -g @angular/cli

b. 受講生に展開

「お知らせ」で受講生に展開します。
下は Udemy のお知らせ登録画面です、こういった感じで受講生に展開しています。
f:id:tetsufuru:20220130001922p:plain

今日の感想


今回は講座のバージョンアップ作業について、どんなことをしたかを書いてみました。
結構手間がかかってます!😊
Angular は年に2回メジャーバージョンアップがあるのでそのたびに今回のような作業をおこないます。
とはいえ書籍のように古いバージョンのまま放っておくにもいきません。
講座がいつも新鮮な状態を保つようにバージョンアップにはこれからも対応していきたいと思います。

ではでは👋

Angular13でWebアプリを作ろう - V13にバージョンアップ - ng update

今日すること

明けましておめでとうございます、ふるてつです。

今回は Angular のお話です。
昨年11月に Angular がバージョン 13 にあがりました。

今回のバージョンアップ作業はいつもより難しかったです。
というのも--forceオプションを使わないとバージョンを上げられませんでした。

新しいバージョンがリリースされた直後はよくあるのですが、
普通は1カ月くらい待つとオプションなしでバージョンアップできるようになります。
しかし今回は待っても変化がなく結局--forceオプションを使いました。
今回はその内容を書いてみようと思います。

1. 準備作業

バージョンアップ前にまずいまの環境に入っているライブラリを最新化します。
下のnodeのコマンドを実行します。
イメージとしてはpackage.jsonに定義してある範囲内でライブラリのマイナーバージョンを上げる感じです。

npm update

わたしの環境では多言語化ngx-translateやそのテスト用モジュールのngx-translate-testingなどを使っていて、それらが古いと警告がでてバージョンアップの邪魔になります。
そのために事前にあらかじめ最新化しておきます。
ただし上記のコマンドだと他のライブラリまで一気にマイナーバージョンがあがります。
そこはわたしは思い切って全部上げています。

2. アップデートコマンドの確認(ng update)

では次に Angular の CLIng updateコマンドを実行します。

ng update

すると下記のリストがでてきます。こちらが具体的なバージョンアップのコマンドです。
今回は cdk 、cli、core と material のほぼ全部のバージョンアップが必要です。
それとは別に、angular-eslint/schematics もバージョンアップします。

ng update
Using package manager: 'npm'
Collecting installed dependencies...
Found 51 dependencies.
    We analyzed your package.json, there are some packages to update:

      Name                                    Version                  Command to update      
     -------------------------------------------------------------------------------------    
      @angular-eslint/schematics              12.3.1 -> 13.0.1         ng update @angular-eslint/schematics
      @angular/cdk                            12.1.1 -> 13.1.2         ng update @angular/cdk
      @angular/cli                            12.1.1 -> 13.1.3         ng update @angular/cli
      @angular/core                           12.1.1 -> 13.1.2         ng update @angular/core
      @angular/material                       12.1.1 -> 13.1.2         ng update @angular/material

実際にバージョンアップするコマンドですが、上のリストの最後右端に書いてあります。

今回は上記のうちどのコマンドを実行しても失敗して--forceオプションを追加してコマンドを実行しなおせと表示されます。 ちなみに下が cdk のコマンドを流した時の警告です。

ng update @angular/cdk
Using package manager: 'npm'
Collecting installed dependencies...
Found 51 dependencies.
Fetching dependency metadata from registry...
                  Package "@angular-devkit/build-angular" has an incompatible peer dependency to "typescript" (requires "~4.2.3 || ~4.3.2", would install "4.5.4").
                  Package "@angular/material" has an incompatible peer dependency to "@angular/cdk" (requires "12.1.1", would install "13.1.2").
                  Package "ngx-translate-testing" has an incompatible peer dependency to "@angular/common" (requires "^10.0.0-rc.0 || >=10.0.0 <12.0.0" (extended), would install "13.1.2").
                  Package "ngx-translate-testing" has an incompatible peer dependency to "@angular/core" (requires "^10.0.0-rc.0 || >=10.0.0 <12.0.0" (extended), would install "13.1.2").
× Migration failed: Incompatible peer dependencies found.
Peer dependency warnings when installing dependencies means that those dependencies might not work correctly together.
You can use the '--force' option to ignore incompatible peer dependencies and instead address these warnings later.

3. バージョンアップ実施

a. コマンドをつなげてアップデート

今回はどの順番でもうまくいかなかったので、すべてのコマンドをつなげて、
さらに--forceオプションもつけて一気にバージョンアップします。
結局コマンドは下記になります。

ng update @angular/core @angular/cli @angular/cdk @angular/material @angular-eslint/schematics --force

では実行します。

ng update @angular/core @angular/cli @angular/cdk @angular/material @angular-eslint/schematics --force
Using package manager: 'npm'
Collecting installed dependencies...
Found 51 dependencies.
Fetching dependency metadata from registry...
    Updating package.json with dependency @angular-devkit/build-angular @ "13.1.3" (was "12.1.1")...
    Updating package.json with dependency @angular-eslint/builder @ "13.0.1" (was "12.3.1")...
    Updating package.json with dependency @angular-eslint/eslint-plugin @ "13.0.1" (was "12.3.1")...
    Updating package.json with dependency @angular-eslint/eslint-plugin-template @ "13.0.1" (was "12.3.1")...    
    Updating package.json with dependency @angular-eslint/schematics @ "13.0.1" (was "12.3.1")...
    Updating package.json with dependency @angular-eslint/template-parser @ "13.0.1" (was "12.3.1")...
    Updating package.json with dependency @angular/cli @ "13.1.3" (was "12.1.1")...
    Updating package.json with dependency @angular/compiler-cli @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency @angular/language-service @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency typescript @ "4.5.4" (was "4.3.5")...
    Updating package.json with dependency @angular/animations @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency @angular/cdk @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency @angular/common @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency @angular/compiler @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency @angular/core @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency @angular/forms @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency @angular/material @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency @angular/platform-browser @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency @angular/platform-browser-dynamic @ "13.1.2" (was "12.1.1")...
    Updating package.json with dependency @angular/router @ "13.1.2" (was "12.1.1")...
  UPDATE package.json (2267 bytes)
✔ Packages successfully installed.
** Executing migrations of package '@angular-eslint/schematics' **

> Updates @angular-eslint to v13.
  UPDATE package.json (2265 bytes)
✔ Packages installed successfully.
  Migration completed.

** Executing migrations of package '@angular/cli' **

> Remove polyfills required only for Internet Explorer which is no longer supported.
  UPDATE src/polyfills.ts (2393 bytes)
  Migration completed.

> Remove no longer valid Angular schematic options from `angular.json`.
  Migration completed.

> Remove deprecated options from 'angular.json' that are no longer present in v13.
  Migration completed.

> Updating '.gitignore' to include '.angular/cache'.
  UPDATE .gitignore (693 bytes)
  Migration completed.

> Update library projects to be published in partial mode and removed deprecated options from ng-packagr configuration.
  Migration completed.

** Executing migrations of package '@angular/cdk' **

> Updates the Angular CDK to v13.
    
      ✓  Updated Angular CDK to version 13

  Migration completed.

** Executing migrations of package '@angular/core' **

> Migrates `[routerLink]=""` in templates to `[routerLink]="[]"` because these links are likely intended to route to the current page with updated fragment/query params.
  Migration completed.

> In Angular version 13, the `teardown` flag in `TestBed` will be enabled by default.
  This migration automatically opts out existing apps from the new teardown behavior.
  UPDATE src/test.ts (817 bytes)
  Migration completed.

> As of Angular version 13, `entryComponents` are no longer necessary.
  UPDATE src/app/core/core.module.ts (2111 bytes)
  Migration completed.

** Executing migrations of package '@angular/material' **

> Updates Angular Material to v13.

      ✓  Updated Angular Material to version 13

  Migration completed.

はい、無事にバージョンが13にあがりました😊

b, グローバルの CLI をバージョンアップ

あとは最後にグローバルの CLI をバージョンアップします。
コマンドは下記です、わたしはいつもこの3点セットを流しています。
①現在のCLIを削除して、②キャッシュをクリア、③最新のCLIをインストールします。
②はよくネットで見かけるので実行しています。

npm uninstall -g @angular/cli
npm cache verify
npm install -g @angular/cli@latest

c, グローバルの CLI のバージョン確認

下記コマンドでインストールしたCLIのバージョンを確認します。

ng version

実行結果はこちらです。

ng version

     _                      _                 ____ _     ___ 
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | | 
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | | 
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 13.1.3
Node: 16.13.0
Package Manager: npm 8.1.0
OS: win32 x64

Angular: 13.1.2
... animations, cdk, common, compiler, compiler-cli, core, forms
... language-service, material, platform-browser
... platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1301.3
@angular-devkit/build-angular   13.1.3
@angular-devkit/core            12.1.1
@angular-devkit/schematics      12.1.1
@angular/cli                    13.1.3
@schematics/angular             12.1.1
rxjs                            6.6.7
typescript                      4.5.4

はい、こちらもバージョンが13にあがりました😊

4. ソースの修正点

わたしの環境では今回 Anglar Material でソースを修正する必要がありました。
入力必須に設定しているインプットのプレースホルダーの右側に * マークが表示されるようになりました。
そもそもわたしの環境では必須項目の左側に手動で * マークを表示していたので、 左右両方に表示されるようになりました、下の画像のような感じです。
(左の青枠がもともと設定していた * マークで、右の赤枠が今回表示されるようになった方)
これを見た時すこし笑いました! 面白い状況ですね。
f:id:tetsufuru:20220116001306p:plain:w500

結局どのように修正したかというと
今回表示されるようになった * マークは、TypeScript側の ReactiveForms の必須バリデーションで自動判定しているようなので、 新しい方をそのまま残すことにして、もともと手動で設定していた分を削除しました。
その方が今後メンテしやすいかと思います。

今日の感想


このV13へのバージョンアップはわたし的にこれまでで一番難しかったように思います。
--forceオプションを数年ぶりに使いました。
Angularをお使いの皆様は今回どのようにバージョンアップされたのかが気になるところです。

余談になりますがわたしは Udemy の Angular コースを公開していて、コース受講生の方々にも同じようなバージョンアップ作業をお願いしたところです。
ちょっと難しい作業なのではたして作業していただけるかどうか?
作業していただけたとしても無事バージョンアップできるだとろうか?と心配する今日この頃です。

では本年もよろしくお願いします。

新人向けのプログラミング教育・ SPA /フロントエンド学習に Udemy で Angular の動画講座を作りました(新人研修、独習、SPA 未経験のエンジニアさん、SPA になじめないデザイナーさん、そして初学者のかた向けです)

Udemy 講座のご紹介

こんにちは、ふるてつです
今月 Udemy で初心者向けの Angular 講座を開設しました
その紹介をさせてください!!

✨講座の紹介動画

こちらは講座の紹介動画です
youtu.be

✨講座のリンク

こちらは講座へのリンクです
www.udemy.com

✨講座の概要

講座の概要を説明します
こちらは「Angular」を初めて学ぶ方向けのコースです
通販サイトの商品管理システムを制作しながら、Angularでの開発を学びます
ある程度の業務経験やプログラミングの経験があると良いですが、 細かい部分まで解説しますのでプログラミング初心者の方でも学べるようになっています

👨対象者さん

  • Angularで実際に業務をしたい方
  • 書籍などで学習したが覚えられない方
  • jQueryなどからAngularに移行したい方
  • 実務的なUnitテスト・E2Eテストの勘所を抑えたい方

👩具体的にどんな方

具体的にはこちらのような方を想定しています。

  • IT業界の新人さん
  • SPA未経験のエンジニアさん
  • SPAになかなかなじめないデザイナーさん(オブジェクト指向色を極力減らしたので学びやすいと思います)
  • プログラミング初学者の方

✨特徴

このコースでは実際の開発業務に沿って、開発からテスト工程までを実施します。

  1. 実際の業務にそった手順で html、css をテンプレートに取り込むところからはじめて、TypeScriptやRxJS、Angular Materialを使い実際に画面を製造します
  2. サインイン画面を含む6画面を作ります。画面数を多くこなすことで学習が定着しやすくなります
  3. Webサービスは別途準備したSpring bootを使いRxJSを使って接続します
  4. その他には、カスタムバリデーション、カスタムパイプ、カスタムディレクティブなどのテクニックを使います
  5. 各画面の製造と同時にJasmine+Karmaを使ったUnitテストも追加します
  6. 終盤のレクチャーではメディアクエリを使ったPCとスマホ両方に適したResponsive対応も行います
  7. 最後にCypress+cypress-image-snapshotを使ってE2Eテストを行います

👍メリット

  • Udemy講座なので動画をつかって独力で学べます
  • 専門学校のコースでまなぶようなボリュームを低価格で学べます
  • Angular Cli や Unitテスト、E2E テストなど SPA のフルスタックな機能をフル活用します

🐛デメリット

  • すでに他のSPAを学習している方にとっては逆に負担になるかもしれません
  • 講座が長いので早く学びたい方には向かないかもしれません(早く学びたい方は学習する画面を減らしたり、Unitテストをスキップしてください)
  • html、css 自体の学習にはむきません(講師自体にデザイナー経験はないので)

😊講座を作ってみての感想

今回はじめて Udemy の講座を作ったのですが思ったよりも長い期間かかりました。
どちらかというとプログラムよりも動画を録画し始めてからが思考錯誤で長くかかりました。
例えば最初は座って声を録音していたのですが、声に元気がないらしく元気感を出すためにわざと立って録音するように途中から変えました。
あとは声が響かないようにマイクのまわりを段ボールで囲んだりもしました。
録音はわたしの部屋でしましたがノイズが入らないように録音中は夏でもエアコンや扇風機はつけないようにして、そして汗だくになるので裸同然の格好で録音していました。しかも立って。
わたし自身おはなしは上手ではないのですが、こういった感じで頑張っていい動画を作りましたので、ぜひご覧いただければと思います。

まとめ


今日はわたしが作った Udemy 講座の紹介をさせていただきました
もしこの講座をご覧になって、内容が良さそうだと思われたらぜひとも応援ください!!

よろしくお願いいたします。

いまだにJava 8 備忘録 - SpotBugsの使い方

今日すること

こんにちはふるてつです。
きょうはSpotBugsのおはなしをします。
f:id:tetsufuru:20210531211456p:plain:w300
SpotBugsJavaの静的解析ツールでCheckstyleとおなじくよく見かけるツールです。
SpotBugsプラグインには開発画面上で動かすSpotBugs Eclipse pluginGradleなどのタスクで動かすSpotBugs Gradle pluginの2種類があります。
まずは開発画面上で動かすSpotBugs Eclipse pluginを説明します。

1. SpotBugs Eclipse plugin の設定

1 - 1. SpotBugs Eclipse plugin のインストール

インストールはEclipse marketplaceを使います。
Eclipse のメニューから「ヘルプ」-「Eclipseマーケットプレイス」を選びます。
そして「Eclipseマーケットプレイス」の画面で「SpotBugs Eclipse plugin」などのキーワードで検索してインストールします。
f:id:tetsufuru:20210601001050p:plain

※ここで注意点ですが、Pleiades のオールインワンなどはすでにビルトインでSpotBugs Eclipse pluginが入っていると思います。
お使いの環境にSpotBugs Eclipse pluginが入っているかは設定画面から確認できます。
Eclipse のメニューから「ウィンドウ」-「設定」を選び、設定画面の左側メニュー欄で「Java」をクリックします。
Java」のサブメニューの中に「SpotBugs」が表示されていればインストール済です。
f:id:tetsufuru:20210601003800p:plain
インストールされているSpotBugsのバージョンを確認しておきます。
「SpotBugs」の設定画面の3番目のタブ(プラグインおよびその他の設定)画面で確認できます。
わたしの環境では4.2.0になっています、あとで Gradle 側の設定を書くときに参考にするのでおぼえておきます。
f:id:tetsufuru:20210601003925p:plain

1 - 2. 「分析力」などの設定

次にSpotBugs Eclipse pluginの設定を行います
設定できる項目はざっとみて4項目あります。

  • 「分析力」
  • 「報告する最小ランク」
  • 「レポートする最低の信頼度」
  • 「報告(可視)バグ・カテゴリー」

a「分析力」

分析力ですがSpotBugsのドキュメントを確認します
下記になります、こちらの「分析力」によってチェックする内容が変わります。
f:id:tetsufuru:20210610224257p:plain 参考:分析力 — spotbugs 4.2.3 ドキュメント

表の右端の列 max が一番多くの項目をチェックするのでそちらを選択したいと思います
(ちなみにデフォルトの「分析力」は右端から2番目の more の列になります)
Eclipse では「最大」、「最小」、「デフォルト」を選択できますが、 maxに相当する「最大」を選んでおきます。

b「報告する最小ランク」

「報告する最小ランク」は高くするほど軽微なものまで報告されます
ずべて確認したいのでスライダーで 20 にまで上げておきます。

c「レポートする最低の信頼度」

わかりずらい項目ですが、まずここでいう「信頼度」はバグの可能性と思うといいです
「信頼度」が高いとバグである可能性が高くて、低いとバグではないかもしれないという感じです
そして「レポートする最低の信頼度」ですが high を設定するとバグの確立が高いものしかレポートされません
バグでなさそうなものまでレポートしてほしい場合は、low を設定します、わたしは low にします。

d「報告(可視)バグ・カテゴリー」

報告するカテゴリーが選択できます、とりあえず全部チェックONにしました。

f:id:tetsufuru:20210601153929p:plain
まとめるとわたしの設定は上記のようになります

1 - 3. 除外設定

わたしはとくに除外設定は行っていませんが「SpotBugs」の設定画面の2番目のタブ(フィルター・ファイル)で設定できると思います
除外用のxmlファイルを選択できるようです f:id:tetsufuru:20210601155019p:plain

xmlファイルの記入例はこちらにあります、ご参考までに。
f:id:tetsufuru:20210601155335p:plain
参考:フィルタファイル — spotbugs 4.2.3 ドキュメント

2. SpotBugs Gradle plugin の設定

2 - 1. SpotBugs Gradle plugin のインストール

ではGradleのタスクで動かす方のSpotBugsについて説明します
これまでにセクション1で説明したのは Eclipse でリアルタイムに動かすプラグインで、これから説明するのはそれとは別物と思ってください。
こちらはリアルタイムではなくGradlebuildコマンドを実行したときにタスク実行されてソースをチェックします。
ビルドをせずチェックのみをおこないたい場合はcheckコマンドで単独で実行できます。

Gradleの設定は Gradle のサイトを参考にします、下記です。
f:id:tetsufuru:20210603001644p:plain 参考:Gradle - Plugin: com.github.spotbugs

最新の書き方とレガシーな書き方が書いてあります、わたしの場合はGradleのマルチプロジェクトにしていて、 親プロジェクトの中で両方の書き方を使っています。

わたしの build.gradle の内容
関係ない項目をだいぶ省略してますがわたしはこのような感じで書いています。

buildscript {
    ext {
        spotbugsVersion = '4.7.1'
        spotbugsToolVersion = '4.2.0'
    }
}

plugins {
    id "com.github.spotbugs" version "${spotbugsVersion}" // ←これは SpotBugs Gradle plugin のバージョン
}

subprojects {
    apply plugin: 'com.github.spotbugs'

    spotbugs {
        toolVersion = "${spotbugsToolVersion}" // ←これはSpotBugs自体のバージョン
        includeFilter = rootProject.file('config/spotbugs/spotbugs-include-filter.xml')
        spotbugsMain {
            reports {
                html {
                    enabled = true
                    stylesheet = 'fancy-hist.xsl'
                }
            }
        }
    }
}
project(':prj-sub') {}

project(':prj-main') {
    dependencies {
        implementation project(':prj-sub')
    }
}
  • plugins{} について
    まずは plugins の中で SpotBugs を使うよう宣言しておきます
    このバージョンは Gradle plugin のバージョンを設定します。
  • subprojects{} について
    そして子プロジェクトの中の設定は subprojects{} の中で行います
    apply plugin と書いて、その下の spotbugs{} の中で細かい設定をおこないます
  • spotbugs{} について
    toolVersion はSpotBugs自体のバージョンを選択します
    わたしは画面側の Eclipse plugin と同じバージョンにしたいので最初のセクションでしらべておいた 4.2.0 にします
    画面側でバグ・カテゴリーをすべてチェックONにしていたので Gradle 側でも同じ設定にします。 その設定は xml ファイルに書いて includeFilter で指定します
    (includeFilter の内容は別途下で説明します)
    最後の spotbugsMain{} はレポートの設定です、 このあたりの書き方は SpotBugs の git の readme が参考になるとおもいます、下記のような内容が書いてあります。
    f:id:tetsufuru:20210603011408p:plain f:id:tetsufuru:20210602235544p:plain 参考:GitHub - spotbugs/spotbugs-gradle-plugin

2 - 2. includeファイルについて

わたしの環境では include ファイルにバグ・カテゴリーの設定を書いています
画面側で設定したバグ・カテゴリーと同じものを Gradle 側でも設定したいので使っています。
spotbugs-include-filter.xml の内容例

<?xml version="1.0"?>
<FindBugsFilter>
    <Match><Bug category="BAD_PRACTICE,MALICIOUS_CODE,CORRECTNESS,PERFORMANCE,SECURITY,STYLE,EXPERIMENTAL,MT_CORRECTNESS,I18N" /></Match>
</FindBugsFilter>

FindBugsFilterタグの中にMatchタグとBugタグを追加して、category= で報告させたいバグ・カテゴリーをカンマ区切りで設定します
すべてのクラスファイルをチェックしたいので、Matchタグの中にはなにも条件を書いていません
BAD_PRACTICEは「悪い記述」のことで MALICIOUS_CODE は「悪意があるコードの脆弱性」のことです
これらのキーワードがどのカテゴリに該当するかはSpotBugsのドキュメントに書いてありました。 下のページの赤い部分です
f:id:tetsufuru:20210603004559p:plain 参考:Bug descriptions — spotbugs 4.2.3 documentation

あとこのファイルの置き場所は下記フォルダ内にしています。

[プロジェクト直下]/config/spotbugs/

2 - 3. Gradle で check コマンドを実行

これで一通りの設定が終わりました。
では check コマンドを実行してみます、プロジェクト直下で gradle のラッパーのコマンドを実行します。

gradlew check

実行結果はプロジェクト直下/build/reports/spotbugs/ に html ファイルが出力されます。
main.html を開いてみます、下のようなイメージになります。

レポートの例
f:id:tetsufuru:20210603005541p:plain

感想


おつかれさまでした。
今回はSpotBugsついて書きました。
SpotBugsはクラスの作りなど根本から変えないと対応できないような指摘をよくしてくるので あとから導入すると結構な目にあいます。
できるだけ早いタイミングで導入したほうが楽だとおもい書きました
少しでも皆さんの参考になればと思います。

それではまた😎

いまだにJava 8 備忘録 - CheckstyleとFormatterの使い方(Google Styleguide)

今日すること

こんにちはふるてつです。

きょうはCheckstyleFormatterのおはなしをします。
f:id:tetsufuru:20210314215338p:plain
わたしは客先に常駐するタイプの仕事をしていてどこの客先でもCheckstyleは見かけます。
慣れているはずですが自分でいちから設定するといつもCheckstyle設定とFormatterとで、つじつまが合わなくなり途中でやめてしまいます。

みなさんそのような経験はないですか?😑

わたしのような不器用なかたはCheckstyleFormatterの両方ともに「google提供の設定ファイル」を使うのがおすすめです。
わたしは EclipseGradleを使っていますので、GradleでのCheckstyle設定についても最後の方に書きたいと思います。

1. EclipseCheckstyle pluginの設定

Checkstyle pluginを使うと Eclipse の画面上でチェック結果を確認できます。
一番なじみのある使い方だと思います。

1 - 1. Checkstyle Plugin をインストール

まずは EclipseCheckstyle Pluginをインストールします。
Eclipse のメニューから「ヘルプ」-「Eclipseマーケットプレイス」を選びます。
f:id:tetsufuru:20210318015343p:plain

そして「Eclipseマーケットプレイス」の画面で「checkstyle」などのキーワードで検索して下記のようにインストールします。
いまバージョンは 8.36.1 が最新のようです。
f:id:tetsufuru:20210317005211p:plain

※ここで注意点ですが、おなじEclipseでも Pleiades のオールインワンを使っているかたは、すでにビルトインでCheckstyle Pluginが入っています。
マーケットプレイスからさらにインストールすると競合して動かなくなるので注意しましょう。

いまの環境にCheckstyle Pluginが入っているかどうかは設定画面で確認します。
下記の左側メニューに「Checkstyle」が表示されている場合はすでに入っていますのでインストールする必要はありません。
f:id:tetsufuru:20210318015651p:plain

1 - 2. Checkstyleの設定ファイル「google_checks.xml」をダウンロード

次にCheckstyleの git から googleCheckstyleの設定ファイルを入手します。

Checkstyleの git はこちらになります。
f:id:tetsufuru:20210318020751p:plain
https://github.com/checkstyle/checkstyle

チェックスタイル本体とプラグインのバージョンは若干づれていてプラグインが少し遅れ気味です。
ダウンロードする際はバージョンに気をつけてください。
Eclipseにインストールしたプラグインより上のバージョンのファイルを使うとCheckstyleが動かないことがあります。

そこで上の git の写真の右側にある「Releases」のところからプラグインと同じバージョンの checkstyle-8.36.1 を選んで「Source code(zip)」をダウンロードして中身を展開しておきます。
f:id:tetsufuru:20210317011620p:plain
https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-8.36.1

1 - 3. Eclipse に設定ファイル「google_checks.xml」を配置

次に Eclipse のプロジェクト直下にCheckstyleの設定ファイル用のフォルダを作成します。
置き場所はデフォルトで名前が決まっていて下記になります。

[プロジェクト直下]/config/checkstyle/

こちらのフォルダに checkstyle-8.36.1 中の src/main/resources/ から「google_checks.xml」をコピーします。

checkstyle-8.36.1の中(コピー元です)
f:id:tetsufuru:20210317092937p:plain

Eclipseのworkspaceの中(コピー先です)
f:id:tetsufuru:20210317095657p:plain

1 - 4. Checkstyleの新規構成を作成

では設定を取り込みます。
Eclipse のメニューから「ウィンドウ」-「設定」を選んで設定画面を開きます。
設定画面の左側メニューから「Checkstyle」をクリックすると下記の画面になります。
f:id:tetsufuru:20210318021359p:plain

すでにグローバルチェック構成のところに「Google Checks」はビルトインで入っていますが、Gradle側と設定を共有したいのでビルトインは使いません。
「新規」ボタンをクリックして
「型」は外部構成ファイル
「名前」は小文字の google_checks
「ロケーション」はEclipseのプロジェクトに置いた「google_checks.xml」を選びます。
f:id:tetsufuru:20210317102130p:plain

OKをクリックすると警告が出ますがそのまま「続行」をクリックして新規作成を完了します。
f:id:tetsufuru:20210318021534p:plain

新しく小文字の google_checks が増えたのでこれを「デフォルトとして設定」しておきます。
下記のような感じになります。
f:id:tetsufuru:20210318021646p:plain

これでCheckstyleのルール設定が新しくなりました。
あとは自動で検査が始まって、Checkstyle違反があるとパッケージエクスプローラーにマークがでると思います。
エラーの例(工事中のような!アイコンがでてきます)
f:id:tetsufuru:20210318022813p:plain

なにも出てこなければパッケージエクスプローラーでプロジェクトを「右クリック」-「Checkstyle」-「Checkstyle でコードチェック」を手動でおこなってみてください。
f:id:tetsufuru:20210318024327p:plain

あとメニューから「ビュー」の表示で「Checkstyle 違反」も見れるようにしておくといいと思います。
f:id:tetsufuru:20210317104003p:plain

1 - 5. Checkstyleの除外設定

Checkstyle Pluginの除外設定について説明しておきます。
除外設定は画面から行います。
設定方法ですが、まずパッケージエクスプローラーでプロジェクトを「右クリック」-「プロパティ」を開きます。
プロパティ画面左側のメニューで「Checkstyle」を選ぶと下記の画面のようにCheckstyle画面が表示されます。
※「ウィンドウ」-「設定」から表示される画面と似ているので間違えないようにしてください。
f:id:tetsufuru:20210318025231p:plain

上記画面で「パッケージのファイル」をクリック、「変更」ボタンをクリックします。
フィルターの画面が表示されるので除外するパッケージをチェックします。
f:id:tetsufuru:20210318025804p:plain

こちらはわたしの例になりますがMyBatisで自動作成した entity や repository のパッケージを除外しています。

2. Formatter設定

2 - 1. 設定ファイルのダウンロードとライセンスについて

次はFormatterの設定を行います。
Googleが提供しているStyleguideを使用します。
こちらのサイトです。
f:id:tetsufuru:20210319021230p:plain https://github.com/google/styleguide

このなかの「eclipse-java-google-style.xml」をダウンロードしてきます。
このファイルは最終更新日が3年前になっています、だいぶ以前からあったようです。
わたしもっと早く気づけばよかったですねぇ😎

ファイルの置き場所はCheckstyleに合わせて config の下に formatter のフォルダを作ってそこに置きます。

[プロジェクト直下]/config/formatter/

f:id:tetsufuru:20210319032414p:plain

ちなみにStyleguideの README にライセンスのことが書いてありこのファイルは「CC-By 3.0 License」とのことです。
f:id:tetsufuru:20210319031157p:plain

これは「クリエイティブコモンズライセンス」といいます。
大まかに説明すると、原作者のクレジット(氏名、作品タイトルなど)を表示すれば、自由にしていいライセンスです。
商業的にも問題ありませんし、修正も可能です。

そこでクレジットを「eclipse-java-google-style.xml」ファイルに追加します。
下記のように2行目にコメントで追加しておきます。
名前と取得元のURLを英語で書いた感じで良いと思います、これでライセンス的に問題なく使えるはずです。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- ここから
    Used this style from Google Style Guides.
    That can be found at https://github.com/google/styleguide
-->  ここまで
<profiles version="13">
以下省略

ちなみにもしソースを git で公開する場合は READMEに使っている旨をひとこと書いた方が良いと思います。
あと補足になりますが、クリエイティブコモンズライセンスについて詳しくは下記を参照ください。
クリエイティブ・コモンズ・ライセンスとは | クリエイティブ・コモンズ・ジャパン

2 - 2. 設定ファイルをインポート

では次に保存した設定ファイル「eclipse-java-google-style.xml」をインポートします。
Eclipse のメニューから「ウィンドウ」-「設定」を選んで設定画面を開きます。
設定画面の左側メニューで「Java」- 「コードスタイル」-「フォーマッター」を選びます。
f:id:tetsufuru:20210319033802p:plain

フォーマッターの画面で「インポート」ボタンをクリックして「eclipse-java-google-style.xml」をインポートします。
インポートが終わると「アクティブなプロファイル」の欄に「GoogleStyle」と表示されます。
f:id:tetsufuru:20210319034650p:plain

2 - 3. 保存アクションの設定

いったんインポートは終わりですが、「保存アクション」の設定も変えておきます。
設定画面の左側メニューで「Java」- 「エディター」「保存アクション」を選びます。
f:id:tetsufuru:20210319035535p:plain

上記のように保存アクション画面で保存時にソースコードのフォーマットを行うように設定します。
これで保存時に毎回Formatterソースコードをフォーマットするようになりました。
補足になりますが、わたしは「インポートの構成」もチェックONにしています。
「インポートの構成」をONにするとソースコードの保存時に Eclipse が自動でインポート文の並び順を調整します。
しかし今度はCheckstyleと合わなくなり、結局Checkstyleの設定ファイルを修正してCustomImportOrderの定義をコメントアウトしました。
同じように設定する場合、参考にしてください。

google_checks.xml の編集内容

<!--
<module name="CustomImportOrder"> ↓ ここからをコメントアウト
    <property name="sortImportsInGroupAlphabetically" value="true"/>
    <property name="separateLineBetweenGroups" value="true"/>
    <property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
    <property name="tokens" value="IMPORT, STATIC_IMPORT, PACKAGE_DEF"/>
</module> ↑ ここまでをコメントアウト
-->

3. GradleでのCheckstyle設定

ではGradleでのCheckstyle設定を説明します。
同じCheckstyleですが、最初に書いた「Eclipseマーケットプレイス」からインストールしたリアルタイムで動くほうのCheckstyle Pluginとは別物と思ってください。
こちらはリアルタイムではなくGradlebuildコマンドを実行したときにバッチ実行されてソースをチェックします。
ビルドをせずチェックのみをおこないたい場合はcheckコマンドで単独で実行できます。

Gradleで使うCheckstyleのサイトはこちらになります。
f:id:tetsufuru:20210319210428p:plain
https://docs.gradle.org/current/userguide/checkstyle_plugin.html

3 - 1. Gradleの設定ファイルにcheckstyleを追加する

ではまず build.gradle ファイルにcheckstyleの設定を追加します。

シングルプロジェクトの場合

プロジェクトが一つだけの普通のプロジェクトの場合はあたらしい書き方ができます。
バージョンや設定ファイルの定義は plugins{ } の下の checkstyle { } の中の Extension 部分に書きます。
プラグインのバージョンは toolVersion で定義します。
Gradleで使うcheckstyleの最新バージョンは現在 '8.41' ですが、わたしはリアルタイムで動くほうのCheckstyle Pluginと同じに合わせたかったので '8.36.1'にしています。
設定ファイルも同一ファイルを使いたいので同じ「google_checks.xml」を指定します。

build.gradle の内容

plugins {
    id 'checkstyle'
}
checkstyle {
    toolVersion = '8.36.1'
    configFile = rootProject.file('config/checkstyle/google_checks.xml')
}

マルチプロジェクトの場合

Gradleでは複数のプロジェクトまとめることができます。
この場合はあたらしい書き方にはまだできないので少し古い書き方になり、subprojects の中に追加します。
内容を少し簡略化していますが下記のような感じになります。
バージョンや設定ファイルはシングルプロジェクトと同じ書き方になります。

build.gradle の内容

subprojects {
    apply plugin: 'checkstyle'

    checkstyle {
        toolVersion = '8.36.1'
        configFile = rootProject.file('config/checkstyle/google_checks.xml')
    }
}
project(':biz') {}

project(':example_project') {
    dependencies {
        implementation project(':biz')
    }
}

3 - 2. チェックスタイルの除外設定ファイルを作成

Gradleで動かすcheckstyleの除外設定はファイルで行います。
設定のサンプルがcheckstyleの git にあります、こちらです。
f:id:tetsufuru:20210319214655p:plain
https://github.com/checkstyle/checkstyle/blob/master/config/suppressions.xml

これをひな型にしてチェックから除外したいパッケージやファイル名を指定します。
具体的は内容ですが例えばわたしはMyBatisで自動作成した entity や repository のパッケージを除外しています。
ほかにはMyBatis Generator の設定ファイルも除外しています「generationConfig.xml
下記を参考にしてみてください。

suppressions.xml の内容例

<?xml version="1.0"?>

<!DOCTYPE suppressions PUBLIC
    "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
    "https://checkstyle.org/dtds/suppressions_1_2.dtd">

<suppressions>
    <suppress checks=".*" files="com[\\/]example[\\/]demo[\\/]entity[\\/]domain[\\/]"/>
    <suppress checks=".*" files="com[\\/]example[\\/]demo[\\/]repository[\\/]"/>
    <suppress checks=".*" files="generationConfig.xml"/>
</suppressions>

あと除外ファイルの置き場所は「google_checks.xml」と同じ場所にしたいので下記フォルダ内にします。

[プロジェクト直下]/config/checkstyle/

名前もそのまま「suppressions.xml」として、下図のように保存しておきます。
f:id:tetsufuru:20210319221157p:plain

3 - 3. google_checks.xml ファイルを再編集

最後に「google_checks.xml」ファイルの中を再び編集して「suppressions.xml 」とリンクさせます。
module name = "Checker" のタグの中に、module name="SuppressionFilter" と書いてあるタグがあります。
そこの property の file を書き換えます。
google_checks.xmlの変更前

<!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
<module name="SuppressionFilter">
    <property name="file" value="${org.checkstyle.google.suppressionfilter.config}"
              default="checkstyle-suppressions.xml" />
    <property name="optional" value="true"/>
</module>

google_checks.xmlの変更後

<!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
<module name="SuppressionFilter">
    <property name="file" value="${config_loc}/suppressions.xml"/>   <!-- この行を書き換え -->
    <property name="optional" value="true"/>
</module>

${config_loc}Checkstyleのビルトインのプロパティでプロジェクト直下のconfigフォルダの意味になります。

3 - 4. Gradle で build コマンドを実行

これで一通りの設定が終わりました。
では build コマンドを実行してみます、プロジェクト直下で gradle のラッパーのコマンドを実行します。

gradlew build

実行結果はプロジェクト直下/build/reports/checkstyle/ に html ファイルが出力されます。
main.html を開いてみます、だいぶ割愛していますが下のようなイメージになります。

Checkstyleレポートの例
f:id:tetsufuru:20210319224317p:plain

感想


おつかれさまでした。
今回はCheckstyleFormatterについて書きました。
わたしはCheckstyleが長いこと苦手で、いままで避けてとおってきましたがブログにこうやって書くことで整理でき、やっと苦手を克服できたかなと思います。
Checkstyleをいちから設定する機会はそれほど多くはないと思いますので、少しでも皆さんの参考になればと思います。

それではまた😎

Angular11でWebアプリを作ろう - V11にバージョンアップ - ng update

今日すること

こんにちは、ふるてつです。
もう年末ですね。
Angularがバージョン 11 にあがりました。
9から10に上がるときはそれほど修正はなかったのでブログを書かなかったのですが、今回はすこし修正が多く感じたのでその内容を書こうと思います。

バージョンアップ情報の確認

まずはこちらのサイトで手順やその他情報をチェックします。
https://update.angular.io/?v=10.0-11.0
わたしの場合は、Materialを使っているので「I use Angular Material」はチェックONにします。
f:id:tetsufuru:20201215161520p:plain:w800 特に大きな変更とか書いてないですね、楽にバージョンアップできそうです。

ng updateコマンド

早速ですがAngularCLIng updateコマンドを実行します。
すると下記のリストがでてきました。
今回はcdkclicorematerialrxjsのほぼ全部のバージョンアップが必要そうです。

ng update
The installed local Angular CLI version is older than the latest stable version.
Installing a temporary version to perform the update.
Installing packages for tooling via npm.
Installed packages for tooling via npm.
Using package manager: 'npm'
Collecting installed dependencies...
Found 39 dependencies.
    We analyzed your package.json, there are some packages to update:

      Name                               Version                  Command to update
     --------------------------------------------------------------------------------
      @angular/cdk                       10.1.0 -> 11.0.0         ng update @angular/cdk
      @angular/cli                       10.0.3 -> 11.0.2         ng update @angular/cli
      @angular/core                      10.0.4 -> 11.0.2         ng update @angular/core
      @angular/material                  10.1.0 -> 11.0.0         ng update @angular/material
      rxjs                               6.6.0 -> 6.6.3           ng update rxjs

    There might be additional packages which don't provide 'ng update' capabilities that are outdated.
    You can update the addition packages by running the update command of your package manager.

実際にバージョンアップするコマンドですが、上のリストの最後右端に書いてあります。
コマンドを実行する順番はcoreが最初で、次clicdk、そしてmaterial、最後にrxjsがこれまでの経験的に良い気がします。
しかし今回は最初にcoreだと警告が出てしまい、順番を変えてcliから先にしました。
この辺の違いをわたしよくわかっていないですねぇ。

ちなみに下がcoreの時の警告です。
こういうメッセージがでたら焦らずに皆さんもupdateの順番を変えてみてください。
--forceのオプションをつけて実行しろとも書いてありますが、どうしてもできないときでいいと思います。

ng update @angular/core
The installed local Angular CLI version is older than the latest stable version.
Installing a temporary version to perform the update.
Installing packages for tooling via npm.
Installed packages for tooling via npm.
Using package manager: 'npm'
Collecting installed dependencies...
Found 39 dependencies.
Fetching dependency metadata from registry...
                  Package "@angular-devkit/build-angular" has an incompatible peer dependency to "typescript" (requires ">=3.9 < 3.10", would install "4.0.5").
× Migration failed: Incompatible peer dependencies found.
Peer dependency warnings when installing dependencies means that those dependencies might not work correctly together.
You can use the '--force' option to ignore incompatible peer dependencies and instead address these warnings later.   
  See "C:\Users\tetsu\AppData\Local\Temp\ng-KpdYdZ\angular-errors.log" for further details.

バージョンアップ実施

angular/cliのバージョンアップ

まず最初にCLIをバージョンアップします。
ng update @angular/cli

ng update @angular/cli
The installed local Angular CLI version is older than the latest stable version.
Installing a temporary version to perform the update.
Installing packages for tooling via npm.
Installed packages for tooling via npm.
Using package manager: 'npm'
Collecting installed dependencies...
Found 39 dependencies.
Fetching dependency metadata from registry...
    Updating package.json with dependency @angular-devkit/build-angular @ "0.1100.2" (was "0.1000.3")...
    Updating package.json with dependency @angular/cli @ "11.0.2" (was "10.0.3")...
    Updating package.json with dependency @angular/compiler-cli @ "11.0.2" (was "10.0.4")...
    Updating package.json with dependency @angular/language-service @ "11.0.2" (was "10.0.4")...
    Updating package.json with dependency karma @ "5.1.1" (was "5.0.9")...
    Updating package.json with dependency typescript @ "4.0.5" (was "3.9.7")...
    Updating package.json with dependency @angular/animations @ "11.0.2" (was "10.0.4")...
    Updating package.json with dependency @angular/common @ "11.0.2" (was "10.0.4")...
    Updating package.json with dependency @angular/compiler @ "11.0.2" (was "10.0.4")...
    Updating package.json with dependency @angular/core @ "11.0.2" (was "10.0.4")...
    Updating package.json with dependency @angular/forms @ "11.0.2" (was "10.0.4")...
    Updating package.json with dependency @angular/platform-browser @ "11.0.2" (was "10.0.4")...
    Updating package.json with dependency @angular/platform-browser-dynamic @ "11.0.2" (was "10.0.4")...
    Updating package.json with dependency @angular/router @ "11.0.2" (was "10.0.4")...
  UPDATE package.json (1684 bytes)
√ Packages installed successfully.
** Executing migrations of package '@angular/cli' **

> Removing "Solution Style" TypeScript configuration file support.
  DELETE tsconfig.base.json
  UPDATE tsconfig.json (569 bytes)
  UPDATE tsconfig.app.json (290 bytes)
  UPDATE tsconfig.spec.json (288 bytes)
  UPDATE e2e/tsconfig.json (230 bytes)
  Migration completed.

> Replace deprecated library builder '@angular-devkit/build-ng-packagr'.
  Migration completed.

> Add 'declarationMap' compiler options for non production library builds.
  Migration completed.

> Remove deprecated options from 'angular.json' that are no longer present in v11.
  UPDATE angular.json (4278 bytes)
  Migration completed.

> Update workspace dependencies to match a new v11 project.
  UPDATE package.json (1685 bytes)
√ Packages installed successfully.
  Migration completed.

** Executing migrations of package '@angular/core' **

> In Angular version 11, the type of `AbstractControl.parent` can be `null` to reflect the runtime value more accurately.
  This migration automatically adds non-null assertions to existing accesses of the `parent` property on types like `FormControl`, `FormArray` and `FormGroup`.
  Migration completed.

> ViewEncapsulation.Native has been removed as of Angular version 11.
  This migration replaces any usages with ViewEncapsulation.ShadowDom.
  Migration completed.

> NavigationExtras omissions migration.
  In version 11, some unsupported properties were omitted from the `extras` parameter of the `Router.navigateByUrl` and `Router.createUrlTree` methods.
  Migration completed.

> Updates the `initialNavigation` property for `RouterModule.forRoot`.
  Migration completed.

> NavigationExtras.preserveQueryParams has been removed as of Angular version 11.
   This migration replaces any usages with the appropriate assignment of the queryParamsHandling key.
  Migration completed.

> The default value for `relativeLinkResolution` is changing from 'legacy' to 'corrected'.
This migration updates `RouterModule` configurations that use the default value to 
now specifically use 'legacy' to prevent breakages when updating.
  UPDATE src/app/app-routing.module.ts (2120 bytes)
  Migration completed.

> `async` to `waitForAsync` migration.
  The `async` testing function has been renamed to `waitForAsync` to avoid confusion with the native `async` keyword.
  UPDATE src/app/app.component.spec.ts (2120 bytes)
  UPDATE src/app/core/components/error-messaging/error-messaging.component.spec.ts (2219 bytes)
  UPDATE src/app/core/components/loading/loading.component.spec.ts (1732 bytes)
  UPDATE src/app/core/components/mat-date-picker/mat-date-picker.component.spec.ts (3059 bytes)
  UPDATE src/app/core/components/success-messaging/success-messaging.component.spec.ts (2018 bytes)
  UPDATE src/app/core/components/yes-no-dialog/yes-no-dialog.component.spec.ts (1112 bytes)
  UPDATE src/app/pages/components/product-listing-page/product-listing-page.component.spec.ts (17363 bytes)
  UPDATE src/app/pages/components/product-registering-page/product-registering-page-edit.component.spec.ts (25442 bytes)
  UPDATE src/app/pages/components/product-registering-page/product-registering-page-new.component.spec.ts (28742 bytes)
  UPDATE src/app/pages/components/purchase-history-listing-page/purchase-history-listing-page.component-clear.spec.ts (7167 bytes)
  UPDATE src/app/pages/components/purchase-history-listing-page/purchase-history-listing-page.component.spec.ts (13654 bytes)
  UPDATE src/app/pages/components/sign-in-page/sign-in-page.component.spec.ts (7720 bytes)
  UPDATE src/app/pages/components/stock-registering-page/stock-registering-page.component.spec.ts (21791 bytes)
  UPDATE src/app/shared/components/footer/footer.component.spec.ts (795 bytes)
  UPDATE src/app/shared/components/header/header.component.spec.ts (4596 bytes)
  UPDATE src/app/shared/components/sidenav/sidenav.component.spec.ts (3605 bytes)
  UPDATE src/app/super-user-pages/dummy-purchasing-page/dummy-purchasing-page.component.spec.ts (25496 bytes)
  Migration completed.

CLIのバージョンアップでの変更点

CLIをバージョンアップすると2種類のコードが変更されました。
1つ目は「AppRoutingModule」です。
バージョンアップ前

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

バージョンアップ後

@NgModule({
  imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
  exports: [RouterModule]
})

 importsの中に{ relativeLinkResolution: 'legacy' }が追加になりました。
日本語リファレンスを見るとRouterバグフィックスとのこと。
必要かどうかV11で新規プロジェクトを作ってみたところCLIが自動で作った「AppRoutingModule」には { relativeLinkResolution: 'legacy' }は含まれていませんでした。
特に動作に問題が出ていなければ不要と思い、上段の方のコードに戻しました。

もう一つはcomponentのテストクラスです。

beforeEach(async(() => {

のところが、バージョンアップした後は下記のようになりました。

beforeEach(waitForAsync(() => {

使用するメソッドがasync()からwaitForAsync()に変わったようです。
こちらもV11でコマンドで新規にcomponentを作ってみます。
すると下記のようにasync ()はまだ使われていて、下の行にawaitが追加されたcomponentのテストコードができました。
あとかっこのネストが一つ減りました。

beforeEach(async () => {
  await TestBed.configureTestingModule({
    declarations: [ExampleComponent]
  }).compileComponents();
  router = TestBed.inject(Router);
});

というわけでV11で新規に作った場合に合わせることにして、waitForAsyncに変わったところはasync ()awaitの組み合わせに変えました。

angular/coreのバージョンアップ

次は最初に警告が出たcoreです。
ng update @angular/core

ng update @angular/core
Using package manager: 'npm'
Collecting installed dependencies...
Found 39 dependencies.
Fetching dependency metadata from registry...
Package '@angular/core' is already up to date.

今度は問題なく上がりました。

angular/materialのバージョンアップ

次はmaterialを上げます。
ng update @angular/material

ng update @angular/material
Using package manager: 'npm'
Collecting installed dependencies...
Found 39 dependencies.
Fetching dependency metadata from registry...
    Updating package.json with dependency @angular/cdk @ "11.0.0" (was "10.1.0")...
    Updating package.json with dependency @angular/material @ "11.0.0" (was "10.1.0")...
  UPDATE package.json (1684 bytes)
√ Packages installed successfully.
** Executing migrations of package '@angular/cdk' **

> Updates the Angular CDK to v11.
    
      ✓  Updated Angular CDK to version 11

  Migration completed.

** Executing migrations of package '@angular/material' **

> Updates Angular Material to v11.
    
    ⚠  General notice: The HammerJS v9 migration for Angular Components is not able to migrate tests. Please manually clean up tests in your project if they rely on HammerJS.
    Read more about migrating tests: https://git.io/ng-material-v9-hammer-migrate-tests
    
      ✓  Updated Angular Material to version 11

  Migration completed.

こちらも良い感じです。

angular/cdkのバージョンアップ

次はcdkを上げます。
ng update @angular/cdk

ng update @angular/cdk
Using package manager: 'npm'
Collecting installed dependencies...
Found 39 dependencies.
Fetching dependency metadata from registry...
Package '@angular/cdk' is already up to date.

もうバージョンが上がっているとのこと、特に問題ないです。

rxjsのバージョンアップ

最後にrxjsを上げます。
ng update rxjs

ng update rxjs
Using package manager: 'npm'
Collecting installed dependencies...
Found 39 dependencies.
Fetching dependency metadata from registry...
    Updating package.json with dependency rxjs @ "6.6.3" (was "6.6.0")...
  UPDATE package.json (1684 bytes)
√ Packages installed successfully.

こちらも問題なしですね。

GlobalのAngularをバージョンアップ

わたしはGlobalの方のAngularをバージョンアップするのをしばしば忘れます。
localだけで動くAngularをお使いの方は関係ありませんが、Globalもある方はお忘れなく😎
わたしはいったん消して最新をインストールしなおす感じです。
真ん中のnpm cache verifyの代わりにnpm cache clean --forceコマンドを実行する方もいるようです。

npm uninstall -g @angular/cli
npm cache verify
npm install -g @angular/cli@latest

動作確認(Unitテスト)

バージョンアップが終わったのでUnitテストを実行しようとしたらエラーで動きません。
カバレッジ関連のようですが、これまでに使っていたkarma-coverage-istanbul-reporterが非推奨になり、 バージョン11からはkarma-coverageを使うようになってました。
あとkarma.conf.jsの内容も変わるようです。

ng test
'karma-coverage-istanbul-reporter' usage has been deprecated since version 11.
Please install 'karma-coverage' and update 'karma.conf.js.' For more info, see https://github.com/karma-runner/karma-coverage/blob/master/README.md
Compiling @angular/core : es2015 as esm2015
Compiling @angular/cdk/keycodes : es2015 as esm2015
Compiling @angular/animations : es2015 as esm2015
Compiling @angular/compiler/testing : es2015 as esm2015
Compiling @angular/common : es2015 as esm2015
Compiling @angular/animations/browser : es2015 as esm2015
Compiling @angular/cdk/observers : es2015 as esm2015
~ 以下略 ~

karma-coverageのインストール

そこでカルマカバレッジをインストールします。
こちらのコマンドです。
npm install karma karma-coverage --save-dev

npm install karma karma-coverage --save-dev
npm WARN codelyzer@6.0.0 requires a peer of @angular/compiler@>=2.3.1 <11.0.0 || >9.0.0-beta <11.0.0 || >9.1.0-beta <11.0.0 || >9.2.0-beta <11.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN codelyzer@6.0.0 requires a peer of @angular/core@>=2.3.1 <11.0.0 || >9.0.0-beta <11.0.0 || >9.1.0-beta <11.0.0 || >9.2.0-beta <11.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN ngx-translate-testing@5.0.0 requires a peer of @angular/common@^10.0.0-rc.0 || >=10.0.0 <11.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN ngx-translate-testing@5.0.0 requires a peer of @angular/core@^10.0.0-rc.0 || >=10.0.0 <11.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\watchpack-chokidar2\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\webpack-dev-server\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ karma@5.1.1
+ karma-coverage@2.0.3
added 3 packages from 95 contributors, removed 1 package, updated 1 package and audited 1540 packages in 19.373s

77 packages are looking for funding
  run `npm fund` for details

karma.conf.jsの変更点

こちらは変更前の「karma.conf.js」です。
「karma-coverage-istanbul」の関連がV11でなくなった模様です。

// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'), // ←なくなる
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: { // ←なくなる
      dir: require('path').join(__dirname, './coverage/product-manage-site-for-hands-on'), // ←なくなる
      reports: ['html', 'lcovonly', 'text-summary'], // ←なくなる
      fixWebpackSourcePaths: true // ←なくなる
    }, // ←なくなる
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    restartOnFileChange: true
  });
};

変更後の「karma.conf.js」はこちらです。
V11で新規プロジェクトを作成してCLIが自動作成した「karma.conf.js」をそのまま自分のに上書きしました✨

// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    jasmineHtmlReporter: { // ←追加される
      suppressAll: true // removes the duplicated traces // ←追加される
    }, // ←追加される
    coverageReporter: { // ←追加される
      dir: require('path').join(__dirname, './coverage/product-manage-site-for-hands-on'), // ←追加される
      subdir: '.', // ←追加される
      reporters: [ // ←追加される
        { type: 'html' }, // ←追加される
        { type: 'text-summary' } // ←追加される
      ] // ←追加される
    }, // ←追加される
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    restartOnFileChange: true
  });
};

E2Eテストの確認

E2Eテストも問題なく動きました。

バージョン確認

最後にAngularのバージョンを確認してみます。
ng version

ng version

     _                      _                 ____ _     ___ 
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | | 
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | | 
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 11.0.2
Node: 12.18.1
OS: win32 x64

Angular: 11.0.2
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1100.2
@angular-devkit/build-angular   0.1100.2
@angular-devkit/core            11.0.2
@angular-devkit/schematics      11.0.2
@angular/cdk                    11.0.1
@angular/material               11.0.1
@schematics/angular             11.0.2
@schematics/update              0.1100.2
rxjs                            6.6.3
typescript                      4.0.5

良かったです、11 に上がってます。

今日の感想


V4あたりのころからAngularのバージョンアップに悩まされてきたので、ちょっとやそっとのことでは困らなくなってきました。
V11ではすこし既存ソースの修正が多かったように感じます。
それでもUnitテストとE2Eテストを準備しておけば、それなりに安心してバージョンアップできるかなぁと思います。

もう年末ですね、わたしは今年の3月から在宅勤務中ですが、来年もしばらくは在宅のままになりそうです。 では来年もよろしくお願いします。

いまだにJava 8 備忘録 - sonarqubeの使い方

今日すること

こんにちはふるてつです。

今回はJava自体のお話ではありません。
sonarqubeのお話になります。
sonarqubeソースコードの静的解析ツールになります。

f:id:tetsufuru:20201009020250p:plain:w300

常駐先のプロジェクトでも使用していますが、すでに設定されたものを使用するだけで、自分でいちから設定することはまずないです。
最近その常駐先で同僚にsonarqubeを教えようとしたところ「あら、どうやるんだっけ??」となりました。

そこで基礎から設定をやり直そうと思いブログにも書いた次第です。
Qiitaなどで話しつくされた感はかなりありますが…

1. sonarqubeの作業

まずsonarqubeダウンロードサイトを見てみます。
f:id:tetsufuru:20201009020730p:plain https://www.sonarqube.org/

コミュニティ版とデベロッパー版があるようですが、 ローカルにインストールして使用する場合は左のコミュニティ版を選ぶようです。
しかしダウンロードしているうちに下記のドキュメントにDocker版もあるというのを見つけまして、途中でダウンロードはやめて今回はDocker版を使うことにしました。

f:id:tetsufuru:20201009022548p:plain https://docs.sonarqube.org/latest/setup/get-started-2-minutes/

sonarqubeの起動

まずはsonarqubeを起動します、Dockerの起動コマンドはこちらです。

docker run -d --name sonarqube -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true -p 9000:9000 sonarqube:latest

プロセスが起動したら下記のURLを参照します、ローカルホストの9000番ポートです。
f:id:tetsufuru:20201009024237p:plain http://localhost:9000

これでsonarqubeが起動しました。

プロジェクトの登録

では解析するプロジェクトを追加していきます。
まずはサインインします、login、password はともにデフォルトで admin です。
f:id:tetsufuru:20201009024350p:plain

サインインすると「Create new project」ボタンがまんなかに出てきます。
f:id:tetsufuru:20201009025218p:plain

「Create new project」ボタンをクリックするとProject keyとDisplay nameを入力しろと出てきます。
Project keyは解析するプロジェクトとは関係なくどんな名前でも大丈夫なようです。
わたしはとりあえず my_sonar_qube_test にしてみました、Display nameも一緒です。 f:id:tetsufuru:20201009025414p:plain

「Set Up」ボタンをクリックすると次は token を入力しろと出てきました。
こちらもとりあえずの値 my_sonar_qube_token と入れました。
f:id:tetsufuru:20201009025833p:plain

「Generate」ボタンをクリックしてそのあと先に進むと下の画面にたどり着きます。
わたしの環境の場合、言語はJavaで、ビルドはGradleを選択しています。
他にもC#JSも解析できるようです。
f:id:tetsufuru:20201009135424p:plain

画面の下に表示されている内容のうちひとつは解析したいソースの build.gradle ファイルに追加する内容です。
もう一つはsonarqubeに解析したいソースを登録するコマンドになります。

2. 解析されるソース(Java)での作業

Gradleにプラグイン追加

下記のプラグインを build.gradle ファイルに追加します。

plugins {
    id "org.sonarqube" version "2.7"
}

わたしの環境はGradleのマルチプロジェクトで、フロント側とBiz側の二つの子供のプロジェクトがあります。
下記のような感じで2つともに追加しました。
(バージョンは変数にして別ファイルで管理してます)

フロント側の build.gradle

f:id:tetsufuru:20201009034647p:plain

Biz側の build.gradle

f:id:tetsufuru:20201009034750p:plain

sonarqubeに解析したいソースの登録

次に以下のコマンドを解析したいソースのディレクトリ直下で実行します。
補足になりますが、わたしはWindows環境なので-Dの書き方を変えないとエラーになりました。
最初の./gradlewのところも、Dosコマンドを使う方は./が不要と思います。

./gradlew sonarqube -D "sonar.projectKey=myTestProject" -D "sonar.host.url=http://localhost:9000" -D "sonar.login=ea493af063a0129adf716dae2e6e41000c9a9379"
}

このコマンドが正常に終了するとsonarqubeで解析結果を見れるようになります。

3. 解析結果の確認

今回の解析結果は下記になります。
解析対象のソースはわたしが個人的にJavaで作ったもので、これまでにCheckstyleSpotBugsなどのツールは一切使っていません。
たくさん指摘がでると思いますー
f:id:tetsufuru:20201009040046p:plain

Bugs

まず一番上のBugsをみると1件出ていますね。
そんなふうには作ってないのですが…クリックして中身を確認します。 f:id:tetsufuru:20201009140201p:plain IntegerIntegerをかけ合わせてそのあとにLongに変えている箇所に指摘がありますね。
「かけ合わせる前にそれぞれをキャストしろ」と言われているようです。

Vulnerabilities

脆弱性は0件です。これはよし。

Security Hotspots

Security Hotspotsは1件あります。
Security Hotspotsは脆弱性とは違うようですね。
「ここリスクが高いから確認しておけよ」という感じでしょうか。
こちらも中を確認します。
f:id:tetsufuru:20201009141230p:plain Spring Securityの security config が指摘されていました。 わたしの環境ではSPAでサインインするときにSpringのBasic認証を使っているのですがそのあたりです。
そうですね、もう一度自分の意図した設定とあっているか確認しておきます。

Debt

これは負債を解消するためのコストらしいのですが、2h 38min ならいいかなと思いここはスキップします。

Code Smells

Code Smells 「あやしいにおい」ですね、ここは29件もあります。
f:id:tetsufuru:20201009142108p:plain 中身を確認してみます。

a. コードの消し忘れ

f:id:tetsufuru:20201009142749p:plain コメントアウトしたままコードを消していなかったところが指摘されています…

b. シリアライズ

f:id:tetsufuru:20201009142932p:plain 「ここではシリアライズできるクラスを使ってくれ」といったことを指摘してますね、そうですか…

c. その変数は省略できます

f:id:tetsufuru:20201009144938p:plain 「その変数は省略できます」というヤツですね、同じ内容が多数指摘されました。
わたしは節目節目で変数にセットしたいタイプなのですが修正した方がいいでしょうねー
あと同じところにもう一つ指摘があり「lambda -> はメソッド参照 :: に変えましょう」というのもありました。
そうなんですね、これも修正せねば。

d. リストの中が空かどうか

f:id:tetsufuru:20201009145837p:plain 「リストの中が空かどうかは size() メソッドを使うのではなく、isEmpty() メソッドを使いましょう」という指摘です。
すみません…

感想


今回はsonarqubeの初期設定について書きました。
いちおう最後までできました。 今回指摘された内容は別途修正します。

実際に自分でやろうとするとうまくできないことがおおいですねぇ
でもこれで常駐先の同僚にちゃんと説明できると思います。どや顔で。

それではまた😎