2012年1月22日日曜日
My aunt's too sudden death
Few years she had been bothered by such a severe hyperesthesia that she couldn't have spend an ordinary life which every middle age ladies can enjoy.
When she and my father were child, she lived in more healthy than my father.
Because she had been seeing my father's weakness, she decided to get a jobs in nurse.
She had wide knowlege about health. She would have been a skillful nurse, if she had not has a severe hyperesthesia.
More excelent her career became, she lost her healthiness.
Finally her health had got lost severely. She had decided to live alone without jobs.
Today her funeral is going to be held.
I cannot take part in it, but I pray for her soul.
2012年1月17日火曜日
TDDと勉強法
オレが高校3年生の時、11月、突如思い立って、物理の勉強に没頭した。
単純な
ma = F
とかいう公式に載っていることではなくて、もっと運動方程式とは何なのかと根源的に追い詰めた。その時に役に立った本が『坂間の物理』という本で、えっと、某台予備校に通っていたかつて学生だった人の何人かは知っている物理教師の本だった。
まあ、その教師の物理の授業を受けたことがある人は知っていると思うけど、あんなのは受験生が期待する授業ではない。
ただ、あの人のやっていることはTDDという観点で見ると、非常に理にかなっている。
彼の教育プロセスをもう一度思い出してみた。
- 真似をさせる→答えは教えてやる。間違えてもいいから、こうなるように計算してみろというのである。
- 徹底的に真似をさせる→教えてやった答えを、問題文を見ないようにして解けというのである。
- 高速化させる→もっとエレガントに解答を書けというのである。
なんか、TDDっぽい教育だと思った。
一般的なTDDスタイルの開発
- 答えはわかっている。テストは落ちる。
- 答えが合うように、実装を作る。
- もっとエレガントになるように実装を洗練させる。
なんか似ている。
オレは思い立った1ヶ月間『坂間の物理』に掲載されている108問の問題をすべて、この三段階の方法で演習した。
結果、予備校生になっても物理は超得点源になって、某大学模試で物理の偏差値78とかありえない値を取得した。
ペアプロの学習効果はよく言われているが、実際にはTDDもプログラマーの成長に欠かせない要素があるのではないかと思う。
テストを書くということは、実装を書くのに加えて、テストコードも書かなければならないから、一見無駄に思える。
だが、それは上記に上げたプロセスのまだ第一段階なのではなかろうか?
本当にTDDが力を発揮してくるのは第二段階、第三段階を超えた時で、エレガントな実装を出来るようになった時には、オレが物理を超得意となった状態と同じく、プログラマーはプログラムの実装を超得意と思って自信をもって取り組むことが出来るようになるのではないかと思う。
まあ、脳足りんの考えたことなので、実証もされてないことだし、単なる妄想かもしれない。
ちなみに坂間先生というのは、自分の授業について、後で答えを書いてきてごらん、添削してあげるからと言っていたので、毎週授業でやった範囲の部分の真似を持っていていたら、ちゃんとレビューしてくれた。この部分はこう書くともっとエレガントになるとか、ここは読みづらいからもっと大きく書けとか。
テストも同様で、それをレビューしてエレガントなコードはどういうものなのかを考えていけば、プログラマーは大いに成長するのではないだろうか。
…
ちなみに、坂間先生はオレが通っていた○進スーパーコースでは人気なかったです。
おわり。
2012年1月14日土曜日
Grails2.0のDomainをTDDしてみる。
の96ページにあるモデル図から。
ここから、今回の対象部分のモデルを抜き出したのが以下の図。
で、今回はこのうち、Shipmentの部分をTDDしていきます。
ドメインの作成
ドメインの作成はいたって簡単です。
$ grails create-domain-class Shipment
これだけで、
Shipment
ドメインクラスと、ShipmentTests
テストクラスが生成されます。Shipment.groovy
package grailsshop
class Shipment {
static constraints = {
}
}
Shipment.groovy
package grailsshop
import grails.test.mixin.*
import org.junit.*
@TestFor(Shipment)
class ShipmentTests {
void testSomething() {
fail()
}
}
なお、テストクラスはデフォルトでは
fail
になるようになっています。最初のテスト
Shipment
(出荷)はイベントなので、必ず日付をもちます。したがって、null
は禁止です。それをテストに書きます。
なお、Grails2.0はJUnit4対応しているので、アノテーションを用いることでテストメソッドであることを示せます。
ここではテストメソッド名も変更しています。
また、
validate
のテストになりますので、前回の結論に書いておいたようにmockForConstraintsTests
メソッドを最初に用いておきます。Shipment.groovy
package grailsshop
import grails.test.mixin.*
import org.junit.*
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateDate() {
mockForConstraintsTest(Shipment)
def object = 'date'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
}
}
実行結果は次のようになります。
grails> test-app grailsshop.Shipment
| Running 1 unit test... 1 of 1
| Failure: validateDate(grailsshop.ShipmentTests)
| Assertion failed:
assert shipment.validate() == false
| | |
| true false
grailsshop.Shipment : null
at grailsshop.ShipmentTests.validateDate(ShipmentTests.groovy:20)
| Completed 1 unit test, 1 failed in 1930ms
| Packaging Grails application.....
| Tests FAILED - view reports in target/test-reports
grails>
まあ、
Shipment
にはdate
というフィールドをまだ実装していないので、落ちるのもやむなしです。暗黙のnullable : false
そこで、実装に行きます。
とりあえず、
Shipment
クラスにDate
型のdate
を持たせてみます。Shipment.groovy
class Shipment {
/**
* 出荷日付.
*/
Date date
static constraints = {
}
}
この状態でテストを実行してみます。
grails> test-app grailsshop.Shipment
| Completed 1 unit test, 0 failed in 152ms
| Tests PASSED - view reports in target/test-reports
grails>
というわけで、とくに
null
チェックの実装を入れていませんが、テストが通りました。Grailsのドメインクラスにあるフィールドはデフォルトで
nullable
がfalse
のようです。適当に制約をいれていく
Shipment
(出荷)、捉え方によるけど、未来の日付は入れられないことにしておきましょう。(出荷予定であれば話は別ですが…)
それをテストに書きます。
ShipmentTests.groovy
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateDate() {
mockForConstraintsTest(Shipment)
def object = 'date'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
shipment = new Shipment(date: dayFromToday(1))
assert shipment.validate() == false
assert shipment.errors[object] == 'max'
}
}
dayFromToday(int)
は今日からの日付を取るユーティリティーメソッドです。0
を指定すると今日の日付、1
を指定すると明日の日付が取得できます。翌日の日付であった場合は、エラーとなるというテストを記述しています。
で、テストの結果は次のとおりになります。
grails> test-app grailsshop.Shipment
| Running 2 unit tests... 1 of 2
| Failure: validateDate(grailsshop.ShipmentTests)
| Assertion failed:
assert shipment.validate() == false
| | |
| true false
grailsshop.Shipment : null
at grailsshop.ShipmentTests.validateDate(ShipmentTests.groovy:24)
| Completed 2 unit tests, 1 failed in 96ms
| Packaging Grails application.....
| Tests FAILED - view reports in target/test-reports
grails>
まず、
validate()
でAssert
が落ちます。落ちた原因を探りたいので、一度テストを修正します。
ShipmentTests.groovy
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateDate() {
mockForConstraintsTest(Shipment)
def object = 'date'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
shipment = new Shipment(date: dayFromToday(1))
shipment.validate()
assert shipment.errors[object] == 'max'
}
}
テスト結果
grails> test-app grailsshop.Shipment
| Running 2 unit tests... 1 of 2
| Failure: validateDate(grailsshop.ShipmentTests)
| Assertion failed:
assert shipment.errors[object] == 'max'
| | || |
| | |date false
| | null
| org.codehaus.groovy.grails.plugins.testing.GrailsMockErrors: 0 errors
grailsshop.Shipment : null
at grailsshop.ShipmentTests.validateDate(ShipmentTests.groovy:25)
| Completed 2 unit tests, 1 failed in 81ms
| Packaging Grails application.....
| Tests FAILED - view reports in target/test-reports
grails>
内容からわかるようにエラーがないということです。
ここで、正しく
validate()
でエラーとなるようにドメインクラスを修正します。Shipment.groovy
class Shipment {
/**
* 出荷日付.
*/
Date date
static constraints = {
date(max: new Date())
}
}
制約を加えたらテストを実行します。
grails> test-app grailsshop.Shipment
| Completed 2 unit tests, 0 failed in 124ms
| Tests PASSED - view reports in target/test-reports
grails>
ちゃんとパスします。
念のため、今日も大丈夫か確認します。
ShipmentTests.groovy
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateDate() {
mockForConstraintsTest(Shipment)
def object = 'date'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
shipment = new Shipment(date: dayFromToday(1))
assert shipment.validate()
assert shipment.errors[object] == 'max'
shipment = new Shipment(date: dayFromToday(0))
shipment.validate()
assert shipment.errors[object] == null
}
}
ポイントとしては、
validate()
が通るケースでは、assert shipment.validate() == true
のテストを行わない方が良いです。理由は、これから他にも
validate
するものが増えるので、後々にテストが通らなくなるからです。テストの実行結果は次のようになります。
grails> test-app grailsshop.Shipment
| Completed 2 unit tests, 0 failed in 81ms
| Tests PASSED - view reports in target/test-reports
grails>
リレーションに関するフィールドの追加とテスト
次にリレーションに関するフィールドの追加とテストです。
先に掲載したモデルから、
Shipment
とWarehouse
、Order
の関係は、次のようになります。Shipment
-Warehouse
Shipment
からみてWarehouse
は唯一つ存在し、かつその参照先を保持する必要がある。Warehouse
からみてShipment
は0または1つ存在し、その参照先は保持しなくて良い。Shipment
-Order
Shipment
からみてOrder
は唯一つ存在し、かつその参照先を保持する必要がある。Order
からみてShipment
は0または1つ存在し、その参照先は保持しなくて良い。
こういうのを一般的には一対一の片方向の関連とかなんとかいうらしいです。
Grailsのドメインにおいて、これを実現するのが
belongsTo
です。では、おもむろにテストを書きます。
ここでは、暗黙の
nullable : false
を利用します。まずは
Order
から…ShipmentTests.groovy
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateOrder() {
mockForConstraintsTests(Shipment)
def object = 'order'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
}
}
テストを実行します。
grails> test-app grailsshop.Shipment
| Running 3 unit tests... 1 of 3
| Failure: validateDate(grailsshop.ShipmentTests)
| java.lang.NoSuchMethodError: grailsshop.Shipment.getBelongsTo()Ljava/lang/Object;
at org.grails.datastore.mapping.reflect.ClassPropertyFetcher$GetterPropertyFetcher.get(ClassPropertyFetcher.java:326)
at org.grails.datastore.mapping.reflect.ClassPropertyFetcher.getPropertyValueWithFetcher(ClassPropertyFetcher.java:218)
at org.grails.datastore.mapping.reflect.ClassPropertyFetcher.getStaticPropertyValue(ClassPropertyFetcher.java:233)
at org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy.establishRelationshipOwners(GormMappingConfigurationStrategy.java:271)
at org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy.getOwningEntities(GormMappingConfigurationStrategy.java:716)
at org.grails.datastore.mapping.model.AbstractPersistentEntity.initialize(AbstractPersistentEntity.java:79)
at org.grails.datastore.mapping.model.AbstractMappingContext.addPersistentEntityInternal(AbstractMappingContext.java:150)
at org.grails.datastore.mapping.model.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:135)
at grails.test.mixin.domain.DomainClassUnitTestMixin.mockDomain(DomainClassUnitTestMixin.groovy:124)
at grails.test.mixin.domain.DomainClassUnitTestMixin.mockDomain(DomainClassUnitTestMixin.groovy:120)
| Failure: validateDate(grailsshop.ShipmentTests)
| java.lang.NullPointerException
at org.grails.datastore.mapping.core.DatastoreUtils.unbindSession(DatastoreUtils.java:362)
at grails.test.mixin.domain.DomainClassUnitTestMixin.shutdownDatastoreImplementation(DomainClassUnitTestMixin.groovy:109)
| Running 3 unit tests... 2 of 3
| Failure: validateOrder(grailsshop.ShipmentTests)
| Assertion failed:
assert shipment.errors[object] == 'nullable'
| | || |
| | |order false
| | null
| org.codehaus.groovy.grails.plugins.testing.GrailsMockErrors: 1 errors
| Field error in object 'grailsshop.Shipment' on field 'date': rejected value [null]; codes [grailsshop.Shipment.date.nullable.error.grailsshop.Shipment.date,grailsshop.Shipment.date.nullable.error.date,grailsshop.Shipment.date.nullable.error.java.util.Date,grailsshop.Shipment.date.nullable.error,shipment.date.nullable.error.grailsshop.Shipment.date,shipment.date.nullable.error.date,shipment.date.nullable.error.java.util.Date,shipment.date.nullable.error,grailsshop.Shipment.date.nullable.grailsshop.Shipment.date,grailsshop.Shipment.date.nullable.date,grailsshop.Shipment.date.nullable.java.util.Date,grailsshop.Shipment.date.nullable,shipment.date.nullable.grailsshop.Shipment.date,shipment.date.nullable.date,shipment.date.nullable.java.util.Date,shipment.date.nullable,nullable.grailsshop.Shipment.date,nullable.date,nullable.java.util.Date,nullable]; arguments [date,class grailsshop.Shipment]; default message [Property [{0}] of class [{1}] cannot be null]
grailsshop.Shipment : null
at grailsshop.ShipmentTests.validateOrder(ShipmentTests.groovy:39)
| Completed 3 unit tests, 3 failed in 75ms
| Packaging Grails application.....
| Compiling 1 source files.
grails>
なんか、関係のない
validateDate
まで落ちてしまいました(´・ω・`)このあたりはGrailsの改善に期待するしかなさそうです…
テストが通るように実装をします。
Shipment.groovy
class Shipment {
/**
* 出荷日付.
*/
Date date
static belongsTo = [
/**
* 発注.
*/
order : Order
]
static constraints = {
date(max: new Date())
}
}
実装したら、テストを実行します。
grails> test-app grailsshop.Shipment
| Completed 3 unit tests, 0 failed in 168ms
| Tests PASSED - view reports in target/test-reports
grails>
今回はすんなり通りました。何だったんでしょう?あの落ちっぷりは…
さて、
Warehouse
の方も同様にテスト、実装します。ShipmentTests.groovy
@TestFor(Shipment)
class ShipmentTests {
@Test
void validateWarehouse() {
mockForConstraintsTests(Shipment)
def object = 'warehouse'
def shipment = new Shipment()
assert shipment.validate() == false
assert shipment.errors[object] == 'nullable'
}
}
Shipment.groovy
class Shipment {
/**
* 出荷日付.
*/
Date date
static belongsTo = [
/**
* 発注.
*/
order : Order,
/**
* 倉庫.
*/
warehouse : Warehouse
]
static constraints = {
date(max: new Date())
}
}
結論
うむ、ほんとうは
@Mock
をやりたかったのだが、書いている量が半端なくなってきたので、次回に…2012年1月10日火曜日
Objective-CのUnit Testを書いてみた
テストを書こう
とつぶやいたお陰で、なんかUnit Testを書くことになったような雰囲気…
とありあえず、簡単なテストを書いてみた。
FirstViewController.m
は、まあ、名前から想像できる通り、画面の操作系のオブジェクトです。ここに、画面の操作(Controller)と画面表示(View)に関係のない部分 = 日付のフォーマット(Model)があったので、Modelの部分についてはテストを書けるだろうということで、書いたテストが上の2つのテストです。
やってみてちょっと判ったこと
NSString系の文字列の扱いがよくわかっていないので、時間が妙にかかった。
このあたりは本で知識を補強していく必要があるっぽい。
2012年1月9日月曜日
#日本鼻メガネの会 に参加してみた的な
参加までの経緯
なんのことやらわからず参加しました。
多分、参加することになった理由は謎のハッシュタグ
#日本鼻メガネの会
ですね。
なんですかこの怪しげな響きは…と調べていくと、
日本鼻メガネの会 新年会
十分に怪しい…
謳い文句もなんだか怪しい…
IT系勉強会でひそかなブームになりつつある鼻メガネを愛でる会です
え、ブーム、そんなのブームなのか?!
だが、もっと怪しいのが参加者の面々。
Twitterでよく見かける人ばっかり…
定員15人で、参加者14人、キャンセル1人だったので、参加できるっぽかったので、とりあえず趣旨はよくわからんが参加ポチった。
当日
とりあえず、鼻メガネは必要そうだったので、歌舞伎町のドンキホーテで鼻だけ購入。
会場は新宿角海老の裏。参考:新宿角海老(R-20限定)
とりあえず、店の名前よく覚えていなかったので(今でも思い出せない…)新宿角海老のあたりをウロウロしていたら、風俗関連のお兄さんに「お兄さん、どのお店探しているの?」と声をかけられました。
いや、おっ◯いパブとか興味ないから…
とりあえず、@shinyaa31さんのおかげで会場にたどり着きましたが、
ツイッターアイコンしか知らんので顔が誰が誰かようわからん…
いつもどおり、コーラをがぶ飲みしておきました。
当日の様子などは以下のエントリーなどが詳しいのでそちらを参照下さい。
- 2012/01/07 日本鼻メガネの会 新年会 #日本鼻メガネの会
- [勉強会]日本鼻メガネの会 新年会に参加してきた #日本鼻メガネの会
- 2012-01-09 #日本鼻メガネの会 新年会に参加しました
- #日本鼻メガネの会 新年会に参加してきた
他にも多数あるけど、まあ、ようまとめきれんです。
結論
勉強会で知り合ったクラスタとか、Twitterで知り合ったクラスタとの、gdgdなオフ会意見交換会も面白いですね。
2012年1月7日土曜日
Grails2.0のDomainのUnit Testハマリどころ
と言っても、ひとつしか書いていませんが…
ConstraintsのValidationテスト
前回の記事では
Validation
のテストについて少し取り扱っています。Book.groovy
class Book {
String name
String author
int price
static constraints = {
name (blank: false)
author (blank: false)
price (min: 0)
}
}
BookTests.groovy
@Test
void validation() {
def book = new Book(name: '吾輩は猫である', price: -1)
assert book.validate() == false
}
このテストで分かるのはこのままでは登録できないということです。
ただ、残念なことに何が悪くて
Validation
で引っかかったのかがわかりません。この際に役立つのがPOGOに自動的に付与される
errors
というメンバーです。くせもののerrors
この
errors
にはvalidate()
でチェックされたエラーのスナップショットが格納されています。上記のコードの例では、
Book
クラスには著者の情報が未設定であり、不適切な価格情報が設定されているという状態です。したがって、
errors
にはauthor
とprice
というメンバーが存在します、いや、するはずです。では、本当に
price
で引っかかっているのか確認するテストを書きます。
@Test
void validation() {
def book = new Book(name: '吾輩は猫である', price: -1)
assert book.validate() == false
assert book.errors['price'] == 'min'
}
このテストは
validate()
でチェックされたエラーのうち、price
に対するエラーはmin
であることをテストします。おもむろに実行します。
実行結果(一部略)
| Failure: validateQuantity(grailsshop.Book)
| Assertion failed:
assert book.errors['price'] == 'min'
| | | |
| | | false
| | Field error in object 'grailsshop.Book' on field 'price': rejected value [0];
| Field error in object 'grailsshop.Book' on field 'price': rejected value [0];
grailsshop.Book: null
実際はもっと長ったらしいエラーメッセージが出ますが、Field errorの部分の内容を見るかぎりではこのテストは通ってもよさそうなものなのですが、ダメなんですね。
書き方間違えたのかと思って、公式サイトを確認しましたが、合っているようです。
mockForConstraints
そんなこんなで、混乱していたところ、Grailsの第一人者であられる@tyamaさんからアドバイスをいただきました。
ふむ、
mockForConstraints(Class<T>)
を使えばよいとな。というわけで、おもむろに入れてテストを通してみる。
@Test
void validation() {
mockForConstraintsTests(Book)
def book = new Book(name: '吾輩は猫である', price: -1)
assert book.validate() == false
assert book.errors['price'] == 'min'
}
そして、テスト実行。
grails> test-app grailsshop.Book
| Completed 1 unit tests, 0 failed in 361ms
| Tests PASSED - view reports in target/test-reports
おお、通った。
結論
とりあえず、
Grails2.0
でconstraints
のValidation
テストをする場合は、黙ってmockForConstraintsTests
を使っとけという話ですな。2012年1月6日金曜日
イケてないGitの覚書き
イケてないGit覚書き
基本
コミットする
# 作業後
# コミットする
$ git commit -a -m '出版社の資本金は1円以上'
[publisher-test e93607c] 出版社の資本金は1円以上
1 files changed, 5 insertions(+), 1 deletions(-)
$
変更したけどイケてないのでもとに戻す
# やらかしたので状態を取り戻す
$ git checkout filename
いや、そもそもコミットを取り消す
# やらかす
$ git commit -a -m '完璧っす'
[publisher-test f08613e3] 完璧っす
1 files changed, 10 insertions(+), 1 deletions(-)
# あああっ!
$ git reset HEAD^
GitHubにpush
$ git push -u origin master
たくさんすることがあるとき
ブランチを作成する
$ git checkout -b publishers-attr
ブランチを移動する
$ git checkout publishers-attr
ブランチの作業結果をmasterにマージする
# 現在のブランチを確認
$ git branch
master
* publishers-attr
# masterに戻る
$ git checkout master
# マージ
$ git merge publishers-attr
イケてないとき
ブランチで途中まで作業をしていてテストこけているのでコミットはしたくないけどこのまま作業を続けたくもない。だからMasterに戻って別の作業をしたい。
# 今のブランチ
$ git branch
master
* publishers-attr
$ git stash
$ git checkout master
# 作業する
Masterで作業していたら閃いたので、さっきのブランチに移動してあのイケテナイ変更から再開する
$ git commit -a -m 'masterでコミット'
# 閃いた
$ git checkout publishers-attr
$ git stash pop
2012年1月5日木曜日
Oekonomisch-philosophische Manuskripte -- マルクス『経済学・哲学草稿』
さてこのエントリは…
巷のエンジニアで話題のテーマ:設計に関するエントリ
- @ryoasai74さんの「開発コストや技術リスクを考えない「上流設計」がシステムの複雑化と大規模な障害の原因となっているのでは?」
- @megascusさんの「上流設計はなぜあるのかとどうすればよいか。」
の2つのエントリーを読んで、ちょっと微妙な横槍を失敗したオフショアでの現場の技術者についての評価をたまたまやったので、そんな話をしつつ、これまた巷のエンジニアで話題のテーマである英語について
- 誰かが書いた日本語賛辞『明暗くっきり、オライリーと技術評論社』
- JavaBlackさんの『日本人技術者が洋書を読まなければならない時代』に、確かにそうだねと頷きつつ
- @JunichiIto77さんの『僕だったらどうやって洋書が読めるように努力するか』から、TOEIC600は取れるよねと同感しつつ、
- @irofさんの『英語駄目と洋書の話』
和書じゃないと売れないなんて、おまいら何してんだと叱責しつつ、たまたま読んでいたカール・マルクスの『経済学・哲学草稿』(岩波文庫)のある一説を踏まえて、昨今の話題になっている少子化および就職難からショッキングな一節を引用して、少子化と就職難について論じてみるという無謀な試みをしたいと思います。
まあ、色々と取り込んだ関係上、焦点がぼやけていますので、少し対象読者を絞りつつ書きたいと思います。
対象読者
- 英語を読むのが苦痛というか、日本語の文献しか読まないというか、日本語の文献も読まないエンジニア
- 大学でまともに勉強しないで、就職活動に勤しむアレな人とそれを強いる企業の人事部
- 要求と仕様と実装の板挟みに合っている人
- リブ管理というお仕事で、決められたフローに基づき朝に申請を受けたソースを夕方頃やっと編集していいよとドヤ顔している超高速なGitみたいな人
- TOCを下げて利益を得たい人
設計の話
@ryoasai74さんのお話
非常に面白い内容で、松屋で読んでいたんですが、かなり熱中して読んでいました。問題点としては
- ウォーターフォールから離れられないこと
- 実装する立場ではないので実現可能性の観点が仕様設計に盛り込まれていないこと
というあたりが問題だったと思います。
ウォーターフォールから離れられないことについては、
@megascusさんのエントリー
に書いてる要点
- 昔はマシンのコストが高かったから、コストの低い人間が頑張って効率的に計算機を使えるように頑張るというのが、計算機の低廉化によりそんなことがなくなってきているんだよ
という解説が、まあ的を得ていると思います。
オレのデスマ
なんかで思ったんですが、実装と企画は同時進行できたらいいよねなんて思ったりするわけであります。
夢を見るのは構わないですよっと。現実も見て欲しいんですね。
G****とかD***N*とかのプラットフォームを既に持っている会社はそれほどコストかけなくても、まあコピゲーは開発できるんですね。
で、そういうプラットフォームを持っている会社はどの層が課金するユーザーであるかといったデータを持っていますし、本屋でちょっと探せばそういうデータは見つけられます。どの層のユーザーにヒットを出せるかというのも、まあ、あの手この手を打ちながらですけど、探るパターンは持っていたりしますし、まあ、今更ね、そういうソーシャルなところに新規参入したって、時間がかかって成果が上がらんだけですよなんて、冗談半分に酔狂で語ってみるわけです。
オフショアのエンジニア
というわけで、オフショアの開発を振り返るのですが、実は@megascusさんのエントリーは、半分正しいのですが、オフショアでは半分正しくないんです。
というのも、スマートフォンを買うのに、給料3ヶ月分もかかるオフショア先の環境では、やはりマシンは高いんです。
だから、オフショアで開発するには、結局ウォーターフォールが前提になってくるわけです。
日本 + 西欧諸国レベルで開発を考える場合は、企画の段階で開発者が入ってCIでリスクを軽減していくというアプローチは生産性が高くなりますが、
なんてことはない、オフショアの国々ではマシンが高いから、
人件費でやったほうがよいというCIとかに慣れた我々には想像のつかないソリューションが大手を振って歩いているわけです。
それだって、コストはめちゃくちゃ安いんです。
オフショア開発者の技術スキル
実はオフショア先の国々では、そんな低賃金ながらも、実はIT系の企業は高収入ということで人気があって、金融の分野に続いて二番目に人気が高いそうです。
というわけで、実はオフショア先の国々のエンジニアは結構優秀だったりするわけです。
英語とかもスラスラしゃべります。
エンジニアの英語嫌い
だから、日本語で書かれた技術書なんて別にいらないし、
別に技評の本が日本人にとってユーザービリティが高くても、オライリーのほうがバリバリ活躍するし、
洋書の方が安価で、早く情報が得られる。
TOEICが大体600点なかばくらいの私と英語で話していて、別に困らないから、
オフショア先のデベロッパーの方々は、まあ大体TOEIC600点くらいのスコアは取れるでしょうね。
で、これは彼らの学歴が良いことにも関係あるし、いい大学に行けるということは彼らはそのプレッシャーに負けずに勉強しているわけで、
やっぱり優秀なわけです。
英語ができない日本人がオフショアでコストが安くなるからと言って、行こうものなら、自分たちの考慮不足をガンガン指摘されます。
@ryoasai74さんの記事に戻って
不良っぽいAPIとか接続定義書とかについても、多分、ガンガンに文句言われるので、
まあ、プライドだけは高い某○ティー・ティーのことですから、メンツ潰れて、だからオフショアはダメなんだって
言い出しかねない……あ、懇意にしていただいている人で某エヌ・○・ティー系列の方がいるから、悪口はよしておこう…
いや、何が言いたいかというと、
オフショアの技術者舐めたらアカンぜよ
というわけです。
少子化
で、ここで、たまたま読んでいたマルクスの『経済学・哲学草稿』の一節を引用するのですが、
あらゆる他の商品の場合と同様に、人間に対する需要が、必然的に人間の生産を規制する。
マルクス『経済学・哲学草稿』(岩波文庫、p.18)
ちうことで、実は、日本の少子化とか就職難とかいった問題は、
日本人の需要が少ないから、子供はいらないし、就職もできない
ということではないのかな…などと思うわけです。
マルクスは『経済学・哲学草稿』のほかで『ドイツ・イデオロギー』(岩波文庫)、『資本論』(岩波文庫)などで、
労働者の「再生産」という表現をよく使っています。
これは『経済学・哲学草稿』の一部ではこのように書かれています。
労賃にとって最低の、どうしても必要な水準は、…(中略)…、労働者が家族を扶養することができ、労働者という種族が死滅しないですむという線である。
マルクス『経済学・哲学草稿』(岩波文庫、p.18)
ということから推測すると、日本人の労働者としての需要は、高い給料を要求するくせに、仕事は賃金の安いオフショア先と変わらんというわけで、需要がなくなりつつあるのではないでしょうか。
そんあわけで、日本人という種別はこれから絶滅への道に歩んでいくので、まあ別に子供作らなくてもいいし、まあ、若い人が就職できなくてもいいんじゃないなんて思うわけです。
で、私は、この状況に対して、何か抗えということも思いません。
実はマルクスの著作から、勘違いした何人かが共産主義だとかコミュニズムだとか、ソビエトだとか、赤とかいう過激な発想や、
まあ、こんな張り紙をする人が現れるわけです。
大阪市役所の大阪府労組連の張り紙がヤバイwwwwwwwwwww
あの、ひとこと言っておきますが、マルクスも、エンゲルスも、彼らが擁護しているように見せかけている労働者ではありませんよ。
マルクスは会社経営者であるエンゲルスから金を無心して、呑んだくれているオヤジですし、
エンゲルスは会社経営者で労働者ではなく資本家の方の立場です。
マルクスの本当に滑稽なところは、「お前労働者の味方のふりして、実は労働者じゃないだろ!」というような悪酔いしたヒゲ爺が
シュールに労働者問題を達観したような顔で述べていく所ですよ。
これは滑稽でないとは思えませんね。
あ、で話を少し戻すと、マルクスは抗えといったのではなくて、現実を直視しろと言っていたのではないかななどと思う、今日この頃なのであります。
柄谷行人
で、私がマルクスを読むきっかけになったのが、柄谷行人の『マルクスその可能性の中心』(講談社学術文庫)という本なのですが、これは非常に面白いので、まあ読んでみてください。労働者とかそういうネタは転がっていなくて、あくまで文学として読もうとする試みですから。
で、そんな柄谷行人が反原発のデモに参加していたみたいです。
デモというのは非常に効果があった。かつては。
なぜなら機械の値段が高い時に、賃金の安い労働者が機械を壊すのだから。
@megascusさんの話に戻る
今はマシンは安くて人件費は高いんですって。
だから、今デモなんかやったって、あまり費用対効果はない。
2チャンネラー湘南ゴミ拾いオフ
なんてイベントがありました。
コレですよ。
警察すら出てきていないんですよ。
効果は、う~ん、まあともかく、費用はほとんどかかっていないはず…
結び
さて、話がどんどんとあらぬ方向に突き進みつつあるので、強引に終わりにするわけですが、
- 英語に取り組まないエンジニアは再生産を諦めてください。
- それでも再生産しちゃった場合は、自分と同じレベルかそれ以下の再生産しかできないと諦めましょう。
- 英語に取り組まないなら真摯に最新技術にキャッチアップしてください。きっと英語が必要になるんですけど…
- オフショアする場合は、オフショア先は旧プロセスを使っていることが多々あります。
- アジャイルっぽいのを目指す場合は、オフショア先にマシンの投資をしてあげてください。
- 賃金が低いからって無茶な要求はしないでください。マシンスペックが低いんですよ。マシンスペックが高い自分ができないことを求めないで挙げてください。
- 賃金が違いからって上から目線やめましょう。相手のほうがスキルに富んでいることがあります。経緯を払ってください。
ちなみに、私、本当に英語が苦手でした。
今でこそ、「a」と「the」の違いを感覚で使い分けられるようになりました。
- This is an apple.
- This is the apple.
中学の時に習った
He was so tired that he canceled the party.
とか、高校で習うような、
I would appreciate, if you would have stopped smoking.
みたいなのも、まあなんとなくわかります。
ちなみに、中学の時の英語の平均を晒すと5段階で3、高校の時に英語の平均を晒すと5段階で2、大学での英語の成績は可がほとんどでした。
今でも英語を時折やっているのは、ずっと出来なかったので、英語コンプレックスがあって勉強しているだけです。
ちなみに、大学でスペイン語が第二外国語でした。成績の平均は優でしたけど…
ちなみに、大学で第三外国語にラテン語やっていました。成績の平均は優でしたけど…
ちなみに、大学で第四外国語でフランス語をやりました。成績は不可でした。
ちなみに、大学で必要にかられて第五外国語にイタリア語をやりました。授業を途中で出なくなりました。
ちなみに、大学入試センター試験での英語の成績は一回目154点、二回目197点でした。
ちなみに、某大学の後期試験の得点の配点は、英語100、数学100、物理300で、物理満点、数学80点、英語80点くらいで入学しました。
2012年1月3日火曜日
はじめてGrailsをさわるオッサンがGrails2.0でDomainを作ってみた
An elder engineer, new for Grails, got involved into a trouble on unit testing of Grails2.0 domain classes.
Grails2.0
昨年末にGrails2.0がリリースされました。
というわけで、正月のお休み期間を利用して触ってみることにしました。
とはいえ、実は初めてGrailsを触るので、『Grails徹底入門』をお手本に写経することにしました。
Grailsというのは、Spring、Hibernate、Groovyを元にして作られたJVM上で動作するWebアプリケーションフレームワークです。
設定よりも規約に準拠することにより高い生産性を発揮することを目標に作られています。
また、GroovyとJavaの親和性は高く、既存のJava資産を有効に活用できるフレームワークでもあります。
Domain
あらまし
アプリケーションを作成する場合、まず問題がどういった要素が関係しているか分析を行います。
これらの要素と関連はWebアプリケーションとか、Androidアプリケーションとかそういったプラットフォームに依存することなく存在します。
こういった要素と関連のことをModelと言ったり、Domainと言ったりします。
GrailsではDomainという言葉で指しているようです。
(テキトーなオッサンなのでツッコミ( `・∀・´)ノヨロシク)
BookとPublisher
『Grails徹底入門』では本屋さんを模してアプリケーションを作成していますので、本(Book)とか、出版社(Publisher)とかそういった類のDomainを定義しています。
というわけで、内容をパクって参考にして、BookとPublisherの関係を書いてみました。
関係性
まあ、難しい関係ではありませんね。
Bookからみて、Publisherは…
- 一つだけある。
- 必ず存在する。
という関係があります。
逆にPublisherからみて、Bookは…
- 複数ある。
- 存在しないこともある。
という関係があります。
まあ、こういう話は、ER図の本とか、データベース設計の本などの方が詳しいので、そちらに譲りましょう。
というわけで、このドメインをGrailsで作っていきたいと思います。
ドメインクラスの作成
create-app
まず、プロジェクトを作成します。
$ cd workspace
$ grails create-app BookShop
これで、
workspace
ディレクトリの下に次のような構造をもつBookShop
プロジェクトディレクトリが作成されます。なお、プロジェクト名が違っていますが、そこは、ほら、その、なんというか、大人な感じに、つまりいい感じに読んでいって下さい。
create-domain-class
次に、ドメインクラスを作成します。
$ cd BookShop
$ grails create-domain-class Publisher
$ grails create-domain-class Book
すると、次のようにDomainクラスとTestクラスが作成されます。
- grails-app
- domain
- bookshop
- Book.groovy
- Publisher.groovy
- test
- unit
- bookshop
- BookTests.groovy
- PublisherTests.groovy
これらの自動生成されたクラスを編集してドメインを実装していきます。
あと、
Order
とかいうクラスがすでに追加されていますが、そこも、ほら、あの、なんていうか、その、大人な感じで( `・∀・´)ノヨロシク。ドメインクラスの実装
メンバーを与える
先ほど書いた図を元にドメインクラスにメンバーを与えていきます。
Publisher.groovy
class Publisher {
String name
}
Book.groovy
class Book {
String name
String author
int price
Date releaseDate
String isbn13
String imageUrl
String description
}
はい、ここまでは難しくありません。
関係に関するメンバーを追加する
で、これに先ほどの関係のメンバーを付与します。
まず、
Publisher
の方ですが、Book
を複数持ちますので、hasMany
を用います。Publisher.groovy
class Publisher {
String name
static hasMany = [books: Book]
}
これによって、
Publisher
クラスにはbooks
というList<Book>
クラスのメンバーを持つことになります。同様に
Book
クラスにもPublisher
への関連性をもたせます。Book
クラスはPublisher
クラスを唯一つ持ちますので、belongsTo
を用います。Book.groovy
class Book {
String name
String author
int price
Date releaseDate
String isbn13
String imageUrl
String description
belongsTo = [publisher: Publisher]
}
これによって、
Books
クラスにはpublisher
というPublisher
クラスのメンバーを持つことになります。ちなみに、これはGroovyのうれしいところですが、
Groovy ではメンバーを記述するだけで、自動的に setter / getter を自動生成してくれる
という機能があります。
Plain Old Java Object : POJO みたいに、 Plain Old Groovy Object : POGOなんて呼ばれているとかなんとか…
制約 (Constraints) を追加する
さて、さきほど関係性だけを記述しましたが、これではまだ十分ではありません。
- 0個存在するとか、1個は必ず存在するとかの制約 (Constraints) の記述がない
- 本の名前がないとか、著者がないとか、価格がマイナスとかっておかしい
- 出版社の名前がないのというのもおかしい
関係性に関する制約にとどまらず、基本的な事柄に関する制約条件が満たされていません。
というわけで、これらの制約を盛り込んで行きましょう。
Publisher
まずは
Publisher
の方からですが、こんな制約が必要でしょうか…- 会社名の空白は禁止
- 会社名が他の会社とかぶってはいけない
まあ、実際には2の制約はないでしょうけど、まあここではそういうことにしておきましょうwww
このような制約を与える場合に使うのが、
constraints
です。では、
Publisher
に制約を与えてみましょう。Publisher.groovy
class Publisher {
String name
static hasMany = [books: Book]
static constraints = {
name(blank: false, unique: true)
}
}
追加した部分はこんな感じです。
- 会社名 (
name
) に対しては、空白 (blank
) は、禁止 (false
) 。 - 会社名 (
name
) は、唯一 (unique
) に決まること (true
) 。
これだけでいいんですか?これだけでいいんです( ー`дー´)キリッ
制約に関するテストを書く
疑心暗鬼に陥っているときは、テストを書いて安心するのがよいらしいです。
PublisherTests.groovy
@TestFor(Publisher)
class PublisherTests {
@Test
void validateName() {
def publisher = new Publisher(name: 'hoge')
assert publisher.validate()
}
}
とりあえず、名前のある会社は大丈夫だよねっていうテストを書いてみました。
ちなみに、コンストラクターのところにある記号、
name: 'hoge'
というのは、Groovy特有の書き方で、Javaで書くとこんな感じになります。
@TestFor(Publisher)
class PublisherTests {
@Test
void validateName() {
def publisher = new Publisher()
publisher.setName('hoge')
assert publisher.validate()
}
}
では、実行しましょう。
Grailsのテストサポート
Grails interactive
さて、テストを実行したいところですが、コマンド
grails test-app bookshop.Publisher
と実行するだけです。実行するだけなのですが、色々とコマンドを覚えるのが面倒ですね。
そこで、grailsのコンソールを起動して、そちらに任せてしまいましょう。
ちなみに、grailsのコンソールとテキトーに書いていますが、正確にはgrails interactiveというらしいです。
grailsのコンソールは何がいいかというと、もしコマンドがわからなければ、Tabを押すだけで、何を入力するべきか表示してくれます。
起動
起動方法は簡単です。
$ grails
と入力するだけです。
こんな感じでgrailsのコンソールが立ち上がります。
$ grails
| Enter a script name to run. Use TAB for completion:
grails>
何をするんですか?
何をすればいいかわかりませんね。Tabを押して下さい。
いろいろとコマンドが表示されます。
自分のやりたいコマンドを選ぶだけで構いません。
そうだテストをしよう
今はテストをやりたいので、
test-app
コマンドを入力します。でも、このコマンドはすべてのテストを実行するコマンドなので、若干不便です。
たった一つのクラスを変更しただけなのに、すべてのテストを実行するのは後々時間がかかって大変です。
そういうのはJenkins先生とかにお願いしましょう。
そこで、
test-app
まで入力して、Tabを押して下さい。どういうテストができるのか一覧が表示されます。
やりたいのは
Publisher
のテストなので、それっぽいやつを途中まで入力して、Tabを押します。
お、なんかいい感じに入力できるコマンドが指定されてきました。
Publisher
も途中まで入力して、Tabを押します。
勝手に補完してくれますね。これで、
Publisher
だけのテストを実行できます。では、おもむろに実行!
成功ですね。
え〜、ここでも、テストの個数が若干異なっていますが、そこは大人の事情ということで…
ちゃんとPublisherのテストを書く
blankに対するテストを書く
さて、今のテストはただ単に成功するだけの条件を書いたので、あまり意味のあるテストではありません。
そこでnameのvalidationに対するテストを書いていきます。
name
がnull
だったらエラーとなるか?name
が長さ0の文字列だったらエラーとなるか?
まず、この二つは確実に抑えておきたいところです。
これについてテストを書いていきます。
PublisherTests.groovy
@TestFor(Publisher)
class PublisherTests {
@Test
void validateName() {
// name が null の場合
def publisher = new Publisher()
assert publisher.validate() == false
// name が '' の場合
publisher = new Publisher(name: '')
assert publisher.validate() == false
// name が長さ1以上の文字列の場合
publisher = new Publisher(name: 'hoge')
assert publisher.validate()
}
}
テストを実行。
はい、成功です。
uniqueに対するテストを書く
さて、
Publisher
の制約条件にunique
というのがありました。読んで字の如くで、同じ名前の会社が登録されていたら、エラーとするというものなのですが、データベースが必要になってきます。
面倒くさそうになって来ました。
そこでGrailsでは、Unitテストにおいてデータベースがなくてもキャッシュだけでテストを行えるような仕組みを提供しています。
mockForConstraintsTests(Class<T>, List<T>)
を用いてテストを実行します。PublisherTests.groovy
@TestFor(Publisher)
class PublisherTests {
@Test
void validateName() {
def existingPublisher = new Publisher(name: 'exists')
mockForConstraintsTests(Publisher, [existingPublisher])
// name が null の場合
def publisher = new Publisher()
assert publisher.validate() == false
// name が '' の場合
publisher = new Publisher(name: '')
assert publisher.validate() == false
// name がすでに存在する会社の名前と一致する場合
publisher = new Publisher(name: 'exists')
assert publisher.validate() == false
// name が長さ1以上の文字列の場合
publisher = new Publisher(name: 'hoge')
assert publisher.validate()
}
}
では、テストを実行してみましょう。
テスト通りました。
締め
以上、gdgdな感じの紹介になりましたが、こんな感じでDomainを作っていきます。
本当はもっとハマリどころがあるんですが、その前段まででめちゃくちゃ長くなってしまったので、ハマリどころについては次回やります。
ん、インストール方法が載っていない?
zipをダウンロードしてパスを通してあげて下さい。
2012年1月1日日曜日
Summary of 2011 and objective of 2012
About 2011
From my impression, changes are ...
- Found new jobs at TopGate Inc.
- Attracted Google's technologies.
- Attracted Groovy programming language.
- Trying to do off-shore work in Vietnam.
About No.2
I just started to study Android technologies at a community named Saitama Android Board.
As I learned Android technologies, I found that there are limitation of Android to create an interesting application without any server or any service.
So I had become tending to learn cloud technologies like Google App Engine.
About No.1
And it was good time to learn Google App Engine because my former company gave me a time to learn Google technologies. But in my former company there is some wasting and boring procedure to search and to learn new technologies. So I decided to change my job, to get a new environment. And luckily vvakame, one of my twitter friend, told me to work together in TopGate Inc where there are some programmers familiar with Google technologies. And I changed my employment from former one to TopGate Inc.
About No.3
At the same time to change my job, I was introduced to Groovy programming language. It was kimkou_26, one of my twitter friend, that told me the most powerful and exciting language. Groovy works on Java Virtual Machine with supporting almost all of Java technologies and with light syntax. Groovy attracted me very much. And with Groovy I met some programmers on groovy community.
If you ask me to decide which gave more impact on me, Google or Groovy, it is too difficult for me to decide. Because the objective is different and I love both technologies.
About No.4
Working foreign country become common to programmers in Japan. Because Japanese Yen is becoming so strong among these days that it costs higher to employ Japanese than to employ Chinese or Vietnamese for them to do same thing. In my project it finished in failure. But I'll get success on off-shore projects this year.
Next 2012
I'd like to work as listed bellow.
- To work on Google Apps Installation
- Create TopGate's additional value
- To get success on off-shore project
About No.3
As I mentioned before, I'd like to get success in off-shore projects. From the view of the cost of project to work outside Japan cannot be ignored.
About No.1
This is my objective to work installation Google Apps to a customer. It seems Google considers Google Apps as their most successful cloud technology. And I think the tendency of companies to move from owning their server to using existing service becomes more popular. So it is business chance to become major company.
About No.2
TopGate Inc. is the re-seller of Google technologies. But I want to add additional G technology, I call it Yet Another G Technology. I mean Groovy and its co-production, like Grails, Griffon, Gradle, with these production we can offer some solutions faster than ordinal technologies. And this may cause create a value for our customer. By becoming familiar with these technologies, we -- TopGate Inc. -- will be able to establish our excellent brand image.
To reader of this blog and to another person, thank you this year!