### Config File
設計 Config File 在寫程式時是一個必定會出現的事情,在 Javascript 的世界裏我們可以使用 JSON 檔案來儲存系統的 Config。而在使用 JSON 時又一定會使用到 Tree 的方法來儲存資料。看看以下的例子 `Config.json` :
```json
{
"app":{
"port":80,
"db":{
"host":"db.abc.com",
"port":3306,
"user":"myuser",
"password":"mypassword",
"database":"myproject"
}
}
}
```
大概有 80% 的系統都會有以下的設定了,最基本的 Database 連線設定檔。
當我們要使用參數時,可以直接匯入要 JSON 檔案然後經 Object 存取資料。
```js
import Config from 'Config.json';
// connect to db
const connectDB = () => {
var host = Config.app.db.host || 'default host name';
var port = Config.app.db.port || 3306;
var user = Config.app.db.user || 'default user';
var password = Config.app.db.password || 'default password';
var database = Config.app.db.database || 'default database';
};
```
以上的方法可以把資料從 Config 中讀取出來,還可以設定他們的預設值。但是有一個問題,就是如果 Config 的路徑內有其中一個環節斷掉,程式就會 throw error。例如 :
```js
// config
const Config = {
"port":80,
"db":{
"host":"db.abc.com",
"port":3306,
"user":"myuser",
"password":"mypassword",
"database":"myproject"
}
}
// connect db
const connectDB = () => {
var host = Config.app.db.host || 'default host name';
var port = Config.app.db.port || 3306;
var user = Config.app.db.user || 'default user';
var password = Config.app.db.password || 'default password';
var database = Config.app.db.database || 'default database';
};
```
因為 Config 中沒有 app 這個屬性存在,所以當運行到 assign host 那句時,就會 throw error 了 !!!
### 解決方法
要解決問題,可以加入檢查就可以了 :
```js
// check every node of config path
var host = (Config && Config.app && Config.app.db && Config.app.db.host? Config.app.db.host: undefined);
```
以上方法可以確保萬無一失,不過又好像寫得太長 !!
### Configuration File 平整化
平整化就是把一個立體的 model 變成為一個單純的 array。我們可以通過 Database First Normalization Form 來達成目的。以下為例 :
```json
{
"app":{
"port":80,
"db":{
"host":"db.abc.com",
"port":3306,
"user":"myuser",
"password":"mypassword",
"database":"myproject"
}
}
}
```
平整化後可以變成為 :
```json
{
"app":{
"port":80,
"db":{
"host":"db.abc.com",
"port":3306,
"user":"myuser",
"password":"mypassword",
"database":"myproject"
}
},
"app.port":80,
"app.db":{
"host":"db.abc.com",
"port":3306,
"user":"myuser",
"password":"mypassword",
"database":"myproject"
},
"app.db.host":"db.abc.com",
"app.db.port":3306,
"app.db.user":"myuser",
"app.db.password":"mypassword",
"app.db.database":"myproject"
}
```
處理好後像 Config 的 Route 檔案,一個 KEY 可以對應到一個 VALUE。在使用上便簡單得多了。
```js
import Config from 'Config.json';
// connect to db
const connectDB = () => {
var host = Config['app.db.host'] || 'default host name';
var port = Config['app.db.port'] || 3306;
var user = Config['app.db.user'] || 'default user';
var password = Config['app.db.password'] || 'default password';
var database = Config['app.db.database'] || 'default database';
};
```
這樣就算其中的一層參數繼掉了,也不會 throw error,而是回傳 `undefined`。
### 如何實作平整化
由於 Config 是一種不轉變的資料,所以我們在 Build 時可以使用 Script 產生 Config 檔案。另一個方法是在 Runtime 是進行。而當然前者的效能會較為好,而後者就有更大的彈性。
```js
import Config from 'config';
/**
* flat config
*/
const flatConfig = (config, path) => {
// result
var result = {};
// init config
config = config || Config;
// init path
path = path || 'Config.';
// each config attribute
for( var i in config ) {
result[path + i] = config[i];
if( typeof config[i] === 'object' ) {
result = {
...result,
...flatConfig(config[i], path + i + '.')
};
}
}
// return
return result;
};
/**
* read config attribute
*/
const readConfig = path => {
// get config
var config = flatConfig();
// return
return config[path];
};
// get host
var host = readConfig('Config.app.db.host');
```
上面使用了 Recursion 的方法來處理整個 tree model。大家可以使用自己的方法來實作也可以的喔 !