2007/07/26

Session-level statspack

Session-level statspack
Filed under: Performance — tanelp @ 3:23 pm

Statspack is a useful tool for easily gathering and reporting some Oracle’s historical workload statistics. However it has its limitations and problems:

One of them that in past it used to record only Oracle statistics, measured from inside Oracle. This made Oracle and people using Oracle ignore other crucial statistics like OS workload below Oracle. For example statspack may show you heavy latch contention as the performance problem, while looking at vmstat output one would see that the server just has been heavily overloaded with numerous other jobs (like multiple backup, export and compress jobs overrunning their run-window) and the latch contention is just a symptom of CPU starvation.

This has been somewhat addressed by adding V$OSSTAT to Oracle 10g and statspack now gathers this info as well. Now we need people to start looking into those stats.

Another problem with statspack is which is described in Dan Fink’s blog, about cursor-level CPU accounting limitations before 10gR2.

However neither of those problems are the main limitations of statspack. The main problem is that statspack samples it’s statistic snapshots from system level views like V$SYSSTAT and V$SYSTEM_EVENT. If every single session in your database is performing exactly the same (kind) of operation, then system level aggregates might be quite OK to get an overview what’s going on in the database. But from the moment you start having different kind of sessions (e.g. OLTP vs batch vs data feed vs report) in your database, then system level aggregates used by statspack do heavily distort what the reality looks like for specific sessions.

There’s another gotcha - by default statspack excludes the “SQL*Net message from client” wait event from main report section, stating that it is not important to look into idle events. However by that we will throw away an important piece of information when diagnosing end-to-end performance, the end user experience. The bad thing is that even if we did include the SQL*Net wait event in our reports (by deleting the corresponding row from STATS$IDLE_EVENT), then we would still have no idea how many of those gazillions of system-wide SQL*Net client wait seconds do belong to our specific session or user.
Statspack doesn’t measure session-experience, it just gives you a system-wide aggregate, which cannot be translated back to individual session statistics (just as you can not convert a hash value back to original value - most of the information is just lost!).

How to get session-level detailed overview of database performance, with historical reporting capability then?

Oracle 10g addresses this partially with ASH and AWR and DBMS_MONITOR’s selective statistic sampling ( V$SERV_MOD_ACT_STATS and V$CLIENT_STATS )

While ASH and AWR are both awesome products, they are not usable in Standard Edition nor before 10g ( you may want to check out Kyle Hailey’s ASH simulator instead ) and for using them you need to pay a separate license fee.

So let me introduce my attempt to solve those problems ( NB! Free stuff!!! ;):
The poor-man’s version of Automatic Workload Repository: It’s called… um… Semi-Automatic Workload Repository :)
The clever-man’s addition to statspack, which takes session-level snapshots: In other words, Sesspack.

The idea is very simple, just take snapshots of V$SESSION_EVENT and some V$SESSTAT (and V$SESS_TIME_MODEL in 10g) statistics and store those in a repository just like statspack does. Snapshots are taken using sesspack.snap_xyz procedures. As a parameter to these procedures I can pass a specific SID, a group of SIDs, a Oracle db username a OS-username or whatever filtering fields can be found from V$SESSION.

Once you have taken your snapshots when running the workload, you can run a report which calculates statistic and wait event deltas between snapshots and that it.

A demo?

The simplest one is to just snap my own session details:

SQL> exec sesspack.snap_me;

PL/SQL procedure successfully completed.

SQL> select avg(length(text)) from dba_source;

AVG(LENGTH(TEXT))
-----------------
114.01304

SQL> exec sesspack.snap_me;

PL/SQL procedure successfully completed.

SQL> @list

Snapshot Snapped
Snap ID Snapshot Time Taken By Mode Sessions
-------- -------------------- -------------------- ---------------------------------------- --------
1 2007-06-24 14:36:47 PERFSTAT SNAP_ME: PERFSTAT 1
2 2007-06-24 14:36:52 PERFSTAT SNAP_ME: PERFSTAT 1


The list.sql has shown that I have two performance snapshots, with ID 1 and 2, so I’ll run a delta report between them with script srs.sql (SAWR Report by SessionID):

SQL> set tab off
SQL> @srs 1 2

SNAPSHOT_BEGIN SNAPSHOT_END DUR_SEC DUR_MIN
----------------- ----------------- ---------- ----------
20070624 14:36:47 20070624 14:36:52 5 .083333333

ms/ ms in Waits in Avg Wait
SID AUDSID Event Name % Total sec snapshot snapshot ms
---------- ---------- ---- --------------------------------------------- ------------ ------- ----------- --------- --------
146 130096 db file scattered read |####### | 676 3378 338 10
CPU Usage |### | 260 1300 0 1300
db file sequential read |# | 44 220 6 37
SQL*Net message from client | | 1 3 3 1
log file sync | | 0 1 1 1
SQL*Net message to client | | 0 0 3 0

6 rows selected.


Another example which should bring the usefulness of sesspack out better:

I dirtied some buffer cache buffers using the delete command, then ran a alter system checkpoint between two snapshots of all background process activity (sesspack.snap_bg).

Tanel@Prod01> delete t;

50705 rows deleted.

Tanel@Prod01> exec sesspack.snap_bg;

PL/SQL procedure successfully completed.

Tanel@Prod01> alter system checkpoint;

System altered.

Tanel@Prod01> exec sesspack.snap_bg;

PL/SQL procedure successfully completed.

Tanel@Prod01> @list

Snapshot Snapped
Snap ID Snapshot Time Taken By Mode Sessions
-------- -------------------- -------------------- ---------------------------------------- --------
1 2007-06-24 14:36:47 PERFSTAT SNAP_ME: PERFSTAT 1
2 2007-06-24 14:36:52 PERFSTAT SNAP_ME: PERFSTAT 1
5 2007-06-24 14:57:49 TANEL SNAP_BG: 14
6 2007-06-24 14:57:55 TANEL SNAP_BG: 14

Tanel@Prod01> @ srs 5 6

SNAPSHOT_BEGIN SNAPSHOT_END DUR_SEC DUR_MIN
----------------- ----------------- ---------- ----------
20070624 14:57:49 20070624 14:57:55 6 .1

ms/ ms in Waits in Avg Wait
SID AUDSID Event Name % Total sec snapshot snapshot ms
------- ---------- ---- --------------------------------------------- ------------ ------- ----------- --------- --------
160 0 rdbms ipc message |##########| 1000 5999 6 1000

161 0 rdbms ipc message |##### | 500 3000 1 3000

162 0 rdbms ipc message |######### | 833 5000 1 5000

165 0 rdbms ipc message |##### | 496 2974 4 744
control file parallel write |## | 159 953 11 87
control file sequential read |# | 57 341 26 13
direct path write | | 0 2 12 0
direct path read | | 0 0 12 0

166 0 rdbms ipc message |##########| 998 5988 3 1996
log file parallel write | | 1 4 2 2

167 0 rdbms ipc message |######### | 818 4911 4 1228
db file parallel write |## | 123 737 93 8

168 0 rdbms ipc message |##########| 1002 6010 2 3005

169 0 rdbms ipc message |##########| 1000 6000 2 3000

170 0 pmon timer |##########| 1000 6000 2 3000

15 rows selected.


An overview of what all background processes were doing at that time :)
If you ever had to diagnose performance issues in a large-scale variable-workload environment with lots of completely different activity going on, you already see the value of session-level statistic snapshots.

When you read the readme, you see that there are various options for taking selective snapshots, like running:

sesspack.snap_sid(57);
sesspack.snap_sid(’150,165,177,202′);
sesspack.snap_orauser(’REPORT_USER’);
sesspack.snap_program(’sqlplus.exe’);
sesspack.snap_machine(’nycprd0005118′);

Also it is possible to snap based on completely custom conditions, using whatever SQL you write to return list of SID’s:
sesspack.snap_sidlist_internal(’select sid from v$session where state=”ACTIVE” and last_call_et > 300′);
sesspack.snap_sidlist_internal(’select sid from v$session where logon_time > sysdate - 1/48′);


Note that there are few crucial issues which need resolving in the snapshot engine (for example, waits are not recorded in V$SESSION_EVENT before event ends or times out, this is a problem with long waits exceeding snapshot interval).

The major work yet to be done is building easy reporting and visualizing capability as this is critical for any useful performance product.
I have experimented with Oracle Application Express for providing a convenient GUI and charting mechanism. Even though APEX charting is still not flexible enough for complex performance data visualization, nevertheless it looks promising! I will release it in version 0.06 perhaps, once rest of the crucial base features have been implemented. I’ll keep you posted.

It all is plain PL/SQL, you can download the package from here: http://www.tanelpoder.com/files/sesspack_0.04.zip

All feedback is appreciated, enjoy!

Fw how to use DBMS_PROFILER

DBMS_PROFILER
The DBMS_PROFILER package was introduced in Oracle8i to allows developers to profile the run-time behaviour of PL/SQL code, making it easier to identify performance bottlenecks which can then be investigated more closely.

The first step is to install the DBMS_PROFILER package:
CONNECT sys/password@service AS SYSDBA
@$ORACLE_HOME/rdbms/admin/profload.sql

CREATE USER profiler IDENTIFIED BY profiler DEFAULT TABLESPACE users QUOTA UNLIMITED ON users;
GRANT connect TO profiler;

CREATE PUBLIC SYNONYM plsql_profiler_runs FOR profiler.plsql_profiler_runs;
CREATE PUBLIC SYNONYM plsql_profiler_units FOR profiler.plsql_profiler_units;
CREATE PUBLIC SYNONYM plsql_profiler_data FOR profiler.plsql_profiler_data;
CREATE PUBLIC SYNONYM plsql_profiler_runnumber FOR profiler.plsql_profiler_runnumber;

CONNECT profiler/profiler@service
@$ORACLE_HOME/rdbms/admin/proftab.sql
GRANT SELECT ON plsql_profiler_runnumber TO PUBLIC;
GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_profiler_data TO PUBLIC;
GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_profiler_units TO PUBLIC;
GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_profiler_runs TO PUBLIC;
Next we create a dummy procedure to profile:
CREATE OR REPLACE PROCEDURE do_something (p_times IN NUMBER) AS
l_dummy NUMBER;
BEGIN
FOR i IN 1 .. p_times LOOP
SELECT l_dummy + 1
INTO l_dummy
FROM dual;
END LOOP;
END;
/
Next we start the profiler, run our procedure and stop the profiler:
DECLARE
l_result BINARY_INTEGER;
BEGIN
l_result := DBMS_PROFILER.start_profiler(run_comment => 'do_something: ' || SYSDATE);
do_something(p_times => 100);
l_result := DBMS_PROFILER.stop_profiler;
END;
/
With the profile complete we can analyze the data to see which bits of the process took the most time, with all times presented in nanoseconds. First we check out which runs we have:
SET LINESIZE 200
SET TRIMOUT ON

COLUMN runid FORMAT 99999
COLUMN run_comment FORMAT A50
SELECT runid,
run_date,
run_comment,
run_total_time
FROM plsql_profiler_runs
ORDER BY runid;

RUNID RUN_DATE RUN_COMMENT RUN_TOTAL_TIME
----- --------- ---------------------------------- --------------
1 21-AUG-03 do_something: 21-AUG-2003 14:51:54 131072000
We can then use the appropriate RUNID value in the following query:
COLUMN runid FORMAT 99999
COLUMN unit_number FORMAT 99999
COLUMN unit_type FORMAT A20
COLUMN unit_owner FORMAT A20

SELECT u.runid,
u.unit_number,
u.unit_type,
u.unit_owner,
u.unit_name,
d.line#,
d.total_occur,
d.total_time,
d.min_time,
d.max_time
FROM plsql_profiler_units u
JOIN plsql_profiler_data d ON u.runid = d.runid AND u.unit_number = d.unit_number
WHERE u.runid = 1
ORDER BY u.unit_number, d.line#;

RUNID UNIT_NU UNIT_TYPE UNIT_OWNER UNIT_NAME LINE# TOTAL_OCCUR TOTAL_TIME MIN_TIME MAX_TIME
----- ------- --------------- ----------- ------------ ----- ----------- ---------- -------- --------
1 1 ANONYMOUS BLOCK 4 1 0 0 0
1 1 ANONYMOUS BLOCK 5 1 0 0 0
1 1 ANONYMOUS BLOCK 6 1 0 0 0
1 2 PROCEDURE MY_SCHEMA DO_SOMETHING 4 101 0 0 0
1 2 PROCEDURE MY_SCHEMA DO_SOMETHING 5 100 17408000 0 2048000

5 rows selected.
The results of this query show that line 4 of the DO_SOMETHING procedure ran 101 times but took very little time, while line 5 ran 100 times and took proportionately more time. We can check the line numbers of the source using the following query:
SELECT line || ' : ' || text
FROM all_source
WHERE owner = 'MY_SCHEMA'
AND type = 'PROCEDURE'
AND name = 'DO_SOMETHING';

LINE||':'||TEXT
---------------------------------------------------
1 : PROCEDURE do_something (p_times IN NUMBER) AS
2 : l_dummy NUMBER;
3 : BEGIN
4 : FOR i IN 1 .. p_times LOOP
5 : SELECT l_dummy + 1
6 : INTO l_dummy
7 : FROM dual;
8 : END LOOP;
9 : END;
As expected, the query took proportionately more time than the procedural loop. Assuming this were a real procedure we could use the DBMS_TRACE or the SQL trace facilities to investigate the problem area further.

For further information see:
DBMS_PROFILER
DBMS_TRACE
Hope this helps. Regards Tim...

Fw how to use DBMS_TRACE

DBMS_TRACE
The DBMS_TRACE package provides an API to allow the actions of PL/SQL programs to be traced. The scope and volume of the tracing is user configurable. This package can be used in conjunction with the DBMS_PROFILER package to identify performance bottlenecks.

The first step is to install the tables which will hold the trace data:
CONNECT sys/password@service AS SYSDBA
@$ORACLE_HOME/rdbms/admin/tracetab.sql

CREATE PUBLIC SYNONYM plsql_trace_runs FOR plsql_trace_runs;
CREATE PUBLIC SYNONYM plsql_trace_events FOR plsql_trace_events;
CREATE PUBLIC SYNONYM plsql_trace_runnumber FOR plsql_trace_runnumber;
GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_trace_runs TO PUBLIC;
GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_trace_events TO PUBLIC;
GRANT SELECT ON plsql_trace_runnumber TO PUBLIC;
Next we create a dummy procedure to trace:
CREATE OR REPLACE PROCEDURE do_something (p_times IN NUMBER) AS
l_dummy NUMBER;
BEGIN
FOR i IN 1 .. p_times LOOP
SELECT l_dummy + 1
INTO l_dummy
FROM dual;
END LOOP;
END;
/
Next we run our procedure three times with different tracing levels:
DECLARE
l_result BINARY_INTEGER;
BEGIN
DBMS_TRACE.set_plsql_trace (DBMS_TRACE.trace_all_calls);
do_something(p_times => 100);
DBMS_TRACE.clear_plsql_trace;

DBMS_TRACE.set_plsql_trace (DBMS_TRACE.trace_all_sql);
do_something(p_times => 100);
DBMS_TRACE.clear_plsql_trace;

DBMS_TRACE.set_plsql_trace (DBMS_TRACE.trace_all_lines);
do_something(p_times => 100);
DBMS_TRACE.clear_plsql_trace;
END;
/
With the tracing complete we can identify the available RUNIDs using the following query:
SELECT r.runid,
TO_CHAR(r.run_date, 'DD-MON-YYYY HH24:MI:SS') AS run_date,
r.run_owner
FROM plsql_trace_runs r
ORDER BY r.runid;

RUNID RUN_DATE RUN_OWNER
---------- -------------------- -------------------------------
1 22-AUG-2003 08:27:18 TIM_HALL
2 22-AUG-2003 08:27:18 TIM_HALL
3 22-AUG-2003 08:27:18 TIM_HALL
We can then use the appropriate RUNID in the following query to look at the trace:
SET LINESIZE 200
SET TRIMOUT ON

COLUMN runid FORMAT 99999
COLUMN event_seq FORMAT 99999
COLUMN event_unit_owner FORMAT A20
COLUMN event_unit FORMAT A20
COLUMN event_unit_kind FORMAT A20
COLUMN event_comment FORMAT A30

SELECT e.runid,
e.event_seq,
TO_CHAR(e.event_time, 'DD-MON-YYYY HH24:MI:SS') AS event_time,
e.event_unit_owner,
e.event_unit,
e.event_unit_kind,
e.proc_line,
e.event_comment
FROM plsql_trace_events e
WHERE e.runid = 1
ORDER BY e.runid, e.event_seq;
The content of the trace record depends on the trace level being used. The available options are:
trace_all_calls constant INTEGER := 1;
trace_enabled_calls constant INTEGER := 2;
trace_all_exceptions constant INTEGER := 4;
trace_enabled_exceptions constant INTEGER := 8;
trace_all_sql constant INTEGER := 32;
trace_enabled_sql constant INTEGER := 64;
trace_all_lines constant INTEGER := 128;
trace_enabled_lines constant INTEGER := 256;
trace_stop constant INTEGER := 16384;
trace_pause constant INTEGER := 4096;
trace_resume constant INTEGER := 8192;
trace_limit constant INTEGER := 16;
Trace can be limited to specified programs by starting the trace with the DBMS_TRACE.%_enabled_% options. A program can have trace enabled using one of the following methods:
ALTER SESSION SET PLSQL_DEBUG=TRUE;
CREATE OR REPLACE [PROCEDURE | FUNCTION | PACKAGE BODY] ...
or:
ALTER [PROCEDURE | FUNCTION | PACKAGE] COMPILE DEBUG [BODY];
For further information see:
DBMS_TRACE
DBMS_PROFILER
Hope this helps. Regards Tim...

2007/07/25

nic alias

configure a network interface and alias. For example:
eth0 NIC IP - 192.168.1.5
eth0:0 first NIC alias: 192.168.1.6


To setup eth0:0 alias type the following command as the root user:

# ifconfig eth0:0 192.168.1.6 up


Verify alias is up and running using following command:

# ifconfig -a
# ping 192.168.1.6


However if you reboot system you will lost your alias. To make it permanent you need to add it network configuration file:

If you are using Debian Linux
Open the file /etc/network/interfaces:

# vi /etc/network/interfaces


Append text as follows:

auto eth0:1
iface eth0:1 inet static
name Ethernet alias LAN card
address 192.168.1.7
netmask 255.255.255.0
broadcast 192.168.1.255
network 192.168.1.0


Save the file and restart the network:

# /etc/init.d/networking restart


If you are using Red Hat / Fedora Linux
Copy etc/sysconfig/network-scripts/ifcfg-eth0 file etc/sysconfig/network-scripts/ifcfg-eth0:0 -

# cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0:0


Open file /etc/sysconfig/network-scripts/ifcfg-eth0:0 using vi text editor:

# vi /etc/sysconfig/network-scripts/ifcfg-eth0:0


Find entry that read as follows:
DEVICE=eth0


Replace with:

DEVICE=eth0:0


Find entry that read as follows:

IPADDR=xxx.xxx.xxx.xxx


Replace it with your actual IP address:

IPADDR=192.168.1.7


At the end your file should like as follows:

DEVICE=eth0:0
IPADDR=192.168.1.7
NETMASK=255.255.255.0
NETWORK=192.168.1.0
ONBOOT=yes
NAME=eth0:0


Open file /etc/sysconfig/network-scripts/ifcfg-eth0 and make sure file does not have a GATEWAY= entry:

# vi /etc/sysconfig/network-scripts/ifcfg-eth0


Find the entry that read as follows:

GATEWAY=192.168.1.254


Remove or comment it out by prefixing # (hash) :

# GATEWAY=192.168.1.254


Save the file. Add the GATEWAY= to your /etc/sysconfig/network:

# vi /etc/sysconfig/network


Append or modify GATEWAY entry:

GATEWAY=192.168.1.254


Save the file. Reboot the system or run the following command:

# ifup eth0:0


OR

# service network restart

2007/07/24

ORA-08104

発生したORA-08104エラーについて
エラー原因と対応方法を報告します。


背景:

テーブルのANALYZE失敗:

SQL> analyze table tmuser.m01_cust compute statistics;

analyze table tmuser.m01_cust compute statistics

*

ERROR at line 1:

ORA-08104: this index object 6571 is being online built or rebuilt



そして上記エラー対象の索引削除も失敗:

SQL> drop index IDX_M01_ADDR_CODE;

drop index IDX_M01_ADDR_CODE

*

ERROR at line 1:

ORA-08104: this index object 6571 is being online built or rebuilt



対応方法:

① 「REBUILD FLAG」が残っている索引を確認する。

SQL> select obj# from ind$ where bitand(flags, 512)=512;

OBJ#

----------

6571

② 対象索引の「REBUILD FLAG」を更新する。

SQL> update ind$ set flags=flags-512 where obj#=6571;



1 row updated.



SQL> commit;

Commit complete.



③ 更新後の「REBUILD FLAG」状態を確認する、「0」であれば、正常に戻ることを判断できる。

SQL> select bitand(flags, 512) from ind$ where obj#=6571;



BITAND(FLAGS,512)

-----------------

0

④ 索引削除できました。

SQL> conn tmuser/tmadmin

Connected.

SQL> drop index IDX_M01_ADDR_CODE;

Index dropped.



⑤ 索引再作成してANALYZEもできました。

SQL> CREATE INDEX TMUSER.IDX_M01_ADDR_CODE

ON TMUSER.M01_CUST

(ADDR_CODE_PREF, ADDR_CODE_CITY, ADDR_CODE_ZONE)

TABLESPACE USERS_INDEX_M01

STORAGE(INITIAL 128M MINEXTENTS 1) NOLOGGING;

Index created.



SQL> analyze table tmuser.m01_cust compute statistics;

Table analyzed.

可用性 mtbf & mttr

可用性 = MTBF / (MTBF + MTTR)

2007/07/19

f.y.i F5 overview guide

Users fed up with poor performing apps? Defuse the situation with expert application acceleration advice from F5

Enterprise DB - another choice of database

google apps

2007/07/17

CVS Setup

install and setup pserver


# check installation and version
rpm -qa | grep cvs
cvs-1.11.1p1-7

# if you hadn't installed cvs or the right version. just install it, or upgrade it.
rpm -ivm cvs-1.11.1p1-7
rpm -Uvm cvs-1.11.1p1-7
rpm -Fvm cvs-1.11.1p1-7

# create user and group for cvsroot user
groupadd -g 502 cvsroot
useradd -u 502 cvsroot -g cvsroot -G cvsroot

# add cvspserver to xinetd.d
cat << EOF > /etc/xinetd.d/cvspserver
service cvspserver
{
disable = no
flags = REUSE
socket_type = stream
wait = no
user = root
env = HOME=
server = /usr/bin/cvs
server_args = -f --allow-root=/home/cvsroot --allow-root=/home/cvsroot0/1 pserver
log_on_failure += USERID
}



setup password


# setup password
touch /home/cvsroot/CVSROOT/passwd

# cvsuseradd.sh - the script for cvsuseradd
perl ./cvsuseradd.pl $1 >> passwd

# cvsuseradd.sh - the script for cvsuseradd
cvsuseradd.sh
perl ./cvsuseradd.pl $1 >> passwd

cvsuseradd.pl
#!/usr/bin/perl

$username = $ARGV[0];
print "\n" . "$username:" . crypt("$username", "SB") . ":cvsroot";

2007/07/12

Free PHP Webhosting Servers

100 Webspace

English 100 MB Banner + TextLinks FTP, Browser CGI, PHP, SSI, Front Page Extensions, Perl Domain or Subdomain Bandwidth limit 3 GB/month. POP3, Catch-all emails, and Web-based Email. SSL. MySQL database. Webalizer Statistics. Password-protected files. Instant activation. File size limit 500 KB. 30-days Inactivity limit. SpamAssassin and Anti-virus protection.

HelioHost

English 150+ MB Banner-Top FTP, Browser CGI, PHP, SSI, Front Page Server Extensions, Perl Domain or Subdomain Bandwidth limit 1500+ MB/month. Cpanel, Fantastico. Unlimited addon domains. POP3 Email, Spam Assassin. Statistics, raw logs. Cron jobs allowed. Unlimited MySQL and PostgreSQL databases. Custom error pages. SSL Secure server.

Zend URL

English 500 MB No ads FTP, Browser CGI, PHP, ASP, SSI, FrontPage Server Extensions, Perl Domain or /dir/you Bandwidth limit 15 GB/month. PostgreSQL, MySQL databases. POP3 Email, Forwarding. Auto-responders. Add-on domain names. Cronjobs allowed. Webalizer free web site statistics. Custom error pages. Shared SSL Secure Server.

人民币升值考验高新技术企业 自主技术才从容

人民币升值考验高新技术企业 自主技术才从容
[日期:2007-06-11] 来源:中国高新技术产业导报 作者:沈敬怡 赵策 [字体:大 中 小]


进入5月份以来,人民币升值明显加速。中国外汇交易中心6月6日的数据显示,美元兑人民币的中间价,首次跌破2005年汇率体制改革以来7.6400的最低关口,报7.6398。



人民币加速升值,对我国高新技术企业,特别是高新技术产品的出口,究竟会带来怎样的影响?近日,本报记者带着疑问,采访了部分高新技术企业和一些业内专家。



记者发现,面对人民币升值压力,不同的企业有着不同的反应。拥有自主核心技术者从从容容;代加工低附加值产品者满腹忧虑。



或许,人民币汇率的变化,给我国的高新技术企业又上了生动的一课:只有坚持自主创新,拥有核心竞争力,才能在各种状况出现时处变不惊。



7.6488,7.6427,7.6398……



许强在办公室里踱步,一系列数据在他脑中反复出现,是调整报价还是削减员工?这个问题使他坐立不安。



许强是北京一家以芯片代工业务为主业的公司负责人,欧美国家的半导体企业是他的主要服务对象,低成本加工和组装是他的获利手段。



从今年3月开始,除了每日一小时的慢跑外,许强又多了一个习惯——去中国外汇交易中心网站看人民币汇率变化,因为汇率的任何微小变化都会引发客户资源的变化。



在中国,这样的企业还有很多。他们大多在东南沿海,价格优势是他们的生命线,尽管他们的利润率只有3%-5%;一旦失去价格优势,他们将失去客户乃至从这个行业中消失。



降低成本、削减价格,似乎成为他们生存的惟一出路。



厦华的调整



中国外汇交易中心6月6日的数据显示,美元兑人民币的中间价首次跌破2005年汇率体制改革以来7.6400的最低关口,报7.6398。



山东省外贸厅2007年第一季度的统计显示,海尔、海信等主要家电出口企业出口额分别下降了11.5%和62.1%。对此,山东省外贸厅给出的解释是:由于汇率变动,国外客户开始提出全年报价的要求,而企业考虑到汇率变化,只能选择提供短期报价,不敢签订长单,从而影响了客户的信心,部分客户开始寻找其他合作伙伴,这导致山东省高新技术产品出口增幅大幅回落。



与此同时,在福建厦门,一场针对汇率变动的战略调整已悄然展开。



厦华电子——中国最大的彩电出口企业之一,行销服务网络遍及世界五大洲119个国家和地区,去年出口总额超过4亿美元。这使厦华比其他企业有更多的机会,去感受人民币升值所带来的冲击。



根据海关出口统计数据(含外资企业),2006年厦华液晶电视和等离子电视的出口金额分别为2.7亿美元和1.19亿美元,分别占同期我国同类出口金额的6.33%和17.47%,分列行业第四和第二,其中大尺寸平板电视的出口比例占该公司出口总量的58%,但其年度报告却显示全年净利润为负值。年报将部分原因归结为市场竞争和人民币升值所带来的双重压力。



为了保持市场份额,价格上的妥协成为企业的一大选择,为了让买家满意,厦华针对长期客户采取了相应的降价策略;另一方面,在坚持以OED/ODM为主、自有品牌为辅的销售原则下,他们开始采取海外市场产品结构重组和培养VIP客户的策略。继续控制外汇风险以及增强海外分公司当地融资能力成为企业发展的重中之重。



厦华电子彩电出口市场分为北美、欧洲等几大区域,他们已经通过国际市场多元化来规避人民币兑美元汇率波动带来的影响,采取了适当控制对美国出口的策略,这意味着人民币升值只影响了他们对美国的出口销售,而在其他国家则依然以当地货币结算。



“通过价格调整和汇率风险规避策略,目前公司产品价格已基本实现了软着陆。”厦华电子有关人士表示。一系列调整过后,厦华电子公告显示2007年一季度净利润比上年同期增长1.93%。



据中国电子信息产业发展研究院IT经济研究所副所长刘军国分析,就电子信息产业而言,人民币升值尽管会对出口有一定不利影响,但不会动摇中国作为全球电子信息制造基地的战略地位。我国电子信息产业已经具备度过本币升值冲击的实力。产业集群的集中度高、基础稳固、产业链配套完善,降低了我国电子信息产业外移的危险。我国电子信息产业已经出现了一批具备国际竞争力的大企业,本币升值会刺激国内企业竞争行为加剧,加速我国电子信息产业结构升级。



博彦的争议



有媒体曾在报道中指出,人民币每升值1%,软件出口的利润将降低0.7个百分点;如果人民币升值3%,软件出口的利润率将降低到不足2%;如果人民币升值5%,整个软件出口几乎处于零利润状态。这对利润率不足4%的软件产业无疑会有极大的打击,对依然处于起步阶段的软件外包业务影响更加严重。



对于这种说法,博彦科技有限公司高级顾问曲玲年的观点却截然不同,“如果制造业还能生存,软件外包企业也能生存”。据他分析,国内加工制造业的利润率已经降到百分之几,而服务业目前的利润率依然在20%以上,并且这一利润还具有弹性空间,因此汇率对服务业并不具有决定性的影响。



事实上,中国软件外包业正处于高速增长期。北京软件行业协会软件进出口工作委员会秘书长李劲认为,在这样一个高增长率的状态下,一些轻微的波动是无法被察觉的。而随着外包企业渐渐做大,在项目单价不变的情况下,考虑到管理成本下降,利润率将会自动升高。



作为国内最大的软件外包企业之一,在汇率的急剧变动之下博彦科技并没有显现出太大的震动。



很少有从美国直接拿到的项目,大部分的美国公司项目都采用人民币结算,不存在汇率问题。因此,对他们来说,目前还无须针对汇率变动采取任何战略性措施。“现在制约这个行业最关键的因素是人力资源,此外还有国内的一些环境成本,比如物业、通信等。”曲玲年说。



另外,根据联合国贸发会议预测,2007年全球服务外包总值将达1.2万亿美元。世界最大的1000家公司中,大约70%的企业尚未向低成本国家外包任何商务流程。2006年,中国软件外包规模约为10.9亿美元,而印度软件和服务外包产业2006-2007财年总收入超过478亿美元。



在这场“龙象之争”中,竞争力的高低集中体现在劳动力成本上。近年来,中国外包业的蓬勃发展,正引起印度这个垄断着全球外包业务70%市场、欧美90%市场的外包大佬的关注。由于印度的价格成本不断在提升,一些海外市场已经开始瞄准中国。那么,人民币升值会不会影响这种趋势?



事实上,中国软件外包服务的价格相对印度来说依然很低。



最近,中国人民银行决定调高存款储备金比率至11.5%,同时将利率及人民币兑美元汇率的浮动幅度由0.3%扩大至0.5%。如果每年汇率保持3%-5%的变化,很难影响到软件企业的发展。



“认为影响软件服务外包竞争的仅仅是价格,这是一个非常错误的概念。”曲玲年表示,软件外包启动之初,价格因素在竞争中发挥了一定的作用,但实际运行一段时间以后,随着软件外包企业人员专业化程度的提高,专业服务带来的流程优化和高质量才是关键。



一些建议来自永威创投总经理谢忠高——对内降低成本,加强管理;对外争取长期稳定的客户合作;另外可采取人民币报价的方式规避汇率变动所带来的风险。



前两点建议很容易被企业接受和采纳,但对于以何种币种报价的问题,曲玲年的反应十分激烈:“客户和厂商谁是老大?供应商怎么可能会命令客户用哪种方式报价?”



“采取人民币报价可以将卖方风险转嫁给买方”,北京大学一位教授分析,但前提是要与对方建立长期稳定的合作关系。



华旗的微笑



一片喧嚣之中,却有一个人始终站在安静的角落里得意地笑。他就是华旗资讯总裁冯军。



一位来自中国人民大学的经济学专家认为,人民币升值将对出口IT产品的科技企业造成很大影响,因为此类产品销售周期较长,在一定的销售周期内降价显著,汇率变化将使产品的利润持续降低。但这一说法被冯军一口否认。



“我根本不关心汇率”,说这话的时候冯军底气十足。



爱国者的名气远远大于华旗资讯。作为国内一直坚持走自主创新道路的民族企业,经过近14年的成长,华旗资讯目前在国际市场上已占有相当的份额,其爱国者品牌的影响力日盛。



人们也许依然记得今年3月在德国CeBIT的IT盛会上,华旗资讯等数家国内数码厂商曾因为涉嫌侵犯意大利SISVEL公司的专利,被当地海关人员现场查抄,大部分产品也被当场扣留。



此后不久,这起侵犯专利事件被证明不过是一场误会。4月底,华旗资讯与SISVEL公司签署战略合作协议,该公司今后将在全球范围内推广华旗拥有自主知识产权的专利技术。



事实证明,握有品牌、核心技术、自主知识产权这三大法宝的企业的确无所畏惧。



从2003年10月华旗资讯以新的英文标识宣布其国际化战略全面启动以来,其销售渠道已经辐射东南亚、欧美等国家和地区,先后获得多笔价值数百万的国外订单,创造了连续10年增速超过60%的行业发展奇迹。



作为消费电子类的IT企业,冯军深知自主创新能力的重要。他们先后在北京、上海、深圳成立了多个研发中心,研发设计人员700多人,其中博士及海外归国技术人员占10%,硕士研究生占30%以上。



“中国的IT产品利润空间很大,即使在价格上作出调整,对企业的影响也不会很大。”冯军说,爱国者在国外的定价比国内高出50%,但因为品牌和技术上的优势,它的市场份额始终居高不下。



冯军有充足的理由漠视汇率变化。



作为高利润企业,他不在乎报价上的调整;作为国际知名品牌,他更不会因为汇率变动而降低售价,“这样可以赢得别人对品牌的尊重!”不仅如此,由于国外企业对人民币长期升值的预期,目前华旗资讯的业务量开始大幅度提高,长期合作业务量不断攀升。



拥有核心竞争力,才能在各种状况出现时处变不惊。



长江商学院教授赵昊的观点恰好印证了华旗之路。赵昊认为,人民币升值冲击最大的是附加值比较低的制造业,高新技术产品尤其是一些拥有自主核心技术的产品利润空间较大,对价格变化不敏感,相对于加工制造企业来说,自主研发的产品可替代性弱,这类企业应对汇率变动的能力很强。

软件中国2006的“微笑曲线”

软件中国2006的“微笑曲线”
2007.06.11 来自:CSDN  常政 [收藏到我的网摘]
产业链的重新洗牌:开源&教育 当然放眼全球,让长期困在世界软件产业链末端的中国软件业,实现整体提升,并不是中间件,而是正蔓延全世界的"开放源代码"震荡,因为它使得中国突然有了与世界IT列强站在同一起跑线展开
寥寥三千字扫描整个2006年中国软件业的状态是件困难的事 : 漫天飘舞的业绩与亏损的数据 ; 纷沓而至的新产品新技术 ; 目眩神迷的并购与融资……庆幸的是,90年代初宏基施振荣提出了一个概念,10多年来经过实践者们的演绎,已演化成可以概括整个产业发展的线索,借助它,至少可以对目前整个软件业的状态一窥端倪。这就是“微笑曲线”。它认为整个软件产业链包括“产品”、“代工(外包)”、“服务”三种模式,贯穿三者的是“创新”,同时由于上游和下游门槛最高、利润潜力最大,因此颇似一张微笑的笑脸。那么,2006年的中国软件业,其笑容是否灿烂呢?

全球扁平化的冲击波
《世界是平的》最近全球热销,因为它形象地描绘了当今全球扁平化的趋势。而对此推波助澜的一股重要力量就是外包。由于做外包,中国比印度有更多优势,所以“印度模式”的成功近年来一直激励着企业家和各级政府。据信产部官员透露,过去5年,中国软件外包的年均增长率超过50%,已在全国范围内形成以大连、上海、深圳、西安等为代表的外包基地,孕育出如东软、中讯、海辉、网新等一批龙头公司。2005年的规模是9.2亿美元,2006年持续着这样的强势,预计到2010年可达70多亿美元。但象征着希望的数字背后,质疑依然存在。最大的诟病是就整个软件产业链来说,外包自主创新的成分最低,更象是在做“编码民工”。但笔者认为,除了促进资本积累、创造就业机会外,外包可以大幅度促进经验不足的中国IT企业和西方先进企业管理文化的“无缝对接”。这种文化交汇的背后,给中国企业的做事方式、态度、眼光等方面带来的影响是深远的,它不仅提炼了企业成熟度和国际竞争力,甚至是滋生产品创新的土壤。
当然以上是基于团队作业和规模化生产的层面,如果深入到对个体的冲击,则是互联网技术和应用了,它使得原本弱势的网民突然拥有了影响和改变世界的可能性,以至美国《时代周刊》直接把“网民”作为2006年的年度人物。“猎户星在线写诗机”,上线没几天就被网民们“创作”出了几十万首“诗歌”,背后隐露的是草根们对长期独占社会主流话语权力的“文化精英”们的嘲弄和颠覆;而以“奇虎安全卫士360”为导火线所引发的声势浩大的“反流氓软件运动”,更是给各炮制流氓插件的厂商提了个醒:网民一旦有渠道抱成一团,便不再是“弱势”了!
权力移交至绝大多数人的结果,是资本找到了更广阔的增长空间。自然对服务的要求需重新定义:要重视用户体验、要强调用户的参与性、要个性化甚至娱乐化……技术也以此为导向,CSS、XML、RSS、TAG、AJAX、Ruby等,其技术含量,有些十分简单甚至陈旧,但通过彼此配合,却构建出五花八门的Web2.0服务。引导中国博客潮流的新浪BLOG、由大众评论来推荐信息的豆瓣网、在线阅读订阅的抓虾、搜索日常生活的酷讯等,在2006年继续处于“事业的上升期”;大笔的融资继续砸了过来,天际网、搜搜客、奇虎等甚至获得了千万美元以上的投资;新的数字英雄也在该领域诞生,Discuz!的创办者戴志康,正撰写着“新80后亿万富豪”的传奇,而史玉柱,2006年终于靠着网络游戏又杀回到了IT。
Web2.0的内核,是“以人为本”的理念,不能简单地理解为某种网站形态。大家所诟病的2006年大批Web2.0网站倒闭,笔者认为主要缘于“项目的重复投资”、“盈利模式单一”所造成的“资本泡沫”,不是Web2.0本身。互连网应用会继续发展,与传统软件业的整合、各细分市场的社区化模式将成为潮流,尤其是随着无线移动终端与传统互联网的集成已大势所趋,不难预见,整个Web2.0的展现形态即将开始重大的升级 : 无论是从资本的增长途径,还是服务的模式、广度与深度,都将进入全新的境界。

中国软件的“突围”
但对整个软件业,如过分偏重外包和互联网应用,会造成结构性缺陷,因为最大的蛋糕还是在于如基础软件这样的高端产品,在于企业信息化运用。毕竟两倍的印度外包业总额也不过是能抗衡一个微软公司。俯瞰软件中国2006,尽管涌现不少令人激动的创新,如已可取代TrueType 的自主字形技术MiniType 曲线字库 ; 解决了集成难题的永中集成OFFICE2007 ;一举获得了国际CES 2006 Innovation Award大奖的虚拟软件平台Aargo等……这些创新固然可喜,但都侧重于各细分市场,没有解决困绕了中国软件产业多年的先天结构缺陷 : 在基础软件(如操作系统、数据库)上,一直不具备与国外抗衡的实力。而它的成败直接影响到中国在整个世界IT产业链中的潜力和地位。
幸运的是,随着对社会(尤其企业)信息化的需求进一步深入,逐渐产生了一种新的基础软件形态——中间件。这给了中国一个机会,加上国外的相关市场已经饱和、中国企业更易理解由于国情引起的复杂运用,因此我们不难理解为什么金蝶的Apusic J2EE应用服务器、中创的InforEAI、浪潮的楼上、普元的EOS等,近年如雨后春笋般迅速地应用于金融、安全、电信、商业等领域。尤其是金蝶的应用服务器,已具备与国外巨头抗衡的能力,在2006年中国市场占有率上,同IBM的Websphere、BEA的Weblogic分列前三。
对于发展战略,“一流的企业做标准”几乎已成IT业内共识。2006年最著名的事件是WAPI的“功败垂成”。但软件企业家们并未因此却步,携书生SEP文档库技术,北京书生公司向OASIS组织正式提交了UOML的国际标准申请。但同前两者“自立为王”的策略不同,中间件厂商们并不与国际巨头们正面冲突,选择的是“融合与共赢”。金蝶自率先加入JCP组织后,新近发布的Apusic 5.0,又率先通过Java EE 5.0认证授权 ; 而普元软件应SOA发展潮流,2006年先后加入SCA/SDO两个重要国际组织,同样引人瞩目。从实效看,由于政治和文化偏见,主动融入国际技术组织比单纯地“分庭抗礼”稳妥,不仅拓宽了视野、提高了技术水准,而且大大提升了市场形象。倪光南院士曾预测,中国的国际软件巨型企业,最有可能在中间件领域诞生。

产业链的重新洗牌:开源&教育
当然放眼全球,让长期困在世界软件产业链末端的中国软件业,实现整体提升,并不是中间件,而是正蔓延全世界的“开放源代码”震荡,因为它使得中国突然有了与世界IT列强站在同一起跑线展开竞争的机会。而此基础上,想再来个“质”的飞跃,则要靠一句老话,“百年大计,教育为本”。
软件“智慧”的彻底开放,大大削减了中国产品自主创新的探索成本,尤其是Linux这只企鹅,使长期徘徊于核心技术之外的中国人终于冲进了基础软件最古老的堡垒——操作系统。尽管影响力还不能与国外的红帽、Ubuntu抗衡,但2006年中国Linux厂商们的探索值得称道,如全面采用Linux2.6内核的中标普华Linux桌面3.0、全球率先通过了LSB3.0测试的红旗Linux5.0等 ; 而2006年4月四部委联合发文,要求售出电脑必须预装正版操作系统,客观上也推动了Linux的进一步普及。以召开“2006 开源中国 开源世界”峰会为标志,2006年是中国开源界全面拥抱世界的转折点。在与国际开源界的技术交流、思想碰撞中,令人尴尬的评价终于显露 : MySQL创始人David Axmark认为中国并不真正理解开源事业;而Intel开源总监Dirk Hohndel更是直言不讳,说“中国只是个开源消费者”。言语刺耳,却中肯。确实许多国人对开源的态度,如“天上掉下的免费蛋糕”,偏重短期效益,忽视了开源背后体现的“自由共享”精神,并没有把它当作一个长期的事业来经营。甚至至今中国还没有一个象样的开源社区,而一度闹得沸沸扬扬的“银河麒麟”事件,背后显露的是对GPL规则的不熟悉。看来中国真正与世界开源的节奏共振,还需要一段时间。
至于2006年的IT人才,还延续着以往的窘境 : 招聘市场“供需两旺”,企业招不到人,人找不到工作 ; 泱泱大国至今鲜有能影响整个软件工业的大师。这缘自高校主流计算机教育和科研机制的尴尬 : 过分偏重基础理论,与实践脱节(但一味迎合需求又会造成人才底蕴的缺失);各大科研所一般没有具体产业化的压力,造成许多科研精英的才华都耗在空中楼阁般的理论和论文中。当然事情正在变化,创新已经到了瓶颈、迫于竞争压力的厂商们,正纷纷把眼睛投向了各大科研机构 ; 而各种培训机构和认证一直绵绵不绝般地出现,正弥补“教育和需求”的真空 : IT培训,2006年已然成为一个如火如荼的产业。
新年即将来临,2007届IT毕业生已经奔波于各大人才市场了,他们于人头攒动中投出的简历如雪花般飞舞;如果镜头远些,是中国各大软件公司工作间忙碌的键盘敲击声、电话铃声、文件翻阅声 ; 再远一些,则是全球化、互联网、开源的一次又一次冲击,它们正改变着中国整个软件产业链产品创新的速度、方式和做事的规则,它们正在调整供需双方的博弈位置,它们正在重新定义服务的理念,而这一切的背后又有资本的力量、对卓越的追求正源源不断地提供动力……所有这一切,包括其背后蕴藏的无限生机,使得我们已经可以如此回答文章开头的问题 : 软件中国2006的“微笑曲线”,尽管不能说“春光灿烂”,但至少,笑得意味深远。

Fw CMMI如何成为软件外包的“通关牒文”

CMMI如何成为软件外包的“通关牒文” (1)

发布时间:2007.07.03 09:59 来源:赛迪网-中国计算机报 作者:罗提


2006年底,商务部制定了“千百十工程”,其中内容包括“力争5年内促进700家企业取得CMM/CMMI3级认证,300家企业取得CMM/CMMI5级认证”。CMMI认证是什么,它对企业意味着什么?

CMMI有如中国软件外包企业进入国际外包市场的通行证

时间:

2007年6月13日

地点:

赛迪大厦17层会议室

形式:

中计在线嘉宾现场对话


对话嘉宾:

解明明

北京斯福泰克科技发展有限公司总经理

宋万辉

北控软件有限公司副总经理

CMMI(Capability Maturity Model Integration,简称CMMI)是专门针对软件行业的一个过程改进方法和规范,是衡量软件外包质量的重要标准之一,有如进入国际软件外包市场的通行证。在中国大力推行软件外包的今天,CMMI认证在中国发展得如何?软件企业在申请通过CMMI认证的过程中存在着哪些问题?

不能单纯为过级而过级

主持人:现在某些软件企业过级带着应试教育的影子,只是单纯地为了过级而过级,过了之后,反而会有下滑的现象。这种现象会导致很多问题。请谈谈造成这种现象的原因以及产生的弊端。

宋万辉:我认为,这种现象并不是企业单方面造成的。现在很多项目招标都会有这样或那样的级别要求,这些要求本来是为了保障项目能够高质量地完成,但事实上当你出示了级别证书之后,没有人会检查你的水平是否真的达到了级别要求。企业都是要赚钱的,如果只把级别证书做为一个标志性的证据,那么企业肯定会想方设法花很少的钱,在较短的时间内得到证书。这对于项目本身来说,是非常不利的。

主持人:解总,您作为评估方,怎么保证被评估企业最终通过CMMI认证,又怎么保证级别的权威性和有效性呢?

解明明:针对服务对象,我们首先要问清楚,你们到底要的是什么?有的企业很明确地说,就是为了过级。我认为这无可厚非,但我们也非常明确地讲,这些企业不是我们服务的对象。

主持人:你们遇到这种情况会拒绝吗?

解明明:首先,我们会建议服务对象通过咨询和学习,了解CMMI真正意义,从而改变态度,真正来做。如果他们同意这个意见,接受了我们的建议,还是可以合作的。如果他们不采纳,我们将选择退出,这是我们的原则。其实,我们碰到的95%以上的客户都是真正要过程改进,要提高自身的开发能力、管理能力的,只有少数客户是为了过级而过级。

再有,实事求是地讲,在过去一些年中,单纯为了过级而过级的现象对于中国软件企业,特别是外包企业来说,已经带来了很坏的负面影响。尤其是目前美国加强了对这方面的质量控制和审计,特别是对过了4、5级的企业都会抽样审计。一个企业踏踏实实过了2级,人家相信你,如果一个企业过了5级,但是一审计,你3级都达不到,认为你造假,那么项目肯定不会包给你。

主持人:这种现象对于评估企业来说,是不是也有很不好的影响?

解明明:是这样的。我们公司有非常严格的原则,任何企业的管理者和领导人都不能对主任评估师施加压力,迫使他们让没有达到标准的企业强行过级,能不能过由主任评估师自己决定。我们的主任评估师都是非常有职业操守的人,勉强通过会影响他们个人的信誉和公司信誉。

主持人:解总,了解到您们是SEI (Software Engineering Institute,软件工程研究院)的合作伙伴,怎么成为合作伙伴的呢?怎么才能具有这种认证的资质?

解明明:SEI对合作伙伴有三个基本要求,一是要有评估及咨询服务的经验和案例,二是要有足够经验的主任评估师和咨询专家,三是在他检查和审计过程当中,没有发现作弊或者放水的情况。SEI合作伙伴要负责监督和管理公司下属的主任评估师。

CMMI整固公司系统

主持人:CMMI资质认证对软件企业的好处和实际意义,具体体现在哪些方面?

宋万辉:这其实是一个很大的问题,我认为应该放在整个企业经营的范围、经营的角度及企业生命周期中来考虑这个问题。作为软件企业,我们要生产产品和加工服务,因此后台要有强大的、质量稳定的生产系统做支撑,从这个角度来看,CMMI对我们的意义非常大。

说得具体一些,因为每个企业要完成自己的使命,需要稳定的系统,包括很多的程序,是脱离人治的系统,CMMI的最大意义就在于可以帮助企业整固这套系统。如果这套系统原来就是零,CMMI不会把从来没有的系统从零搭建成5级,这不现实,没有一个企业是这样的。

如果单纯为了一个项目或工程,把CMMI拿过来,大家背下来,把级过了,其实没有什么意义,系统根本没有留下来。如果这个企业是做外包的,人一下子走掉了一半,它的系统仍然运转得很好,产品质量很稳定,成本控制得也不错,各方面的指标都很好,那说明CMMI帮他整固了系统。

主持人:对企业来说,有这么一套系统,是不是就不用过于担心人员流动的问题了?

宋万辉:担心流动只是一个体现,对每个企业来说,重要的是一个系统,这套系统包括很多层面,如财务、沟通、市场渠道、现金管理、法律层面,并由很多子系统组成。任何企业想在市场中生存,这个系统必须高效,如果不高效,它的垄断或它的资源一旦耗尽,一定会垮掉。

咨询和推广过程最关键

主持人:现在国内做CMMI认证培训咨询的公司有多少家?斯福泰克有什么样的特点和与众不同的地方?

解明明:国内做CMMI认证培训咨询的公司至少有几十家,规模和历史都不太一样。有一定规模的大约在10家左右。斯福泰克是较早提供咨询服务的公司。我们当时回中国推行CMMI,主要是为了赶超印度外包,把中国外包产业带动起来。

我们提出一个概念,尽可能培养国内专家,既懂CMMI、又懂开发的人,作为辅助企业做过程改进的顾问。我们最早培养的这批人,有咨询师的特色,中国软件产业的发展和这些咨询专家的努力是分不开的。

主持人:如果这样的话,你们与被评估公司双方的合作关系不仅仅局限于评估和认证,也会对他们进行培训和咨询。你们其实是把国外的系统推介到中国来,可能中国人一开始还不太明白这套系统是怎么运作的,需要一边学习,一边评估。

CMMI如何成为软件外包的“通关牒文” (2)

发布时间:2007.07.03 09:59 来源:赛迪网-中国计算机报 作者:罗提


解明明:对,关于你说的有一些体会,请宋总讲讲。

宋万辉:我们跟斯福泰克正式合作之前做过一些调查,市场上有很多认证,虽然都很好,但我们不想做。因为我们找不到一个真正帮我们的体系,能用这套体系,通过给你提供专业的咨询服务以及培训,让你的系统更加稳固。

后来经过考察,斯福泰克的想法和我们非常一致,就开展合作了。咨询师跟企业频繁交流,他们更了解企业,了解企业目前现状,了解企业需要什么,哪些方面是强项,哪些方面是弱项,所以给企业的建议相当具体,并且帮助企业改进。

主持人:请解总具体介绍一下咨询、评估的流程,有哪些关键要素?

解明明:目前CMMI大概有以下几个步骤:第一个步骤,对企业进行现状调查分析,提出企业目前的弱项,整个过程当中存在哪些需要改进的地方;第二步,由SEI授权的咨询师对企业进行培训;第三步,由咨询师协助企业建立企业自己的EPG(组织过程改进)组,建立起自己的整个规范和流程,这个过程我们称之为咨询和项目推广过程,它是非常重要的,将成为成功的关键。

这部分完了以后可以做预评估,也就是模拟评估,像正式考试之前的模拟考试,预评估完了以后,找出弱项再进行一段时间的改进。最后就是正式评估。大概要经过四到五个阶段。

主持人:一个3级认证拿下来平均需要多长时间?

解明明:现在做3级评估基本上需要一年到一年半的时间。比如宋总所在的北控软件有限公司现在已经做了18个月,马上要做预评估了,属于做得比较踏实稳健的,大概18~20个月可以过3级。

宋万辉:刚才解总侧面提到了关键因素,从企业来看,我认为关键因素有三点:第一,要求企业做这个工作的人知道往何处去。第二,要诚实。我们有什么问题,别人批评我们,要如实表述。第三,要勇敢。可能会发现很多问题,要勇于面对现实。这三点做到了,改进的机会就很大。

主持人:过程改进操作方法和有效技术手段缺乏的问题是否已得到解决?

解明明:过程改进操作方法和有效技术手段,是两个概念。过程改进首先是思想观念上的一个认识,在做的过程当中,需要有效的介入手段,比如用到一些工具。但我们认为没有任何工具是适合所有企业的。厂商提供的工具是否适合于企业,由企业的类型、规模、人员素质以及工作内容所决定,还有企业所能承受的费用也起到一定的作用。确实没有办法说哪个公司的工具可以包打天下。现在只能部分解决,没有一个全面的解决方法。

宋万辉:我比较同意解总的说法,这也是斯福泰克比较可贵的地方。第一阶段既然传播价值观念和最佳实践,平常用什么就用什么好了,因为这是价值观念的改造和系统方面的改造。第二阶段才进入高速提效阶段,当你的系统稳固以后,你发现在某些方面投入更有价值,这时候Soft Tech会给你一些更专业的建议,如果一开始向你推销很多工具,可能很多工具用不上,是浪费的。

CMMI与生存压力不矛盾

主持人:过程改进是个过程,保持这种改进更是一个过程,认证以后还要继续保持这个状态,保持系统的有效性。面对市场压力,应该如何让改进持续下去?

宋万辉:针对这个问题,不能单纯论过程,因为过程是系统的一部分。好多企业这样认为,当你面对市场压力的时候,才会在生存和改进之间作出选择,我认为这是不对的。如果按照这个逻辑,可能企业不用面对市场压力就已经死掉了。因为每个企业都面临竞争,竞争是有压力的。如果因为有压力,才选择要么自我改进,要么逐利,我想这个企业应该不是解总的客户。

解明明:如果当企业的生存压力与过程改进有冲突时,我认为生存压力要放在第一位,任何时候生存压力都是要放在第一位的。但是有一条,如果什么档案都没有留下来,什么东西都放弃的话,你后期的服务也可能拖垮你的公司,因为你什么都没有。甚至走几个人都会拖垮你的公司,怎么办?所以要分析清楚哪些东西是主要的,分清主次。

更主要的一点,我们应该尽可能早地健全我们的管理体制,无论在任何时候,都能保持企业最基本的管理规范。或者通过前期做很多工作,积累下来很多可复用的模板和模块,在压力很大的时候也可以保持规范化管理和质量。

宋万辉:解总这句话相当于CMMI让我们更善于在压力下正确的思考。

解明明:在初期,没有建立起体系的时候,紧急的情况下必须放弃一些管理规范。当你的CMMI做到一定程度,做得很规范的时候,你把很多的成果都已经积累下来变成成熟模块的时候,将来你在很紧急的时候就捡几个模块搭积木,这时候你不会认为CMMI和任务有冲突,反而是有帮助,因为CMMI最重要是建立可复用体系。

印度的几家大公司成立得相对都比较晚,但利润很高,原因在哪儿,它在接单的时候会仔细评估它的价值,评估的时候,估值非常准。之所以比较准,是因为它建立了一个非常好的数据库,把过去每一个类型的软件都进行分解,一些模块弄得很好。这么算下来以后价格比人家还要低一些,但是利润还要高一些。这就是当两个问题发生冲突的时候,CMMI越成熟,建立的体系越好,有压力的时候,能对抗和解决问题的能力就越强。

等边三角形最稳定

主持人:最后问一个额外问题,感觉CMMI主要还是注重工作的流程化,非常客观的系统,但是每一项工作最终还是要落实到各种各样的人来做,这有很多主观变动性,CMMI如何考虑这方面的问题,其中有没有包含对人员的管理?

解明明:这是一个非常好的问题,其实决定一个软件开发企业的好坏可以用三角形解释,三角形一个边是技术,一个边是过程,第三个边就是人力资源,当是等边三角形的时候,这个企业最稳固,质量最高。技术是指你开发团队的编程能力、技术能力,过程就是CMMI程度如何。CMMI和人力资源的关系是什么?我认为,实际上CMMI本身就有一个关于人力资源的评估体系,这体系跟CMMI评估体系差不多,只是关注的点不同。用CMMI这套体系,不但能够解决过程改进问题,而且CMMI人力资源体系可以解决人力资源管理问题。整个指导思想是差不多的,模式也差不多。

宋万辉:我同意解总的观点。因为人力资源是为整个企业服务的。CMMI里面讲的人更多的不是谈个体的人,它一直讲团队,它的团队不是随便几个人凑在一起就可以了。要完成一件事需要不同水平、不同知识面的人处在一起有机互动,这才是团队。既然提到目标和要求,这恰恰是人力资源管理的基本要求,如果整个企业做的都是这件事,我认为,人力资源跟团队管理要完全结合在一起,如果脱钩的话,那人力资源部就形同虚设,不过发发传单,面试面试人,其他作用不会太大。

点击CMMI

CMMI全称是Capability Maturity Model Integration, 即软件能力成熟度模型集成模型,是由美国国防部与卡内基-梅隆大学和美国国防工业协会共同开发和研制的。CMMI是一套融合多学科的、可扩充的产品集合,其研制的初步动机是为了利用两个或多个单一学科的模型实现一个组织的集成化过程改进。

CMMI分为5个等级,25个过程区域。

初始级 软件过程是无序的,有时甚至是混乱的,对过程几乎没有定义,成功取决于个人努力。管理是反应式的。

已管理级 建立了基本的项目管理过程来跟踪费用、进度和功能特性。制定了必要的过程纪律,能重复早先类似应用项目取得的成功经验。

已定义级 已将软件管理和工程两方面的过程文档化、标准化,并综合成该组织的标准软件过程。所有项目均使用经批准、剪裁的标准软件过程来开发和维护软件,软件产品的生产在整个软件过程是可见的。

量化管理级 分析对软件过程和产品质量的详细度量数据,对软件过程和产品都有定量的理解与控制。管理有一个作出结论的客观依据,管理能够在定量的范围内预测性能。

优化管理级 过程的量化反馈和先进的新思想、新技术促使过程持续不断改进。

每个等级都有几个过程区域组成,这几个过程域共同形成一种软件过程能力。每个过程域,都有一些特殊目标和通用目标,通过相应的特殊实践和通用实践来实现这些目标。当一个过程域的所有特殊实践和通用实践都按要求得到实施时,就能实现该过程域的目标。 (责任编辑:王林)

Fw How to use mutt email

MuttMutt email 程序使用入门 作者:王垠

"All mail clients suck. This one just sucks less." -me, circa 1995

你也许听说过这句话?这不是危言耸听,我还没有遇到一个令我满意的 email 程序,直到我遇到 mutt。它不是图形界面的,但是它非常强大和方便。我曾经把它忽略,但是后来我发现其它 email 程序都有某种我不喜欢的怪毛病。最后我选择了 Mutt。

有人说 Gnus 才是最好的 email 客户端,可是 Gnus 要达到 Mutt 这种效果和方便程度,你需要付出太多代价。所以我宁愿使用 Mutt 调用 Emacs 来编辑 email 而不愿把 Gnus 配置来处理 email.
Mutt 的特点

mutt 具有以下特点:

* 超强的信件分类功能

你可以设置几乎任意的条件来从一堆信件里找到你所需要的那封。比如,你可以说:“只显示一个月之类,不是清华大学发来的,内容包含‘光盘’两个字的信件”,“把从 fvwm 邮件列表一个星期以前发来的,而且还没有看过的信件全部移到叫 old-fvwm 的信箱”……
* 信件打分排序功能

你可以给你的信件打分,比如我说:
o 主题包含 "Circulation Notices" 的 +3 分。否则小心被图书馆罚款 :P
o 从我爸爸发来的信件 +2 分。听爸爸话……
o 主题包含"通知"两个字 +2 分。随时听取党中央号召 :)
o 主题包含"believe me", "believe.*dream", "win.*free" 字样的, -1 分。这些一般都是广告。
o 新的信件 +4 分。新的应该最先看。
o 新的而上次忘了读的信件(old), +1 分。可能太忙了上次忘了看的信,这次应该先看。

信件最后的得分就是它的这些分数相加的结果。这样处理之后,你最想看的信件肯定就在最上面了。
* 几乎任意条件的彩色设置

你看我的 Mutt 可以变成这个样子。当然这太花了,我不会设置这么多颜色的 :)

mutt-color
* 可以随意绑定热键

这个功能类似 Emacs。你可以把几乎任意的功能绑定到键盘。你可以让 Mutt 的行为变成你喜欢的编辑器。比如我习惯了 VIM 的控制方式,我就把 "gg" 绑定到 "first-entry", 把 "G" 绑定到 "last-entry", 把 "Ctrl-F" 绑定到 next-page, 把 "Ctrl-B" 绑定到 previous-page.
* 设置条件挂钩

你可以对满足不同条件的信件,信箱采取不同的设置。比如,对于用来收邮件的那些信箱,显示邮件时只显示 from, date, subject, x-mailer 这几个邮件头,而对 sent-mail 信箱还显示 to 这个邮件头;发给我家人,朋友的信件都存到一个特别的信箱中保存。
* 批量邮件处理

你可以把一些邮件作上标记(tag),然后对它们进行同意操作,比如删除,存到其它文件,删除附件,……
* 任选编辑器

用一个强大的编辑器来编辑你的 email 你才能高效的完成编辑。一般 email 客户端都是用的自己内嵌的编辑器,这些编辑器一般功能很弱。mutt 并没有试图自己写一个编辑器,因为它明显不可能超过 VIM 和 Emacs, 所以 mutt 可以让你自己选择你喜欢的编辑器,它会去调用它,并且设置很多方便编辑 email 的参数。编辑器编辑完毕后 mutt 会从编辑器得到编辑好的文本,然后你可以加附件什么的。我现在在 mutt 里使用 Emacs 编辑器。
* 高级的 MIME 支持

Mutt 不像一般的 email 程序那样直接支持打开某些种类的附件。因为附件的种类实在太多,一个 email 客户端没有可能自己实现所有的功能。所以 Mutt 提供了 .mailcap 的设置。你可以启用你最喜欢的程序来打开某种特定类型的附件。比如,我可以让 lynx 帮我把含有 HTML 附件的信件都转成文本在 Mutt 里显示,我让 ImageMagick 的 display 程序帮我显示图片……
* 支持PGP加密

Mutt 可以利用 GnuPG 这样的程序来对信件进行 PGP 加密和数字签名。别人可以用你的公用密钥给你发一封只有你才能看到的信件。你也可以用你的私有密钥给信件“签名”,收到信的人可以用你公布的公钥验证这封信确实是你发出来的。
* Mutt是免费的

听了上面那么多好处之后,还有比这更好的消息吗?

Mutt 到哪里去找?

Mutt 的主页在 http://www.mutt.org/。上面有所有源程序和说明文档。
Mutt 跟其它 email 程序有什么重大区别吗?

Mutt 显然是一个 Unix 的邮件程序,它跟一般的 Windows 邮件程序不同,它不是一个包罗万象的大杂烩。你甚至会发现它根本不直接发出邮件,它从来不自己编辑邮件,它从来不自己对邮件进行加密和数字签名……

Mutt 更像一个文件管理器,只不过它管理的是email。它的功能是借助各个最强大的程序来实现的。这符合 UNIX 的设计思想。

* 当 Mutt 需要编辑邮件时,它有可能调用 Emacs, vi, VIM, pico, ……等编辑器。
* 当 Mutt 需要发信时,它把需要发出的信件放到 sendmail 的队列里,就什么都不管了。
* 当需要数字签名时,Mutt 会把信件交给 GnuPG 之类的程序处理一下,然后再发出去。
* 怎么收邮件呢?Mutt 不会自己到 POP 服务器去取邮件,你需要一个 fetchmail 程序,帮你把 email 从 POP 服务器取回来,转发到自己的 sendmail 的邮箱里。这样看起来就是你的主机成为了一个完整的 UNIX 网络工作站。

是不是觉得挺麻烦?其实有些 patch 可以使 Mutt 不依赖于这些程序,而自己处理收发工作。但是,强烈建议你使用这些外部程序!到时候你就知道这些东西的好处了。首先,VIM, sendmail, fetchmail 这些程序都是经过千锤百炼的质量信得过的程序,用它们编辑,发送,收取邮件你绝对放心。其次,你得到了一个 UNIX 网络工作站的功能:

* sendmail 不但可以帮 Mutt 发出邮件,也可以帮其它 Unix 程序比如 tin 发送邮件。如果你需要一个邮件服务器帮你中转,那么你只需要设置一次就可以使所有的用户的所有这样的程序都自动可以发送邮件,不用每个程序都去设置帐号了。
* fetchmail 收到邮件之后会转发给本地的 sendmail. sendmail 如果允许 .forward, 你就可以在自己的目录里编辑一个 .forward 文件,信件可以自动被转发到其它地方或者经过一个过滤器过滤。你可以自己用perl等语言来写一个过滤器,它可以根据信件内容实现很多功能,比如自动回复等等。比如我就写了一个简单的过滤器,它可以记录所有发件人的地址,如果我把 helloooo 机器人连接到过滤器,恐怕你们就会收到可爱的 helloooo 的回信了 :)

Mutt 使用指南

Mutt 的用法类似 VIM。你的每一个键都是一个命令,你可以在配置文件~/.muttrc设置很多选项来改变 Mutt 的行为。我没有太多时间写一个入门的介绍。你可以自己看看 Mutt Manual。我下面只解决一些中国人用 Mutt 常常遇到的问题。
基本配置

你一开始看到 Mutt 说明书上说的配置方法可能不知所措。现在我把你开始用的时候需要的一些必要的配置说一下。

1. alternates

这个变量应该设置为一个正则表达式,它是你有可能收到信件的地址。比如我的很简单,只有一个地址:

set alternates="wang-y01@mails.tsinghua.edu.cn"

这个变量有助于 Mutt 显示邮件的地址特征。一般 Mutt 会在index中显示几种不同的邮件地址特征,它们是由 $to_chars 变量指定的。
2. to_chars

一般 $to_chars 的定义为 " +TCFL".
* " "(空): 表示这封邮件不是给你的,也就是说 To: 和 Cc: Bcc: 都没有你的地址,很多转发的邮件,未确认的邮件列表邮件,垃圾邮件都有这个特征。
* +: 表示你是收件人(To: 是你的地址之一),而且是唯一的收件人。
* T: 表示你是收件人(To: 包括了你的地址之一),但是你不是唯一的收件人。这是一封群体信件。
* C: 表示你的地址出现在 CC:,但是你不是唯一的被抄送的人。
* F: 表示这封邮件是你发出去的。
* L: 表示这是一封你已经加入的邮件列表寄来的。

你看看下面这幅图,就是mutt 有可能出现的一种列表,你看到地址特征没有?实际上地址特征出现在列表中的位置是可以改变的。待会儿在 $index_format 里你会看到的。

mutt-to
3. index_format

这是一个格式字符串,用来控制你的index的列表显示。它的缺省定义是:

set index_format="%4C %Z %{%b %d} %-15.15L (%4l) %s"

显示出来就是这个样子:
index-original

这里有一个简单的对应关系,%4C表示4位数的序号,%Z是邮件状态,你看到那个 "r" 了吗?也就是说我已经回了这封信。%Z 还包含那个 "T", 也就是说这封信不只是寄给我一个人的,我爸爸每次寄信都会CC他自己一份 :) %{%b %d} 是日期格式,它是由 strftime() 函数的格式定义的。这里 %b 就是根据当前的 locale 设置的月份简称,“12月”。%d 就是十进制表示的每月的日号,“31”。后面的……你自己看看manual吧,我不罗嗦了。
4. mailboxes

指定你有那些信箱文件。当你按 "c" 切换信箱时,再按 Tab 键,这些信箱就可供你选择。

mailboxes Mailbox sent-mail

5. header

这是一个 bool 型变量。它表明你在回信时引用原文是否加入原文的邮件头。

set header=no

6. quit

mutt-quit

可以设置为 yes, no, ask-yes, 或者 ask-no. 这是说,当你按q退出时,是否提示你(ask-yes,ask-no),还是直接就退出了(yes),还是根本不理你(no)。

set quit=ask-yes

7. auto_view

那些类型的附件是允许直接通过 .mailcap 浏览的?

auto_view text/html

8. move

这也是一个提示性变量。它是确定当你退出时,是否提示你把信件从 spool 移动到的 mbox 文件。

set move=no

9. ascii_chars

当 Mutt 用 thread 方式显示时,是否用纯 ascii 表示树状列表。

set ascii_chars=yes

如果设置了就是这个样子:
mutt-ascii
10. include

回信时是否包含原文。

set include

11. indent_str

回信的引文之前插入那个符号?

set indent_str="> "

12. my_hdr

设置你自己的邮件头。比如我想让信件看上去是从 wang-y01@mails.tsinghua.edu.cn 发出的,而不是从 wy@wangyin.com 发出的。因为 wangyin.com 是我自己设置的主机名,不是注册的合法域名。我想让别人看到我的信是从我的清华信箱发出的,让他们直接回信到我的清华信箱,就这么干:

my_hdr From: wang-y01@mails.tsinghua.edu.cn

13. 打分

新信件+4分,爸爸(w2r007)发来的 +2,主题包含“通知”的+2,主题包含 “Circulation” +3, 已经标记删除的 -5,上次没有读的 +1,包含 “believe”的 -10(垃圾广告!)。

score "~N" +4
score "~f w2r007" +2
score "~s 通知" +2
score "~s Circulation" +3
score "~D" -5
score "~O" +1
score "~s believe" -10

14. sort

排序方式。可以是

date
date-sent
date-received
from
mailbox-order (unsorted)
score
size
subject
threads
to

几种方式,每种方式可以在前面加一个 "reverse-" 前缀表示反方向排序。我一般按分数排序:

set sort=score

15. sort_aux

当用 thread 排序方式时,我们对各个 thread 的相对排序顺序。

set sort_aux=date

16. pager_stop

如果设置,那么你在pager(就是你看信的内容的窗口里)翻页时,如果翻到最后,再按往下翻也不会翻到下一封信件。如果不设置就会自动翻到下一封信。

set pager_stop

17. fast_reply

如果设置,当你按 "r" 回信时,就不会再提示你输入回信地址和主题,直接进入编辑模式。

set fast_reply

18. resolve

当你按 "t" 或者 "D" 之类的标记操作时,是否自动把光标移动到下一封信件。

set resolve=yes

19. alias_file

当你在 index 里按 "a" 为来信者取别名时,使用哪一个别名文件保存这个别名。

set alias_file=/home/wy/.mutt.alias

20. record

你发出的邮件保存到那个信箱文件?比如可以像我这样每个月发出的信件放在不同的文件里。

set record="~/Mail/=sent-mail-`date +%Y-%m`"

21. charset

你的终端支持哪一种编码的显示?这个必须和你的终端编码一样。

set charset="gb2312"

22. send_charset

发信时可以使用的字符集。只有当前面的字符集不能正确表示信件内容时才会使用后面的。比如,如果你像下面这样设置,你的信件如果全是英文,那么信件就会被设置为 us-ascii 编码,如果出现了法语字符,那么就会用 iso-8859-1,如果出现了汉字就会用 gb2312,如果以上都不是,那么就用 utf-8。

set send_charset="us-ascii:iso-8859-1:gb2312:utf-8"

23. wait_key

当外部程序退出时,是否要求用户按一个键才返回。这在察看某些shell命令输出时是比要的,否则它们一下就消失了。

set wait_key=yes

24. confirmappend

当你要把信件存到另一个信箱,而这个信箱已经存在时,是否提示附加?

set noconfirmappend

25. edit_headers

是否把邮件头也放在编辑器里可以修改?

set edit_headers=no

26. pager_index_lines

当你在用 pager 看信件时,在 index 留出多少行显示邮件列表?

set pager_index_lines=4

比如我留下4行显示列表,其它的用来显示正文: mutt-indexpager
27. subscribe

告诉 Mutt 你已经订阅了那些邮件列表(mailing-list). 这有助于 Mutt 判断那些信件是邮件列表转过来的,避免你错误的回复到别人的私人信箱。也避免别人回复到你的私人信箱。

subscribe fvwm@fvwm.org

之后,收到的 To: 是 fvwm@fvwm.org 的信件看起来是这样:

mutt-list

地址前面那个 "L" 表示这是一个邮件列表转过来的。你看到以后就不要按 "r" 回信,这样会回到别人的私人信箱去。按 "L",就可以回复到邮件列表地址,这里就是 fvwm@fvwm.org。

Mutt中文FAQ

以下是一些常见问题和解决方法。很多是我遇到的一些不能直接连接国外网络,没有自己的域名和邮件服务器的人遇到的问题。

1. 怎样才能让我发出的信件使用我的POP邮箱的地址,而不是 root@myhost.com 这样的地址?

用 my_hdr 把你的 From: 设置为你想要的地址就行了。比如我是这样设置的:

my_hdr From: wang-y01@mails.tsinghua.edu.cn

注意 From: 的冒号之后有空格!
2. 怎样让 Mutt 显示日期等为中文?

set locale="zh_CN"

3. 发出的信件为什么设置了错误的 charset?别人的程序不能正确显示我的中文信件!

把 gb2312 编码加到你的 send_charset. 就像这样最好:

set send_charset="us-ascii:iso-8859-1:gb2312:utf-8"

4. 收到一些中文信件全部显示为 "???"

这是因为某些 email 客户端,比如清华大学 mails.tsinghua.edu.cn 的WWW界面客户端 没有设置字符编码,你看看邮件头(按h),是不是有个

Content-Type: text/plain

但是后面没有说 charset="GB2312"? Mutt 遇到这种没有设置 charset 的邮件就会使用 "us-ascii",所以如果你想让这种信件可以正确显示,就把 "us-ascii" 设置为 "gb2312" 的别名:

charset-hook ^us-ascii$ gb2312

注意 "us-ascii" 中间的连字号!
5. 可是仍然有邮件标题乱码呢!

看看你的 $spool 里那个乱码的信件是不是有类似如下内容:

Subject: =?iso8859-1?B?U29oddCj09HCvDq587Dg09DQwrPJ1LG808jro6E=?=

Chinaren 等服务器发出来的信件使用了 quoted-printable 的 subject,而且设置编码为 "iso8859-1",这显然是错误的。

对付这个错误的办法是把 iso-8859-1 变成 gb2312 的别名:

charset-hook ^iso-8859-1$ gb2312

注意 "iso-8859-1" 中间的连字号!

如果仍然有信件乱码。干脆用

charset-hook .* gb2312

把所有信件都用 gb2312 显示。
6. 可是这样设置之后 evolution 发过来的 subject 为 utf-8 编码的邮件标题乱码!

那就把不是 utf-8 的编码都映射到 gb2312:

charset-hook !utf-8 gb2312

7. 怎样配置 fetchmail?

fetchmail 的配置非常简单。如果只是一个人用的话,可以这样设置:比如,我在我的 $HOME 目录编辑了一个 .fetchmailrc:

set daemon 60
poll mails.tsinghua.edu.cn
protocol POP3
user "wang-y01"
password "wang-y01的密码"
poll smth.org
....
....

然后把 fetchmail 写到我的shell启动脚本里:

! ps aux | grep -q fetchmail && fetchmail &

fetchmail 启动后成为一个 daemon, 每分种帮我检查所有邮箱里的邮件,收回来,并且转发到本地信箱。修改上面那个 "60" 就可以改变检查时间间隔。

如果不想让 fetchmail 删除服务器上的文件,而且每次只取新的信。就在配置文件里加上:

keep
uidl

8. 我不想用 fetchmail,能不能直接收回 POP 信件啊?

如果你的 Mutt 编译时加入了 POP 功能,那么你可以直接从 POP 服务器收邮件而不用借助于 fetchmail. 把类似这些行加入 ~/.muttrc

set pop_user=wang-y01
set pop_pass="wang-y01的密码"
set pop_host="pop://mails.tsinghua.edu.cn"

也可以一次性输入所有内容:

set pop_host="pop://wang-y01:wang-y01的密码@smth.org"

在 Mutt 里按一下 "G" 就可以取邮件了。
9. 怎样处理多个 POP3 信箱?

如果你有多个POP信箱,你可以设置一些方便的宏把POP信件收到你信箱里。举个例子,就像我这样:

macro index ,shredder ":set pop_host=\
\"pop://shredder:shredder的密码@smth.org\"\r\
"

macro index ,sk8er ":set pop_host=\
\"pop://sk8er:sk8er的密码@smth.org\"\r\
"

macro index ,ts ":set pop_host=\
\"pop://wang-y01:wang-y01的密码@mails.tsinghua.edu.cn\"\r\
"

macro index ,g ",shredder,sk8er,ts"

这样,我只要按 ,shredder 就可以收我在 smth 上 shredder 的信件,只要按 ,sk8er 就可以收我在 smth 上 sk8er 的信件,只要按 ,ts 就可以收 mails.tsinghua.edu.cn 的信件,只要按 ,g 就可以收取我所有 POP 信箱的信件了。
10. 怎样直接访问 POP3 信箱?

除了上面的方法,你还可以直接访问 POP3 信箱。比如,我可以直接按 "c" 切换到信箱 pop://sk8er:sk8er的密码@smth.org

就可以浏览 pop 的信件了。切换到其它信箱就浏览不同的 pop。如果你嫌按键太多可以自己定义一个宏。这是同步操作,你如果在这个信箱里删除一封信件,mutt 就会删除你 pop3 服务器上的信件。你不删它也不删。

邮件太多时这样效率很低,每次都要取所有邮件头,就像 Foxmail 的“远程邮件管理”。所以最好在那种不想取回信件,而想直接删除垃圾邮件的时候用这个办法。
11. 怎样处理邮件列表?

参看subscribe命令。
12. 我按 "d" 的时候邮件被直接标记删除了,怎样才能把删掉的信件都移到一个“垃圾箱”呢?

你只要把信件用 save-message 函数保存到你的垃圾箱,比如 ~/Mail/Trash,信件会被自动做上 "D"(删除) 标志。为了让 "d" 可以保存到垃圾箱,你可以把 "d" 键绑定到一个宏。但是如果你要删除垃圾箱里的邮件,这个宏会再次把垃圾箱的邮件存储到垃圾箱,产生循环。所以你应该使用 folder-hook 在垃圾箱里把 "d" 恢复到原来的 delete-message 函数,而在其它信箱使用那个宏。

现在你可以用以下设置得到一个“垃圾箱”的功能。第一次按 "d" 时有可能会被讯问是否建立这个信箱(Trash).

folder-hook . 'macro index d "~/Mail/Trash\r"'
folder-hook ~/Mail/Trash 'bind index d delete-message'

13. 当收到的邮件的 header 有很多项目时,我的 pager 里全都是邮件头。怎样才能只看到某些我想看的邮件头呢?

你可以用 ignore 忽略你不想看到的邮件头,如果 ignore *,你就可以忽略所有邮件头。用 unignore 可以恢复显示被忽略的邮件头。所以一个简单的办法就是先把所有邮件头忽略,然后放出你想看的那几个。

看下面的设置。我的 sent.*(发件箱) 里只显示 To: Subject: Date: 三项。而在其它信箱就显示 From: Subject: X-Mailer: Date: 这几项。

folder-hook . "ignore *; unignore from subject X-mailer date"
folder-hook sent.* "ignore *; unignore to subject date"

你还可以指定邮件头显示的顺序:

hdr_order from to subject date

14. Mutt 怎么使用地址簿呢?

你可以用 alias 来实现一个地址簿。alias 命令的形式是这样的,举个例子:

alias wy Wang Yin

alias 是命令,wy 是别名,Wang Yin 是一个标准的 email 地址。这样,如果你在 index 里按 "m",在 To: 的提示下输入 "wy",就可以发信给 Wang Yin

在 To: 的提示下按 Tab 就可以显示联系人列表,然后你可以移动光标选择联系人。

如果你有很多 alias 要写,最好把它们写到另外一个文件,比如叫 .mutt.alias. 然后在 .muttrc 里加上:

source ~/.mutt.alias

你还可以设置一个变量:

set alias_file=~/.mutt.alias

这样你在 index 里按 "a",就可以把来信人加入到这个 alias 文件了。
15. Mutt 如何处理 HTML 附件?

Mutt 可以处理任何类型的附件。因为它可以调用合适的程序来处理它们。为了直接在 mutt 的窗口里显示 HTML,你只需要在 ~/.mailcap 文件加入:

text/html; lynx --dump %s; nametemplate=%s.html; copiousoutput

在 ~/.muttrc 加入:

auto_view text/html

16. Mutt 如何处理 Word doc 附件。

清华大学总是喜欢发送含有 doc 附件的通知。真是让人ft。现在有一个完美的解决方案了:使用 wvware 把 doc 转成 HTML 嵌入mutt里。

wvware 可以在 http://www.wvware.com/免费得到。

wvHtml --charset=gb2312 your.doc your.html

就可以把doc转成 HTML。经测试,能够正确处理汉字和图片。

你可以让mutt调用 wvHtml 在自己的窗口里直接显示转换的 doc 文档。只需要在 ~/.mailcap 文件加入:

application/msword; wvHtml --charset=gb2312 %s - | lynx --dump -stdin;
nametemplate=%s.html; copiousoutput

text/html; lynx --dump %s; nametemplate=%s.html; copiousoutput

在 ~/.muttrc 加入:

auto_view text/html application/msword

这样你的 mutt 看一个 doc 的时候就像这个样子:
mutt-wvware
17. 我想在 Mutt 里使用 Emacs 怎么办?

Emacs 是一个非常强大的编辑器,所以你肯定会希望能在 Mutt 里使用 Emacs。你可以选择两种方式:
1. 一种方式是直接在 Mutt 的终端里使用非图形界面的 Emacs (emacs -nw)。

你只需要在 .muttrc 设置:

set editor="emacs -nw"

这样会启动一个新的 Emacs。如果你的 Emacs 配置加入了大量扩展,这个启动时间是相当长的,你不希望每回一封email就等上10秒等Emacs启动吧?

有一个办法可以跳过冗长的 Emacs 扩展。只需要把你的 .emacs 里耗时的部分放在一个条件语句里。比如,我就把 desktop 和 session 放在了一个条件语句里启动。如果知道编辑的文件名叫做 "/tmp/mutt-..." 那我们就知道是 mutt 在调用 Emacs,所以我就不加载 desktop 和 session 这种费时间又没用的东西。

(unless
(catch 'found
(dolist (arg command-line-args)
(if (string-match "^/tmp/mutt-" arg)
(throw 'found t))))

;; load desktop
(load "desktop")
(desktop-load-default)
(desktop-read)

;; load session
(require 'session)
(add-hook 'after-init-hook 'session-initialize)
(setq desktop-globals-to-save '(desktop-missing-file-warning))

;; start server
(server-start)
)

2. 一种方式是使用 emacsclient 发送到 GUI 的 Emacs 服务器编辑。

这种方式可以使用一个已经启动的 Emacs,启动非常快速。但是我不是很喜欢这种方式,因为我不想离开 Mutt 的终端到 Emacs 的窗口,编辑完了还要切换窗口。看这幅图。

先来看看 Emacs 的设置,启动 Emacs 后,你可以使用 server-start 启动 Emacs 服务器。你也可以把

(server-start)

加入到你的 .emacs 文件,这样 Emacs 启动时自动就启动了服务器。

在 .muttrc 里加入

set editor=emacsclient

这样 Mutt 在要发送邮件时,就把需要编辑的东西送到已经启动的 Emacs 里。编辑完了之后你按 C-x #,控制会转回到 Mutt.
18. 我不能直接连国外,sendmail必需通过 mails.tsinghua.edu.cn 转发,但是 sendmail 不能通过 ESMTP 验证怎么办?

由于清华大学网络中心的限制,一般同学不能直接连接国外的服务器。这样 sendmail 就不能直接将邮件发送到目的地。我们需要依赖国内的邮件服务器来转发到目的地。但是现在国内的smtp邮件服务器通常需要 SMTP 验证才能帮你转发邮件。比如 mails.tsinghua.edu.cn, 这是一种防止别人利用自己主机发送垃圾邮件的办法。

sendmail 怎样才能通过 SMTP 身份验证呢?sendmail 的网页上说有办法。可是我搞了一天还是没有搞定。而且 sendmail 是以安全漏洞著称的。所以我决定换用 Postfix。qmail 也很好,但是我不知道怎么让 qmail 通过 AUTH SMTP 转发, 如果有人知道请告诉我。

postfix 是一个可以取代 sendmail 的邮件服务器。它在普通机器上可以达到 sendmail 3 倍的吞吐率。而且相当安全。它可以在 www.postfix.org 下载安装过程如下:
1. 编译的时候你需要让 postfix 支持 SASL 验证,使用以下选项编译:

% make makefiles CCARGS="-DUSE_SASL_AUTH -I/usr/local/include" \
AUXLIBS="-L/usr/local/lib -lsasl"

然后安装

% make; make install

2. 为了 postfix 能够正确发送本地邮件,请在 /etc/postfix/main.cf 加上:

myhostname = tu140066.tsinghua.edu.cn
mydestination = wangyin.com, $myhostname, localhost.$mydomain

$myhostname 指明了你的主机域名,清华大学的网络给了每个人一个域名,其实就是 tuxxxxxx.tsinghua.edu.cn, xxxxxx 就是你的 IP 后面的数字,比如我的IP是166.111.140.66, 所以我的域名是 tu140066.tsinghua.edu.cn.

$mydestination 指出哪些地址是认为是你自己的地址。你应该把你的机器名(我的是 wangyin.com),$myhostname, $localhost.$mydomain 加进去。
3. 为了能够使用 SASL 验证登录,把这些行加到 /etc/postfix/main.cf

smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options =
relayhost = mails.tsinghua.edu.cn

4. 编辑口令文件 /etc/postfix/sasl_passwd。加入一行:

Your.Relay.Server your_auth_login_name:Your_PassWord

比如我的口令文件是这样的:

mails.tsinghua.edu.cn wang-y01:aDF2m@3d$q=+

当然密码不是那个 :P
5. 把口令文件转成 Berkeley DB 格式:

#postmap hash:sasl_passwd

6. 启动你的 postfix 服务器

postfix start

Valid HTML 4.01!

IE hole and web mail security

This summary is not available. Please click here to view the post.

2007/07/11

About "pre" and "code" style

I very like the <pre> and </pre> style of the Sun Microsystems.
This is the test code.

single line style code
style=" color: black; font-family: Courier, monospace; background-color: #efefef; border: 1px solid #ccc; font-size: 100.01%; padding: 0.5em; overflow: hidden;"

CSS code
code, pre {
color: black;
font-family: Courier, monospace; /* [3] */
}
pre {
background-color: #efefef;
border: 1px solid #ccc;
font-size: 100.01%;
padding: 0.5em;
overflow: hidden;
}

Bourne/Korn Shell Coding Conventions

Bourne/Korn Shell Coding Conventions

Mike Shapiro

This document describes the shell coding style used for all the init.d script changes integrated into Solaris.

All new init.d shell code should conform to this coding standard, which is intended to match our existing C coding standard.

When in doubt, think "what would be the C-Style equivalent?" Table of contents
1 Basic Format
2 If, For, and While
3 Test Built-in
4 Single-line if-statements
5 Infinite Loops
6 Exit Status and If/While Statements
7 Variable References
8 Variable Naming
9 Quoting
10 Testing for (Non-)Empty Strings
11 Commenting
12 Pathnames
13 Interpreter Magic
14 Use of the C shell

Basic Format

Similar to cstyle, the basic format is that all lines are indented by TABs, and continuation lines (which in the shell end with "\") are indented by an equivalent number of TABs and then an additional four spaces, e.g.
cp foo bar
cp some_realllllllllllllllly_realllllllllllllly_long_path \
to_another_really_long_path
If, For, and While

To match cstyle, the sh token equivalent to the C "{" should appear on the same line, separated by a ";", as in:
if [ $x = hello ]; then
echo $x
fi

for i in 1 2 3; do
echo $i
done

while [ $# -gt 0 ]; do
echo $1
shift
done
Test Built-in

DO NOT use the test built-in. Sorry, executive decision. In our Bourne shell, the test built-in is the same as the "[" built-in (if you don't believe me, try "type test" or refer to usr/src/cmd/sh/msg.c). So please do not write:
if test $# -gt 0; then

instead use:
if [ $# -gt 0 ]; then

In the Korn shell, the [[ ]] syntax is preferred, as this adds additional operators not available in the Bourne shell, such as short-circuit && and ||:
if [[ $# -gt 0 && $? -eq 0 ]]; then
Single-line if-statements

It is permissible to use && and || to construct shorthand for an "if" statement in the case where the if statement has a single consequent line:
[ $# -eq 0 ] && exit 0

instead of the longer:
if [ $# -eq 0 ]; then
exit 0
fi

DO NOT combine && with { }, as in:
[ $# -eq 0 ] && {
do something
do something else
}

Use a complete "if-then-fi" construct for this instead.
Infinite Loops

The proper way to write an infinite loop in the shell is to use the ":" built-in, which evaluates to true (exit status 0). This is better than using "true", because that is *not* a built-in and thus runs /bin/true.
while :; do
echo infinite loop
done
Exit Status and If/While Statements

Recall that "if" and "while" operate on the exit status of the statement to be executed. In the shell, zero (0) means true and non-zero means false. The exit status of the last command which was executed is available in the $? variable. When using "if" and "while", it is typically not necessary to use $? explicitly, as in:
grep foo /etc/passwd >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo found
fi

Instead, you can more concisely write:
if grep foo /etc/passwd >/dev/null 2>&1; then
echo found
fi

Or, when appropriate:
grep foo /etc/passwd >/dev/null 2>&1 && echo found
Variable References

Variable references begin with $ and *may* have their name enclosed in {}'s. I prefer to only see the {}'s when required. Do not spuriously enclose all your variable names in braces, like this:
foo=${bar}

This is kind of like writing all your C variable assignments like this:
foo = (bar);

It compiles, but it looks stupid.

Braces are required around variable names in two specific cases:

(1) when you are forming the string concatenation of your variable with another string:
[ $install = yes ] && root="/a/" || root="/"
hosts=${root}etc/inet/hosts

and (2) when you are using one of the various substitution/assignment operators:
echo ${BASEDIR:-/a}
Variable Naming

For our init scripts, I prefer that you adopt a shell variable naming scheme where capitalization provides additional meaning (as in our C style): use CAPITAL letters for variables that are exported into the environment, or are equivalent to C constants or #defines. Use lowercase letters for other variable names:
BASEDIR=/a; export BASEDIR
argc=$#

This helps your reader immediately understand the implication of modifying a given variable (i.e. whether it will be inherited by child processes).
Quoting

Quick review of the quoting basics:
single quotes ('') mean quote but do not expand variable or backquote substitutions.
Double quotes ("") mean quote but allow expansion.
Backquotes (``) mean execute the command and substitute its standard output
(note: stderr is unchanged and may "leak" through unless properly redirected)

Use whatever quotes are appropriate for your situation, but please do not unnecessarily quote everything (also see 7 above).

For example, variable references do not have to be quoted unless you are expecting your variable to expand to multiple tokens, or to the empty string.
Testing for (Non-)Empty Strings

DO NOT test for non-/empty strings by comparing to "" or ''. ALWAYS use the test operators -n (non-zero-length string) and -z (zero-length string):
if [ -z "$foo" ]; then
echo 'you forgot to set $foo'
fi

if [ -n "$BASEDIR" ]; then
echo "\$BASEDIR is set to $BASEDIR"
fi
Commenting

Shell comments are preceded by the '#' character. Place single-line comments in the right-hand margin. Use an extra '#' above and below the comment in the case of multi-line comments:
cp foo bar # Copy foo to bar

#
# Modify the permissions on bar. We need to set them to root/sys
# in order to match the package prototype.
#
chown root bar
chgrp sys bar
Pathnames

It is always a good idea to be careful about $PATH settings and pathnames when writing shell scripts. This allows them to function correctly even when the user invoking your script has some strange $PATH set in their environment.

There are two acceptable ways to do this:

(1) make *all* command references in your script use explicit pathnames:
/usr/bin/chown root bar
/usr/bin/chgrp sys bar

or (2) explicitly reset $PATH in your script:
PATH=/usr/bin; export PATH

chown root bar
chgrp sys bar

DO NOT use a mixture of (1) and (2) in the same script. Pick one method and use it consistently.
Interpreter Magic

The proper interpreter magic for your shell script should be one of these:
#!/bin/sh Standard Bourne shell script

#!/sbin/sh Init.d script or other Bourne shell script which must run
early in single-user mode (when /usr is not mounted).
#!/bin/ksh -p Standard Korn shell script. You should always write ksh
scripts with -p so that $ENV (if set by the user) is not
sourced into your script by the shell.
Use of the C shell

Don't use the C shell for any scripts. Executive decision. End of discussion.

2007/07/09

talend - a open source etl product

Ad Hoc amazing chart

Ad Hoc has amazing chart how they implemented those functions on web?

Java with Spring just as productive as a 4GL RAD tool

Java with Spring just as productive as a 4GL RAD tool
by Erwin Bolwidt and Vincent Partington
Java is known for its platform portability, its scalability, and the large number
of libaries and tools available for it. However it is oft maligned as not offering
sufficient productivity especially when compared to 4GL RAD tools or the .NET
framework. During the 2005 Dutch RAD Race we proved that Java beats the
.NET framework and measures up to the best RAD tool, without sacrificing
quality and flexibility.
The contest consisted of the development of an administrative application for a fictional
travel agency in two days. Apart from numerous data entry screens, the application had
to invoke a web service, expose a web service, provide management reports in a
number of formats (Excel, HTML) and there was some complicated logic like searching
for a flight schedule.
We produced a full working application in two days by using new frameworks like Spring
and Hibernate, proving that Java can be as productive as any other environment. In
this article, we explain what tools we used, what went well and what went wrong.
So what libraries and tools did we use?
The most important software we used was:

Spring Framework 1.1.3

Eclipse IDE 3.1M4 with Eclipse Web Tools Platform 1.0M3

Hibernate 2.1.7

Hibernate Synchronizer Eclipse plugin 2.3.1

Tomcat 5.5.4

MySQL 4.1
On top of that, we prepared by designing a template/starter application using these
tools. For the GUI, we made extensive use of tag files we created ourselves. Tag files
are a JSP 2.0 feature.
How did these things help us?
One thing that stands out is the non-invasiveness of the tools. Neither the IDE nor the
libraries rigidly forced us in a direction thereby making it easier to combine them.
During the race, we had to extend the domain model and the database a few times.
Hibernate is a great OO mapping tool, but the Hibernate Synchronizer is what helped us
here the most. It takes a sensible approach by generating and re-generating
superclasses for your domain model, so you can add your OO logic to the subclasses
without having to worry about your code being modified or deleted after regeneration.
Compare the BaseTrip class generated by the Hibernate Synchronizer to the Trip class.
The latter contains additional business logic to calculate trip prices and apply discounts.
We used Spring Web MVC for the web interface. One of its prime advantages in rapid
development is that it allows your domain objects (which were generated by the
Hibernate Synchronizer) to be used directly as command objects in form controllers; no
separate "form object" is required, reducing code duplication. See the EditTripForm
class.Page 2

We also used the "open session in view" interceptor, which allows the views,
implemented as JSP's, to access lazy associations in the domain model by retaining a
read-only hibernate session during JSP rendering. We didn't have time to analyse the
performance impact this would have in a production application, but it is a really handy
pattern during rapid development, and can always be rewritten by putting more
complexity in the DAO during an optimization sweep over the application.
The biggest advantage of the Spring framework is how it allows the application to be
'componentized'. The IoC-based XML configuration of components makes team
development a real breeze, which is extremely important when you're quickly building
an application with a team, since you tend to get into each others hair all the time. It's
really a matter of defining an interface, letting one developer use it and another
developer implement it. If the implementation takes too long, implement a simple stub
version of it to test the client against; a simple change in one xml file rewires the
application against the correct implementation whenever that is needed.
For example, in this Spring bean configuration the real temperature report that invokes
the web service is wired in:
class="com.xebia.teltravel.bizlogic.TemperatureReportImpl">




However, by changing those lines to the following, a fake implementation can be used
that does not require access to the webservice:
class="com.xebia.teltravel.bizlogic.FakeTemperatureReportImpl"
/>
One caveat: it is important to split up the XML files, either logically based on application
layers, or based on team members; the latter is preferable during rapid development to
reduce the number of CVS merge actions.
Finally, Eclipse is a flexible IDE with a plethora of available plugins to make it even
better. Apart from the Hibernate Synchronizer already mentioned, we used the Web
Tools Platform to integrate Tomcat very closely, allowing us to start the application in
ten seconds on our 3GHz Pentium IV, 1GB laptops. No EJB layer means there are no
deployment cycles and that the application server starts up quickly. The close
integration with Eclipse meant we could debug on source level. When making a change
we had the choice of letting the JVM modify the class on-the-fly, restart the application
or restart the application server. All this gave us quick turn-around on our change.
To summarize, we believe these to be the strong points that benefited us most:
 Easy team development because of component separation,
 Fast and powerful assembly of our own code and third party components (such
as Hibernate, Axis, etc.) into the application using the Spring Framework,
 Easy fit of third party libraries into the application, and
 Having a skeleton application (based on the Spring PetClinic sample), including
a consistent skeleton GUI, available to bootstrap the project from.Page 3

Weak points
To be honest, we did run into some problems.
The biggest problem was the speed at which we could build the user interface. Despite
having a skeleton GUI and customized JSP tag files, this took us significantly more time
than other teams that worked as fast as we did. Time that could have been spent on
completing more parts of the assignment and on better peer review of the code. A
faster solution for this problem would have given us the edge, and victory. But alas, we
didn't have or know a good solution that fits into the toolset that we are using.
What we envision as a solution is a flexible approach, using the same principles as the
Spring Framework.

No code generation during the build phase

Form rendering with minimal configuration, using introspection on domain
objects to find as much information as possible

Open, pluggable architecture where all components can be replaced or
customized

Should place little or no requirements on application architecture
Another issue is the time is takes to propagate changes through layers. Although its
impact is less profound than that of the GUI problem, and despite the re-use of domain
objects for web forms, it is still necessary to make changes to the application in
multiple locations for some types of changes. Mainly those in the domain model.
Smarter plugins for the IDE may alleviate this problem, but in a layered application,
this problem will probably always remain to some degree.
Conclusions
Out of the 9 contestants, we came up third. Visual Studio .NET came in eighth place,
and Java with a traditional toolset came in seventh. A 4GL tool called Magic e-
Developer came first, and an Oracle toolset second, the first three positions within 10%
of each other.
Java can be really productive right now. It can equal the productivity of 4GL tools that
are specifically designed for rapid application development and outpace .NET which is
regularly touted as being more productive than J2EE.
Spring allows for greater modularization because of Inversion of Control and its non-
invasive approach. The basic concepts of Spring are simple and consistently
implemented, making it easy to learn enough of Spring to be productive in a short
period of time.
Hibernate, especially combined with the Hibernate Synchronizer plugin, is a quickly
implemented and dependable solution for data access, and works well in tandem with
Spring Web MVC.
Finally, it's more fun to develop in parallel and being able to present working versions
of an application so soon in the development process.
These tools provide a significant improvement over 'plain Java'. Our score was more
than twice that of the 'plain Java' and 'plain .NET' entries. In previous years of the
competition, Java consistently ended in the bottom half of the results. Our personal
experience also indicates that we are much more productive with the combination of
Spring, Hibernate and Eclipse than with a 'plain J2EE' approach.Page 4

About the authors
The authors of this article, Vincent Partington and Erwin Bolwidt, are the team that
participated in the Dutch Rad Race 2005 for Xebia. They are J2EE consultants for Xebia
and each have more than 8 years experience in software engineering with Java and were
involved with server-side Java technology for nearly as long

2007/07/08

メダカ

最近透明のメダカなどを白鼠の替わりに研究に使われてる。