SlideShare una empresa de Scribd logo
1 de 28
Descargar para leer sin conexión
よいコード、わるいコード
京都大学理学部数学系4回生
KMC ID: hatsusato
2015/05/11
2/28
自己紹介
● hatsusato
– 理学部数学系4回生
●
最近は数学基礎論とか集合論とかやってる。
●
プログラミング言語を作りたい。
– 趣味
●
作画アニメ
– すきなもの
● C++
– きらいなもの
● C++
3/28
よいコード わるいコード
●
そんなの ひとの かって
– ではない。
– 良いコード、悪いコードは存在する。
4/28
よいコード わるいコード
● この講座では、良いコード、悪いコードの例(当社調べ)
を挙げることで啓蒙しようと思います。
– サンプルコードには、良いコードを書くのが難しいと定評
のある[要出典]、C++を用います。
● 僕がC++と言ったらそれはC++11以降のC++のことです。
– 他の言語ではあまり役に立たないアドバイスもあるか
も。
●
良いコード、悪いコードを知って、ライバルに差を
つけろ!
5/28
よいコード わるいコード
●
ここでの良いコードとは、保守性の高いコードの
ことを指すものとします。
– 機能の追加・修正を行い易く、バグが発生しにくい。
6/28
目次
●
一貫性
– 初期化
– オブジェクトの整合
●
疎結合
– 間接メンバアクセス
– 非メンバ関数
– const教
●
例外安全
– No new, No delete
7/28
一貫性
●
コードの一貫性を保つ
– 何をしたいコードなのかを誰が読んでもわかるようにす
る。
– コードの表記の一貫性を保つ
●
コーディング規約とか。
– オブジェクト表現の一貫性を保つ
●
オブジェクトのコード上の見た目と表現する実体とを一致させ
る。
8/28
初期化
●
まず初期化しろ
– 未初期化オブジェクトはしばしば未定義動作を引き起こ
し、デバッグを困難にする。
9/28
初期化
●
まだパフォーマンスを気にするような時間じゃな
い
– 初期化をあとですることによるパフォーマンス向上<<
<<越えられない壁<<<<デバッグの利便性
– パフォーマンスは、ベンチマークを取ってから検討する。
– プログラムの処理にかかる時間の80%は、コード全体の
20%の部分が占める。
10/28
オブジェクトの整合
●
悪い例
– Cでは文字列を格納する領域を表現するのに、先頭ポイ
ンタと領域の長さとの2つで表現する。
– 2つは密接に関連するのに、別々に管理される。
整合性のないオブジェクトが簡単に出来てしまう!
#include <cstdio>
char* fgets(char* str, int count, FILE* stream);
11/28
オブジェクトの整合
●
良い例
– stringクラスは文字列の情報をまとめて管理する。
オブジェクトの整合性は常に保たれる!
#include <string>
istream& getline(istream& input,string& str);
12/28
オブジェクトの整合
●
お互いに強く依存するオブジェクトはまとめて管
理する。
– 我々が通常構造体などを導入して行っていること。
●
単にまとめるだけでなく、オブジェクト全体が常に有
効な状態になるようにする。
– stringの保持する文字数とsize()とは連動する。
13/28
疎結合
●
各コンポーネント間の依存度をできるだけ下げる
– 問題を細かく分割して考えることができる。
– 変更のもたらす影響の範囲を把握しやすくなる。
– コンポーネントの再利用性が高まる。
14/28
間接メンバアクセス
●
悪い例
– オブジェクトのメンバに直接アクセスしている。
メンバの名前との依存関係がオブジェクトの外にま
で染み出してしまう!
#include <utility>
pair<int, int> pii;
pii.first = 0;
pii.second = 1;
15/28
間接メンバアクセス
●
良い例
– オブジェクトのメンバに間接的にアクセスしている。
メンバへのアクセスが抽象化され、自由度が増加!
#include <tuple>
tuple<int, int> tii;
get<0>(tii) = 0;
get<1>(tii) = 1;
16/28
間接メンバアクセス
●
メンバ変数より関数の方が疎結合
– 関数でアクセスするようにしておけば、変数の名前や表
現方法を変更しても、ユーザコードに影響しないように
できる。
17/28
非メンバ関数
●
悪い例
begin()やend()をメンバとしてもたないオブジェクト
に対して適用できない!
template <typename C, typename F>
void foreach(C&& c, F&& f) {
for (auto it = c.begin();
it != c.end(); ++it) {
f(*it);
}
}
18/28
非メンバ関数
●
良い例
begin()やend()のオーバーロードを追加すること
で、任意のオブジェクトに対して拡張できる!
template <typename C, typename F>
void foreach(C&& c, F&& f) {
for (auto it = begin(c);
it != end(c); ++it) {
f(*it);
}
}
19/28
非メンバ関数
●
メンバ関数より非メンバ関数の方が疎結合
– メンバ関数は対応するクラスとの依存関係がある。
– メンバ関数はthisポインタへのアクセス権を持つので、ク
ラスメンバとの依存性も高い。
20/28
const教
●
悪い例
sを書き換えるつもりがないのに書き換わっている!
int s[5] = {0, 1, 2, 3, 4};
int d[5] = {};
for (int i = 0; i < 5; ++i) {
s[i] = d[i];
}
21/28
const教
●
良い例
constをつければオブジェクトの不変性を明示でき
る!
const int s[5] = {0, 1, 2, 3, 4};
int d[5] = {};
for (int i = 0; i < 5; ++i) {
s[i] = d[i]; // compile error
}
22/28
const教
● const教 is 何?
– ローカル変数を含めたあらゆるオブジェクト・関数にでき
るだけconst修飾を施す思想のこと。
– constを付けずに書けるところでも、できるだけconstを
使って書くようにする。
– const教らしいコードの例
● constをつければ実際安心!
const int n = [](){
int tmp = 0;
cin >> tmp;
return tmp;
}();
23/28
例外安全
● C++は例外機構を持つ
– 例外が発生すると、従来のC的なエラーハンドリングで
は対処できない不整合が発生しうる。
– 例外が発生した時に、リソースリークやデータの不整合
が発生しない保証を例外安全という。
●
例外安全は難しい
– 難しいからと言って諦めては、良いコードは書けない。
●
例外安全でないコードはその時点で潜在的なバグを持つ。
– 例外安全を意識する姿勢は大切。
24/28
No new, No delete
●
悪い例
secondの確保に失敗した場合、firstがリークする!
struct X {
X() : first(new int(1)),
second(new int(2)) {}
~X() {
delete first;
delete second;
}
int *first, *second;
};
25/28
No new, No delete
●
良い例
IntPtrがそれぞれのリソースを管理するのでリーク
しない!
struct IntPtr {
IntPtr(int n) : ptr(new int(n)) {}
~IntPtr() { delete ptr; }
int *ptr;
};
struct X {
X() : first(1), second(2) {}
IntPtr first, second;
};
26/28
No new, No delete
●
もっと良い例
newやdeleteは自分で書かない!
template <typename T, typename... Args>
unique_ptr<T> make_unique(Args&&... args) {
return unique_ptr<T>(
new T(forward<Args>(args)...));
}
struct X {
X() : first(make_unique<int>(1)),
second(make_unique<int>(2)) {}
unique_ptr<int> first, second;
};
27/28
No new, No delete
● 訓練されたC++erはdeleteを書かない
– newもラップして使うので、直接書かない。
● デストラクタは1つの仕事だけをする
– デストラクタが複数の仕事をしている。
→ 対応する複数の初期化が存在する。
→ 複数の仕事は同時にはできない。
→ 一部しか初期化が済んでない段階で例外が投げら
れると不整合が発生する。
→ 例外安全でない。
28/28
まとめ
●
変更に耐えるコードを書くよう心がけよう!
– キーワード:一貫性・疎結合
– 例外安全は難しいけど、少しずつ慣れていこう。
●
良いコードは身を助く
– 将来困らないように(困らせないように)、今のうちに注意
しておこう。

Más contenido relacionado

La actualidad más candente

ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門Fixstars Corporation
 
2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)
2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)
2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)智啓 出川
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装MITSUNARI Shigeo
 
多倍長整数の乗算と高速フーリエ変換
多倍長整数の乗算と高速フーリエ変換多倍長整数の乗算と高速フーリエ変換
多倍長整数の乗算と高速フーリエ変換京大 マイコンクラブ
 
ニューラルチューリングマシン入門
ニューラルチューリングマシン入門ニューラルチューリングマシン入門
ニューラルチューリングマシン入門naoto moriyama
 
新しい並列for構文のご提案
新しい並列for構文のご提案新しい並列for構文のご提案
新しい並列for構文のご提案yohhoy
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプKohsuke Yuasa
 
プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜京大 マイコンクラブ
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性Hibiki Yamashiro
 
SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介MITSUNARI Shigeo
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23Masashi Shibata
 
高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!masakazu matsubara
 
不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarray不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarrayRyosuke839
 

La actualidad más candente (20)

実用Brainf*ckプログラミング入門編
実用Brainf*ckプログラミング入門編実用Brainf*ckプログラミング入門編
実用Brainf*ckプログラミング入門編
 
ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門
 
プログラムを高速化する話
プログラムを高速化する話プログラムを高速化する話
プログラムを高速化する話
 
2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)
2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)
2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装
 
多倍長整数の乗算と高速フーリエ変換
多倍長整数の乗算と高速フーリエ変換多倍長整数の乗算と高速フーリエ変換
多倍長整数の乗算と高速フーリエ変換
 
ニューラルチューリングマシン入門
ニューラルチューリングマシン入門ニューラルチューリングマシン入門
ニューラルチューリングマシン入門
 
直交領域探索
直交領域探索直交領域探索
直交領域探索
 
新しい並列for構文のご提案
新しい並列for構文のご提案新しい並列for構文のご提案
新しい並列for構文のご提案
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプ
 
プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
 
SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
 
高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!
 
不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarray不遇の標準ライブラリ - valarray
不遇の標準ライブラリ - valarray
 
Pietで競プロしよう
Pietで競プロしようPietで競プロしよう
Pietで競プロしよう
 

Más de 京大 マイコンクラブ

かわいくなろうとしたら語彙力が下がった話
かわいくなろうとしたら語彙力が下がった話かわいくなろうとしたら語彙力が下がった話
かわいくなろうとしたら語彙力が下がった話京大 マイコンクラブ
 
つくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタつくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタ京大 マイコンクラブ
 
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?京大 マイコンクラブ
 
ドット絵でプログラミング!難解言語『Piet』勉強会
ドット絵でプログラミング!難解言語『Piet』勉強会ドット絵でプログラミング!難解言語『Piet』勉強会
ドット絵でプログラミング!難解言語『Piet』勉強会京大 マイコンクラブ
 
DTM練習会2017第1.5回 「伴奏の付け方」
DTM練習会2017第1.5回 「伴奏の付け方」DTM練習会2017第1.5回 「伴奏の付け方」
DTM練習会2017第1.5回 「伴奏の付け方」京大 マイコンクラブ
 
暗号技術入門 秘密の国のアリス 総集編
暗号技術入門 秘密の国のアリス 総集編暗号技術入門 秘密の国のアリス 総集編
暗号技術入門 秘密の国のアリス 総集編京大 マイコンクラブ
 

Más de 京大 マイコンクラブ (20)

テキストファイルを読む💪 第1回
テキストファイルを読む💪  第1回テキストファイルを読む💪  第1回
テキストファイルを読む💪 第1回
 
かわいくなろうとしたら語彙力が下がった話
かわいくなろうとしたら語彙力が下がった話かわいくなろうとしたら語彙力が下がった話
かわいくなろうとしたら語彙力が下がった話
 
Common Lisp入門
Common Lisp入門Common Lisp入門
Common Lisp入門
 
つくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタつくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタ
 
Geometry with Unity
Geometry with UnityGeometry with Unity
Geometry with Unity
 
セミコロンレスc++
セミコロンレスc++セミコロンレスc++
セミコロンレスc++
 
エンジニアと健康
エンジニアと健康エンジニアと健康
エンジニアと健康
 
女の子になれなかった人のために
女の子になれなかった人のために女の子になれなかった人のために
女の子になれなかった人のために
 
もし太陽のコアがIntelCoreだったら
もし太陽のコアがIntelCoreだったらもし太陽のコアがIntelCoreだったら
もし太陽のコアがIntelCoreだったら
 
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
 
ドット絵でプログラミング!難解言語『Piet』勉強会
ドット絵でプログラミング!難解言語『Piet』勉強会ドット絵でプログラミング!難解言語『Piet』勉強会
ドット絵でプログラミング!難解言語『Piet』勉強会
 
No SSH (@nojima; KMC関東例会)
No SSH (@nojima; KMC関東例会)No SSH (@nojima; KMC関東例会)
No SSH (@nojima; KMC関東例会)
 
DTM練習会2017第1.5回 「伴奏の付け方」
DTM練習会2017第1.5回 「伴奏の付け方」DTM練習会2017第1.5回 「伴奏の付け方」
DTM練習会2017第1.5回 「伴奏の付け方」
 
hideya流 テストプレイ観察術
hideya流 テストプレイ観察術hideya流 テストプレイ観察術
hideya流 テストプレイ観察術
 
暗号技術入門 秘密の国のアリス 総集編
暗号技術入門 秘密の国のアリス 総集編暗号技術入門 秘密の国のアリス 総集編
暗号技術入門 秘密の国のアリス 総集編
 
Altseed
AltseedAltseed
Altseed
 
C#でゲームを作る2016 第8回
C#でゲームを作る2016 第8回C#でゲームを作る2016 第8回
C#でゲームを作る2016 第8回
 
C#でゲームを作る2016 第7回
C#でゲームを作る2016 第7回C#でゲームを作る2016 第7回
C#でゲームを作る2016 第7回
 
C#でゲームを作る2016 第5回
C#でゲームを作る2016 第5回C#でゲームを作る2016 第5回
C#でゲームを作る2016 第5回
 
C#でゲームを作る2016 第3回
C#でゲームを作る2016 第3回C#でゲームを作る2016 第3回
C#でゲームを作る2016 第3回
 

よいコード、わるいコード