大(中)規模Java script開発について

Preview:

Citation preview

大(中)規模JavaScript開発について

@tan-yuki

2013/03/16

13年3月7日木曜日

自己紹介

- Web Application Programmer

- PHP,Java,JavaScript

- 日曜プログラマーでRubyとか

- Github: @tan-yuki

13年3月7日木曜日

自己紹介

MyBlog:なら日記http://www.tan-yuki.info/blog/

Programmingネタ

13年3月7日木曜日

ならちゃん

13年3月7日木曜日

発表内容

13年3月7日木曜日

1. JavaScriptという言語について

2. 大(中)規模開発について 2-1. 困ること 2-2. 解決策

3. テストについて

13年3月7日木曜日

1. JavaScriptという言語について

13年3月7日木曜日

長所

- Browserとtexteditorがあれば誰でもできる

- 柔らかい言語である(短所でもある)

- スクリプト言語(面倒なコンパイル作業はない)

- V8 JavaScriptは言語として実行速度が早い

13年3月7日木曜日

短所①- 変数の型なし

- Javaに比べると、コーディング規約がしっかりとさだまっていない

var a = "string value"; a = 1; // ok

var someVars = “”, some_int = 0;

13年3月7日木曜日

短所②- DOM API の使いにくさ (jQueryでカバー)

- 様々なブラウザで挙動が割りと違う

- Microsoft・IEが嫌いになる

document.getElementsByTagName // なげぇ

var obj = { delete: function() {} }

// Chrome, FF: ◯ IE: ☓

13年3月7日木曜日

2. 大(中)規模開発について

13年3月7日木曜日

2-1. 困ること

13年3月7日木曜日

- JavaScriptのソースが多くなってくると どこに何があるかよくわからなくなってくる

- 名前の衝突が起こりやすくなる

- 何も考えないでコーディングしていると、 かなりメンテナンスしずらい状態になる

13年3月7日木曜日

// register_user.js function getCookie() {};

function setCookie() {};

function getUserInfoFromDOM() {};

function createParamHiddenDOM() {};

function checkSubmitForm() {};

function checkInput() {};

// ....  ・ページと強依存

 ・ひとつの関数を呼びたいがためにこのJSを別ページにロード

13年3月7日木曜日

function request(obj) { // .....};

引数に何渡せばいいんだろう。。。

13年3月7日木曜日

<script src=”./jquery.js”></scirpt><script src=”./prototype.js”></scirpt><script><!-- $(‘#some-id’).append(‘<h1>Hello world!</h1>’); // error--></script>

奪い奪われるGlobal変数

13年3月7日木曜日

2-2. 解決策

13年3月7日木曜日

WebInspector

- Search sources - Break point - Console - etc....

13年3月7日木曜日

OOP (オブジェクト指向開発)

13年3月7日木曜日

var Person = function() { this.init.apply(this, arguments); };

Person.prototype = { // constructor init: function(name, age, male) { this.name = name; this.age = age; this.male = !! male; }, greet: function() { return "Hello, I'm " + this.name + ". " + "I'm " + this.age + " years old."; } };

var lisalisa = new Person("LisaLisa", 50, false); lisalisa.greet(); // === "Hello, I'm LisaLisa. I'm 50 years old."

13年3月7日木曜日

// extends var Man = function() { this.init.apply(this, arguments); }; Man.prototype = $.extend(true, {}, Person.prototype, { male: true, init: function(name, age) { this.name = name; this.age = age; } });

var caesar = new Man("Caesar", 20);

caesar.greet(); // === "Hello, I'm Caesar. I'm 20 years old."

caesar.male; // === true

13年3月7日木曜日

Global変数を減らす

13年3月7日木曜日

無名関数を使ってスコープを制限

(function() { var a = "hogehoge";})();

console.log(a); // Reference Error

13年3月7日木曜日

cf) jQueryを使う場合

(function($) {

// $ === jQuery;

})(jQuery);

ってやると無名関数内の$変数がjQuery

であることを保証できる。

13年3月7日木曜日

Global変数はProjectに対して一つ

if (! window.app) var app = {};(function($) { var SomeController = function() {};

// implement SomeController....

app.controller = new SomeController();

}) (jQuery);

外出ししたいものは、そのGlobal変数の子供として定義

13年3月7日木曜日

例)掲示板アプリ// directory structure

./bbs!"" apiclient.js!"" controller.category.js!"" controller.post.js!"" controller.thread.js!"" elem.js!"" model.category.js!"" model.post.js!"" model.thread.js!"" router.js!"" util.js!"" view.category.js!"" view.post.js#"" view.thread.js

0 directories, 13 files

13年3月7日木曜日

例)controller.category.js

if (! window.bbs) bbs = {}; if (! bbs.controller) bbs.controller = {};

(function($, __global__) {

/** * Category controller * * @require bbs.model.category * @require bbs.view.category */ var CategoryController = function() {};

CategoryController.prototype = { // .... };

bbs.controller.category = new CategoryController();

})(this.jQuery, this);

13年3月7日木曜日

オブジェクト引数

13年3月7日木曜日

受け取り側がこんな感じなら、何を渡すべきかわかりやすい。

var request = function(options) { options = $.extend(true, { /** * Host name. This is required. * * @type String */ host: null,

/** * Port number. * * @type Number */ port: 80, // This is default port number.

/** * Parameter send to server. * * @type Object */ parameter: {} }, options);

// implements request function....

13年3月7日木曜日

3. テスト

13年3月7日木曜日

- 大規模になると手でブラウザを叩いてテスト するだけでは限界がある(それも複数のブラウザ)

- テストケースを書いて自動化することを心がける

- 単体テストツール JSTestDriver, QUnit, Jasmine, ...

- テストしやすいコード => なるべく外部要因に影響されないようなコード

13年3月7日木曜日

QUnit

13年3月7日木曜日

13年3月7日木曜日

こんなかんじです。 module('Model');

test("Create model", function() { var Person = Model.create(); ok(Person.records, "model has records");

var person = Person.init({ name: 'tanakayuki', age: 25, male: true });

person.save();

var p = Person.find(person._id); equal(p.name, 'tanakayuki'); equal(p.age, 25); ok(p.male) });

test("Throw exception when record is not found", function() { var Person = Model.create(); Person.attributes = ['name', 'age', 'male']; throws(function() { Person.find(1); }); });

13年3月7日木曜日

非同期テスト

(function($) {

test("Async test", function() { expect(1); stop(); setTimeout(function() { equal($(‘#navigation’).find(‘li’).length, 4); start(); }, 1000); });

test(“ajax test”, function() { expect(2); stop(); $.get(‘/user/take/?id=1’, function(data) { equal(data.id, 1); equal(data.name, ‘tanakayuki’); start(); }); });

}) (jQuery);

13年3月7日木曜日

テストしやすいコード

13年3月7日木曜日

実装

var init = function(options) { options = $.extend(true, { now: new Date() }, options);

if (options.now >= new Date(“2014/01/01”)) { // .... } else { // .... }};

13年3月7日木曜日

テスト

test(function() { init({ now: new Date(“2013/12/31”) }); // 現在日時が2013/12/31のときのテスト });

test(function() { init({ now: new Date(“2014/01/01”) }); // 現在日時が2014/01/01のときのテスト });

13年3月7日木曜日

実装 その2

if (! window.app) app = {};

app.alert = window.alert; app.validate = function(name) { if (! name) app.alert('Not set name!'); };

13年3月7日木曜日

テスト

test(function() { app.alert = function(msg) {   equal(msg, 'Not set name!',

'should alert error message');    };

   app.validate();

});

13年3月7日木曜日

まとめ

13年3月7日木曜日

- 規模が大きくなることに備えて Global変数の仕様は極力おさえましょう。

- クラス、継承などを用いてOOPな実装 をしましょう。

- テストは自動化しましょう。

13年3月7日木曜日

Any questions?

13年3月7日木曜日