1 開發環境技術:B/S(.NET C# )
2、Microsoft Visual Studio 2013 C#.NET
3、.NET Framework 4.0及以上 (支援最新4.5版本)
4、
SQL Server 2008 R2及以上 (支援2012/2014)框架特點
2 系統簡介
1、幫企業快速地實現各種通用功能,結合系統現有的通用權限管理功能。
2、快速地開發出各種項目應用系統。讓企業開發一個系統變得非常輕松。
3、符合RBAC 靈活不僅符合國際通用標準,又能滿足國內的大中小型軟件項目的靈活設置需求。
4、文檔齊全支持二次開發提供完善的接口函數調用說明、開放接口、開放源碼、開放
數據庫結構設計。
5、分層理念 SOA理念程序可以采用不同的實施策略、架構需求、方便維護、方便擴展。
6、有價值且優秀的產品,這樣您就有了市場需求了。
7、適用于OA、網站、電子政務、ERP、CRM等基于B/S架構的應用軟件系統的快速開發框架。
3 系統應用價值
避免重復開發,降低開發成本,權限模塊是每個應用系統的不可缺少的部分,但每個客戶對權限管理的需求卻不完全相同。 如果按需從頭分析和設計,必將造成重復開發。BPMS通用基本權限系統針對不同應用系統設計, 提供用戶、角色權限模塊的基礎框架和通用模型,幫助開發者快速實施和開發出符合不同需求的用戶權限管理模塊。 能夠最大程度降低開發
工作量,節約開發成本。
3.1 產品優點體系
1、通用權限管理系統其中最重要的思路就是把常用的模塊封裝成控件進行重復使用,一則可以避免重復開發,提高開發效率,它能縮短開發時間,減少代碼量,使開發者更專注于業務和服務端,輕松實現界面開發,帶來絕佳的用戶體驗,適用于OA、網站、電子政務、ERP、CRM等基于B/S架構的應用軟件系統的快速開發框架。
2、角色權限分配與用戶權限分配相結合,融合了角色的權限管理的統一便捷性和用戶權限分配的靈活性。
3、強大的數據權限管理,實現了單筆數據的權限分配。
4、細粒度的權限管控,權限分配能精確到界面上的每一個功能按鈕。
5、實現簡易的單點登錄功能,用戶只要記住一對用戶名密碼就可以。
6、多個管理系統可以用統一的一套后臺管理工具進行管理。
7、二次開發簡單,幾分鐘即可部署一個系統(快速、簡單、高效、安全、可靠)、編碼簡單易懂、注釋詳細。
3.2 全新的技術架構
1、本套框架涵蓋了ASP.NET4.0、ASP.NET MVC 5.0、WebAPI、WCF、WEB Pages、SignalR、WF、AJAX、EntityFramework、IOC、AOP和SSB等。解決在開發中經常用到的日志、緩存、異常、事務、多瀏覽器支持、通用權限、安全、加密解密、壓縮解壓。實現基于XML的動態配置,JS腳本、CSS樣式、圖片文件支持動態配置,解決通常用到的打印、報表、圖標、導入和導出等功能。
2、采用Ajax技術交互,帶來良好的用戶體驗。
3、界面簡潔大方,加載迅速。
4、結合CodeSmith代碼模板生成器快速開發系統、
5、瀏覽器支持:IE8、IE9、IE10、firefox 、Chrome、
360、 Safari、Opera、傲游、搜狗、世界之窗。
6、內置模塊 :基本權限關系系統,CRM、OA、進銷存和業務管理系統
7、采用 WEB FORM、MVC、SignalR和WebAPI同一ASP.NET的框架模式,具有耦合性低、重用性高、生命周期成本低、可維護性高、有利軟件工程化管理等優點
8、采用WebAPI,客戶端完全擺脫了代理和管道來直接進行交互
9、采用標準CSS前臺UI界面,可輕松的打造出功能豐富并且美觀的UI界面
10、數據訪問層采用強大的Ghd.Net Framework框架完美地支持數據庫操作
11、提供多種豐富的組件,封裝了一大部分比較實用的控件和組件,如自動完成控件、彈出控件、拼音模糊輸入控件、日期控件My97DatePicker、導出組件、Jquery、 AjaxToolkit、 AntiXss、 AspNetPage、 Dundas、 EnterpriseLib、 Grid++Report 5.0 、 JSON、 NPOI、 Quartz.Net、Telerik UI for ASP.NET AJAX 和 Telerik UI for ASP.NET MVC等。
3.3 高度可擴展性和靈活性
1、動態表單管理,靈活配置減少因需求變更帶來的開發工作。
3、系統菜單靈活配置,并和權限系統進行關聯。
3.4 豐富的系統功能
1、數據庫資源管理,不用登陸數據直接在頁面上進行數據庫管理、數據定時備份
2、操作日志生成
3、動態接口管理,動態配置WCF接口,無須開發實現即可提供WCF接口
4、系統訪問控件,限制指定IP對系統的訪問
3.5 優秀的用戶體驗
1、通用權限系統為最終用戶提供全可視化的操作界面,輕松管理維護用戶權限和用戶相關數據。
2、超高效配置系統,從新增應用系統到配置完成最快只需幾分鐘。
3、界面異步刷新,操作性能優秀,提供更佳的用戶體驗。
4、提供用戶數據圖表統計和操作日志。
4 功能描述
1.菜單導航管理
2.操作按鈕
3.角色管理
4.部門管理
5.用戶管理(用戶權限))
6.系統配置(動態配置系統參數)
7.系統日志(異常記錄)
8.數據庫備份/還原
9.數據回收站(業務功能刪除過數據,全部保留在回收站)
5 產品適用對象與用戶群體
1、大中小型軟件開發公司,技術支持、技術咨詢公司。
2、管理類軟件開發者。
3、想進一步提升自身技術能力的開發者、學生等。
4、培訓教程、大學課外、員工培訓。
5、政府機關、事業單位、集團公司。
6、企業、工廠等。
數據庫結構如下圖:
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
但是包嵌入到
Python中的只有輕量級數據庫SQLite,所以不用安裝SQLite數據庫操作包(但要安裝數據庫軟件, 此處我犯錯誤了)。其他的必須安裝。同時也要安裝數據庫軟件。
先講解下DB-API。因為數據庫類型實在太多太雜,所以就出現了SGI小組,為不同的數據庫提供一致的訪問接口即DB-API,可以在不同數據庫間快速移植代碼。
比如Python開發的MySQLdb遵從DB-API, 實現了connect(), connect.cursor()等方法...其他的db類也實現了同樣的方法,故可以很容易移植。
DB-API規范的屬性:
apilevel DB-API 模塊兼容的 DB-API 版本號
threadsafety 線程安全級別
paramstyle 該模塊支持的
SQL 語句參數風格
DB-API規范的方法:
connect() 連接函數,生成一個connect對象,以提供數據庫操作,同事函數參數也是固定好的
其中connect對象又有如下方法:
#所謂事務可以認為是一整套操作 只要有一處紕漏就廢
close():關閉此connect對象, 關閉后無法再進行操作,除非再次創建連接
commit():提交當前事務,如果是支持事務的數據庫執行增刪改后沒有commit則數據庫默認回滾,白操作了
rollback():取消當前事務
cursor():創建游標對象
其中cursor游標對象又有如下屬性和方法:
常用方法:
close():關閉此游標對象
fetchone():得到結果集的下一行
fetchmany([size = cursor.arraysize]):得到結果集的下幾行
fetchall():得到結果集中剩下的所有行
excute(sql[, args]):執行一個數據庫查詢或命令
excutemany(sql, args):執行多個數據庫查詢或命令
常用屬性:
connection:創建此游標對象的數據庫連接
arraysize:使用fetchmany()方法一次取出多少條記錄,默認為1
lastrowid:相當于PHP的last_inset_id()
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
前一段時間由于開題的事情一直耽擱了我搞
Linux的進度,搞的我之前學的東西都遺忘了,非常煩躁的說,如今抽個時間把之前所學的做個小節。
文章內容主要總結于《Linux程序設計第3版》。
1.Linux進程與線程
Linux進程創建一個新線程時,線程將擁有自己的棧(由于線程有自己的局部變量),但與它的創建者共享全局變量、文件描寫敘述符、信號句柄和當前文件夾狀態。
Linux通過fork創建子進程與創建線程之間是有差別的:fork創建出該進程的一份拷貝,這個新進程擁有自己的變量和自己的PID,它的時間調度是獨立的,它的運行差點兒全然獨立于父進程。
進程能夠看成一個資源的基本單位,而線程是程序調度的基本單位,一個進程內部的線程之間共享進程獲得的時間片。
2._REENTRANT宏
在一個多線程程序里,默認情況下,僅僅有一個errno變量供全部的線程共享。在一個線程準備獲取剛才的錯誤代碼時,該變量非常easy被還有一個線程中的函數調用所改變。相似的問題還存在于fputs之類的函數中,這些函數通經常使用一個單獨的全局性區域來緩存輸出數據。
為解決問題,須要使用可重入的例程??芍厝氪a能夠被多次調用而仍然
工作正常。編寫的多線程程序,通過定義宏_REENTRANT來告訴編譯器我們須要可重入功能,這個宏的定義必須出現于程序中的不論什么#include語句之前。
_REENTRANT為我們做三件事情,而且做的很優雅:
(1)它會對部分函數又一次定義它們的可安全重入的版本號,這些函數名字一般不會發生改變,僅僅是會在函數名后面加入_r字符串,如函數名gethostbyname變成gethostbyname_r。
?。?)stdio.h中原來以宏的形式實現的一些函數將變成可安全重入函數。
?。?)在error.h中定義的變量error如今將成為一個函數調用,它可以以一種安全的多線程方式來獲取真正的errno的值。
3.線程的基本函數
大多數pthread_XXX系列的函數在失敗時,并未遵循UNIX函數的慣例返回-1,這樣的情況在UNIX函數中屬于一少部分。假設調用成功,則返回值是0,假設失敗則返回錯誤代碼。
1).線程創建:
#include <pthread.h>
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
參數說明:
thread:指向pthread_create類型的指針,用于引用新創建的線程。
attr:用于設置線程的屬性,一般不須要特殊的屬性,所以能夠簡單地設置為NULL。
*(*start_routine)(void *):傳遞新線程所要運行的函數地址。
arg:新線程所要運行的函數的參數。
調用假設成功,則返回值是0,假設失敗則返回錯誤代碼。
2).線程終止
#include <pthread.h>
void pthread_exit(void *retval);
參數說明:
retval:返回指針,指向線程向要返回的某個對象。
線程通過調用pthread_exit函數終止運行,并返回一個指向某對象的指針。注意:絕不能用它返回一個指向局部變量的指針,由于線程調用該函數后,這個局部變量就不存在了,這將引起嚴重的程序漏洞。
3).線程同步
#include <pthread.h>
int pthread_join(pthread_t th, void **thread_return);
參數說明:
th:將要等待的張璐,線程通過pthread_create返回的標識符來指定。
thread_return:一個指針,指向還有一個指針,而后者指向線程的返回值。
一個簡單的多線程Demo(thread1.c):
編譯這個程序時,須要定義宏_REENTRANT:
gcc -D_REENTRANT thread1.c -o thread1 –lpthread
執行這個程序:
$ ./thread1輸出:
thread_function is running. Argument was Hello World
Waiting for thread to finish...
Thread joined, it returned Thank you for your CPU time!
Message is now Bye!
這個樣例值得我們去花時間理解,由于它將作為幾個樣例的基礎。
pthread_exit(void *retval)本身返回的就是指向某個對象的指針,因此,pthread_join(pthread_t th, void **thread_return);中的thread_return是二級指針,指向線程返回值的指針。
能夠看到,我們創建的新線程改動的數組message的值,而原先的線程也能夠訪問該數組。假設我們調用的是fork而不是pthread_create,就不會有這種效果了。原因是fork創建子進程之后,子進程會拷貝父進程,兩者分離,相互不干擾,而線程之間則是共享進程的相關資源。
4.線程的同一時候運行
接下來,我們來編寫一個程序,以驗證兩個線程的運行是同一時候進行的。當然,假設是在一個單處理器系統上,線程的同一時候運行就須要靠CPU在線程之間的高速切換來實現了。
我們的程序須要利用一個原理:即除了局部變量外,全部其它的變量在一個進程中的全部線程之間是共享的。
在這個程序中,我們是在兩個線程之間使用輪詢技術,這樣的方式稱為忙等待,所以它的效率會非常低。在本文的興許部分,我們將介紹一種更好的解決的方法。
以下的代碼中,兩個線程會不斷的輪詢推斷flag的值是否滿足各自的要求。
編譯這個程序:
gcc -D_REENTRANT thread2.c -o thread2 –lpthread
執行這個程序:
$ ./thread2
121212121212121212
Waiting for thread to finish...
5.線程的同步
在上述演示樣例中,我們採用輪詢的方式在兩個線程之間不停地切換是很笨拙且沒有效率的實現方式,幸運的是,專門有一級設計好的函數為我們提供更好的控制線程運行和訪問代碼臨界區的方法。
本小節將介紹兩個線程同步的基本方法:信號量和相互排斥量。這兩種方法非常類似,其實,它們能夠互相通過對方來實現。但在實際的應用中,對于一些情況,可能使用信號量或相互排斥量中的一個更符合問題的語義,而且效果更好。
5.1用信號量進行同步
1.信號量創建
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
參數說明:
sem:信號量對象。
pshared:控制信號量的類型,0表示這個信號量是當前進程的局部信號量,否則,這個信號量就能夠在多個進程之間共享。
value:信號量的初始值。
2.信號量控制
#include <semaphore.h>
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
sem_post的作用是以原子操作的方式給信號量的值加1。
sem_wait的作用是以原子操作的方式給信號量的值減1,但它會等到信號量非0時才會開始減法操作。假設對值為0的信號量調用sem_wait,這個函數就會等待,直到有線程添加了該信號量的值使其不再為0。
3.信號量銷毀
#include <semaphore.h>
int sem_destory(sem_t *sem);
這個函數的作用是,用完信號量后對它進行清理,清理該信號量所擁有的資源。假設你試圖清理的信號量正被一些線程等待,就會收到一個錯誤。
與大多數Linux函數一樣,這些函數在成功時都返回0。
以下編碼實現輸入字符串,統計每行的字符個數,以“end”結束輸入:
編譯這個程序:
gcc -D_REENTRANT thread2.c -o thread2 –lpthread
執行這個程序:
$ ./thread3 Input some text. Enter 'end' to finish 123 You input 3 characters 1234 You input 4 characters 12345 You input 5 characters end Waiting for thread to finish… Thread join |
通過使用信號量,我們堵塞了統計字符個數的線程,這個程序似乎對高速的文本輸入和悠閑的暫停都非常適用,比之前的輪詢解決方式效率上有了本質的提高。 5.2用相互排斥量進行線程同步
還有一種用在多線程程序中同步訪問的方法是使用相互排斥量。它同意程序猿鎖住某個對象,使得每次僅僅能有一個線程訪問它。為了控制對關鍵代碼的訪問,必須在進入這段代碼之前鎖住一個相互排斥量,然后在完畢操作之后解鎖它。
用于相互排斥量的基本函數和用于信號量的函數很類似:
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t, *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destory(pthread_mutex_t *mutex);
與其它函數一樣,成功時返回0,失敗時將返回錯誤代碼,但這些函數并不設置errno,所以必須對函數的返回代碼進行檢查。相互排斥量的屬性設置這里不討論,因此設置成NULL。
我們用相互排斥量來重寫剛才的代碼例如以下:
編譯這個程序:
gcc -D_REENTRANT thread4.c -o thread4 –lpthread
執行這個程序:
$ ./thread4 Input some text. Enter 'end' to finish 123 You input 3 characters 1234 You input 4 characters 12345 You input 5 characters end You input 3 characters Thread joined |
6.線程的屬性
之前我們并未談及到線程的屬性,能夠控制的線程屬性是許多的,這里面僅僅列舉一些經常使用的。
如在前面的演示樣例中,我們都使用的pthread_join同步線程,但事實上有些情況下,我們并不須要。如:主線程為服務線程,而第二個線程為數據備份線程,備份工作完畢之后,第二個線程能夠直接終止了,它沒有必要再返回到主線程中。因此,我們能夠創建一個“脫離線程”。
以下介紹幾個經常使用的函數:
(1)int pthread_attr_init (pthread_attr_t* attr);
功能:對線程屬性變量的初始化。
attr:線程屬性。
函數返回值:成功:0,失?。?1
(2) int pthread_attr_setscope (pthread_attr_t* attr, int scope);
功能:設置線程綁定屬性。
attr:線程屬性。
scope:PTHREAD_SCOPE_SYSTEM(綁定);PTHREAD_SCOPE_PROCESS(非綁定)
函數返回值:成功:0,失敗:-1
(3) int pthread_attr_setdetachstate (pthread_attr_t* attr, int detachstate);
功能:設置線程分離屬性。
attr:線程屬性。
detachstate:PTHREAD_CREATE_DETACHED(分離);PTHREAD_CREATE_JOINABLE(非分離)
函數返回值:成功:0,失?。?1
(4) int pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy);
功能:設置創建線程的調度策略。
attr:線程屬性;
policy:線程調度策略:SCHED_FIFO、SCHED_RR和SCHED_OTHER。
函數返回值:成功:0,失敗:-1
(5) int pthread_attr_setschedparam (pthread_attr_t* attr, struct sched_param* param);
功能:設置線程優先級。
attr:線程屬性。
param:線程優先級。
函數返回值:成功:0,失?。?1
(6) int pthread_attr_destroy (pthread_attr_t* attr);
功能:對線程屬性變量的銷毀。
attr:線程屬性。
函數返回值:成功:0,失?。?1
(7)其它
int pthread_attr_setguardsize(pthread_attr_t* attr,size_t guardsize);//設置新創建線程棧的保護區大小。
int pthread_attr_setinheritsched(pthread_attr_t* attr, int inheritsched);//決定如何設置新創建線程的調度屬性。
int pthread_attr_setstack(pthread_attr_t* attr, void* stackader,size_t stacksize);//兩者共同決定了線程棧的基地址以及堆棧的最小尺寸(以字節為單位)。
int pthread_attr_setstackaddr(pthread_attr_t* attr, void* stackader);//決定了新創建線程的棧的基地址。
int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stacksize);//決定了新創建線程的棧的最小尺寸(以字節為單位)。
例:創建優先級為10的線程。
pthread_attr_t attr; struct sched_param param; pthread_attr_init(&attr); pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); //綁定 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); //分離 pthread_attr_setschedpolicy(&attr, SCHED_RR); param.sched_priority = 10; pthread_attr_setschedparam(&attr, ¶m); pthread_create(xxx, &attr, xxx, xxx); pthread_attr_destroy(&attr); |
以下實現一個脫離線程的程序,創建一個線程,其屬性設置為脫離狀態。子線程結束時,要使用pthread_exit,原來的主線程不再等待與子線程又一次合并。代碼例如以下:
編譯這個程序:
gcc -D_REENTRANT thread5.c -o thread5 –lpthread
執行這個程序:
$ ./thread5
thread_function is running. Argument: hello world!
Waiting for thread to finished...
Waiting for thread to finished...
Waiting for thread to finished...
Waiting for thread to finished...
Second thread setting finished flag, and exiting now
Other thread finished!
通過設置線程的屬性,我們還能夠控制線程的調試,其方式與設置脫離狀態是一樣的。
7.取消一個線程
有時,我們想讓一個線程能夠要求還有一個線程終止,線程有方法做到這一點,與信號處理一樣,線程能夠在被要求終止時改變其行為。
先來看用于請求一個線程終止的函數:
#include <pthread.h>
int pthread_cancel(pthread_t thread);
這個函數簡單易懂,提供一個線程標識符,我們就能夠發送請求來取消它。
線程能夠用pthread_setcancelstate設置自己的取消狀態。
#include <pthread.h>
int pthread_setcancelstate(int state, int *oldstate);
參數說明:
state:能夠是PTHREAD_CANCEL_ENABLE同意線程接收取消請求,也能夠是PTHREAD_CANCEL_DISABLE忽略取消請求。
oldstate:獲取先前的取消狀態。假設對它沒興趣,能夠簡單地設置為NULL。假設取消請求被接受了,線程能夠進入第二個控制層次,用pthread_setcanceltype設置取消類型。
#include <pthread.h>
int pthread_setcanceltype(int type, int *oldtype);
參數說明:
type:能夠取PTHREAD_CANCEL_ASYNCHRONOUS,它將使得在接收到取消請求后馬上採取行動;還有一個是PTHREAD_CANCEL_DEFERRED,它將使得在接收到取消請求后,一直等待直到線程運行了下述函數之中的一個后才採取行動:pthread_join、pthread_cond_wait、pthread_cond_timedwait、pthread_testcancel、sem_wait或sigwait。
oldtype:同意保存先前的狀態,假設不想知道先前的狀態,能夠傳遞NULL。
默認情況下,線程在啟動時的取消狀態為PTHREAD_CANCEL_ENABLE,取消類型是PTHREAD_CANCEL_DEFERRED。
以下編寫代碼thread6.c,主線程向它創建的線程發送一個取消請求。
編譯這個程序:
gcc -D_REENTRANT thread6.c -o thread6 –lpthread
執行這個程序:
$ ./thread6
thread_function is running...
Thread is still running (0)...
Thread is still running (1)...
Thread is still running (2)...
Thread is still running (3)...
Canceling thread...
Waiting for thread to finished...
8.多線程
之前,我們所編寫的代碼里面都不過創建了一個線程,如今我們來演示一下怎樣創建一個多線程的程序。
編譯這個程序:
gcc -D_REENTRANT thread7.c -o thread7 –lpthread
執行這個程序:
$ ./thread7 thread_function is running. Argument was 0 thread_function is running. Argument was 1 thread_function is running. Argument was 2 thread_function is running. Argument was 3 thread_function is running. Argument was 4 Bye from 1 thread_function is running. Argument was 5 Waiting for threads to finished... Bye from 5 Picked up a thread:6 Bye from 0 Bye from 2 Bye from 3 Bye from 4 Picked up a thread:5 Picked up a thread:4 Picked up a thread:3 Picked up a thread:2 Picked up a thread:1 All done |
9.小結
本文主要介紹了Linux環境下的多線程編程,介紹了信號量和相互排斥量、線程屬性控制、線程同步、線程終止、取消線程及多線程并發。
本文比較簡單,僅僅作為初學Linux多線程編程入門之用。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
一、 背景
SQL Server,如果我們需要把數據庫A的所有表數據到數據庫B中,通常我們會怎么做呢?我會使用SSMS的導入導出功能,進行表數據的導入導出,無可厚非,這樣的導入非常簡單和方便;
但是,當我們的表有上百個,而且有些表是有自增ID的,那么這個時候使用SSMS的話,你需要一個個手動設置(如圖1),你要知道,需要設置上百個的這些選項是件多么痛苦的事情,而且最后很可能會因為外鍵約束導致導入導出失敗。
?。▓D1)
雖然SSMS在導入導出的最后一步提供了生成SSIS包的功能,但是對于轉移數據的需求來說,還是無法達到我想要的快速、方便。
自然而然,我想到了INSERT INTO XX SELECT FROM XX WHERE這樣的方式(這種方式的好處就是可以對數據記錄、字段進行控制),但是如何才能快速生成整個
數據庫所有表的這些語句呢?
假如你需要批量生成下面的SQL,我想這篇
文章就可以幫到你了:
--[OpinionList]
SET IDENTITY_INSERT [master_new].[dbo].[OpinionList] ON
INSERT INTO [master_new].[dbo].[OpinionList](Id,Batch,LinkId,DB_Names,CreateTime)
SELECT * FROM [DBA_DB].[dbo].[OpinionList]
SET IDENTITY_INSERT [master_new].[dbo].[OpinionList] OFF
GO
二、 腳本解釋
(一) 我編寫了一個模板,這個模板你只需要設置@fromdb和@todb的名稱,這樣就會生成從@fromdb導出所有表插入到@todb中的SQL語句,需要注意的是:要選擇@fromdb對應的數
據庫執行模板SQL,不然無法生成需要的表和字段。 DECLARE @fromdb VARCHAR(100) DECLARE @todb VARCHAR(100) DECLARE @tablename VARCHAR(100) DECLARE @columnnames NVARCHAR(300) DECLARE @isidentity NVARCHAR(30) DECLARE @temsql NVARCHAR(max) DECLARE @sql NVARCHAR(max) SET @fromdb = 'master' SET @todb = 'master_new' --游標 DECLARE @itemCur CURSOR SET @itemCur = CURSOR FOR SELECT '['+[name]+']' from sys.tables WHERE type='U' order by name OPEN @itemCur FETCH NEXT FROM @itemCur INTO @tablename WHILE @@FETCH_STATUS=0 BEGIN SET @sql = '' |
--獲取表字段 SET @temsql = N' BEGIN SET @columnnamesOUT ='''' SELECT @columnnamesOUT = @columnnamesOUT + '','' + name From sys.columns where object_id=OBJECT_ID(''['+@fromdb+'].dbo.'+@tablename+''') order by column_id SELECT @columnnamesOUT=substring(@columnnamesOUT,2,len(@columnnamesOUT)) END ' EXEC sp_executesql @temsql,N'@columnnamesOUT NVARCHAR(300) OUTPUT',@columnnamesOUT=@columnnames OUTPUT PRINT ('--'+@tablename) --判斷是否有自增字段 SET @temsql = N' BEGIN SET @isidentityOUT ='''' SELECT @isidentityOUT = name From sys.columns where object_id=OBJECT_ID(''['+@fromdb+'].dbo.'+@tablename+''') and is_identity = 1 END ' EXEC sp_executesql @temsql,N'@isidentityOUT NVARCHAR(30) OUTPUT',@isidentityOUT=@isidentity OUTPUT --IDENTITY_INSERT ON IF @isidentity != '' BEGIN SET @sql = 'SET IDENTITY_INSERT ['+@todb+'].[dbo].['+@tablename+'] ON ' END --INSERT SET @sql = @sql+'INSERT INTO ['+@todb+'].[dbo].['+@tablename+']('+@columnnames+') SELECT * FROM ['+@fromdb+'].[dbo].['+@tablename+']' --IDENTITY_INSERT OFF IF @isidentity != '' BEGIN SET @sql = @sql+' SET IDENTITY_INSERT ['+@todb+'].[dbo].['+@tablename+'] OFF' END --返回SQL PRINT(@sql)PRINT('GO')+CHAR(13) FETCH NEXT FROM @itemCur INTO @tablename END CLOSE @itemCur DEALLOCATE @itemCur |
(二) 下面就是返回的生成的部分腳本,模板會自動判斷表是否存在自增字段,如果存在就會生成對應的IDENTITY_INSERT語句。
--spt_values INSERT INTO [master_new].[dbo].[spt_values](name,number,type,low,high,status) SELECT * FROM [master].[dbo].[spt_values] GO --[OpinionList] SET IDENTITY_INSERT [master_new].[dbo].[OpinionList] ON INSERT INTO [master_new].[dbo].[OpinionList](Id,Batch,LinkId,DB_Names,CreateTime) SELECT * FROM [DBA_DB].[dbo].[OpinionList] SET IDENTITY_INSERT [master_new].[dbo].[OpinionList] OFF GO |
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
replace和replaceAll是JAVA中常用的替換字符的方法,它們的區別是: 1)replace的參數是char和CharSequence,即可以支持字符的替換,也支持字符串的替換(CharSequence即字符串序列的意思,說白了也就是字符串);
2)replaceAll的參數是regex,即基于規則表達式的替換,比如,可以通過replaceAll("\\d", "*")把一個字符串所有的數字字符都換成星號;
相同點是都是全部替換,即把源字符串中的某一字符或字符串全部換成指定的字符或字符串,如果只想替換第一次出現的,可以使用 replaceFirst(),這個方法也是基于規則表達式的替換,但與replaceAll()不同的是,只替換第一次出現的字符串;
另外,如果replaceAll()和replaceFirst()所用的參數據不是基于規則表達式的,則與replace()替換字符串的效果是一樣的,即這兩者也支持字符串的操作;
還有一點注意:執行了替換操作后,源字符串的內容是沒有發生改變的.
舉例如下:
String src = new String("ab43a2c43d"); System.out.println(src.replace("3","f"));=>ab4f2c4fd. System.out.println(src.replace('3','f'));=>ab4f2c4fd. System.out.println(src.replaceAll("\\d","f"));=>abffafcffd. System.out.println(src.replaceAll("a","f"));=>fb43fc23d. System.out.println(src.replaceFirst("\\d,"f"));=>abf32c43d System.out.println(src.replaceFirst("4","h"));=>abh32c43d. |
如何將字符串中的"\"替換成"\\":
String msgIn;
String msgOut;
msgOut=msgIn.replaceAll("\\\\",\\\\\\\\);
ps:貌似這樣也可以:msgIn = msgIn.replaceAll("\\\\",\\\\\\\\);
原因:
'\'在java中是一個轉義字符,所以需要用兩個代表一個。例如System.out.println( "\\" ) ;只打印出一個"\"。但是'\'也是正則表達式中的轉義字符(replaceAll 的參數就是正則表達式),需要用兩個代表一個。所以:\\\\被java轉換成\\,\\又被正則表達式轉換成\。
同樣
CODE: \\\\\\\\
Java: \\\\
Regex: \\
將字符串中的'/'替換成'\'的幾種方式:
msgOut= msgIn.replaceAll("/", "\\\\");
msgOut= msgIn.replace("/", "\\");
msgOut= msgIn.replace('/', '\\');
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
摘要:
IT行業已經發展了幾十年,但如何成為一個優秀的IT項目經理?這個問題還在困擾著很多人。本文結合自己的實踐經驗和理論研究,針對中國國情,論述了IT項目經理基礎知識體系的重要性,指出了IT項目經理應具備的知識體系和個性特征。
本節對于項目管理資深人士屬于啰嗦,但筆者慎重思考后還是認為有必要啰嗦幾句,因為錯誤的觀念依然在傳播,毒害不知真相的人。只有讓正確的觀點流行傳播,讓大家了解真相,才能少走彎路,減少錯誤,使得更多人用寶貴的時間做更有意義的事。
有一種觀念在我國非常流行:項目經理是干出來的,不是考出來的;PMBOK是老外整出來的東西,內容根本就是花架子,不適合國情,拿PMP純粹是糊弄人,耽擱時間。其實還有很多類似的觀點在廣泛傳播,比如大學生無用論,MBA無用論,其根本就是沒有辨清知識體系與能力之間的關系,而不明真相,缺少判斷力的人只看結果,讓這些似是而非的錯誤觀念到處傳播,到處發毒。這種毒對年輕人毒害尤其大!
項目管理也是管理,管理的對象主要包括兩個:人和事,主要是人。雖然有東西方文化差異,但是人性是相通的,尤其是現在全球化日益深入的情況下,在同一個項目中同時存在東西方文化和不同國籍組員的情況日益普遍,而管理思想深層次折射的是文化。對于刻意突出“西方管理不適合中國土壤”的人,除了要以“語不驚人死不休”的表達方式來體現他的真知灼見外,同時也反映了這些人某些層面的淺薄:用地域和群體來表述必然會以偏概全!
獲得PMP不一定就完全掌握了PMBOK,這跟一個大學畢業生拿到學士學位,對大學某一專業的知識體系有了全面了解,但畢業后卻不一定就能成為該專業領域的優秀人才一樣:知道不一定能做到!
學習知識,需要的是記憶和分析能力,主要是記憶;而每個人的實際能力卻跟個人的天賦有很大關系。掌握PMBOK,明白項目管理該做些什么,其中的方法論也具體指導你某些事該怎么做,但真正的管理項目,卻需要根據實際情況靈活判斷該采用哪些知識、哪些方法來處理。再舉個大家更熟悉的例子,一個學習了PMBOK并獲得PMP的人,就好比一個精讀并熟記了“葵花寶典”的書生,能否成為“東方不敗”,這一方面要靠自己的天賦,另一方面真的需要苦練,甚至揮刀自宮的酷刑(得摒棄自己性格中的某些缺陷,比如一個自由散漫的人一定得學會自律,才可能成為一個優秀的項目經理)。
PMBOK包含5大過程,9大知識領域,集成了全球項目經理人豐富的最佳實踐,稱之為《項目管理的“葵花寶典”》毫不夸張。最為關鍵的是,PMBOK在不斷更新完善,新的最佳實踐和知識在不斷對其充實。PMI的認證體系根據項目管理崗位,管理能力和管理范圍的不同需要進行了分級:CPMP(項目經理助理)、PMP(項目經理)、PgMP(高級項目經理)。不同的
工作崗位需要不同的知識體系。據最新獲得的消息,PMBOK在今后的版本中很有可能根據行業不同分出不同行業的PMBOK,我們將會看到建筑行業的PMBOK,IT行業的PMBOK,制造業的PMBOK……,這是集體智慧的結晶,并且在不斷融入新的智慧!
知道了不一定能做到,但是根本不知道,你認為能做到么?
明白了以上的關系,PMBOK我們要不要去讀?PMP認證我們該不該拿?這個你自己決定。“要練神功,先要自宮”,可能會嚇跑不想獲得神功的人,但嚇不跑“東方不敗”!
二、IT項目經理應具備的知識體系
比較流行的觀念是,IT項目經理需要三方面的知識:IT專業知識、業務知識、管理知識。這是國內企業對戰斗在一線的項目經理的普遍要求,尤其是軟件項目的PM。
什么樣的人才適合項目管理的職責?“從理論上,具體到特定的項目任務,誰更有可能取得項目成功,誰就應該承擔項目管理的職責。”這是一個相當騎墻的答案,但說出了本質。項目經理的任命,項目經理應該具備的知識體系,完全是由具體項目任務決定的。
對于單個的中小軟件項目,國內多數企業都是以1個項目經理+N(0~12)個開發人員這樣的團隊進行任命組建,而為了壓縮成本,多數開發人員都是剛畢業或者有短暫開發經驗的年輕技術人員,項目所需的知識要求,可能多數都集中在了項目經理一個人身上。而多數這樣的項目經理,從公司的角度,要求的是經驗,有過1個或幾個同類項目的開發經驗,是編程高手,懂一些系統分析設計和
數據庫設計的知識即可,而對管理的要求,只要你能帶好幾個人干活就行。
這是普遍現象,也有把項目做成功的,但失敗率很高,失敗的項目問題出在什么地方?如果說責任,可以說是企業任命錯誤,也可以說項目經理本人能力不足。但作為個人,項目經理如果不能認識到自己的不足,那注定不可能有進步和提升。
因為業務性質的不同,IT項目所需知識差異很大,但可以總括為軟硬件知識、網絡知識、美術知識、業務知識、管理知識。其中軟件知識領域會包含
操作系統、應用服務器、數據庫、編程(語言、算法和數據結構、設計模式)、軟件工程等。
而管理知識,沒學過項目管理的軟件專業人士多數都熟悉軟件工程,其中有很多管理思想,但是軟件工程的管理不同于項目管理,有哪些差異請參閱喬東的
文章《IT產品管理與項目管理的關系》。
“麻雀雖小,五臟俱全”。任何一個IT項目,都會涉及到以上所有知識領域,隨著項目的增大相應的知識領域復雜度會更大。很難有一個人精通以上所有知識,因為這些知識隨著創新還在不斷的增加?,F在極個別情況下還有一個人開發一個軟件項目的情況,但這樣的情形越來越少。多數項目失敗,都是因為項目組知識體系不健全導致,可能是技術知識,也可能是管理知識。
國內很多軟件項目的項目經理是由程序員提拔上來,如果他對軟件工程掌握得比較好,對某些簡單的軟件項目,基于過去項目的經驗,可能會成功,這也是很多人認“項目經理是干出來,不是學出來”的理由。這樣的項目經理如果面對多個子項目,功能復雜,干系人復雜,時間要求緊等復雜情況時,必然會因為知識體系的不健全,越來越多的問題不知道如何處理,不能很好的預測項目風險,隨著項目的開展,使局面混亂復雜,最終導致項目失敗。
還有一個讓很多人困惑的問題是,一個完全不懂IT技術的人是否可以做IT項目經理?對此的答案是很明確的:這跟“什么樣的人才適合項目管理的職責?”答案相同,如果他能使項目成功,就是可以。項目的成功靠團隊,而不僅是某一個人!項目所需要的知識體系,是由整個團隊成員的知識體系總和決定。其實優秀的項目多數都是項目組成員知識能力差異互補,形成的是一個完整圓滿的團隊。如果項目中僅有一個或者兩個“牛人”來支撐,其他組員不能快速學習提升,必然會因為“木桶短板”,導致項目出問題。
另一個困惑很多人的問題是對業務知識的掌握。幾乎所有的招聘單位都是要求既要有IT技術知識,開發經驗,又要有相關行業背景或者行業軟件開發經驗才能勝任某一行業IT項目的項目經理。其實造成這樣的現狀,企業也是被逼出來的。國內的多數軟件開發方都比較弱勢,為了把項目做好需要做很多本該甲方做的事情。相比而言,懂業務知識的項目經理跟客戶溝通更方便,更容易理解客戶需求,對推動項目進展有很大的促進作用。但有兩個問題需要思考:
1) 項目經理掌握多少業務知識才算夠?
2) 有經驗,或者某些頂著“專家”頭銜的甲方業務人員,就真的能提出很好的IT系統需求么?
諾貝爾經濟學獎得主西蒙教授的研究結果表明:“對于一個有一定基礎的人來說,他只要真正肯下功夫,在6個月內就可以掌握任何一門學問。”教育心理學界為感謝西蒙教授的研究成果,故命名為西蒙學習法??梢?,掌握一門陌生的學問遠遠沒有想想的那么高難、深奧。
研究結果和事實都表明,有行業背景和相關行業軟件的開發經驗,對項目需求獲取有很好的促進作用,可以作為軟件項目經理的充分條件,但不是必要條件,“有一定基礎”和“肯下功夫”才是關鍵。做好業務建模,除了熟悉行業知識,更重要的是精通系統分析設計方法和清晰良好的分析判斷能力。
三、IT項目經理應該具備的基本個性特征
有很多人一直都不明白有些人講起管理頭頭是道,為什么卻做不了管理?前面也已經做了分析,學習PMBOK拿了PMP不一定就具備項目管理的能力,每個人的實際能力跟個人天賦有很大關系。對一個項目經理來說,究竟該具備什么樣的特質和天賦?筆者概括為四力一度。
1、學習力
二十一世紀,最重要的不是學歷,也不是能力,而是學習力!
學習力包括三點:1、喜歡學習;2、快速學習;3、持續學習!這三點缺一不可。
干IT行業注定比其他行業更累,就是因為不斷有新的技術、新的思想、新的工具在產生,并且項目經理注定要帶各種項目,面對很多行業,沒有很好的學習力不可能適應這個行業,更不可能干好。
對很多IT項目經理來說,最可怕的就是“終于由程序員熬成了項目經理”這種想法。國內不少由開發人員晉升上來的項目經理,就是倒在了這條路上!職位的晉升本來是好事,但把一個人安排到不合適的崗位上,真的有可能毀掉一個人。受3000多年傳統“官本位”思想的影響,很多國人想做管理,“官”“管”直接掛了鉤,在IT行業也不例外。
在很多開發人員眼里,項目經理就是一個指揮指揮,聊聊天,說說話就行的職位,貌似根本不用再學習。有些開發人員就是按照自己的觀察理解來干這個工作,放棄了學習,每天忙于項目事務,一些簡單的項目基于原有的項目經驗,真的有可能會帶成功,但遇到復雜的項目,就會發現力不從心,捉襟見肘。
IT項目經理,不僅要學習當下項目需要用到的業務知識、技術知識,掌握新的工具等等,更要不斷學習鞏固項目管理知識、軟件工程知識,因為這些知識體系都在不斷的發展充實。而管理學,人類幾千年文明史,從未停止過進步。PMBOK現有的5大過程,9大知識領域,沒有持續的學習、經驗積累、實踐總結,絕不可能很好掌握。胸有“萬卷詩書”,才可能輕松面對項目中“千奇百怪”復雜的局面!
2、溝通力
溝通管理在PMBOK中做為9大知識領域之一奉獻給大家,足見溝通在項目管理中的重要性。溝通力主要體現在兩點:1、順暢良好的溝通;2、適當的溝通力度。
首先要澄清一個誤區:溝通能力需要很好的表達能力,包括語言表達、文字表達和肢體表達等,但表達能力不等于溝通能力。細心、耐心,廣博的學識、良好的傾聽對溝通都非常重要。很多有豐富溝通經驗的管理人士強調傾聽的重要性,是因為太多人都“好為人師”,喜歡講,不喜歡聽。溝通是個雙向的事情,每次溝通一定要明確肯定對方的表達,給予準確答復,同時也要得到對方的明確答復,確認對方真正理解了你的意思。
干系人識別、分析、分類是項目經理制定溝通管理計劃首先要做的事情,但更復雜也最能體現項目管理藝術的,就是項目經理要能清晰判斷如下內容并付諸實施:
1)在什么時機(到了項目哪個階段,發生了什么事件);
2)跟哪些人(用戶、客戶、客戶領導、組員、公司領導、銷售、監理公司);
3)通過什么方式(會議、當面公談或私談、電話、電子郵件、別人轉達);
4)在適當的時間(立刻、周幾、上午、下午、下班后、幾點幾分);
5)什么地點(會議室、辦公室、茶餐廳……);
6)說什么(長篇大論、簡明扼要,這種度需要自己把握)。
每次溝通,如果不能解決問題,就可能產生更大的新問題。以上任何一個環節出了差錯,都可能會造成一次事故,給項目帶來很大風險。
溝通在項目中是如此重要,順暢良好的溝通需要項目經理不斷觀察,學習總結。普遍的觀點認為成功的項目經理80%的時間都會運用在溝通上。有些能力很強的項目經理,或是因為心情不佳,或是因為積極性不高,偷懶,僥幸等等心態作怪,在該溝通的時候未進行溝通,致使項目問題堆堆,最終導致項目失敗,這是非常可惜可悲的事情。充分準備是良好溝通的必要保證。
溝通是貫穿整個項目生命周期的任務,項目經理要為整個項目創造良好的溝通交流氛圍,并把控好溝通的力度:既要保證每次溝通有實際效果,又要保證溝通的周期、時間、時機。
3、決策力
良好決策是成功管理的必須前提,任何管理者都必須具有良好的決策力,項目經理也不例外。良好決策必是基于對現狀的清晰認識,因此,首先對項目整體情況的跟蹤和檢查是項目經理一定要做好的事情,其次就是要求項目經理必須具備良好的分析判斷能力。
成熟的方法是項目經理有清晰思路的保證,也是做好分析判斷的基礎。對分析判斷,軟件工程和項目管理知識體系提供了很多實用的方法和工具,如軟件工程中常用的流程圖,質量管理中有名的戴明環(PDCA)、帕累托圖、魚刺圖,深刻理解了這些工具的概念、使用方法,理解了其核心思想,我們在面對復雜問題時,就會有很好的分析方法,獲得判斷依據。
分析判斷能力有先天因素的影響,但更重要的是后天的學習和思考。即使是發散型思維,經過學習和訓練,也可以形成很好的邏輯判斷能力;習慣邏輯思考的人,通過頭腦風暴、聯想式思考的訓練,也可以形成很好的發散思維思考模式。這是對日常事務處理的分析判斷。
對于項目經理來說,還有一點就是對干系人行為的分析判斷。先天的情商很重要,很多人從小就對別人的行為十分敏感,能比較清晰的判斷出對方的情緒、想法以及下一步要采取的行動,也能清晰地知道自己采取的行動能對對方產生好的或者壞的影響,這是情商很高的人。
如果你覺得自己情商不夠高,通過學習觀察,經驗累積,對人的分析判斷能力會逐步提高。關于人性的討論,中華民族是走在世界前列的,“太陽之下,無新鮮事”!通讀史書能對人性有很好的了解,還有經典古籍、文學名著,都有助于我們對人性的了解,現代翻譯引進的很多西方管理學書籍也都有這方面的論述,《人性的弱點》這本書就很不錯。
決策的形成過程有時很漫長,有時只是瞬間,每個項目都會持續一定時期,大的項目甚至會持續很多年,持續不斷的正確決策保證項目順利進行和成功結束。正確的決策一方面依賴于個人天賦,另一反面取決于個人平時的用心程度和用功程度。
4、執行力
任何事情的結果都離不開踏踏實實的執行,我們常聽說“千言萬語不如一個行動”。但項目管理是如此的實實在在,并且項目管理的典型特征就是時間限制。在有限的時間內通過團隊合作來完成項目目標,項目經理沒有很好的執行力絕對不行!
在整個項目過程中,會遇到各種各樣的問題、麻煩和阻撓,項目經理必須清楚在什么樣的時機采取什么樣的行動。項目經理是整個項目團隊的核心,項目經理的執行力包含兩個層面:一是做好自己,把那些需要自己親力親為的事情做好;二是推動別人,領導推動項目相關者在相應的時機采取相應的行動,該指揮就上去指揮,需要指導就上去指導,需要協調就擇機協調,需要求助上司就及時跟上司匯報。
制定一份優秀的項目計劃是一個項目經理能力的體現,將計劃按預期逐一落實更是必須具備的能力。項目成功是項目經理的唯一目標,所有的行動都要為此服務!時刻牢記這個目標,采取所有正確的行動來實現這個目標,不要懈怠。
沒有一個項目會毫無阻力、沒有麻煩的結束,如果項目都那樣就不需要項目經理了,項目經理的職責就是解決問題。無論多么優秀的項目經理,沒有人能把所有問題都解決得完美無缺。做項目管理,你總會遇到新的問題和麻煩,因此項目經理需要不斷的學習、思考和總結,不斷改進過程,提高個人能力,改善自己的執行力。
五、成熟度
這里的成熟度主要指個人修養,或者說人格的成熟度。這是一個較大的話題,寫幾本書未必能描述詳盡,但也足以說明個人修養絕非一日之功。個人成熟度受個人成長環境、所受教育、個人天賦等多方面影響,但以下三點對一個成功的項目經理有著至關重要的影響,如果這三點不具備,肯定會出大問題。
1、 信仰正確
信仰是每個人都必須面對的。談到信仰大家多數立刻會想到宗教或哲學派別,在這里不評論宗教或者哲學派別的好壞對錯,這是人類一直在探索和爭論的永恒話題。這里的信仰,是指每個人自己心目中的生活信條和生活目標。宗教和哲學派別有很大差異,但對“真善美”的追求是人類共識的正確追求。
PMP認證考試時專門加入了職業道德部分,這是無比正確的。一個信仰錯誤的人,能力越強,破壞力越大。但因為文化差異,PMP考試的職業道德考試也給其他國家,包括中國的考生帶來不少困惑和煩惱,作為一個國際性認證,這也是需要改進的一個方面。
一個成功的項目經理,必須有自己清晰的生活信條和生活目標,這些信條務必是由一系列健康樂觀,積極向上的處世原則組成。一個有人格缺陷或悲觀甚至邪惡信仰的人做項目經理,會給項目團隊帶來毀滅性打擊,甚至會給其他團隊或公司帶來毀滅性打擊。
2、 情緒穩定
是人類,就避免不了喜怒哀樂等心情的變化,有時也會有莫名其妙的憂郁。沒有情緒變化的人不會是一個正常的人,但一個任由壞情緒發泄的人絕對是一個不成熟的人,這樣的人就好像一個“不定時炸彈”,身邊的人不知道他會什么時候“爆炸”。
“炸彈”的說法好像有點夸張,但很多人都領教過“神經質”領導的威力,迫于權勢和其他考慮,很多人選擇忍受。這顆炸彈威力較輕,會忍受時間長些,一旦遍體鱗傷,肯定會選擇離開。但項目經理算不上大領導,項目經理要面對臨時組成的團隊和各種各樣的干系人,這些情況就確定了有太多不穩定因素。如果項目經理不能控制好情緒,這顆“炸彈”的爆炸極有可能成為群爆的“導火索”,最終結局就是遍地尸身。這樣的情況已經有無數先例。
項目經理這個團隊核心,無疑會比多數團隊成員有更大的影響力,項目經理的情緒變化必然會給整個團隊帶來較大影響。壞情緒未必都會造成壞結果,這需要項目經理審時度勢,控制好自己的情緒在合適的時機表現出來。無論如何,不能讓情緒造成的“沖動”左右自己的行動,“沖動”是魔鬼,魔鬼從來不會干好事!
心身健康是穩定情緒的關鍵。心,指思想觀念;身,指軀體。積極向上的思想觀念會正面影響一個人的一切。大量事實和經驗也說明,身體不好的人各種壞情緒會接踵而至。多做充實自己的事,多想快樂的事,多鍛煉身體,你一定能心身健康。平衡是一個很重要的項目思維,項目經理首先得能做好工作與生活的平衡。
3、 換位思考
一個不能換位思考的人,一定不是一個成熟的人!
項目經理不可避免要面對很多陌生但很關鍵的“干系人”,并且要滿足各種各樣干系人不同的項目需求(而不是個人要求)。換位思考是良好溝通的基礎,更是締造雙贏局面的必須。一個不懂得換位思考的項目經理不會懂得理解,更無法做到包容。總是基于自身利益考慮問題必然導致客戶嚴重不滿,也必然導致項目失敗。
換位思考是一個簡單的處世法則,但簡單的道理卻有很多人無法做到,這也決定了為什么有的人做不了項目經理。古往今來,從孔子的“己所不欲,勿施于人”到《馬太福音》的“你們愿意別人怎樣待你,你們也要怎樣待人”,不同地域、不同種族、不同宗教、不同文化的人們,說著大意相同的話。
在項目的實施過程中,很多情況下項目經理不僅需要做到“換位思考”,還需要“替人辦事”,尤其是國內多數軟件實施項目,實施方多數處于“弱勢”地位。一方面是很多客戶在信息化和管理方面的不成熟,不知道該怎么辦;另一方面可能是強勢的客戶知道,但他卻不想辦。無論哪種情況,很多時候靠協調和合同約束無法完成項目,如果糾纏于責任和法律條款,致使項目時間延遲或者項目失敗,最終造成“雙輸”局面,這絕不是理想的結局。
一個優秀的項目經理,會很好的換位思考,圍繞“項目成功”這個最大目標,不會推卸責任,不會糾纏于一些無法界定責任人的小事,會積極地思考、溝通、協調、推動每項任務的順利進行,哪怕在經濟或其他方面吃些“小虧”,處理好項目的每件關鍵事情,使項目順利進行。
換位思考,是一個人“智慧”的體現!替人想在前面、做在前面,“智慧”會為你贏得非凡的成功!
四、總結
如果沒有充分的知識,一個項目經理無法知道要成功完成項目該“做什么”,“怎么做”;如果沒有必備的個人天賦和后天的勤奮努力,也絕無可能成為優秀的項目經理。
項目需要團隊合作才能成功,但任何時候,用“求人”不如“求己”來提醒自己,多學習,充實自己,在緊急關頭,你會更容易度過難關。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
1.字符串比較,使用“==”還是equals()?
"=="判斷兩個引用的是不是同一個內存地址(同一個物理對象)。
equals()判斷兩個字符串的值是否相等。
除非你想判斷兩個string引用是否同一個對象,否則應該總是使用equals()方法。
如果你了解字符串的駐留(String Interning)則會更好地理解這個問題。
2. 對于敏感信息,為何使用char[]要比String更好?
String是不可變對象,意思是一旦創建,那么整個對象就不可以改變,即使新手覺得String引用變了,實際上只是(指針)引用指向了另一個(新的)對象。
而程序員可以明確地對字符數組進行修改,因此敏感信息(如密碼)不容易在其他地方暴露(只要你用完后對char[]置0).
3.在switch語句中使用String作為case條件
從JDK7開始,
Java 6及以前的版本都不支持這樣做的
// 只在java 7及更高版本有效!
switch (str.toLowerCase()) { case "a": value = 1; break; case "b": value = 2; break; } |
4.轉換String為數字
對于非常大的數字請使用long.代碼如下:
int age = Integer.parseInt("10");
long id = Long.parseLong("190"); // 假如值可能很大.
5.如何通過空白符拆分字符串
String的split()方法接收的字符串會被當做正則表達式解析。
"\s"代表空白字符,如空格"",tab制表符"\t",換行"\n",回車"\r".
而編譯器在對源代碼解析時,也會進行一次字面轉碼。所以需要"\\s".
String[] strArray = aString.split("\\s+");
6.substring()方法內部是如何處理的?
在JDK6中,substring()方法還是共用原來的char[]數組,通過偏移和長度構造了一個"新"的string.
想要substring取得一個全新創建的對象,使用如下這種方式:
String sub = str.substring(start, end) + "";
當然Java 7中,substring()創建了一個新的char[]數組,而不是共用。想了解更多,請參考:JDK6和JDK7中String的substring()方法及其差異
7.String vs StringBuffer vs StringBuilder
StringBuilder是可變的,因此可以在創建以后修改內部的值。
StringBuffer是同步的,因此是線程安全的,但是效率相對更低。
8.如何重復拼接同一個字符串?
方案一:使用Apache Commons Lang庫的StringUtils工具類。
String str = "abcd";
String repeated = StringUtils.repeat(str,3);//abcdabcdabcd
方案二:使用StringBuilder構造,更靈活。
String src = "name"; int len = src.length(); int repeat = 5; StringBuilder builder = new StringBuilder(len * repeat); for(int i=0; i<repeat; i++){ builder.append(src); } String dst = builder.toString(); |
9.如何將String轉換成日期?
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String str = "2013-11-07";
Date date = format.parse(str);
System.out.println(format.format(date));//2013-11-07
10.如何統計某個字符出現的次數?
同樣使用Apache Commons Lang 庫StringUtils類:
int n = StringUtils.countMatches("11112222", "1");
System.out.println(n);
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
剛接觸
配置管理的同志,很容易將配置管理等同于SVN,認為SVN系統是一套配置管理系統。這是嚴重的誤解。
配置管理包括: 版本控制,變更控制,基線管理,產品發布管理,權限管理,配置審計,狀態報告等。
SVN是一個版本控制系統,除此之外對變更控制,產品發布管理,配置審計都無能為力。類似的 git 也一樣。
CC和 CQ才是真正意義上的配置管理系統。所謂管理系統,必須擔負起應有的管理功能。
舉一個最簡單的例子,svn中只有checkout commit update幾個動作。對于配置項的狀態是沒有檢入和檢出的標記的。因此,如果發生變更控制某個配置項的變更,只能通過權限方式去實現。而CC中則清楚地分開了檢入和檢出動作。管理員可以要求項目組每天至少檢入一次。這種要求在SVN中變得難以實現。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
令我印象深刻而難以忘懷的,是我親自經歷的、親眼目睹的、道聽途說的一個又一個的軟件項目,它們有的獲得了成功,但更多的是令人沮喪的失敗。套用一下大文豪托爾斯泰體:幸福的家庭都是一樣的,不幸的家庭卻各有各的不幸;幸福的軟件項目都是一樣的,不幸的軟件項目卻各有各的不幸;或者說,成功的軟件項目都是一樣的,失敗的項目卻各有各的問題。我常常在想,我們的項目開發到底怎么了,進而把它們一個一個的剝開來深入分析,竟然觸目驚心。它們有的是需求的問題,有的是客戶關系的問題,還有設計的問題、技術的問題、時間管理的問題、人員培養的問題.....但歸根到底更多的還是需求的問題。需求分析既是一份體力活兒,更是一份技術活兒,它既是人際交往的藝術,又是邏輯分析與嚴密思考的產物。正是我們在需求分析過程存在的巨大隱患,最終導致了那么多項目的失敗。也許你認為我在危言聳聽,好吧,我來舉幾個典型事例分析分析吧。
我的第一個故事來自大名鼎鼎的東軟。我在2005年接一個項目的時候,聽說這個項目之前是東軟做的。當時東軟在做這個項目的時候,整個過程經歷了10多次結構性的大變更,局部性的調整更是不計其數。據說某天早上,客戶對某個功能不滿意,他們不得不對幾百處程序進行修改。之后客戶對修改的內容還是不滿意,又不得不將幾百處修改重新改回來。最后這個項目導致的結果是,整個這個項目組的所有成員都離開了東軟,并似乎從此不愿涉足
軟件開發領域。多么慘痛的教訓?。∥页3B牭骄W友抱怨客戶總是對需求改來改去,但客戶對需求改來改去的真正原因是什么呢?當我們對客戶的需求沒有真正理解清楚時,我們做出來的東西客戶必然不滿意??蛻糁恢浪粷M意,但怎樣才能使他滿意呢?他不知道,于是就在一點兒一點兒試,于是這種反復變更就這樣發生了。如果我們明白了這一點,深入地去理解客戶的業務,進而想到客戶的心坎兒上去,最后做出來的東西必然是客戶滿意的。記住,當客戶提出業務變更的時候,我們一定不能被客戶牽著走,客戶說啥就是啥。我們要從業務角度深入的去分析,他為什么提出變更,提得合不合理,我有沒有更合理的方案滿足這個需求。當我們提出更加合理的方案時,客戶是樂于接受的,變更也變得可控了。
第二個故事來自我自己的項目,一個早期的項目。在這個項目中,客戶扔給了我們很多他們目前正在使用的統計報表,要我們按照報表的格式做出來。這些報表都是手工報表,許多格式既不規范,又很難于被計算機實現。這些報表令我耗費了不少腦細胞,直到最終項目失敗都沒法完成。這件事留給我的深刻教訓是,不能客戶怎么說軟件就怎么做。客戶提出的原始需求往往是不考慮技術實現,基于非計算機管理的操作模式提出來的。他們提出的很多需求常常比較理想而不切實際,畢竟人家是非技術的。但我們作為技術人員,需求分析必須實事求是的、基于技術可以實現的角度去考慮。那種“有條件要上,沒有條件創造條件也要上”的魯莽行事,結果必然是悲慘的。所以我們必須要基于技術實現去引導客戶的需求。同時,計算機信息化管理就是一次改革,對以往手工管理模式的改革。如果我們上了信息化管理系統,采用的管理模式卻依然是過去的手工模式,新系統的優勢從何而來呢?因此,我們做需求就應當首先理解現有的管理模式,然后站在信息化管理的角度去審視他們的管理模式是否合理,最后一步一步地去引導他們按照更加合理的方式去操作與管理。
2007年,我參與了一個集團信息化建設的項目。這個項目中的客戶是一個龐大的群體,他們分別扮演著各種角色。從機構層次劃分,有集團領導、二級機構人員、三級機構人員;從職能角色劃分,有高層領導、財務人員、生產管理員、采購人員、銷售人員,等等。在這樣一個復雜場景中,不同人員對這個項目的需求是各自不同的。非常遺憾的是,我們在進行需求分析的時候沒有認真分析清楚所有類型人員的需求。在進行需求調研的時候,總是集團領導帶領我們到基層單位,然后基層單位將各方面的人員叫來開大會。這樣的大會,各類型的人員七嘴八舌各說各自的需求,還有很多基層人員在大會上因為羞澀根本就沒有提出自己的需求。這樣經過數次開會,需求調研就草草收場。我們拿著一個不充分的需求分析結果就開始項目開發,最終的結果可想而知。直到項目上線以后,我們才發現許多更加細節的業務需求都沒能分析到,系統根本沒法運行,不得不宣告失敗。一個軟件項目的需求調研首先必須要進行角色分析,然后對不同的角色分別進行調研。需求調研的初期需要召開項目動員大會,這是十分必要的。但真正要完成需求分析,應該是一個一個的小會,1~3個業務專家,只討論某個領域的業務需求,并且很多問題都不是能一蹴而就完成的,我們必須與專家建立聯系,反復溝通后完成。需求分析必須遵從的是一定的科學方法,而不是盲目的大上快上。
我的最后一個故事可能典型到幾乎每個人都曾經遇到過。我們的項目從需求分析到設計、開發、
測試都十分順利。但到了項目進行的后期,快到達最后期限時,我們將我們的開發成果提交給客戶看,客戶卻對開發結果不滿意,提出了一大堆修改,而且這些修改
工作量還不小。怎么辦呢?加班、趕工,測試時間被最大限度壓縮。最后項目倒是如期上線了,但大家疲憊不堪,并且上線以后才發現許多的BUG。需求分析不是一蹴而就的,它應當貫穿整個開發周期,不斷的分析確認的過程。以上這個事例,如果我們提早將開發成果給客戶看,提早解決問題,后面的情況就將不再發生。這就是
敏捷開發倡導的需求反饋。敏捷開發認為,需求分析階段不可能解決所有的需求問題,因此在設計、開發、測試,直到最終交付客戶,這整個過程都應當不停地用開發的成果與客戶交流,及時獲得反饋。只有這樣才能及時糾正需求理解的偏差,保證項目的成功。
以上的故事各有各自的不幸,各自都在不同的開發環節出現了問題。但經過深入的分析,各自的問題最終都歸結為需求分析出現了問題。為了使我們今后的軟件項目不會重蹈覆轍,似乎真的有必要討論一下我們應該怎樣做需求分析。
English » | | | | | | | | |
Text-to-speech function is limited to 100 characters
之前寫過一篇
Appium for windows的
文章,因為是09年的T400,啟動
Android模擬器的時候死機三次,那就公司申請臺Macbook air吧,15寸的Macbook Pro實在太重了,也就Mac才能真正發揮Appium的功能,支持Android和iOS。好了,廢話不多,開始。
1. 爬墻
因為后續安裝過程中可能會碰到墻的問題,所以首先得解決爬墻的問題。
我的方便,公司提供代理。
guowenxie-macbookair:~ guowenxie$ java -version
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)
3. git
guowenxie-macbookair:~ guowenxie$ git --version
git version 1.8.5.2 (Apple Git-48)
4. ruby
guowenxie-macbookair:~ guowenxie$ ruby -v
ruby 2.0.0p451 (2014-02-24 revision 45167) [universal.x86_64-darwin13]
5. brew
guowenxie-macbookair:~ guowenxie$ brew -v
Homebrew 0.9.5
這邊提下brew的安裝,brew是Mac OS不可或缺的套件管理器
執行下面命令
ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
6. node
有了brew安裝node就方便了
brew install node
7. npm
guowenxie-macbookair:~ guowenxie$ npm -v
2.0.0-alpha-5
8. Appium
現在可以開始安裝Appium
guowenxie-macbookair:~ guowenxie$ appium -v
1.2.0
9. wd
npm install wd
10. Xcode和Android SDK
這個不說了
11. 檢查環境
Appium提供了一個doctor,運行appium-doctor
guowenxie-macbookair:~ guowenxie$ appium-doctor Running iOS Checks Xcode is installed at /Applications/Xcode.app/Contents/Developer Xcode Command Line Tools are NOT installed: Error: Command failed: No receipt for 'com.apple.pkg.CLTools_Executables' found at '/'. Fix it (y/n) y Press any key to continue: Xcode Command Line Tools are installed. DevToolsSecurity is enabled. The Authorization DB is set up properly. Node binary found at /usr/local/bin/node iOS Checks were successful. Running Android Checks ANDROID_HOME is set but does not exist on the file system at "Users/guowenxie/Documents/adt-bundle_mac-x86_64-20140702/sdk" Appium-Doctor detected problems. Please fix and rerun Appium-Doctor. |
這里可以看到我Xcode Command Line Tools沒有安裝,這個方便,Fix it 的時候輸入Y,就能自動導向安裝了。
另一個是ANDROID_HOME的環境變量沒配置好,那么我們要配置下。
12. bash_profile文件
Mac 默認是沒有這個文件的,我們自己建一個
touch .bash_profile
vi .bash_profile
打開bash_profile文件配置ANDROID_HOME和JAVA_HOME
export ANDROID_HOME="/Users/guowenxie/Documents/adt-bundle-mac-x86_64-20140702/sdk"
export JAVA_HOME=$(/usr/libexec/java_home)
source .bash_profile
好了,再次運行appium-doctor
guowenxie-macbookair:~ guowenxie$ appium-doctor Running iOS Checks Xcode is installed at /Applications/Xcode.app/Contents/Developer Xcode Command Line Tools are installed. DevToolsSecurity is enabled. The Authorization DB is set up properly. Node binary found at /usr/local/bin/node iOS Checks were successful. Running Android Checks ANDROID_HOME is set to "/Users/guowenxie/Documents/adt-bundle-mac-x86_64-20140702/sdk" JAVA_HOME is set to "/usr/libexec/java_home." ADB exists at /Users/guowenxie/Documents/adt-bundle-mac-x86_64-20140702/sdk/platform-tools/adb Android exists at /Users/guowenxie/Documents/adt-bundle-mac-x86_64-20140702/sdk/tools/android Emulator exists at /Users/guowenxie/Documents/adt-bundle-mac-x86_64-20140702/sdk/tools/emulator Android Checks were successful. All Checks were successful |
到此,環境基本準備好了。
最后,如果不想通過命令行安裝Appium,也可以安裝dmg

English » | | | | | | | | |
Text-to-speech function is limited to 100 characters