独学Ruby -基礎③-
引き続き、Rubyの基礎その3。
Contents
- インスタンスメソッド
- クラスメソッド
- 関数的メソッド ... print文とか
# インスタンスメソッドの例 array = "10, 20, 30, 40" print array,"\n" array = "10, 20, 30, 40".split(",") print array,"\n" print array[0], "-",array[1] , "-",array[2] , "-",array[3], "\n" # クラスメソッドの例 # 新しい配列を作成 a = Array.new
メソッドの定義
メソッド名にはアルファベット、数字、アンダースコアを使うことができる。
数字で始めるのはNG。
@myNumber = 0 def GetMyNumber() return @myNumber end def SetMyNumber(number=100) @myNumber = number end
呼び出し元
require_relative "mymethod.rb" my_number = GetMyNumber() print my_number,"\n" SetMyNumber(10) my_number = GetMyNumber() print my_number,"\n" SetMyNumber() my_number = GetMyNumber() print my_number,"\n"
引数を省略したときにデフォルト値を設定することもできる。
複数の戻り値を返すことも可能
def GetValue() return 1, 2 end results = Array.new results = GetValue() print results
オブジェクトが属しているクラスを知る
.classメソッド
ary = Array.new p ary.class str = "String" p str.class
オブジェクトがクラスのインスタンスかどうかを知る
.instance_of_?(クラス名)
ary = Array.new p ary.instance_of?(Array) str = "String" p str.instance_of?(String)
クラスの定義
class文
クラスを作るときの注意点
クラス名は必ず大文字で始めること。
# 時計クラス(スーパークラス) class Clock # 定数 Version = "1.0" # クラス変数 @@name = "Clock" # インスタンス変数 @current_time = Time.new # 現在時刻で初期化 # クラスメソッド def Clock.getVersion() return Version end def Clock.getName() return @@name end # newメソッドコール時に実行される def initialize(cur_time=Time.new) print "Clock Class Version is ", Version,"\n" @current_time = cur_time end # インスタンスメソッド def setTime(time) @current_time = time end def getTime() return @current_time end # アクセスメソッド def current_time return @current_time end def current_time=(time) @current_time = time end end
initializeメソッドを定義すると、newメソッド時に実行される。
require_relative "clock" # クラスメソッド p Clock.getVersion() p Clock.getName() # 定数のGet p Clock::Version # インスタンス生成 clock = Clock.new() current_time = clock.getTime() p current_time # インスタンスメソッドでSet/Get clock.setTime(Time.local(2019,1,1,12,30,10,0)) current_time = clock.getTime() p current_time # アクセスメソッドでSet/Get clock.current_time = Time.new() p clock.current_time
クラスの拡張
たとえばStringクラスを定義し、メソッドを拡張してみる。
string.rb
class String def func() print "func method of String\n" end end
ext_string.rb
class String def extFunc() print "extFunc of String(Extention)\n" end end
str.rb(実行元)
require_relative "string" require_relative "ext_string" str = String.new str.func() # string.rbで定義 str.extFunc() # ext_string.rbで定義
メソッド呼び出しの制限
アクセス制限レベル | 説明 |
---|---|
public | メソッドをインスタンスメソッドとして使えるように公開する |
private | メソッドをクラス内部でだけ使えるようにする |
protected | メソッドをクラス内部で使えるようにする 同一クラス内ではインスタンスメソッドとしても使える |
# アクセス制限 class AccessTest def pubMethod print "called Public Method\n" end public :pubMethod def privateMethod print "called Private Method\n" end private :privateMethod def protectedMethod print "called Protected Method\n" end protected :protectedMethod end
require_relative "access_test" access_test_obj = AccessTest.new() # インスタンスメソッドとして直接呼べる access_test_obj.pubMethod() # インスタンスメソッドとして直接呼べない access_test_obj.privateMethod() # Error # インスタンスメソッドとして直接呼べない access_test_obj.protectedMethod() # Error
Protectedメソッドへのアクセス
# AccessTestクラスを継承する require_relative "access_test" class AccessSubTest < AccessTest def hoge privateMethod() end end
require_relative "access_sub_test" access_sub_test_obj = AccessSubTest.new() access_sub_test_obj.hoge()
アクセス制限の記述方法
上のようにpublic :メソッド名という形で書くこともできるが、
次のようにするとまとめて同じアクセス制限にできる。
# アクセス制限 class AccessTest public #これ以降のメソッドはPublic def pubMethod1 print "called Public Method\n" end def pubMethod2 print "called Public Method\n" end private #これ以降のメソッドはPrivate def privateMethod1 print "called Private Method\n" end def privateMethod2 print "called Private Method\n" end protected #これ以降のメソッドはProtected def protectedMethod1 print "called Protected Method\n" end def protectedMethod2 print "called Protected Method\n" end end
クラスの継承
class クラス名 < スーパークラス名 ... end
すでに上のprotectedメソッドのアクセス確認で書いたけど。
# スーパークラス class SuperClass def initialize() print "Create Super Class.\n" end def func1() print "func1 of SuperClass.\n" end def func2() print "func2 of SuperClass.\n" end end
# サブクラス require_relative "super_class" class SubClass < SuperClass def initialize() print "Create SubClass.\n" end def func2() print "func2 of SubClass.\n" end end
require_relative "sub_class" obj1 = SuperClass.new() obj2 = SubClass.new() obj1.func1() obj2.func1() obj1.func2() obj2.func2()
実行結果。
Create Super Class. Create SubClass. func1 of SuperClass. func1 of SuperClass. func2 of SuperClass. func2 of SubClass.
以上、。
独学Ruby -基礎②-
引き続き、Rubyの基礎その2。
Contents
データを表現する基本単位(オブジェクト)。
- 数値オブジェクト(Numeric)
- 文字列オブジェクト(String)
- 配列オブジェクト (Array)
- ハッシュオブジェクト(Hash)
- 正規表現オブジェクト(Regexp)
- ファイルオブジェクト(File) などなど
変数の種類
- ローカル変数 ... 先頭がアルファベットの小文字か「_」で始まる
- グローバル変数 ... 先頭が「$」で始まる
- インスタンス変数 ... 先頭が「@」で始まる
- クラス変数 ... 先頭が「@@」で始まる
- 擬似変数 ... true, false, self, nil などの予約語
変数のスコープ確認
# グローバル変数 $globalVariable = 111 # ローカル変数 localVariable = 222 # sub.rb呼び出し require_relative "sub" p $globalVariable p localVariable
#グローバル変数に代入 $globalVariable = 777 #ローカル変数に代入 localVariable = 555
globalVariableは111ではなく777となる。
localVariableは555ではなく222のまま。
定数
先頭がアルファベットの大文字で始まるもの
実際に定数宣言後に別の値を代入するとWarningが宣告される。
値は書き換わる。
scopetest.rb:17: warning: already initialized constant CONST_VARIABLE scopetest.rb:14: warning: previous definition of CONST_VARIABLE was here
BEGIN
END など
- if
- unless
- case
number = ARGV[0].to_i #------------------------- # if文 #------------------------- if number == 1 print "number is 1.\n" elsif number == 2 print "number is 2.\n" else print "number is ", number , "\n" end #------------------------- # unless文 #------------------------- unless (number == 1) || (number == 2) print "number is ", number , "\n" else print "number is 1 or 2.\n" end #------------------------- # case文 #------------------------- case number when 1 then print "number is 1.\n" when 2 then print "number is 2.\n" else print "number is ", number, ".\n" end # 複数の条件を指定することもできる case number when 1, 2 then print "number is 1 or 2.\n" else print "number is ", number, ".\n" end # クラス判定 array = ["moji", 1, nil] array.each do |obj| case obj when String print "obj is a String.\n" when Numeric print "obj is a Numeric.\n" else print "obj is someting.\n" end end
if修飾子とunless修飾子
実行したい式の後ろに条件式を書ける。
number = ARGV[0].to_i print "number is 0.\n" if number == 0 print "number is not 0.\n" if number != 0
- 構文
- メソッド
命令 | 構文 | メソッド |
---|---|---|
times | ○ | |
for | ○ | |
while | ○ | |
until | ○ | |
each | ○ | |
loop | ○ |
timesメソッド
2通りの書き方がある。
# timesメソッド # 書き方1 3.times do print "loop.\n" end # 書き方2 3.times { print "loop.\n" } # 繰り返し回数を知る 3.times do |i| print "loop[", i, "].\n" end
for文
#ループ回数を指定する方法 from_idx = 3 to_idx = 5 for idx in from_idx..to_idx print idx,"\n" end #範囲オブジェクトでループ回数を指定する方法 array = [1, 2, 3] for var in array print var,"\n" end
while文
i = 1 while i < 3 print i,"\n" i += 1 end
until文
i = 1 until i > 3 print i,"\n" i += 1 end
eachメソッド
names = ["awk", "Perl", "Python", "Ruby"] #書き方1 names.each do |name| print name, "\n" end #書き方2 names.each { |name| print name, "\n" } #書き方3 (1..5).each do |num| print num, "\n" end
loopメソッド
無限ループにならないように繰り返しの制御を。
#loopメソッド + break i = 0 loop do if i == 5 then break else i += 1 end print i, "\n" end
繰り返し制御
- break
- next
- redo
language = ["C", "C++", "Ruby", "Python", "Java"] print language,"\n" # break language.each do |lang| case lang when /^C/ then print "C Series language =>", lang, "\n" when /Ruby/ then print "Ruby\n" else print "Other" break; end end print "\n---------------\n" # next language.each do |lang| if lang == "C++" then print "Skip C++\n" next end print lang,"\n" end print "\n---------------\n" # redo language.each do |lang| if lang == "C++" then print "C++ => C#\n" lang = "C#" redo end print lang,"\n" end
以上。
独学Ruby -基礎①-
まずは基礎の基礎から。
Contents
・配列(Array) ・ハッシュとシンボル ・正規表現(パターンマッチング) ・コマンドライン ・ファイルの読み込み
paiza.io (https://paiza.io/ja/projects/new)
Ruby MSI Packages (https://www.artonx.org/data/asr/)
ではさっそくRubyを動かしてみよう
まずはお決まりのHelloWorldから。どれも同じ出力結果。
print("Hello World\n") print "Hello World\n" print "Hello", " ", "World", "\n" puts "Hello World\n"
文字列と数値を意識して出力してくれるpメソッド。
3puts "100" puts 100
コメントを現す記号は#。行末までコメントになる。
# コメント
=beginと=endで囲まれた範囲もコメント。
=begin コメント コメント =end
制御構造を分類すると、
- 逐次処理
- 条件判断 (if then end)
- 繰り返し (while times)
- 例外処理
my_weight_kg = 80 your_weight_kg = 70 # 条件判断 if my_weight_kg > your_weight_kg then print "私の体重のほうが重い" else print "あなたの体重のほうが重い" end # 繰り返し i = 1 while i <= 10 print i, "\n" i = i + 1 end 10.times do print "A" end
メソッドの作成について。
# メソッド定義 def hello print "Hello World\n" end # メソッド呼び出し hello
自作したrubyファイル(.rb)を呼び出す
def hello print("Hello World\n") end
hello.rbのhelloメソッドを呼び出すためにrequireメソッドを使うのだが、自作したrbファイルはrequire_relativeメソッドがよさそう。requireメソッドはPathが通っていないとダメっぽい。
require_relative "hello" hello()
Rubyで書籍の購入リストを作ることを考えてみる。購入リストの項目は以下とする。
- 購入日
- 種別(コンピュータ書、ノンフィクション、小説など)
- 書名
- 著者名
- 出版社
- ISBN
- 金額
例)
パラメータ名 | 値の例 | データ型 |
---|---|---|
購入日 | 2019年1月17日 | 日付 |
種別 | コンピュータ書 | 文字列 |
書名 | たのしいRuby 第3版 | 文字列 |
著者名 | 高橋征義、後藤裕蔵 | 文字列 |
出版社 | Softbank Creative | 文字列 |
ISBN | 978-4-7973-5740-0 | 文字列 |
金額 | 2640 | 数値 |
配列(Array)
- 生成
- 取り出し
- 代入
- 繰り返し
# 空配列の生成 name = [] p name # 初期値付き配列の生成 name = ["A", "B", "C"] p name # 配列からオブジェクトを取り出す print("[0]=", name[0], "[1]=", name[1], "[2]=", name[2], "\n") # オブジェクトの代入 name[0] = "D" print("[0]=", name[0],"\n") # 配列には異なるデータ型のオブジェクトを混ぜられる mix = ["String", 1, "A", 2, "B"] p mix # 配列と繰り返し mix.each do |var| print(var , "\n") end
ハッシュ(Hash)とシンボル(Symbol)
- 生成
- 取り出し
- 代入
- 繰り返し
# ハッシュテーブルの生成] hash_table = {:sym1 => 0, :sym2 => "string"} p hash_table # ハッシュテーブルからの取り出し print("[0] = ", hash_table[:sym1], "\n") print("[1] = ", hash_table[:sym2], "\n") # ハッシュテーブルへの格納 hash_table[:sym1] = 1 hash_table[:sym2] = "index" hash_table[:sym3] = "new" print("[0] = ", hash_table[:sym1], "\n") print("[1] = ", hash_table[:sym2], "\n") print("[2] = ", hash_table[:sym3], "\n") # データ型も変更可能 hash_table[:sym3] = 1 print("[2] = ", hash_table[:sym3], "\n") # 繰り返し hash_table.each do |symbol, var| print(symbol, "=", var, "\n") end
# パターンマッチング # 先頭で一致 pos = /Ruby/ =~ "Ruby" print(pos, "\n") # 中間で一致 pos = /Ruby/ =~ "iRuby" print(pos, "\n") # 一致しない pos = /Ruby/ =~ "rUBY" print(pos, "\n")
nil(ニル)
- オブジェクトが存在しないことを示す値
コマンドライン引数ARGV[]。
print "1番目の引数:", ARGV[0], "\n" print "2番目の引数:", ARGV[1], "\n" print "3番目の引数:", ARGV[2], "\n"
文字列を数値に変換(to_iメソッド)
print ARGV[0], "\n" num = ARGV[0].to_i print num
ファイル読み込み
- openメソッド
- readメソッド
- closeメソッド
- getsメソッド
一度にテキストファイルをロードする
# ARGV[0] = FileName(*.txt) # Case1 filename = ARGV[0] file = open(filename) text = file.read print text file.close # Case2 filename = ARGV[0] text = File.read(filename) print text # Case3 print File.read(ARGV[0])
一行ずつ読み込む
# ARGV[0] = FileName filename = ARGV[0] file = open(filename) # 1行ずつ読み出す while textline = file.gets print textline end file.close
特定パターンの行のみを出力する
# ARGV[0] is Pattern String # ARGV[1] is File Name pattern = Regexp.new(ARGV[0]) filename = ARGV[1] file = open(filename) while textline = file.gets if pattern =~ textline print textline end end file.close
以上。
Python3.7.2 on Windows
ゼロから作るDeepLearning2を独学するためPythonをインストールしました。
本書で使用するプログラミング言語とライブラリは以下。
-
-
NumPy
-
Matplotlib
-
CuPy (オプション) ... 今回は使用しない
本書のサンプルコードは以下。
以下のサイトを参考にします。
Python 3.7.2 Windows 64Bit版 (2019/1/19 最新)をダウンロード。
https://www.python.org/ftp/python/3.7.2/python-3.7.2-amd64.exe
インストール確認は、コマンドプロンプトを開いて「python -V」を実行。
Python 3.7.2と表示されればOK。
-
NumPy
-
Matplotlib
コマンドプロンプトで以下を実行する。
> python -m pip install numpy
> python -m pip install matplotlib
これでOK。
ということで早速、独学スタート!
以上。
攻撃から工場を守る産業制御システム・セキュリティ
セキュリティベンダーのSymantecが工場向けにセキュリティソリューションを推し進めている。競合のトレンドマイクロやマカフィーも同様。各社制御セキュリティに詳しくない現場にとって利用しやすいソリューションを提案している。(らしい)
(by Kunal Agarwal@Symantec)
-
ネットワーク
次に、この攻撃ベクトルに対してSymantecが提案しているソリューションについて。
Symantecの提案するソリューション
USBスキャンクリーニングステーション
-
工場で利用するPCはUSBスキャニングステーションでチェック済のUSBメモリだけを認識できるドライバを組み込む
データシート
https://www.symantec.com/content/dam/symantec/docs/data-sheets/usb-scanning-data-sheet.pdf
クリティカルシステムプロテクション(CSP)
-
-
組み込み機器などに適用できように軽量化されている
-
工場で稼働しているレガシーな端末を最新機器のようにネットワーク利用できる
データシート
どちらも現場の技術者の敷居を下げるため、シンプルさに重きを置いている。
Symantec Blogs
以上。
制御セキュリティがなぜアツいのか!?
今年度(2019)は制御セキュリティに関する話題を収集するためのアンテナを張ろうかと思う。今日はMONOistから「なぜ今、制御システムセキュリティがアツいのか?」という特集を紹介する。
制御システムのセキュリティが注目を浴びている理由
-
制御システムを取り巻く環境の変化
-
制御システムを狙った攻撃(マルウェアの登場)
-
制御システムセキュリティに対する国レベルでの取り組み開始
何年か前にドイツのテクノロジー企業シーメンスのPLCが攻撃にあった。
確かそのときのマルウェアがStuxnet。イランの核施設の破壊も狙ったとか。
https://wired.jp/2012/06/04/confirmed-us-israel-created-stuxnet-lost-control-of-it/
この工場などの制御システムを狙ったマルウェアの登場で国レベルで対策が必要と考えられ始めた。工場の閉じた世界もIoTなどの普及に伴い外部のネットワークと密接に絡み始めた昨今、制御システムのセキュリティ対策が急務とされる所以である。
制御システムを取り巻く環境の変化
かつてはRS232Cなどのシリアル通信インタフェースが一般的だったが、いまではイーサネットが当たり前になってきており、EtherNet/IP、EtherCATなどの通信規格も利用されている。工場のLAN化が進みセキュリティの面に配慮せざるを得なくなっている。また制御システムに汎用OSが使われることも増え、脆弱性を狙った攻撃に対しても防御しなければならなくなっている。
制御システムを狙った攻撃の登場
制御システムを狙った代表的なマルウェア。
マルウェア名 | 概要 |
---|---|
Stuxnet | インターネットまたはUSBメモリから感染し潜伏する。 感染したコンピュータに接続するとパンデミックを引き起こす。 イランの核施設を攻撃するためにアメリカとイスラエルが開発した。 |
Slammer | SQLサーバ2000の不具合を利用して UDPポート1434に対して攻撃するワーム。 |
Zotob | Windows2000にターゲットとし プラグ案とプレイ機能の脆弱性をついて侵入する。 自動的に再起動するなどの症状を引き起こす。 |
Conficker |
ConfickerのようなUSBメモリを介して感染するタイプのマルウェアが2008年頃から今もなお猛威を振るっているらしい。
こういった背景もあってトレンドマイクロなどの大手セキュリティソフトウェア会社はさまざまなセキュリティソリューションを提案している。
https://www.trendmicro.com/ja_jp/about/trendpark/es-smartfactory-expo-201803-01-01.html
制御システムセキュリティに対する国レベルの取り組み開始
2013年にオバマ大統領が重要インフラに対するサイバー攻撃に対処するように大統領令を発行。時を同じくして欧州でもセキュリティ強化をインフラ事業者に求めた。
では我が日本国はどうか・・・
https://www.jssec.org/dl/20180309_Hiroshi_itou.pdf
情報セキュリティの10大脅威
順位 | 脅威 |
---|---|
1 | 標的型攻撃による情報流出 |
2 | ランダムウェアによる被害 |
3 | ビジネスメール詐欺 |
4 | 脆弱性対策情報の公開に伴い公知となる脆弱性の悪用増加 |
5 | セキュリティ人材の不足 |
6 | ウェブサービスからの個人情報の窃取 |
7 | IoT機器の脆弱性の顕在化 |
8 | 内部不正による情報漏えいとそれに伴う業務停止 |
9 | サービス妨害攻撃によるサービス停止 |
10 | 攻撃のビジネス化(アンダーグラウンドサービス) |
経済産業省の取り組み
-
IPAが監査・監視
-
産業分野別のセキュリティポリシーの設定、国際標準化
-
サイバーセキュリティガイドラインの策定
-
重要インフラ事業者のリスク評価事業
-
情報供給、初動対応支援体制の強化
-
人材育成
-
国際連携(アメリカ・欧州など)
これから
すでに「工場は閉じた世界だからセキュリティは大丈夫」という神話は崩れている。
制御システム技術者としてこの流れをどのように捉えるか。
制御システムセキュリティはすでにビジネス化しつつある。。。。
リーダブルコード
リーダブルコード
O'REILLY Japan
本書のテーマ
読みやすいコードを書くコツを会得しよう!
読みやすさの基本定理
コードは他の人または(数カ月後の自分)が最短時間で理解できるように書くべし!
表面上の改善
Check | 鍵となる考え | ポイント |
---|---|---|
□ | 名前に情報を詰め込む | 明確な単語を選ぶ 汎用的な名前を避ける 抽象的な名前よりも具体的な名前を使う 接尾辞や接頭辞を使って情報を追加する 名前の長さを決める 名前のフォーマットで情報を伝える |
-
類語辞典を使って、より明確で正確な単語を探してみるべし
-
tmpという名前は生存期間が短い変数につけるべし
-
イテレータによく使うi, jなどを説明的な工夫を(club_i, members_i, users_i とか)
-
変数名に単位を入れる (size_mbyte, max_kbps, delay_secとか)
-
重要な属性を付与する (plaintext_pasword, html_utf8とか)
-
スコープが狭いなら短い変数名もOK
-
プロジェクト固有の省略形はNG
-
意味が損なわれないなら不要な単語を削除 (ConvertToString→ToString)
-
名前のフォーマットで情報を伝える
以下はGoogle社のあるプロジェクトチームで使われているフォーマット規約(らしい)
要するに、自分自身やチームで規約を守ろうということ。
クラス名:キャメルケース
ローカル変数:小文字をアンダースコアで区切る
メンバ:最後にアンダースコア
static const int kMaxOpenFiles = 100;
class LogReader {
public:
void OpenFile(string local_file);
private:
int offset_;
};
Check | 鍵となる考え |
---|---|
□ | 他の意味と間違えられることはないか自問自答すべし |
-
限界値を含めるときはmin, maxを使う
-
範囲を指定するときはfirst, lastを使う
-
包含/排他的範囲にはbegin, endを使う
-
ブール値の名前 (is・has・can・shouldなど)
-
ブール変数名は肯定的にすべし
-
ユーザが期待するとおりに命名すべし (get関数は値をgetするだけであるべき)
Check | 鍵となる考え | ポイント |
---|---|---|
□ | そのコードの見た目は美しいか | 読み手がなれているパターンか? 一貫性のあるレイアウトか? 似ているコードは似ているように見せる 関連するコードをブロック化 |
見た目が美しいコードのほうが理解する時間は短縮される!
さっと流し読みできるのが理想。
-
一貫性のある簡潔な改行位置 (すっと内容が目に飛び込んでくるか)
-
縦の線をまっすぐにすると文章に目を通しやすくなる
-
一貫性と意味のある並び
-
改行で論理的なグループに分ける、段落に分ける
-
一貫性のあるスタイルを貫く
-
マクロを使うとキレイになることがある
-
コードを見て本質がすぐに分かるのが理想
Check | 鍵となる考え | ポイント |
---|---|---|
□ | コメントは書き手の意図を伝えること | コメントすべきでないもの コードを書いている時に自分の考えを記録する 読み手の立場で必要な情報を書く |
-
コードから分かることをコメントにしない
-
ひどい名前はコメントをつけず名前を改善
-
関数名は自己文書化されいろんなところで使われるのでコメントより名前のほうが重要!
-
コメンタリーを入れる (コードが汚い理由を書いたっていい)
-
キーワードでコードの状態を知らせる(以下は一例)
記法 | 意味 |
---|---|
TODO: | あとで手を付ける |
FIXME: | 既知の不具合があるコード |
HACK: | あまりキレイじゃない解決策 |
XXX: | 危険!大きな問題がある! |
NOTE: | 注意 |
-
定数にコメントをつける (値の根拠などについて書いておこう)
-
質問されそうなことを先回りしてコメントする
-
他の人がコードをみてビックリしそうなことを想像する
-
他の人がどんなふうに間違えて使う可能性があるか想像する
-
-
全体像のコメント
-
要約コメント
-
ライターズ・ブロックを乗り越える(コメントは悪しき習慣の思想)
Check | 鍵となる考え |
---|---|
□ | コメントは明確で正確に詳細に |
-
コメントは画面を多くとるし、読むのが億劫になる。そうなると書く意味がなくなる。
-
あいまいな代名詞は避けるべし
-
歯切れの悪い文章を磨く
-
プログラムの動作を高次元から説明する
-
名前付き引数コメントを利用 (Connect(/*timeout_ms = */10)とか) ※インラインコメント
-
情報密度の高い単語を使って文章を簡潔にする
ループとロジックの単純化
Check | 鍵となる考え |
---|---|
□ | 制御フローは自然にする |
□ | 3項演算子は記述が簡潔になるときだけに |
□ | do - whileを避ける |
□ | 関数から早く返す(ガード節)、ネストを浅く |
□ | 巨大な式は、説明変数や要約変数をうまく使って飲み込み安い大きさに分割し コードの主要な概念を認識 |
-
条件式の引数の並びに気を配る
while(byte_expected > bytes_received)
よりも
while(bytes_received < bytes_expected)
のほうが読みやすい左辺 右辺 調査対象。変化する。 比較対象。あまり変化しない。
-
条件は否定形よりも肯定形を使う(ド・モルガンの法則を活用する)
if(!debug)
よりも
if(debug)
のほうが読みやすい
-
頭の良いコードに気をつける(あとでわかりにくいことがよくある)
Check | 鍵となる考え |
---|---|
□ | 変数を少なくし、変数を追跡しやすくする |
□ | 変数の生存期間を短くする |
□ | 変数が頻繁に変更されると現在の値を把握するのが難しくなる |
-
役に立たない一時変数を削除しよう
-
中間結果を削除してみる
-
制御フロー変数を削除する(ループから抜けるためだけのフラグとか)
-
変数の定義を使う直前にできないか検討する