锘??xml version="1.0" encoding="utf-8" standalone="yes"?>
enhanceInteractionOnElements();
});
function helper_methods() {
}
file = "#{params[:controller]}/#{params[:action]}.js"
File.exist?("#{RAILS_ROOT}/public/javascripts/#{file}") ? javascript_include_tag(file) : ""
end
this method will look for js file for a particular page. And in you layout file, add one line in the head sectin:
That's it. Whenever you request an action of a particular controller, it will find and include the PE js files automatically. Now we've very very primitive support of PE in Rails framework now.
]]>
Ok, let's start from the 'Hello World in Compiler Construction' 鈥斺?Expression Evaluation
2
3 class ExpressionGrammar < Aurum::Grammar
4 tokens do
5 ignore string(' ').one_or_more # <= a
6 _number range(?0, ?9).one_or_more # <= b
7 end
8
9 precedences do # <= c
10 left '*', '/'
11 left '+', '-'
12 end
13
14 productions do # <= d
15 expression expression, '+', expression {expression.value = expression1.value + expression2.value} # <= e
16 expression expression, '-', expression {expression.value = expression1.value - expression2.value}
17 expression expression, '*', expression {expression.value = expression1.value * expression2.value}
18 expression expression, '/', expression {expression.value = expression1.value / expression2.value}
19 expression '(', expression, ')' do expression.value = expression1.value end # <= f
20 expression _number {expression.value = _number.value.to_i}
21 expression '+', _number {expression.value = _number.value.to_i}
22 expression '-', _number {expression.value = -_number.value.to_i}
23 end
24 end
If you has any experience with other compiler compiler/parser generator, you probably could understand what happens above quite easily. Instead of explaining things like token, character class, and production, I'd like to emphasise some Aurum conventions:
Now, let's find out how we could use this expression grammar. You could use the helper method as below(it will recalcuate lexical table and parsing table for every call, could be quite slow):
or use the lexical table and parsing table to create your own lexer & parser:
2 parser = Aurum::Engine::Parser.new(ExpressionGrammar.parsing_table(:expression))
3 puts parser.parse(lexer).value
At the end of this post, I'd like to give another grammar example coming from Martin Fowler's HelloParserGenerator series:
2
3 Item = Struct.new(:name)
4
5 class Catalog < Aurum::Grammar
6 tokens do
7 ignore enum(" \r\n").one_or_more
8 _item range(?a,?z).one_or_more
9 end
10
11 productions do
12 configuration configuration, item {configuration.value = configuration1.value.merge({item.value.name => item.value})}
13 configuration _ {configuration.value = {}}
14 item 'item', _item {item.value = Item.new(_item.value)}
15 end
16 end
17
18 config = Catalog.parse_configuration(<<EndOfDSL).value
19 item camera
20 item laser
21 EndOfDSL
22
23 puts config['camera'].name
P.S.:The post is based on the developing version of Aurum(0.2.0). You could get it from the svn repository.
P.S.P.S.: There is a more complicated example in the examples directory, a simple Smalltalk interpreter. Have fun:)
]]>
Aurum鏄竴涓敤Ruby瀹炵幇鐨凩ALR(n) parser generator錛堟槸鐨勶紝鍙堟槸涓涓猵arser generator錛夛紝涓嶈繃瀹冨拰鍏朵粬涓浜涘箍娉涘簲鐢ㄧ殑parser generator鐩告瘮鐣ユ湁涓嶅悓鐨勶細(xì)
1.Aurum鐨勪富瑕佺洰鏍囦箣涓錛屾槸綆鍖杄xternal DSL鐨勫紑鍙戯紙灝ゅ叾鏄痳uby external DSL錛夈?br />
2.Aurum閲囩敤澧為噺LALR(n)綆楁硶錛岃屼笉鏄氬父鐨凩ALR(1)銆傝繖鎰忓懗鐫錛?br />
a.涓嶅繀鐢變簬LALR(1)鑳藉姏鐨勯檺鍒訛紝鑰屾敼鍐欒娉曪紝寰堝鍦↙ALR(1)涓啿紿佺殑璇硶鍦↙ALR(n)涓彲浠ユ瘮杈冭嚜鐒跺湴琛ㄨ揪銆?br />
b.鐢變簬璇嗗埆鑳藉姏鐨勫寮猴紝鍙互澶勭悊涓浜涙瘮杈冨鏉傜殑璇硶錛屾瘮濡侰OBOL(LALR(2)鎴朙ALR(3))錛屾瘮濡備竴浜涚畝鍖栫殑鑷劧璇█(LALR(3+))銆?br />
c.澶勭悊鑳藉姏鎺ヨ繎Generalized LR錛屽嵈蹇緢澶?br />
d.姣旇搗Full LALR/LR(n)錛屽閲忕畻娉曠敓鎴愮殑璇硶琛ㄦ洿灝忋?br />
3.鍑轟簬綆鍖杄xternal DSL瀹炵幇鐨勮冭檻錛孉urum鏀寔璇硶閲嶇敤銆?br />
4.Aurum閲囩敤Ruby internal DSL浣滀負(fù)璇硶澹版槑鐨勫厓璇█錛屽彲浠ュ埄鐢≧uby涓板瘜鐨勬祴璇曟鏋訛紝鏈夋晥鍦板緙栬瘧錛忚В閲婏紡鍒嗘瀽鍣ㄨ繘琛屾祴璇曘?br />
5.姝e鍚嶅瓧鎵鏆楃ず鐨勶紝Aurum錛圙old鐨勫寲瀛﹀悕縐幫級(jí)鐨勪竴閮ㄥ垎鐏墊劅鏉ヨ嚜GOLD parsing system錛屽畠?yōu)畣鏀寔鐙珛浜庲q沖彴鍜岃璦鐨勭紪璇戝櫒寮鍙戙?br />
濂斤紝闂茶瘽灝戣錛岀湅涓涓緥瀛愶紝緙栬瘧鍘熺悊涓殑Hello World 鈥斺?琛ㄨ揪寮忔眰鍊鹼細(xì)
2
3 class ExpressionGrammar < Aurum::Grammar
4 tokens do
5 ignore string(' ').one_or_more # <= a
6 _number range(?0, ?9).one_or_more # <= b
7 end
8
9 precedences do # <= c
10 left '*', '/'
11 left '+', '-'
12 end
13
14 productions do # <= d
15 expression expression, '+', expression {expression.value = expression1.value + expression2.value} # <= e
16 expression expression, '-', expression {expression.value = expression1.value - expression2.value}
17 expression expression, '*', expression {expression.value = expression1.value * expression2.value}
18 expression expression, '/', expression {expression.value = expression1.value / expression2.value}
19 expression '(', expression, ')' do expression.value = expression1.value end # <= f
20 expression _number {expression.value = _number.value.to_i}
21 expression '+', _number {expression.value = _number.value.to_i}
22 expression '-', _number {expression.value = -_number.value.to_i}
23 end
24 end
濡傛灉璇鎬綅瀵逛箣鍓嶆湁鐢ㄨ繃compiler compiler鎴栬卲arser generator鐨勮瘽錛屽簲璇ヨ兘鐪嬩釜涓冧竷鍏叓鍚с傛垜澶ф瑙i噴涓涓嬶細(xì)
a.榪欓噷瀹氫箟浜?jiǎn)鏂囨硶绌虹櫧锛屼篃灏辨槸琚玪exer蹇界暐鐨勯儴鍒嗭紝鍦ㄩ氬父鐨勮璦涓紝鏄┖鏍煎洖杞︽崲琛屼箣綾葷殑瀛楃錛泂tring鏄敤浜庡畾涔塴exical pattern鐨刪elper鏂規(guī)硶錛堝嚭浜?jiǎn)string涔嬪錛岃繕鏈塺ange, enum鍜宑oncat錛夛紱ignore鏄竴涓瀹氫箟鐨勮鏄庢寚浠わ紝琛ㄧず鑻ユ枃鏈尮閰嶇粰瀹氭ā寮忓垯璇ユ枃鏈細(xì)琚玪exer鑷姩蹇界暐錛屽叾鏍煎紡涓猴細(xì)
ignore pattern {//lexical action}
b.姝ゅ涓簂exical token澹版槑錛屾墍鏈塴exical token蹇呴』浠寮澶達(dá)紝鍏舵牸寮忎負(fù)錛?br />
_token_name pattern {//lexical action}
榪欓噷鍏跺疄鏄竴涓畝鐣ュ啓娉曪紝絳変環(huán)浜?br />
match pattern, :recognize => 錛歘token_name
c.姝ゅ涓鴻繍綆楃浼樺厛綰у0鏄庯紝鏀寔宸?鍙崇粨鍚堣繍綆楃錛堟棤緇撳悎灞炴ц繍綆楃寮鍙戜腑錛夛紱姣忎竴琛屼腑鎵鏈夎繍綆楃鍏鋒湁鐩稿悓浼樺厛綰э紱姣斿畠涓嬩竴琛岀殑榪愮畻絎﹂珮涓涓紭鍏堢駭銆傛瘮濡傚湪榪欎釜渚嬪瓙涓紝'*'鍜?/'鍏鋒湁鐩稿悓浼樺厛綰э紝浣嗘槸姣?+'鍜?-'鐨勪紭鍏堢駭鍒珮銆?br />
d.姝ゅ涓鴻娉曡鍒欏0鏄庯紝鎵浣跨敤鐨剆ymbol涓昏鏈変笁縐嶏紝nonterminal(灝忓啓瀛楁瘝寮澶?錛宼erminal(鍏跺疄灝辨槸lexical token錛屼互_寮澶?鍜宭iteral(瀛楃涓插父閲?錛屽叾涓墍鏈塴iteral閮戒細(xì)琚嚜鍔ㄥ0鏄庝負(fù)淇濈暀瀛椼?br />
e.姝ゅ瀹氫箟浜?jiǎn)涓鏉℃枃娉曡鍒欙紙鍔犳硶錛夛紝浠ュ強(qiáng)瀵瑰簲鐨剆emantic action銆傚湪semantic action涓彲浠ョ洿鎺ラ氳繃symbol鐨勫悕瀛楁潵鑾峰彇鍊兼爤涓殑瀵硅薄銆傚閬囧埌鍚屽悕symbol錛屽垯鎸夌収鍑虹幇欏哄簭榪涜緙栧彿鍗沖彲銆?br />
f.鍏跺疄榪欎釜娌″暐錛屽彧涓嶈繃鐢變簬鎴戜滑浣跨敤鐨勬槸Ruby DSL錛屾墍浠ユ湁鏃跺欎笉鑳介兘鐢▄}錛岄渶瑕乨o end錛岃繖灝辨槸涓涓緥瀛愩?br />
鏈鍚庢祴璇曚竴涓嬪疄闄呬腑濡備綍浣跨敤瀹氫箟濂界殑璇硶錛堜嬌鐢╤elper method錛屾敞鎰忕敱浜庡垎鏋愯〃娌℃湁緙撳瓨錛屾瘡嬈¢兘浼?xì)閲嵔帡璇硶琛ㄥQ屼粎浠呴傜敤浜巇ebug mode銆傦級(jí)
puts ExpressionGrammar.parse_expression('1+1').value
鎴栬呴氳繃鍒嗘瀽琛ㄨ嚜宸辨瀯閫爈exer鍜宲arser
lexer = Aurum::Engine::Lexer.new(ExpressionGrammar.lexical_table, '1+1')
parser = Aurum::Engine::Parser.new(ExpressionGrammar.parsing_table(:expression))
puts parser.parse(lexer).value
鏈鍚庢渶鍚庯紝緇欏彟澶栦竴涓緥瀛愶紝灝辨槸Martin Fowler Blog涓婄殑HelloParserGenerator緋誨垪涓墍鐢ㄧ殑璇硶錛?br />
2
3 Item = Struct.new(:name)
4
5 class Catalog < Aurum::Grammar
6 tokens do
7 ignore enum(" \r\n").one_or_more
8 _item range(?a,?z).one_or_more
9 end
10
11 productions do
12 configuration configuration, item {configuration.value = configuration1.value.merge({item.value.name => item.value})}
13 configuration _ {configuration.value = {}}
14 item 'item', _item {item.value = Item.new(_item.value)}
15 end
16 end
17
18 config = Catalog.parse_configuration(<<EndOfDSL).value
19 item camera
20 item laser
21 EndOfDSL
22
23 puts config['camera'].name
P.S.:鏈枃鏄牴鎹瓵urum0.2.0鍐欐垚鐨勶紝浣犲彲浠ヤ粠rubyforge鐨剆vn涓婂緱鍒板畠銆?br />
P.S.P.S.: 鍦╡xmaples鐩綍閲屾湁涓涓洿澶嶆潅涓浜涚殑渚嬪瓙錛屾槸涓涓畝鍗曠殑Smalltalk瑙i噴鍣ㄣ?br />
]]>
2 -export([start/2]).
3
4 start(N, M) ->
5 Pid = create_process(self(), N - 1, M),
6 time(fun() -> Pid ! start, loop(Pid, M) end).
7
8 time(Fun) ->
9 statistics(wall_clock),
10 Fun(),
11 {_,Time} = statistics(wall_clock),
12 io:format("Run : ~w s ~n", [Time/1000]).
13
14 create_process(Pid, 0, _) -> Pid;
15 create_process(Pid, N, M) -> create_process(spawn(fun() -> loop(Pid, M) end), N - 1, M).
16
17 loop(_, 0) -> void;
18 loop(Next, M) ->
19 receive
20 Message -> Next ! Message,
21 loop(Next, M - 1)
22 end.
23
24
鏈夋剰鎬濇槸瀹冭繕鏈変竴涓浜岄棶錛岃浣犵敤鍙﹀涓縐嶇啛鎮(zhèn)夌殑璇█瀹炵幇鍚屾牱鐨勫姛鑳斤紝鍙戦佸悓鏍峰鐨勬秷鎭紝涔熸妸鏃墮棿璁板綍涓嬫潵錛岀劧鍚庡啓涓綃嘼log鏉ublish浣犵殑緇撴灉銆傚叾瀹烇紝澶у蹇?jī)鐭ヨ倸鏄庡Q岃繖縐峫ightweight process鍟婏紝message passing concurrency鍟婇兘鏄疎rlang鐨勫己欏癸紝鑰屼笖瀹炴祴緇撴灉涔熺潃瀹為涓烘亹鎬栵紝涓鑸篃灝辨病閭i棽蹇?jī)鎷垮埆鐨勪笢瑗挎潵闄‖涓鎶婁簡(jiǎn)錛圓rmstrong鍚屽鑷繁瀹炵幇浜?jiǎn)涓涓狫ava version錛屾晥鐜囧ぇ綰﹁兘宸埌鐧懼嶅惂錛夈備笉榪囪繕鐪熸湁閭e啓涓嶄俊閭殑鑰佸ぇ錛?a >鐢╯tackless python瀹炵幇浜?jiǎn)鍚屾狅L(fēng)殑ring benchmark錛屽彂鐜版瘮erlang榪樺揩...鍚庢潵淇敼浠g爜鍘繪帀io鎿嶄綔錛孍rlang鍊掓槸姣攕tackless python蹇簺錛屼絾涔熷彧鏄竴浜涜屽凡銆?br>
]]>
搴旂敤Selenium榪涜W(xué)eb嫻嬭瘯寰寰浼?xì)瀛樺湪鍑犱釜bad smell錛?br>1.澶ч噺浣跨敤name, id, xpath絳夐〉闈㈠厓绱犮傛棤璁烘槸鍔熻兘淇敼銆乁I閲嶆瀯榪樻槸浜や簰鎬ф敼榪涢兘浼?xì)濯?jiǎng)鍝嶅埌榪欎簺鍏冪礌錛岃繖浣垮緱Selenium嫻嬭瘯鍙樺緱闈炲父鑴嗗急銆?br>2.榪囦簬緇嗚妭鐨勯〉闈㈡搷浣滀笉瀹規(guī)槗浣撶幇鍑?guó)櫋屼负鐨勬剰鍥惧Q屼竴孌墊椂闂翠箣鍚庡氨寰堥毦鐪熸鎶婃彙嫻嬭瘯鍘熸湁鐨勭洰鐨勪簡(jiǎn)錛岃繖浣垮緱Selenium嫻嬭瘯鍙樺緱闅句簬緇存姢銆?br>3.瀵瑰叿浣撴暟鎹彇鍊肩殑瀛樺湪渚濊禆錛屽綋涓埆鏁版嵁涓嶅啀鍚堟硶鐨勬椂鍊欙紝嫻嬭瘯灝變細(xì)澶辮觸錛屼絾榪欐牱鐨勫け璐ュ茍涓嶈兘鏍囪瘑鍔熻兘鐨勭己澶憋紝榪欎嬌寰桽elenium嫻嬭瘯鍙樺緱鑴嗗急涓旈毦浠ョ淮鎶ゃ?br>
鑰岃繖鍑犵偣鐩存帴琛嶇敓鐨勭粨鏋滃氨鏄笉鏂湴娣誨姞鏂扮殑嫻嬭瘯錛岃屾瀬灝戝湴鍘婚噸鏋勩佸埄鐢ㄥ師鏈夋祴璇曘傚叾瀹炶繖鍒頒篃鏄甯革紝鍗曞厓嫻嬭瘯嫻嬭瘯鍐欏浜?jiǎn)锛屼篃鏈変細(xì)鏈墭q欐牱鐨勯棶棰樸備笉榪囨瘮杈冭鍛界殑鏄紝Selenium鐨勬墽琛岄熷害姣旇緝鎱紙鐩稿鍗曞厓嫻嬭瘯錛夛紝闅忕潃嫻嬭瘯閫愭笎鐨勫澶氾紝榪愯鏃墮棿浼?xì)閫愭笎澧炲姞鍒頒笉鍙繊鍙楃殑紼嬪害銆備竴緇勬剰鍥句笉鏄庨毦浠ョ淮鎶ょ殑Selenium嫻嬭瘯錛屽彲浠ュ緢杞繪澗鍦板湪姣忔build鐨勬椂鍊欐潃鎺?0鍒嗛挓鐢氳嚦2涓皬鏃剁殑鏃墮棿錛屽湪涓嬪氨鏈夎姳2涓皬鏃跺潗鍦ㄧ數(shù)鑴戝墠闈㈢瓑寰?50涓猄elenium嫻嬭瘯榪愯閫氳繃鐨勬?zhèn)叉儴缁忓巻銆傚洜姝ゅ悎鐞嗘湁鏁堝湴瑙勫垝Selenium嫻嬭瘯灝辨樉寰楁牸澶栫殑榪垏鍜岄噸瑕佷簡(jiǎn)銆傝岀洰鍓嶆瘮杈冭涔嬫湁鏁堢殑鍔炴硶錛屽線澶т簡(jiǎn)璇達(dá)紝鍙互鍙玠omain based web testing錛屽叿浣撴潵璁詫紝灝辨槸Page Object Pattern銆?br>
Page Object Pattern閲屾湁鍥涗釜鍩烘湰姒傚康錛欴river, Page, Navigator鍜孲hortcut銆侱river鏄祴璇曠湡姝g殑瀹炵幇鏈哄埗錛屾瘮濡係elenium錛屾瘮濡俉atir錛屾瘮濡侶ttpUnit銆傚畠浠噦寰楀浣曞幓鐪熸鎵ц涓涓獁eb琛屼負(fù)錛岄氬父鍖呭惈鍍廲lick錛宻elect錛宼ype榪欐牱鐨勮〃紺哄叿浣撹涓虹殑鏂規(guī)硶錛汸age鏄涓涓叿浣撻〉闈㈢殑灝佽錛屽畠浠簡(jiǎn)瑙i〉闈㈢殑緇撴瀯錛岀煡閬撹濡俰d錛?name錛?class錛寈path榪欑被瀹炵幇緇嗚妭錛屽茍鎻忚堪鐢ㄦ埛鍙互鍦ㄥ叾涓婅繘琛屼綍縐嶆搷浣滐紱Navigator鍒欎唬琛ㄤ簡(jiǎn)URL錛岃〃紺轟竴浜涗笉緇忛〉闈㈡搷浣滅殑鐩存帴璺寵漿錛涙渶鍚嶴hortcut灝辨槸helper鏂規(guī)硶浜?jiǎn)锛岄渶瑕佺湅鍏蜂綋鐨勯渶瑕佷簡(jiǎn)銆備笅闈㈡潵鐪嬩竴涓秴綰х畝鍗曠殑渚嬪瓙鈥斺旀祴璇曠櫥褰曢〉闈€?br>
1. Page Object
鍋囪鎴戜滑浣跨敤涓涓崟鐙殑Login Page榪涜鐧誨綍錛岄偅涔堟垜浠彲鑳戒細(xì)灝嗙櫥褰曠殑鎿嶄綔灝佽鍦ㄤ竴涓悕涓篖oginPage鐨刾age object閲岋細(xì)
2 def initialize driver
3 @driver = driver
4 end
5
6 def login_as user
7 @driver.type 'id=', user[:name]
8 @driver.type 'xpath=', user[:password]
9 @driver.click 'name='
10 @driver.wait_for_page_to_load
11 end
12 end
login_as鏄竴涓叿鏈変笟鍔″惈涔夌殑欏甸潰琛屼負(fù)銆傚湪login_as鏂規(guī)硶涓紝page object璐熻矗閫氳繃渚濋潬id錛寈path錛宯ame絳変俊鎭畬鎴愮櫥褰曟搷浣溿傚湪嫻嬭瘯涓紝鎴戜滑鍙互榪欐牱鏉ヤ嬌鐢ㄨ繖涓猵age object錛?br>
2 page.login_as :name => 'xxx', :password => 'xxx'
3
涓嶈繃鏃㈢劧鐢ㄤ簡(jiǎn)ruby錛屾昏鐢ㄤ竴浜況uby sugar鍚э紝鎴戜滑瀹氫箟涓涓猳n鏂規(guī)硶鏉ヨ〃杈鵑〉闈㈡搷浣滅殑鐜錛?br>
2 page = page_type.new $selenium
3 page.instance_eval &block if block_given?
4 end
涔嬪悗鎴戜滑灝卞彲浠ヤ嬌鐢╬age object鐨勭被鍚嶅父閲忓拰block鎻忚堪鍦ㄦ煇涓壒瀹氶〉闈笂鎿嶄綔浜?jiǎn)锛?xì)
2 login_as :name => 'xxx', :password => 'xxx'
3 end
4
闄や簡(jiǎn)琛屼負(fù)鏂規(guī)硶涔嬪錛屾垜浠繕闇瑕佸湪page object涓婂畾涔変竴浜涜幏鍙栭〉闈俊鎭殑鏂規(guī)硶錛屾瘮濡傝幏鍙栫櫥褰曢〉闈㈢殑嬈㈣繋璇嶇殑鏂規(guī)硶錛?br>
@driver.get_text 'xpath='
end
榪欐牱嫻嬭瘯涔熷彲琛ㄨ揪寰楁洿鐢熷姩涓浜涳細(xì)
2 assert_equal 'Welcome!', welcome_message
3 login_as :name => 'xxx', :password => 'xxx'
4 end
褰撲綘鎶婃墍鏈夌殑欏甸潰閮界敤Page Object灝佽浜?jiǎn)涔嬪悗锛尀鏈夋晥鍦板垎绂讳簡(jiǎn)娴嬭瘯鍜寵宓闈⒕l撴瀯鐨勮﹀悎銆傚湪嫻嬭瘯涓紝鍙渶浣跨敤璇稿login_as, add_product_to_cart榪欐牱鐨勪笟鍔¤涓猴紝鑰屼笉蹇呬緷闈犲儚id錛宯ame榪欎簺鍏蜂綋涓旀槗鍙樼殑欏甸潰鍏冪礌浜?jiǎn)銆傚綋榪欎簺欏甸潰鍏冪礌鍙戠敓鍙樺寲鏃訛紝鍙渶淇敼鐩稿簲鐨刾age object灝卞彲浠ヤ簡(jiǎn)錛岃屽師鏈夋祴璇曞熀鏈笉闇瑕佸お澶ф垨澶鐨勬敼鍔ㄣ?br>
2. Assertation
鍙湁琛屼負(fù)榪樺涓嶆垚嫻嬭瘯錛屾垜浠繕瑕佸垽鏂涓虹粨鏋滐紝騫惰繘琛屼竴浜涙柇璦銆傜畝鍗曞洖欏句竴涓嬩笂闈㈢殑渚嬪瓙錛屼細(xì)鍙戠幇榪樻湁涓浜涘緢閲嶈鐨勯棶棰樻病鏈夎В鍐籌細(xì)鎴戞庝箞鍒ゆ柇鐧誨綍鎴愬姛浜?jiǎn)鍛㈠Q熸垜濡備綍鎵嶈兘鐭ラ亾鐪熺殑鏄鍦ㄧ櫥褰曢〉闈簡(jiǎn)鍛紵濡傛灉鎴戣皟鐢ㄤ笅闈㈢殑浠g爜浼?xì)鎬庢牱鍛紵
2 on LoginPage {}
鍥犳鎴戜滑榪橀渶瑕佸悜page object澧炲姞涓浜涙柇璦鎬ф柟娉曘傝嚦灝戯紝姣忎釜欏甸潰閮藉簲璇ユ湁涓涓柟娉曠敤浜庡垽鏂槸鍚︾湡姝e湴杈懼埌浜?jiǎn)杩欎釜椤甸潰锛屽鏋滀笉澶勫湪杩欎釜椤甸潰涓殑璇濆Q屽氨涓嶈兘榪涜浠諱綍鐨勪笟鍔¤涓恒備笅闈慨鏀筁oginPage浣夸箣鍖呭惈榪欐牱涓涓柟娉曪細(xì)
2 include Test::Unit::Asseration
3 def visible?
4 @driver.is_text_present() && @driver.get_location ==
5 end
6 end
鍦╲isible?鏂規(guī)硶涓紝鎴戜滑閫氳繃瀵逛竴浜涚壒瀹氱殑欏甸潰鍏冪礌錛堟瘮濡俇RL鍦板潃錛岀壒瀹氱殑UI緇撴瀯鎴栧厓绱狅級(jí)榪涜鍒ゆ柇錛屼粠鑰屽彲浠ュ緱涔嬫槸鍚︾湡姝e湴澶勫湪鏌愪釜欏甸潰涓娿傝屾垜浠洰鍓嶈〃杈炬祴璇曠殑鍩烘湰緇撴瀯鏄敱on鏂規(guī)硶鏉ュ畬鎴愶紝鎴戜滑涔熷氨欏虹悊鎴愮珷鍦板湪on鏂規(guī)硶涓鍔犱竴涓柇璦錛屾潵鍒ゆ柇鏄惁鐪熺殑澶勫湪鏌愪釜欏甸潰涓婏紝濡傛灉涓嶅鍦ㄨ繖涓〉闈㈠垯涓嶈繘琛屼換浣曠殑涓氬姟鎿嶄綔錛?br>
2 page = page_type.new $selenium
3 assert page.visible?, "not on #{page_type}"
4 page.instance_eval &block if block_given?
5 page
6 end
7
榪欎釜鏂規(guī)硶紲炵鍦拌繑鍥炰簡(jiǎn)page瀵硅薄錛岃繖閲屾槸涓涓瘮杈僼ricky鐨勬妧宸с傚疄闄呬笂錛屾垜浠彧鎯沖埄鐢╬age != nil榪欎釜浜嬪疄鏉ユ柇璦欏甸潰鐨勬祦杞紝姣斿錛屼笅闈㈢殑浠g爜鎻忚堪鐧誨綍鎴愬姛鐨勯〉闈㈡祦杞繃紼嬶細(xì)
assert_equal 'Welcome!', welcome_message
login_as :name => 'xxx', :password => 'xxx'
end
assert on WelcomeRegisteredUserPage
闄や簡(jiǎn)榪欎釜鍩烘湰鏂█涔嬪錛屾垜浠繕鍙互瀹氫箟涓浜涗笟鍔$浉鍏崇殑鏂█錛屾瘮濡傚湪璐墿杞﹂〉闈㈤噷錛屾垜浠彲浠ュ畾涔変竴涓垽鏂喘鐗╄濺鏄惁涓虹┖鐨勬柇璦錛?br>
2 @driver.get_text('xpath=') == 'Shopping Cart(0)'
3 end
闇瑕佹敞鎰忕殑鏄紝铏界劧鎴戜滑鍦╬age object閲屽紩鍏ヤ簡(jiǎn)Test::Unit::Asseration妯″潡錛屼絾鏄茍娌℃湁鍦ㄦ柇璦鏂規(guī)硶閲屼嬌鐢ㄤ換浣昦ssert*鏂規(guī)硶銆傝繖鏄洜涓猴紝姒傚康涓婃潵璁瞤age object騫朵笉鏄祴璇曘備嬌涔嬪寘鍚竴浜涚湡姝g殑鏂█錛屼竴鍒欐蹇墊販涔憋紝浜屽垯瀹規(guī)槗浣縫age object鍙樻垚閽堝鏌愪簺鍦烘櫙鐨則est helper錛屼笉鍒╀簬浠ュ悗嫻嬭瘯鐨勭淮鎶わ紝鍥犳鎴戜滑寰寰鍊懼悜浜庡皢鏂█鏂規(guī)硶瀹炵幇涓轟竴涓櫘閫氱殑榪斿洖鍊間負(fù)boolean鐨勬柟娉曘?br>
3. Test Data
嫻嬭瘯鎰忓浘鐨勪綋鐜頒笉浠呬粎鏄湪琛屼負(fù)鐨勬弿榪頒笂錛屽悓鏍瘋繕鏈夋祴璇曟暟鎹紝姣斿濡備笅涓ゆ浠g爜錛?br>
2 login_as :name => 'userA', :password => 'password'
3 end
4 assert on WelcomeRegisteredUserPage
5
6 registered_user = {:name => 'userA', :password => 'password'}
7 on LoginPage do
8 login_as registered_user
9 end
10 assert on WelcomeRegisteredUserPage
嫻嬭瘯鐨勬槸鍚屼竴涓笢瑗匡紝浣嗘槸鏄劇劧絎簩涓祴璇曟洿濂界殑浣撶幇浜?jiǎn)娴嬭瘯鎰忓浘锛?xì)浣跨敤涓涓凡娉ㄥ唽鐨勭敤鎴風(fēng)櫥褰曪紝搴旇榪涘叆嬈㈣繋欏甸潰銆傛垜浠湅榪欎釜嫻嬭瘯鐨勬椂鍊欙紝寰寰涓嶄細(xì)鍏沖績(jī)鐢ㄦ埛鍚嶅晩瀵嗙爜鍟婂叿浣撴槸浠涔堬紝鎴戜滑鍏沖績(jī)瀹冧滑琛ㄨ揪浜?jiǎn)鎬庢牱鐨勬祴璇曟渚嬨傛垜浠彲浠ラ氳繃DataFixture鏉ュ疄鐜拌繖涓鐐癸細(xì)
2 USER_A = {:name => 'userA', :password => 'password'}
3 USER_B = {:name => 'userB', :password => 'password'}
4
5 def get_user identifier
6 case identifier
7 when :registered then return USER_A
8 when :not_registered then return USER_B
9 end
10 end
11 end
鍦ㄨ繖閲岋紝鎴戜滑灝嗘祴璇曟渚嬪拰鍏蜂綋鏁版嵁鍋氫簡(jiǎn)涓涓搴旓細(xì)userA鏄敞鍐岃繃鐨勭敤鎴鳳紝鑰寀serB鏄病娉ㄥ唽鐨勭敤鎴楓傚綋鏈変竴澶╋紝鎴戜滑闇瑕佸皢鐧誨綍鐢ㄦ埛鍚嶆敼涓洪偖綆辯殑鏃跺欙紝鍙渶瑕佷慨鏀笵ataFixture妯″潡灝卞彲浠ヤ簡(jiǎn)錛岃屼笉蹇呬慨鏀圭浉搴旂殑嫻嬭瘯錛?br>
2
3 user = get_user :registered
4 on LoginPage do
5 login_as user
6 end
7 assert on WelcomeRegisteredUserPage
褰撶劧錛屽湪鏇村鏉傜殑嫻嬭瘯涓紝DataFixture鍚屾牱鍙互浣跨敤鐪熷疄鐨勬暟鎹簱鎴栨槸Rails Fixture鏉ュ畬鎴愯繖鏍風(fēng)殑瀵瑰簲錛屼絾鏄諱綋鐨勭洰鐨勫氨鏄嬌嫻嬭瘯鍜屾祴璇曟暟鎹湁鏁堟х殑鑰﹀悎鍒嗙錛?br>
2 case identifier
3 when :registered then return User.find '.'
4 end
5 end
4.Navigator
涓庣晫闈㈠厓绱犵被浼鹼紝URL涔熸槸涓綾繪槗鍙樹笖闅句互琛ㄨ揪鎰忓浘鐨勫厓绱狅紝鍥犳鎴戜滑鍙互浣跨敤Navigator浣夸箣涓庢祴璇曡В鑰︺傚叿浣撳仛娉曞拰Test Data鐩鎬技錛岃繖閲屽氨涓嶈禈榪頒簡(jiǎn)錛屼笅闈㈡槸涓涓緥瀛愶細(xì)
2 on ProductDetailPage do
3 .
4 end
5. Shortcut
鍓嶉潰鎴戜滑宸茬粡鏈変簡(jiǎn)涓涓緢濂界殑鍩虹錛屽皢Selenium嫻嬭瘯涓庡悇縐嶈剢寮變笖鎰忓浘涓嶆槑鐨勫厓绱犲垎紱誨紑浜?jiǎn)锛岄偅涔堟渶鍚巗hortcut涓嶈繃鏄湪铔嬬硶涓婇潰鏈婕備寒鐨勫ザ娌圭艦浜?jiǎn)鈥斺斿畾涔夊叿鏈夋紓浜娉曠殑helper錛?br>
2 on LoginPage do
3 assert_equal 'Welcome!', welcome_message
4 login_as user
5 end
6 assert on WelcomeRegisteredUserPage
7 end
鐒跺悗鏄彟澶栦竴涓猰agic鏂規(guī)硶錛?br>
2 words = identifier.to_s.split '_'
3 eval "get_#{words.last} :#{words[0..-2].join '_'}"
4 end
涔嬪墠鐨勬祴璇曞氨鍙互琚敼鍐欎負(fù)錛?br>
should_login_successfully given :registered_user
end
榪欐槸涓縐嶇粨璁烘х殑shortcut鎻忚堪錛屾垜浠繕鍙互鏈夋洿behaviour鐨勫啓娉曪細(xì)
2 on page_type do
3 assert_equal 'Welcome!', welcome_message
4 login_as @user
5 end
6 end
7
8 def login_successfully
9 on WelcomeRegisteredUserPage
10 end
11
12 def given identifer
13 words = identifier.to_s.split '_'
14 eval "@#{words.last} = get_#{words.last} :#{words[0..-2].join '_'}"
15 end
鏈鍚庯紝嫻嬭瘯灝變細(xì)鍙樻垚綾諱技楠屾敹鏉′歡鐨勬牱瀛愶細(xì)
2 given :registered_user
3 login_on LoginPage
4 assert login_successfully
5 end
鎬諱箣shortcut鏄竴涓棤鍏沖ソ鍧忥紝鍙叧涔庢兂璞″姏鐨勪笢瑗匡紝灝芥儏鎸ユ磼Ruby DSL鍚?D
緇撹
Selenium鏄竴涓浜哄張鐖卞張鎭ㄧ殑涓滆タ錛岄敊璇湴浣跨敤Selenium浼?xì)缁欐暣涓晱鎹峰洟闃熺殑寮鍙戣妭濂忓甫鏉ョ伨闅炬х殑褰卞搷銆備笉榪囧煎緱搴?jiǎn)骞哥殑鏄纭滎C嬌鐢⊿elenium鐨勫師鍒欎篃鏄浉褰撶殑綆鍗曪細(xì)
1.閫氳繃灝嗚剢寮辨槗鍙樼殑欏甸潰鍏冪礌鍜屾祴璇曞垎紱誨紑錛屼嬌寰楅〉闈㈢殑鍙樺寲涓嶄細(xì)瀵規(guī)祴璇曚駭鐢熷お澶х殑褰卞搷銆?br>2.鏄庣‘鎸囧畾嫻嬭瘯鏁版嵁鐨勬剰鍥撅紝涓嶅湪嫻嬭瘯鐢ㄤ嬌鐢ㄤ換浣曞叿浣撶殑鏁版嵁銆?br>3.灝戒竴鍒囧彲鑳斤紝鏄庣‘鍦拌〃杈懼嚭嫻嬭瘯鐨勬剰鍥撅紝浣挎祴璇曟槗浜庣悊瑙c?br>
褰撶劧錛岄櫎浜?jiǎn)閬靛惊杩欏嚑涓熀鏈師鍒欎箣澶栧Q屼嬌鐢╬age object鎴栧叾浠杁omain based web testing鎶鏈槸涓笉閿欑殑閫夋嫨銆傚畠浠皢浼?xì)甯姪浣犳洿瀹规槗鍦版帶鍒禨elenium嫻嬭瘯鐨勮妯★紝鏇村ソ鍦板鉤琛¤鐩栫巼鍜屾墽琛屾晥鐜囷紝浠庤屾洿鍔犳湁鏁堝湴浜や粯楂樿川閲忕殑Web欏圭洰銆?br>
楦h阿
姝ゆ枃涓秹鍙?qiáng)鐨勯兘鏄垜鏈榪戜笁鍛ㄤ互鏉ュSelenium嫻嬭瘯榪涜閲嶆瀯鏃舵墍閲囩敤鐨勭湡瀹炴妧鏈傛劅璋ick Drew甯姪鎴戞竻鏅板湴鍒掑垎浜?jiǎn)Driver, Page, Nagivator鍜孲hortcut鐨勫眰嬈″叧緋伙紝瀹冧滑鏋勬垚鎴戞暣涓疄璺電殑鍩虹煶錛涙劅璋hris Leishman錛屽湪鍜屼粬pairing programming鐨勮繃紼嬩腑錛屼粬甯姪鎴戦敜鐐間簡(jiǎn)Ruby DSL錛涜繕鏈塎ark Ryall鍜孉bhi錛屾槸浠栦滑絎竴嬈″湪欏圭洰涓紩鍏ヤ簡(jiǎn)Test Data Fixture錛屼嬌寰楁墍鏈変漢鐨勫伐浣滈兘鍙樺緱綆鍗曡搗鏉ャ?br>
]]>
Which Programming Language are You?
p.s. 榪欎釜鍙兘涓嶅噯...鍥犱負(fù)鏉庨粯鍚屽绔熺劧鏄疞isp...鎬庝箞鍙兘...
]]>
1. IEC61970 Metadata: Electricity Power Trading System
褰撴椂鍒氫笂鐝紝team閲屾湁涓涓狣oamin鐭ヨ瘑寰堝帀瀹崇殑娓呭崕鐨勫崥澹紝姣曚笟鐨勮鏂囧氨鏄數(shù)鍔涘競(jìng)鍦猴紝鑰屾竻鍗庡張鏄浗瀹跺紩鍏EC61970鐨勪簲瀹朵箣涓銆傛墍浠ヤ粬寰堣秴鍓嶇殑鎶婅繖涓や釜涓滆タ緇撳悎鍦ㄤ竴璧鳳紝鍋氭垚浜?jiǎn)涓涓郴緇熴傝瀹炶瘽錛屽垰浜?jiǎn)瑙EC61970鐨勬椂鍊欙紝鎴戞槸鐩稿綋鐨勯渿鎾肩殑錛屾湁璧朵笂閭f椂鍊橫DA椋庢皵鍒氳搗錛孖EC61970鍙堟槸鍚屾椂MOF(Meta Object Facility)鍜孯DF based錛屽崕涓藉緱涓嶈銆備竴涓嬪瓙鎴戝氨鍙樻垚浜?jiǎn)涓涓狹DA guy錛屼竴涓猰etadata guy...浠ヨ嚦浜庯紝鍦˙JUG鏈鍒濈殑2騫撮噷錛孧DA/MOF/Metadata鎴愪負(fù)浜?jiǎn)涓绘棆寰?..
2. IEC61970 & CWM(Common Warehouse Metamodel) & Office Plugin : Data Warehouse Integration System
榪欐槸榪勪粖涓烘錛屾垜鏈涓嶆効鎰忓洖蹇嗙殑涓涓」鐩?..鍥犱負(fù)Office Plugin...鍔ㄨ緞钃濆睆鐨勯伃閬囪鎴戝績(jī)鏈変綑鎮(zhèn)?..榪欐槸涓涓猙ackend鏄疛2EE錛宖rontend鏄?Net鐨刼ffice鎻掍歡緋葷粺錛屼富瑕佹槸鎶ヨ〃...涓よ竟閮戒嬌鐢–WM浣滀負(fù)鏁版嵁緇熶竴鐨勫艦寮?..鍩烘湰涓婂仛鍒頒竴鍗婃垜鐨勬剰蹇楀氨宕╂簝浜?..
3. DB Migration/Refactoring : Jyxpearl
榪欎釜欏圭洰...鏄潕榛樺悓瀛︾殑縐佹埧鏈鐖憋紝浠庡ぇ瀛︿竴鐩村仛浜?jiǎn)寰堜箙锛屾敼鐗堟棤鏁皨?..褰撴椂娌℃湁榪欎箞嫻佽鐨勫ソ璇嶏紝浠涔圖B Migration鍟婏紝DB Refactoring鍟婏紝閭f椂鍊欐垜浠粺縐板鏁版嵁...鎴戝浜?jiǎn)濂藉浼?xì)...鍩烘湰涓婄嚎涓鍥炲涓鍥?..鏃惰嚦浠婃棩...鏉庨粯鍚屽鎬繪槸涓嶆棤寰楁剰鐨勮錛氫綘鐪嬶紝浣燚B Migration鐨勮兘鍔涘氨鏄垜鍩瑰吇鐨?..
4. JMI(Java Metadata Interface) & Eclipse RCP : Multi/Rich Client ERP Product
榪欎釜team鍏跺疄鎸哄崕涓界殑錛岃佹牼鐨勪駭鍝佺粡鐞嗭紝鏉庨粯鏄紑鍙戠粡鐞嗭紝瓚呯駭璧勬繁琛屼笟涓撳(浜哄瀹為檯鍋氳繃鐢熶駭縐戦暱錛孧RPII錛孍RP閮芥槸浜哄鐜╁墿涓嬬殑)鑰侀綈鍋氶渶姹傦紝淇烘槸Architect錛岃繕鏈夊姩鐗╁洯閲岀殑鐚猄enior Dev錛屾垜璁よ瘑浜轟腑緹庡伐鑳藉姏絎竴浜や簰璁捐鑳藉姏絎竴鐨勭背綾沖鍋歎I鍜屼氦浜掋傜敱浜庡綋鏃剁湅浜?jiǎn)netbeans鍜宻un鐨勫畼鏂笿MI瀹炵幇寰楀お鐜╁叿銆傛垜浠喅瀹氫粠鑷繁鐨凧MI瀹炵幇寮濮嬶紝緋葷粺緇撴瀯瑕佹眰澶氬鎴風(fēng)錛寃eb錛宺cp閮借...鎵浠ユ槸瓚呰交http鍗忚鐨刡/s錛宑/s銆傜粨鏋勮繕鏄笉閿欑殑錛岃繃紼嬫潕榛樺拰鎴戝綋鐒舵槸鏁忔嵎浜?jiǎn)銆備技涔庝竴璧烽兘瓚呯駭瀹岀編鐨勬椂鍊欙紝灝辨槸瑕佸潖鑿滅殑鏃跺?..浼佷笟浜嬩笟閮ㄨВ鏁d簡(jiǎn)...
5. Java Communication & Eclipse RCP : IC Card Reader
涓婇潰閭d釜欏圭洰瑙f暎涔嬪悗錛屾垜璺熸潕榛樿祴闂插湪瀹訛紝鏈変笉蹇嶅績(jī)鎵撴壈鏀垮簻錛岃嚜璋嬬敓璺壘鐨勯」鐩?..榪欎釜欏圭洰瑕佺敤IC鍗¤鍗″櫒錛屼負(fù)浜?jiǎn)閿荤偧鎴戜滑鐨凟clipse RCP鑳藉姏錛屾垜浠喅瀹氱敤eclipse rcp鏉ュ仛銆備簬鏄棶棰樺氨鍑烘潵浜?..IC鍗℃庝箞鍔烇紵google涓鎶婂彂鐜板ぉ鏃犵粷浜轟箣璺?..Java鏈変竴涓狢ommunication鍖咃紝鍙互榪炴帴serial port...涓嶈繃褰撴椂tricky鐨勬槸...鎴戠殑鏈瓙娌℃湁涓插彛錛屾垜浠拱浜?jiǎn)涓涓覆鍙e埌usb鐨勮漿鎹㈠櫒...鍙戠幇鏍規(guī)湰涓嶈兘鐢?..浜庢槸鍙ソ璺戝埌鏉庨粯瀹剁敤浠栧崕涓界殑鍙板紡鏈猴紙榪欏幃褰撳勾瑾撹█鏃︽棪鐨勮錛宭aptop澶參錛屼竴瀹氳鐢ㄥ彴寮忔満錛屼笢鍊熻タ鍊熸悶浜?jiǎn)涓?G RAM SATA錛繪敞鎰忥紝榪欐槸浼忕瑪錛界殑鏈哄櫒錛夈傛垜褰撴椂灝辮寰楋紝Java鐨勮繖涓笢瑗垮熀鏈氨鏄厖鏁扮殑錛岃矊浼煎畬鍏ㄦ病鏈変漢鐢ㄨ繃錛屾枃妗e暐鐨勯兘鐗瑰皯...鍙兘鑷繁鎽哥儲(chǔ)銆傚湪緇忓巻浜?jiǎn)鏃犳暟娆″まp觸涔嬪悗錛岀粓浜庢垚鍔熶簡(jiǎn)銆傚湪showcase閭eぉ鐨勪笂鍗堬紝鎴戞渶鍚庡疄楠屼簡(jiǎn)璇誨崱浠涔堢殑錛岄兘娌¢棶棰樸傚叴楂橀噰鐑堢殑鎶妀ar鎷峰埌浼樼洏涓婏紝鍒氭彃鍒皍sb鍙d笂...鍙涓閬撻棯鐢?..鏈哄櫒榛戜簡(jiǎn)...鎹潕榛樺悗鏉ュ垎鏋愭槸涓繪澘鐑т簡(jiǎn)...鎴戣娌′簨錛屾嬁涓婄‖鐩橈紝鍦熶竴鐐逛篃涓嶅獎(jiǎng)鍝峴howcase銆傛潕榛樿...榪欎釜...SATA鑰?..榪樹笉嫻佽鍛?..鎴戠豢...姝ゅ悗寰堥暱鏃墮棿錛屾垜閮芥鐤戞槸鎴戣窡鏉庨粯鍚屽鑼冨啿錛岃秴綰ч」鐩潃鎵?..
6. RDF, Semantic Web, SparQL : Ontology-Relationship DB Mapping
榪欐槸鍦ㄤ竴瀹跺叕鍙稿仛浜у搧錛屽綋鏃舵垜鍏冩暟鎹?MDA棰嗗煙棰囨湁縐瘡...璺熻繖瀹跺叕鍙稿仛寰楃被浼鹼紝灝辮繃鏉ヨ礋璐g爺鍙戞湰浣撳埌鍏崇郴鏁版嵁搴撶殑鏄犲皠...鍏煎甫鍦―2RQ鐨勫熀紜涓婂疄鐜頒竴涓猄parQL鏌ヨ璇█銆傛庝箞鏍?..鍚笂鍘誨緢鍗庝附鍚?..鍒扮幇鍦ㄦ垜閮借涓猴紝榪欎釜欏圭洰鏄垜鏈鏈夋綔鍔涚殑鐗涚毊錛屼笉瀹氶偅澶﹚eb x.0浜?jiǎn)锛屾垜涔熻佷簡(jiǎn)錛屾垜灝卞彲浠ユ媺鐫灝忔湅鍙嬬殑鎵嬪幓鍚圭墰b浜?05騫存垜灝卞仛semantic web,O/R mapping鐭ラ亾涓嶏紵Ontology鍟婏紝浣犱滑鍟婏紝sometime too simple"...涓嶈繃浼拌榪欎竴澶╄繕鏃╁緱寰堝憿
7. Agile Domain Specified Language : Goodhope
榪欎釜涔熸槸鏉庨粯鍚屽鏈変喚鐨勯」鐩?..璇濋噷鐨勬晱鎹稤SL瀹炶返...涓嶈繃璇村疄璇濓紝涔熸湁鐐筙...
]]>
Customer collaboration over Contract negotiation
鏁忔嵎杞歡寮鍙戯紝灝辨槸瑕佷互涓縐嶆洿鍚堢悊鐨勫叡璧㈢殑鍚堜綔鍏崇郴錛屼唬鏇夸互鍓嶇暩褰㈢殑閲囪喘寮忕殑鍚堢害鍏崇郴銆備負(fù)浠涔堝悎綰﹀叧緋誨氨鏄暩褰㈢殑錛熸垜浠潵鐪嬬湅鍚堢害鍙屾柟鐨勫澧冦?br />
棣栧厛杞歡鍥㈤槦鏂歸潰鎵挎媴浜?jiǎn)杩囧鐨勯闄╁Q氫笟鍔″彉鍖栵紝鏀逛唬鐮侊紒錛佸晢涓氭妷鎷╄漿鎹紝鏀逛唬鐮侊紒錛佸嚟鍟ヤ綘鐢叉柟鐨勭紭鏁呴潪瑕佹垜鎵挎媴棰濆鐨勬垚鏈紵浣犺鎴戝啢涓嶅啢錛熷啢錛佷絾鏄漢瀹剁敳鏂逛篃鍐わ紒錛佷漢瀹惰姳浜?jiǎn)澶ф妸鐨勯摱瀛愬Q屾嬁鍒頒竴鍫嗕笉鑳界敤鐨勮蔣浠訛紙浣犺鏄‖浠朵漢瀹惰繕鑳借漿鎵嬪崠鐐歸挶錛夛紝灝卞儚浣犺鐮嶆爲(wèi)鍒漢緇欎綘鎶婇摬瀛愶紝浣犺縐嶆爲(wèi)浜哄緇欎簡(jiǎn)浣犳妸閿傛悂浣狅紝浣犱篃涓嶆効鎰忋備笖涓嶈鍗氬紙錛屽氨綆楀弻鏂歸兘鏈夊績(jī)鎶婁簨鎯呭仛濂斤紝鎸夊悎鍚屾潵錛岀敳鏂逛笉騫詫紱涓嶆寜鍚堝悓鏉ワ紝涔欐柟涓嶅共錛屾渶鍚庡彉鎴愨滄湁蹇?jī)鏉璐兼棤鍔涘洖澶┾濓紝澶у涓璧鋒壇鎵毊絳変簩鏈熺畻浜?jiǎn)銆俵ose-lose錛屾病鏈夎耽瀹躲?br />
閭d箞鍚堜綔鐨勫叧緋繪槸浠涔堝憿錛熷悎浣滅殑鍏崇郴灝卞ソ姣斾綘鍘籹ubway涔頒笁鏄庢不錛岄潰鍖呬綘鑷繁閫夛紝瑕佷粈涔堣倝浣犳潵鎸戯紝钄彍錛宑heese錛岄叡姹佷綘涔熻嚜宸辯湅鐫鍔炪傛妧鏈垜鏉ワ紝鍙e懗浣犻夈傛妧鏈け璐ユ垜璐熻矗錛屽彛鍛充笉鍚堥備綘璐熻矗銆備綘鍋氫綘鐨勫己欏規(guī)垜鏉ユ垜鐨勫己欏癸紝鏈緇堝ぇ瀹墮珮楂樺叴鍏村樆鍢誨搱鍝堜笉鍚典笉闂癸紝浣滃嚭涓欏垮彲鍙e崍槨愩傝繖鏄椂鍊欙紝鐢熶駭鍏崇郴鍙樹簡(jiǎn)錛屾垜涓嶆槸浣犵殑鍐峰啺鍐扮殑渚涘簲鍟嗭紝浣犱篃涓嶆槸鎴戦偑鎭剁殑瀹㈡埛錛屾垜浠槸鎷村湪涓鏍圭懷瀛愪笂鐨勮殏铓便傛垚鍔熸槸鎴戜滑鐨勶紝澶辮觸涔熸槸鎴戜滑鐨勩傝崳杈變笌鍏憋紝鎼烘墜騫惰偐銆傚惉鐫鏈夌偣鑰崇啛錛熸病閿欙紝SaaS銆傛晱鎹峰璦鏃╁氨璇翠簡(jiǎn)錛孋oC鍟娿備粠渚涘簲鍟嗗彉鎴愭湇鍔″晢錛屼粠鏈嶅姟鍟嗗彉鎴愭垬鐣ュ悎浣滀紮浼達(dá)紝榪欐槸鍦ㄧ粰杞歡浼佷笟鎸囧嚭璺紝鏂扮殑鐢熶駭鍏崇郴宸茬粡灝藉湪鍏朵腑浜?jiǎn)銆?br />
濡傛灉鐪嬩笉娓呮晱鎹風(fēng)殑榪欎釜鏍規(guī)湰闈╁懡鐐癸紝浠ヤ負(fù)榪樻槸寮鍙戞柟娉曠殑灝忔墦灝忛椆錛岄偅涔堟晱鎹鋒牴鏈疄鏂戒笉鎴愩傝繖璇濅竴鑸垜涓嶆暍璇寸殑錛岀▼搴忓憳鑷彂瀹炴柦鏁忔嵎錛屽彧鍦ㄤ竴縐嶆儏鍐典笅鍙兘鎴愬姛錛氬ぇ浼佷笟鐨処T閮ㄩ棬銆傚啀璧朵笂涓己鍔涚殑IT棰嗗錛岃嚜瀹朵漢鍢涳紝鏈変粈涔堜笉濂借皥鐨勩備竴鏉ヤ簩鍘伙紝灝辨垚鍔熶簡(jiǎn)錛堢湅鐪婥3錛岃鐧戒簡(jiǎn)涓嶅氨鏄疘T閮ㄩ棬鍜屼笟鍔¢儴闂紵錛変絾鏄紝濡傛灉鏄仛欏圭洰鐨勫叕鍙革紝浣犺惀閿鎵嬫涓嶆敼鍙橈紝鏁忔嵎灝變笉鍙兘鎴愬姛銆備綘鐨勫鎴瘋窡浣犱笉鏄悎浣滃叧緋伙紝浣犻氳繃鏁忔嵎澧炲姞璐ㄩ噺錛堢鍚堟ц川閲忥級(jí)鐨勫伐浣滃氨涓嶄細(xì)琚漢鍙紝閭d箞灝變笉鑳芥垚涓烘姇璧勶紝鍙兘鏄垚鏈傚綋鎴愭湰澧炲姞鍒頒笉鍙壙鎷呯殑鏃跺欙紝鏁忔嵎灝變笉浜?jiǎn)浜?jiǎn)涔嬩簡(jiǎn)銆備負(fù)浠涔堝ソ澶氫漢璇磋佹澘娌℃湁鍝嶅簲錛熸棫鐨勭敓浜у叧緋諱笅鏁忔嵎鏍規(guī)湰灝辨槸璐熸媴銆?br />
璇撮亾榪欓噷錛岃涓涓嬩互鏁忔嵎闂誨悕鐨凾houghtWorks銆傚叾瀹炲緢澶氫漢閮戒互涓篢hougtWorks鍙湁鏂規(guī)硶璁哄挩璇紝娌¢敊鎴戜滑鏄湁鏂規(guī)硶璁哄挩璇紝浣嗘槸涔熸湁涓氬姟妯″紡鍜ㄨ錛屽鎴蜂笟鍔℃ā寮忎笉鏀瑰彉錛屼粬鎬庝箞鑳藉交搴曟晱鎹鳳紵榪欑偣澶у涓嶅彲涓嶆煡鍟娿?img src ="http://www.tkk7.com/raimundox/aggbug/107375.html" width = "1" height = "1" />
]]>
#!/usr/local/bin/ruby
require 'rss/1.0'
require 'rss/2.0'
require 'open-uri'
require 'rubygems'
require 'blinkenlights'
SUCCESS = 'success'
def read_rss source='http://cruisecontrolrb.thoughtworks.com/projects/CruiseControl.rss'
聽 content = ''
聽 open(source) do |s| content = s.read end
聽 rss = RSS::Parser.parse content, false
聽 rss.items[0].title.include?(SUCCESS) ? all_ok : alarm
end
def all_ok times = 50
聽 BlinkenLights.open { |lights| times.times {lights.random} }
end
def alarm times = 50, invertal = 0.0
聽 BlinkenLights.open { |lights| times.times {lights.flash invertal} }
end
while true
聽 read_rss
聽 sleep 5聽
end
make sure to have sufficient permissions to access the device, or you could simple run it as super user.
]]>
I - Independent
N - Negotiable
V - Valuable
E - Estimable
S - Small
T - Testable
鎴戜釜浜鴻寰楋紝榪欎釜鎬葷粨铏藉ソ錛屼絾涓嶅厤鍒嗘暎娉ㄦ剰銆傝鎴戣錛屾兂鎶婃彙濂経ser Story錛屽彧鐢ㄦ妸鎻′袱涓氨澶熶簡(jiǎn)Negotiable鍜孷aluable銆傞偅涔堥鍏堣紜畾浠涔堟槸Negotiable鐨勩俇ser Story鏈変竴涓祦浼犲箍娉涚殑涔﹀啓褰㈠紡錛?br />
As <role>, I'd like to <action>, so that <benifit/value/goal>.
涓轟簡(jiǎn)鏇村ソ鐨勮幏鍙杝tory榪樻湁寰堝鏈浣?jīng)_疄璺碉紝姣斿personas, 姣斿business process modeling錛屽叾瀹炶繖浜涘叏鏄硸琛g偖寮癸紝As, I'd like to閮芥槸鍣卞ご錛屽氨鏄負(fù)浜?jiǎn)鎶婄敤鎴峰拷鎮(zhèn)犳檿浜?jiǎn)錛岀劧鍚庡浘絀峰寱鐜扮洿鍙栧晢涓氫環(huán)鍊煎拰鐩爣銆備竴鏃﹀晢涓氫環(huán)鍊肩‘瀹氫笅鏉ワ紝role, action閮芥槸鍙互negotiable銆傛瘮濡傛潕榛樹箣鍓嶅湪鏂囩珷閲屼婦鐨勭敤鎴風(fēng)櫥褰曠殑渚嬪瓙錛岃緭涓嶈緭鐢ㄦ埛鏄庡瘑鐮侊紵鍙互鍟嗛噺鍢涳紒鏄笉鏄彧鏈夋敞鍐岀敤鎴峰彲浠ヤ韓鍙椾釜鎬ф湇鍔★紵鍙互鍟嗛噺鍢涳紒鍏抽敭鏄敤鎴鋒兂瑕佷粈涔堬紝鑷充簬鎬庝箞瀹炵幇榪欎簺鍒板ご鏉ラ兘鏄彲浠ュ晢閲忕殑錛岄兘鏄疦egotiable銆傚彧鏈夊鎴風(fēng)殑鍟嗕笟浠峰兼槸涓嶈兘鍟嗛噺鐨勶紝涔熸病鐨勫晢閲忋備環(huán)鍊兼病鏈変簡(jiǎn)錛岀洰鏍囦笉瀛樺湪浜?jiǎn)锛寴q欎釜User Story涔熷氨娌$敤浜?jiǎn)锛屽晢閲忓暐锛熼噸鍐欎竴寮犲氨濂戒簡(jiǎn)銆?br />
鍥犳user story鍙堟湁鍙﹀涓涓悕縐幫紝鍙玶equirement placeholder銆傚氨鏄鎴蜂環(huán)鍊肩殑"绔嬫瀛樼収"銆傝嚦浜庡叿浣撻渶姹傦紝閭d箞灝卞埌iteration plan meeting涓婃槸鍟嗛噺鍚э紝鐪嬬湅褰撴椂浠涔堟牱鐨勫艦寮忥紙鍔熻兘錛夋墠鏄渶絎﹀悎鐢ㄦ埛闇瑕併傚埌姝わ紝鍏跺疄澶у鍙互鐪嬪嚭鏉ヤ簡(jiǎn)錛寀ser story閲嶇偣灝變笉鍐岺ow涓婏紝鑰屾槸鍦╓hy涓婄殑銆傛湁浜?jiǎn)why錛屼笖鍙疦egotiable錛屾妸鎻′簡(jiǎn)綺劇錛屼綘灝辨槸鎸夌敤渚嬫潵鍐欓渶姹傚張鏈変綍濡ㄦ秴錛?br />
鏈変簡(jiǎn)valuable鍜宯egotiable鐨勬兂娉曞灚搴曪紝鍦ㄧ湅鐪嬪熀浜巙ser story鐨勫垵姝ヨ鍒掑埗瀹氣斺斾篃灝辨槸鏈夊悕鐨刾rioritization鈥斺斿氨瀹規(guī)槗鐞嗚В澶氫簡(jiǎn)銆傜敤鎴鋒牴鎹瘡寮犲崱鐨勪環(huán)鍊鹼紝鑷姣旇緝浣滃嚭鍐沖畾錛屽ぇ浣撳満鏅氨璺熷悜紲炰粰璁告効涓鏍楓?br />
紲炰粰錛氭垜鍙互婊¤凍浣犱竴涓効鏈涖?br />鎴戯細(xì)鎴戣鑽e崕瀵岃吹錛侊紒錛?br />紲炰粰錛氬摝錛岃崳鍗庡瘜璐碉紝閭d箞瑕佷笉瑕佺埍鎯呮秴錛?br />鎴戯細(xì)鎭╋紝榪欎釜...閭f垜瑕佸繝璐炵殑鐖辨儏濂戒簡(jiǎn)錛侊紒
紲炰粰錛氬摝錛屽繝璐炵殑鐖辨儏錛岄偅涔堣涓嶈鍋ュ悍騫沖畨鍛紵
鎴戯細(xì)鍛?...
repeat 鏃犳暟嬈★紝鏈緇堟垜瑕佷簡(jiǎn)涓浠惰繃鍐殑鐨尨...
]]>
]]>
涓婂浘鏄憲鍚嶇殑Ron Jefferies Model錛屽彲浠ョ湅鍒癤P鏈浣?jīng)_疄璺佃鍒掑垎鎴愪簡(jiǎn)涓涓竴涓殑鍦嗗湀錛岃宲air, TDD, refactor鍜宻imple design浣嶄簬涓績(jī)銆傝繖騫朵笉鏄榪欏洓涓疄璺靛氨鏄痻p鐨勬牳蹇?jī)銆俲efferies model姣忎竴鍦堜唬琛ㄤ簡(jiǎn)xp瀹炶返榪囩▼涓殑涓嶅悓鍏蟲敞鐐癸紝鏈涓績(jī)鐨勬槸dev瑙嗚錛屽叾嬈℃槸team瑙嗚錛屾渶澶栧眰鏄氦浠橈紡綆$悊瑙嗚銆傛瘡鍦堜笂鐨勬渶浣蟲椂闂村灝戦兘鏈変簺绱ц﹀悎錛屾斁寮鍏朵粬鐨勪笉璁詫紝鎴戜滑涓撻棬璇磋dev鍦堬紝pair programing, tdd, refactor鍜宻imple design銆?br />
榪欏洓涓疄璺甸噷鍙湁simple design鏈铏氫篃鏈閲嶈銆傛湁涓涓棶棰樺凡緇忚闂繃鏃犳暟嬈′簡(jiǎn)錛屸滃埌搴曞simple鐨刣esign鎵嶅彨simple鈥濄傛垜瀵規(guī)涔熸湁涓涓繎涔庡埢鏉跨殑鍥炵瓟錛歵eam閲屾墍鏈変漢鍛橀兘鑳藉鐞嗚В鐨刣esign灝辨槸simple鐨勩備竴鏃︾珛浜?jiǎn)鏍囧噯锛寴q欏洓涓疄璺電殑涓諱粠鍏崇郴灝變竴涓嬪瓙娓呮櫚璧鋒潵鈥斺攕imple design鏄繖鍥涗釜瀹炶返鐨勬牳蹇?jī)锛屽叾浠栦笁涓疄璺甸兘鏄畠鏈嶅姟鐨勩?br />
棣栧厛鍋氬嚭涓涓璁★紝鏈綆鍗曠殑鍒ゆ柇鏍囧噯灝辨槸鏄惁鍙祴錛屼竴涓笉鍙祴鐨勮璁″熀鏈笂鍙互璁や負(fù)鏃犳硶瀹炵幇錛屼簬鏄疶DD鍗蟲槸simple design鐨勮川閲忎繚璇佸張鏄痵imple design鐨勭洿瑙夐獙璇併?br />
refactor鏄負(fù)浜?jiǎn)寰楀埌濂界殑浠g爜锛岄偅涔堜粈涔堟槸濂界殑浠g爜錛焥imple design!!!榪欓噷鏈変漢涓嶅悓鎰忎簡(jiǎn)錛屾湁浜鴻鍙槸瑕佹槗浜庝慨鏀瑰拰鎵╁睍錛屽彲鏄墿灞曞拰淇敼涔熻鍒漢鐪嬪緱鎳傛墠琛屽晩...simple design鏄搗鐮佺殑瑕佹眰鍢涖傚疄闄呬笂錛孹P涓殑refactor灝辨槸鏈濈潃simple design鐨勬柟鍚戦噸鏋勮繃鍘葷殑錛屼篃灝辨槸鏈濈潃鎵鏈変漢閮借兘鐞嗚В鐨勪唬鐮乺efactor榪囧幓鐨勩傛彃涓鍙ラ澶栬瘽錛屼負(fù)鍟ヨ濂界殑鏋舵瀯鐨勪笉鏄璁″嚭鏉ョ殑鍛紵鍥犱負(fù)濂界殑鏋舵瀯鑷沖皯搴旇鏄痵imple design鐨勶紝鑰宻imple鐨勬蹇墊湁鍜屼漢鍛樼浉鍏?..鎵浠ュ綋浣犳瀬灝借兘浜媠how off浣犵殑pattern鐭ヨ瘑涔嬪悗錛屽緱鍒板鏉傝璁℃牴鏈氨涓嶅彲鑳芥槸濂界殑鏋舵瀯銆傛椂鍒葷揣璁幫紝鏋舵瀯鏄Ε鍗忓晩...
鏈鍚庯紝pair programming鏄痵imple design鐨勫疄闄呮楠岋紒錛侊紒鍥犱負(fù)鍗充究鏄渶澶嶆潅鐨勮璁★紝鍙鏄綘鑷繁鎯沖嚭鏉ョ殑錛屼綘閮借寰楀畠綆鍗曟棤姣旓紝閲岄潰鍏呮弧浜?jiǎn)鐩寸櫧涓旀樉鑰屾槗瑙佺殑鐞嗙敱銆傚彲鎯滀笉騫哥殑鏄紝鎴戜滑瑕佺殑綆鍗曪紝鏄team閲屾墍鏈変漢鐨勭畝鍗曘傚鏋滀綘鐨刾air涓嶈兘鐞嗚В浣犵殑璁捐錛岄偅涔堣鏄庝綘鐨勮璁″鏉備簡(jiǎn);濡傛灉浣犱滑涓や釜浜烘噦錛屼絾鏄痵with pair鐨勬椂鍊欙紝鎹㈣繃鏉ョ殑浜轟笉鎳傦紝璇存槑浣犵殑璁捐澶嶆潅浜?jiǎn)銆俻air programming(浠ュ強(qiáng)浠栭偅瀹規(guī)槗璁╀漢蹇界暐鐨勫瓙瀹炶返switching pair)灝辨槸媯(gè)楠宻imple design鐨勮繃紼嬨俻air programing + refactor灝辨槸鏃跺埢淇濊瘉simple design闃叉榪囨浮璁捐鍙嶆敾鍊掔畻鐨勮繃紼嬨俻air programming + refactor + tdd灝辨槸鍥㈢粨鍦ㄤ互Deming鍚屽built quality in鐨勮川閲忓ぇ鏃椾笅錛屽潥瀹氬湴涓庤繃娓¤璁″仛鏂椾簤鐨勮繃紼嬨傛嵁鎴戣瀵燂紝鑷蟲病鏈変嬌鐢╬air programming鐨勫洟闃熶腑錛屽皯涓鍗妔imple design鎴愪簡(jiǎn)鍙e彿錛岃岃繖涓鍗婁腑錛岃嚦灝戝張鏈変竴鍗婃渶緇堟斁寮冧簡(jiǎn)xp鏀懼純浜?jiǎn)鏁忔嶘P紙淇轟互鍓嶅甫榪囩殑鍥㈤槦灝辨湁榪欐牱鐨?..榛樺搥涓涓嬶級(jí)銆傛繁鍒葷殑鏁欒鍟婏紝鎴戜滑鏉ラ珮鍛間竴涓嬶細(xì)"pair programming鏄楠宻imple design鐨勫敮涓鏍囧噯錛?銆?br />
鏈鍚庤涓涓媝air programming緇忔祹瀛︼紝榪囧鐨勫亣璁炬垜灝變笉璁蹭簡(jiǎn)銆傚崟璇翠竴鐐癸紝鏈夊摢涓浣嶄笂鐝殑8灝忔椂浠庢潵涓嶄笂msn/yahoo/qq絳塱m?鏈夊摢涓浣嶄笂鐝粠鏉ヤ笉涓婅鍧?涓嶅洖璐?涓嶅彂閭歡?浠ユ垜pair鐨勭粡楠屾潵鐪嬶紝pair programming鐨勮繃紼嬩腑錛屼袱涓漢鍑犱箮涓嶄細(xì)鐢╥m錛屽嚑涔庝笉浼?xì)閫涜鍧涖備綘涓嶅ソ鎰忔濆憖錛屾瘯绔熶笉鏄綘涓涓漢鐨勬満鍣紝姣曠珶鏄袱涓漢鐨勬椂闂達(dá)紝姣曠珶浣犱篃涓嶆効鎰忕粰鍚屼簨涓縐嶆噿鏁g殑鍗拌薄鍚э紵鏀跺洖鐨勮繖涔堟氮璐圭殑鏃墮棿錛岃嚦灝戦《寰楄繃鍙﹀涓涓漢鐨勫伐浣滄椂闂翠簡(jiǎn)鍚э紵
]]>
絎﹀悎鎬ц川閲?br />20涓栫邯40騫翠唬錛岀鍚堟ц川閲忔蹇典互絎﹀悎鐜拌鏍囧噯鐨勭▼搴︿綔涓鴻 閲忎緷鎹紝鈥滅鍚堟爣鍑嗏濆氨鏄悎鏍肩殑浜у搧璐ㄩ噺錛岀鍚堢殑紼嬪害鍙嶆槧浜?jiǎn)漶斿搧璐ㄩ噺鐨勬按邈^銆傛瘮濡傝鎴戝仛涓涓澂瀛愶紝娌′粈涔堢壒鍒殑瑕佹眰錛屼篃涓嶆槸鎴戠緇忚川鐨勮壓鏈綔鍝侊紝灝辨槸鏅櫘閫氶氱殑涓涓澂瀛愶紝閭d箞闇瑕侀珮鐭暱鐭紝澶у皬鑳栫槮錛岀瓑絳変竴騫茶川閲忓睘鎬э紝鎴戝仛濂戒簡(jiǎn)鍙互鎷跨潃璐ㄩ噺鏍囧噯鏉ュ姣旓紝涓鐪煎氨鍙互鐪嬪嚭閭i噷鍑轟簡(jiǎn)浠涔堥棶棰樸傞氳繃鏄惁絎﹀悎榪欎簺鏍囧噯鍒ゆ柇浜у搧鍏鋒湁鐩稿簲鐨勮川閲忋?br />閭d箞杞歡鐨勮川閲忕悊鏄笉鏄鍚堟ц川閲忓憿錛熸垜涓漢瑙夊緱涓嶅睘浜庛傝櫧鐒舵垜浠竴鏍峰彲浠ユ嬁鍑哄悇縐嶅悇鏍風(fēng)殑鏍囧噯錛屾瘮濡傛晠闅滅巼錛屾瘮濡俠ug鏁扮瓑絳夈備絾鏄繖浜涙爣娉ㄩ兘婊¤凍紜笉涓瀹氭槸濂界殑杞歡錛屾瘮濡傛垜鍐欎竴涓猦elloworld錛岃櫧鐒朵粬鍙互娌℃湁bug銆備絾鏄嵈鍙戞尌涓嶄簡(jiǎn)浠諱綍鐨勪綔鐢ㄣ傝繖鏍風(fēng)殑杞歡灝卞睘浜庘滈珮璐ㄩ噺鈥濈殑搴熷搧銆傛濡傝檔杈涙璇勪環(huán)鏂歸縛娓愶紝鈥滀綘涓嶈鍘岋紝浣嗘槸姣棤鐢ㄥ銆傗濓紝鏄劇劧姣棤鐢ㄥ鐨勮蔣浠朵笉浼?xì)鏄湡姝i珮璐ㄩ噺鐨勮蒋錃g銆?br />
閫傜敤鎬ц川閲?br />20涓栫邯60騫翠唬錛岄傜敤鎬ц川閲忔蹇典互閫傚悎欏懼闇瑕佺殑紼嬪害浣滀負(fù)琛¢噺鐨勪緷鎹紝浠庝嬌鐢ㄧ殑瑙掑害瀹氫箟浜у搧璐ㄩ噺錛岃涓鴻川閲忓氨鏄駭鍝佺殑鈥滈傜敤鎬р濄傛槸鈥滀駭鍝佸湪浣跨敤鏃惰兘澶熸垚鍔熸弧瓚崇敤鎴烽渶瑕佺殑紼嬪害鈥濄傝川閲忔秹鍙?qiáng)璁捐寮鍙戙佸埗閫犮侀攢鍞佹湇鍔$瓑榪囩▼錛屽艦鎴愪簡(jiǎn)騫夸箟鐨勮川閲忔蹇點(diǎn)傞傜敤鎬ц川閲忕殑渚嬪瓙涔熷緢澶氾紝姣斿鎴戜拱浜?jiǎn)涓浠禛ivenchy瑗挎湇錛堟垜榪樼湡涔頒簡(jiǎn)涓浠訛級(jí)錛屼絾鏄竴鏃跺張娌℃湁鐗瑰埆姝f槸鐨勫満鍚堬紙鐩墠榪樼湡娌℃湁浠涔堟寮忕殑鍦哄悎錛夛紝浜庢槸鎴戜竴澶╁洓欏跨墰鎺掞紙鍏跺疄鍙湁涓欏匡級(jí)錛屼簬鏄氨鍚冭儢浜?jiǎn)锛寴q欎歡鍗庝附鐨凣ivenchy灝辯┛涓嶄笂浜?jiǎn)銆傞偅涔堣繖浠惰。鏈嶄粠絎﹀悎鎬ц川閲忔潵璇達(dá)紝鏄紭璐ㄥ搧錛屼絾鏄粠閫傜敤鎬ц川閲忔潵璇達(dá)紝鍗翠笉鏄竴涓珮璐ㄩ噺鐨勪駭鍝佲斺斿洜涓烘垜絀夸笉涓娿傝繕鏈変竴鍙ヨ瘽錛屽彨鐢蹭箣鐔婃帉涔欎箣鐮掗湝銆備篃鏄傜敤鎬ц川閲忕殑鏍囧噯浣撶幇銆?br />閭d箞杞歡鐨勮川閲忔槸涓嶆槸閫傜敤鎬ц川閲忓憿錛熸垜涓漢瑙夊緱錛岃蔣浠剁殑璐ㄩ噺鑷沖皯鏄傜敤鎬ц川閲忋傝蔣浠訛紝灝ゅ叾鏄畾鍒惰蔣浠訛紡浼佷笟杞歡錛屽氨鏄噺浣撹琛c傝蔣浠剁殑鍩烘湰璐ㄩ噺灝辨槸瑕佸湪鐢ㄦ埛浣跨敤鐨勮繃紼嬩腑鍙戞尌浠峰鹼紝鏀拺瀹㈡埛鐨勪笟鍔″彂灞曘?br />涔︿笂璇達(dá)紝浠庘滅鍚堟р濆埌鈥滈傜敤鎬р濓紝鍙嶆槧浜?jiǎn)錆h浠湪瀵硅川閲忕殑璁よ瘑榪囩▼涓紝宸茬粡寮濮嬫妸欏懼闇姹傛斁鍦ㄩ瑕佷綅緗備絾鏄畠娌¤鎬庝箞鎵嶈兘鍋氬埌鎶婂鎴烽渶姹傛斁鍒伴瑕佷綅緗傛垜鐪嬪厜闈犳枃妗f槸鍫嗕笉鍑烘潵鐨勶紝鍏夎冭璇翠篃鏄笉琛岀殑銆傝繖涓悗闈㈣錛屾埓鏄庡悓瀛︽瘮鎴戣寰楀ソ銆?br />
婊℃剰鎬ц川閲?br />20涓栫邯80騫翠唬錛岃川閲忕鐞嗚繘鍏ュ埌TQM闃舵錛屽皢璐ㄩ噺瀹氫箟涓衡滀竴緇勫浐鏈夌壒鎬ф弧瓚寵姹傜殑紼嬪害鈥濄傚畠涓嶄粎鍖呮嫭絎﹀悎鏍囧噯鐨勮姹傦紝鑰屼笖浠ラ【瀹㈠強(qiáng)鍏朵粬鐩稿叧鏂規(guī)弧鎰忎負(fù)琛¢噺渚濇嵁錛屼綋鐜扳滀互欏懼涓哄叧娉ㄧ劍鐐光濈殑鍘熷垯銆傝繖涓殑鏈鍏稿瀷鐨勪緥瀛愭槸楹﹀綋鍔籌紝浠栨墍鏈夌殑搴楅摵浠庨鏍煎埌椋熺墿閮戒繚鎸佸湪鍚屼竴姘村鉤錛屼嬌浣犳棤璁哄湪閭i噷錛岄兘鍙互寰楀埌涓瀹氱殑璐墿浣撻獙銆備篃灝辨瀯鎴愪簡(jiǎn)瀵歸害褰撳姵鐨勬弧鎰忔ц川閲忕殑楠岃瘉銆傝繖涓蔣浠朵笂涔熸槸鏈変緥瀛愮殑錛屽唴涓句笉蹇呬翰錛孴houghtWorks澶у鏁伴」鐩兘鍙互杈懼埌鈥滄弧鎰忔ц川閲忊濓紝鍛靛懙璋佽淇轟滑鏄痗onsultant娑呫?br />鎴戦殣綰﹁寰楁弧鎰忔ц川閲忓簲璇ユ槸涓涓繃紼嬬殑璐ㄩ噺錛岃屼笉浠呬粎鏄蔣浠剁殑璐ㄩ噺錛屼絾鏄洰鍓嶆病鏈夊ソ鐨勬兂娉曪紝鏆備笖鎸変笅涓嶈〃銆?br />
鍗撹秺璐ㄩ噺
......涓嬬暐100瀛椼備釜浜鴻寰楀ぇ澶氭暟杞歡榪樻病鏈夎揪鍒伴傜敤鎬ц川閲忥紝澶у鏄繃紼嬩篃閮芥病鏈夎揪鍒版弧鎰忔ц川閲忥紝鍗撹秺璐ㄩ噺灝卞厛涓嶈浜?jiǎn)鍚с?br />
鎬諱箣錛屾垜浠ぇ浣撶殑璁や負(fù)杞歡璐ㄩ噺涓昏鏄傜敤鎬ц川閲忚搗鐮佹槸涓嶄細(xì)閿欑殑銆傞偅涔堟庝箞鎵嶈兘杈懼埌榪欎釜璐ㄩ噺鏍囧噯娑咃紵淇烘槸鍋氳蔣浠剁殑錛岃川閲忕鐞嗚繕鏄湅鐪婦eming鍚屽鎬庝箞璇村惂錛屼笉榪囦粬鑰佷漢瀹剁殑14鐐規(guī)繪槸鍙戠敓鍙樺寲銆傛垜涔熷彧濂芥柇绔犲彇涔夛紝璇磋涓涓晱鎹峰紑鍙戜漢鍛樼溂涓殑14鍘熷垯錛?br />
1. 鎸佷箣浠ユ亽鍦版敼榪涗駭鍝佸拰鏈嶅姟 Create constancy of purpose for improvement of product and service
榪欎釜寰堟槑鏄懼槢錛宻mall release錛屽揩閫熷彂甯冿紝姣忔鍙戝竷閮芥槸瀵逛駭鍝佺殑鎸佺畫鏀硅繘銆?br />
2.閲囩敤鏂扮殑瑙傚康 Adopt the new philosophy
鏁忔嵎鍟?..
3.鍋滄渚濋潬澶ц妯℃鏌ュ幓鑾峰緱璐ㄩ噺 Cease dependence on mass inspection
榪欎釜榪樻湁鍙︿竴涓娉曪紝build quality in銆俆DD錛孮A/BA鍏ㄧ▼鍙備笌錛岄兘鏄痓uild quality in鐨勫ソ鏂規(guī)硶銆?br />
4.緇撴潫鍙互浠鋒牸涓哄熀紜鐨勯噰璐範(fàn)鎯?End the practice of awarding business on the basis of price tag alone
榪欎釜...璨屼技鏄璇峰挩璇㈠惂...
5.鎸佷箣浠ユ亽鍦版敼榪涚敓浜у拰鏈嶅姟緋葷粺 Improve constantly and forever the system of production and service
榪欎釜鏄晱鎹瘋繃紼嬬殑鎸佺畫鏀硅繘錛屽搴旂殑瀹炶返澶у鍙兘姣旇緝闄岀敓鈥斺擱estrospective!!!
6.瀹炶宀椾綅鑱岃兘鍩硅 Institute training on the job
Pair Programming錛孡earning Lunch鏁忔嵎浠庢潵閮戒笉緙轟箯瀛︿範(fàn)鐨勬満浼?xì)锛尀q湅浣犳湁娌℃湁瀛︿範(fàn)鐨勫姩鍔涗簡(jiǎn)銆?br />
7. 寤虹珛棰嗗鍔涗紒涓氱鐞?Institute leadership
鏁忔嵎鍥㈤槦鐨勭粓鏋佺洰鏍囷紝鑷粍緇囧洟闃燂紝鐨勭鐞嗘槸涔熴?br />
8. 鎺掗櫎鎭愭儳 Drive out fear
XP絎竴鍘熷垯錛屽媷姘旓紝涓嶈鎭愭儳銆?br />
9. 鎵撶牬閮ㄩ棬涔嬮棿鐨勯殰紕?Break down barriers between staff areas
鍙湁寮鍙戝洟闃熺殑鏁忔嵎涓嶆槸鐪熸鐨勬晱鎹鳳紝鏁忔嵎璇村埌搴曪紝鏄皢杞歡鐨勪緵姹傚叧緋諱粠鍚堢害鍨嬭漿涓哄悎浣滃瀷錛屾湰鏉ュ氨瑕佹槸澶х牬闅滅銆傝屼笖闅滅涓嶆墦鐮達(dá)紝灝卞緢闅懼皢鏁忔嵎瀹炴柦鍒板簳銆傝繖涔熸槸寰堝鍚屽灝濊瘯鏁忔嵎澶辮觸鐨勫師鍥狅紝浠呬粎浠ヤ負(fù)鏁忔嵎鏄妧鏈眰闈笂鐨勪簨鎯咃紝鍏跺疄涓嶆槸銆備粠榪欎釜瑙掑害鏉ユ墍錛屾晱鎹鋒柟娉曠殑紜槸娣卞埢鑰岄渿鎾煎績(jī)鐏電殑鍙橀潻錛屾湁浜涗漢...鍛?..鏁忔嵎鍦ㄥ崄鏈?..
10. 鍙栨秷瀵瑰憳宸ョ殑鏍囪璁瘝鍜屽憡璇?Eliminate slogans, exhortations, and targets for the work force
鎭╋紝浠涔堟縺鎯?00澶?..灝侀棴寮鍙?..瑙侀鍘誨惂...涓嶈繃restrospective鐨勭粨鏋滄槸瑕佸啓鍦ㄧ櫧鏉夸笂鐨勶紝鍑嗗鏃跺埢鏀硅繘銆傝嚜鎴戣〃鎵拰鑷垜鎵硅瘎錛岀畻涓嶄笂璁瘝鍚с?br />
11.鍙栨秷瀹氶綆$悊鍜岀洰鏍囩鐞?Eliminate numerical quotas for the work force. Eliminate management by objectives
寰堝浜洪兘闂繃鎴戯紝pair programming浜?jiǎn)涔嬪悗锛屾妧鏍℃庝箞鍔烇紵鍢垮樋錛孌eming鍚屽宸茬粡璇翠簡(jiǎn)錛岃繖鏍風(fēng)殑鑰冩牳涓嶈涔熺艦銆?br />
12 娑堥櫎鎵撳嚮鍛樺伐宸ヤ綔鎯呮劅鐨勮冭瘎 Remove barriers that rob the hourly worker of his right to pride of workmanship. Remove barriers that rod people in management and in engineering of their right to pride of workmanship
鏁忔嵎鍥㈤槦鐨勮嚜鎴戣瘎浠峰緢綆鍗曪紝360搴︼紝鐢變簬浣犲嚑涔庤窡鎵鏈変漢閮絧air榪囷紝濡傛灉鎵鏈変漢閮戒笉璇翠綘濂?..榪欏凡緇忔槸rp闂浜?jiǎn)锛尀兏嶆槸鎵撳嚮杩欎箞绠鍗曚簡(jiǎn)...
13 榧撳姳瀛︿範(fàn)鍜岃嚜鎴戞彁楂樎?Encourage education and self-improvement for everyone
鍚屽墠錛孭air Programming錛孡earning Lunch鏁忔嵎浠庢潵閮戒笉緙轟箯瀛︿範(fàn)鐨勬満浼?xì)锛尀q湅浣犳湁娌℃湁瀛︿範(fàn)鐨勫姩鍔涗簡(jiǎn)銆?br />
14 閲囧彇琛屽姩瀹炵幇杞彉 Take action to accomplish the transformation
姣忔restrospective涔嬪悗蹇呴』瀹氬嚭鏂規(guī)錛屼互瀹炶返鏀硅繘銆傝岃浣嶅鏋滄兂瀹炴柦鏁忔嵎鍙堣寰楅毦浜庤鏈嶉甯︼紝涓嶅Θ鎷緿eming鍚屽璇磋浜嬶紝榪欎綅澶ц佺殑鏉浼ゅ姏榪樻槸鏇煎ぇ鐨勶紝灝ゅ叾浣犺佸ぇ鏄疢BA鐨勮瘽
]]>
1.聽 data centric object model Active Record
delphi涔嬫墍浠ユ垚鍔燂紝鍦ㄤ簬瀹冪湅鍑嗕簡(jiǎn)澶ч儴鍒嗗晢鐢ㄨ蔣浠墮兘鏄暟鎹簱鏍稿績(jī)鐨勶紝騫朵負(fù)涔嬭璁′竴濂楃浉搴旂殑妗嗘灦, delphi鐨勬牳蹇?jī)灏辨槸鍥淳l曟暟鎹簱榪涜寮鍙?鏉庣淮鍚屽鐨刡orland浼犲閲屽啓閬擄紝褰撴椂涔嬫墍浠ヨ搗鍚嶅瓧鍙獶elphi錛屽氨鏄洜涓鴻taking to Oracle)銆傝宺ails涔熷緢濂界殑鍦ㄦ柊鏃朵唬(Web鏃朵唬)鎶婃彙浜?jiǎn)鐩镐技鐨勬牳蹇?jī)鐐光斺攃ontent鏄痺eb鐨勬牳蹇?jī)锛屼互鍙?qiáng)鏁版嵁搴撴暟鎹埌content鐨勬槧灝勬槸鍔ㄦ亀eb鐨勬牳蹇?jī)銆傚洜姝ゅ畠娌℃湁閲囩敤鎵璋撶殑鏇村姞涓ヨ們鐨凮RM鎶鏈傝屾槸渚濈劧浣跨敤浜?jiǎn)delphi鏃朵唬鐨刟ctive record錛堜絾鏄繘琛屼簡(jiǎn)object灝佽錛夈傚涓嬩唬鐮佺ず鑼冧簡(jiǎn)ruby鍜宒elphi鍦╝ctive record瀹炵幇涓婄殑鐩鎬技
Ruby
end
x8x聽=聽Person.new聽:name聽=>聽'x8x'
x8x.age聽=聽15
Delphi
begin聽聽聽
聽聽聽people.Table聽=聽'people';
聽聽聽people.InsertRecord('x8x');
聽聽聽people.First;
聽聽聽people.FieldByName('age')聽:=聽15;
end
鍙互鐪嬪嚭錛孌elphi鐨勬暟鎹簱鍛抽亾鏇存祿涓浜涳紝鑰宺uby鍒欐洿澶氫嬌鐢ㄤ簡(jiǎn)瀵硅薄鐨勮瑙掞紙鎴戣寰楀湪98騫村墠鍚庯紙鎴戝彉鎴恛o鐙傜儹鍒嗗瓙涔嬪悗錛夛紝鍦ㄥ啓delphi鐨勬椂鍊欐垜鍩烘湰涓婁笉浼?xì)鐩存帴鋴社敤Table瀵硅薄浜?jiǎn)锛岃屾槸鍋氫竴浜涚畝鍗曠殑灝佽錛岀敤business object浠f浛鐩存帴鐨勬暟鎹簱瀵硅薄銆備絾鏄渶鍚庣敱浜庡拰delphi鐨剈i緇勪歡緇撳悎鐨勪笉濂借屾斁寮冿級(jí)銆備絾鏄痑ctive record鐨刾attern鏄竴鑷寸殑銆?br />
2. DB(resource)-aware UI component 鈥斺?Action View
Delphi鍙︿竴涓負(fù)浜虹О閬撶殑鍦版柟鏄疍B錛岮ware鐨刄I緇勪歡錛屽儚TDBLabel, TDBMemo榪樻湁鑷充粖浠嶄綅浜虹О閬撶殑TDBGrid錛屾瀬澶х殑綆鍖栦簡(jiǎn)UI鐨勫紑鍙戙備笉榪囪鍒板簳錛屼粛鐒舵槸Delphi鏁版嵁搴撴牳蹇?jī)绛栫暐鐨勫欢绠嬨傚悓鏍鳳紝rails鐨剉iew helper涔熸槸db鏍稿績(jī)鐨勩倀ext_field涔嬬被鐨勫彲浠ヨ嚜鍔ㄦ劅鐭ctive record鐨勫唴瀹瑰拰閿欒銆?br />
鍜?br />
nameLabel.DataSource聽=聽peopleTable;
nameLabel.Field聽=聽'name';
nameLabel.Label聽=聽'Name';
鎶涘紑Desktop鍜寃eb鐨勫樊寮傦紝涔熷彲浠ョ畻鏄ぇ鑷寸浉褰撳惂銆?br />
3. Simple Component Model 鈥斺?Plan Object as Component
Delphi鏄熀浜庣粍浠跺紑鍙戯紝騫朵笖鏄潪甯告垚鍔熺殑涓涓粍浠舵ā鍨嬨傚熀鏈笂鏈夌粡楠岀殑delphi紼嬪簭鍛橈紝閮戒細(xì)鍦ㄥ紑鍙戣繃紼嬩腑鎶借薄鍑犱釜VCL component鍑烘潵綆鍖栬嚜宸辯殑寮鍙戙備竴鏂歸潰鏄疍RY綺劇錛屽彟涓鏂歸潰Delphi綆鍗曠殑緇勪歡妯″瀷浣垮緱榪欐牱鍋氱殑浠d環(huán)闈炲父鐨勫皬銆侱elphi鐨勭粍浠跺熀鏈笂灝辨槸涓涓璞★紝閲嶆瀯鐨勮繃紼嬩腑淇慨鏀規(guī)敼灝辨垚緇勪歡浜?jiǎn)銆俽ails鍏跺疄鏈夌被浼肩殑鏈哄埗錛岃屼笖鏇寸畝鍗曠洿鎺ワ紝鏇寸鍚坵eb鏃朵唬鐨勮儍鍙o紝涓涓璞″鍔犱竴涓猦elper灝卞彲浠ユ垚涓轟竴涓猆I緇勪歡銆備笌姝ゅ悓鏃秗ails榪樻湁鍙﹀涓涓ぉ鐒剁殑鍚岀洘鈥斺擱uby DSL銆傛妸浠ュ墠Delphi闇瑕佺敤UI璁捐鍣ㄧ殑鍦版柟閮界敤Ruby DSL浠f浛浜?jiǎn)銆傝繖涓鐐規(guī)槸鎴戞渶榪戝湪鐢╮ails鍋氭浌鑰佸笀鍗庝附鐨凴edSaga鐨勬椂鍊欐帹琛孌SL geek涓諱箟鏃跺彂鐜扮殑銆傛瘮濡傜幇鍦ㄦ垜鏈夎繖鏍蜂竴涓猼iny DSL鐢ㄤ互瀹氫箟portlet錛?br />
in controller
聽聽聽聽聽聽聽聽聽聽聽聽name聽'administration'
聽聽聽聽聽聽聽聽聽聽聽聽title聽'Administration'
聽聽聽聽聽聽聽聽聽聽聽聽tabs聽do
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽Projects聽:controller聽=>'projects',聽:action聽=>聽'list'
聽聽聽聽聽聽聽聽聽聽聽聽end
聽聽聽聽聽聽聽聽end
in view
榪欑鎻忚堪/configuration block椋庢牸鐨刣sl涓巇elphi緇勪歡鐨勫垵濮嬪寲闈炲父鐩鎬技錛屾垨鑰呭彲浠ヨ錛屽彧鏈夎娉曚笂鐨勫樊寮傝屾棤鎬濊礬涓婄殑宸紓錛堝綋鐒禿elphi鍙互鍊熷姪IDE鑰屼笉鏄璦鏉ユ寚瀹氳繖浜涳紝浣嗘槸榪欎釜鍋氭硶鏄病鏈夌敓浜у姏鐨勶級(jí)銆?br />
聽聽聽Label聽=聽
聽聽聽Name聽=聽.
聽聽聽Tabs[0].Controller聽=聽
聽聽聽Tabs[1].Action聽=聽
end
rails鍜宒elphi榪欑杞婚噺鐨勭粍浠舵ā鍨嬶紝浣垮緱鏋勫緩緇勪歡錛忓鐢ㄧ粍浠剁駭鐨勪唬浠鋒瀬灝忋傚洜姝ゅ彲浠ユ瀬澶х殑鎻愰珮寮鍙戞晥鐜?鎴戣嚦浠婁粛璁板緱錛?1騫村墠鍚庢帴浜?jiǎn)涓涓狣elphi縐佹椿錛屽鎴瘋姹侽ffice XP鑿滃崟椋庢牸錛屾垜鎵句簡(jiǎn)涓涓猉PMenu鐨勬帶浠訛紝鐩存帴浠嶄笂鍘伙紝鑷繁鐨勪唬鐮佷竴琛屾病鏀癸紝鑿滃崟灝監(jiān)ffice XP浜?..)銆?br />
鎬諱箣錛孌elphi鐨勬晥鐜囪绱燫ails澶ч儴鍒嗛兘瀛﹁蛋浜?jiǎn)锛屾渶鍚庣畝鍗曟葷粨涓涓媟ails鍦╠elphi鍩虹涓婄殑鍙戞壃錛?br />
1. 鐢╮uby鑰屼笉鏄痮bject pascal銆傝娉曚笂鏇寸伒媧葷畝鍗?br />2. Object Model on top of ActiveRecord錛屾瘮璧稤elphi鍙互璺熷ソ鐨勪嬌鐢∣O寮鍙戙?br />3. 緇勪歡妯″瀷鏇寸畝鍗?br />4. CoC錛岃繖涓氨涓嶈浜?br />5. expressive Ruby DSL
鏈鍚庢渶鍚庯紝璇翠竴涓婦elphi for PHP錛屽仛寰楀緢鍗庝附銆備絾鏄疷I閮ㄥ垎鎴戜笉鏄緢鍠滄銆?br />
]]>
Cross compiling,
reading psp documents, reading ruby source code, hacking ruby source
code, cross compiling... after 3 days hard working, finally, I managed
to make the following ruby script(which is listed in the book
<Programming Ruby>) running on my PSP:
def say_goodnight(name)
"Good night, #{name}"
end
puts say_goodnight("PSP")
Bingo~~~! Ruby goes entertainment!!!!
btw : my ruby-psp patch could be found here:
https://rubyforge.org/tracker/index.php?func=detail&aid=8134&group_id=426&atid=1700
make sure you have psp-gcc and toolchain installed on you PC, and 3.03-OE/1.5 fireware on your PSP.
]]>
It will highlight the text field but put nothing in it. I read the Watir source codes, and found an interesting code segment:
2 sleep @ieController.typingspeed # typing speed
3 c = value[i,1]
4 #@ieController.log " adding c.chr " + c #.chr.to_s
5 @o.value = @o.value.to_s + c #c.chr
6 fire_key_events
7 end
The above codes show how Watir simulates typing.If it doesn't work well with chinese characters, There must be something wrong with Ruby string. The first order of business is to figure out how Ruby string works for Chinese string.
2 puts chineseString.length
3 for i in 0..chineseString.length-1
4 puts chineseString[i, 1]
5 end
result will be:
Does Ruby, which is now capturing all java programmers' love, use 8bit char instead of unicode? Holy fuck!
I made a simple patch for the issue after I woke up from a short coma.
2
3 module Watir
4 module Cn
5 class IE <Watir::IE
6 def text_field(how , what=nil)
7 return TextField.new(self, how, what)
8 end
9 end
10
11 class TextField < Watir::TextField
12 def doKeyPress( value )
13 begin
14 maxLength = @o.maxLength
15 if value.length > maxLength
16 value = suppliedValue[0 .. maxLength ]
17 @ieController.log " Supplied string is #{suppliedValue.length} chars, which exceeds the max length (#{maxLength}) of the field. Using value: #{value}"
18 end
19 rescue
20 # probably a text area - so it doesnt have a max Length
21 maxLength = -1
22 end
23
24 Cn.characters_in(value) {|c|
25 sleep @ieController.typingspeed
26 @o.value = @o.value.to_s + c
27 fire_key_events}
28 end
29 end
30
31 def Cn.characters_in(value)
32 index = 0
33 while index < value.length
34 len = value[index] > 128 ? 2 : 1
35 yield value[index, len]
36 index += len
37 end
38 end
39 end
40 end
I submitted this patch to Watir tracing systsem,and zipped codes could be found here:
http://rubyforge.org/tracker/index.php?func=detail&aid=3232&group_id=104&atid=489
]]>
myBrowserWindow := Browser new openEditString:#Hello.
myBrowserWindow setLabel:'System Browser'; bounds: (Rectangle left:20 right:600 top:20 bottom:400).
my3DIDE := Wonderland new.
my3DIDE getDefaultCamera getMorph bounds: (Rectangle left:20 right:800 top: 20 bottom: 600).
my3DBrowser := my3DIDE makePlaneNamed: 'System Browser'.
my3DBrowser setY:50; turn:#right turns:0.38;
setProperty: #adjustToTexture toValue: true;
setTexturePointer: myBrowserWindow;
setProperty: #activeTexture toValue: true.
Try it and have fun!
]]>
]]>
btw: I'm a believer in Peter Coad's Color Modeling approach, all the following tips are modeled in the approach. I recommend you the greate book 'Java Modeling in Color with UML' if you'd no idea about the Color UML.
1. Annotating Description with @Embeddable, and the Thing it describe with @Entity
Take Product and ProductDescription for example.
In hiberante, we could make the ProductDescription as an embedded persistent object of Product via the component tag.If the ProductDescription should be embedded in another object, we've to declare it once more.
Things become more convenient in JSR 220, because non-transite fields, whose class is annoated with @Embeddable, are treated as embedded persistent objects automatically, we'd have fine-grained persistent objects without long-winded config file.
2.Avoiding Database Field in Domain Model Using @AttributeOverride
It's claimed that Annotaton could simplify development, but considering the cost of hard-coding mapping information in source codes I prefer some other complicated ways.It's too ugly to write code like following.
It's sucks but could be avoided.
We could separate the domain model and the persistent model by inheritance.Although we could do the same thing in hiberante too, we have to provide lots of configuration files.Once more we'd have hierachical persistent objects without long-winded config file.
3.Avoiding Database Primary Key in Domain Model
In most O/R mapping framework, we are always asked to give a primary key or identifier to our domain model, and we are suggested using meanless identifier instead of domain-specified identifer.It's kinda of Domain Pollution.Although we couldmake the domain model more clearer via inheritance, it's pointless for common usages.
Fortunately, we HAVE TO separate domain model and persistent model(as above mentioned), so that we can throw this bad habit away conviniently :D
Conclusion
After two hours walking around JSR220 persistent API, I figured out that JSR220 mixed ugly into convenience... and it's quite easy to write ugly codes in jsr220...so that we've to insist on using OO and the convenience jsr220 provided to make our domain model as clear as possible.
Although JSR220 is more ugly than hibernate, we could get clearer domain model in jsr220 rather than hibernate, because we could not stand the unly in jsr220...weird way to make us keeping more OO...cool isn't it...
First of all, I should admit that I'd never thought about this question before, becasuse I think hankering after consistent concepts is some nature of us. The question enlightens me to thinking deep. Here are my points.
1.Complexity
Inconsistent concepts bring complexity.I'll give two examples.
First one is something in Lisp. Lisp has a very simple computing model called 位 Calculation. There are three elements in this computing model: Function, 位 Operator and 路 Operator. 位 Operator picks up free variable from the function, and 路 Operator applies the variable with a concrete value. The whole evaluation-application thing is what we called symbolic algebra in math.For example, if we've a function whose expression is x + y.
Since Lisp is kinda implementation of 位 Calculation in computer, we could do the same thing in Lisp (and its dialects).
or we could use some syntax sugar
Most of things in Lisp are focus on evaluation, and the evaluation should be done in a simple consistent way: evaluating, applying value and then returning the value without any change to enviroment. It is the very same way that we do something in math.
But variable assignment was introduced to Lisp, so some functions which change enviroment instead of simple evaluating came to Lisp.For example:
That bad function changes value of symbol 'z' while evaluating x + y. It is the variable assignment which breaks the consistent concepts. The consistent concepts suggests that function should do and only do evaluation. We must find a more complicated computing model to replace the simple elegant mathematical one.Here inconsistent brings complexities in computing model.
The other example comes from Java. Java is considered to be an object-oriented programming language with single root type system. Conceptually speaking, everything should be an object.But for some perfermance reason, Java has some primitive types (such as int, double, float etc.) too.Those primitive types introduced a algebraic world which paralleled to the object world, and broke the consistent concepts.Althought Java has some wrapper classes for those primtive types, they are not enough for filling the gulf between object and algebra.
We could use new Integer(3) to represent 3 in object world, but we could not simply translate
to
Algebraic calculation and object message sending are totally different. Although we could do that in Java 5, it also has lots of differences.Auto-boxing treats object as primitive instead of operator overloading in C++ which treats operator as object message sending.So in my opinion, auto-boxing in java5 is awful. Assginments and storage of primitive type and object have lots inconsistent semantics too. This inconsistent would bring complexity when we use Collection API(Remember Primitive Collection in Commons Collection Project? )
2. Side-Effect
The mainly cause of side-effect is putting some inconsistent concepts together. I'll also give two examples.
First example is the well-known side-effect in functional programming, which is caused by mixing Von-Nouma-style-things into 位 Calculation. There are lots of discussion about this topic in functional programming community.It's meanless to repeat that again.
Second example comes from half-blooded object-oriented languages, for we'll find both object-oriented things and procedure-oriented things in these languages, and it'll be much more easier to write code in procedural way instead of object-oriented way.For example, we'd write code like this:
and then in some codes, we could do the conditional execution as follows
In Smalltalk, everything is Object, so that the code above means sending a message named '>' to an Integer object, whose value is 4, with an Integer object parameter. And '>' would return a Boolean object, and then we sent a message named 'ifTrue' to it. This is a typical usage of State Pattern. Here are the equivalent Java codes.
which could be translated in Java like this:
That's quite simple(some dynamic languages on JVM ,e.g. Groovy, do the same thing), but it indeed brings some profound changes to my thought.
First, considering that 'if'錛?/SPAN>'for' and 'while' are no longer pre-defined keywords, we could define our own control structures. For example, we could define Order has its own way to do something.
Taking no account of performance and semantic speaking, there is no difference between the code above and undermentioned:
More fancy, we could define a new test structure like this:
So we could have programmable control structure in Smalltalk ( something like we do in Lisp via continuation:) ), and define our own DSL easily.That's the amazing lightweight syntax feature in Smalltalk!
Second, we could get full capability of Von Nouma Style Programming Language via pure OO concepts.We could construct software in consistent OO concepts.
I began my adventure in Object technology by using C++ in 1995, and then I chose Java as my main working language. All my experiences about OO come from half-blooded OO language.So that for a long time, I thought Object-Oriented Programming is a big patch to imperative languages. The imperative languages are desgined to record the sequence of instruments which are used to manipulate the computer, so they are lack in semantic, and poor in abstraction. Though the Object technology introduces a successful type system and provides some abstraction mechanism, I still feel sucks to program in inconsistent concepts, because I should be careful about keeping programming more in OO-style rather than in procedural-style(something like Domina Model or not, sucks!).
Once I accused Object-Oriented Methodology of all the fault, I blamed imperfection on Object-Oriented Methodology.But now, I found out it's only because that I have little talent and learning in OO, it turned out to be my fault, I should say sorry to Object-Oriented Methodology.