ラベル アーキテクチャ の投稿を表示しています。 すべての投稿を表示
ラベル アーキテクチャ の投稿を表示しています。 すべての投稿を表示

2012年9月20日木曜日

Groovy!!(Linuxに環境構築編)


Groovyきわめる!

まずはLinuxに環境構築する

前提確認。OS.
# uname -a
Linux polyrhythm.e2info.co.jp 2.6.32-220.el6.x86_64 #1 SMP Tue Dec 6 19:48:22 GMT 2011
x86_64 x86_64 x86_64 GNU/Linux

種類わかったから以下。
# cat /etc/redhat-release
CentOS release 6.2 (Final)

あとJava
java version "1.7.0_05-icedtea"
OpenJDK Runtime Environment (rhel-2.2.1.el6_3-x86_64)
OpenJDK 64-Bit Server VM (build 23.0-b21, mixed mode)


Groovyインストール!

バイナリ取得
[root@polyrhythm tmp]# cd /tmp
[root@polyrhythm tmp]# wget http://dist.groovy.codehaus.org/distributions/groovy-binar


展開と移動
[root@polyrhythm tmp]# unzip groovy-binary-2.0.2.zip
[root@polyrhythm tmp]# mv groovy-binary-2.0.2/ /usr/share/


シンボリックリンク(必須じゃない)
[root@polyrhythm share]# mv /usr/share/
[root@polyrhythm share]# ln -s /usr/share/groovy-2.0.2/ groovy


パス設定(本当は~/.bash_profileで。)
[root@polyrhythm share]# PATH=$PATH:/usr/share/groovy/bin/
[root@polyrhythm share]# export PATH

要チェック!
[root@polyrhythm share]# groovy -v
Groovy Version: 2.0.2 JVM: 1.6.0_24 Vendor: Sun Microsystems Inc. OS: Linux
やった。

コード実行
[root@polyrhythm e2info]# vi hw.groovy
println "Hello World!"

[root@polyrhythm e2info]# groovy hw.groovy
Hello World!

Groovyさいこう!

かねこ(^-^)

2012年9月14日金曜日

Jenkins先生とIRCの連携の巻

IRCサーバうごいたので、早速Jenkinsのビルド結果をIRCサーバに送ってみよう。
JenkinsにはIRC Pluginがあるので導入。

Jenkinsの管理→プラグインの管理→Jenkins IRC Plugin



「Jenkinsの管理」→「システムの設定」にIRC Nortification発見!有効に。


ビルドしてみる…jenkins-botきた!わーい


いや、なんかしろ(笑)

気を取り直して設定見直し。
プロジェクト単位の設定の方にあった。


再度ビルド。



できたー!連携サイコー!
IRC用のちっちゃいモニター欲しい。

かねこ( ^ω^ )

2012年9月10日月曜日

MVCとMOVE

世間ではMVC is dead, it's time to MOVE on.和訳)の話題が花盛り♪

ちょっと見てみた。

MVC is a phenomenal idea. You have models, which are nice self-contained bits of state, views which are nice self-contained bits of UI, and controllers which are nice self-contained bits of …

What?

I'm certainly not the first person to notice this, but the problem with MVC as given is that you end up stuffing too much code into your controllers, because you don't know where else to put it.

これの、too much code into your controllers, because~ の下り、イマイチ(><)

実際は、MVCのモデルの領域は、”データと手続き”の部分なので、Controllerが誇大化する場合は、そもそもModelの扱い方を間違えてるのではないかと思います(よくあるのは、ControllerからDAO操作してるとか)

ということで、MVC死んでねー

MOVEは一読してよくわからなかったので、次回お勉強してみようと思います。

かねこ( ・`д・´)

2012年4月9日月曜日

MongoDB(5) シャーディング

今日はMongoDBのシャーディングをやってみよう。

shardingとは: Shard(database_architecture)
mongoのシャーディング: Sharding

はじめにデータベース起動(とりあえず3つ)
mongod --dbpath=d:\xampp\mongodb\data\shard1 --port 28017
mongod --dbpath=d:\xampp\mongodb\data\shard2 --port 28018
mongod --dbpath=d:\xampp\mongodb\data\shard3 --port 28019


コンフィグサーバ起動
mongod --configsvr --port 28099 --dbpath=d:\xampp\mongodb\data\config


ルーティングプロセス起動

(デフォルトチャンクサイズは200MBだけど、テストのために3MBに指定)
mongos --configdb localhost:28099 --port 28100 --chunkSize 3


ここまでで、サーバ群起動完了。
次に、shardingの設定をする。


mongo起動、adminデータベースに接続
D:\xampp\mongodb\bin>mongo localhost:28100/admin
MongoDB shell version: 2.0.3
connecting to: localhost:28100/admin


shardサーバ追加
mongos> db.runCommand({addshard:"localhost:28017"});
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> db.runCommand({addshard:"localhost:28018"});
{ "shardAdded" : "shard0001", "ok" : 1 }
mongos> db.runCommand({addshard:"localhost:28019"});
{ "shardAdded" : "shard0002", "ok" : 1 }


ステータス確認
mongos> db.rintShardingStatus();
--- Sharding Status ---
  sharding version: { "_id" : 1, "version" : 3 }
  shards:
        {  "_id" : "shard0000",  "host" : "localhost:28017" }
        {  "_id" : "shard0001",  "host" : "localhost:28018" }
        {  "_id" : "shard0002",  "host" : "localhost:28019" }
  databases:
        {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }

mongos>



shardキーを指定
mongos> db.runCommand({shardcollection:"test.test",key:{userid:1}});
{ "ok" : 0, "errmsg" : "sharding not enabled for db" }


おこられた(><)

データベースにsharding許可を指示
mongos> db.runCommand({enablesharding:"test"});
{ "ok" : 1 }



再度挑戦
mongos> db.runCommand({shardcollection:"test.test",key:{userid:1}});
{ "collectionsharded" : "testdb.test", "ok" : 1 }

ていうか、これ、コレクション単位でshardできるのか。すごい柔軟。



ルーティングサーバに接続して、テストデータ投入。
D:\xampp\mongodb\bin>mongo localhost:28100
MongoDB shell version: 2.0.3
connecting to: localhost:28100/test
mongos>



100万件くらい、いれればいいかな。
mongos> for(var i =0; i<1000000; i++) {
... var doc = {userid:i, name:"user"+i};
... db.test.save(doc);
... }


状況確認
mongos> db.runCommand({addshard:"localhost:28017"});db.printShardingStatus();
--- Sharding Status ---
  sharding version: { "_id" : 1, "version" : 3 }
  shards:
        {  "_id" : "shard0000",  "host" : "localhost:28017" }
        {  "_id" : "shard0001",  "host" : "localhost:28018" }
        {  "_id" : "shard0002",  "host" : "localhost:28019" }
  databases:
        {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
        {  "_id" : "testdb",  "partitioned" : true,  "primary" : "shard0000" }
        {  "_id" : "test",  "partitioned" : true,  "primary" : "shard0000" }
                test.test chunks:
                                shard0000       8
                                shard0001       7
                                shard0002       14
                        too many chunks to print, use verbose if you want to force print


状況確認2
mongos> db.test.count();
1000000


100万件はいってる。


接続先を個別のデータベースに変えて確認
D:\xampp\mongodb\bin>mongo localhost:28017
MongoDB shell version: 2.0.4
connecting to: localhost:28017/test
> db.test.count();
162515

D:\xampp\mongodb\bin>mongo localhost:28018
MongoDB shell version: 2.0.4
connecting to: localhost:28018/test
> db.test.count();
171400

D:\xampp\mongodb\bin>mongo localhost:28019
MongoDB shell version: 2.0.4
connecting to: localhost:28019/test
> db.test.count();
666085

合計100万件はいってる。ナイス。

というわけで、MongoDB編おしまい。

かねこ( ;∀;)

2012年3月28日水曜日

MongoDB(4) レプリケーション

概要

CRUDはいい加減おもしろくないですが、MongoDBのレプリケーションは簡単で面白いらしいよ。ということで、やってみる。

まず、レプリケーションのアーキテクチャにMaster/SlaveReplica Sets(+Replica Pair)がある。

新しいバージョンのMongoDBが導入できるならReplica Sets。

とくちょう

・Data Redundancy
・Automated Failover
・High Availability
・Distributing read load
・Simplify maintenance (compared to "normal" master-slave)
・Disaster recovery
日本語訳と違う(><)


レプリカ用ディレクトリ作成
D:\xampp\mongodb\data
┗rep1
┗rep2
┗rep3



レプリカセット起動
mongod --replSet rep_test --port 27017 --dbpath ../data/rep1
mongod --replSet rep_test --port 27018 --dbpath ../data/rep2
mongod --replSet rep_test --port 27019 --dbpath ../data/rep3

rep_testがレプリカセットの名前。

起動したけど、初期化してないから警告が出てる
Wed Mar 28 07:48:44 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)



レプリカセット初期化
D:\xampp\mongodb\bin>mongo

MongoDB shell version: 2.0.3
connecting to: test
> config = {_id: 'rep_test', members: [
{_id: 0, host: '127.0.0.1:27017'},
{_id: 1, host: '127.0.0.1:27018'},
{_id: 2, host: '127.0.0.1:27019'}]
};

rs.initiate(config);
{
        "info" : "Config now saved locally.  Should come online in about a minute.",
        "ok" : 1
}
>


initiate()すると、初期化がはじまってPrimary/Secondaryが選択される
[rsStart] replSet STARTUP2
[rsSync] ******
[rsSync] creating replication oplog of size: 47MB...
[rsSync] ******
[rsSync] replSet initial sync pending
[rsSync] replSet initial sync need a member to be primary or second initial sync
[rsHealthPoll] replSet member 127.0.0.1:27017 is up
[rsHealthPoll] replSet member 127.0.0.1:27017 is now in state SECONDARY
[rsHealthPoll] replSet member 127.0.0.1:27018 is up
[rsHealthPoll] replSet member 127.0.0.1:27018 is now in state SECONDARY
[rsSync] replSet initial sync finishing up


なぜか27019がマスタに。



状態確認
PRIMARY> rs.status()
{
        "set" : "rep_test",
        "date" : ISODate("2012-03-27T23:03:25Z"),
        "myState" : 1,
        "syncingTo" : "127.0.0.1:27019",
        "members" : [
                {
                        "_id" : 0,
                        "name" : "127.0.0.1:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "SECONDARY",
                        "optime" : {
                                "t" : 1332888980000,
                                "i" : 1
                        },
                        "optimeDate" : ISODate("2012-03-27T22:56:20Z"),
                        "self" : true
                },
                {
                        "_id" : 1,
                        "name" : "127.0.0.1:27018",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 422,
                        "optime" : {
                                "t" : 1332888980000,
                                "i" : 1
                        },
                        "optimeDate" : ISODate("2012-03-27T22:56:20Z"),
                        "lastHeartbeat" : ISODate("2012-03-27T23:03:25Z"),
                        "pingMs" : 0
                },
                {
                        "_id" : 2,
                        "name" : "127.0.0.1:27019",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "PRIMARY",
                        "uptime" : 159,
                        "optime" : {
                                "t" : 1332888980000,
                                "i" : 1
                        },
                        "optimeDate" : ISODate("2012-03-27T22:56:20Z"),
                        "lastHeartbeat" : ISODate("2012-03-27T23:03:24Z"),
                        "pingMs" : 0
                }
        ],
        "ok" : 1
}


自動フェイルオーバーの確認

PRIMARYを落としてみる
[rsHealthPoll] replSet member 127.0.0.1:27019 is now in state DOWN


状態確認
PRIMARY> rs.status()
{
        (略)
        "members" : [
                {
                        "_id" : 0,
                        "name" : "127.0.0.1:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        (略)
                },
                {
                        "_id" : 1,
                        "name" : "127.0.0.1:27018",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        (略)
                },
                {
                        "_id" : 2,
                        "name" : "127.0.0.1:27019",
                        "health" : 0,
                        "state" : 8,
                        "stateStr" : "(not reachable/healthy)",
                        (略)
                }
        ],
        "ok" : 1
}

27017がPRIMARYになった。

27019復活
mongod --replSet rep_test --port 27019 --dbpath ../data/rep3


状態確認
PRIMARY> rs.status()
{
        (略)
        "members" : [
                {
                        "_id" : 0,
                        "name" : "127.0.0.1:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        (略)
                },
                {
                        "_id" : 1,
                        "name" : "127.0.0.1:27018",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        (略)
                },
                {
                        "_id" : 2,
                        "name" : "127.0.0.1:27019",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        (略)
                }
        ],
        "ok" : 1
}

27019はSECONDARYとして復活。

master/secondaryノードの決定は、各サーバの多数決で決定される。


というわけで、うわさどおり簡単で面白かったです。

かねこ(ゝω・)



2012年3月26日月曜日

MongoDB(3) クエリ速習

クエリに挑戦!

サンプルデータ
> db.example.remove()
> for(var i =0; i<6; i++) {
... var doc = {name:'user'+i, point: i*1000};
... db.example.save(doc);
... }
>

全件検索
> db.example.find()
{"_id":ObjectId("4f69766ea84ad157af92c6ab"),"name":"user0","point":0}
{"_id":ObjectId("4f69766ea84ad157af92c6ac"),"name":"user1","point":1000}
{"_id":ObjectId("4f69766ea84ad157af92c6ad"),"name":"user2","point":2000}
{"_id":ObjectId("4f69766ea84ad157af92c6ae"),"name":"user3","point":3000}
{"_id":ObjectId("4f69766ea84ad157af92c6af"),"name":"user4","point":4000}
{"_id":ObjectId("4f69766ea84ad157af92c6b0"),"name":"user5","point":5000}

条件検索
> db.example.find({point:2000})
{ "_id" : ObjectId("4f69766ea84ad157af92c6ad"), "name" : "user2", "point" : 2000 }

ソート(昇順)
> db.example.find().sort({point:1})
{ "_id" : ObjectId("4f69766ea84ad157af92c6ab"), "name" : "user0", "point" : 0 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6ac"), "name" : "user1", "point" : 1000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6ad"), "name" : "user2", "point" : 2000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6ae"), "name" : "user3", "point" : 3000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6af"), "name" : "user4", "point" : 4000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6b0"), "name" : "user5", "point" : 5000 }

ソート(降順)
> db.example.find().sort({point:-1})
{ "_id" : ObjectId("4f69766ea84ad157af92c6b0"), "name" : "user5", "point" : 5000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6af"), "name" : "user4", "point" : 4000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6ae"), "name" : "user3", "point" : 3000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6ad"), "name" : "user2", "point" : 2000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6ac"), "name" : "user1", "point" : 1000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6ab"), "name" : "user0", "point" : 0 }

リミット
>db.example.find().limit(2)
{ "_id" : ObjectId("4f69766ea84ad157af92c6ab"), "name" : "user0", "point" : 0 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6ac"), "name" : "user1", "point" : 1000 }

オフセット
> db.example.find().skip(4)
{ "_id" : ObjectId("4f69766ea84ad157af92c6af"), "name" : "user4", "point" : 4000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6b0"), "name" : "user5", "point" : 5000 }

リミット&オフセット(ページング)
> db.example.find().skip(2).limit(2)
{ "_id" : ObjectId("4f69766ea84ad157af92c6ad"), "name" : "user2", "point" : 2000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6ae"), "name" : "user3", "point" : 3000 }

条件演算子(条件演算子一覧はここ
> db.example.find({point:{$gte:3000}})
{ "_id" : ObjectId("4f69766ea84ad157af92c6ae"), "name" : "user3", "point" : 3000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6af"), "name" : "user4", "point" : 4000 }
{ "_id" : ObjectId("4f69766ea84ad157af92c6b0"), "name" : "user5", "point" : 5000 }


カーソル
> var cursor = db.example.find();

> cursor.hasNext()
true

> cursor.next()
{
        "_id" : ObjectId("4f69766ea84ad157af92c6ab"),
        "name" : "user0",
        "point" : 0
}

>while (cursor.hasNext()){printjson(cursor.next());}
{
        "_id" : ObjectId("4f69766ea84ad157af92c6ac"),
        "name" : "user1",
        "point" : 1000
}
{
        "_id" : ObjectId("4f69766ea84ad157af92c6ad"),
        "name" : "user2",
        "point" : 2000
}
{
        "_id" : ObjectId("4f69766ea84ad157af92c6ae"),
        "name" : "user3",
        "point" : 3000
}
{
        "_id" : ObjectId("4f69766ea84ad157af92c6af"),
        "name" : "user4",
        "point" : 4000
}
{
        "_id" : ObjectId("4f69766ea84ad157af92c6b0"),
        "name" : "user5",
        "point" : 5000
}

まとめ

MongoDBのクエリー単純で簡単。

かねこ(~_~)

2012年3月22日木曜日

MongoDB(2) はろーわーるど

つづき。MongoDBをつかってみます。

mongoシェルログイン
> mongo
MongoDB shell version: 2.0.3
connecting to: test
>

testデータベース(?)にログインしたっぽい。

create tableどーやるんだ。
ヘルプで確認。
> help
  db.help()                    help on db methods
  db.mycoll.help()             help on collection methods
  rs.help()                    help on replica set methods
  help admin                   administrative help
  help connect                 connecting to a db help
  help keys                    key shortcuts
  help misc                    misc things to know
  help mr                      mapreduce
  show dbs                     show database names
  show collections             show collections in current database
  show users                   show users in current database
  show profile                 show most recent system.profile ....
  show logs                    show the accessible logger names
  show log [name]              prints out the last segment of log in ....
   use                 set current database
   db.foo.find()                list objects in collection foo
  db.foo.find( { a : 1 } )     list objects in foo where a == 1
  it                           result of the last line evaluated; use to further iterate
  DBQuery.shellBatchSize = x   set default number of items to....
  exit                         quit the mongo shell

create table ない。

もういっこのヘルプ参照
>db.mycoll.help()
DBCollection help
  db.mycoll.find().help() - show DBCursor help
  db.mycoll.count()
  db.mycoll.dataSize()
  db.mycoll.distinct( key ) - eg. db.mycoll.distinct( 'x' )
  db.mycoll.drop() drop the collection
  db.mycoll.dropIndex(name)
  db.mycoll.dropIndexes()
  db.mycoll.ensureIndex(keypattern[,options]) - options is an object withthese ....
  db.mycoll.reIndex()
  db.mycoll.find([query],[fields]) - query is an optional query filter. fields is op....
  db.mycoll.find(...).count()
  db.mycoll.find(...).limit(n)
  db.mycoll.find(...).skip(n)
  db.mycoll.find(...).sort(...)
  db.mycoll.findOne([query])
  db.mycoll.findAndModify( { update : ... , remove : bool [, query: {}, sort: {}, 'new': false] } )
  db.mycoll.getDB() get DB object associated with collection
  db.mycoll.getIndexes()
  db.mycoll.group( { key : ..., initial: ..., reduce : ...[, cond: ...] })
  db.mycoll.mapReduce( mapFunction , reduceFunction ,  )
  db.mycoll.remove(query)
  db.mycoll.renameCollection( newName ,  ) renames the collection.
  db.mycoll.runCommand( name ,  ) runs a db command with the gi....
  db.mycoll.save(obj)
  db.mycoll.stats()
  db.mycoll.storageSize() - includes free space allocated to this collection
  db.mycoll.totalIndexSize() - size in bytes of all the indexes
  db.mycoll.totalSize() - storage allocated for all data and indexes
  db.mycoll.update(query, object[, upsert_bool, multi_bool])
  db.mycoll.validate(  ) - SLOW
  db.mycoll.getShardVersion() - only for use with sharding
  db.mycoll.getShardDistribution() - prints statistics about data distribution in the cluster

みつからず。

mycollってのはコレクションのことっぽい。

ていうか、もしかして、
>db.example.save({name:'myname'})
>db.example.find();
{ "_id" : ObjectId("4f69656db3855bee2fdca9f2"), "name" : "myname" }

スキーマレスってそういうことかー。 すごい。
>db.example.save({age: 50})
>db.example.find()
{ "_id" : ObjectId("4f69656db3855bee2fdca9f2"), "name" : "myname" }
{ "_id" : ObjectId("4f696610b3855bee2fdca9f3"), "age" : 50 }

カオス!
> db.example.find({age: 50})
{ "_id" : ObjectId("4f696610b3855bee2fdca9f3"), "age" : 50 }

おもしろい!


まとめ

MongoDBはFacebookのデータ構造に近い。

かねこ(*´σ`)



2011年12月5日月曜日

おさらい(1)ソフトウェア内部アーキテクチャ

さて、勢いにのってガリガリとコードを書きたかったのですが、そんな時間はありませんでした。

なので、そういえば書きたかったシステムの設計について書いてみようと思います。
だいいちだん、ソフトウェア内部構造のまき。

ちなみにこれは、某Challenging Tomorrow's Changesな会社のSFAシステム構築プロジェクトに僕とまっちゃんコンビで参画したときに、お師匠のたなかみつるさんに教えてもらったアーキテクチャで、わずか数ヶ月の間にみにつけたこの設計技法は、その後何年間もずーっと、僕のシステム設計思想のベースになっているものです。ありがとう、お師匠。げんきか、まっちゃん。

というわけで、絵をかいてみました。
  • N層アーキテクチャは導入必須。層を分離しないとテストコードが書けない。
  • テストコード必須。テストコード書かないと、機能追加の際に一定ライン以上の品質を保証することができません。あと、漠然とした不安につきまとわれます。
  • 基本的にMVCパターンの適用は必須で、要件と複雑さに応じて層を設計します。上の図は中間規模の業務システムを構築するときに設計のベースとしているMVC+Serviceでの設計。もう少し大規模になると、サービス層と永続化層の間にLogic層を挟むことを検討する。
  • View層(プレゼンテーション層)にはテンプレートエンジンを導入。JavaだとVelocityとかFreeMarker、PHPはSmartyなど。PHP自体がテンプレートエンジンだけど、そのレベルでは保守性からみてダメで、ちゃんと処理・データとテンプレートが分離されている必要がある。
  • Controller層では、View層(ブラウザ)からのリクエストを受け取って、ビジネスロジックに繋ぐ。Controllerにはビジネスロジックは記述しない。1画面(や、1機能)に対して1コントローラが存在する設計(P of EAAのPage Controllerパターン)と、システム内で一つのコントローラがすべてのリクエストをハンドリングする方法(P of EAAのFront Controllerパターン)があって、別にどっちでもいい。
  • Service層(ロジック層)は、Session Facadeとして定義。トランザクションを意識した設計にする。
  • 永続化層は、どの言語でもすぐれたフレームワークがたくさんあるので導入する。種類が色々あるので特性を理解して選定する。というか、実は選定はどれでもよくて、メンバーに特性を理解させることが重要。
  • DaoとEntityにMockオブジェクトを定義するのは、Service層の自動テストを書くときにMockオブジェクトを利用したテストを実行するため。あとは、ビルドパラメータでmock/releaseの切り替えできるようにしておくことで、データベースに接続できない環境で画面を動かすことができる。
  • また、某所では、サービス層のMockオブジェクトも定義するルールになっていて、プレゼンテーション層とロジック部分の開発の切り離しをしていた。これも上手くまわっていた。
  • 上図にでてきていない部分としては、例外設計とログ設計重要。ちゃんとやる。あと、パターンの理解重要。同じ用語と概念でシステムについての会話ができるようになる。
そんなこんなで、なんでこんなことするかというと、すべては「テストを書きやすくするため」です。
TDDまでいかなくても、テストまで書くサイクルがきちんと回っているプロジェクトの場合、そうでないプロジェクトと比較すると品質がとてもよいです。経験上。
で、テストをちゃんと書くするために、層を分離しましょうということになります。その結果、コンポーネントの独立性がたかくなって、保守もやりやすくなる。まさに、いいことずくめ。

自動テスト実行、自動ビルド、構成管理、カバレッジ、メトリクス、コード規約、コードの自動精査など、他にもまだまだおもしろそうな話題がいろいろありますよ。

というわけで、つづく。
やっぱりコード書けばよかった。

かねこ( ´_ゝ`)