星期六, 6月 05, 2010

zend DB 常用動作

直接對Zend_Db操作
  • 新增DB連線
    $db = Zend_Db::factory('Pdo_Mysql', array(
    'host'     => '127.0.0.1',
    'username' => 'webuser',
    'password' => 'xxxxxxxx',
    'dbname'   => 'course'
    ));
  • 下sql語法
    $stmt = $db->query('SELECT * FROM course');
    
    //Zend_Db提供fecth(),可抓出row object
    while($row = $stat->fetch()){
        echo $row['name'];
    }
  • 替換sql語法裡的參數
    $sql = 'SELECT * FROM course WHERE nam = ? AND status = ?';
    $stmt = new Zend_Db_Statement_Mysqli($db, $sql); //mysql就用mysqli
    $stmt->execute(array('demo course','display'));

宣告多個DB
  • 宣告(configs/application.ini)
    //db1
    resources.multidb.course.adapter = "PDO_MYSQL"
    resources.multidb.course.host = "localhost"
    resources.multidb.course.username = "root"
    resources.multidb.course.password = "ok1234"
    resources.multidb.course.dbname = "course"
    resources.multidb.course.driver_options.1002 = "SET NAMES utf8"
    resources.multidb.teegle.default = true
    
    //db2
    resources.multidb.admin.adapter = "PDO_MYSQL"
    resources.multidb.admin.host = "localhost"
    resources.multidb.admin.username = "root"
    resources.multidb.admin.password = "ok1234"
    resources.multidb.admin.dbname = "admin"
    resources.multidb.admin.driver_options.1002 = "SET NAMES utf8"
  • 選擇db
    $resource = $this->PluginResource('multidb');
    $resource->init();
    $db = $resource->getDb('course'); //取得course db
    $db->select()
        ->from( ... ) //多個from
        ->where( ... );

對Zend_Db_Table下指令
  • 設定table
    Zend_Db_Table::setDefaultAdapter($db);
    $courseTable = new Zend_Db_Table('course');
  • 在fetchAll裡加參數
    $resultSet  = $table->fetchAll(
            $table->select()
               ->where('status = ?', 'NEW') //有多個where就再下一次where(xx)
               ->order('id ASC')
               ->limit(10, 0)
    );
    
    //塞進array
    $entries   = array();
    foreach ($resultSet as $row) {   
        $object = row->id; // or row['id'];
        $entries[] = $object;
    }
  • 讓DbTable物件 讀非預設DB
    DbTable會預設讀config裡設定的"db"
    如果要讀一個db怎麼辦咧?
    1.註冊db
    在Bootstrap.php裡,註冊想要讀的db
    //application/Bootstrap.php
    class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
    {
        $resource = $this->getPluginResource('multidb'); //假設存放在multidb裡,參考如何設定多個db
        $resource->init(); //初始化,不然不會動
    
        //註冊要讀取的DB - admin
        $admin = $resource->getDb('admin');
        Zend_Registry::set("admin", $admin);
    }
  • 2.改寫DbTable的建構子 方法一 就在DbTable的class下,override construct 把要給DbTable的物件參數中的'db'改成目前要讀的db
    class Application_Model_DbTable_User extends Zend_Db_Table_Abstract { 
        protected $_name = 'user'; 
        //方法一     
        public function __construct($config=array()){
            $this->read  = Zend_Registry::get('admin');
            $this->write = Zend_Registry::get('admin');
            $config['db'] = Zend_Registry::get('admin');                       
            return parent::__construct($config);
        }  
    
        //方法二  
        protected function __setupDatabaseAdapter(){ 
        } 
    }
    join
    //Build this query: 
    //  Select p."product_id",p."product_name", l.* 
    //  From "products" AS p JOIN "line_items" AS l 
    // ON p.product_id = l.product_id  
    $select = $db->select()->from (array('p'=> 'products'), 
    array('product_id','product_name'))->join(array('l' => 'line_items'), 'p.produt_id = l.product_id');
References
Zend Framework Certification Study Guide

星期五, 6月 04, 2010

jqueryui button

原來disable不是改tag屬性... (會失敗)
試了好久才發現要丟參數
利用.button( "disable" ), enable就一樣囉

星期二, 6月 01, 2010

星期二, 5月 25, 2010

jqgrid - search

我怎麼照官網做 都沒有search的結果
看官網的php 也不像會有search的結果...

最後還是上網找

server.php (同官網範例,就在下sql那段 加入這個)
$where = "WHERE 1=1 " . constructWhere();
$SQL = "SELECT ... FROM xxx $where ORDER BY $sidx $sord LIMIT $start , $limit";
...

//--------------------------
function constructWhere(){
  $wh = "";
  $searchOn = $_REQUEST['_search'];
  if($searchOn=='true')
  {
   $fld = $_REQUEST['searchField'];

   //過濾欄位,填入會用到search的欄位
   if(!( $fld=='id' || $fld =='name'))
   {
    $fldata = $_REQUEST['searchString'];
    $foper = $_REQUEST['searchOper'];

    //construct where
    $wh .= " AND " . $fld;
    switch ($foper) {
      case "bw":
        $fldata .= "%";
        $wh .= " LIKE '" . $fldata."'";
        break;
      case "eq":
        if(is_numeric($fldata)) {
          $wh .= " = " . $fldata;
        }else{
          $wh .= " = '" . $fldata."'";
        }
        break;
      case "ne":
        if(is_numeric($fldata)) {
          $wh .= " <> " . $fldata;
        }else{
          $wh .= " <> '" . $fldata . "'";
        }
        break;
      case "lt":
        if(is_numeric($fldata)) {
          $wh .= " < " . $fldata;
        } else {
          $wh .= " < '" . $fldata."'";
        }  
        break;
      case "le":
        if(is_numeric($fldata)) {
          $wh .= " <= " . $fldata;
        }else {
          $wh .= " <= '" . $fldata."'"; 
        }
        break;
      case "gt":
        if(is_numeric($fldata)) {
          $wh .= " > ".$fldata;
        } else {
          $wh .= " > '".$fldata."'";
        }
        break;
      case "ge":
        if(is_numeric($fldata)) {
          $wh .= " >= ".$fldata;
        } else {
          $wh .= " >= '".$fldata."'";
        }
        break;
      case "ew":
        $wh .= " LIKE '%".$fldata."'";
        break;
      case "ew":
        $wh .= " LIKE '%".$fldata."%'";
        break;
      default :
        $wh = "";
    }
  }
  return $wh;
}

Reference
忘了哪看的了...

接收完成的callback function
jQuery("#tbSearch").jqGrid({
  datatype:function(postdata) {
  jQuery.ajax({
  url: "server.php", //原本寫在外面的,現在外面那個就參考用
  data:postdata,
  datatype:"json",
  complete:function(xmldata,stat){
   if(stat=="success") {
    //xmldata是XMLHttpRequest, 所以如果是datatype的話,就要 xmldata.responseXML
    alert(xmldata.responseText);
   }
  }
});
},
...

Reference
Data Manipulation
jqGrid 的多字段查詢

星期二, 5月 18, 2010

zend - 關連table

我也不知道怎麼做出來的
一開始明明就照著教學做
可是怎麼做都說有錯
什麼No reference rule \"$ruleKey\" from table $thisClass to table $tableClassname"
不然就什麼 No reference from table $thisClass to table $tableClassname"
說xx table裡找不到reference關係...

最後進到Zend/library/Db/Table/Abstract.php一步步查
先看建構子有存進去了
最後一路看到getReference()
因為會說沒有rule 所以就先把那段解註掉
if ($ruleKey !== null) {
...
}

再看foreach ($refMap as $reference)...這段
明明有哇... 再把註解全拿掉時...
神奇的事發生了...
一切的值都有了 也不會有例外
這... 到底發生什麼事了...= =?

過程中 我是有一直亂改值測試...
可是... 最後成功的值...應該是一樣的
嗯哉~~ 總之先記錄下來.... 免得又遇到了

說明
table "GroupTee"裡有teeid,需要跟table "Tee"的主鍵id做關連
table grouptee
<?php
class Application_Model_DbTable_GroupTee extends Zend_Db_Table_Abstract
{
protected $_name = 'group_tee_rt';
protected $_dependentTables = array('Application_Model_DbTable_Tee'); // 對應到關連的 Table Class
}


table tee
<?php
class Application_Model_DbTable_Tee extends Zend_Db_Table_Abstract
{
protected $_name = 'tee'; //real table name

protected $_referenceMap= array(
'TeeName' => array( //rule名稱
'columns' => array('id'), //tee的pky
'refTableClass' => 'Application_Model_DbTable_GroupTee', //參考GroupTee
'refColumns' => array('teeid') //GroupTee裡的teeid
)
);
}


contoller或應用的地方
$tbGroupTee = new Application_Model_DbTable_GroupTee();
$group = $tbGroupTee ->fetchRow('id=1'); //取得第1個group
$grouptee = $group->findDependentRowset('Application_Model_DbTable_Tee','TeeName');
Zend_Debug::dump($grouptee, $label = "grouptee", $echo = true);



References
初探 Zend_Db_Table Relationships
One To Many Relationship with Zend Framework

星期日, 5月 16, 2010

dokuwiki - gcalendar

不知大家拿來做什麼用
公司是拿來當工作日誌用...
所以有分預定計劃,實際執行Deadline
而event type當沒沒這麼巧的有這幾樣
不過可自定event type

作法
1.連結內容
=== 預定計劃 ===
*2010-5-3 - 2010-5-4 teegle
=== 實際執行 ===
*2010-5-3
=== Deadline ===
*2010-5-4


2.增加event type
到events.css增加與引用名稱相同的class名
path: [dokuwiki資料夾]/lib/plugins/gcalendar/user/events.css
/* 就是自己增加css的class */
.預定計劃
{
 color:grey; //改字型色彩
}
.實際執行
{
 background-image:url(images/gear.gif); //自行定義圖示
}
.Deadline
{
 color:red;
 bold:true;
 background-image:url(images/deadline.gif); //自行定義圖示
}


3.上傳圖片
就看自己寫到哪就傳到哪個資料夾囉
預設位置是[dokuwiki資料夾]/lib/plugins/gcalendar/user/images

結果如下
嗯 圖示的大小為15*16...
圖有點過大 不過效果還不錯...


Reference:dokuwiki - gcalendar

星期六, 5月 15, 2010

常用的10個jqgrid提示

網路上看的10 JQGrid Tips learned from my experience,再補點自己常遇到的

  1. Changing JQGrid width and height
    "//自動調寬度
    jQuery("#list2").jqGrid({
    autowidth: true, 
    ...
    //手動設定
    $("#list2").setGridWidth(200,true); //忘了true是什麼


    ColModel的屬性

    jQuery("#list2").jqGrid({
    ...
    colModel: [
    {
     name: 'rowid',  //將欄位名稱
     index: 'rowid asc, createddate', //click此欄位的排序會依據的order
      width: 50,
     sorttype: "int",
      align: "center",
     key:true, //將欄位設為pk
     search:true, //是否提供search
     hidden:false, //讓此欄位隱藏
    ...
  2. Grid without unnecessary scroll area
  3. Error due to missing locale file
  4. Callback function
    • loadComplete //ajax完成後的事件
      loadComplete: function(){
      var ids = jqgrid.jqGrid('getDataIDs'); //取得所有ids  
      alert(ids.length);
    • gridComplete //將所有資料讀進grid後的事件
    gridComplete及loadComplete差異
    $("#list").clearGridData();會觸發gridComplete
    利用ajax讀入資料時,jqgrida會先清掉grid內容,但不會觸發gridComplete,而讀完資料時,先後觸發gridComplete及loadComplete
    其他event
  5. Using pagers only for buttons (or icons)
  6. Hiding unwanted buttons in navigation bar
  7. Hiding the inline search by default
  8. Having your own icons for navigation bar buttons
  9. Removing title bar close button
  10. Adding toolbar    

常用指令
  • Get data from selected row
    var id = jQuery("#list2").jqGrid('getGridParam','selrow'); 
    if (id) {
        var ret = jQuery("#list2").jqGrid('getRowData',id); //3.6的方法
        //var ret = jQuery("#list2").getRowData(id);  //3.5以前的方法
        alert("id="+ret.id+" invdate="+ret.invdate+"...");
    } else {
        alert("Please select row");
    } 
  • 刪除
    //設定刪除事件
    $("#bDelete").click(function(){
    // Get the currently selected row
    toDelete = $("#mygrid").jqGrid('getGridParam','selrow');
    
    // You'll get a pop-up confirmation dialog, and if you say yes,
    // it will call "delete.php" on your server.
    $("#mygrid").jqGrid(
    'delGridRow',
    toDelete,
    { url: 'delete.php',
    reloadAfterSubmit:false}
    );
    });
    post資料有[oper] => del,[id] => 88
    Custom delete button in jqGrid

    //直接在navigator裡設刪除事件
    jQuery("#list2").jqGrid({
    ...
    }).navGrid('#pager2', {
    view: true,
    edit: true,
    add: false,
    del: true
    },{
       //依序view
    },{
        /edit
    },{
        //add
    },{
        //delete options 
        url: 'delete.php', //response的url
    
        //submit前驗證,其他看p.s.1
         beforeSubmit : function(id, formid) {
            if (id) {
               var ret = jQuery("#list2").jqGrid('getRowData',id);
               if (!(ret.xxx == "" )
                {
                    return [false,"xxx皆為空白才可以刪除"]; //false會顯示錯誤訊息
                }
            } else {
                return [false,"Please select row"];
            }
            return [true,""]; //true才會繼續
       
    }


    //刪除第12行row
    var su=jQuery("#list5").jqGrid('delRowData',12);
    if(su) 
        alert("Succes. Write custom code to delete row from server"); 
    else
        alert("Allready deleted or not in list"); 
    //清空grid內容
    $("#list1").clearGridData();


References

星期三, 5月 12, 2010

zend - 常見錯誤訊息

  • Action xxx does not exist and was not trapped in __call().
  • 大小寫都試過,最後換個全小寫名稱是成功了 還不知到底是什麼問題
  • Invalid controller specified (CourseTee)
    因為controller的名稱為2個字組合Course, Tee, 但zend不支援什麼駝峰字母,所以真正的名稱被改為Course-Tee 當利用zf create controller CourseTee時 會自動建立controolerview/script/course-tee
  • Zend沒有report error
  • Firefox 回報"伺服器要將此網址重新導向的要求無法完成"

星期二, 5月 11, 2010

jqueryui - dialog

在關閉dialog時 => $(this).dialog('close');
jqueryui會將input的內容清掉...
所以會抓不到.....
氣死... 搞好久才發現...

星期二, 4月 27, 2010

Zend Controller- 常用動作

  1. Debug
    Zend_Debug::dump($row, $label = "current row", $echo = true);
  2. 不render view or layout
    • no render
      $this->_helper->viewRenderer->setNoRender();
    • disable layout
      $this->_helper->layout->disableLayout();
  3. BaseUrl, Controller or Action Name
    透過request取得
    $this->_request->getControllerName()
    ->getActionName()
    ->getParams() //取post或get之類的參數
    ->getBaseUrl()

  4. 轉頁動作
    • redirector,forward
      //給同一controller的 action (ex.index)
      $this->_redirect('Controller/actionA'); //要給完整的Controller及Action
      //=$this->_helper->redirector('actionA');  //如果直給action,會轉給此controller下的action
    • 轉給controllerA的actionA
      $this->_helper->redirector('controllerA/actionA');
      this->_forward('actionA', 'controllerA', null, array('param1' => 'xxx'));

    • $this->_redirect與$this->_helper->redirector的不同? Ans:_redirect需包("controller/action"), redirector可只下("action") ex.在TeeController下 $this->_redirect('index'); //會跑到Index/index,而不會是Tee/index $this->_redirect('Tee') // $this->_helper->redirector('index'); $this->_redirect('Tee/add'); // $this->_helper->redirector('add');
    • 保留訊息給redirect後的頁面
      //set
      $flashMessenger = $this->_helper->getHelper('FlashMessenger');
      $flashMessenger->addMessage($message);

      //get
      $message = $flashMessenger->getMessages(); //array
      if(count($message) == 0 )  
         $this->view->message = "";
      else
         $this->view->message = $message[0];
      }
    • 也可指定Namespace,透過setNamespace即可,範例如下 $flashMessenger->setNamespace('actionErrors');
    • redirect 給參數
      //add parameters
      $controller = 'index';$action = 'message'; $module = null;
      $parameters = array(    'para1' => 'test1',    'para2' => 'test2' );
      $this->_helper->redirector(action , controller , $module, parameters );

      //get parameters
      public function toNextPageAction(){
         $para1 = $this->getRequest()->getParam('para1');
         $para2 = $this->getRequest()->getParam('para2');
      }
    //宣告Registry變數 Zend_Registry::get("course", $course);
  5. 在controller裡,加入Header資訊
    • 加入Meta
      $this->headMeta()->appendName('keywords', 'framework, PHP, productivity');
    • js,css路徑(如果要直接在view裡加入看這)
      $this->view->headLink()->appendStylesheet(‘css/homepage.css');
      $this->view->headLink()->appendStylesheet($baseUrl.'/css/admin/tinybrowser.css');
      $this->view->headScript()->appendFile('/' . $file_uri);
    • 最後要echo資訊到header
      <html>
      <head>
        <?= $this->headTitle() ?>
        <?= $this->headMeta() ?>
        <?= $this->headScript() ?>
        <?= $this->headLink() ?>
        <?= $this->headStyle() ?>
      </head>
      <body>
        <?= $this->layout()->content ?>
      </body>
      </html>

zend 建立CRUD

Zend Framework version: 1.10
參考:Tutorial: Getting Started with Zend Framework 1.10

針對IndexController建立CRUD action
URLAction method
http://localhost/public/IndexController::indexAction()
http://localhost/add /IndexController::addAction()
http://localhost/edit /IndexController::editAction()
http://localhost/delete /IndexController::deleteAction()
分別輸入以下指令:
  • %zf create action add Index
  • %zf create action edit Index
  • %zf create action delete Index
這時除了建立各action的page外,還會自動在IndexController建立各action的動作
所以說如果是要針對UserController,最後的Index就改成User
以下是IndexController的內容
//controllers/IndexController.php
class IndexController extends Zend_Controller_Action
{
public function init()
{
/* Initialize action controller here */
}

public function indexAction()
{
// action body
}

public function addAction()
{
// action body
}

public function editAction()
{
// action body
}

public function deleteAction()
{
// action body
}
}

vm二三事

VMware Tools
啥是VMware Tools
安裝在vm裡的虛擬os裡的套件

優點
  • 驅動vm裡面os顯卡等,像CentOS只能640 x 480和800 x 600
  • 可直接用滑鼠拖曳傳檔
  • 滑鼠可跨主機與vm視窗移動
  • 複製的東西可以在主機與vm視窗共用

 
安裝:
如何在CentOS安裝VMWare Tools?

組合exe,dll成單一執行檔 - ILMerge

寫好的程式常會include一些dll檔,每次copy給同事,就會發現漏掉dll沒給
查了一下 原來.net下有ILMerge 這好東西
下載:ILMerge

寫法
將aaa.exe跟bbb.dll及ccc.dll合併成Merged.exe
ILMerge.exe /out:Merged.exe aaa.exe bbb.dll ccc.dll
當然要先設環境變數囉
一般預設路徑C:\Program Files\Microsoft\ILMerge

另還有GUI
不過還是直接在建置事件那設定完最快了
每次compile完 就完成了...真是好東西
到Visul Studio的專案屬性裡的建置事件,如下圖












Error Code
  • 1: 發現是缺了要合併的檔案,補上就ok了
    • 不過有時也有其他問題,要log下來才知道 其他

Reference:
介紹好用工具:ILMerge (將多的 .NET 組件合併成單一組件)

zend - 建立layout

參考:Create A Layout
顧名思義就是套版型,Zend利用將網頁的header,body,footer拆開,方便header及footer可共用,不同的地方(即body),拆給MVC架構完成,所以最後要合併起來
Zend提供了二種做法:
Step1先從資料庫取出資料,Step2再轉成要呈現的資料


某些action不要有layout
將menu鏈結放在layout 則每頁都會有鏈結
但某些情況下,如嵌ifrmae 就不想再出現menu鏈結
就可以在該action下 加入這行
public function xxxAction(){
$this->_helper->layout->disableLayout();
}


加入在controller裡定義的標題資訊
在controller定義好要加入的標題檔資訊後,在layout加入echo的程式
<html>
<head>
  <?= $this->headTitle() ?>
  <?= $this->headMeta() ?>
  <?= $this->headScript() ?>
  <?= $this->headLink() ?>
  <?= $this->headStyle() ?>
</head>
<body>
  <?= $this->layout()->content ?>
</body>
</html>

星期一, 4月 26, 2010

zend 建立form

參考:Create A Form
跟使用者互動就透過form啦
1.建立form
指令:% zf create form Guestbook
Creating a form at application/forms/Guestbook.php
Updating project profile '.zfproject.xml'


// application/forms/Guestbook.php
class Application_Form_Guestbook extends Zend_Form
{
    public function init()
    {
        // Set the method for the display form to POST
        $this->setMethod('post');
 
        // Add an email element
        $this->addElement('text', 'email', array(
            'label'      => 'Your email address:',
            'required'   => true,
            'filters'    => array('StringTrim'),
            'validators' => array(
                'EmailAddress',
            )
        ));
 
        // Add the comment element
        $this->addElement('textarea', 'comment', array(
            'label'      => 'Please Comment:',
            'required'   => true,
            'validators' => array(
                array('validator' => 'StringLength', 'options' => array(0, 20))
                )
        ));
 
        // Add a captcha
        $this->addElement('captcha', 'captcha', array(
            'label'      => 'Please enter the 5 letters displayed below:',
            'required'   => true,
            'captcha'    => array(
                'captcha' => 'Figlet',
                'wordLen' => 5,
                'timeout' => 300
            )
        ));
 
        // Add the submit button
        $this->addElement('submit', 'submit', array(
            'ignore'   => true,
            'label'    => 'Sign Guestbook',
        ));
 
        // And finally add some CSRF protection
        $this->addElement('hash', 'csrf', array(
            'ignore' => true,
        ));
    }
}


2.建立對應action
指令:% zf create action sign Guestbook
Creating an action named sign inside controller
at application/controllers/GuestbookController.php
Updating project profile '.zfproject.xml'
Creating a view script for the sign action method
at application/views/scripts/guestbook/sign.phtml
Updating project profile '.zfproject.xml'
// application/controllers/GuestbookController.php
class GuestbookController extends Zend_Controller_Action
{
    // snipping indexAction()...
 
    public function signAction()
    {
        $request = $this->getRequest();
        $form    = new Application_Form_Guestbook();
 
        if ($this->getRequest()->isPost()) {
            if ($form->isValid($request->getPost())) {
                $comment = new Application_Model_Guestbook($form->getValues());
                $mapper  = new Application_Model_GuestbookMapper();
                $mapper->save($comment);
                return $this->_helper->redirector('index');
            }
        }
 
        $this->view->form = $form;
    }
}


3.設定view
<!-- application/views/scripts/guestbook/sign.phtml -->
Please use the form below to sign our guestbook!
<?php
$this->form->setAction($this->url());
echo $this->form;


完成啦,檢查一下http://localhost/guestbook/sign
應該會出現下圖

zend - 建model與database 連結


主要參考官網這篇Create a Model and Database Table

1.db設定檔
指令:zf configure db-adapter
以下各別為開發、測試及成品設定其db
//設定成品db
% zf configure db-adapter 'adapter=PDO_MYSQL&dbname="db_production"&host="localhost"&username="username"&password="ok1234"' production
//設定測試db    
% zf configure db-adapter 'adapter=PDO_MYSQL&dbname="db_testing"' testing
//設定開發db      
% zf configure db-adapter 'adapter=PDO_MYSQL&dbname="db_development"' development
設定完後的結果會存在application/configs/application.ini
所以...其實到application.ini改就可以
那些指令那記得起來...
完整的檔案如下
//application/configs/application.ini
[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
resources.view[]=
resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "localhost"
resources.db.params.username = "root"
resources.db.params.password = "ok1234"
resources.db.params.dbname = "db_production"
resources.db.params.driver_options.1002 = "SET NAMES utf8"

[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.db.adapter = "PDO_MYSQL"
resources.db.params.dbname = "db_testing"

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1
resources.db.adapter = "PDO_MYSQL"
resources.db.params.dbname = "db_development"
中文亂碼問題
到application.ini中加入resources.db.params.driver_options.1002 = "SET NAMES utf8"
多個db問題
Zend_Application_Resource_Multidb
留著原本預設的db,才不用再改原本預設的資料

2.建立table物件
針對table(guestbook)建立對應table物件Guestbook.php
指令:% zf create db-table Guestbook guestbook
Creating a DbTable at application/models/DbTable/Guestbook.php
Updating project profile 'zfproject.xml'
Guestbook.php的內容如下
// application/models/DbTable/Guestbook.php
/**
* This is the DbTable class for the guestbook table.
*/
class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
{
    /** Table name */
    protected $_name    = 'guestbook';
}

3.建立Mapper
剛建立了table物件,在這要建立mapper
mapper的做用在處理insert,delete相關動作地方(要select的欄位,要下的where)
讓table物件與DB處理分開只負責存屬性(欄位)及方法,參考Data Mapper的觀念



% zf create model GuestbookMapper
Creating a model at application/models/GuestbookMapper.php
Updating project profile '.zfproject.xml'
// application/models/GuestbookMapper.php 
public function save($model);
public function find($id, $model);
public function fetchAll();
4.建立model
針對Guestbook建立該model
指令:% zf create model Guestbook
這指令會建立application/models/Guestbook.php
並更新project profile '.zfproject.xml'
// application/models/Guestbook.php
class Application_Model_Guestbook
{
    protected $_comment;
    protected $_created;
    protected $_email;
    protected $_id;

    public function __construct(array $options = null)
    {
        if (is_array($options)) {
            $this->setOptions($options);
        }
    }

    public function __set($name, $value)
    {
        $method = 'set' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            throw new Exception('Invalid guestbook property');
        }
        $this->$method($value);
    }

    public function __get($name)
    {
        $method = 'get' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            throw new Exception('Invalid guestbook property');
        }
        return $this->$method();
    }

    public function setOptions(array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }
        return $this;
    }

    public function setComment($text)
    {
        $this->_comment = (string) $text;
        return $this;
    }

    public function getComment()
    {
        return $this->_comment;
    }

    public function setEmail($email)
    {
        $this->_email = (string) $email;
        return $this;
    }

    public function getEmail()
    {
        return $this->_email;
    }

    public function setCreated($ts)
    {
        $this->_created = $ts;
        return $this;
    }

    public function getCreated()
    {
        return $this->_created;
    }

    public function setId($id)
    {
        $this->_id = (int) $id;
        return $this;
    }

    public function getId()
    {
        return $this->_id;
    }
}

5.建立controller
指令:% zf create controller Guestbook

  • Creating a controller at application/controllers/GuestbookController.php
  • Creating an index action method in controller Guestbook
  • Creating a view script for the index action method at application/views/scripts/guestbook/index.phtml
  • Creating a controller test file at tests/application/controllers/GuestbookControllerTest.php
  • Updating project profile '.zfproject.xml'

=>會建立預設的index action
// application/controllers/GuestbookController.php
class GuestbookController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $guestbook = new Application_Model_GuestbookMapper();
        $this->view->entries = $guestbook->fetchAll();
    }
}

6.編輯view
<!-- application/views/scripts/guestbook/index.phtml -->
<p><a href="<?php echo $this->url(
    array(
        'controller' => 'guestbook',
        'action'     => 'sign'
    ),
    'default',
    true) ?>">Sign Our Guestbook</a></p>

Guestbook Entries: <br />
<dl>
    <?php foreach ($this->entries as $entry): ?>
    <dt><?php echo $this->escape($entry->email) ?></dt>
    <dd><?php echo $this->escape($entry->comment) ?></dd>
    <?php endforeach ?>
</dl>

總算結束了
鍵入http://localhost/guestbook 應該會看到下面畫面

vim常用指令

Vi Cheat Sheet

  • Get the name of the current file
    :echo @%def/my.txtdirectory/name of file
    :echo expand('%:t')my.txtname of file ('tail')
    :echo expand('%:p')/abc/def/my.txtfull path
    :echo expand('%:p:h')/abc/defdirectory containing file ('head')
  • 移動浮標指令

    Motion


    hMove left
    jMove down
    kMove up
    lMove right
    wMove to next word
    WMove to next blank delimited word
    bMove to the beginning of the word 單字字首
    BMove to the beginning of blank delimted word 單字字尾
    eMove to the end of the word 單字字首
    EMove to the end of Blank delimited word
    (Move a sentence back
    )Move a sentence forward
    {Move a paragraph back
    }Move a paragraph forward
    0Move to the begining of the line
    $Move to the end of the line
    1GMove to the first line of the file
    GMove to the last line of the file
    nGMove to nth line of the file
    :nMove to nth line of the file
    fcMove forward to c
    FcMove back to c
    HMove to top of screen
    MMove to middle of screen
    LMove to botton of screen
    %Move to associated ( ), { }, [ ]
  • 常用指令
    指令說明備註
    yy複製整行文字
    y$複製cursor後,到行尾文字
    gg=G格式化全文一直看人在寫gg=G
    還以為打gg或G都可以... 怎麼都試不出來...
    原來... 真的是打gg=G 靠... 試了好久... 機車
    gg - 到文章開頂端
    = - apply indentation (縮排)
    G - 到文章尾端
  • 分頁指令
    指令說明備註
    :tabnew開新分頁
    :tabedit path/to/file開啟舊檔
    Ctrl+6切換分頁
    gt依序切換
    :tabn,:tabp前後切換
  • 快速移動
    捲動螢幕
    ^F 往前捲動一個螢幕
    ^B 往後捲動一個螢幕
    ^D 往前捲動半個螢幕
    ^U 往後捲動半個螢幕

    重新調整螢幕位置
    z[enter] 將游標移到螢幕頂端
    zz 將游標移到螢幕中心
    z- 將游標移到螢幕底端


References

星期六, 4月 24, 2010

建立Zend Project

  1. prerequisite
    Zend 1.10要求PHP 5.2.4 or later.
    1. 先升級PHP
      #vi /etc/yum.repos.d/utterramblings.repo
    2. 輸入以下內容
      [utterramblings]
      name=Jason's Utter Ramblings Repo
      baseurl=http://www.jasonlitka.com/media/EL$releasever/$basearch/
      enabled=1
      gpgcheck=1
      gpgkey=http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka
    3. 進行更新
      #yum -y update php
  2. 安裝Zend
    1.下載 http://framework.zend.com/download/latest
    #tar -zxvf ZendFramework-xx-.tar.gz   
    #mv ZendFramework-xx /var/www/zend //移到www下,順便重新命名
    2.設定php.ini
    #vim /etc/php.ini 
    -------------------------------------------
    //找到include_path那行,改成下面 
    include_path="/var/www/zend/library"
    貼心小叮嚀:要重啟httpd, #service httpd restart
    3.建立project (網站) 不知從哪一版開始 就像ror可下指令建立預設的資料結果
    #zf create project quickstart
    所有指令:Command Line Console Tool zf指令位於[Zend資料夾]/bin下,當然要自己去設定path才抓的到
    ln -s /var/www/zend/bin/zf.sh /usr/local/bin/zf
    錯誤訊息:當zf create project時,出現:PHP Fatal error: Class 'DOMDocument' not found in /var/www/html/Zend... 表示系統未安裝php-xml
    #yum install php-xml
    4.建立Zend Libraray 如果沒php.ini裡加的話,也可直接做link或複製一份到project下的library
先到剛建立的project下的library
      利用link
      #ln -s path/to/ZendFramework/library/Zend  
      直接copy一份
      #cp -r path/to/ZendFramework/library/Zend   
    5.Create a virtual host
    #vim /etc/httpd/[conf]/httpd.conf
    ----------------------------------
    <virtualhost *:80>    
      ServerName quickstart.local    
      DocumentRoot /var/www/html/quickstart/public    
      SetEnv APPLICATION_ENV "development"          
      <Directory /var/www/html/quickstart/public>      
        DirectoryIndex index.php      
        AllowOverride All      
        Order allow,deny      
        Allow from all    
      </Directory>  
    </virtualhost>
    6.確認是否成功 直接用browser開始127.0.0.1,看到下面畫面就是成功啦
    Reference

星期日, 4月 18, 2010

Code Complete 2

作者:Steve McConnell

Ch6 工作類別

類別基礎:抽象資料型別(ADT)
將字型大小變更為12點,即16個像素高
//易混淆
currentFont.size = 16; //不知是pixel還是點

//較具意義
currentFont.size = PointsToPixels(12); 
currentFont.bold = true;
currentFont.setBoldOn();

Ch7 高品質常式

從常式名稱中可猜出其作用
單一且明確定義的目的
參數不易超過7個,造成閱讀不易
具備抵禦錯誤資料,不會造成當機

良好的常式名稱
  • 描述常式的所有工作
  • 避免無意義、模糊式空泛的動詞命令
  • FormatAndPrintOut()會比HandleOutput()更加的清楚
  • 勿僅用數字后別常式名稱
  • part1(),part2()
  • 用回傳值述命名函式
  • printer.isReady(),user.next()
如何使用常式參數
  • 文件化有關參數的介面假設
  • 不要回頭再寫註解,數字參考單位,預期值的範圍、永不應出現的特定值
  • 考慮輸入、修改和輸出參數的命名慣例
  • input_,modify_,output_

Ch8 防禦性程式設計

用判斷提示證明和驗證前置條件及後置條件
又稱為design by contract (Meyer 1997)
function velocity(float latitude, float longitude,float elevation){
//Preconditions
Debug.Asert ( -90 <= latitude && latitude <= 90); 
Debug.Assert ( 0 <= longitude && longitude<= 360); 
Debug.Assert ( -500 <= elevation && elevation <= 75000); ... 

//Postcondition 
Debug.Assert()0 <= returnVelocity && returnVelocity <= 600);  
//return value 
return returnVelocity ; 
}

對於錯誤的條件,常式通常會用判斷提示直接處理錯誤的程式碼
判斷提示
Debug.Assert()0 <= returnVelocity && returnVelocity <= 600); 

直接處理錯誤的程式碼
...
//cloest legal value
if(latitude <-90) latitude = -90; else if (latitude > -90)
latitude = 90;
...

8.3 處理錯誤的技巧
傳回中性值
有時對錯誤資料的最佳反應就是持續操作,回傳預設值。數字計算=>0,文字操作=>空字串
關鍵情況下,就回傳錯誤,不要回傳錯誤的資料。
以下一個有效資料取代
處理資料串流時
傳回與上一次相同的回答
考慮建立集中的例外況報告程式
確保例外狀況處理一致性,也能提供中央儲存機制九
function reportException(string className, Exception ex){
string caption="Exception";
string message = 
"Exception: " + ex.Message + Enviroment.NewLine +
"Class: " + className + Enviroment.NewLine +
"Routine: " + ex.TargetSite.Name;

MessageBox.Show(message,caption);
}

//example
try{
...
}catch(Exception ex){
reportException(CLASSNAME,ex);
}

8.5 建立路障,避免程式內含錯誤造成的損毀
撰寫驗證類別,在所有介面運算資料前,透過驗證類別確保資料有效

Ch14 組織直線
14.1.須依特定順序排列的陳述式
1.連續呼叫相依的methods
//計算年營收前,得先計算季營收,而計算季營收前,要先計算月營收
revenue.ComputeMonthly(); //
revenue.ComputeQuarterly();
revenue.ComputeAnnual();
相依性不明顯,將來順序對換,會造成錯誤, 要讓程式碼可看出其相依關係
 2.初始化
//求各部門支出前,要先利用ComputeMarketingExpense()初始化
ComputeMarketingExpense(); //
ComputeSalesExpense();
ComputeTravelExpense();
無法在第一時間看出計算前要先初始化,將來順序對換會錯誤

使常式參數使相依性明顯 
//利用初始化及輸出值,提示相依性
expenseData = InitializeExpenseData(expenseData);

expenseData = ComputeMonthly(expenseData);
expenseData = ComputeQuarterly();
expenseData = ComputeAnnual();  

Ch15 使用條件式
15.1 if
指導方針
  • 先寫pass判斷的正常路徑;再寫異常案例後,避免模糊掉執行邏輯
  • 將正常的case置於if block, 而非else後方
OpenFile(inputFile, status); 
if( status = Status_Success )  //pass
    ReadFile( inputFile, fileData, status); //名目案例
    if(status = Status_Success)
    { 
        end(); 
        errorType= ErrorType_None;
    }
    else
        errorType = ErrorType_FileReadError; //錯誤案例
else
    errorType = FileOpenError; //錯誤案例
重點在讀取主要流程,而非費力專研例外案例
Ch26. 程式碼微調技巧
26.2 迴圈
決策外置(Unswitching)
如果if判斷不會在迴圈執行時變更,就把if搬到迴圈外

合併
將兩個相同集合項目的迴圈合併,一次就把兩次事做完
for(i=0;i<n;i++)
  a++;
for(i=0;i < n;i++)
  b++;
------------------------合併成------------------------
for(i=0;i < n;i++){
  a++;
  b++;
}

減少迴圈內的工作
要使迴圈有效率,其中的關鍵在減少迴圈內部的工作。
如果可在外部運算部份或全部的陳述式,只讓結果進入迴圈內,就可提升效率

26.3 資料轉換
使用整數而非浮點數
盡量不要使用陣列維度
減少陣列參考
利用變數存陣列值,就可避免在迴圈內讀取陣列值
for(...)
  rate[level] *= discount[type]; //discount[type]可抽出來
---------------------用變數取代---------------------------------
discounttype =  discount[type];
for(...)
  rate[level] *=  discounttype;

26.4 運算式
利用代數恆等式
not a and not b = not (a or b)
後者會比前者快上將近1份的時間
使用強度降代
  • 用加法取代乘法
  • 用乘法取代乘冪
  • 用三角恆等式取代三角常式
  • 整數運算會比浮點數快
  • 使用位移運算取代整數乘除

星期五, 4月 16, 2010

與熊共舞:軟體專案的風險管理 Waltzing with Bears: Managing Risk on Software Projects


與熊共舞:軟體專案的風險管理
Waltzing with Bears: Managing Risk on Software Projects

作者:湯姆.狄馬克、提摩西.李斯特/著












風險管理的主要活動
  • 風險探索(risk discovery):風險腦力激盪,把風險歸類,再訂出可長久運作的機製
  • 承擔分析(exposure analysis):以風險成形的機率,及其潛在的衝擊程度為基礎,量化每個風險
  • 應變規劃(contingency planning):萬一風險真的成形,你期望採取的行動
  • 紓緩(mitigation):在風險蛻變前必須進行的步驟,使事先規劃的應變行動在必要時能發揮作用
  • 蛻變的持續監視(ongoing transition monitoring):風險被納管之後,就要進行風險追蹤,留意是否成形

Ch8.將不確定性量化

- 風險圖
最早的完成時間會自動變成最後期限
但完成機率是零...
說定最中間的日期(5/1)
加減10~15%


Ch9.風險管理的技巧

  • 風險庫
  • 選擇偵測風險成形的指標
卡車司機的座右銘:
每個滾動的球後面都跟著一位追逐的孩童
並不是指都有孩童將被撞到,但看到球,還是立刻踩下煞車比較好

Ch10.風險管理的處方


如何做風險管理
  1. 透過風險抭索程序找出專案面臨的風險,彙整成風險調查報告
  2. 確定軟體專案的主要風險都已納入調查報告
  3. 針對每個風險,完成以下事項:
    • 命名風險,賦予唯一編號
    • 找出蛻變指標-能及早預告風險即將成形的事物
    • 預估風險成形對成本和時程的衝擊
    • 預估風險成形的機率
    • 計算時程和預算的風險承擔
    • 預先決定執行應變行動而必須預先進行的紓緩措施
    • 把紓緩措施納入專案計劃
    • 把所有細節記錄在類似附錄B的制式文件內
  4. 指出致命風險(showstopper)
  5. 假設不會有任何風險成形,估計最早完成日期(奈米機率日,N點)
  6. 參考自己或業界的不確定性係數,以N點為起點,畫出風險圖
  7. 利用風險圖表示出所有承諾,風跟規劃日期和預算有關的不確定性也標示出來
  8. 監視所有風險,注意是否成形或解除,一旦成形,便立即啟動應變計劃
  9. 在專案進行時,持續風險探索程序,以對付較晚才浮現出來的風險
承諾與目標
時程 = 目標 = N <=非常笨的做法
時程 > 目標 > N <=比較合乎情理

不確定性的取捨
如果交付日期已敲定,且不留任何延誤的餘地
可利用版本交付時程來達成


Ch13.軟體專案的核心風險

  1. 先天的時程錯誤(schedule flaw)
  2. 不把規模想清楚就敲定時程,逾期50%~80%不足為奇,主管很少會怪時程,相反地,會怪人沒有盡力
  3. 需求膨脹(requirement inflation) ... 沒完沒了的需求變動
  4. 每月合理的需求變更應小於1%,因此預留時間
  5. 人力流失(employee turnover)
  6. 技術人員的年平均流動率 接替人員完全進入狀況時間(ramp-up time)
  7. 規格崩潰(specification breakdown)
  8. 一般人傾向於促成案子,有談不攏的衝突都會先被掩飾起來,於是專案就在缺陷、模糊的目標下進行,但開發產品時就會爆發,通常是在專案後期,預算、時間都花光了。
  9. 低生產力(poor productivity)
  10. 開發人員的表現好壞差異相當大,但在團隊中,個人因素或多或少都會被中和掉,所以差異不大。
把核心風險當作風險管理是否完備的指標
不敢說核心風險是完善,但沒考量五個核心風險,就說有做風險管理....

Ch16.漸進式風險紓緩

預先採取的一套作為,萬一風險成形,便可有效地處理風險
漸進式式交付的好處:
  • 迫使為組件進行優先順序
  • 反暈真實的開發效率
交付計劃

  • 設計藍圖(design blueprint):顯示要實作的低階模組或類別,及彼此之間的關係
  • 工作分解結構(work breakdown structure, WBS):顯示要完成的工作,及彼此之間的相依關係
  • 一組版本驗收測試(version acceptance test, VAT):把產品的驗收測試按版本細分,顯示哪個測試可用在哪個中間產品上
實獲率
工作編號工作量工作百分比完成的版本小計VAT通過日期
1.11人週11%版本1
2.7人週7%版本1
3.12人週12%版本130%第100天
4.10人週10%版本2
5.9人週9%版本249%第154天
6.8人週8%版本3
7.13人週13%版本369%第173天
8.9人週90%版本478%第185天
9.14人週14%版本5
10.7人週7%版本5100%第206天

ch17 終極的風險紓緩策略
計劃準時參加會議,途中可能遇到預料外的耽擱,最簡單的做法只要提早出發...
假如專案交付日期非常關鍵,那麼早點出發才是真正的風險紓緩措施

星期四, 4月 15, 2010

PHP Framework - Zend

經過大師的開示
現在也準備以framework來開發專案
 看了半天挑了Zend來開發
  1. 安裝與建立Project

    References
  2. IDE
    Zend自已有利用eclipse改了一套Zend Studio,另外還有video教學
    不過要coco...還是用forever的vim吧...
  3. E.書及資源
    書或電子檔
References: PHP Framework 的效能比較 

十個最好的所見即所得編輯器

10 best WYSIWYG Text and HTML Editors for Your Next Project

嗯...都很棒
不copy原著的了...
不過留下10大的名稱,免得網頁不見了...
1. NicEdit
2. TinyMCE
3. CKEditor
4. YUI Rich Text Editor
5. MarkItUp!
6. FreeTextBox
7. MooEditable
8. OpenWysiwyg
9. Spaw Editor
10. jHtmlArea
給我最好的那個讓我抄就好...

星期四, 4月 08, 2010

jQuery的mouse座標

沒想到jQuery對mouse event的x,y就有很好的支援...
我還在努力的用javascript在event.x ..........

在element上的mouseover或click
Mouse co-ordinates within the element when mouseover or click an element
Relative Mouse Position

星期四, 4月 01, 2010

web效率評估

yahoo訂出的14條規則
  1. Make Fewer HTTP Requests
  2. Use a Content Delivery Network
  3. Add an Expires Header
  4. Gzip Components
  5. Put CSS at the Top
  6. Move Scripts to the Bottom
  7. Avoid CSS Expressions
  8. Make JavaScript and CSS External
  9. Reduce DNS Lookups
  10. Minify JavaScript
  11. Avoid Redirects
  12. Remove Duplicate Scripts
  13. Configure ETags
  14. Make Ajax Cacheable
還出firefox的評估外套
Yahoo! YSlow
http://developer.yahoo.com/yslow/


不要讓 JavaScript 拉長你網站的反應時間

Ruby

thread, fiber, continuation
  • thread
差不多...
不過可直接用...如程式中直接sleep...
不用透過thread去start
<code> while true do
    sleep 1;
    puts "take a break" //我沒有廣告嫌疑....
 end</code>
  • fiber
比較好的說法 協同常式 (coroutin)
我... 還是直接看範例吧
<code>f=Fiber.new{
puts "Fiber says Hello"
Fiber.yield
puts "Fiber says Goodbye"
}
puts "Caller says Hello"
f.resume
puts "Caller says Goodbye"
f.resume</code>
Output
Caller says Hello
Fiber says Hello
Caller says Goodbye
Fiber says Goodbye
reference: The Ruby Programmikng Language
  • continuation
類似basic的goto...其他的不想知道了

方法、proc、lambda與colsure

反射 reflection
延續伺服器 continuation server
<code>def loop
 for i in 1..5 do
  puts i
  callcc {|continualtion| return continuation} if i= =3
 end # cont.call returns here
 return nil
end
puts "Before loop call"
cont=loop()
puts "After loop call"
cont.call if cont
puts "After continuation call"</code>
結果
Before loop call
1
2
After loop call
3
4
5
After loop call
After continuation call

何時用
多部電腦之間同步的「請求 - 回應」溝通時
主線需暫停控制權,直到遠端系統回應之後再繼續
=>方便解決Http是stateless問題,不需用到session
ex. seaside web framework

看不懂說什麼嗎...
我也看不懂...


星期六, 3月 27, 2010

dokuwiki

看大家推薦dokuwiki好用,而且新增套件很方便
就來安裝一下吧
官網:http://www.dokuwiki.org/

1.下載
實際操作一下 還真的很方便
直接給套件下載位置 ... download就完成了
wget http://www.splitbrain.org/_media/projects/dokuwiki/dokuwiki-2011-05-25a.tgz

2.安裝
tar zxvf dokuwiki-2011-05-25a.tgz
mv dokuwiki-2011-05-25a /var/www/html/doku


3.設定權限
太多了,所以用browser開啟 http://xxxxx/doku/install.php
會出現權限有問題的資料夾及檔案
到dokuwiki的安裝目錄一個個設定
  • dokuwiki/data
  • dokuwiki/lib/plugins
及之下的file權限也都改成777
應該就可以了
否則會出現新增失敗問題
There was a file copy error while attempting to install files for plugin
... the disk could be full or file access permissions may be incorrect xx

外掛篇
  1. 將內容做成線上投影片(deckjs)
    wow, 這真是好東西,拿來當週報報告還挺不錯的
    裝好後,只要在該頁加上
    ~~DECKJS~~
    就會在畫面出現個icon, 點開就會有投影片的效果
    真是好東西
    DokuWiki + Deck.js 打造超快速簡報發佈工具


References

DokuWiki Plugin 精選

MoinMoin、PmWiki和DokuWiki editor比較

星期六, 3月 20, 2010

Apache整合Tomcat

整合Tomcat 5.x
Linux下Apache與Tomcat整合的簡單方法

整合Tomcat 6.x
1.下載相關檔案
The Apache Tomcat Connector 隨意下載個mod_jk+版本號.so

2.so檔放到apache/modules文件夾裡面
3.修改apache/conf/httpd.conf 文件
...
還是看別人寫好的吧...

Reference
Apache 2.2 + Tomcat 6.0 + MySQL 5.0 + mod_jk 整合
apache tomcat6整合域名直接訪問
window 系統下 apache 2.2.6 + tomcat 6.0 整合工作配置

星期四, 3月 11, 2010

案例圖

目的:滿足系統外部的參與者對系統的某種預期
一個使用案例代表使用者在完成該期望後,就可以離開系統

界限(Boundary)
明確表達系統該關心與不應關心的部份

Reference
UML團隊開發流程與管理

UML應用時機

from UML團隊開發流程與管理

Ch2.企業流程與系統需求 (活動圖、案例圖)
1.瞭解企業流程
ex.記錄現在流程,如SOP
利用活動圖記錄大流程,幫助瞭解

2.取得系統需求
ex.使用者的需求
利用案例圖記錄大方向的系求需求,重心放在該功能需求的描述上
注意不是開發者想提供的功能
-利用使用者易理解的字眼來描述某功能需求
-描述是「目的性」,而非「操作性」
-明確指出相關人員及系統

Ch3.表達系統內部的結構
(類別圖、循序圖、溝通圖)
3.記錄關係
利用類別圖建立通盤性的瞭解

4.記錄流程
利用循序圖說明案例的流程中物件間的互動關係
溝通圖呈現物件結構與合作關係

Ch4.系統的微觀設計 (物件圖、狀態機圖、時序圖)
5.記錄特定時間點中,所有物件在系統的結構,如同某時間點的「快照」
ex.住院事件發生,有病人物件、主治醫生物件、住院醫生物件…
物件圖

6.有複雜的狀態轉換時
ex.病床需為empty才能住
利用狀態機圖描述狀態轉換的機制

7.超過特定時間,要改變狀態
ex.ATM操作
利用時序圖

Ch5.表達系統的鉅觀設計 (套件圖、互動概觀圖、複合結構圖)

活動圖

主要目的:陳述活動與活動之間的流程控制的轉移

適合用在描述企業的本質性的工作流程(Essential Workflow)
盡可能把「中介產出文件」(抱括表單、報表等)排除在外
不要落入活動的細節,需要的是整體業務流程的「大方向」
過早介入流程細節,需求收集容易陷入分析癱瘓陷阱

誤解
誤認活動圖中的活動是可以「共用」
因此想將相關活動併成一張活動圖使用
這會喪失活動圖的易讀性,也無法可顯「共用」的精神

資源的共用性很難透過活動圖來表達
活動圖的目的在表達流程的完整性,而非表達資源的共用價值
重點:活動是沒有共用性
繪製活動圖時,比較不容易綁手綁腳

設計原則
-目的在表達「流程完整性」,而非活動細節
-元素(主要是活動)不要考慮共用的議題
-繪製了「分派點」,則一定有個「會合點」
-盡量不要表達「文件」或是「資料」

Reference
UML團隊開發流程與管理

星期一, 3月 01, 2010

安裝JIRA跟Confluence

公司要建立issus tracking及KMS
被指派裝JIRA跟confluence
那就來吧...

安裝JIRA
1.設定jira.home
<install-dir>/WEB-INF/classes/jira-application.properties
就是儲放記錄的資料夾

2.啟動jira
到<install-dir>
下bin/startup.sh


有兩種裝法 一個是standalone版(包了Tomcat),一個WAR-EAR(要架在tomcat下)
1.JIRA Installation 官方教學
2.Linux下JIRA的安裝配置 //安裝standalone
*linux下的standalone不用裝tomcat
一時裝太快 把tomcat也建好了... (裝聰明)


安裝Confluence
一樣有standalone版跟WAR-EAR,一般會將Confluence跟Jira結合
1.Confluence Installation Guide 官方教學
2.如何將Confluence和JIRA standalone安裝到一起 window版
3.testlink+jira+confluence安裝 linux版
4.JIRA與Confluence的安裝與集成(1)
*設定confluence.home
就是儲放記錄的資料夾

注意事項
1.設定環境變數
export JRE_HOME=/usr/java/jdk1.6.0_18/jre
export JAVA_HOME=/usr/java/jdk1.6.0_18
CATALINA_HOME=/opt/apache-tomcat-6.0.24
CLASSPATH=$CATALINA_HOME/common/lib/servlet.jar
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$CLASSPATH
PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH



2.設mysql connector
將使用mysql的驅動mysql-connector-java-5.0.3-bin.jar 放到/usr/local/jira/common/lib
一般的文檔都說放到這裡,但是後來發現應該放到/usr/local/jira/server/lib下


改DataBase
也有預設的db -HSQLDB
讓新手無痛安裝
不過建議指定其他的db
* SQL Server 2005
* SQL Server 2008
* MySQL
* PostgreSQL
* Oracle
* HSQLDB

錯誤
用jira發mail出現javax.mail.AuthenticationFailedException
=>mail設定錯了....一般是寄送的帳號或密碼打錯

星期四, 2月 25, 2010

委派時機

雖然知道delegate
但要說使用時機..還真不知什麼時候用

委派有用的時機:

* 當單一方法被呼叫。
* 當一個類別可能想要有該方法規格的多個實作。
* 當想要允許使用靜態方法來實作規格。
* 當想要事件形式的設計模式 (如需詳細資訊,請參閱事件教學課程)。
* 當呼叫者不需要知道或取得定義方法所在的物件。
* 當實作的提供者只想要將規格的實作「提供」給少數選取的元件。
* 當想要易於撰寫。

介面有用的時機:

* 當規格定義了一組會被呼叫的相關方法。
* 當類別通常只實作規格一次。
* 當介面的呼叫者想要轉換成或從介面型別上取得其他介面或類別。


Reference
委派教學課程

ajax跨Domain安全性問題

利用jQuery做ajax時
發現跨Domain時 會出現ajax error
查了一下才發現原來跨domain會有安全性的問題

AJAX的限制
  • 不能存取用戶端的任何檔案。
    ajax.open('GET', 'file://c:\\\\hello.html', ture); //錯誤
  • 不能存取不同來源位置的檔案 也就是網域(Domain)要相同
    更多解釋
Solution 利用JSONP來代替JSON.
  1. .client.html設定
    $.ajax({
      url: 'http://192.168.1.228/~kevyu/Testing/test.php',
      dataType: 'jsonp',                //1.將dataType定為jsonp
      jsonp: 'getAjaxData',
      data: {  callback: 'getAjaxData'}, //2.定義callback function
      error: function(xhr) {
        alert('Ajax request 發生錯誤');
      }
    });
    //3.這裡就是callback
    function getAjaxData(data){
       //alert(data);
       //alert(data.name);
    }

    新做法
    簡單多了,連callback function都不用設定
    最後加上callback=?,就這麼簡單,連jsonp都不用設
    $.ajax('returnJSON.php?callback=?', function(json) {
      //...
    }); 
  2. server.php設定
    還需server端配合,呼叫callback的function及回傳的parameter
    • 回字串
      <?php
        echo $_GET['callback']."('kevyu');"; //依callback的function名回傳kevyu字串
      ?>
    • 回json
      <?php
        $data = array("name"=>"kevyu", "gender"=>"male"  );
        $json=json_encode($data ); //編成json格式
        echo $_GET['callback']."({$json});"; //因為是json,所以要加"{ }"
      ?>

References
1.AJAX的安全性問題[筆記]
2.jQuery.ajax() 的 callback
3.Remote JSON - JSONP
1.用英文學英文
-發音
-文法 => 習慣 ex.常用字常不同,易分辯
-文化 (無相對字詞,就不要硬翻)

2.單字 (利用發音記)
-基本字 (1500~3000字)
-靠例句加深
-大量閱讀 500~1000字文章
查keyword
不查=>猜,畫線保留

Reading
速讀
1.強迫500字20秒
*不是讀,抓重點
2.計時(加強注意力)
閱讀=>將一個字一個字唸改成看,不是讀

1.讀句=>讀動詞
2.文章結構
首段 最後兩句是主題句
敘述 第一句
結論 第一句
1.這些是重點,有單字需要查才查,因為是keyword
2.或是重覆出現的字

星期一, 2月 22, 2010

檢查網路連線

You can check for a network connection in .NET 2.0 using GetIsNetworkAvailable():

System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()

To monitor changes in IP address or changes in network availability use the events from the NetworkChange class:

System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged
System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged


Reference
How do I check for a network connection

星期四, 2月 11, 2010

常用註冊值

更改windows授權的使用者名稱及組織名稱
利用ghostxp重灌後 開發的產品都是ghost的名字...
這東西釋出去好不太好看...
找了一下 還挺簡單的...
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\下的
RegisteredOwner //更改使用者名稱
RegisteredOrganization //更改組織名稱

第一隻ROR

照Agile Web Development with Rails寫的第一個範例
在這此抓出重要用到的指令









1.Build Project
rails demo //建立demo專案
cd demo


2.啟動server
ruby script/server //啟動server
//到http://localhost:3000下,檢查是否有啟動
//沒問題就可先關掉,準備coding


3.建立controller
ruby script/generate Controller Say
瞭解一下MVC架構 p29

4.建templete


...待續

星期三, 2月 10, 2010

利用scaffold做資料庫應用

天啊.遇到太多問題了
因為rails升到2.0有些語法不一樣
看書寫不出來,上網查才知道語法有不同了
而rails db:migrate又需與database溝通
所以事前也得先設定好...
練習第一個saffold做資料庫 還沒感受到 就先覺得好辛苦
不寫下來將來換個環境一定又忘了...
不過設定完... 還真的挺開心的 沒寫到任何sql所有欄位的新增、修改都做好了...
人說「頭過身就過」 希望接下來的路順一點...

建立專案
rails demo -d mysql //指定db可順便改好database.yml
1.設定資料庫
問題:解決rails的sqlite3.dll錯誤
沒有sqlite的dll是做呼叫sqlite的function...

問題:缺mysql
看範示的console畫面還想說~
哇~~跟mysql都整合在一起來
原來還是得自己先建立mysql環境
下載安裝mysql吧




2.scaffold
設定好資料庫就是來用scaffold
因為升級到rails 2的關係 所以下的參數會不一樣
1.0:ruby script/generate scaffold Movie Admin //直接指向Admin
2.0:ruby script/generate scaffold Movie title:string description:text one_sheet_url:string

Rails 2.0 scaffolding step by step.

3.rake db:migrate
這一步會遇到以下的問題
問題:syntax error on line xxx
一般來說是database.yml的設定出錯
冒號後面一定要有一個空白,否則會出錯!!
adapter: mysql
...
username:root <= 冒號後要空隔,不然會說argument錯誤

MySql問題
1.權限問題
解法:當然就要開放權限啦,另外注意不能用root

2.Commands out of sync; you can't run this command now: SHOW TABLES
-Mysql::Error: Commands out of sync; you can't run this command now: SHOW TABLES解决方案
-Rails2.1.0出现的问题undefined method `each' for
解法:從mysql/bin/目錄下找出libmySQL.dll,再copy到ruby/bin
*有時一樣會失敗,請注意抓的libmySQL.dll是跟MySQL server版本相同
我就抓了5.1.43的dll,連5.0.45... 問題一樣...硬是從5.0.45找出dll才pass


其他參考
第一個資料庫應用(with scaffold)--Ruby on Rails 完全新手手冊

星期日, 2月 07, 2010

來吧... Ruby

躲不掉的...
快讀吧...
先來名詞解釋

  • Ruby
    • 一種程式語言,如同C,Java
    • 所以不是只能寫網頁
    • 物件導向,類似Perl, Smalltalk, Python, Lisp
  • Rails-Web application framework
    • 用Ruby寫的
    • MVC架構
    • 利用convention替代掉大部份的設定
  • Active Record
    • Rails的ORM名稱
    • 與一般ORM不同的是Active Record利用convention替代掉大部份的設定
Ruby新手入門
Rails新手入門
第一隻ROR
不多說
直接看別人教學
實際做一次就會了
1.Ruby on Rails(Windows),從安裝到 Helloworld 2009/02 update
先簡單的做出Helooworld,不過重點在下一篇的scaffold
2.第一個資料庫應用(with scaffold)--Ruby on Rails 完全新手手冊
用scaffold才會感覺到ROR的方便,直接看Agile Web Development with Rails做範例感受更深,不過版本要看對...不然開發會很想打人

實際開發
遇到太多問題了...
自己也寫了一篇 第一隻ROR

討論
從 Django 看 Ruby on Rails 成功的原因

--------------------------------------
Reference
教學資源
安裝、應用
1.Ruby on Rails (ROR)入門第一站,InstantRails安裝圖文教學
2.在 Ubuntu 下部屬 RoR 環境


教學
1.ROR 的新手建議書單 from xdite
2.Ruby & Rails on Rails 進階書單
3.幾本不錯的Ruby和Ruby On Rails電子書下載
4.Top 13 Ruby on Rails Presentations
有書.... 就有電子書....
有電子書就...不用花錢買了... XD ...

Aptana IDE
官網:radrails
1.Get Rolling with Ruby on Rails in RadRails //標題還挺有趣的
2.5分鐘RadRails錄影教學

社群討論區,Blog
Ruby Taiwan 台灣的 Ruby 社群。
RailsFun!! Rails 討論區

Blog
Lighty RoR 介紹 Ruby,Ruby on Rails,JRuby
xdite

星期六, 2月 06, 2010

編輯Windows右鍵選單

常要開「裝置管理員」看USB有沒有連結
用regedit在「我的電腦」右鍵選單增加「裝置管理員」
出現「MMC無法開啟」...
"銀"了很久 一直沒處理
今天總算狠下心google找到解決方法了

@="裝置管理員"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\shell\DevMgr\command]
"mmc.exe %%systemroot%%\\SYSTEM32\\devmgmt.msc"
改成"mmc.exe devmgmt.msc"



Reference:
用Reg在「我的電腦」右鍵增加「裝置管理員」、「服務」會出現MMC無法開啟的看這裡

星期五, 2月 05, 2010

InstallShield中 變更資料夾路徑的方法

OS:XP
InstallShield版本:2010

建立專案時
在Installation Design/Application Data/Files And Folders
將要封裝的Source資料夾"拉進"Destination資料夾
=>Sourece的路徑為D:\test (將test資料夾全部安裝到使用者的電腦)

後來想移動test資料夾至D:\Project\test,
因此Soure的路徑就需要更動,但找不到任何設定可以更動
惟一想到的方法就是刪掉舊的資料夾 再重新拉進
只是在Installation Design/Organization/Components 裡
已經為每個不同的資料夾取命了...
如此一來便得再重新命名...

後來跟原廠詢問
原來所有的變數路徑都儲放在Media / Path 下
也就是說在這裡就可以設定路徑了...

Sql字串有特殊符號

當字串裡有單引號如"It's good",或其他特殊符號時
Sql命令都會掛掉...
解決方法
1.在特殊符號前加入 \
"It's good"=>"It\'s good"
*透過mysqlconnector會發生錯誤...改用法2就沒問題了

2.遇單引號可再一個單引號
"It's good"=>"It''s good"

php可用直接呼叫
1.mysql_escape_string
2.mysql_real_escape_string
3.addslashes
至於差別...有看沒有懂...

星期日, 1月 31, 2010

日文學習

五十音還真不好背
背了一個忘一個
上網查五十音表時 看五十音平假名五十音片假名的由來
日文本來就是漢字去改的
利用一些字型和國、台發音 還挺好記..
現在都已經把五十音給背起來的 真是不錯的東西

看了五十音表 都是寫好的字
不知道筆劃,不會寫,寫了都怪怪的
五十音平假名書筆劃

背起來後還有小遊戲可以挑戰
類似以前學輸入法玩的小遊戲...叫什麼都忘了 哈

星期四, 1月 21, 2010

到底啥係native,strictfp,transient,volatile

雖然考過SCJP都不知道幾年了
不過要我解釋native,strictfp,transient,volatile
還是支支吾吾說不出來
下定決心要看懂這四大天"字"是什麼意思

1. native
簡單講,呼叫其他語言(c,c++之類)做出來的dll
做法
1.利用java做個介面供其他語言實作(也就是宣告成native)
2.用javah產出.h;
3.用其他語言實現native方法
4.編譯成dll
5.在Java中,再用System.loadLibrary()方法讀dll,就成功啦

還是看原作的範例比較快
認識理解Java中native方法

2. strictfp
意思是FP-strict,精確浮點,符合IEEE-754規範的,那為什麼不一開始就符合規範咧?
看wiki是這麼說地
In older JVMs, floating-point calculations were always strict floating-point, meaning all values used during floating-point calculations are made in the IEEE-standard float or double sizes. This could sometimes result in a numeric overflow or underflow in the middle of a calculation, even if the end result would be a valid number.

3.transient
為了避免把password等之類機密的資料序列化儲在永久媒體(如硬碟)
因此只要將該變數宣告為transient,就會禁止此變數被序列化
用過hibernate後,就更能瞭解是什麼了


4. volatile
每次被thread執行時,都強迫重讀宣告為volatile的變數。
什麼意思咧?如同synchronized鎖定function的意思一樣,而volatile可直接對特定變數
看volatile的例子

嗯 要尊重原作 我就不再copy-paste了
其實是懶得貼 哈

不過~~總算都懂了...ya~~

Reference
認識理解Java中native方法
Java關鍵字之native,strictfp,transient,volatile

星期二, 1月 19, 2010

jQuery 1.4出來囉

1月14是jQuery的四歲生日...所以出了1.4版
除了新方法外 還重寫了一些增強即有的功能

新功能
.delay()
太酷了...
/*二個div同時向上縮,first div先等個800毫秒
*這時second先淡入,再400ms後first div才淡入
*/
$("div.first").slideUp(300).delay(800).fadeIn(400);
$("div.second").slideUp(300).fadeIn(400);


舊function增加
.addClass()
function(index, class)A function returning one or more space-separated class names to be added. Receives the index position of the element in the set and the old class value as arguments.
//可以一次加多個class,或移除
$('p').addClass('myClass yourClass');
$('p').removeClass('myClass noClass').addClass('yourClass');

//還有更酷的 呼叫addClass時,動態加入class name
//就是Function Settter厲害的地方,其他.css(),.attr(), .val(), .html(), .text(), .append(), .prepend() ...也都有支援
$('ul li:last').addClass(function() {
return 'item-' + $(this).index();
});


jQuery.param()
直接將array轉成url參數格式

/*jQuery.param( obj ) 1.2
*jQuery.param( obj, traditional ) 1.4
*objAn array or object to serialize.
*traditionalA Boolean indicating whether to perform a traditional "shallow" *serialization.
*/
var myObject = {
a: {
one: 1,
two: 2,
three: 3
},
b: [1,2,3]
};
var shallowEncoded = $.param(myObject, true);
var shallowDecoded = decodeURIComponent(shallowEncoded);
--
a=%5Bobject+Object%5D&b=1&b=2&b=3
a=[object+Object]&b=1&b=2&b=3


寫到一半....
還是看別人整理好的比較快....
懶得寫了...

reference
New or Changed in 1.4
jQuery 1.4官方文檔中文版發佈
jQuery 1.4 小閱兵

星期一, 1月 04, 2010

書 - 完美程式設計指南

Ch2 自我維護
程式釋出前都要做unit test,即使是只改一點點

測試人員存在的目的是找尋程式員沒找到的錯誤,寫程式的人應該自己找尋自己製造的臭蟲。

coding時
1.用防禦性程式寫作,但別隱藏錯誤(bug)
2.加上除錯檢查(ex:assert) - 印出錯誤方便debug

*維護程式的發行版跟除錯版。發行版用來打包發行,除錯版用來盡可能快速抓蟲。
*除錯檢查巨集是寫出除錯檢查的快速方式。用它們來捕捉不應該發生的非法狀況。不要把這些狀況跟錯誤狀況混在一起;錯誤狀況在最後的產品中一定得被處理掉。
*用除錯檢查巨集來核對函式參數,並警告程式原有東西是未定義的。你愈嚴格定義你的函式,核對它的參數就愈簡單。
*一旦你寫好了一個函式,把它重新檢查一遍,並問問你自己,"我假設了什麼條件一定成立的嗎?"如果你找到一個假設條件,用除錯檢查巨集檢查這條件是否永遠成立,或者重寫程式以去除這樣的假設。也問問自己,"程式中哪裡最可能出錯,我怎樣才能自動找到錯誤?"盡可能將捕捉錯誤的測試放在愈早執行到的地方愈好。
*教科書鼓勵程式員防禦性的寫程式,可是記住這種寫作方式會隱藏錯誤。當你寫出防禦性的程式時,用除錯檢查巨集來提醒你自己是否有"不可能"發生的狀況發生了。

Ch3 增強子系統
檢查你的子系統,問問你自己,程式員們可能會怎麼誤用它。加上除錯維護敘述跟核對檢查來捕捉不好找跟常見的錯誤。

如果你不重複找尋,就修不好錯誤。找尋任何可能造成隨機行為的東西,把它們從除錯版程式中拿掉。將未初始化的記憶體以某個垃圾值填滿只是一種去除隨機行為的辦法,那樣子如果有參考到未初始化記憶體的情形發生,你就可以在每次執行到出錯的程式時都能重複同樣的現象。

如果你的子系統釋放記憶體(或其他資源)然後製造垃圾,請清理被釋放的記憶體中的內容,讓裡頭的東西看起來像垃圾;不然別處的程式可能會繼續使用這些已釋放記憶體中的東西而不被察覺。

類似的,如果你的子系統有些可能會發生卻不一定發生的行為,加上除錯碼來確定這些行為一定會發生。讓每件事都發生過可以增進你捕捉到較少執行到的程式中出現的怪異現象。

確定你的測試工作在程式員沒注意到時都在進行著。最佳的測試方式就是那些完全不用在乎它們的存在的測試。

如果可能,將測試碼建立在子系統裡頭,而不要寫在它們上頭。不要等到子系統已經寫好了,才來想辦法查對它們的動作正不正確。對每個你考慮的設計方式,問問你自己,"我該怎樣徹底查對這個實作?"如果你發現幾乎不可能或難於測試這個實作方式,好好考慮一下是不是該換個設計方式,即使那表示拿程式大小跟執行速度為代價來讓系統可被測試。26

在拿掉一個讓程式跑得很慢或吃很多記憶體的查核測試前,多想一遍。記住,查核程式碼不會出現在發行版的程式裡。如果你發現自己想著,"這些測試太慢了(或太大了)",停下來,問問自己,"我該怎樣讓這些測試繼續留著,而讓程式跑快一點(或變小一點)?"

星期日, 1月 03, 2010

Python開發

什麼是Python? Why Python?
* Python基礎教學
* Python入門教學
* Python進階教學
* Python程式範例
* Twisted教學
* TurboGears教學
* Eclipse 的 Pydev IDE教學

這裡有教學
從基礎到進階都有 真不錯
版主真有心
連Eclipse的安裝都有了
而且是圖文教學 「足感心ㄟ」

星期三, 12月 30, 2009

餐廳列表

每次想吃什麼都想不到
事後想起才覺得可惜 忘了這間
先寫好 以便日後查詢...改名叫"魚乾的美食筆記本"好了

台北
墨西哥料理

佬墨日出-Tequila Sunrise
墨西哥餐飲美味道地,經典的仙格麗亞,順口的瑪格麗特,香脆玉米片搭配勁辣爽口瀟灑醬


義大利麵

La Pasta

中式熱炒
新東南活海鮮料理
鮮納肚~100元快炒店(東區)

星期三, 12月 16, 2009

Facebook 二三事

FBML
json_encode問題~ php有些版本不支援
但只要引用facebook.php 就會有了
require_once 'facebook.php';

FBJS
當只有script時,一定要有個內文,script才會執行
echo "test
<script> function go(){
//xxx
}
go();
</script>";


showPermissionDialog說有ondone,但加了會掛...拿掉反而可以執行..怪
Facebook.showPermissionDialog('publish_stream');

星期一, 12月 07, 2009

Refactoring: Impoving The Design of Existing Code

中譯:重構-改善既有程式的設計

前言

古老的工程諺語:「如果它還能執行,就不要動它」
 但專案功能不斷修改程碼,使原先系統結構逐漸衺弱,程式碼也更加複雜,無法除錯,也無法獲得可被接受的性能/效率
最後重新編寫整個系統,作者指出堅持以持續不斷的重構行為是成功專案的重要角色

重構:「在不改變程式碼外在行為的前提下,對程式碼做出修改,以改進程式的內部結構」

軟體會慢慢腐爛
 重構的步驟只要把某欄位(field)從一個class移到另一個class,把某段程式碼從method拉出成另一個method,或是在class hierarchy中把某些程式碼推上推下就行了,聚沙成塔,小小的修改累積就可以改善設計品質,這和「軟體會慢慢腐爛」的觀點恰恰相反

Ch1 Refactoring, a First Example

分解並重組method
案例中的錄影帶出租statement()做太多事,程式碼太長,可以其目的拆成至不同的class
每個method的程式碼越少越容易維護,且拆成 更多的method更容易reuse(copy-paste相同的程式碼,常發生改了a method忘了改相同容內的b method)
重構技術係以微小的步伐修改程式。改錯時,很容易發現它

更改變數是值得的行為嗎?(p.15)
好的程式碼應清楚表達自己的功能,變數名稱是程式碼清晰的關鍵
任何一個傻瓜都能寫出計算機可以理解的程式碼。唯有寫出人類容易理解的程式碼,才是優秀的程式員


Replace Temp with Query(p.21)
int thisAmount => each.getCharge()
儘量除去暫時變數,暫時變數會導致大量參數被傳來傳去。也很容易失去蹤跡=>相對要付出效率上的代價,但可由最佳化來調整(細節p.69)

運用多型取代與價格相關的條件邏輯(p.34)
=>引用State pattern
在父類別宣告abstract int getPriceCode(),讓子類別實作其條件,使其有自己的計費法
*另外邏輯判斷也該在物件本身的class(指switch(getMovie().getPriceCode())=>應在class movie裡寫switch (getPriceCode())
當有傳入值有可能有變化時,選擇可能變化小的,折起的side effect也較小
=>引用State pattern的重點在「修改與價格有關的行為」,或「新增定價標準」會較容易

Ch2 Principles in Refactoring

為何重構
-改進軟體設計=>消除duplicate code
-使軟體更易被理解
-助找到bugs=>程式碼易於理解,而不是從一個500行的method找

何時重構 The Rule of Three (p.58)
1.反感,第三次又做類似的事就該重構
2.添加功能時
3.修補錯誤時
4.code review時

Ch3 Bad smells in Code

何時重構、何時停止及重構的機制
1.Duplicated Code p.76
2.Long Method p.76
3.Large Class p.78
class太大,instance變數就會多,Duplicated Code也接腫而至
4.Long Parameter List p.78
5.Divergent Change(發散式變化) p.79
隨外界變化而有所修改,找出原因運幅Extract Clss提煉到另一個class
6.Shotgun Surgery(霰彈式修改) p.80
每遇修改就得在不同的classes內做小修改
7.Feature Envy(依戀情結)
某method內呼叫該class幾乎半打的getting method
8.Data Clumps
每次都會同時出現的幾個field
9.Primitive Obsession
日期年月日,3個int不如定義成object
原則
應放在一起的fields =>Extract Class
參數列中有基本型資料=>Introduce Parameter Object
從array挑資料 =>Replace Array with Object
10.Switch Statements

星期五, 11月 27, 2009

軟體工程

物件導向

物件導向程式的九個體操練習
by ihower
遵守九條規則,改善OO實作能力

測試
為什麼要寫 unit test?為什麼要先寫測試?
TDD 推廣:背景知識和簡介

看來還有很多東西要學習...加油...

星期四, 11月 26, 2009

INF檔結構

INF是Device INFormation File的英文縮寫

編寫規則

*規則一:INF文件是分節的,每一個INF文件有許多的節組成,節名用方括號括起來。
*規則二:在節與節之間的內容叫條目,每一個節又是由許多的條目組成的,每一個條目都是由形如「signature="$CHICAGO$"」的形式組成的。如果每一個條目的等號後有多個值,則每一個值之間用「,」號分隔開。
  
*規則三:INF文件對大小寫不敏感。  
*規則四:「;」號後面的內容為註釋。
*規則五:如果一個條目的內容過多,在一行無法書寫完全,則用「\」將一行內容書寫為多行。

百度Inf

星期日, 11月 22, 2009

資料庫索引

設計準則(減少IO存取次數)
 1.經常被用來搜尋資料記錄的欄位
 2.Primary key(sqlserver自動建立)
 3.套用unique限制條件的欄位(sqlserver自動建立)
 4.Foreign key定義作為外部索引鍵欄位?
 5.於查詢中被用來連結資料表的欄位
 6.用來作排序基準的欄位
  -不要替超過20bytes的欄位作索引(索引體佔太多空間 ex.地址)
  -很少變動,經幣被查詢
 7.索引需維設,減少使用頻率低的索引,以免耗維護成本
 8.內容重複率高的欄位效益低
 9.資料記錄多,存取效率才會明顯,反過來說少反而慢(path)
  -利用query analyzer執行,檢視execution plan與執行時間來測
  -不斷嚐試、不停修正

索引的類型
 1.Clustered Index(簇集索引) -範圍(日期,編號)
 改變資料表記錄存放次序,並與簇集索引中錄值次序相同
  -ex. between 100 and 200=>以昇冪來排就直接抓出其間的100筆
  每個table只能有一個clustered index

 2.NonClustered index(非簇集索引) -特定值(姓名,電話)

星期五, 10月 30, 2009

要先引用幾個COM元件
查了一下還真麻煩
後來發現直接引進Microsoft Excel 11 Object就會自動帶入其他的COM

[C# .Net] Microsoft.Office.Interop.Excel 讀 / 寫 Excel 語法概全

Reading and Writing Excel Spreadsheets Using ADO.NET C# DbProviderFactory

星期一, 10月 19, 2009

jQuery bind與live

要加event listener時,可用bind或live來綁event 究竟兩者差在哪邊 bind如下以綁drag事件
$(function(){
   $('.floatBox').bind('drag',function( event ){
       $( this ).css({
                       top: event.offsetY,
                       left: event.offsetX
       });
       //var pageCoords = "( " + e.pageX + ", " + e.pageY + " )";
       //var clientCoords = "( " + e.clientX + ", " + e.clientY + " )";
   }); 
});
將event在onload時,加入listener 可是當之後要動態加入時,後續加入的floatBox就不會有反應 因此得再bind的新的floatBox 這時就可以改用live,程式碼如下(只是把bind改用live) jQuery就會聰明的自己bind事件,真的是太神奇了
$(function(){
   $('.floatBox').live('drag',function( event ){
       $( this ).css({
                       top: event.offsetY,
                       left: event.offsetX
       });      
   }); 
});

不規則 Form 透背及拖曳

簡單方法 (只限24bit color以下)
//將form的透明鍵值設為一特定值
//方法1.圖中的10,10為透明鍵值
this.TransparencyKey = Img.GetPixel(10,10);

//方法2.直接指定顏色為透明鍵值
this.TransparencyKey = System.Drawing.Color.Transparent;//指定透明色
this.TransparencyKey = Color.Red; //或指定特定色

如此一來 圖中有該指定色 即會透明

如果放在panel裡,那panel也要設透背
在panel要設背景色,才會透到form上的顏色(當然...form也是透背...)
xxPanel.BackColor = System.Drawing.Color.Transparent;
這樣裡面的東西才會透背

WebBrowser透背
只要在form的屬性設TransparencyKey 為Transparent即可
剩下的當然是網頁裡的圖要去背

另一種方法-以圖去畫透背 ( 24bit Color 以上適用 )
先引用using System.Drawing.Drawing2D;
看source吧



--

假設標題列(pnlTitle)為拖曳
//全域變數
int nOldWndLeft;
int nOldWndTop;
int nClickX;
int nClickY;
...

#region "GUI event"
//滑鼠按下的事件
private void pnlTitle_MouseDown(object sender, MouseEventArgs e)
{
nOldWndLeft = this.Left;
nOldWndTop = this.Top;
nClickX = e.X;
nClickY = e.Y;
}

//滑鼠拖曳事件
private void pnlTitle_MouseMove(object sender, MouseEventArgs e)
{
if (pnlTitle.Capture == true) //如果滑鼠按著拖曳
{
//'設定新的視窗位置
this.Top = e.Y + nOldWndTop - nClickY;
this.Left = e.X + nOldWndLeft - nClickX;
//更新紀錄的視窗位置
nOldWndLeft = this.Left;
nOldWndTop = this.Top;
}
}
#endregion



form在拖拉時會產生閃爍問題
//建構子裡
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
SetStyle(ControlStyles.DoubleBuffer, true); // 雙緩衝


source:
C#製作不規則窗口 ( 24bit Color 以上適用 )

星期五, 10月 16, 2009

facebook DataStoreAdmin怎麼搞

利用facebook的object data要來存資料
什麼type,又property看了半天都看不懂
努力查資料加亂測總算試出來了
如果把object data看成database(object)

A.建立Table
相關API: Object Data Definition API
1.Object Type:就是table(class) 原文:object type is like a "table" in SQL terminology, or a "class" in object-oriented programming concept
2.Object Properties:就是DB中的Column(或物件中屬性)

B.新增、刪除、修改資料
相關API:Object Data AccessAPI
想說總算會依樣畫葫蘆了
本能反應的用FQL來insert... 居然失敗了...
又花了點時間才發知道不是這簡單...

1.新增
搞了好久... 原來要create...
所以還是別以talbe的觀念來做 不然要想好久..
不過create完...讓我在想是只存在記憶體...重開就沒了嗎
$result=api_client->data_createObject("tablename",array('name'=>123,'tel'='123456')); //回傳即$obj_id
2.修改
api_client->data_updateObject($obj_id,$properties,$replace)

利用DataStoreAdmin來建立table
建了半天也建不出來,才發現只能用小寫,
有大寫字也沒說失敗 就改半天不知是怎樣
而且改成功沒有新增的或修改過的名稱不會馬上出現
要refresh過才會有

星期四, 10月 15, 2009

CSS去除連結虛線框,無法用輸入法,刪除,貼上

鏈結在focus後,會出現鏈結虛線


為了去除連結虛線框,會在CSS下以下語法
//css
a, input{
outline: none; /* for Firefox */
hlbr:expression(this.onFocus=this.blur()); /* for IE */
}


但利會造成輸入方塊(input type='text'),無法用輸入法、刪除、貼上
因為foucs就blur,所以無法鎖住在textbox上
就依樣畫葫蘆吧... 在textbox下void(0)...
//html
<input type="text" style="hlbr:expression(void(0));">

星期一, 9月 28, 2009

html做listbox單選

html做listbox很簡單,就select tag加個multiple屬性為true即可
但都mutiple了怎麼做單選... 好像在找碴
上網查一下 好像沒人做這麼無聊的事
但美工很機車... 只好自己來了 (johnny我恨你)
利用javascript動態讀一下

html
<select id="test1" multiple="true"> //設multiple為true
 //<option id='test1_opt1'>1</option>
 ...
 //就不多寫了,不過得先為option取可識別的名字
</select>


javascript ... 唔 其實是透過jquery
var lastSelectedID=-1;
$("select#test1").change(function(){
 var tmpLastSelectedID=-1;
 jQuery('option:selected', this).each(function(){
  //避開滑鼠直接選2個以上
  if(tmpLastSelectedID>0){
   $(this).attr("selected",false);
   return true;
  }

  //避開ctrl點選
  if (lastSelectedID==$(this).attr("id")){
   $(this).attr("selected",false);
   return true;
  }else{
   tmpLastSelectedID=id;
  }
 });
 lastSelectedID=tmpLastSelectedID;
});


p.s 不過避開滑鼠直接選2個以上還有問題 就是都是預設選到第一個

星期五, 9月 25, 2009

即刻提升jQuery性能的十个技巧[TUTS+]

1. 使用最新版本
2. 合併、最小化腳本
3. 用for替代each
4. 用ID替代class選擇器
5. 給選擇器指定前後文
6. 建立緩存
7. 避免DOM操作
8. 避免使用concat(),利用join()處理長字串
9. 返回false值
10. 利用小抄和參考文檔



英文 NetTut+:10 Ways to Instantly Increase Your jQuery Performance
中文翻譯:十种方式即刻提升您的jQuery代码性能[TUTS+]