<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                關于本系列文字的來源,初衷和內容定位可以參考第一篇的開頭部分,鏈接地址如下: http://blog.csdn.net/binarytreeex/article/details/8174445 http://www.cnblogs.com/WideUnion/archive/2012/11/12/2766397.html 本文前一篇地址如下,感興趣的可以訪問下面的連接: http://blog.csdn.net/binarytreeex/article/details/8456766 http://www.cnblogs.com/WideUnion/archive/2013/01/01/2841335.html 本文是問題解決篇的第二部分,繼續討論與解決實際工作中的問題相關的內容。本文假設讀者是具備一定開發經驗的。這個所謂的經驗是指需要滿足這樣一個底線:代碼中的語法錯誤和邏輯錯誤可以自己獨立解決,或者說基本上可以獨立解決。如果是開發新手,尤其是沒有經驗的畢業生,我不推薦來看本文,對這部分程序員來說本文的難度有點大了。 對于有一定開發經驗的程序員來說,工作中遇到的問題基本上是可以自己獨立解決的。所以本文討論的內容旨在幫助這部分程序員更好的解決問題,或者說在進一步提高解決問題的能力上,提供一些參考和有用的方法與思路。和上一篇一樣你不能期望本文可以解決你所遇到的所有問題,或者看了本文之后就可以立馬武功大增,這是不現實的。但是如果記住我個人的這些經驗,然后在工作中去實踐,在日積月累中可以幫助你(至少有一部分程序員是這樣)更快,更好的提高解決問題的能力,這個是可以做到的。因為我就是這么走過來的,所以如果你也想這么走過來,那么我分享的經驗對你一定是有幫助的。 再次強調本文介紹的內容來自個人的實踐,對于解決問題這樣一個宏大的話題和全體開發者這樣一個寬泛的群體來說,局限性和片面性是在所難免的。所以請同行們自行取舍,同時也要根據自己的經驗,實際應用場合做出適當的變化,這樣才能更好的應用本文介紹的內容。如果分享的內容可以為同行們解決實際工作中的問題起到積極作用的話,那么我的目的就達到了。當然如果能夠達到庖丁解牛那樣游刃有余的境界那是最好的。 **一.解決問題的一般步驟** 當程序員在實際工作中遇到問題時該如何去解決呢?以我個人的經驗來說大致是以下幾個步驟。首先需要去認識問題,確認這是一個什么樣的問題或者問題是什么。比如對于調試程序中出現的bug,往往是以能夠重現bug為前提的,否則無從下手。這種可重現性對我們認清并判斷問題是一個前提。在實現某一個功能時,程序員也需要對實現的功能有一個清楚的認識,然后才能選擇合適的方法來解決。所以解決問題的第一步是認清問題。第二步是評估這個問題是否有解決的辦法,或者說需要做一定嘗試工作以確定這個問題是可以解決的。這一步也很重要,它的作用在于保證程序員在解決問題的一開始就朝一個正確地方向前進。這一步的另外一個作用在于評估解決一個問題是否值得去做。有時候解決一個問題,不總是以解決作為結果的,有時候放棄也是一個合理的選擇。第三步是選擇合適的方法解決問題。不同的人對于相同的問題可能會給出不同解,這個由解決問題的程序員自己決定。能力,環境等等因素都會導致不同的解決問題的方法。 **二.程序員通常會遇到什么樣的問題** 在大部分的情況下程序員遇到的問題屬于工程問題,而不是科研問題。與我們在學校中做習題相比實際工作中的問題具有一些不同的特征。 1.是否存在解 在學校中我們做的習題一定是有解的,但是實際工作中的問題則未必,或者說自己面對的問題不一定是可以最終被解決的,而是以失敗告終的。 2.是否有最優解 習題往往存在一個所謂的標準答案,但是實際工作中的問題往往會存在多個或者若干個可行辦法來解決問題,工程師需要從中選擇一個。所謂的最優解有可能是不存在的。 3.選擇解的標準不同 用于判斷最優(或者說最合適)的解的標準不同。做習題往往是單純的比較方法本身的差異。而在實際工作中需要考慮其它相關的或者周邊的因素,比如:難易程度,成本等等。對我而言我把最終選擇的方法的可理解性,可維護性和功能變化后可重構性放在非常重要的位置,作為選擇解的標準。 4.可選解的選擇范圍不同 做習題只能是用知識正面解決問題,當然抄襲是不算的。但是實際工作中的問題可以使用非技術手段來解決。比如對于性能問題的改善,可以通過重新設計算法來解決,也可以通過改善硬件配置來解決;對于用戶提出的bug,可以直接修改解決,也可以通過富有技巧性的溝通來解決,等等。 實際工作中的問題還有一個比較樂觀的特點,那就是問題往往總是可以被解決的。其原因是有由于大環境和小環境決定的。大環境是公司或者團隊在選擇開發任務或者立項時會有一個評估,這和上面提到的解決問題步驟中的第一第二步類似。小環境是,在具體安排開發任務時,往往會根據各人不同的技術特長而安排有針對性的開發任務,或者有選擇性的安排不同難度的任務。就我而言,當初是以VC入行的,結果公司開始就安排VC的開發任務,今后就一直以此為依據來安排開發任務的。從而導致我很少有機會接觸其他的開發任務,比如Java之類的。 在實際工作中,程序員遇到的大部分問題都是如此的。所以從戰略層面講,沒有必要畏懼問題。當程序員遇到問題時,請保持信心,要相信方法總是會比問題多的。這樣的心理狀態對解決問題也是很有幫助的。 **三.解決問題的基礎條件** 就我個人的體會而言,解決問題的基礎條件應該有三個,但是本文需要關注的只有兩個,那就是知識和經驗。實際上對我而言,在解決問題時我最擔心的是需要用到我不知道的知識,這才是最可怕的。這次在給Entity Model Studio開發時序圖時就出現過這樣的擔心,后文會討論這個例子的。現在舉另外一個例子來簡單說明一下知識的作用。 有一個非常著名游戲叫魔法門,我在2000年之前玩過其中的幾個版本。其中一個版本有這么一個任務,要求主角到一個修道院去拿一件物品。該物品在一條走廊的盡頭,如果直接走過去拿是不行的,因為那里有一個牧師在做禱告,擋住了去路。按照攻略上的說法,需要去大堂的閣樓上按照一定的次序拉動五根繩索,然后回來,這時牧師就離開了,從而可以成功拿到物品。這五根繩子的拉動方式是這樣,用鼠標選擇然后點擊,如果點擊的順序匹配上了,游戲就給出一個響聲作為提示。否則你就可以一直沒完沒了的點下去。好,現在簡單說明一下這個問題的核心焦點是什么。 首先說明這不是一個難問題,但是有一個不算問題的小障礙,那就是在處理輸入數據時和我們通常的方式是不同的。我們回想一下自己實現過的功能,一般來說用戶輸入的數據(這個游戲場景里就相當于用鼠標點繩索)會有一個明顯的結束操作。比如:用戶注冊,填完注冊信息之后按提交按鈕;查詢時輸入表示條件的數據,然后按查詢按鈕,等等。但是這個游戲中的場景卻不是這樣的,這個第一人稱的角色扮演游戲允許用戶可以不停的點擊鼠標,而不是要求玩家每點五次鼠標然后再按提交按鈕,程序做判斷,匹配就通過,否則重新再點五次。與我們通常處理的情況相比這是最大的不同,這個問題的核心焦點就在這里。有興趣的同行可以考慮一下自己會如何做。這里限于篇幅,我就不說明解決的過程了,而是直接給出我的作法。當然這個不是什么標準答案,但是從用到的知識和方法來說,我相信魔法門的真正開發者也應該是這么做的。 這里假設正確的點擊次序是54321,也就是第一次點第五根繩子,第二次點擊第四根繩子,以下類推,這個數據可以保存在一個數組里,比如整型數組。當玩家第一次點擊時,獲得點擊的繩子的序號,然后和數組的第一個元素比較。如果相同,那么玩家第二次點擊時就和數組中的第二個元素比較,如果一直正確那么每次點擊后都依次比較后一個元素,一直比較到最后一個元素正確時,就可以讓那個牧師走開了。如果比較的結果不對,那么當玩家再次點擊時就要和數組中的第一個元素比較,重新開始了。比如,玩家連續三次點對,但是第四次點擊錯誤的話,那么第五次點擊時比較的數據是數組中的第一個元素。好了,解決問題的思路有了,下面的問題是代碼怎么寫?一般來說直接用嵌套的if語句或者嵌套的循環就算做出來也是不可取的。打分的話是零分,肯定是零分。我推薦一個做法是用狀態轉換圖,到這里,書上學到的知識開始用上了。 下圖是我畫的狀態轉換圖,當然只是一個示意,將就著看吧,不規范或者不正確的地方可以指出來。 ![](https://box.kancloud.cn/2016-06-02_5750091522100.png) 由于問題比較簡單,表示狀態的變量和表示數組下標的變量可以用同一個來表示,并且初始化為零。玩家每點擊一次就和下標指示的當前位置的元素比較,如果一致,下標就加一。然后判斷下標是否超出數組長度,如果是那就表示通過了,否則將下標設置為零。所以,可能的代碼大概是這樣: ~~~ if (data[state] == inputData) state = state + 1; else state = 0; if (state >= 5) { 觸發通過劇情 } ~~~ 或者簡潔一點可以寫成這樣: ~~~ state = (data[state] == inputData)? state + 1 : 0; if (state >= 5) { 觸發通過劇情 } ~~~ 其中data保存的是正確次序的數組,state就是那個狀態也就是下標,inputData表示玩家點擊的繩子的編號。 這里需要強調一下,如果按照書本上的知識,嚴格規范的按照狀態轉換圖的作法來解決這個問題的話,代碼會比較臃腫。比如,我們在這個例子中還是遵守一個狀態用一個獨立方法來處理的話,那就很沒有必要了。所以提醒工程師們在應用知識時做適當的有針對性的變化。另一個需要強調的是,知識在這個例子中對解決問題是非常有效的。想想開發魔法門的程序員和我們相比當然強的很多很多,但是只要有足夠的知識,我們就可以和他們做的一樣好,至少這個局部的小功能是這樣的。請體會一下知識的重要性。 解決問題的另外一個基礎條件是經驗。這是在長期職業工作中逐步積累起來的一種敏銳的判斷力和識別能力。這種職業的嗅覺或者直覺往往可以在第一時間告訴工程師自己,什么是正確的方法。但是遺憾的是,經驗這個東西除了自己逐步積累,或者用功的去積累,好像沒有什么別的辦法可以替代。 基于上面的討論:解決問題的步驟,問題的類型,解決問題的條件,在實際工作中解決問題時,我歸納出需要注意的事項有三點,它們是:行不行,好不好和對不對。很遺憾的是,在實際工作中這三點往往被忽略,或者沒有主動的使用,即便是用上了,也是下意識的。下面依次討論這三點。 1.行不行 所謂行不行就是,需要考慮面臨的問題是可以解決的么?這個解決有兩個層面的意思,第一個層面是能不能解決這個問題,第二個層面是我能不能解決這個問題。基于上面的介紹,一般來說或者大部分情況下,程序員是不會明顯的體會到這個步驟的存在的。因為接受的開發任務都是被過濾過的,大部分情況下程序員自己都是知道應該怎么去完成工作的。所以這個步驟往往被忽略了。還有一種認識是,行不行這個問題往往是存在于一些比較難的或者大的問題中。比如考察項目的可行性,等等。這當然是事實,但是在實際工作中,在處理一些小問題時(或者相對較小的問題),也會需要程序員帶著這種意識,去解決問題,從而避免自己在第一時間犯錯誤。這時行不行這個步驟的作用可以理解為,這個問題是否值得或者是否應該去解決。下面舉幾個例子說明一下。 第一次例子是在一個對日外包工作做得一個通信程序的項目。預計的工作量是三個程序員兩個月完成,應該說是一個不起眼的小項目。但是日方在工作環境上提出了苛刻的要求,這些要求導致通信程序的調試將無法從服務器得到任何可用信息。另一個問題是中方項目經理對通信程序的開發經驗不足,沒有要求日方提供與服務器端通信的協議文檔。在這樣的前提下,兩次會議先后經過三個項目經理,一個部門經理,一個技術總監的參與下,還是認為項目是可以完成的。最后實際耗費的開發時間是七個月,日方限制的條件全部作廢,并且提供了通信協議文檔,這才算勉強完成。這應該是一個教訓,我覺得其最大原因可能是對日外包公司有一種奴性的文化,對員工提出的正確意見完全不予采納,盲目強調下級對上級的服從,同時還唯日方要求為正確。 第二個例子也是一個外包的活。客戶提出的要求是改進一下現有的程序,通過進一步了解需求后發現兩個情況: 1. ?修改的原因是性能問題 2. ?客戶很快就會實施新的系統 由于改善性能的前提是需要明確性能的瓶頸在哪里,根據對實際的工作環境的了解,發現這個工作做起來會比較困難。其次性能是否有足夠的提高沒有把握。所以這項目最后評估下來是不做了。 第三個例子是當初確定Entity Model Studio是否支持圖形化的UML建模功能。這個判斷相對上面兩個例子就復雜一些了。正方的理由是: 1. ?Entity Model Studio從最初開始的定位就需要支持 2. ?通過市場調研為了確立優勢,也需要支持 3. ?我們有自己的一些理解和特色的功能需要圖形化的設計界面作為支持 而反方的理由基本上只有一個,那就是WideUnion的開發團隊是否可以勝任這個開發任務。相對上面兩個例子,是否支持這個決定事實上不是通過一次,兩次溝通就完成的。而是在此后的一個相當長的時間段中才逐步完成的。最終還是認為需要支持,當然事實上我們也做到了。最終確定支持的理由來自同類產品的比較,Entity Model Studio產品的遠景和定位,以及開發技能的積累和研發難點的突破。 上面的三個例子所涉及的問題都不是很大的問題,但是復雜程度有差異,做出判斷的理由不同,最終的結果也各有不同。所以提醒開發者在類似場合下還是需要認真對待這個步驟的。 2.好不好 所謂好不好是指最終選擇的用來解決問題的方法是否為最優的或者是否為足夠好。作為一個獨立的用于幫助程序員判斷自己選擇的方法是否足夠好的提問,這是一個很有挑戰的步驟,對工程師的能力是一個綜合的考驗,當然也是一個富有樂趣的工作。在實際工作中,工程師在第一判斷下所選擇的方法往往就是應該滿足工作要求的,從這個角度來說就是足夠好的。之所以出現這個情況是由于上面介紹的大小環境決定的。那么在這樣的前提下,還有必要再獨立的用好不好這樣的提問步驟來幫助我們確認所選擇的方法是否足夠好呢? 回答當然是肯定的,有必要。我們從上文提到的問題解決步驟開始解答這個提問。作為解決問題的第一步,需要考察面臨的問題是否可以解決。作為最直接也是最簡單的回答就是給出一個可以解決該問題的方法。這樣我們在解決這個問題的過程中就得到了第一個解。但是這個解往往是不能用于實際工作中的,因為這個解只是為了確認問題可解決,而在解的質量上可能會存在缺陷或者在可行性上存在難度,從而使得這個解在用于實際工作中時,往往不能滿足工程上的要求。于是我們在解決問題的下一個步驟中需要在第一個解的基礎上做優化或者再找出一個更好的解。這樣會得到第二個解,基于第二個解,我們才真正開始著手解決問題。但是在這個解決過程中,我們會發現當前對問題的認識有可能是不全面或者錯誤的,也有可能若干細節我們還沒有考慮到。這個時候需要對第二個解做修改,改進或者重新尋找第三個解。所以從這個步驟來說,我們在解決同一個問題的過程中很有可能會得到兩個,三個解或者若干個解。因此面臨好不好這個問題是經常性的。 這里再用上面提到的魔法門點繩索的例子來說明一下如何查找不同的解。在尋找新的解時,首先需要明確一點,我為什么需要去尋找新的解,或者說尋找新的解的理由是什么。這個步驟對開發者能力是有要求的,需要對具體的問題,環境和要求綜合考慮。就本例來說尋找不同解的原因主要是兩個。第一個是原來的解用到了狀態圖,這部分內容來自編譯原理的自動機。顯然沒有學到這部分知識的程序員要用這個解是有困難的,也就是說這個解對使用的人是有要求的。第二個原因是來自另一個游戲中的場景。在暗黑2中為了解救凱恩首先需要在石頭礦野中按照指定的次序點擊五根石柱,從而激活一個傳送門來解救凱恩。這里點擊五根石柱和點擊五根繩索兩個場景幾乎一模一樣,唯一的區別是魔法門中點擊的次序玩家是不知道的,而暗黑中點擊的次序是知道的。這個差異是讓我嘗試找出不同解的第二個原因。 下面就直接給出新的解法。將繩索看作是按鈕,開始時只允許第一個按鈕可以點擊,其他按鈕為disable,當然這個disable不是不讓點,而是說點了沒有效果。玩家點擊第一個繩索時,就enable下一個繩索,這個enable是指點擊了有效果。然后玩家點擊下一個繩索時,再enable下下一個繩索。直至所有繩索被點擊后觸發劇情。這個解對書本知識的要求可能幾乎沒有。 還可以給出第三個解法。這個解法需要我們再定義一個新的數組(或者鏈表),這個數組用于保存玩家過去五次點擊鼠標的數據。但是這個數組需要用一個與眾不同的數來初始化,這里可以選用-1,而繩子的編號是0,1,2,3,4,注意這點。當玩家每次點擊鼠標時,將玩家點擊的繩子的序號插入到最后,然后數組中的原來數據依次往前移一個位置,這樣原來第一個元素就從數組中移出去了,不在數組中了。實際上這就是一個隊列的基本操作,注意這里使用到了數據結構的知識。然后再將這個數組中的數據和data數組中的數據比較,如果一致就通過,否則繼續等待玩家的輸入。關于尋找不同解的其他例子可以參考我的其它博文,比如: http://blog.csdn.net/binarytreeex/article/details/1595936 http://blog.csdn.net/binarytreeex/article/details/1585550 再簡單說明一下,上面的例子在推廣到一般情況下的應用。尋找不同的解首先需要一個理由,開發者需要根據自己的實際情況去發現這樣的理由。一般來說這個理由往往是某一個存在的缺陷或者瑕疵。在開始尋找不同的解時,需要明確主要矛盾是什么,或者說新的解的目的是什么。如果把,團隊成員的技能水平,成員人數,時間,問題難度,開發工具,可利用的資料,完成的質量數量等等統稱為外部條件,那么當外部條件發生變化時,尋找不同的解可以幫助我們任然可以完成原來的目標和任務。需要強調一下,在我的觀念中,根據不同條件,要求和場合找出不同的解來更好的達到目的,是一個工程師應該具備的能力,而且是一個很重要的能力。 下面說一下如何來判斷一個解是否更好。如果面臨的是一個算法問題,我的建議是時間復雜度放在優先考慮的地位,可以為了性能犧牲空間,只要不是巨大的犧牲空間都是可以接受的。如果是非算法問題,那么考慮的因素就會多一些,情況會有點復雜。我的建議是首先考慮選的方法是否可以滿足功能的要求,其次是考慮穩定性和可靠性。選擇的方法可以在各種條件或者情況下相對更可靠穩定的工作。然后是選擇的方法是否夠簡單,夠易于理解。應該說前面兩個是硬指標,是必須滿足的,而排在第三個標準就是簡單和易于理解,這說明我對這點非常重視。其原因是簡單和易于理解的方法有以下幾個優點: 1. ?可以得到的更好的質量和可靠性。 2. ?便于實現和修改 3. ?更少的調試和測試的工作量 4. ?對編碼人員的要求可以相對低一些 當然還有其他的一些可供參考的標準,同行們可以根據自己面對的實際問題和場景自己來確定。 3.對不對 對不對的意思是指,我們做的對么?這個步驟可能最有可能或者最高頻被忽略掉的。對于一個有經驗的程序員來說,一般不會去選擇一個對錯不確定的方法來解決問題。或者更恰當的表述是,有經驗的程序員都是在認為自己正確的前提下才會去做出選擇。而問題就恰好出在這里,自己認為正確并不表示事實上就是對的。這里需要明確一下,如果一個程序員需要一個獨立的步驟來確認自己的選擇是否正確,那么這個程序員面臨的問題是比較難的或者比較復雜的,否則是沒有必要這么做的。 最理想的確認自己的選擇是否正確,是象數學證明那樣得到證明,當然這并不容易做的。因為我們面臨的問題往往不是一個可以用數學來描述的命題。其次是尋找足夠的充分的理由來說明正確性,這時經驗的作用至關重要。我曾在實際工作中發現這么一個情況。一個開發者按照我的要求去實現一個功能。等我去查看進度的時候發現解決的過程基本順利,編碼也完成,但是問題出在解的正確性的保證上。這個開發者對正確性的保證是用調試和測試來完成的。由于使用到了一個自己設計的算法,所以只靠調試和測試來確保正確是不對的,象這類問題的正確性的保證首先是算法正確性需要得到證明。調試和測試只是例證,不是推演證明,只能作為輔助手段。這個步驟有可能被很多開發者忽略,或者沒有意識到。就這個例子來說,經過溝通后發現所采用的算法的正確性的證明難度太大,所以重新設計了一個易于理解的算法來完成功能。如果不這么做的話,完成的軟件就有可能會表現為不穩定,時不時出錯,導致用戶覺得質量太差。 作為一個解決問題的思維和溝通上的方法,對自己提問對不對也是很有用處的。在一次和其他部門的同事配合解決問題時就是如此。那次的背景情況如下:我的同事是做PHP的,有經驗但是不太強;我是做C的,做過通信,但是我剛去什么情況都不了解。C寫的通信程序拼接字符串,然后通過socket直接向PHP服務器的端口發送字符串,以模擬http通信。現在問題來,測試程序發現數據沒有保存到數據庫中。PHP一側有日志,從日志看數據沒有發送過去,而C這邊也有日志,日志表明數據發送了。于是雙方各持一詞,都懷疑對方的程序問題。那么誰出問題了?這次遇到的問題的關鍵是我剛去那個公司上班,接手時也沒有交接,直接通過讀程序了解相關的事情。所以無論從哪一個角度講,我都不是很清楚,再說我對PHP一竅不通,從而給溝通和解決問題帶了難度。這個時候就需要冷靜的問一下自己,我懷疑對方的程序有問題,那么我有證據么?或者說我的判斷對么?于是和相關的PHP程序員溝通了一下,要求在服務器端的PHP代碼中獨立加入寫文件的代碼,并且這部分代碼是不受如何業務邏輯干擾的。測試后發現日志文件可以生成,從而證明數據發送到了服務器端。然后,還是使用這個方法在PHP代碼的不同位置,加入寫日志文件的代碼,最終找出了問題代碼的位置。 這次就寫到這里,下一篇還是繼續討論如何解決問題這個話題。下一次討論的是在遇到一個自己不知道如何解決的問題時應該采取什么樣的方法和思路最終解決該問題。下一篇的題目是問題解決篇(下)。如何解決問題這個話題原本只打算寫一篇的,現在最終會寫成三篇,應該說這在實際工作中是一個很有份量也很有實際價值的話題。我相信靠博文分享是不夠的,如果有興趣的可以加我的QQ群,群號是:244054966,這個群創業的人多一點;231233168,這個群新手多一點。希望能在群中和同行們互相分享共同提高。加入時請說明:CSDN博文
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看