qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          修復bug的12個關鍵步驟

          boss:那么,你需要多長時間來修復這個bug?
            沒有經驗的程序員:給我一個小時?最多兩個小時?我能馬上搞定它!
            有經驗的程序員:這么說吧,釣到一條魚要多久我就要多久?!
            要多少時間才能修復bug,事先是很難知道的,特別是如果你和這些代碼還素不相識的話,情況就更加撲朔迷離了。James Shore在《The Art of Agile 》一書中,明確指出要想修復問題得先知道問題的所在。而我們之所以無法準確估計時間是因為我們不知道需要多久才能發現癥結的所在,只有清楚這一點,我們才能合理估計修復bug所需要花費的時間。不過,這個時候恐怕黃花菜都涼了。 Steve McConnell曾說過:
            “發現問題—理解問題—這就是程序員90%的工作。”
            很多bug都只需改動某一行代碼即可。但是需要投入大量時間的是,后面還得指出怎么樣才是正確的——就像我們在釣魚的時候,得知道往哪里下誘餌,什么時候魚兒容易上鉤等等。話說bug有四種類型:第一種易尋易修復,第二種難尋易修復,第三種易尋難修復,第四種難尋難修復。最悲劇的就是最后一型的,不但“尋尋覓覓,凄凄涼涼戚戚”,哪怕終于千辛萬苦滴水穿石,也只能在那邊不由自主地抓耳撓腮,無奈嘆一句“路漫漫其修遠兮”。可以這么說,除非是新鮮出爐的代碼,不然讓你找bug就跟瞎子摸象一樣——糊里糊涂,不知道歸屬于哪種bug類型。
            查找和修復bug
            你知道“查找和修復bug”意味著什么嗎?沒錯,就是調試!不斷的調試,無數次的調試!Paul Butcher通過大量工作,總結出以下結構化的步驟:
            1.明確目的。仔細查閱異常報告,確定是否是個bug,找出各種有用的信息發現問題的癥結,予以重現。再次檢查是否與報告發生重復。如果發生重復,那看看曾經的相關人員是如何處理的。
            2.準備工作——找出正確的代碼,用排除法清理工作區域。
            3.匹配測試環境。如果客戶正在操作計算機配置,那么此過程可以跳躍。
            4.明確代碼的用途,確保現有測試工具一切正常。
            5.好了,現在可以出發釣魚去咯——重現和診斷錯誤。如果你不能做到重現,那你就不能證明你已經完成修復工作。
            6.編寫測試案例,或者通過現成的測試案例來捕獲bug。
            7.進入修復模式——請務必確保不會影響到其他任何部分。但是,在開展修復工作之前,可能你還要包攬重構工作,因為只有這樣,你才能無所顧忌地搗鼓代碼。而且事后回歸測試,還能確保你不會加入任何新的bug。
            8.整理代碼。通過一步一步重構,讓你的代碼更易于理解,更安全。
            9.找別人來審查一下,當局者迷旁觀者清。
            10.再次檢查此修復過程。
            11.試著不從主線出發,以檢查這些bug是否會影響其他支線。合并這些變化,處理代碼中的差異,回顧所有的審查和測試等工作。
            12.思考。好好想一想哪里錯了以及為什么錯了?為什么你的修復會起效?這種類型的bug還會出現在哪里?在《 The Pragmatic Programmer》一書中,Andy Hunt 和Dave Thomas也如是指出“如果一個bug需要耗費你很多時間,那么一定要好好弄清楚原因”。此外,還需要思考的是,怎么做才能吸取經驗教訓,將來在類似的問題上不再栽跟頭?以及,我們采用的方法、使用的工具是否還有可以改進的地方?以及這些bug的影響和嚴重程度。
            找到bug,還是修復bug,哪個需要更多時間?
            或許建立一個測試環境、重現問題和測試bug所需的時間,要遠遠多于找到bug和修復bug的時間。不過對于一小部分顯而易見的bug,找到它們很簡單——不過修復起來可能就不盡如人意了。
            在《Making Software》一書中,有一章主要是探討“大部分的軟件漏洞的來源”,Dewayne Perry分析認為,相較于修復,發現bug(包括理解bug和重現bug)所需時間更長。有研究表明,大多數的bug(差不多有3/4)既易于發現又易于修復:5天或許更少(這是基于大規模實時系統通過重量級SDLC、大量審查和測試得出的數據)。但是也有很惡心的bug,即便你可以輕輕松松揪到它,還是還得“嘔心瀝血”才能修復好。
            發現/修復修復時間<=5天修復時間>5天
            能重現問題72.5%18.4%
            難以重現或根本沒法重現5.9%3.2%
            所以如果你打賭說你能很快修復bug,大多數情況下你還真沒說錯。不過當你打賭輸了的時候,那么,嘿嘿,就意味著你有大麻煩了。
            所以,下次,boss再問什么時候能修復bug,別再傻乎乎地回答“馬上就能搞定”了。

          posted @ 2014-11-21 10:50 順其自然EVO 閱讀(201) | 評論 (0)編輯 收藏

          TP框架集成支付寶,中轉頁變成gbk編碼

           tp框架中集成支付寶的功能,將支付寶的demo例子存在到下圖位置\Extend\Vendor\Alipay
            生成支付訂單
          /**
          *支付訂單
          */
          publicfunctionpay(){
          header("Content-Type:text/html;charset=utf-8");
          $id=I('post.oid','','htmlspecialchars');
          $DAO=M('order');
          $order=$DAO->where("id=".$id)->find();
          $error="";
          if(!isset($order)){
          $error="訂單不存在";
          }elseif($order['PaymentStatus']==1){
          $error="此訂單已經完成,無需再次支付!";
          }elseif($order['PaymentStatus']==2){
          $error="此訂單已經取消,無法支付,請重新下單!";
          }
          if($error!=""){
          $this->_FAIL("系統錯誤",$error,$this->getErrorLinks());
          return;
          }
          $payType=I('post.payType','','htmlspecialchars');
          #支付寶
          if($payType=='alipay'){
          $this->payWithAlipay($order);
          }
          }
           支付訂單提交
          /**
          *以支付寶形式支付
          *@paramunknown_type$order
          */
          privatefunctionpayWithAlipay($order){
          //引入支付寶相關的文件
          require_once(VENDOR_PATH."Alipay/alipay.config.php");
          require_once(VENDOR_PATH."Alipay/lib/alipay_submit.class.php");
          //支付類型
          $payment_type="1";
          //必填,不能修改
          //服務器異步通知頁面路徑
          $notify_url=C("HOST")."index.php/Alipay/notifyOnAlipay";
          //頁面跳轉同步通知頁面路徑
          $return_url=C("HOST")."index.php/Pay/ok";
          //賣家支付寶帳戶
          $seller_email=$alipay_config['seller_email'];
          //必填
          //商戶訂單號,從訂單對象中獲取
          $out_trade_no=$order['OrderNum'];
          //商戶網站訂單系統中唯一訂單號,必填
          //訂單名稱
          $subject="物流服務";
          //必填
          //付款金額
          #正常金額
          $price=$order['Price'];
          #測試金額
          #$price=0.1;
          //必填
          $body=$subject;
          //商品展示地址
          $show_url=C('HOST');
          //構造要請求的參數數組,無需改動
          $parameter=array(
          "service"=>"create_direct_pay_by_user",
          "partner"=>trim($alipay_config['partner']),
          "payment_type"=>$payment_type,
          "notify_url"=>$notify_url,
          "return_url"=>$return_url,
          "seller_email"=>$seller_email,
          "out_trade_no"=>$out_trade_no,
          "subject"=>$subject,
          "total_fee"=>$price,
          "body"=>$body,
          "show_url"=>$show_url,
          "_input_charset"=>trim(strtolower($alipay_config['input_charset']))
          );
          Log::write('支付寶訂單參數:'.var_export($parameter,true),Log::DEBUG);
          //建立請求
          $alipaySubmit=newAlipaySubmit($alipay_config);
          $html_text=$alipaySubmit->buildRequestForm($parameter,"get","去支付");
          echo$html_text;
          }
          支付寶回調接口
          <?php
          /**
          *支付寶回調接口
          */
          classAlipayActionextendsAction{
          /**
          *支付寶異步通知
          */
          publicfunctionnotifyOnAlipay(){
          Log::write("notify:".print_r($_REQUEST,true),Log::DEBUG);
          require_once(VENDOR_PATH."Alipay/alipay.config.php");
          require_once(VENDOR_PATH."Alipay/lib/alipay_notify.class.php");
          $orderLogDao=M('orderlog');
          //計算得出通知驗證結果
          $alipayNotify=newAlipayNotify($alipay_config);
          $verify_result=$alipayNotify->verifyNotify();
          Log::write('verify_result:'.var_export($verify_result,true),Log::DEBUG);
          if($verify_result){//驗證成功
          //商戶訂單號
          $out_trade_no=$_POST['out_trade_no'];
          //支付寶交易號
          $trade_no=$_POST['trade_no'];
          //根據訂單號獲取訂單
          $DAO=M('order');
          $order=$DAO->where("OrderNum='".$out_trade_no."'")->find();
          //如果訂單不存在,設置為0
          if(!isset($order)){
          $orderId=0;
          }
          else{
          $orderId=$order['id'];
          }
          //交易狀態
          $trade_status=$_POST['trade_status'];
          $log="notifyfromAlipay,trade_status=".$trade_status."alipaysign=".$_POST['sign'].'price='.$_POST['total_fee'];
          $orderLog['o_id']=$orderId;
          if($_POST['trade_status']=='TRADE_FINISHED'||$_POST['trade_status']=='TRADE_SUCCESS'){
          #修改訂單狀態
          if((float)$order['Price']!=(float)$_POST['total_fee']){
          $data['PaymentStatus']='2';
          }else{
          $data['PaymentStatus']='1';
          }
          $DAO->where('id='.$orderId)->save($data);
          }
          $orderLog['pay_id']=$trade_no;
          $orderLog['pay_log']=$log;
          $orderLog['pay_type']='alipay';
          $orderLog['pay_result']='success';
          $orderLogDao->add($orderLog);
          /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          echo"success";//返回成功標記給支付寶
          }
          else{
          //驗證不通過時,也記錄下來
          $orderLog['pay_log']="notifyfromAlipay,但是驗證不通過,sign=".$_POST['sign'];
          $orderLog['o_id']=-1;
          $orderLog['pay_type']='alipay';
          $orderLog['pay_result']='fail';
          $orderLogDao->add($orderLog);
          //驗證失敗
          echo"fail";
          }
          }
          }
          ?>
            今天在tp框架中集成支付寶功能,跳轉支付寶的時候出現亂碼錯誤。
            需要設定header("Content-Type:text/html;charset=utf-8");
            如果還有亂碼查看日志信息是否出現
            NOTIC:[2]Cannotmodifyheaderinformation-headersalreadysentby(outputstartedat
            上面錯誤,刪除錯誤文件開始的空格
            <emid="__mceDel"></em>

          posted @ 2014-11-21 10:50 順其自然EVO 閱讀(521) | 評論 (0)編輯 收藏

          測試計劃與測試方案的區別

            計劃:屬于組織管理層面的文檔,從組織管理的角度對測試活動進行規劃; 方案:屬于技術層面的文檔,從技術的角度對測試活動進行規劃。
            測試計劃:
            對測試全過程的組織、資源、原則等進行規定和約束,并制定測試全過程各個階段的任務分配以及時間進度安排,并提出對各項任務的評估,風險分析和管理需求。
            測試方案:
            描述需要測試的特性,測試的方法,測試環境的規劃,測試工具的設計和選擇,測試用例的設計方法,測試代碼的設計方案。
            測試方案需要在測試計劃的指導下進行,測試計劃提出“做什么”,而測試方案明確“如何做”
            軟件測試用例包括軟件測試用例設計和寫作。
            軟件測試用例設計是從設計層面考慮,比如從功能性、可用性、安全性等方面考慮設計測試用例。
            軟件測試用例寫作是指軟件測試用例的寫作規范,包括寫作格式、標識的命名規范等。 軟件測試用例設計得出軟件測試用例的內容,然后,按照軟件測試寫作方法,落實到文檔中,兩者是形式和內容的關系。 測試用例格式的八個基本項是:測試用例編號、測試項目、測試標題、重要級別、預置條件、輸入、操作步驟、預期輸出。
            一、什么是測試計劃?
            所謂測試計劃是指描述了要進行的測試活動的范圍、方法、資源和進度的文檔。它主要包括測試項、被測特性、測試任務、誰執行任務和風險控制等。
            二、什么是測試方案?
            所謂測試方案是指描述需要測試的特性、測試的方法、測試環境的規劃、測試工具的設計和選擇、測試用例的設計方法、測試代碼的設計方案。
            三、測試計劃與測試方案區別

          posted @ 2014-11-21 10:43 順其自然EVO 閱讀(240) | 評論 (0)編輯 收藏

          IOS開發之視圖和視圖控制器

           視圖(View), 視圖控制器(ViewController)是IOS開發UI部分比較重要的東西。在學習視圖這一塊的東西的時候,感覺和Java Swing中的Panel差不多。在UIKit框架中都有一個UIWindow來容納我們的View。應用程序中幾乎全部的可視控件都是UIView以及UIView的子類的實例,并且UIWindow也是UIView的子類。UIWindow可以不借助于父類視圖顯示在屏幕上,其余的視圖都需要添加到父視圖中才能顯示。窗口是用來顯示視圖的,下面我們將會結合著實例來具體的學習一下IOS中的View和ViewController
            1.首先我們需要建一個EmptyProject來測試我們的View和ViewController. 我們空工程的文件結構如下,我們只需在AppDelegate.m中添加我們的視圖,還是那句話為了更好的理解我們的視圖,所有視圖的創建和配置我們都用代碼編寫。
            2.在學習UIView之前我們先在我們的EmptyProject中添加一個視圖,看一下效果,上面的代碼是為我們的EmptyProject添加一個UIWindow,是系統為我們創建的,我們接下來要放置的UIIView都是放在Window中,一般每個應用都只有一個Window,當然有的游戲會有多個應用窗口。下面的一段代碼是往我們Window上添加一個主視圖,通過CGRectMake來給我們新添的View定位。 CGRectMake(x, y, width, height);  配置背景顏色為greenColor,最后添加到我們的window上。
            3.界面都是視圖對象,即在UIView類的實例中進行布局,UIView表示屏幕上的一塊矩形區域,負責渲染矩形區域中的內容,并且響應該區域內發生的觸摸事件。我們還可以把視圖看做是一個視圖容器,視圖上面還可以添加一個子視圖。往父視圖中添加的SubView會被放在一個數組中。往我們SuperView中添加的SubView的坐標和index都是相對于我們的父視圖來配置的。我們為上面的視圖在添加一個subView,代碼如下:
            運行效果如下:
            下面是iOS提供的一些管理子視圖的方法,常用方法如下:
            (1) initWithFrame : 通過frame初始化視圖,參數為CGRectMake(x, y, width, height);
            (2) insertSubView: atIndex: 往指定層上插入視圖,哪個View調用該方法,index就是相對于誰。
            (3) insertSubView: aboveSubView: 在某個視圖上插入子視圖。
            (4) insertSubView: belowSubView: 在某個子視圖的后面添加一個新的視圖
            (5) bringSubViewToFront: 把子視圖放到最前
            (6) sendSubViewToBack: 把子視圖放到最后
            (7) exchangeSubviewAtIndex: withSubviewAtIndex: 交換兩個視圖的前后順序
            (8) removeFromSuperview: 從父視圖中移除view
            (9) -(void) addSubview: (UIView *) view 添加一個視圖
            視圖的層次用index來區分,這個值從0開始以步長1依次增加,index為0的時候代表視圖層次的最底層,下面是蘋果官方文檔對Views的介紹的截圖:
            視圖層大致分為下面的幾類
            1.容器視圖
            容器視圖用于增強其他視圖的功能,或者為視圖內容提供額外的視覺分隔,比如UIScorllView類用于顯示因內容太大而無法顯示在一個屏幕上的視圖,也就是自動添加滾動條,入下面第一個圖。UITableView類是UIScrollView類的子類,用于管理數據列表,如圖二,還有其他的容器視圖在這就不一一列舉啦。
            2.控件
            控件用于創建大多數應用程序的用戶界面。控件是一種特殊類型的視圖,繼承子UIControl超類,通常要綁定回調方法(比如Target-Action回調和委托回調),用于用戶交互。控件包括按鍵,文本框,滑塊,和切換開關。部分控件如下所示:
            3.顯示視圖
            控件和很多其他類型的視圖都提供了交互行為,而另外一些視圖則只是用于簡單的顯示信息。具有這種行為的UIKit類包括 UIImageView, UILabel, UIProgressView, UIActivityIndicatorView;下面是UIProgressView顯示視圖
            4.文本和Web視圖
            文本和web視圖為應用程序提供更為高級的顯示多行文本的方法。UITextView類支持在滾動區域內顯示和編輯多行文本;而UIWebView類則提供顯示HTML內容的方法
            5.警告視圖和動作表單
            警告視圖和動作表單用于即刻取得用戶的注意。 UIAlertView類在屏幕上彈出一個藍色的警告框,而UIActionSheet類則從屏幕的底部劃出動作框

           6.導航視圖
            頁簽條和導航條和視圖控制器結合使用,為用戶提供從一個屏幕到另一個屏幕的導航工具。在使用是,你通常不必直接UITableBar和UINavigationBar的項,而是通過恰當的控制器接口或Interface Builder來對其進行配置,Table Bar 和 Navigation Bar如下:
            上面視圖部分先就說這么多吧,那么我們的視圖控制器應如何使用呢? 在本文剛開始的時候我們加入的view的代碼都是在AppDelegate.m的文件里加的,其實沒沒那么做的,如果我們一直在上面的文件中實例化我們的各種控件,我們的應用程序代碼會非常難維護。那么我們如何給一個EmptyProject添加一個視圖控制器呢?上面貼啦這么的多的圖片啦,接下來讓我們上點代碼吧!
            1.我們在一個空工程中新建一個視圖控制器的類MainViewController, 讓MainViewController繼承于UIViewController, MainViewController.h文件的內容如下:
            #import <UIKit/UIKit.h>
            @interface MainViewController : UIViewController
            @end
            2.我們在MainViewController.m中進行我們的視圖聲明和實例化,代碼如下:
          #import "MainViewController.h"
          //用延展隱藏我們的組件
          @interface MainViewController ()
          @property (nonatomic, strong) UIView *subView;
          @end
          //-------實現部分-----------
          @implementation MainViewController
          //主視圖加載后要做的事情
          -(void)viewDidLoad
          {
          //實例化view并添加到mainView
          self.subView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 150)];
          self.subView.backgroundColor = [UIColor brownColor];
          [self.view addSubview:self.subView];
          }
          @end
            3.我們需要把我們新建的視圖控制器和我們的窗口關聯,在AppDelegate.m中實例化MainViewController并添加到window中,代碼如下:
            - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
            {
            self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
            // Override point for customization after application launch.
            self.window.backgroundColor = [UIColor whiteColor];
            [self.window makeKeyAndVisible];
            //實例化MainViewController,并添加到window
            MainViewController * mianViewController = [[MainViewController alloc] init];
            [self.window addSubview:mianViewController.view];
            return YES;
            }
            先暫且這么理解著視圖和視圖控制器,隨著以后的深入的學習會隨時更新和修改博客的。

          posted @ 2014-11-21 09:38 順其自然EVO 閱讀(197) | 評論 (0)編輯 收藏

          IOS開發之視圖和視圖控制器

           視圖(View), 視圖控制器(ViewController)是IOS開發UI部分比較重要的東西。在學習視圖這一塊的東西的時候,感覺和Java Swing中的Panel差不多。在UIKit框架中都有一個UIWindow來容納我們的View。應用程序中幾乎全部的可視控件都是UIView以及UIView的子類的實例,并且UIWindow也是UIView的子類。UIWindow可以不借助于父類視圖顯示在屏幕上,其余的視圖都需要添加到父視圖中才能顯示。窗口是用來顯示視圖的,下面我們將會結合著實例來具體的學習一下IOS中的View和ViewController
            1.首先我們需要建一個EmptyProject來測試我們的View和ViewController. 我們空工程的文件結構如下,我們只需在AppDelegate.m中添加我們的視圖,還是那句話為了更好的理解我們的視圖,所有視圖的創建和配置我們都用代碼編寫。
            2.在學習UIView之前我們先在我們的EmptyProject中添加一個視圖,看一下效果,上面的代碼是為我們的EmptyProject添加一個UIWindow,是系統為我們創建的,我們接下來要放置的UIIView都是放在Window中,一般每個應用都只有一個Window,當然有的游戲會有多個應用窗口。下面的一段代碼是往我們Window上添加一個主視圖,通過CGRectMake來給我們新添的View定位。 CGRectMake(x, y, width, height);  配置背景顏色為greenColor,最后添加到我們的window上。
            3.界面都是視圖對象,即在UIView類的實例中進行布局,UIView表示屏幕上的一塊矩形區域,負責渲染矩形區域中的內容,并且響應該區域內發生的觸摸事件。我們還可以把視圖看做是一個視圖容器,視圖上面還可以添加一個子視圖。往父視圖中添加的SubView會被放在一個數組中。往我們SuperView中添加的SubView的坐標和index都是相對于我們的父視圖來配置的。我們為上面的視圖在添加一個subView,代碼如下:
            運行效果如下:
            下面是iOS提供的一些管理子視圖的方法,常用方法如下:
            (1) initWithFrame : 通過frame初始化視圖,參數為CGRectMake(x, y, width, height);
            (2) insertSubView: atIndex: 往指定層上插入視圖,哪個View調用該方法,index就是相對于誰。
            (3) insertSubView: aboveSubView: 在某個視圖上插入子視圖。
            (4) insertSubView: belowSubView: 在某個子視圖的后面添加一個新的視圖
            (5) bringSubViewToFront: 把子視圖放到最前
            (6) sendSubViewToBack: 把子視圖放到最后
            (7) exchangeSubviewAtIndex: withSubviewAtIndex: 交換兩個視圖的前后順序
            (8) removeFromSuperview: 從父視圖中移除view
            (9) -(void) addSubview: (UIView *) view 添加一個視圖
            視圖的層次用index來區分,這個值從0開始以步長1依次增加,index為0的時候代表視圖層次的最底層,下面是蘋果官方文檔對Views的介紹的截圖:
            視圖層大致分為下面的幾類
            1.容器視圖
            容器視圖用于增強其他視圖的功能,或者為視圖內容提供額外的視覺分隔,比如UIScorllView類用于顯示因內容太大而無法顯示在一個屏幕上的視圖,也就是自動添加滾動條,入下面第一個圖。UITableView類是UIScrollView類的子類,用于管理數據列表,如圖二,還有其他的容器視圖在這就不一一列舉啦。
            2.控件
            控件用于創建大多數應用程序的用戶界面。控件是一種特殊類型的視圖,繼承子UIControl超類,通常要綁定回調方法(比如Target-Action回調和委托回調),用于用戶交互。控件包括按鍵,文本框,滑塊,和切換開關。部分控件如下所示:
            3.顯示視圖
            控件和很多其他類型的視圖都提供了交互行為,而另外一些視圖則只是用于簡單的顯示信息。具有這種行為的UIKit類包括 UIImageView, UILabel, UIProgressView, UIActivityIndicatorView;下面是UIProgressView顯示視圖
            4.文本和Web視圖
            文本和web視圖為應用程序提供更為高級的顯示多行文本的方法。UITextView類支持在滾動區域內顯示和編輯多行文本;而UIWebView類則提供顯示HTML內容的方法
            5.警告視圖和動作表單
            警告視圖和動作表單用于即刻取得用戶的注意。 UIAlertView類在屏幕上彈出一個藍色的警告框,而UIActionSheet類則從屏幕的底部劃出動作框

           6.導航視圖
            頁簽條和導航條和視圖控制器結合使用,為用戶提供從一個屏幕到另一個屏幕的導航工具。在使用是,你通常不必直接UITableBar和UINavigationBar的項,而是通過恰當的控制器接口或Interface Builder來對其進行配置,Table Bar 和 Navigation Bar如下:
            上面視圖部分先就說這么多吧,那么我們的視圖控制器應如何使用呢? 在本文剛開始的時候我們加入的view的代碼都是在AppDelegate.m的文件里加的,其實沒沒那么做的,如果我們一直在上面的文件中實例化我們的各種控件,我們的應用程序代碼會非常難維護。那么我們如何給一個EmptyProject添加一個視圖控制器呢?上面貼啦這么的多的圖片啦,接下來讓我們上點代碼吧!
            1.我們在一個空工程中新建一個視圖控制器的類MainViewController, 讓MainViewController繼承于UIViewController, MainViewController.h文件的內容如下:
            #import <UIKit/UIKit.h>
            @interface MainViewController : UIViewController
            @end
            2.我們在MainViewController.m中進行我們的視圖聲明和實例化,代碼如下:
          #import "MainViewController.h"
          //用延展隱藏我們的組件
          @interface MainViewController ()
          @property (nonatomic, strong) UIView *subView;
          @end
          //-------實現部分-----------
          @implementation MainViewController
          //主視圖加載后要做的事情
          -(void)viewDidLoad
          {
          //實例化view并添加到mainView
          self.subView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 150)];
          self.subView.backgroundColor = [UIColor brownColor];
          [self.view addSubview:self.subView];
          }
          @end
            3.我們需要把我們新建的視圖控制器和我們的窗口關聯,在AppDelegate.m中實例化MainViewController并添加到window中,代碼如下:
            - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
            {
            self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
            // Override point for customization after application launch.
            self.window.backgroundColor = [UIColor whiteColor];
            [self.window makeKeyAndVisible];
            //實例化MainViewController,并添加到window
            MainViewController * mianViewController = [[MainViewController alloc] init];
            [self.window addSubview:mianViewController.view];
            return YES;
            }
            先暫且這么理解著視圖和視圖控制器,隨著以后的深入的學習會隨時更新和修改博客的。

          posted @ 2014-11-21 09:38 順其自然EVO 閱讀(147) | 評論 (0)編輯 收藏

          MySQL數據庫優化技術之數據庫表的設計

          三范式介紹
            表的范式:只有符合的第一范式,才能滿足第二范式,進一步才能滿足第三范式。
            1、第一范式:
            表的列具有原子性,不可再分解。只要是關系型數據庫都自動滿足第一范式。
            數據庫的分類:
            關系型數據庫:MySQL/ORACLE/Sql Server/DB2等
            非關系型數據庫:特點是面向對象或者集合
            nosql數據庫:MongoDB(特點是面向文檔)
            2、第二范式:
            表中的記錄是唯一的,就滿足第二范式。通常我們設計一個主鍵來實現。
            主鍵一般不含業務邏輯,一般是自增的;
            3、第三范式:
            表中不要有冗余數據,即如果表中的信息能夠被推導出來就不應該單獨的設計一個字段來存放;對字段冗余性的約束,要求字段沒有冗余。
            如下表所示,符合三范式要求:
            student表
            class表
            如下表所示,不符合三范式要求:
            student表
            class表
            反三范式案例:
            一個相冊下有多個圖片,每個圖片有各自的瀏覽次數,相冊有總的瀏覽次數。
            相冊瀏覽表
            圖片表:
            如果相冊瀏覽表沒有適當的冗余,效率有影響。
            冗余比較可以得出一個結論:1對N時,冗余應當發生在1的一端。

          posted @ 2014-11-21 09:26 順其自然EVO 閱讀(636) | 評論 (0)編輯 收藏

          Java跳出多重嵌套循環

            在java里面,我們知道有goto這個關鍵字,但是實際卻沒有啥作用,這就讓我們不像在c/c++里面能夠隨便讓程序跳到那去執行,而break只能跳出當前的一個循環語句,如果要跳出多個循環體那么該怎么辦呢。
            我們可以這樣解決:
            我們可以在循環體開頭設置一個標志位,也就是設置一個標記,然后使用帶此標號的break語句跳出多重循環。
          public class BreaklFor {
          public static void main(String args[]){
          OK:                    //設置一個標記 使用帶此標記的break語句跳出多重循環體
          for(int i=1;i<100;i++){   //讓i循環99次
          for(int j=1;j<=i;j++){
          if(i==10){
          break OK ;
          }
          System.out.print(i + "*" + j + "=" + i*j) ;
          System.out.print(" ") ;
          }
          System.out.println() ;
          }
          }
          }
            運行結果當然是打印九九乘法表。當i=10時跳出了循環。
            當然還有另外一種方法,這也是設置一個boolean值的標記位,在for循環中使用判斷是否繼續循環來達到目的。
          public class BreaklFor {
          public static void main(String args[]) {
          int array[][] = { { 5, 7, 6, 4, 9 }, { 1, 2, 8, 3, 2 } };
          boolean flag = false;
          for (int i = 0; i < array.length && !flag; i++) {  //當flag為true時跳出循環
          for (int j = 0; j < array[i].length; j++) {
          if (array[i][j] == 8) {
          flag = true;
          break;
          }
          }
          }
          System.out.println(flag);
          }
          }
            通過設置標志位,實現里成的代碼控制外層的的循環條件。

          posted @ 2014-11-21 09:25 順其自然EVO 閱讀(200) | 評論 (0)編輯 收藏

          一步步學敏捷開發—如何做需求分析

           剛開始寫就忙著搬家,這次沒有找搬家公司,螞蟻搬家真是太麻煩,以后搬家還是要找搬家公司。
            需求分析
            在敏捷開發中需求分析需要全體成員參與,體現了敏捷開發的“ 個體和互動 高于 流程和工具”的價值觀。讓全體成員參與有幾點好處:有助于及時發現團隊成員對同一個需求理解不一致的問題;有助于規避人力風險,當一個需求分析者突然請假其他人可以馬上頂替他;也有助于全體成員能力的提升。但是,開發人員和測試人員們在能力和經驗方便,不足以勝任需求分析工作。這意味著還需要一個商務分析師這個角色,他帶領全體成員去進行有效的需求分析。商務分析師最重要的職責就是與客戶交談,了解和分析需求。搞清楚客戶到底需要什么,到底為什么需要這些東西。商業價值是商務分析師關注的最終目標。
            軟件開發所要解決的問題就是將用戶需求轉換為可運行的代碼。需求反映的是"什么"(What)的問題,從問題解決的角度來看,要解決一個問題首先要弄清楚的是"問題"究竟是什么。而開發人員在需求分析時往往易犯的一個問題是急于考慮"怎么"(How)的問題,這是設計所要解決的問題。
            頭腦風暴 + 原型設計
            我們在做項目需求分析時,通過與真實用戶的交流,和用戶一起進行頭腦風暴,并將討論結果使用頭腦風暴軟件(比如:MindMapper)整理出類似如下的頭腦風暴圖。
            頭腦風暴圖
            與用戶討論結束后,回去再通過GUI Design將頭腦風暴里的內容快速做出一個原型,下次再找用戶確認,經過幾次反復確認修改基本可以確定一個版本。但這并不是最終的,用戶的想法隨時還會變,即使到開發階段用戶的需求一樣會有變化,請參考敏捷原則第2條。
            原型圖
            還可以使用紙質原型,這也是一種精益設計思考。

          posted @ 2014-11-21 09:24 順其自然EVO 閱讀(229) | 評論 (0)編輯 收藏

          測試團隊管理-第二篇:部門整合(1)

           來到公司后,接手的第一項任務,就是把原有的兩個小測試部門整合為一個公司級的大測試部門。公司有兩大業務方向,每個業務方向都有一個開發部門和一個測試 部門,每個測試部門的主管都匯報給相應開發部門的主管。公司之所以考慮將測試部門整合起來,原因大致有以下幾點。第一,公司治理的需要。測試部門直接受開 發部門管理,將無法有效地行使監督檢查和質量保證的職責,裁判員兼任球員,很多問題被捂住,公司層面在一定程度上無法獲取到項目的真實質量情況。第二,原 有的兩個測試部門主管能力不受認可,一位主管是在老主管離職的情況下臨時代理,另外一位主管被公司徹底否定。第三,兩個小測試部門規模都不大,分別是20 人左右,各自都有一套自己的測試管理和技術體系,如測試用例、計劃、報告模版,Bug庫,測試流程,版本控制工具,全都不一樣。整合后有利于更充分利用有 限資源,消除不必要冗余。第四,公司兩個業務方向產品間的相互依賴調用和融合越來越多,一個大測試部門更便于產品多個組件間的集成測試和測試人員調配。第五,原有的兩個測試主管,一個正在休產假,一個在孕期即將休產假,公司也迫切需要有人能夠盡快把管理工作接管過來。
            深入分析已有兩個業務方向和兩個測試部門的各方面情況足足一個月后,編寫出一份《公司級測試部門整合評估報告》。為了寫出這份報告,我在兩個測試部門各選 了一個代表性測試項目做深入調研,以專題會議、旁聽會議、座談、閱讀文檔、瀏覽項目管理系統等各種形式,收集到了大量數據和信息,然后在此基礎上做了大量 匯總分析。評估報告涵蓋了已有兩個部門的現狀分析,部門整合的有利因素、不利因素、風險和應對方案,整合方案及整合后新部門的發展路線圖。評估報告受到了公司老板較高評價和認可,整合方案也受到大力支持,而我個人卻頗感心驚肉跳、如履薄冰,和剛來時的豪情萬丈相比,謹小慎微多了。為什么?因為調研后我才發現,這哪里是兩個獨立的業務方向啊,分明是兩個事業部,或者是兩家獨立的公司。除了財務、人力、行政等職能是公用公司的,其他的產品策劃、需求分析、開發、測試、技術支持都各有一套體系,各不相同。一個業務方向以軟件產品研發為主,另一個以軟件工程項目為主,即使是類似的工作也沒有統一術語,各有一套表 述方法,相互溝通起來到處都是障礙。換句化說,這兩個業務方向,產品、開發、測試、服務都完全獨立,并且差異很大,現在要人為地把測試部門捏到一起,作為 產品或者項目完整生命周期里的其他環節還是分開的,難度可想而知。我強烈地預感到,整合過程絕對不會輕松,整合后想發展好就更加困難重重。

          posted @ 2014-11-21 09:24 順其自然EVO 閱讀(269) | 評論 (0)編輯 收藏

          項目bug的修正

          這幾個月來,大部分業余時間,都花在閱讀軟件工程和編譯原理方面的書籍上了。軟件工程方面的書,包括軟件需求、風險管理、敏捷建模,系統設計,軟件項目管理,還有一些類似于的沉思錄書籍等。
            在這些書中,都只是講了如何讓項目健康發展,最后成功的提交一個產品。盡管它們都是從不同的角度,用不同的方法去完成同樣的事。但它們幾乎都支持這樣的觀點:計劃+修正計劃(不但設計是迭代的,計劃也是迭代的)。用其中一個作者的話說,傷害你的,不是那些你沒有考慮完整的,而是你根本沒去考慮的事情。
            然而,幾乎沒有一本書里,講到關于消防隊的事,唉,真是奇怪,老外聲稱有超過50%的項目是失敗的,那么在他們的項目中,失火也是常事,為什么就不談談救火的招數呢?難道他們也相信,不叫出魔鬼的名字,魔鬼就不會找上門來嗎?
            唯一的解釋就是,救火太難了,可能老外的救火能力遠不如我們,他們干脆就不談了。我在上一個項目中犧牲慘重,巨大的壓力之下,精神上和身體上都受到極大的傷害,當然,我不是那個項目唯一的犧牲品,很多同事,他們很優秀,也一樣的無助。之后,我一直在想,既然有50%的項目會失火,那么救火能力和計劃能力至少是等同重要了。我苦苦的思索,回憶上次的經歷,查找相關資料,然而收獲甚微。
            救火的銀彈也許永遠不會出現,我把自己一些經驗寫出來,或許對大家有點幫助,如果能達到拋磚引玉的效果那是更好了:
            1.在FIX BUG過程中,持續進行重構。在設計時沒有做好,重做是不太可能的了,但絕望也是沒有意義的,我們只能想法去改進它。利用前人一些經驗,持續進行重構,每FIX一個BUG,我們讓代碼更好一點,而不是更壞一點,FIX了一個BUG,代碼中就少了一個BUG,而不是引更多的BUG。在實際上,重構最大的困難是沒有完整的自動測試程序和測試用例,這使得我們根本不敢去改動代碼,或者為了讓改動最小,采取一些折中的方法,這都使得代碼不斷的變臭。在這種情況下,建議是建立自動測試,然后不斷完善測試用例,我覺得建立自動測試任何時候都不晚。如果建立自動測試確實比較困難,那就列出所有的測試用例,然后手工測試。這時候,工程師的工作就是:重構à測試àFIX BUGà測試。有人說,我沒有時間去重構,沒有時間去測試。呵,這會使我想到,一個人圍繞著一個小圓圈拼命的奔跑,累得半死的時候,發現在原地,他還在說,我沒有時間去看清方向。
            2.關注常用功能。在項目的最后階段,千萬不要被QA牽著走,他們發現一個BUG,我們就FIX它。FIX一個BUG當然好,但是FIX BUG不是免費的,要不但要成本,還有潛在的風險。編譯的優化原理是基于:20%的代碼花了80%的時間。如果這個原理成立,可以推出:80%的用戶實際上只使用20%的功能。QA并不是最終用戶,QA和最終用戶的不同在于:QA盡力去發現不常見的問題,而最終用戶經常使用最常用的功能。這時候我們可以把自己想成最終用戶,列出最常用的測試用例,如果不在這些測試用例中的情況,即使BUG的現象很嚴重,我們也要考慮一下再決定是否修改它。
            3.確定哪些BUG不改同樣重要。這一點與2有一定的重復,為了強調有必要單獨提出來。在軟件需求分析時,分析師們都認為,要確定什么不在系統內和什么在系統內一樣重要。程序員對于BUG態度,有時往往走兩個極端:一種是老子就不改。一種QA怎么說我就怎么改。前者往往被看著工作態度不端正。而后者呢,卻被視為好孩子。其實,在項目的最后階段,后者未必正確,正如前面所說,FIX BUG不是免費的。這時候建立一個仲裁委員會有必要的,確定哪些BUG不改是他們的職責之一。
            4.BUG分類,明確責任。以前接手別人一個模塊,處于Pending狀態的BUG已經有110多個了。要把每一個BUG都看一遍就要花幾個小時,不看吧,每次改一個BUG時,總有只見樹木不見森林的感覺。最初,我很努力的去修改BUG,進展還是甚微。后來我花了幾天時間,仔細分析了所有BUG,把它們歸納幾類:其它模塊引起的BUG; 和其它模塊的接口引起的BUG; 超出需求之外的BUG; 完全是本模塊內部的BUG。然后把其它模塊引起的BUG提交給相關人員,和相關人員確認因接口不統一引起的BUG,把超出需求之外的BUG提交給需求控制委員會,最后剩下本模塊的BUG又根據引起BUG的原因分為幾類。這樣,這些BUG很快被FIX了。
            5.工程師應該積極尋求幫助。有什么自己解決不了問題,應該向知道的人請教,或者向上司尋求幫助,不要出于面子或者其它原因,而花費大量的時間。在項目的最后階段,每一分鐘都很寶貴,不要重新發明輪子,對于有共性的難題也應該由專人解決。
            6.項目經理應該把眼光放在全局上。項目經理應該更多的關注于全局的事務,不要學只想拿大紅花的小學生。別只顧修改自己的BUG,你的BUG少,并不能說明你是個好項目經理,在項目失敗時,你個人的BUG少,并不能真正減輕你的罪惡感。據說軟件團隊遵循水桶原則,最低的那塊木板才是決定裝多少水要素,而不是最高的那塊。項目經理應該隨時關注哪塊是最低的,然后把它補起來,自己成為最高的那塊是沒有意義的。
            7.Person Review以提高士氣。呵,不知道有沒有Person Review這個術語,反正我覺得挺好的,在項目的最后階段,士氣是非常寶貴的東西,可以說得士氣者得天下。在前一個公司,每周一,老板會把每個工程師叫到他的辦公室,一起聊會兒,聊天內容不限,多半是問問你這邊工作上存在什么問題,有什么看法,非常坦白的談一會兒,最后會得到他的鼓勵和贊揚,自己感覺這對提高士氣很有幫助的,當然老板最好是個好的煽動者。
            8.Bug Review。建立一個Bug Review小組,他們的主要責任是: 發現一些具有共性的BUG,確認哪些BUG需要FIX,哪個BUG不用FIX。有共性的BUG,讓專人解決或者督促。不管一個BUG是要FIX還是不用FIX,都要注明足夠的理由。
            9.加強QA和RD之間的合作。呵,根據遺傳學和適者生存原理可以知道,在最后階段,BUG的生命力極強,往往花費很長時間才能重現。加上自然語言本身具有的二義性和個人看問題的側重點不同,QA可能忽略了RD讓認為很重要的重現步驟,QA的BUG描述在RD眼中也可能迥然不同。在這個階段,直接到現場和QA交流一下,可能會節省很多時間。同時也要尊重QA的勞動成果,這樣他們才會更積極的配合。
            10.經驗積累。每遇到一個BUG,想一想,它為什么會出現,為什么才出現,修改它后會有什么后果。把重要的記錄下來,可能對自己和別人都有所啟發,以減少犯同樣錯誤的機會。

          posted @ 2014-11-21 09:20 順其自然EVO 閱讀(176) | 評論 (0)編輯 收藏

          僅列出標題
          共394頁: First 上一頁 13 14 15 16 17 18 19 20 21 下一頁 Last 
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 治多县| 宜良县| 沂源县| 潼关县| 乐安县| 虞城县| 邢台市| 临西县| 武乡县| 舞阳县| 高台县| 方城县| 罗山县| 焦作市| 光泽县| 红河县| 子长县| 博白县| 射洪县| 长沙市| 皋兰县| 灵台县| 江津市| 津市市| 肥城市| 长治市| 拉萨市| 江安县| 乐安县| 镇康县| 永修县| 石屏县| 顺平县| 威信县| 饶阳县| 亳州市| 兴山县| 平江县| 枣庄市| 永福县| 聊城市|