- 投稿日:2021-01-10T22:42:39+09:00
Eclipseインストール
IBMが Java で開発した、オープン・ソースの統合開発環境(IDE)である
『Eclipse』をインストールしていきます。
『7-zip』をインストールする。
『Pleiades All in One』をダウンロードする。
Pleiades All in One ダウンロード
① 左上の『Eclipse 2020』をクリック。
②『Windows 64bit-Full Edition-Java』をダウンロードする。
ダウンロードしたファイルを、7-zipを使用して解凍
◆ Windows環境では『7-Zip』という解凍ソフトで解凍してください。
それ以外の解答ソフトでダウンロードしたファイルは正常動作しないとされています。
◆ 解凍してできたフォルダを、cドライブ直下など任意の場所に配置して下さい
Eclipse の起動
インストールフォルダの「eclipse」にある「eclipse.exe」を実行し、Eclipseを起動
終わり
Eclipse での環境構築の詳細に付いては、また今度まとめます。\(^o^)/
- 投稿日:2021-01-10T22:42:15+09:00
読書メモー「オブジェクト指向でなぜ作るのか」
はじめに
技術書等を読んで得た知識をまとめた、自分用の読書メモです。なので、自分の所感多めでまとめていきます。
今回は「オブジェクト指向でなぜつくるのか(著 平澤章)」(以下「本書」)についてです。
本の目次(日経BP書店のサイトです)
3行まとめ
- オブジェクト指向(OOP)についてよくある言説が含む誤りを示し、より実態に近いOOPの説明を与えてくれる
- OOPの基本的な概念やその歴史、そしてメモリの使われ方などOOPについての基礎知識について丁寧に書かれている
- UMLや設計・開発プロセスなどOOPを取り巻く周辺技術についてもまとめられている
第1章 オブジェクト指向はソフトウェア開発を楽にする技術
- 初心者にありがちな3つの混乱の整理
- 用語の洪水
- 比喩の乱用
- なんでもオブジェクト症候群
用語の洪水は、確かに学びはじめの頃に頭を悩ませた記憶がある。日常生活で聴き慣れないような単語は特に(ポリモーフィズムなど)。
比喩・なんでもオブジェクト症候群について意識はしていなかったが、本書によって現実世界とプログラム世界との境界がはっきりしたと思う。現実世界!=プログラム世界
第2章 オブジェクト指向と現実世界は大違い
- SSIA
第3章 OOPを理解する近道はプログラミング言語の歴史にあり
- OOP誕生に至るまでのプログラミング言語の歴史について
OOPは
連綿と続いてきたプログラミング言語の工夫と改良の歴史の中で、必然性を持って登場したものといってもいいでしょう。
ということだ。
OOP以前の言語(Cなど)とOOPとの違いはクラスの有無くらいしか認識していなかったが、その違いや関係性について理解できた。
そんなに昔からOOPが存在していたとは思いもしなかった(Simula67という言語を初めて知った)。
GOTO文はわるいぶんか。
第4章 OOPは無駄を省いて整理整頓するプログラミング技術
- OOPの特徴と言われる「カプセル化(本書では「クラス」)」、「ポリモーフィズム」、「継承」についてのわかりやすい説明
プログラミング言語は退化した?
という説が印象に残った。確かに、ものが進化していくにつれ、ある意味「危険」な機能はなくなっていくのかな(e.g.)自動車のMTとか)?
これらの隠れた機構について基礎寄りの知識を深めることと、これらを前提として高機能に(応用的に)使いこなしていくおことの、どちらも面白いと思った(自分はどちらかというと応用よりだと思う)。例外が比較的新しい概念であることを初めて知った。
OOPを生かすも殺すもプログラマの心がけ次第
第5章 メモリの仕組みの理解はプログラマのたしなみ
- OOPにおけるメモリの使われ方について
- ガベージコレクション
- インスタンス生成時のメモリ
メモリは「静的領域」「ヒープ領域」「スタック領域」(ここらへん地味に難しい...)
インスタンス変数はインスタンスごとに生成されるが、メソッドについてはクラスにごと1つずつしかメモリ上に存在しない。
OOPにも「ポインタ」は存在する(プログラマが意識しなくて良くなっているだけ)「メソッドテーブル」
第6章 OOPがもたらしたソフトウエアとアイデアの再利用
- OOPから発展した、ソフトウェアの枠組みを超えた「デザインパターン」について
つまり再利用部品群を作った時のノウハウを新しいデザインパターンとして抽出し、それをまた次の再利用部品群の開発に生かしているというわけです。
- フレームワークについての「ハリウッドの原則」
- GoFのデザインパターン -> 古いものではあるが、未だに通用するものである。
デザインパターンについては興味を持ったので今後書籍などを参照しようと思った。
第7章 汎用の整理術に化けたオブジェクト指向
- オブジェクト指向(の考え方)がソフトウェアを超えて開発工程の汎用的な整理術となったこと
- この側面が「オブジェクト指向」の理解の妨げの要員の日つつとなっている?
第8章 UMLは形のないソフトウエアを見る道具
- UMLについて
UMLは使ってはいたものの、ここまで広汎で汎用的なものだとは知らなかった(このことが批判される場合もあるらしい)。
ソフトウェア設計においては「クラス図」と「シーケンス図」で事足りそう(コミュニケーション図はよく分からなかった)。これらはソフトウェア以外の汎用的な知識の表現にも用いることができる。
非オブジェクト指向の表現としては、「ユースケース図」、「アクティビティ図」、「ステートマシン図」が使えそう。
これらは今関わっているプロジェクトでも頻繁に用いられるので、これを機に精通していきたい。
第9章 現実世界とソフトウエアのギャップを埋めるモデリング
- 投稿日:2021-01-10T22:36:32+09:00
リファクタリングの初歩知識・Java
はじめに
リファクタリングに必要と思われる基本的なことを随時追加していく
基本的には、以下の書籍を参考にした
- 結城浩 著『Java言語で学ぶリファクタリング入門』ソフトバンククリエイティブ(株)刊
意識しておくべき原則
- DRY原則
- Don’t Repeat Your Self
- 繰り返し(重複)を避けること
- KISSの原則
- Keep it simple, stupid
- 設計の簡潔性は大切、不必要な複雑性は避けるべき
- YAGNI原則
- You ain't gonna need it
- 機能は実際に必要となるまでは追加しないのがよい
前提知識
- OOP(オブジェクト指向プログラミング)の基礎的な理解
- クラスとインスタンスの関係
- アクセス修飾子
- 継承(抽象クラスとインタフェース)
- オーバーライド、オーバーロード
- ローカル変数・インスタンス変数・static変数(クラス変数)
リファクタリングの定義
- 外部から見たプログラムの振る舞いを変えずに、プログラム内部の構造を改善すること
テストについて
- 必ずユニットテスト(unit test)が必要
ユニットテストの定義
- 開発者自身が作成すること
- コード(通常はクラスやメソッドの単位)を対象としていること
- 自動化されていること
リファクタリングの目的
- バグを見つけやすくする
- 機能追加しやすくする
- レビューしやすくする
コツ
- 感覚で修正するのではなく、リファクタリングカタログに従う
- ステップ・バイ・ステップ(一度に一つずつ)
- まず不吉な匂いをかぎ取ること
不吉な匂い(リファクタリングの可能性)
- 重複したコード
- コードがあちこちでダブっている
- 長すぎるメソッド
- メソッドが長すぎる
- 巨大なクラス
- クラスが持っているフィールドやメソッドが多すぎる
- 多すぎる引数
- メソッドへ渡す引数が多すぎる
- 変更の発散
- 仕様変更が起きた時の修正箇所があちこちに散らばっている
- 変更の分散
- あるクラスを修正すると、他のクラスもあわせて修正しなければならない
- 属性、操作の横恋慕
- いつも他のクラスの中身をいじってるクラスがある
- データの群れ
- まとめて扱うべき複数のデータが、1つのクラスにまとまっていない
- 基本データ型への執着
- クラスを作らず、intのような基本データ型ばかり使っている
- スイッチ文
- switch文やif文を使って振る舞いを分けている
- パラレル継承
- サブクラスを作るとクラス階層の別のところにもサブクラスを作らなければならない
- 怠け者クラス
- クラスが大した仕事をしていない
- 疑わしき一般化
- いつかこういう拡張もするだろうと期待して、一般化しすぎる
- 一時的属性
- 一時的にしか使わないフィールドがある
- メッセージの連鎖
- メソッドの呼び出しの連鎖がある
- 仲介人
- 移譲ばかりしていて、自分では仕事をしていないクラスがある
- 不適切な関係
- その必要がないのに双方向リンクを張っていたり、IS-A関係がないのに継承を使っていたりする
- クラスのインタフェース不一致
- クラスのインタフェース(API)が不適切である
- 未熟なクラスライブラリ
- 既存のクラスライブラリが使いにくい
- データクラス
- フィールドとgetterメソッドとsetterメソッドしか持っていないクラスがある
- 相続拒否
- 継承しているメソッドなのに、それを呼ぶと問題が起きる
- コメント
- コードの不備を補なうために、詳しいコメントがある
リファクタリング・カタログ
適切な名前をつける
- シンボリック定数によるマジックナンバーの置き換え
- Replace Magic Number with Symbolic Constant
- メソッド名の変更
- Rename Method
- 説明用変更の導入
- Introduce Explaining Variable
- 一時変数の分離
- Split Temp ## 一時変数をなくす
- 一時変数のインライン化
- Inline Temp
- 問い合わせによる一時変数の置き換え
- Replace Temp with Query
- 制御フラグの削除
- Remove Control Flag ## 条件分岐をシンプルにする
- 条件記述の分解
- Decompose Conditional
- 重複した条件記述の断片の統合
- Consolidate Duplicate Conditional Fragments
- ガード説による入れ子条件記述の置き換え
- Replace Nested Conditional with Guard Clauses
- 条件記述の統合
- Consolidate Conditional Expression
- ヌルオブジェクトの導入
- Introduce Null Object
- ポリモーフィズムによる条件記述の置き換え
- Replace Conditional with Polymorphism ## 条件判定か例外か
- 例外によるエラーコードの置き換え
- Replace Error Code with Exception
- 条件判定による例外の置き換え
- Replace Exception with Test ## オブジェクトを作る
- Factory Method によるコンストラクタの置き換え
- Replace Constructor with Factory Method ## クラスやインタフェースを抜き出す
- クラスの抽出
- Extract Class
- クラスのインライン化
- Inline Class
- サブクラスの抽出
- Extract Subclass
- 階層の平坦化
- Collapse Hierarchy
- スーパークラスの抽出
- Extract Superclass
- インタフェースの抽出
- Extract Interface (カタログにない) ## 修正できないクラスにメソッドを追加する
- 外部メソッドの導入
- Introduce Foreign Method (カタログにない)
- 局所的拡張の導入
- Introduce Local Extension (カタログにない) ## カプセル化
- フィールドのカプセル化
- Encapsulate Field
- 自己カプセル化フィールド
- Self-Encapsulate Field
- コレクションのカプセル化
- Encapsulate Collection
- ダウンキャストのカプセル化
- Encapsulate Downcast (カタログにない) ## 状況を変えるかどうか
- setメソッドの削除
- Remove Setting Method
- 問い合わせと更新の分離
- Separate Query from Modifier ## フィールドの位置を整える
- フィールドの移動
- Move Field
- フィールドの引き下げ
- Push Down Field
- フィールドの引き上げ
- Pull Up Field ## メソッドの位置を整える
- メソッドの移動
- Move Method
- メソッドの引き下げ
- Push Down Method
- メソッドの引き上げ
- Pull Up Method
- コンストラクタ本体の引き上げ
- Pull Up Constructor Body ## メソッドを作る
- メソッドの隠蔽
- Hide Method (カタログにない)
- メソッドの抽出
- Extract Method
- メソッドのインライン化
- Inline Method
- アサーションの導入(表明の導入)
- Introduce Assertion
- アルゴリズムの取り換え
- Substitute Algorithm
- メソッドオブジェクトによるメソッドの置き換え
- Replace Method with Method Object ## メソッドの引数を整える
- 引数の削除
- Remove Parameter
- 引数の追加
- Add Parameter
- パラメータへの代入の除去
- Remove Assignments to Parameters
- 明示的なメソッド群による引数の置き換え
- Replace Parameter with Explicit Methods
- メソッドのパラメータ化
- Parameterize Method
- オブジェクトそのものの受け渡し
- Preserve Whole Object
- メソッドによる引数の置き換え
- Replace Parameter with Method
- 引数オブジェクトの導入
- Introduce Parameter Object ## タイプコードを置き換える
- クラスによるタイプコードの置き換え
- Replace Type Code with Class
- サブクラスによるタイプコードの置き換え
- Replace Type Code with Subclasses
- State/Strategyによるタイプコードの置き換え
- Replace Type Code with State/Strategy
- フィールドによるサブクラスの置き換え
- Replace Subclass with Fields ## 古いシステムへのオブジェクト指向を導入する
- オブジェクト指向による配列の置き換え
- Replace Array with Object (カタログにない)
- オブジェクトによるデータ値の置き換え
- Replace Data Value with Object
- データクラスによるレコードの置き換え
- Replace Record with Data Class
- 手続き的な設計からオブジェクトへの変換
- Convert Procedural Design to Objects (カタログにない) ## 値オブジェクトか参照オブジェクトか
- 値から参照への変更
- Change Value to Reference
- 参照から値への変更
- Change Reference to Value ## モデルとビュー
- 観察されるデータの複製
- Duplicate Observed Data (カタログにない)
- プレゼンテーションとドメインの分離
- Separate Domain from Presentation ## 継承と移譲を切り替える
- 移譲による継承の置き換え
- Replace Inheritance with Delegation
- 継承による移譲の置き換え
- Replace Delegation with Inheritance (カタログにない) ## 移譲
- 移譲の隠蔽
- Hide Delegate
- 仲介人の除去
- Remove Middle Man ## 継承
- Template Methodの形成
- From Template Method (カタログにない)
- 継承の分割
- Tease Apart Inheritance (カタログにない)
- 階層の抽出
- Extract Hierarchy (カタログにない) ## クラスの関連
- 双方向関連の単方向への変更
- Change bidirectional association to unidirectional (カタログにない)
- 単方向関連の双方向への変更
- Change unidirectional association to bidirectional (カタログにない)
- 投稿日:2021-01-10T22:36:32+09:00
Java言語でリファクタリングするときに最低限知っておくべきこと
はじめに
リファクタリングに必要と思われる基本的なことを随時追加していく
基本的には、以下の書籍を参考にした
- 結城 浩 著『Java言語で学ぶリファクタリング入門』ソフトバンククリエイティブ(株)刊
- Dustin Boswell, Trevor Foucher 著『リーダブルコード』オライリー・ジャパン刊
- 平澤 章 著『オブジェクト指向でなぜつくるのか』日経BP社刊
意識しておくべき原則
- DRY(Don’t Repeat Your Self)原則
- https://ja.wikipedia.org/wiki/Don%27t_repeat_yourself
- 繰り返し(重複)を避けること
- KISS(Keep it simple, stupid)の原則
- https://ja.wikipedia.org/wiki/KISS%E3%81%AE%E5%8E%9F%E5%89%87
- 設計の簡潔性は大切、不必要な複雑性は避けるべき
- YAGNI(You ain't gonna need it)原則
- https://ja.wikipedia.org/wiki/YAGNI
- 機能は実際に必要となるまでは追加しないのがよい
前提知識
- OOP(オブジェクト指向プログラミング)の基礎的な理解
- クラスとインスタンスの関係
- アクセス修飾子
- 継承(抽象クラスとインタフェース)
- オーバーライド、オーバーロード
- ローカル変数・インスタンス変数・static変数(クラス変数)
リファクタリングの定義
- 外部から見たプログラムの振る舞いを変えずに、プログラム内部の構造を改善すること
テストについて
- 必ずユニットテスト(unit test)が必要
ユニットテストの定義
- 開発者自身が作成すること
- コード(通常はクラスやメソッドの単位)を対象としていること
- 自動化されていること
リファクタリングの目的
- バグを見つけやすくする
- 機能追加しやすくする
- レビューしやすくする
コツ
- 感覚で修正するのではなく、リファクタリングカタログに従う
- ステップ・バイ・ステップ(一度に一つずつ)
- まず不吉な匂いをかぎ取ること
不吉な匂い(リファクタリングの可能性)
- 重複したコード
- コードがあちこちでダブっている
- 長すぎるメソッド
- メソッドが長すぎる
- 巨大なクラス
- クラスが持っているフィールドやメソッドが多すぎる
- 多すぎる引数
- メソッドへ渡す引数が多すぎる
- 変更の発散
- 仕様変更が起きた時の修正箇所があちこちに散らばっている
- 変更の分散
- あるクラスを修正すると、他のクラスもあわせて修正しなければならない
- 属性、操作の横恋慕
- いつも他のクラスの中身をいじってるクラスがある
- データの群れ
- まとめて扱うべき複数のデータが、1つのクラスにまとまっていない
- 基本データ型への執着
- クラスを作らず、intのような基本データ型ばかり使っている
- スイッチ文
- switch文やif文を使って振る舞いを分けている
- パラレル継承
- サブクラスを作るとクラス階層の別のところにもサブクラスを作らなければならない
- 怠け者クラス
- クラスが大した仕事をしていない
- 疑わしき一般化
- いつかこういう拡張もするだろうと期待して、一般化しすぎる
- 一時的属性
- 一時的にしか使わないフィールドがある
- メッセージの連鎖
- メソッドの呼び出しの連鎖がある
- 仲介人
- 移譲ばかりしていて、自分では仕事をしていないクラスがある
- 不適切な関係
- その必要がないのに双方向リンクを張っていたり、IS-A関係がないのに継承を使っていたりする
- クラスのインタフェース不一致
- クラスのインタフェース(API)が不適切である
- 未熟なクラスライブラリ
- 既存のクラスライブラリが使いにくい
- データクラス
- フィールドとgetterメソッドとsetterメソッドしか持っていないクラスがある
- 相続拒否
- 継承しているメソッドなのに、それを呼ぶと問題が起きる
- コメント
- コードの不備を補なうために、詳しいコメントがある
リファクタリング・カタログ
適切な名前をつける
- シンボリック定数によるマジックナンバーの置き換え
- Replace Magic Number with Symbolic Constant
- メソッド名の変更
- Rename Method
- 説明用変更の導入
- Introduce Explaining Variable
- 一時変数の分離
- Split Temp
一時変数をなくす
- 一時変数のインライン化
- Inline Temp
- 問い合わせによる一時変数の置き換え
- Replace Temp with Query
- 制御フラグの削除
- Remove Control Flag
条件分岐をシンプルにする
- 条件記述の分解
- Decompose Conditional
- 重複した条件記述の断片の統合
- Consolidate Duplicate Conditional Fragments
- ガード説による入れ子条件記述の置き換え
- Replace Nested Conditional with Guard Clauses
- 条件記述の統合
- Consolidate Conditional Expression
- ヌルオブジェクトの導入
- Introduce Null Object
- ポリモーフィズムによる条件記述の置き換え
- Replace Conditional with Polymorphism
条件判定か例外か
- 例外によるエラーコードの置き換え
- Replace Error Code with Exception
- 条件判定による例外の置き換え
- Replace Exception with Test
オブジェクトを作る
- Factory Method によるコンストラクタの置き換え
- Replace Constructor with Factory Method
クラスやインタフェースを抜き出す
- クラスの抽出
- Extract Class
- クラスのインライン化
- Inline Class
- サブクラスの抽出
- Extract Subclass
- 階層の平坦化
- Collapse Hierarchy
- スーパークラスの抽出
- Extract Superclass
- インタフェースの抽出
- Extract Interface (カタログにない)
修正できないクラスにメソッドを追加する
- 外部メソッドの導入
- Introduce Foreign Method (カタログにない)
- 局所的拡張の導入
- Introduce Local Extension (カタログにない)
カプセル化
- フィールドのカプセル化
- Encapsulate Field
- 自己カプセル化フィールド
- Self-Encapsulate Field
- コレクションのカプセル化
- Encapsulate Collection
- ダウンキャストのカプセル化
- Encapsulate Downcast (カタログにない)
状況を変えるかどうか
- setメソッドの削除
- Remove Setting Method
- 問い合わせと更新の分離
- Separate Query from Modifier
フィールドの位置を整える
- フィールドの移動
- Move Field
- フィールドの引き下げ
- Push Down Field
- フィールドの引き上げ
- Pull Up Field
メソッドの位置を整える
- メソッドの移動
- Move Method
- メソッドの引き下げ
- Push Down Method
- メソッドの引き上げ
- Pull Up Method
- コンストラクタ本体の引き上げ
- Pull Up Constructor Body
メソッドを作る
- メソッドの隠蔽
- Hide Method (カタログにない)
- メソッドの抽出
- Extract Method
- メソッドのインライン化
- Inline Method
- アサーションの導入(表明の導入)
- Introduce Assertion
- アルゴリズムの取り換え
- Substitute Algorithm
- メソッドオブジェクトによるメソッドの置き換え
- Replace Method with Method Object
メソッドの引数を整える
- 引数の削除
- Remove Parameter
- 引数の追加
- Add Parameter
- パラメータへの代入の除去
- Remove Assignments to Parameters
- 明示的なメソッド群による引数の置き換え
- Replace Parameter with Explicit Methods
- メソッドのパラメータ化
- Parameterize Method
- オブジェクトそのものの受け渡し
- Preserve Whole Object
- メソッドによる引数の置き換え
- Replace Parameter with Method
- 引数オブジェクトの導入
- Introduce Parameter Object
タイプコードを置き換える
- クラスによるタイプコードの置き換え
- Replace Type Code with Class
- サブクラスによるタイプコードの置き換え
- Replace Type Code with Subclasses
- State/Strategyによるタイプコードの置き換え
- Replace Type Code with State/Strategy
- フィールドによるサブクラスの置き換え
- Replace Subclass with Fields
古いシステムへのオブジェクト指向を導入する
- オブジェクト指向による配列の置き換え
- Replace Array with Object (カタログにない)
- オブジェクトによるデータ値の置き換え
- Replace Data Value with Object
- データクラスによるレコードの置き換え
- Replace Record with Data Class
- 手続き的な設計からオブジェクトへの変換
- Convert Procedural Design to Objects (カタログにない)
値オブジェクトか参照オブジェクトか
- 値から参照への変更
- Change Value to Reference
- 参照から値への変更
- Change Reference to Value
モデルとビュー
- 観察されるデータの複製
- Duplicate Observed Data (カタログにない)
- プレゼンテーションとドメインの分離
- Separate Domain from Presentation
継承と移譲を切り替える
- 移譲による継承の置き換え
- Replace Inheritance with Delegation
- 継承による移譲の置き換え
- Replace Delegation with Inheritance (カタログにない)
移譲
- 移譲の隠蔽
- Hide Delegate
- 仲介人の除去
- Remove Middle Man
継承
- Template Methodの形成
- From Template Method (カタログにない)
- 継承の分割
- Tease Apart Inheritance (カタログにない)
- 階層の抽出
- Extract Hierarchy (カタログにない)
クラスの関連
- 双方向関連の単方向への変更
- Change bidirectional association to unidirectional (カタログにない)
- 単方向関連の双方向への変更
- Change unidirectional association to bidirectional (カタログにない)
- 投稿日:2021-01-10T22:36:07+09:00
getPackageManagerでインストールアプリ一覧が表示されない(SDK30・Android11)
これまでgetPackageManager()#getInstalledPackages()を用いれば簡単に端末内のインストールアプリ情報を取得することができました。
しかし、Android 11(SDK30)からは単に下記のようなコードを記載するだけではシステムアプリ情報しか取得できなくなりました。例)デバイス内のインストールアプリをLog出力する
MainActivity.javaPackageManager pm = getApplicationContext().getPackageManager(); List<PackageInfo> appInfoList = pm.getInstalledPackages(0); for(int i =0;i<appInfoList.size();i++){ Log.d("MainActivity",appInfoList.get(i).applicationInfo.loadLabel(pm).toString()); }何がダメだったか
Android 11(SDK30)からはセキュリティ的に厳しくなっており、外部パッケージへのアクセスについてはManifestに明示する必要があります。
解決策
AndroidManifest.xmlにパーミッションの記述を書いてしまう。
AndroidManifest.xml<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>…全部許可してしまうので非推奨なやり方だと思われます。
本来は<queries>
で囲って個別に明示するのが正しい方法なのかも。参考
- 投稿日:2021-01-10T22:36:07+09:00
getPackageManagerでインストールアプリ一覧が表示されない(Android11・APIレベル30)
これまでgetPackageManager()#getInstalledPackages()を用いれば簡単に端末内のインストールアプリ情報を取得することができました。
しかし、Android 11(APIレベル30)からは単に下記のようなコードを記載するだけではシステムアプリ情報しか取得できなくなりました。例)デバイス内のインストールアプリをLog出力する
MainActivity.javaPackageManager pm = getApplicationContext().getPackageManager(); List<PackageInfo> appInfoList = pm.getInstalledPackages(0); for(int i =0;i<appInfoList.size();i++){ Log.d("MainActivity",appInfoList.get(i).applicationInfo.loadLabel(pm).toString()); }何がダメだったか
Android 11(APIレベル30)からはセキュリティ的に厳しくなっており、外部パッケージへのアクセスについてはManifestに明示する必要があります。
解決策
AndroidManifest.xmlにパーミッションの記述を書いてしまう。
AndroidManifest.xml<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>…全部許可してしまうので非推奨なやり方だと思われます。
本来は<queries>
で囲って個別に明示するのが正しい方法なのかも。参考
- 投稿日:2021-01-10T22:00:52+09:00
VSCodeでJavaの開発環境を構築!
Visual Studio Code (VSCode) で Javaの開発環境を構築してみました。
開発環境
OS : Windows10
VSCode : Version 1.52.1
手順
- [JDK] インストール
- [Java Extension Pack] インストール
- [Java.home] で [JDK] へパスを通す
JDK (Java SE Development Kit) をインストール!
JDK15ダウンロードページ へアクセス
Windows x64 に合わせて【jdk-15.0.1_windows-x64_bin.exe】をダウンロードします。
その後、画面の指示に従いデフォルト設定でインストール。
拡張機能 Java Extension Pack をインストール
拡張機能検索で『Java Extension Pack』と入力し、インストール。
java.homeを記述して、JDKにパスを通す
『VScode の設定』を開く
検索フォームに『java.home』と入力
【settings.json】と書かれている箇所をクリックすると
jsonファイルが開けるので、インストールしたバージョンに合わせて
下記のパスを入力します。{ "java.home": "C:/Program Files/Java/jdk-15.0.1", }これで設定は完了です。
VSCode再起動して、開環境構築完了です!
参考
- 投稿日:2021-01-10T20:13:38+09:00
Spring Boot + Java + GitHub認証ログイン
OAuth2を使ったSSOに苦戦したので、備忘録として残しておきます。
GitHubで「OAuth Apps」のクライアントIDとクライアントシークレットを生成する。
- GitHubを開く
- 右上のプロフィール画像を押下し、「Settings」を押下
- サイドバーの「Developer Settings」を押下
- サイドバーの「OAuth Apps」を押下
- [New Auth App]ボタンを押下
- 「Application name」に任意でアプリケーションの名前を入力
- 「Homepage URL」に作成中のアプリのトップページのURLを入力、ローカル環境で作成中なら「http://localhost:8080」
- 「Authorization callback URL」に「http://localhost:8080/login/oauth2/code/github」を入力
- 上記の手順で作成が完了したらクライアントIDとクライアントシークレットを控えておく
application.ymlに以下のように入力
spring security: oauth2: client: registration: github: client-id: 控えておいたクライアントID client-secret: 控えておいたクライアントシークレット scope: - read:user
- pom.xmlに以下のdependencyを追加
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency>
- 「configuration」パッケージを作成し、その中にconfigurationファイルを作成
@Configuration public class OAuth2ClientConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/") .permitAll() .antMatchers("/home") .permitAll() .antMatchers("/home/**").permitAll() .and() .oauth2Login() .loginPage("/login"); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/css/**", "/img/**", "/js/**" ); // staticフォルダ以下の静的ファイルはconfigure(WebSecurity web)でオーバーライド } } ```java @Controller @RequestMapping("") public class OAuth2ClientController { @GetMapping("") public String index(OAuth2AuthenticationToken authentication, @AuthenticationPrincipal OAuth2User oauth2User, Model model) { if(Objects.isNull(authentication)){ return "index"; } String userName = oauth2User.getAttributes().get("name").toString(); // githubのアカウント情報からユーザ名を取得 model.addAttribute("userName", userName); return "index"; } }<p th:text="${userName}"></p> <!-- 出力: githubのユーザ名 -->
- 投稿日:2021-01-10T14:51:52+09:00
2分探索法の練習
やったこと概要
基本情報処理技術者試験のアルゴリズムを自己流で練習として書いてみました。
他のアルゴリズムでも使う用の共通部品
線形探索法などの練習でも流用できるように作ったクラス。
探索結果をプリントするクラス。
MessagePrinter.java/** * 探索結果のメッセージをプリントするクラス * * @author hatena * */ import java.util.List; public class MessagePrinter { public void printFoundMessages(int targetNumber, List<Integer> targetList) { System.out.println("リストの中に探索対象の数" + targetNumber + "が存在しました。"); System.out.println("探索対象リストは" + targetList + "でした。"); System.out.println("探索対象の数のインデックスは" + targetList.indexOf(targetNumber) + "です。"); } public void printNotFoundMessages(int targetNumber, List<Integer> targetList) { System.out.println("リストの中に探索対象の数" + targetNumber + "は存在しませんでした。"); System.out.println("探索対象のリストは" + targetList + "でした。"); } }ランダムな整数のリストを作るクラス。
java.util.Random
クラスに指定範囲のIntStreamを返すints()メソッドがありました。
乱数に偏りがあるような気がする。。。RandomListCreator.javaimport java.util.List; import java.util.Random; import java.util.stream.Collectors; import lombok.AllArgsConstructor; /** * ランダムな正の整数のリストを作成するクラス。 * * @author hatena * */ @AllArgsConstructor public class RandomListCreator { public int lengthOfList; public int maximumNumber;//ex:50を指定したら生成されるリストは50も含む。 /** * 並び替えされていない指定長さの整数リストを返すメソッド。 * * */ public List<Integer> createRandUnorderdList() { // 乱数生成用クラス Random rand = new Random(); //@formatter:off List<Integer> unorderdRandlist = rand .ints(this.lengthOfList, 0, this.maximumNumber + 1) .boxed() .collect(Collectors.toList()); //@formatter:on return unorderdRandlist; } }2分探索法メイン部分
現時点で昇順のみに対応。
2分探索法機能を備えたクラス
BinSearch.javaimport java.util.List; import lombok.Data; /** * 2分探索法(対象配列は現時点で昇順のみ対応) * * @author hatena */ @Data public class BinSearch { // 先頭・中央・終端インデックス // 探索対象リスト、見つかったかどうかのフラグ private int beginIndex; private int midIndex; private int lastIndex; private List<Integer> targetList; private boolean isFound; // コンストラクタ。中央インデックスを先頭・終端インデックスで算出。 public BinSearch(List<Integer> targetList) { this.targetList = targetList; this.beginIndex = 0; this.lastIndex = targetList.size() - 1; this.midIndex = (this.beginIndex + this.lastIndex) / 2; this.isFound = false; } /** * 2分探索法本体を行うメソッド * */ public void findTargetNumber(int targetNumber) { // 確認するリストの先端インデックスが終端インデックス以下の間、探索を継続 // 見つからなかったらisFoundがfalseのままでループ終了 while (beginIndex <= lastIndex) { // リストの中央値とターゲット数が等しいか判定 // 等しければisFoundを更新してループ終了。 if (targetList.get(midIndex) == targetNumber) { isFound = true; break; } else if (targetList.get(midIndex) > targetNumber) { // リスト中央インデックス値のほうが大きいかどうか判定、確認対象インデックス更新 lastIndex = midIndex - 1; midIndex = (beginIndex + lastIndex) / 2; continue; } else { // リスト中央インデックス値のほうが小さいかどうか判定し、確認対象インデックス更新 beginIndex = midIndex + 1; midIndex = (beginIndex + lastIndex) / 2; continue; } } } }2分探索法を実行するメインのクラス
MainBinSearch.javaimport java.util.Collections; import java.util.List; import java.util.Scanner; import bisearch.BinSearch; import common.MessagePrinter; import common.RandomListCreator; /** * 2分探索法実行クラス * * @author hatena * */ public class MainBinSearch { public static void main(String[] args) { // 標準入力および結果表示用インスタンス作成 Scanner scanner = new Scanner(System.in); // ランダムなリスト作成に必要な情報(長さ、リスト内の最大数)をユーザーに入力させる。 // ランダムなリストを作るクラスをインスタンス化 System.out.print("リストの長さを正の整数で入力:"); int lengthOfList = scanner.nextInt(); System.out.print("リストに含める最大の数を入力:"); int maximumNumber = scanner.nextInt(); // ランダムな数字の昇順リストを作成 RandomListCreator listCreator = new RandomListCreator(lengthOfList, maximumNumber); List<Integer> targetList = listCreator.createRandUnorderdList(); Collections.sort(targetList); System.out.println("昇順のランダムな数のリストを作成しました。"); // 探したい数を標準入力 System.out.print("2分探索したい数を入力:"); int targetNumber = scanner.nextInt(); // 2分探索用のインスタンス作成、探索メソッド実行 BinSearch binSearch = new BinSearch(targetList); binSearch.findTargetNumber(targetNumber); // メッセージ表示用のインスタンス作成 MessagePrinter messagePrinter = new MessagePrinter(); // 探索結果に応じてメッセージを表示 if (binSearch.isFound()) { messagePrinter.printFoundMessages(targetNumber, binSearch.getTargetList()); } else { messagePrinter.printNotFoundMessages(targetNumber, binSearch.getTargetList()); } scanner.close(); } }※boolean型のisFoundというフィールドは、lombokによるアクセサメソッドの自動生成だと、メソッド名がgetIsFoundやsetIsFoundというメソッド名にならないことが判明。
getIsFoundがisFound
、setIsFoundがsetFound
というメソッド名になってしまいます(参考)。結果例
■ リストにターゲットの数字が存在したとき
リストの長さを正の整数で入力:10 リストに含める最大の数を入力:15 昇順のランダムな数のリストを作成しました。 2分探索したい数を入力:3 リストの中に探索対象の数3が存在しました。 探索対象リストは[0, 1, 2, 3, 6, 7, 8, 12, 13, 15]でした。 探索対象の数のインデックスは3です。■ リストにターゲットの数字が存在しなかったとき
リストの長さを正の整数で入力:10 リストに含める最大の数を入力:15 昇順のランダムな数のリストを作成しました。 2分探索したい数を入力:3 リストの中に探索対象の数3は存在しませんでした。 探索対象のリストは[1, 1, 8, 10, 10, 11, 11, 14, 14, 14]でした。
- 投稿日:2021-01-10T14:42:07+09:00
線形探索法の練習
やったこと概要
基本情報処理技術者試験のアルゴリズムを自己流で練習として書いてみました。
他のアルゴリズムでも使う用の共通部品
2分探索法などの練習でも流用できるように作ったクラス。
探索結果をプリントするクラス。
MessagePrinter.java/** * 探索結果のメッセージをプリントするクラス * * @author hatena * */ import java.util.List; public class MessagePrinter { public void printFoundMessages(int targetNumber, List<Integer> targetList) { System.out.println("リストの中に探索対象の数" + targetNumber + "が存在しました。"); System.out.println("探索対象リストは" + targetList + "でした。"); System.out.println("探索対象の数のインデックスは" + targetList.indexOf(targetNumber) + "です。"); } public void printNotFoundMessages(int targetNumber, List<Integer> targetList) { System.out.println("リストの中に探索対象の数" + targetNumber + "は存在しませんでした。"); System.out.println("探索対象のリストは" + targetList + "でした。"); } }ランダムな整数のリストを作るクラス。
java.util.Random
クラスに指定範囲のIntStreamを返すints()メソッドがありました。
乱数に偏りがあるような気がする。。。RandomListCreator.javaimport java.util.List; import java.util.Random; import java.util.stream.Collectors; import lombok.AllArgsConstructor; /** * ランダムな正の整数のリストを作成するクラス。 * * @author hatena * */ @AllArgsConstructor public class RandomListCreator { public int lengthOfList; public int maximumNumber;//ex:50を指定したら生成されるリストは50も含む。 /** * 並び替えされていない指定長さの整数リストを返すメソッド。 * * */ public List<Integer> createRandUnorderdList() { // 乱数生成用クラス Random rand = new Random(); //@formatter:off List<Integer> unorderdRandlist = rand .ints(this.lengthOfList, 0, this.maximumNumber + 1) .boxed() .collect(Collectors.toList()); //@formatter:on return unorderdRandlist; } }線形探索法メイン部分
単純に先頭から合致する数字がないか見ていく。
線形探索法機能を備えたクラス
SeqSearch.javaimport java.util.List; import lombok.AllArgsConstructor; import lombok.Data; /** * 線形探索法を行うクラス(拡張for文なので番兵の出番なし。) * * @author hatena */ @Data @AllArgsConstructor public class SeqSearch { private List<Integer> targetList; /** * 線形探索法本体のメソッド。先頭から順番に探索。 * * @return 一致したインデックス。一致しなかったら-1が返却。 * */ public int findTargetNum(int targetNumber) { // リスト先頭から順に一致するか確認。 for (int num : this.targetList) { // ターゲットの数字がリストに含まれていたらインデックス番号を返却。 if (num == targetNumber) { return this.targetList.indexOf(targetNumber); } } // 最後まで一致しなかった場合。 return -1; } }線形探索法を実行するメインのクラス
MainSeq.javaimport java.util.List; import java.util.Scanner; import common.MessagePrinter; import common.RandomListCreator; import seqsearch.SeqSearch; /** * 2分探索法実行メインクラス * * @author hatena * */ public class MainSeq { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // ランダムなリスト作成に必要な情報(長さ、リスト内の最大数)をユーザーに入力させる System.out.print("リストの長さを正の整数で入力:"); int lengthOfList = scanner.nextInt(); System.out.print("リストに含める最大の数を入力:"); int maximumNumber = scanner.nextInt(); // ランダムなリストを作成 RandomListCreator listCreator = new RandomListCreator(lengthOfList, maximumNumber); List<Integer> targetList = listCreator.createRandUnorderdList(); System.out.println("ランダムな数のリストを作成しました。"); // 探索したい数を標準入力する System.out.print("線形探索したい数を入力:"); int targetNumber = scanner.nextInt(); System.out.println("このリストの中に" + targetNumber + "があるか線形探索します。"); // 線形探索本体のクラスに、リストと探索対象を渡す。 SeqSearch seqSearch = new SeqSearch(targetList); // 結果メッセージ表示用クラスインスタンス化 MessagePrinter messagePrinter = new MessagePrinter(); // リストに該当すれば0以上の整数が返り、結果をプリント if (seqSearch.findTargetNum(targetNumber) >= 0) { messagePrinter.printFoundMessages(targetNumber, seqSearch.getTargetList()); } else { messagePrinter.printNotFoundMessages(targetNumber, seqSearch.getTargetList()); } scanner.close(); } }結果例
■ リストにターゲットの数字が存在したとき
リストの長さを正の整数で入力:10 リストに含める最大の数を入力:15 ランダムな数のリストを作成しました。 線形探索したい数を入力:9 このリストの中に9があるか線形探索します。 リストの中に探索対象の数9が存在しました。 探索対象リストは[0, 14, 14, 9, 6, 0, 4, 7, 15, 7]でした。 探索対象の数のインデックスは3です。■ リストにターゲットの数字が存在しなかったとき
リストの長さを正の整数で入力:10 リストに含める最大の数を入力:15 ランダムな数のリストを作成しました。 線形探索したい数を入力してください。:9 このリストの中に9があるか線形探索します。 リストの中に探索対象の数9は存在しませんでした。 探索対象のリストは[11, 7, 10, 10, 14, 4, 11, 3, 11, 1]でした。
- 投稿日:2021-01-10T03:48:01+09:00
Eclipse + Codewind で、コンテナ化された Java Web アプリを開発してみる
2020年8月頃に、IBM のクラウドネイティブアプリ/コンテナ向け開発環境「Accelerators for Teams(Appsody Stacks)」を紹介いたしました。
※ Accelerators for Teams を、以下 「AfT」 と略します。・「Appsody Stacks」を30分 x 3回で理解できるかやってみる(1回目)
・「Appsody Stacks」を試してみる(2回目:パイプラインで自動化)
・「Appsody Stacks」を試してみる(3回目:GitHubとパイプラインの連携)前回は、Appsody Stacks の CLI環境である appsody CLI の利用方法を紹介しましたが、プログラミング では VSCode や Eclipse といったソースコードエディタ・IDEを使用するのが一般的かと思います。
VSCode・Eclipse 環境に AfT による開発のために拡張機能を提供する、「Eclipse Codewind」を利用する方法について記載します。用語について
AfT は、IBM の「IBM Cloud Pak for Application」に含まれる製品となります。
昨今の IBM プロダクトの特長かと思いますが、AfT も様々なオープンソースプロジェクト化されて展開されています。
IBM 製品にありがち(?)な、様々な用語が出てきますので、ここで AfT に関連する用語を簡単に解説します。IBM Cloud Pak for Applications(略:CP4App)
・IBM の説明抜粋
既存のアプリケーションを最新化し、RedHat OpenShift で実行される新しいクラウドネイティブアプリを開発するための、エンタープライズ対応のコンテナ化されたソフトウェアソリューションです。ざっくりと言えば、IBM WebSphere Application Server などの主に Java EE 対応のアプリケーションサーバ(ミドルウェア)向けのアプリケーションを、クラウドネィテブなアプリケーションとして、コンテナ環境へ移行・実行するための製品と言えるでしょうか。
(アプリケーションの開発言語は Java EE に制限されるわけではありません。)【参考】Cloud Pak for Applications入門
https://cloud.ibm.com/docs/cloud-pak-applications?topic=cloud-pak-applications-getting-started&locale=jaAccelerators for Teams(略:AfT)
・IBM の説明抜粋
IBM Accelerators for Teams は、Red Hat OpenShift を統合、拡張し、その価値を高めます。
Kabanero.io オープン・ソース・コミュニティー・プロジェクトの、フルサポートされている企業向けの商用実装環境。
Accelerators for Teams は、Kubernetes と Knative (サーバーレス) の両方のアプリケーションの開発、ビルド、およびデプロイメントを簡素化するマイクロサービス・ベースのフレームワークを提供します。ざっくりと言えば、コンテナ化されたアプリケーションを開発するための各種OSSツールを統合しフレームワークを提供すると言えるでしょうか。従来は Kabanero Enterprise と呼称されていましたが、AfT にリブランドされたみたいです。
Kabanero については後述。【参考】CP4App 概要
https://www.ibm.com/support/knowledgecenter/ja/SSCSJL_4.3.x/about-overview.htmlAppsody Stacks
・Appsody プロジェクトの説明抜粋
Appsody は、クラウド用のコンテナ化されたアプリケーションの開発を支援するように設計されています。
Appsody Stacks は、Eclipse MicroProfile を使用した Java や、Express を使用した Node.js など、一般的なランタイムとフレームワークで構築された構成可能なテクノロジースタックです。これらのスタックは、Kubernetesで効果的にデプロイおよび管理できるアプリケーションを構築するための基盤を提供します。ざっくりと言えば、Java・Node.js など各言語に対応したアプリケーション開発用のツール・スタックを提供すると言えるでしょうか。
Appsody は、2020年12月に独立プロジェクトとしては終了し、Red Hat の Odo(オドー)に引き継がれたとのこと。【参考】Appsody Stacks
https://appsody.dev/docs/stacks/stacks-overview/Eclipse Codewind(略:Codewind)
・IBM BLOG の説明抜粋
Eclipse Codewind は、開発者がお気に入りの IDE 内で簡単にクラウド・ネイティブ・アプリケーションを作成できるようにするための新しいオープン・ソース・プロジェクトです。現時点で Codewind がサポートしているのは Visual Studio Code、Eclipse IDE、Eclipse Che です。ざっくりと言えば、Appsody (CLI・Stacks)による開発を、VSCode・Eclipse と統合するための拡張機能と言えるでしょうか。
【参考】Eclipse Codewind の紹介
https://developer.ibm.com/jp/technologies/containers/blogs/codewind-introduction/Kabanero
・IBM BLOG の説明抜粋
Kabanero はオープン・ソース・プロジェクトの Knative、Istio、Tekton と、新しいオープン・ソース・プロジェクトである Codewind、Appsody、Razee を 1 つにまとめ、Kubernetes ベースのアプリケーション・ライフサイクルを設計、作成、デプロイ、管理するためのエンドツーエンドのソリューションに仕上げています。ざっくりと言えば、AfT の オープンソース版と言えるでしょうか。Kabanero を製品版としてサポートを付けて提供するのが、AfT ですね。
【参考】Kabanero を使用して、Kubernetes 対応のクラウド・ネイティブ・アプリを迅速に構築する
https://developer.ibm.com/jp/technologies/containers/blogs/cloud-native-apps-kubernetes-kabanero/今回やってみたこと
・Eclipse IDE に、Codewind を導入して AfT を利用した Java 開発をやってみる。
・作成した Java アプリケーションを、CP4App 上で稼動させてみる。今後の予定
以下の内容に分けて、順次 Qiita に掲載していこうと思います。
・Eclipse + Codewind のインストール。
・Open Liberty(*) + Db2 on Cloud を使って、簡単な Java による Web アプリを作ってみる。
・作った Web アプリを、CP4App 上にデプロイする。※Open Liberty とは、IBM の Java アプリケーションサーバである、WebSphere Liberty のオープンソース版。
ぼやき・・・
この検証は昨年の12月下旬から初めて、つい先日終えたので Qiita にまとめようと思った次第なのですが、CP4Appの最新版 Ver 4.3 が昨年12月から提供された模様です。
リリースノートを見ると、、、
https://www.ibm.com/support/knowledgecenter/ja/SSCSJL_4.3.x/about-whats-new.html「Appsody CLI (appsody) およびパイプラインは、このリリースでも引き続き非推奨」
Appsody が終了して、Odo に移行しますからね。。。「Eclipse Codewind は、このリリースでは非推奨」
あれ・・・「Tekton Webhook 拡張機能も削除」
以前、「Appsody Stacks」を試してみる(3回目:GitHubとパイプラインの連携)で使った機能ですが。
あれれ・・・今後も目が離せません(泣