【プリンシプルオブプログラミング】アーキテクチャ非機能要件

 

目次

はじめに

この記事は「プリンシプルオブプログラミング」を読んで自分なりにまとめた学習メモです。 

思想 〜プログラミングのイデオロギー

非機能要件

非機能要件とは、機能面以外の全般についての要件のこと。

 

6つの観点

  • 変更容易性
  • 相互運用性
  • 効率性
  • 信頼性
  • テスト容易性
  • 再利用性

 

変更容易性

変更容易性とは、どれだけ容易に改善できるか、という能力のこと。

 

【具体的に】

  • 簡単に修正できるか
  • 簡単に拡張できるか
  • 簡単に再組織できるか
  • 簡単に別のプラットフォームに移行できるか

【意識すべきこと】

  • 保守性
  • 拡張性
  • 再構築
  • 移植性

 

相互運用性

相互運用性とは、ソフトウェアが、ほかのソフトウェアとやりとりできる能力のこと。

 

【意識すべきこと】

標準規格を選択する。外部の機能やデータ構造へ、アクセスが明確に定義されたアーキテクチャを設計する。

 

効率性

効率性とは、ソフトウェアが、実行に伴うリソース使用において、適切な性能を引き出す能力のこと。

 

【2つの観点】

  • 時間効率性スループット、レスポンスタイム、ターンアラウンドタイムなどで計測する
  • 資源効率性:CPUの使用時間、メモリ使用量、ストレージ消費量、ネットワーク転送量などで計測する

【意識すべきこと】

コンピュータのリソースを、適切に利用する。

あるものは有効活用して、ソフトウェア性能を最大限引き出すということ。節約することも必要だが、活用するという観点でもアーキテクチャを設計する。

 

信頼性

信頼性とは、ソフトウェアが、例外的な場面、予期しない方法や不正な方法で使用された場面においても、機能を維持する能力のこと。

 

【2つの側面】

  • フォールトトレランス:ソフトウェアに障害が発生した時に、正常な動作を保ち続ける能力。
  • ロバストネス:不正な使用方法や入力ミスから、ソフトウェアを保護する能力。

【フォールトトレランス観点の対策】

アーキテクチャに内部的な冗長性(二重化など)を持たせるようにする。

また、障害時に、提供する機能を絞り込み、大事な機能のみを提供して処理継続を優先する設計(フェールソフト)も考慮する。

ロバストネス観点の対策】

障害時に、その部分を切り離す設計(フェールセーフ)を検討する。

また、そもそも障害が発生しないように、あらかじめユーザが誤った操作を行っても安全に稼働させる設計(フェールプルーフ)も考慮する。

 

テスト容易性

テスト容易性とは、ソフトウェアに対して、「効果的」かつ「効率的」にテストを行う能力のこと。

  • 効果的:テストが深く、質が高いこと。
  • 効率的:テストのコストや労力が少ないこと。

 

【意識すべきこと】

アーキテクチャの策定の時点から、検証方法の観点も含めて設計する。

テストコードは、本番コードに従属するイメージだが、テストのためのコードが本番にあっても構わない。テストしやすくするための構造が、本番コードにあっていい、というくらい価値観の転換が必要。それぐらい、テストは重要。

テスト容易性のための設計では、モジュール間の依存関係の排除がポイントになる。依存関係があると、テストがしにくい部分に、全体が足を引っ張られる可能性が高くなる。極力、依存関係を排除し、小さい単位でテストが可能となるように設計する。

 

再利用性

再利用性とは、ソフトウェアを、全体でも一部でも、別のソフトウェアの開発に再利用する能力のこと。

 

【2つの側面】

  • 再利用するソフトウェア開発:ソフトウェア内の既存モジュール、以前のプロジェクトのモジュール、各種ライブラリなどを利用することを意味する。再利用可能な成果物を、開発中のソフトウェアに、そのまま、あるいは変形して統合する。
  • 再利用のためのソフトウェア開発:将来のプロジェクトで再利用できるようなモジュールを、現在のソフトウェアに再利用されるためのソフトウェア開発で創出することを意味する。他のソフトウェアに再利用されるためのソフトウェアを開発する。

【意識すべきこと】

再利用するソフトウェア開発の場合、アーキテクチャの構成を、既存の構造やモジュールに「プラグイン」できるようにする。独立してビルドできるようなモジュールにしパッケージにしておく。

 

 

 

【プリンシプルオブプログラミング】アーキテクチャ根底技法

 

目次

はじめに

この記事は「プリンシプルオブプログラミング」を読んで自分なりにまとめた学習メモです。 

思想 〜プログラミングのイデオロギー

アーキテクチャ根底技法

アーキテクチャ根底技法とは、よいソフトウェア・アーキテクチャ構築のための基礎原理のこと。

 

10の技法

  • 抽象
  • カプセル化
  • 情報隠蔽
  • パッケージ化
  • 関心の分離
  • 充足性、完全性、プリミティブ性
  • ポリシーと実装の分離
  • 参照の一点性
  • 分割統治

 

抽象

抽象とは、概念的に明確な「線引き」を行うこと。

 

【2つの観点】

  • 捨象:複雑な対象のいくつかの性質を捨て去り、特定の性質に目を向けること
  • 一般化:具体的な対象から共通の性質を抽出し、より汎用的な概念に定式化すること

【使える場面】

  • 複雑なものに取り組む時に使える

 

カプセル化

カプセル化とは、関連性の強いデータ群とロジック群を、モジュールという膜で包み込むこと。

 

【メリット】

  • 関連のない要素が混じらないため、コードが見やすくなる
  • 変更時の影響が、モジュール内に閉じることになる
  • 影響度が明確になるので、コードの変更が容易になる
  • それぞれが独立した部品になるので、再利用性が高まる
  • 小さい単位に分割されるので、複雑な問題に対処できる

 

情報隠蔽

必要ないものはみせないという考えで、モジュールの実装を、そのモジュールを使用するクライアントから隠蔽する。

 

【メリット】

  • インタフェースが小さくなり、やりとりがシンプルになり、コード全体の複雑性を下げることができる
  • クライアントから見ても、余計な情報が見えないため、モジュールの使い方がシンプルになり、使い勝ってがよくなる
  • 公開されている部分が少なければ、モジュールの内部に変更を留め置くことができる可能性が高くなり、コードの変更の波及を最小限に抑えることができる

 

パッケージ化

パッケージ化とは、モジュールを意味のある単位にまとめ、グループ化すること。

 

【メリット】

  • ソフトウェア全体が、パッケージという小さい単位に分割されるので、複雑度が下がる
  • パッケージ内は、関連のないモジュールが混じらないので、モジュールの管理がしやすくなる
  • 修正に対して、影響度がパッケージ内に留まる可能性が高いので、コードが変更しやすくなる
  • 依存関係が整理されることになり、パッケージを単位とした再利用をしやすくなる

【使える場面】

 

関心の分離

関心」とは、ソフトウェアの機能や目的のこと。

関心の分離とは、それぞれの関心に関連するコードを集めて、独立したモジュールとし、他のコードから分離するということ。

 

【メリット】

  • 関心ごとに独立して修正できるので、読む範囲が限られ、変更が容易になる
  • 影響範囲が関心内に留まることになるので、変更時の品質が安定する
  • コードを書く時は、関心を単位として開発するため、分業して並行して開発を進めることができる

【使える場面】

  • 関心ごとにモジュールを作成し、互いに異なる責務や、無関係な責務は、分離する
  • 例:「Model-View-Controller」パターンでは「ビジネスロジック」「ユーザへの表示」「入力処理」を分離している

 

充足性、完全性、プリミティブ性

カプセル化により、関連のある要素が、ある抽象概念を担うべく、モジュールに集まる。

  • 充足性:モジュールが表現しようとしている抽象が、それを伝えるために十分であるか
    • 例:「remove」が提供されていても、「add」が提供されてなければ、コレクションとして不十分
  • 完全性:すべての特徴を備えているか
    • 例:要素数を取得する「size」が提供されていなければ不完全
  • プリミティブ性:すべて純粋であるかどうか
    • 例:アイテムを1つ追加する「add」が提供されていれば、10個追加する「add10」は必要ない

 

ポリシーと実装の分離

ポリシーモジュール:そのソフトウェアの前提に依存する、ビジネスロジック部分

実装モジュール:そのソフトウェアの前提に依存しない、独立したロジック部分

 

【意識すべきこと】

  • ポリシー」と「実装」を意識して実装する
  • それぞれを別のモジュールに分けてコードを書く

 

参照の一点性 

モジュールの要素は、宣言され定義されるのは一回限りにする。

 

【メリット】

  • 副作用のないプログラミングが可能になる

 

【使える場面】

  • 見通しのよいコードにするために、変数に対して値の再代入を行わない

 

分割統治

 そのままでは解決することが難しい「大きな問題」は、いくつかの「小さな問題」に分割して、個別に解決する

 

【使える場面】

  • 大きな問題にぶつかったときに、制御が容易になるような規模まで問題を分割して、それから取り組む方が効率的

 

 

【Git】よく使うコマンド一覧

目次

 

ローカルリポジトリ

ローカルリポジトリとは、自分のマシン内にある作業ディレクトリのことです。

Gitの初期設定

// 初期化する
$ git init

add

ファイルの変更内容をステージ(インデックス)に追加するコマンド

// ファイルを追加
$ git add "ファイル"
// すべてのファイルを追加
$ git add .

 

commit

ファイルの変更内容をリポジトリに記録するコマンド

// 一つのファイルをコミット
$ git commit "ファイル"
// すべてのファイルをコミット
$ git commit .
// コメント付きのコミット
$ git commit -m "コメント"
// 直前のコミットを置き換える
$ git commit --amend
// 空白を削除
$ git commit strip

 

branch

// ブランチ一覧、作業中ブランチの確認
$ git branch
// 新しいブランチ作成
$ git branch "ブランチ"

 

checkout

// ブランチの切り替え
$ git checkout "ブランチ"

HEAD:作業中のコミットを指す

merge

$ git merge

rebase

$ git rebase

 

リモートリポジトリ

clone

$ git clone

pull

$ git pull

push

$ git push

remote

$git remote add origin master

 

引用サイト:
https://learngitbranching.js.org/

【Docker】よく使うコマンド一覧

 

目次

docker

Image

イメージ一覧

docker images

イメージ取得

docker pull <イメージ名>

イメージ削除

docker rmi <イメージID/イメージ名>

Container

コンテナ一覧

docker ps -a

コンテナ削除

docker rm <コンテナID/コンテナ名>

起動

docker run -d -name <コンテナ名> --network <ネットワーク名> -p <ポート>

-d: バックグランド実行

-name: コンテナ指定

-network: ネットワーク指定

-p: ポートフォワード指定

 

停止

docker stop <コンテナ名>

 

docker-compose

ビルド

docker-compose build

コンテナを起動

docker-compose up -d
docker-compose ps

コンテナを停止

docker-compose stop

停止、削除、ネットワーク削除

docker-compose down

イメージも合わせて削除

docker-compose down --rmi all

 

Dockerネットワーク

ネットワーク作成

docker network create <ネットワーク名>

ネットワーク確認

docker network ls

ネットワーク詳細確認

docker network inspect <ネットワーク名>

 

Dockerfile

FROM <イメージ> 
RUN <OSコマンド>
ADD <コピー元> <Dockerイメージ内のコピー・展開先>
CMD [ "<コマンド1>", "<コマンド2>" ]

FORM: ベースとするDockerイメージを指定

RUN: OSのコマンドを実行

ADD: コピー、展開

CMD: コンテナ起動時に実行するコマンド

 

docker-compose.yml

FROM <イメージ> 
RUN <OSコマンド>
ADD <コピー元> <Dockerイメージ内のコピー・展開先>
CMD [ "<コマンド1>", "<コマンド2>" ]

FORM: ベースとするDockerイメージを指定

RUN: OSのコマンドを実行

ADD: コピー、展開

CMD: コンテナ起動時に実行するコマンド

 

Other

コンテナを全削除

docker ps -aq | xargs docker rm

イメージを全削除

docker images -aq | xargs docker rmi

 

【プリンシプルオブプログラミング】プログラミングセオリー

 

目次

はじめに

この記事は「プリンシプルオブプログラミング」を読んで自分なりにまとめた学習メモです。 

思想 〜プログラミングのイデオロギー

プログラミングセオリー

「最高のコード」の定義

最高のコードとは、「拡張方法が多く存在し、余分な要素が存在せず、読みやすく、理解しやすい」コードのこと。

 

プログラミングセオリーを支える3つの価値

最高のコードを実現するために、プログラミングには「セオリー」があり、セオリーは3つの「価値」に支えられている。

  • コミュニケーション:「他の人はこのコードを見てどう感じるだろう?」と考える
  • シンプル:「余分な複雑性」を取り除く
  • 柔軟性:拡張しやすく、かつ、その拡張がほかに波及しないような設計を心がける

 

プログラミングセオリーを実現する6つの原則

価値と実際のプログラミングの架け橋となる、6つの「原則」がある。

  • 結果の局所化
  • 繰り返しの最小化
  • ロジックとデータの一体化
  • 対称性
  • 宣言型の表現
  • 変更頻度

結果の局所化

結果 = 変更の影響

つまり、「結果の局所化」とは、「変更の影響が、局所に留まるようにコードを構成する」ということ。関係性の高いコードを密集させ、関係性の低いコード同士が依存しないようなコードにする。

 

繰り返しの最小化

重複したロジックを関数化して、一つにまとめて共有コードとして使用できるようにする。

string yamada = "山田";
string tanaka = "田中";
string taro = "太郎";

System.out.println("おはよう。" + yamada);
System.out.println("おはよう。" + tanaka);
System.out.println("おはよう。" + taro);
string yamada = "山田";
string tanaka = "田中";
string taro = "太郎";

method(yamada);
method(tanaka);
method(taro);

// 出力処理を一つにまとめる
void method(String name) {
System.out.println("おはよう" + name);
}

 

ロジックとデータの一体化

「ロジック」と「ロジックが操作するデータ」を、互い近くに置く。

class Sample {
string str; // ロジックが操作するデータ

void method1() {
str = ...;
method2();
}

void method2() {
// strを使っている
}

// strを使っていないメソッド
...
}

 

 対称性

同じ種類のもの、つまり同質なものは、同じレベルで表現する。

  • 「追加」メソッドがあれば、対になる「削除」メソッドを作成
  • あるグループにある関数は、同じ引数を取るようにする
  • あるモジュール内のデータは、すべて生存期間が同じであるようにする
  • ある関数内で、呼び出し関数の抽象度は同じレベルとする

 

宣言型の表現

コードの意図を伝えようとする時、できるだけ「命令型」よりも「宣言型」で表現する。 

 

変更頻度

変更するタイミングが同じ要素は同じ場所に、違う要素は違う場所に置く。

 

 

【プリンシプルオブプログラミング】7つの原則

 

目次

はじめに

この記事は「プリンシプルオブプログラミング」を読んで自分なりにまとめた学習メモです。 

原則 〜プログラミングのガイドライン

7つの原則

  • KISS
  • DRY
  • YAGNI
  • PIE
  • SLAP
  • OCP
  • 名前重要

 

KISS

Keep It Simple, Stupid.

シンプルにしておけ、愚か者よ。

Keep It Short and Simple.

簡潔かつ単純にしておけ。

  • 意味:コードをシンプルに保つ
  • つまり:「動作させるために、もっともシンプルなものは何か」と常に問いかけ、コードに余計なことをしない
  • やってはいけないこと:
    • 新しく覚えた技術を使いたいがために、不要にトリッキーなコードを書いてしまうこと
    • 将来の必要に備えたいという考えで、過剰なコードを書いてしまうこと
    • 勝手に要件を判断し、余計なコードを加えてしまうこと

 

DRY

Don't Repeat Yourself.

繰り返すな。

  • 意味:コードのコピペ厳禁
  • つまり:コードを抽象化して、重複を排除する
  • 簡単な例:
   alert("スパゲッティが食べたい!");
   alert("チョコレートムースが食べたい!");
   function SwedishChef( food )
   {
       alert(food + "が食べたい!");
   }
   
   SwedishChef("スパゲッティ");
   SwedishChef("チョコレートムース");

 

YAGNI

You Aren't Going to Need It.

それはきっと必要にならない。

  • 意味:コードは必要最低限
  • つまり:汎用性のもたらす再利用性や拡張性よりも、まず「使える」ことに価値を置くよう単純性を考える

 

PIE

Program Intently and Expressively.

意図を表現してプログラミングせよ。

  • 意味:コードの意図を伝える
  • つまり:コードは「書きやすさ」よりも「読みやすさ」が最優先

まず、コードを比較してみる

return exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent)
if(exponent >= 0) {
    return mantissa * (1 << exponent);
} else {
  return mantissa / (1 << -exponent);
}

前者は簡潔で書きやすいコードだが、後者のほうが読みやすくて安心できる。

「簡潔」と「安心」はどちらを選ぶべきだろうか?

答えは、「安心」です。

プログラムの動作を把握するには、コードを読むしかない。「コードを書く時間」より「コードを読む時間」の方がずっと多い。

よって、第三者が理解しやすいコードを書くべき。

 

参考:

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

 

SLAP

Single Level of Abstraction Principle.

抽象化レベルの統一。

  • 意味:コードのレベルを合わせる
  • つまり:関数を構造化してレベルを揃える
  • 高水準、低水準:
    • 高水準なコード:Publicで外部公開されたメソッド、ユーザ側、外向けのコード
    • 低水準なコード:Privateで非公開のメソッド、より内部的なコード
  • レイヤの階層構造:
    • ユーザーの操作を受ける最上位レイヤ
    • 最上位レイヤが持つモデルクラスの公開メソッドとなる第2レイヤ
    • モデルクラスの公開メソッド内で呼び出される実際の処理の第3レイヤ
    • 実際の処理の中で呼び出されるライブラリの関数となる第4レイヤ
  • 参考:https://qiita.com/TSKGunGun/items/7b09d8a6f6623d67daa6

 

OCP

Open-Closed Principle.

オープン・クローズドの原則

開放・閉鎖原則

 

名前重要

Naming is important.

  • 意味:コードで命名は最重要課題
  • つまり:第三者視点に立ってコードの意図が正確に伝わるように命名する
  • 具体的に:
    • 明確な単語を選ぶ
    • tmp や retval などの汎用的な名前を避ける
    • 具体的な名前を使って、物事を詳細に説明する
    • 変数名に大切な情報を追加する
    • スコープの大きな変数には長い名前をつける
    • 大文字やアンダースコアなどに意味を含める
  • 参考:

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

 

【Webを支える技術】第5部 Webサービスの設計 学習メモ

 

目次

はじめに

この記事は「Webを支える技術」を読んで自分なりにまとめた学習メモです。

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

 

第5部 Webサービスの設計

第15章 読み取り専用の Web サービスの設計

 リソース設計

リソース設計とは、クライアントとサーバの間のインタフェースの設計、つまり Webサービスや Web APIの外部設計です。

設計とは、システムをどのような構成でどのように開発するのかを検討し、図や文書に残す作業です。設計図、設計書を作る作業とも言えます。

リソースを設計する際に大切なことは、Webサービスと Web API を分けて考えないことです。

 

リソース指向アーキテクチャのアプローチ

  1. Webサービスで提供するデータを特定する
  2. データをリソースに分ける
  3. リソースにURIので名前を付ける
  4. クライアントに提供するリソースの表現を設計する
  5. リンクとフォームを利用してリソース同士を結び付ける
  6. イベントの標準的なコースを検討する
  7. エラーについて検討する

 

第16章 書き込み可能な Web サービスの設計

 設計のバランス

  • なるべくシンプルに保つ
    • 設計が複雑になってきたら、機能が無駄に増えてきたら、1段階メタな視点で全体で考え直すこと。
    • 不要な機能や、やり方を変えることで削除できる機能があるかもしれない。
    • 全体をシンプルに保つことで、設計バランスを考えるうえで最も重要である。
  • 困ったらリソースに戻って考える
    • HTTPメソッドでは実現できない機能があると感じたら、それが独立した別リソースで代替できないかを考える。
    • 検索機能を実現するSEARCHメソッドをHTTPに追加するのではなく、「検索結果リソース」をGETする、と考えることが重要である。
  • 本当に必要なら POST で何でもできる
    • 更新にはPUTを用いるべきだとしても、たとえばバッチ処理のように複数リソースが対象となった時点で、PUTを使うのはあきらめてPOSTを用いるほどが賢明である。

 

第17章 リソースの設計 

関係モデル 

関係モデル(Relational Model)は RDBMS の基礎となっているデータモデルであり、数学的基盤を持っていることが特徴です。データの冗長性を排除するための正規化の手法が確立されており、効率的なデータベース設計ができます。

 

関係モデルからリソースを導出する場合は、

  • データの持つ階層構造を考えること
  • トップレベルリソースの存在を忘れないこと
  • リソースを設計する際は正規化を崩してすべての情報を含めるようにすること

 

オブジェクト指向モデル

オブジェクト指向設計は対象システムの分析モデルをオブジェクト指向言語のクラスとインスタンスに対応付けます。

 

成果物

  • クラス図
  • シーケンス図

 

オブジェクト指向モデルからリソースを導出する場合は、

  • クラスの持つメソッドを操作結果リソースへと変換すること。
  • これにより、クラスの持つ豊富なメソッドをHTTPの限定されたメソッドに置き換えられる。

 

情報アーキテクチャ

情報アーキテクチャ(Information Architecture)は、知識やデータの組織化を意味し、「情報をわかりやすく伝え」「受け手が情報を探しやすくする」ための表現技術です。

 

 

リソース設計で最も重要なこと

  • リソース設計するときはWebサービスとWeb APIを分けて考えないこと