2012年1月22日日曜日

My aunt's too sudden death

Yesterday my father told me that two or three days ago my aunt had died suddenly in cancer. She had finished fourty to fifty years life that is shorter than Japanese average.

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してみる。

出展はいつもどおりの『Grails徹底入門』
の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のドメインクラスにあるフィールドはデフォルトでnullablefalseのようです。

適当に制約をいれていく


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>


リレーションに関するフィールドの追加とテスト


次にリレーションに関するフィールドの追加とテストです。

先に掲載したモデルから、ShipmentWarehouseOrderの関係は、次のようになります。

  • 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を書いてみた

ツイッター上で、Objective-Cの本について、

テストを書こう



つぶやいたお陰で、なんかUnit Testを書くことになったような雰囲気…


とありあえず、簡単なテストを書いてみた。







FirstViewController.mは、まあ、名前から想像できる通り、画面の操作系のオブジェクトです。

ここに、画面の操作(Controller)と画面表示(View)に関係のない部分 = 日付のフォーマット(Model)があったので、Modelの部分についてはテストを書けるだろうということで、書いたテストが上の2つのテストです。

やってみてちょっと判ったこと


NSString系の文字列の扱いがよくわかっていないので、時間が妙にかかった。

このあたりは本で知識を補強していく必要があるっぽい。




2012年1月9日月曜日

#日本鼻メガネの会 に参加してみた的な

参加までの経緯


なんのことやらわからず参加しました。

多分、参加することになった理由は謎のハッシュタグ

#日本鼻メガネの会

ですね。

なんですかこの怪しげな響きは…と調べていくと、

日本鼻メガネの会 新年会

十分に怪しい…

謳い文句もなんだか怪しい…

IT系勉強会でひそかなブームになりつつある鼻メガネを愛でる会です

え、ブーム、そんなのブームなのか?!

だが、もっと怪しいのが参加者の面々。

Twitterでよく見かける人ばっかり…

定員15人で、参加者14人、キャンセル1人だったので、参加できるっぽかったので、とりあえず趣旨はよくわからんが参加ポチった。

当日


とりあえず、鼻メガネは必要そうだったので、歌舞伎町のドンキホーテで鼻だけ購入。

会場は新宿角海老の裏参考:新宿角海老(R-20限定)

とりあえず、店の名前よく覚えていなかったので(今でも思い出せない…)新宿角海老のあたりをウロウロしていたら、風俗関連のお兄さんに「お兄さん、どのお店探しているの?」と声をかけられました。

いや、おっ◯いパブとか興味ないから…

とりあえず、@shinyaa31さんのおかげで会場にたどり着きましたが、

ツイッターアイコンしか知らんので顔が誰が誰かようわからん…

いつもどおり、コーラをがぶ飲みしておきました。

当日の様子などは以下のエントリーなどが詳しいのでそちらを参照下さい。


他にも多数あるけど、まあ、ようまとめきれんです。

結論


勉強会で知り合ったクラスタとか、Twitterで知り合ったクラスタとの、gdgdなオフ会意見交換会も面白いですね。

2012年1月7日土曜日

Grails2.0のDomainのUnit Testハマリどころ

今日はGrailsのDomainテストのハマリどころについてのメモです。
と言っても、ひとつしか書いていませんが…

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にはauthorpriceというメンバーが存在します、いや、するはずです。

では、本当に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.0constraintsValidationテストをする場合は、黙って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 -- マルクス『経済学・哲学草稿』

さてこのエントリは…


巷のエンジニアで話題のテーマ:設計に関するエントリ


の2つのエントリーを読んで、ちょっと微妙な横槍を失敗したオフショアでの現場の技術者についての評価をたまたまやったので、そんな話をしつつ、これまた巷のエンジニアで話題のテーマである英語について


和書じゃないと売れないなんて、おまいら何してんだと叱責しつつ、たまたま読んでいたカール・マルクスの『経済学・哲学草稿』(岩波文庫)のある一説を踏まえて、昨今の話題になっている少子化および就職難からショッキングな一節を引用して、少子化就職難について論じてみるという無謀な試みをしたいと思います。

まあ、色々と取り込んだ関係上、焦点がぼやけていますので、少し対象読者を絞りつつ書きたいと思います。

対象読者


  • 英語を読むのが苦痛というか、日本語の文献しか読まないというか、日本語の文献も読まないエンジニア
  • 大学でまともに勉強しないで、就職活動に勤しむアレな人とそれを強いる企業の人事部
  • 要求と仕様と実装の板挟みに合っている人
  • リブ管理というお仕事で、決められたフローに基づき朝に申請を受けたソースを夕方頃やっと編集していいよとドヤ顔している超高速な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というのは、SpringHibernateGroovyを元にして作られた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に対するテストを書いていきます。

  • namenullだったらエラーとなるか?
  • 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

Now looking back to 2011, there was some change in my environment.

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!