ためすう
Ruby で hash を利用する
2019-04-08やったこと
Ruby で hash を利用する方法について調べました。
確認環境
$ ruby -v
ruby 2.2.7p470 (2017-03-28 revision 58194) [x86_64-darwin16]
調査
test.rb
h = {'key' => 'key1', 'desc' => 'desc'}
p h
h2 = {:key => 'key1', :desc => 'desc'}
p h2
h3 = {key: 'key1', desc: 'desc'}
p h3
実行結果
$ ruby test.rb
{"key"=>"key1", "desc"=>"desc"}
{:key=>"key1", :desc=>"desc"}
{:key=>"key1", :desc=>"desc"}
Ruby の empty? と nil? について調べた
2019-04-07やったこと
Ruby で empty? と nil? について調べました。
確認環境
$ ruby -v
ruby 2.2.7p470 (2017-03-28 revision 58194) [x86_64-darwin16]
調査
test.rb
abc = [
nil,
'',
false,
0,
[],
]
abc.each_with_index do |v, i|
printf("check %d\n", i)
begin
if v.nil?
p 'abc is nil'
else
p 'abc is not nil'
end
rescue => error
p error
end
begin
if v.empty?
p 'abc is empty'
else
p 'abc is not empty'
end
rescue => error
p error
end
end
実行結果
$ ruby test.rb
check 0
"abc is nil"
#<NoMethodError: undefined method `empty?' for nil:NilClass>
check 1
"abc is not nil"
"abc is empty"
check 2
"abc is not nil"
#<NoMethodError: undefined method `empty?' for false:FalseClass>
check 3
"abc is not nil"
#<NoMethodError: undefined method `empty?' for 0:Fixnum>
check 4
"abc is not nil"
"abc is empty"
Ruby で構造体を使う
2019-04-04やったこと
Ruby で構造体を利用する方法を調べました。
確認環境
$ ruby -v
ruby 2.2.7p470 (2017-03-28 revision 58194) [x86_64-darwin16]
試す
test.rb
Node = Struct.new(:key, :parent, :left, :right)
node = Node.new('key1', 'parent1', 'left1', 'right1')
p node
実行結果
$ ruby test.rb
#<struct Node key="key1", parent="parent1", left="left1", right="right1">
参考
Ruby でループを逆向きに実行する
2019-04-02やったこと
ループを逆向きに実行する方法を調べました。
例えば下記の配列があった場合
[1, 3, 5, 7, 9]
下記のように出力します
9
7
5
3
1
確認環境
$ ruby -v
ruby 2.2.7p470 (2017-03-28 revision 58194) [x86_64-darwin16]
試す
ruby test.rb
a = [1, 3, 5, 7, 9]
(a.length-1).downto(0) do |i|
p a[i]
end
実行結果
$ test.rb
9
7
5
3
1
参考
【Ruby】繰り返し処理について(for, while, until, each, time, loop) - TASK NOTES
Ruby で文字列を配列にする
2019-03-29やったこと
文字列を1文字ずつ配列にする方法を調べました。
確認環境
$ ruby -v
ruby 2.2.7p470 (2017-03-28 revision 58194) [x86_64-darwin16]
調査
test.rb
a = "1234"
p "a.split"
b = a.split("")
# 分割後
p b
# 分割してに1文字ずつ取り出すパターン
p "パターン1"
b.each do |v|
p v
end
# 分割せずに1文字ずつ取り出すパターン
p "パターン2"
for i in 0...a.length
p a[i]
end
実行結果
$ ruby test.rb
"a.split"
["1", "2", "3", "4"]
"パターン1"
"1"
"2"
"3"
"4"
"パターン2"
"1"
"2"
"3"
"4"
参考
Ruby で平方根を求める
2019-03-27やったこと
平方根を求める方法を調べました。
確認環境
$ ruby -v
ruby 2.2.7p470 (2017-03-28 revision 58194) [x86_64-darwin16]
平方根を求める
test.rb
p Math.sqrt(2)
p 2 ** 0.5
実行結果
$ ruby test.rb
1.4142135623730951
1.4142135623730951
参考
継承による委譲の置き換え (リファクタリング-p355)
2019-03-20目的
「リファクタリング」を理解するためにサンプルコードを PHP で書き換えてみました。
今回は「継承による委譲の置き換え」について書きます。
「継承による委譲の置き換え」 について
データの共有は継承では変換できない責任です。
例
変更前
<?php
class Employee
{
/* @var Person */
private $_person;
public function __construct()
{
$this->_person = new Person();
}
public function getName()
{
return $this->_person->getName();
}
public function setName($arg)
{
$this->_person->setName($arg);
}
public function toString()
{
return 'Emp: ' . $this->_person->getLastName();
}
}
class Person
{
private $_name;
public function getName()
{
return $this->_name;
}
public function setName($arg)
{
$this->_name = $arg;
}
public function getLastName()
{
return 'getLastName';
}
}
$e = new Employee();
$e->setName('namename');
echo $e->getName() . "\n";
echo $e->toString() . "\n";
変更後
<?php
class Employee2 extends Person2
{
public function toString()
{
return 'Emp: ' . $this->getLastName();
}
}
class Person2
{
private $_name;
public function getName()
{
return $this->_name;
}
public function setName($arg)
{
$this->_name = $arg;
}
public function getLastName()
{
return 'getLastName';
}
}
$e = new Employee2();
$e->setName('namename');
echo $e->getName() . "\n";
echo $e->toString() . "\n";
インターフェースの抽出 (リファクタリング-p341)
2019-03-19目的
「リファクタリング」を理解するためにサンプルコードを PHP で書き換えてみました。
今回は「インターフェースの抽出」について書きます。
「インターフェースの抽出」 について
複数のクライアントが、あるクラスのひとまとまりのインターフェースを使っている。または2つのクラス間でインターフェースの一部が共通である。
クラスは、互いにさまざまな方法で利用し合います。あるクラスを利用することは、しばしばそのクラスのすべての責任を当てにすることを意味します。
例
変更前
<?php
class Timesheet
{
public function charge(Employee $emp, $days)
{
$base = $emp->getRate() * $days;
if ($emp->hasSpeciallSkill()) {
return $base * 1.05;
}
return $base;
}
}
class Employee
{
public function getRate()
{
return 0.72;
}
public function hasSpeciallSkill()
{
return true;
}
}
$e = new Employee();
$ts = new TimeSheet();
echo $ts->charge($e, 200) . "\n";
変更後
<?php
class Timesheet2
{
public function charge(Billable2 $emp, $days)
{
$base = $emp->getRate() * $days;
if ($emp->hasSpeciallSkill()) {
return $base * 1.05;
}
return $base;
}
}
class Employee2 implements Billable2
{
public function getRate()
{
return 0.72;
}
public function hasSpeciallSkill()
{
return true;
}
}
interface Billable2
{
public function getRate();
public function hasSpeciallSkill();
}
$e = new Employee2();
$ts = new TimeSheet2();
echo $ts->charge($e, 200) . "\n";
スーパークラスの抽出 (リファクタリング-p336)
2019-03-18目的
「リファクタリング」を理解するためにサンプルコードを PHP で書き換えてみました。
今回は「スーパークラスの抽出」について書きます。
「スーパークラスの抽出」 について
似通った特性を持つ2つのクラスがある。
コードの重複は、システムにおける主要な問題点の1つです。
例
変更前
<?php
class Employee
{
private $_name;
private $_annualCost;
private $_id;
public function __construct($name, $id, $annualCost)
{
$this->_name = $name;
$this->_id = $id;
$this->_annualCost = $annualCost;
}
public function getId()
{
return $this->_id;
}
public function getName()
{
return $this->_name;
}
public function getAnnualCost()
{
return $this->_annualCost;
}
}
class Department
{
private $_name;
private $_staff = [];
public function __construct($name)
{
$this->_name = $name;
}
public function getTotalAnnualCost()
{
$e = $this->getStaff();
$result = 0;
foreach ($e as $v) {
$result += $v->getAnnualCost();
}
return $result;
}
public function getHeadCount()
{
return count($this->_staff);
}
public function addStaff(Employee $arg)
{
$this->_staff[] = $arg;
}
public function getStaff()
{
return $this->_staff;
}
public function getName()
{
return $this->_name;
}
}
$e1 = new Employee('emp1', 100, 2000);
$e2 = new Employee('emp2', 200, 5000);
echo $e1->getName() . "\n";
echo $e2->getName() . "\n";
$d = new Department('department1');
$d->addStaff($e1);
$d->addStaff($e2);
echo $d->getName() . "\n";
echo $d->getTotalAnnualCost() . "\n";
変更後
<?php
abstract class Party
{
private $_name;
protected function __construct($name)
{
$this->_name = $name;
}
public function getName()
{
return $this->_name;
}
abstract public function getAnnualCost();
}
class Employee2 extends Party
{
private $_annualCost;
private $_id;
public function __construct($name, $id, $annualCost)
{
parent::__construct($name);
$this->_id = $id;
$this->_annualCost = $annualCost;
}
public function getId()
{
return $this->_id;
}
public function getAnnualCost()
{
return $this->_annualCost;
}
}
class Department2 extends Party
{
private $_staff = [];
public function __construct($name)
{
parent::__construct($name);
}
public function getAnnualCost()
{
$e = $this->getStaff();
$result = 0;
foreach ($e as $v) {
$result += $v->getAnnualCost();
}
return $result;
}
public function getHeadCount()
{
return count($this->_staff);
}
public function addStaff(Employee2 $arg)
{
$this->_staff[] = $arg;
}
public function getStaff()
{
return $this->_staff;
}
}
$e1 = new Employee2('emp1', 100, 2000);
$e2 = new Employee2('emp2', 200, 5000);
echo $e1->getName() . "\n";
echo $e2->getName() . "\n";
$d = new Department2('department1');
$d->addStaff($e1);
$d->addStaff($e2);
echo $d->getName() . "\n";
echo $d->getAnnualCost() . "\n";
サブクラスの抽出 (リファクタリング-p330)
2019-03-18目的
「リファクタリング」を理解するためにサンプルコードを PHP で書き換えてみました。
今回は「サブクラスの抽出」について書きます。
「サブクラスの抽出」 について
「サブクラスの抽出」を行う主なきっかけは、あるクラスが、特定のインスタンスだけでしか使われない振る舞いを持っていることがわかった場合です。
例
変更前
<?php
class JobItem
{
private $_unitPrice;
private $_quantity;
private $_isLabor;
private $_employee;
public function __construct($unitPrice, $quantity, $isLabor, Employee $employee)
{
$this->_unitPrice = $unitPrice;
$this->_quantity = $quantity;
$this->_isLabor = $isLabor;
$this->_employee = $employee;
}
public function getTotalPrice()
{
return $this->getUnitPrice() * $this->_quantity;
}
public function getUnitPrice()
{
return $this->_isLabor ?
$this->_employee->getRate() :
$this->_unitPrice;
}
public function getQuantity()
{
return $this->_quantity;
}
public function getEmployee()
{
return $this->_employee;
}
}
class Employee
{
private $_rate;
public function __construct($rate)
{
$this->_rate = $rate;
}
public function getRate()
{
return $this->_rate;
}
}
$e = new Employee(0.6);
$ji = new JobItem(2, 100, true, $e);
echo $ji->getTotalPrice() . "\n";
変更後
<?php
class JobItem2
{
private $_unitPrice;
private $_quantity;
private $_isLabor;
private $_employee;
protected function __construct($unitPrice, $quantity, $isLabor, Employee2 $employee)
{
$this->_unitPrice = $unitPrice;
$this->_quantity = $quantity;
$this->_isLabor = $isLabor;
$this->_employee = $employee;
}
public function getTotalPrice()
{
return $this->getUnitPrice() * $this->_quantity;
}
public function getUnitPrice()
{
return $this->_isLabor ?
$this->_employee->getRate() :
$this->_unitPrice;
}
public function getQuantity()
{
return $this->_quantity;
}
public function getEmployee()
{
return $this->_employee;
}
}
class LaborItem2 extends JobItem2
{
public function __construct($unitPrice, $quantity, $isLabor, Employee2 $employee)
{
parent::__construct($unitPrice, $quantity, $isLabor, $employee);
}
}
class Employee2
{
private $_rate;
public function __construct($rate)
{
$this->_rate = $rate;
}
public function getRate()
{
return $this->_rate;
}
}
$e = new Employee2(0.6);
$ji = new LaborItem2(2, 100, true, $e);
echo $ji->getTotalPrice() . "\n";