「三十歲的黑洞」之詳細說明

我看了天文:三十歲的黑洞,針對「我們正觀察到黑洞三十歲的樣子」這一句,我覺得可以進一步詳細說明。

我對相對論有些了解,但這個問題也是想了很久,以下請指正。

以五千萬光年距離的星體來說,其後退速度應該也蠻接近光速的,由地球上看該星體,星體的時間會走得會非常慢。意思是說,雖然在地球上過了三十年,但現在看到的光並不是誕生後三十年時發出的,也許是誕生後一年發出的,也就是現在可能看到的是一歲時的樣子。

但上面分析只考慮狹義相對論與哈柏常數的效應。這個例子又扯到必須用廣義相對論來解釋的黑洞。

黑洞本身不發光,或者說發射的光都會落回黑洞。因此我們看不見黑洞本體。而在黑洞事相地平面之外的光,是可以來到地球,但越接近事相地平面的光,必須花越久時間脫離 (趨近於事相地平面上的光,則要花趨近於永遠的時間才能脫離)。

因此除了超新星爆炸所產生的強光外,我們僅能看到中心星體蹋陷當中,且位於事相地平面之外的部份所發出的光。而且由外界看,其蹋陷過程是無限久 (因為越近的光要花越久的時間才能到達外界觀察者)。這也導致其波長很快被拉長,紅移至非常非常微弱的程度。

也就是說,即使位在該黑洞旁,比如說一光年的位置觀察,不用考慮狹義相對論與哈柏常數之效應。三十年後所看到的光,仍然是處於蹋陷當中,事相地平面之外的光,也就是看起來該星體仍緩慢地蹋陷當中…

狹義與廣義相對論的結果都是看起來時間變慢,因此結論是,現在所能「看到」的並不是黑洞本體三十歲的樣子,而是仍在誕生之初,也許幾秒、幾分鐘內,形成貨真價實之黑洞之前蹋陷中的樣子。

再論實際的天文觀測。上述所謂蹋陷中樣子的光,很快就變得微弱地偵測不到,技術上能偵測到的是周圍吸積圓盤,周圍物質被吸入黑洞前,被強大潮汐力撕碎時發出的強烈光線,也就是原文中的 X 光。

所謂潮汐力,就是不同距離所感受到的重力不相等所產生的拉力。最直接的例子就是地球海水因月球 (及太陽) 重力而有面向月球及背向月球處有海水升高的潮汐現象。黑洞端處的引力大於背對端處的引力,而且引力之差大到足以撕碎任何大小與質量的物質,包括原子、原子核在內。所以雖然有可能「通過黑洞/蟲洞」到達「另一世界」,但在到達前,太空船與太空人都已化為基本粒子,原本的樣子都不復存在了,怎麼可能活著見到另一世界呢?

而吸積圓盤,則是因廣義相對論的重力拖曳效應,也就是質量的移動會拉扯,扭曲四維時空。中子星都可以每秒旋轉數十圈,黑洞只會旋轉得更快 (旋轉這麼快是因為角動量守恆原理,如同溜冰選手縮手,旋轉會加快的道理一樣。高質量縮在極小半徑,轉速當然變得難以想像的快),導致周圍物質也會被引力拖曳,一起旋轉。好像水中漩渦一樣,越近轉越快,越無法脫身。旋轉最快的地方自然是赤道,因此物質漩渦會向赤道平面靠近,看起來就成為如土星環,但更為大面積,越靠近越密集、扁平的「吸積圓盤」了。

當然,就外界觀察者而言,周圍物質吸入黑洞的過程,一樣是無限久。越接近越慢、越暗、越紅移、越旋轉、越壓扁 (因為靠近端「看起來」向黑洞前進得比遠離端更慢,故「看起來」越來越扁,事實上,潮汐力會讓靠近端向黑洞前進得比遠離端更快,所以實際上是前後拉長)。

張貼在 物理 | 發表迴響

轉換至 WordPress

因為 Windows Live Spaces 要轉換至 WordPress…所以…就跟著轉換過來了…不過還是不太習慣就是了…不知道會不會繼續下去…

張貼在 網誌 | 1 則迴響

轉換通知

因為個人因素,這個網站以及 Ning 網站一直沒有好好灌溉。沒想到 Ning 準備要全面收費了…Windows Live Spaces 也一直沒改善…看來是該換新據點的時候了…我也不知道要換到哪裡比較適合…暫時先轉到我的 FaceBook 帳號 Chris Torng,仍然想追蹤我的消息的人,就加入好友一下吧…

另外我推薦 Scrum Community in TaiwanDavid Ko 的學習之旅Teddy Chen 搞笑談軟工。我有很多觀念都是向他們學習的。

張貼在 網誌 | 發表迴響

MOQ 撰寫 Mock 的測試框架 + 我自己寫的例外測試函式

MOQ The simplest mocking library for .NET 3.5 and Silverlight with deep C# 3.0 integration 看起來還蠻有趣的,想寫 Mock 的人可以參考一下。


我自己先前也有為了測 Exception 而使用了 lambda expression,覺得 lambda expression 是個全新的寫程式方法,一開始看起來會比較難理解,但有時可以減少很多程式碼…減少程式碼又會讓程式碼較易讀…

標準的測試寫法,在待測函式會丟出預期中的例外時,要使用 [ExpetationException],但只能一個 TestMethod 測一個例外。我寫的這個功能,是為了在同一個 TestMethod 中可以測試多個會丟出例外的目標函式。

程式碼很短,貼出來供參考:


正常的連續測試例外的寫法會是這樣:

[TestMethod]
public void TestThrowExceptions()
{
    Foo foo = new Foo();

    try
    {
        foo.ThrowArgumentException();
        Assert.Fail();
    }
    catch (Exception ex)
    {
        if (ex.GetType() != typeof(ArgumentException))
            Assert.Fail();
    }

    try
    {
        foo.ThrowArgumentNullException();
        Assert.Fail();
    }
    catch (ArgumentException ex)
    {
        if (ex.GetType() != typeof(ArgumentNullException))
            Assert.Fail();
    }
}

非常地長…而且重覆的地方很多…但 try/catch 樣式又沒辦法包在共用的子函式中重覆呼叫,因為裡面有 foo.xxx() 會每次都不一樣…這就令我想到: 匿名函式可以上場了…

以下是可以重覆使用的測試函式:


public static void Throws(Type exceptionType, Action action)
{
    if (exceptionType == null)
    {
        throw new ArgumentNullException("exceptionType");
    }

    if (exceptionType != typeof(Exception) && !exceptionType.IsSubclassOf(typeof(Exception)))
    {
        throw new ArgumentException("exceptionType 參數必須為一例外型別。", "exceptionType");
    }

    try
    {
        action();
    }
    catch (Exception actualException)
    {
        if (actualException.GetType() != exceptionType)
        {
            Assert.Fail("預期要丟出例外 {0},但卻丟出例外 {1}。此例外之內容為: {2}", exceptionType.ToString(), actualException.GetType(), actualException.ToString());
        }

        return;
    }

    Assert.Fail("預期要丟出例外 {0},但卻完成執行,沒有例外。", exceptionType.ToString());
}  

測試的寫法為:
AssertExtension.Throws(typeof(ArgumentNullException),() => foo.Bar());


後來看到這個 MOQ 後,發現使用 Generic Method 更簡單,於是改寫如下:

public static void Throws<T>(Action action) where T : Exception
{
    try
    {
        action();
    }
    catch (Exception actualException)
    {
        if (actualException.GetType() != typeof(T))
        {
            Assert.Fail("預期要丟出例外 {0},但卻丟出例外 {1}。此例外之內容為: {2}", typeof(T).ToString(), actualException.GetType(), actualException.ToString());
        }

        return;
    }

    Assert.Fail("預期要丟出例外 {0},但卻成功完成執行,沒有例外。", typeof(T).ToString());

測試的寫法為:
AssertExtension.Throws<ArgumentNullException>(() => foo.Bar());


因為在原來的寫法,丟入 exceptionType 有可能不是 Exception 類別,因此要在執行時期做檢查。新的寫法,若是不正確的類別,會無法通過編譯…因此就不必做執行期檢查。而且測試的寫法也更精簡一點。

所以連續測試丟出例外的 TestMethod 可能是這樣:
[TestMethod]
public void TestFooToInt()
{
    Foo foo = new Foo();

    AssertExtension.Throws<ArgumentNullException>(() => foo.ToInt(null));
    AssertExtension.Throws<ArgumentOutOfRangeException>(() => foo.ToInt("a"));
    Assert.AreEqual(1, foo.ToInt("1"));
    Assert.AreEqual(-1, foo.ToInt("-1"));
}

這樣就可以在同一個 TestMethod 用很簡單的寫法測會丟出例外的函式了。

一開始寫 MOQ,到後面全部是寫我自己的東西,跟 MOQ 沒什麼關係…

張貼在 團隊開發 | 發表迴響

預備推廣 Agile 軟體開發方法

此分享空間已經不再維護,我另外開了一個預備推廣 Agile 軟體開發方法的網站,在 http://christorng.ning.com/,請大家往前支持。
張貼在 團隊開發 | 發表迴響

關於 Google 瀏覽器 Chrome

ZDNet[網路部落格]瀏覽器只要快就好?我所寫的回應,轉來此處與大家分享。


Chrome 可以搶得到的佔有率,主要應該是 IE 以外的 FF/Opera/Safari 等,因為用 IE 的人還是繼續會用 IE,會想用 FF/Opera/Safari 等其他瀏覽器的人,也才會想試用 Chrome,而可能被它吸引。最該緊張的應該是 FF 吧。

FF 之前才拿到三年的 Google 合約,可見 Google 並沒有想要吃掉 FF,而是希望 FF 繼續侵蝕 IE 市場。

如果真想要搶 IE 的佔有率,最簡單的做法不是遵循標準,而是完全支援 IE 的所有語法…Chrome 沒有這麼做…

Google 自己都講了,它並不在乎 Chrome 的市佔率。它的推出,更重要的任務是逼迫其他瀏覽器的速度也要加快,最好也加上防當、應用程式捷徑等讓一般網站變得像本機應用軟體的特性。所有的瀏覽器速度加快了,執行速度變得跟本機應用程式相當,使用者就會更喜歡使用網路應用程式,而不喜歡自行安裝本機軟體了。

因此,免費開放原始碼的 Chrome 市佔率即使是 0%,只要大家都喜歡使用網站服務,Google 的目的就達到了。Google 想賺的錢是來自線上流量/廣告,而 Google 網站使用 JavaScript 的量又特別大。加速 JavaScript 這個環節,讓網站服務執行速度與本機一樣快,這就是 Google 所要的。

使用者習慣上網處理工作,而不是在本機安裝軟體後,裝置/OS 的重要性就日漸降低,不在乎你用什麼裝置、OS、瀏覽器,反正只要一上網,什麼工作都可以做。不必再搞防毒、備份、一堆 Windows 更新又得重開等麻煩的事情。

IE 為了保住佔有率,也得加把勁加速 JavaScript 及其他部份的執行速度,這也讓自己的 OS 版本變得不重要 (大家就不必再吵需不需要升級 OS 了),自己打敗自己。這就是 Google 對抗微軟的絕招,Chrome 成功失敗都無所謂,反正 Google 只要專心做第一名的線上服務提供者即可。

Google 更想藉由 Chrome 表達的,是「你們的瀏覽器都太複雜了」,在一堆華而不實的功能上做文章,卻沒有把核心執行速度放在第一位。他想要證明:「你們瀏覽器裡的那一堆功能,我可以全部搬到網路上來做。」

因此, Google 瀏覽器真的只是一個很簡單的窗口,窗口不必做什麼花樣,只要窗外的世界更美好就夠了。

我只好奇一點,Google 瀏覽器為何沒有全螢幕顯示的功能。就是完全蓋住工作列,只用瀏覽器執行日常工作,瀏覽器的 Tab 就可以切換各個「應用程式」,完全取代工作列了…

更甚者, Google OS 也可以推出來,只需要比 Linux 更更簡單的硬體,只有瀏覽器一個功能,一切只要上網都可以解決。(當然我知道這個可能講得太誇張了,但,是否可能是將來的趨勢?)

上線費用太貴? 沒問題,只要你願意看廣告,一切都是免費的。電腦可以送給你,GPhone 也可以送給你。免月租費,免連線費,一切全部免費。所有的活動都由廣告商支付,換個方式講是所有想賣商品給消費者的廠商,將支付一切的線上活動費用,只求你上它的網站進行消費。

微軟已經被逼得要走上相容於標準之路,將來所有網站撰寫者的工作將會更容易,可以寫一套全部都能跑。

還想要撰寫本機軟體嗎? 還想下載、安裝、破解,與莫名奇妙的問題奮鬥、防毒、備份嗎?

還想學各種程式語言與技術嗎? 何不把 HTML/CSS/JavaScript 這一套徹底搞通就好?

越加越多功能的 Windows 還賣得出去嗎? 偏偏那些功能上網就有免費的…
.
.
.
.
.
.
你所要付出的代價,就是隱私。

Google 在隱私這方面是一直受爭議的。是的,廣告要賺錢,第一就是掌握客戶資訊,才能精準行銷。

Google 的策略,資料與軟體都在它的伺服器上,一切上網都能解決,你就是相信它,把你的一切都交給它。它如果關了,你的一切也就沒了。

再來還可以扯到 Live Mesh。Live Mesh 是微軟仍然要讓裝置很重要,讓你所屬的所有裝置,任何現有既成的軟體,都能很輕易地互相同步 (這樣你就不需要依賴線上服務來達成到處皆可取得的特性),沒有自己所屬裝置時還有 Live Desktop,其上的使用經驗與本機 Vista 完全相同。但這也限制了它的使用族群,基本上只在 Windows 使用者裡。Google 的策略則針對所有使用者,而且管道是大家早都有也用得很習慣的各式瀏覽器 (Google 並沒有期待你要用 Chrome 上網!),而不是目前還在 Tech Preview 的全新軟體 Live Mesh。依我個人目前看起來,Google 的策略贏面較大。

由 Live Mesh 來看微軟的策略,軟體可以安裝在你的電腦上,資料也可以本機處理,每一個裝置之間自動同步資料也可以完全點對點完成 (目前還不行,將來的版本才行),根本不會到微軟手上。微軟伺服器只用作當你不在自己的電腦上網時,還有最後一個備用方案。你想放全部資料進去也可以,完全沒有也沒關係,只是有時會不太方便。

企業會比較不願意把資料交給外人管理。但它也不想沒事被逼著簽軟體合約,兩三年就換一版 Windows、Office 或 IE,把本來用得好好的資訊系統給搞砸,又得花額外的人力去處理多餘的問題。

我也在推測,微軟在 Windows 7 之後,何去何從? 我公司內的網站/軟體,到現在連 IE7/Vista 都還沒辦法完全相容,還有可能去買 Windows 8/Office 201x ??????

Windows 8/Office 201x 可能沒人要買了…微軟怎麼辦? 要針對全網路時代,重新發明新的網路 OS??? 那過去一切的優勢都歸 0 了? 但現有優勢也一直在流失中…不做是不是等死?

Google 瀏覽器不會對瀏覽器市場的佔有率分配有多少影響。但它的釋出,將影響所有的瀏覽器,把核心功能做得更快,提高一切線上服務的可用性,降低作業系統與裝置的重要性。

Google 將會大大得利,微軟則會陷入「要不要以自己的線上服務 打自己的本機軟體」的矛盾苦戰。


你要選擇將自己的一切交給一家公司,完全相信它會好好保管你寶貴 (也許其中許多根本就不寶貴,只不過因為免錢,沒必要留的垃圾也全放進去) 的資料,將來有格式轉換時,一定會幫你轉換到最新的平台? 至於資料放在它那兒,它要怎麼運用,就相信它的隱私權說明了,雖然你從來也沒看過裡面寫些什麼…

還是選擇把隱私、資料放在自己的裝置上,自己想辦法維持電腦正常運作,克服一切的麻煩問題,任何的格式轉換、備份也自己包辦?

張貼在 電腦和網際網路 | 發表迴響

ChrisTorng 樣式訊息記錄在 Vista 下的問題

感謝 Tony 提醒,告知 ChrisTorng 樣式訊息記錄在 Vista 下無法儲存設定的問題,另我也發現刪除對話階段功能亦有問題。慚愧的是,雖然我自己也使用 Vista,但卻從未用過自己的訊息記錄工具。目前我仍不確定問題是 Vista 造成還是 IE7 造成,若有朋友有 XP 已安裝 IE7 可回報一下是否正常。

刪除對話階段之問題目前仍不知如何解決。而儲存設定的問題,追查了一下,遇到兩個問題,一個是檔案路徑分隔字元原本是 "\",現在變成 "/"。這個問題倒容易解決。另一個問題,不支援中文檔案路徑。目前會遇到的中文檔案路徑,包括「我已接收的檔案」及「記錄」兩者。我試了一下,找不到方法可以正確讀寫中文檔案路徑,只試出來純英文路徑是正常的。因此必須要將訊息記錄移至純英文路徑上才能正確讀寫設定檔。

也就是說,就目前來說,要修正儲存設定的問題,我想到兩個方法:「改程式+改路徑」與「直接改設定檔」。


方法一:改程式+改路徑

這個方法可以解決無法儲存設定的問題,適合於常常修改設定的人。
以記事本開啟 ".\ChrisTorngStyle\SettingProcess.xsl",找到:
function GetCurrentPath()
{
    var Path = decodeURI(location.pathname.substr(1));
    return Path.substring(0, Path.lastIndexOf("\\") + 1);
}
將這段代換成:
function GetCurrentPath()
{
    var Path = decodeURI(location.pathname.substr(1));
    var LastSlashPos = Path.lastIndexOf("\\");
    if (LastSlashPos &lt; 0)
    { LastShashPos = Path.lastIndexOf("/"); }
    return Path.substring(0, LastShashPos + 1);
}
即可修復路徑分隔字元問題。
再來要把訊息記錄路徑上所有非英文字換成英文,在繁體中文版中包括「我已接收的檔案」及「記錄」兩者。可換成英文版的 "My Received Files" 及 "History"。然後在 Windows Live Messenger 中亦需設定新的訊息路徑:「工具 – 選項 – 訊息 – 將我的對話內容儲存在此資料夾」。


方法二:直接改設定檔

如果只需要設為繁體中文,不需要常常改設定值的話,建議用這個比較簡單的方法。
設定檔位於訊息記錄資料夾內 ".\ChrisTorngStyle\CurrentSetting.xsl",以記事本開啟,將其中的 "Language_en-us.xsl" 代換成 "Language_zh-cht.xsl" 存檔後即可。
所有可用的語言檔名列在 ".\ChrisTorngStyle\AllSetting.xml" 中之 "AllSettings\Languages\Language\File" 段落,可以任選其一。其他 "CurrentSetting.xsl" 中的設定值,只要看得懂一些英文,相信不會太難看懂,如果有需要的話可自行修改,只要小心別動到 9/30/true/false 這些設定值以外的字元即可。


而這個工具當初有繼續製作下一版本,但功能尚未完成,又因自己忙,就停了下來。因此目前沒有更新版本的計劃。
張貼在 Messenger | 2 則迴響