SlideShare a Scribd company logo
1 of 65
リーダブルコード
 読み易いコードの書き方
リーダブルコード

• Dustion Boswell,
  Trevor Foucher 著

• 角征典 訳

• 1-2週間で読める

•  他の書籍より読み易い
  のでオススメ
リーダブルコードとは? 

• リーダブルコード、つまり読み易いコード

• 読み易いと何がいいの?

• 他人が最短時間で理解できるようになる
 (他人とは半年後の自分も含む)
理解とは?

• 仕様がわかる     

• バグがわかる

• 変更方法がわかる

• 他との連携する方法がわかる
理解しやすいコードの
   書き方
表面上の問題
ネーミング 
名前に情報を詰め込む

• 明確な単語を選ぶ

 Getじゃなくてfetchとかdownloadとかにする

 例)send     deliver, dispatch, distribute

     find       search, extract, locate 

     start      launch, create, begin, open

     make     create, set up, build, generate, add, new
汎用的な名前は避ける

• tmpとかresultとか     

• でもローカル変数で使う場所が狭ければ
 使ってもいいよ!

• ループのイテレータとかはi・j・kでOK
名前に情報を追加する

• time -> time_ms
• size -> size_mb
 名前の長さ



• スコープが小さければ、短い名前でよい
名前のフォーマット(例
• kConstantName          定数

• CONSTANT_NAME     マクロ

• ClassName                   クラス

• methodName               メソッド

• variable_name             変数
誤解されない名前(例     
• min, max     限界値を含む

• first, last      範囲指定

• begin, end   包含、排他的範囲(endは含まれない

• bool             isやhasをつける、否定型にしない

• get             getは軽量アクセサである

             getで重くなるような計算してはいけない
美しさ
余白、配置、順序
余白


• インデント、空行によってブロックや段
 落を整える(縦のラインを意識

• 論理的な区切りができる
配置


• 同様の処理はシルエットを える

• メソッドを使って える
 DRY化にもなる
順序

• 順序は変えない

• A・B・Cとあった情報をB・C・Aにして
 はいけない

• 一貫性が大事
コメント
コメントすべきこと
 コメントすべきでは"ない"こと

• コードからわかることを書かない

• コメントのためのコメントを書かない

 例)関数には必ずコメントを書かなければならない

   // 名前を取得する  ←意味がない

   getName();

• ひどいコードの場合はコメントを書くより修正する
自分の考えを記録する

• 映画のコメンタリーのようなもの

• コードを書いた時の背景や理由がわかる

• Why, How, Whatは特にこだわらなくて
 もよい
欠陥をコメントする



• // TODO:もっと高速化が必要

• // XXX:破壊的なメソッド!
 全体像をコメントする


• // このクラスはキャッシュです、システ
 ムのことは関知しません

• // このクラスはファイルシステムに関す
 るヘルパー関数を提供します
要約をコメントする

• // ロックを取得

• // ユーザの情報をDBから読む

• // 情報をファイルに書き出す

• // ロックを開放
正確で完結に
完結に書く



• 領域に対する情報の比率が高くなければ
 いけない
代名詞はさける    



• それ、これ
 ⇒ データを、価格を
 正確に記述する



• // 行数を返す
 ⇒   // 改行文字(n)を数える
実例を使う



• // 例) Strip("abba/a/ba", "ab") => "/a/"
コードの意図を書く



• // 逆順で表示する
 ⇒ // 値段の高い順に表示する
ループとロジックの単純化
制御フロー
自然に書く

• if( length > 10 )    ←こっちのほうがいい
 if(10 <= length)

• 左側:調査対象の式、変化する

• 右側:比較対象の式、あまり変化しない
if/elseブロックの書き方


• 否定形よりも肯定形

• 単純な条件を先に

• 関心を引く条件や目立つ条件を先に
三項演算子



• 使うならわかりやすく
関数から早く返す



• ガード節とか
ネストは浅く



• 早めに返す、内部のネストを関数化する
式の分割



• 巨大な式を飲み込みやすい大きさに
説明変数を導入する


• line.split(":").[0] == “Bob”
• user_name = line.split(":").[0];
  user_name == “Bob”
ロジックを書き直す

• ド・モルガンの法則を使う

• 反対にすると、簡単になるかもしれない

• 重なる範囲を探す
 ⇒ 重ならないケースを探す
変数と読みやすさ

• 変数を削除する

• 変数のスコープを縮める

• 変数は一度だけ書き込む

 変数がどこで書き変えられたかを追跡するのは難しい

 constやfinalでイミュータブルにするのは有効
コードの再構成
無関係の下位問題

1. このコードの高レベルな目標は何かを見定める

2. 高レベルの目標に直接関係あるのか、無関係の
下位問題なのか見分ける

3. 無関係の下位問題を抽出する
無関係の下位問題


• プロジェクト固有のコードから汎用コードを
 分離すること

• ヘルパーをたくさん作る
1度に1つのことを

• コードは1つずつタスクを処理しなけれ
 ばならない

• タスクは小くできる

• そのコードで行なわれているタスクを列
 挙し、分割し、適用させる
コードに思いを込める



• ロジックを簡単な言葉で説明する、それ
 に合せてコードも書く
短いコード
質問と要求の分割

• 「その機能の実装について悩まない、
 きっと必要ないから」

•  過剰な機能を抑えて、単純に実装する

• 全てのプログラムがあらゆる入力に対応
 し、高速である必要はない
コードを小く保つ



•  定期的に見直す
ライブラリを使う

• 平均的なエンジニアが1日に書く"出荷用"のコー
 ドは10行

• 設計・デバッグ・修正・文章・最適化・テストな
 どのコストを含んだ値

• なるべくコードを再利用をする
  Unixのコマンドを使う


• 実装するよりコマンドを直接呼んだ方が
 いい

•  awkとかegrepとか便利
テスト
テストも読み易く
 保守しやすいものにする

• テストが複雑だと…

• 本物のコードを修正しなくなる

• テストを追加しなくなる
最小のテストを作る  



• 入出力のテストなどは1行でかけると良い
独自のミニ言語を実装する



• テスト用に実装しちゃう

• DSLとか
エラーメッセージ

• エラーが発生しました!
 じゃわからない

• エラー時の変数の値を出力すると良い

• assertを書き変えてカスタマイズするの
 もアリ
テストの入力値


• コードをテストする最も単純な入力値の
 組み合せにする

 checkScore("999.97, -246, 3", )
 checkScore("1e100, -1, 2")
1つの機能で複数のテスト

•  小さなテストを複数作る
 assert(“Barack”, person.firstName)

 assert(“Obama”, person.familyName)

 assert(“male”, person.sex)
テストの名前は適切に



•  テストからしか呼ばれないので、冗長で
 説明的でよい
やりすぎ注意  

• テストのために本物のコードを犠牲にする

• テストのカバレッジを100%にしないと気が
 すまない     

 90%でよい、残りの10%はUIやどうでもい
 いエラーである
まとめ
• ネーミング

 わかりやすい名前をつける

• 分割

  飲み込みやすい大きさに分割

• コメント

 そのコードの狙いは、なぜそのコードを書いたのかを書く

• スタイル(見た目)

 インデントやブロックを   えて見た目で理解できるように
 理解しやすいコードを書こう!
END

More Related Content

What's hot

それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?Yoshitaka Kawashima
 
シリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのかシリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのかAtsushi Nakada
 
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8Koichiro Matsuoka
 
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24Shin Ohno
 
VPCのアウトバウンド通信を制御するためにおさえておきたい設計ポイント
VPCのアウトバウンド通信を制御するためにおさえておきたい設計ポイントVPCのアウトバウンド通信を制御するためにおさえておきたい設計ポイント
VPCのアウトバウンド通信を制御するためにおさえておきたい設計ポイントTakuya Takaseki
 
ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割
ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割
ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割Recruit Lifestyle Co., Ltd.
 
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるGoのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるpospome
 
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力ThinReports
 
Fault, Error, Failure の違い
Fault, Error, Failure の違いFault, Error, Failure の違い
Fault, Error, Failure の違いMizuhiro Kaimai
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪Takuto Wada
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門masayoshi takahashi
 
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発Yahoo!デベロッパーネットワーク
 
Beyond the Twelve-Factor App
Beyond the Twelve-Factor AppBeyond the Twelve-Factor App
Beyond the Twelve-Factor AppKazuya Takahashi
 
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptxネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptxShota Shinogi
 
Keycloak拡張入門
Keycloak拡張入門Keycloak拡張入門
Keycloak拡張入門Hiroyuki Wada
 
k8s初心者が gRPC × envoyを導入したら色々苦労した話 #yjbonfire
k8s初心者が gRPC × envoyを導入したら色々苦労した話 #yjbonfirek8s初心者が gRPC × envoyを導入したら色々苦労した話 #yjbonfire
k8s初心者が gRPC × envoyを導入したら色々苦労した話 #yjbonfireYahoo!デベロッパーネットワーク
 
[External] 2021.12.15 コンテナ移行の前に知っておきたいこと @ gcpug 湘南
[External] 2021.12.15 コンテナ移行の前に知っておきたいこと  @ gcpug 湘南[External] 2021.12.15 コンテナ移行の前に知っておきたいこと  @ gcpug 湘南
[External] 2021.12.15 コンテナ移行の前に知っておきたいこと @ gcpug 湘南Google Cloud Platform - Japan
 
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDayマイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay都元ダイスケ Miyamoto
 
実録Blue-Green Deployment導入記
実録Blue-Green Deployment導入記実録Blue-Green Deployment導入記
実録Blue-Green Deployment導入記Hiroyuki Ohnaka
 

What's hot (20)

それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?
 
シリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのかシリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのか
 
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
 
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
Mercari JPのモノリスサービスをKubernetesに移行した話 PHP Conference 2022 9/24
 
VPCのアウトバウンド通信を制御するためにおさえておきたい設計ポイント
VPCのアウトバウンド通信を制御するためにおさえておきたい設計ポイントVPCのアウトバウンド通信を制御するためにおさえておきたい設計ポイント
VPCのアウトバウンド通信を制御するためにおさえておきたい設計ポイント
 
Google Cloud で実践する SRE
Google Cloud で実践する SRE  Google Cloud で実践する SRE
Google Cloud で実践する SRE
 
ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割
ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割
ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割
 
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるGoのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
 
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
Ruby向け帳票ソリューション「ThinReports」の開発で知るOSSの威力
 
Fault, Error, Failure の違い
Fault, Error, Failure の違いFault, Error, Failure の違い
Fault, Error, Failure の違い
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
 
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
 
Beyond the Twelve-Factor App
Beyond the Twelve-Factor AppBeyond the Twelve-Factor App
Beyond the Twelve-Factor App
 
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptxネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
 
Keycloak拡張入門
Keycloak拡張入門Keycloak拡張入門
Keycloak拡張入門
 
k8s初心者が gRPC × envoyを導入したら色々苦労した話 #yjbonfire
k8s初心者が gRPC × envoyを導入したら色々苦労した話 #yjbonfirek8s初心者が gRPC × envoyを導入したら色々苦労した話 #yjbonfire
k8s初心者が gRPC × envoyを導入したら色々苦労した話 #yjbonfire
 
[External] 2021.12.15 コンテナ移行の前に知っておきたいこと @ gcpug 湘南
[External] 2021.12.15 コンテナ移行の前に知っておきたいこと  @ gcpug 湘南[External] 2021.12.15 コンテナ移行の前に知っておきたいこと  @ gcpug 湘南
[External] 2021.12.15 コンテナ移行の前に知っておきたいこと @ gcpug 湘南
 
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDayマイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
マイクロサービス時代の認証と認可 - AWS Dev Day Tokyo 2018 #AWSDevDay
 
実録Blue-Green Deployment導入記
実録Blue-Green Deployment導入記実録Blue-Green Deployment導入記
実録Blue-Green Deployment導入記
 

Similar to リーダブルコード

リーダブルコード 1.0'
リーダブルコード 1.0'リーダブルコード 1.0'
リーダブルコード 1.0'Yamamura Takashi
 
Web本文抽出 using crf
Web本文抽出 using crfWeb本文抽出 using crf
Web本文抽出 using crfShuyo Nakatani
 
プログラマ人生論
プログラマ人生論プログラマ人生論
プログラマ人生論ymmt
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Rubymitim
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースHajime Yanagawa
 
良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方Shigenori Sagawa
 
ロジカル資料作成講座【作成編】株式会社okunote
ロジカル資料作成講座【作成編】株式会社okunoteロジカル資料作成講座【作成編】株式会社okunote
ロジカル資料作成講座【作成編】株式会社okunoteTakamasaTayano
 
チーム開発をうまく行うためのコーディング規約論
チーム開発をうまく行うためのコーディング規約論チーム開発をうまく行うためのコーディング規約論
チーム開発をうまく行うためのコーディング規約論Kentaro Matsui
 
ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方増田 亨
 
プログラミングNet framework3のお題
プログラミングNet framework3のお題プログラミングNet framework3のお題
プログラミングNet framework3のお題Kazushi Kamegawa
 
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについてNobukazu Hanada
 
ドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装までドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装まで増田 亨
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, CodereadingHiro Yoshioka
 
C# design note sep 2014
C# design note sep 2014C# design note sep 2014
C# design note sep 2014信之 岩永
 
2018年度 若手技術者向け講座 リファクタリング
2018年度 若手技術者向け講座 リファクタリング2018年度 若手技術者向け講座 リファクタリング
2018年度 若手技術者向け講座 リファクタリングkeki3
 
Programming camp code reading
Programming camp code readingProgramming camp code reading
Programming camp code readingHiro Yoshioka
 
フロント作業の効率化
フロント作業の効率化フロント作業の効率化
フロント作業の効率化Yuto Yoshinari
 

Similar to リーダブルコード (20)

リーダブルコード 1.0'
リーダブルコード 1.0'リーダブルコード 1.0'
リーダブルコード 1.0'
 
Web本文抽出 using crf
Web本文抽出 using crfWeb本文抽出 using crf
Web本文抽出 using crf
 
プログラマ人生論
プログラマ人生論プログラマ人生論
プログラマ人生論
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Ruby
 
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェース
 
良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方
 
ロジカル資料作成講座【作成編】株式会社okunote
ロジカル資料作成講座【作成編】株式会社okunoteロジカル資料作成講座【作成編】株式会社okunote
ロジカル資料作成講座【作成編】株式会社okunote
 
チーム開発をうまく行うためのコーディング規約論
チーム開発をうまく行うためのコーディング規約論チーム開発をうまく行うためのコーディング規約論
チーム開発をうまく行うためのコーディング規約論
 
ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方
 
プログラミングNet framework3のお題
プログラミングNet framework3のお題プログラミングNet framework3のお題
プログラミングNet framework3のお題
 
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
 
ドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装までドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装まで
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, Codereading
 
Tdd
TddTdd
Tdd
 
C# design note sep 2014
C# design note sep 2014C# design note sep 2014
C# design note sep 2014
 
2018年度 若手技術者向け講座 リファクタリング
2018年度 若手技術者向け講座 リファクタリング2018年度 若手技術者向け講座 リファクタリング
2018年度 若手技術者向け講座 リファクタリング
 
Programming camp code reading
Programming camp code readingProgramming camp code reading
Programming camp code reading
 
第1回python勉強会
第1回python勉強会第1回python勉強会
第1回python勉強会
 
フロント作業の効率化
フロント作業の効率化フロント作業の効率化
フロント作業の効率化
 

リーダブルコード

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n