ステップ3:既存のコードの置き換え
次に、main内部のコードを新しい関数に置き換えてみます。例えば以下のようになるでしょう。
// 前半省略:ステップ2のコードと同じ
int main() {
std::map<std::string, std::vector<double>> products = {
{"T-Shirts", {29.99, 34.99, 24.99, 19.99}},
{"Jeans", {49.99, 59.99, 69.99, 79.99}}
};
// ステップ3: 既存のコードを新しい関数に置き換える
for (const auto& product : products) {
double total, average;
std::tie(total, average) = calculateTotalAndAverage(product.second);
std::cout << "Total price of " << product.first << ": $" << total << std::endl;
std::cout << "Average price of " << product.first << ": $" << average << std::endl;
}
return 0;
}
今後productsが増えることを考慮し、T-Shirts、Jeansと処理を別々に書くのではなく、ループで回して計算・表示するようにしました。コードの修正が終わったら、すかさずコンパイル・テストを行いましょう。オリジナルやステップ2のコードと結果が変わらないことを確認してください。
ステップ4:再利用性を考慮して、コード分割
実装したcalculateTotalAndAverageは、プロジェクト内の他のプログラムからも便利に使えそうです。再利用のため、コードを分割しましょう。具体的には以下のような手順で分割します。
1. 関数宣言をヘッダーファイルに移動
calculateTotalAndAverage関数の関数宣言を新しいヘッダーファイル calculateTotalAndAverage.hに移動します。
2. 関数の実装をソースファイルに移動
calculateTotalAndAverage関数の実装を新しいソースファイル calculateTotalAndAverage.cppに移動します。
3. main関数を含むファイルの更新
main関数があるファイル(main.cppとします)から、新しいヘッダーファイル calculateTotalAndAverage.hをインクルードします。
これにより、作成された3つのファイルはそれぞれ以下のようになります。
#ifndef CALCULATE_TOTAL_AND_AVERAGE_H #define CALCULATE_TOTAL_AND_AVERAGE_H #include <vector> #include <utility> std::pair<double, double> calculateTotalAndAverage(const std::vector<double>& prices); #endif // CALCULATE_TOTAL_AND_AVERAGE_H
#include "calculateTotalAndAverage.h"
std::pair<double, double> calculateTotalAndAverage(const std::vector<double>& prices) {
double total = 0.0;
for (double price : prices) {
total += price;
}
double average = prices.empty() ? 0.0 : total / prices.size();
return {total, average};
}
#include <iostream>
#include <vector>
#include <map>
// ステップ3: calculateTotalAndAverage 関数を別ファイルにする
#include "calculateTotalAndAverage.h"
int main() {
std::map<std::string, std::vector<double>> products = {
{"T-Shirts", {29.99, 34.99, 24.99, 19.99}},
{"Jeans", {49.99, 59.99, 69.99, 79.99}}
};
for (const auto& product : products) {
double total, average;
std::tie(total, average) = calculateTotalAndAverage(product.second);
std::cout << "Total price of " << product.first << ": $" << total << std::endl;
std::cout << "Average price of " << product.first << ": $" << average << std::endl;
}
return 0;
}
すかさずコンパイル・テストをお願いします。ファイル分割した後のコンパイルは、各ソースファイル(.cppファイル)を個別にコンパイルしてから、それらをリンクして実行可能ファイルを作成するという手順になります。以下は、コマンド例です。
$ g++ -c -std=c++11 main.cpp -o main.o $ g++ -c -std=c++11 calculateTotalAndAverage.cpp -o calculateTotalAndAverage.o $ g++ main.o calculateTotalAndAverage.o -o myprogram $ ./myprogram
実行結果がステップ2、3のコードと同じであることを確認してください。口酸っぱく言ってしまってすみませんが、リファクタリングでは、こまめにコンパイル・テストすることが大事です。
