阿里技术学习博客

分享学习经验

IT博客 联系 聚合 管理
  42 Posts :: 1 Stories :: 36 Comments :: 0 Trackbacks

2009年5月4日 #

公司一套系统的同步使用的donotify,不能实现子目录的实时同步,通过查资料,发现inotify可以实现子目录的实时同步,以下为笔记。


一、介绍
Inotify 是文件系统事件监控机制,作为 dnotify 的有效替代。dnotify 是较早内核支持的文件监控机制。Inotify 是一种强大的、细粒度的、异步的机制,它满足各种各样的文件监控需要,不仅限于安全和性能。


inotify 可以监视的文件系统事件包括:
IN_ACCESS,即文件被访问
IN_MODIFY,文件被 write
IN_ATTRIB,文件属性被修改,如 chmod、chown、touch 等
IN_CLOSE_WRITE,可写文件被 close
IN_CLOSE_NOWRITE,不可写文件被 close
IN_OPEN,文件被 open
IN_MOVED_FROM,文件被移走,如 mv
IN_MOVED_TO,文件被移来,如 mv、cp
IN_CREATE,创建新文件
IN_DELETE,文件被删除,如 rm
IN_DELETE_SELF,自删除,即一个可执行文件在执行时删除自己
IN_MOVE_SELF,自移动,即一个可执行文件在执行时移动自己
IN_UNMOUNT,宿主文件系统被 umount
IN_CLOSE,文件被关闭,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
IN_MOVE,文件被移动,等同于(IN_MOVED_FROM | IN_MOVED_TO)
注:上面所说的文件也包括目录。

 


二、为能在shell下使用inotify特性,需要安装inotify-tools


1、inotify-tools:The general purpose of this package is to allow inotify's features to be used from within shell scripts.


下载地址:[url]http://inotify-tools.sourceforge.net/[/url]


编译安装
./configure
make
make install
完成后,注意查看manpage,man inotify 、 man inotifywait

 


inotifywait 仅执行阻塞,等待 inotify 事件。您可以监控任何一组文件和目录,或监控整个目录树(目录、子目录、子目录的子目录等等)。在 shell 脚本中使用 inotifywait。
inotifywatch 收集关于被监视的文件系统的统计数据,包括每个 inotify 事件发生多少次。


2、inotify的系统相关参数:
 /proc interfaces
       The following interfaces can be used to limit the amount of kernel memory consumed by inotify:


       /proc/sys/fs/inotify/max_queued_events
              The value in this file is used when an application calls inotify_init(2) to set an upper  limit  on  the number  of  events  that  can be queued to the corresponding inotify instance.  Events in excess of this limit are dropped, but an IN_Q_OVERFLOW event is always generated.


       /proc/sys/fs/inotify/max_user_instances
              This specifies an upper limit the number of inotify instances that can be created per real user ID.


       /proc/sys/fs/inotify/max_user_watches
              This specifies a limit the number of watches that can be associated with each inotify instance.

 


3、inotifywait 相关的参数(更多,查看manpage):
inotifywait
This command simply blocks for inotify events, making it appropriate for use in shell scripts. It can watch any set of files and directories, and can recursively watch entire directory trees.
-m, --monitor
              Instead  of  exiting  after receiving a single event, execute indefinitely.  The default behaviour is to exit after the first event occurs.
-r, --recursive
              Watch all subdirectories of any directories passed as arguments.  Watches will be set up recursively  to an  unlimited  depth.   Symbolic  links  are  not


traversed.  Newly created subdirectories will also be watched.
-q, --quiet
              If specified ce, the program will be less verbose.  Specifically, it will not state when it  has  completed establishing all inotify watches.
 -e <event>, --event <event>
              Listen for specific event(s) ly.  The events which can be listened for are listed in the  EVENTS  section.  This option can be specified more than ce.  If omitted, all events are listened for. use“,”separate multi events

 


三、使用
1.查看是否支持inotify,从kernel 2.6.13开始正式并入内核,RHEL5已经支持。
看看是否有 /proc/sys/fs/inotify/目录,以确定内核是否支持inotify
[root@RHEL5 Rsync]# ll /proc/sys/fs/inotify
total 0
-rw-r--r-- 1 root root 0 Oct  9 09:36 max_queued_events
-rw-r--r-- 1 root root 0 Oct  9 09:36 max_user_instances
-rw-r--r-- 1 root root 0 Oct  9 09:36 max_user_watches


2.关于递归:
inotifywait
This command simply blocks for inotify events, making it appropriate for use in shell scripts. It can watch any set of files and directories, and can recursively watch entire directory trees.

 


3.使用:
#!/bin/sh
src=/opt/webmail
des=/tmp
ip=192.168.7.192


/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format  '%T %w%f' \
 -e modify,delete,create,attrib \
${src} \
| while read  file
        do
                rsync -avz --delete --progress ${src} root@${ip}:${des} &&
                echo "${file} was rsynced"
                echo "---------------------------------------------------------------------------"
        done
注:
当要排出同步某个目录时,为rsync添加--exculde=PATTERN参数,注意,路径是相对路径。详细查看man rsync
当要排除都某个目录的事件监控的处理时,为inotifywait添加--exclude或--excludei参数。详细查看man inotifywait


另:
/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format  '%T %w%f' \
 -e modify,delete,create,attrib \
${src} \
上面的命令返回的值类似于:
10/03/09 15:31 /wwwpic/1

这3个返回值做为参数传给read,关于此处,有人是这样写的:
inotifywait -mrq -e create,move,delete,modify $SRC | while read D E F;do

细化了返回值。

 

 


说明: 当文件系统发现指定目录下有如上的条件的时候就触发相应的指令,是一种主动告之的而非我用循环比较目录下的文件的异动,该程序在运行时,更改目录内的文件时系统内核会发送一个信号,这个信号会触发运行rsync命令,这时会同步源目录和目标目录。
--timefmt:指定输出时的输出格式
   --format:  '%T %w%f'指定输出的格式,上面的输出类似于:12/10/08 06:34 /opt/webmail/dovecot-1.1.2/src/test/1

 


小脚本,同步到多台主机:
 
 
 
 

 
 
使用rsync+inotify配置触发式(实时)远程同步
 
 
 
使用rsync+inotify配置触发式(实时)远程同步
 
2008-11-01 TsengYia#126.com
 
################################################################
系统环境:RHEL5 [ 2.6.18-8.el5xen ]
软件环境:
    rsync-2.6.8-3.1
    nfs-utils-1.0.9-16.el5
    portmap-4.0-65.2.2.1
    inotify-tools-3.13.tar.gz
        —— [url]http://downloads.sourceforge.net/inotify-tools/inotify-tools-3.13.tar.gz?modtime=1199213676&big_mirror=0[/url]
 
目标功能:
    源主机H1: 192.168.1.11/24
    目标主机H2: 192.168.1.12/24
   
    将H1主机中的开发数据(/var/devel/目录),上传同步至H2主机的/backup/devel/h1/目录。——当源数据有文件或目录更新时,即时启动rsync同步进程。[基于安全性考虑,建议只在内部网络中使用]
 
################################################################
    除inotify-tools(需要2.6.13以上内核的inotify功能支持)以外,其他软件均使用RHEL5系统自带的rpm包安装。
 
一、配置目标主机H2(发布NFS可写共享)
   
shell> mkdir -p /backup/devel/h1/
shell> vi /etc/exports
/backup/devel/h1    192.168.1.11(rw,no_root_squash)
shell> service portmap start
shell> service nfs start
shell> chkconfig portmap
shell> chkconfig nfs
 
  如有必要,可以结合防火墙规则控制访问权限
shell> iptables -I INPUT -p tcp --dport 111 -j DROP
shell> iptables -I INPUT -p tcp --dport 111 -s 192.168.1.11 -j ACCEPT
shell> iptables -I INPUT -p udp --dport 111 -j DROP
shell> iptables -I INPUT -p udp --dport 111 -s 192.168.1.11 -j ACCEPT
 

二、配置源主机H1(上传备份发起端)
 
    1、安装inotify-tools工具包
shell> tar zxvf inotify-tools-3.13.tar.gz -C /usr/src/
shell> cd /usr/src/inotify-tools-3.13
shell> ./configure
shell> make
shell> make install
—— 可以使用man inotify、man inotifywait、man inotifywatch查看相关手册页。
 
    2、挂载H2发布的备份目录
shell> service portmap start
shell> chkconfig portmap
shell> mkdir -p /media/h2nfsdir/
shell> vi /etc/fstab
192.168.0.12:/backup/devel/h1    /media/h2nfsdir    nfs    defaults,noexec    0 0
shell> mount /media/h2nfsdir
 
    3、编写触发同步脚本
shell> vi /opt/h1-h2_inosync.sh
#!/bin/sh
SRC=/var/devel/
DST=/media/h2nfsdir/
INWT=/usr/local/bin/inotifywait
RSYNC=/usr/bin/rsync
$INWT -mrq -e create,move,delete,modify $SRC | while read D E F ; do
    $RSYNC -aHqz --delete $SRC $DST
done
shell> chkmod +x /opt/h1-h2_inosync.sh
 
    4、每次开机自动运行监控脚本
shell> echo "/opt/h1-h2_inosync.sh &" >> /etc/rc.local
shell> /opt/h1-h2_inosync.sh &
 

三、测试实时同步
    在源主机H1上,修改/var/devel/目录中的内容(如增、删、改文件,添加、移除目录等),
    ——同时在目标主机H2上,观察备份目录/backup/devel/h1/中内容的变化。
 
############################## The End ##################################
 
 

posted @ 2009-05-04 21:01 阿里爸爸 阅读(2855) | 评论 (2)编辑 收藏

2009年3月2日 #

这两天使劲玩git和hg,本周四要给兄弟们讲啦!

之前看分布式版本控制时,不是太注重使用.周四就要讲了,必须注重理论,更注重实用!因为到时我必须阐述清楚为什么要使用分布式版本控制.和SVN比有什么优点!用的时候怎么用?

今天碰到一下奇怪的问题,特记录下来.
今天我在一台机器(71.85两台都是linux)上装了git,另一台没有装[128.212].
先在71.85上git init初始化了版本库,并把一老项目代码提交了进去.
然后把71.85整个目录打包到扔到128.212上,想这样就可以偷懒少装一个git环境,以后用的时候就用71.85
然后在71.85用这个命令去取代码"git clone ssh://jian@xx.xxx.128.212/home/jian/temp/temp/gittest/",但是就是报错,就是取不出来,出错信息如下:\

Initialized empty Git repository in /data/git/git_clone/gittest/.git/
jian@xx.xxx.128.212's password:
bash: git-upload-pack: command not found
fatal: The remote end hung up unexpectedly

搞了好一会就是不行,google之无解!最后想会不会是那边128.212上没装git.再试一下在128.212装上git.在71.85上重试下,问题解决!这个git的错误信息太难懂了!
posted @ 2009-03-02 00:42 阿里爸爸 阅读(3052) | 评论 (18)编辑 收藏

2009年2月13日 #

一.序

1.什么是Haskell?

     Haskell是一种函数编程语言. 1980年代以前对函数编程有很多研究, 但不同的研究者使用各自不同的语法记号, 一起交流时造成一些不便. 后来1987年的时候, 在FPCA'87会议上制定了统一的Haskell语言. Haskell吸收了各家的长处, 是一种纯粹的函数编程语言,并根据科学家Haskell B.Curry的名字命名. Haskell经过多年的发展完善, 目前使用的版本是Haskell 98.
     
2.Haskell有什么特点?

    相对Haskell来说,传统的Basic,Pascal,C++,C#,Java,Python等都是命令(imperative)编程语言, 程序语句有一定的执行次序. 函数(functional)编程语言则给出执行的内容, 关注于更高层次的"做什么"而不是"怎么做", 这就是二者最明显的一个区别。函数编程语言的语法功能非常强,使编程的效率大幅提高。
    Haskell是世界上公认的语法最优美最简洁的一种语言。的确,Haskell语言是写给人看的,而不是写给机器看的。另一方面,这也使得的Haskell的编译技术成为一个难点。从以人为本的角度来看,程序员的时间比机器的时间更宝贵,所以Haskell是明智的选择。

3.如何获得Haskell?

     Haskell是一个公共的语言定义, 任何人都可以编写它的实现(implementation), 因而Haskell有很多解释器(比如Hugs)和编译器(比如GHC), 它们都可以在www.haskell.org上得到. 解释器的优点是便于学习和开发,程序写好后不需要编译直接就可以运行,编译器则可以将程序编译可独立执行的文件,便于发布. Haskell既能解释执行, 也能槐槐嘁? 这也是优于其他语言的一个地方.

附:Hugs使用指南

    本文中的示例程序都将在Hugs中运行, 在这里简要介绍一下Hugs的使用方法。Hugs可以在http://www.haskell.org/hugs/下载,安装文件只有2.8M, 是学Haskell的必备工具.

使用方法:

1.用你自己喜欢的文本编辑器将源程序写好, 保存到文件中, 文件以扩展名 hs 结尾.

2.运行Hugs, 出现提示符: Prelude> ,表示Prelude库已经装载.

3.输入:? 可以查看可供使用的一些命令的说明

4. 先输入:!, 然后就可以输入DOS命令并执行. 比如输入:!dir查看当前的工作目录

5. 输入:cd directory_name 将工作目录改为你保存源文件的目录

6. 输入:l file_name 将源程序载入, 提示符变为Main>

现在就可以在提示符后输入各种表达式以检验所定义的函数的功能, 执行所需的运算.

注意: 在提示符后不可以定义新的函数, 因为Haskell中各语句不是顺序执行的, 而把整个源文件当作一个整体来处理, 在编辑器中修改源程序并保存后, 只要输入:r就重新载入, 改动就生效了.


二.语法概要

1.注释有两种: 一种以"--"开始到行尾结束, 一种以"{-"开始,以"-}"结束,可以延续多行.

2.表达式和函数都有类型,但类型声明不是必需的,有一套类型推断系统可以推断出所涉及的类型.

3.函数的定义多使用模式(pattern)匹配的方法, 两个标识符(identifier)邻接就表示函数调用.

4.函数变量和类型变量的标识符以小写字母开头, 类型构造和模块的标识符以大写字母开头.

5.语句块以缩进区分, 从同一列开始的语句属于同一个块.

6.保留字: case class data default deriving do else if import in infix infixl infixr instance let module newtype of then type where _

7.运算符可以自定义,由以下符号进行组合:
       : # $ % & * + - = . / \ < > ? ! @ ^ |
 预定义的运算符有:
       +  -  *  /  ^  $  ++  .  &&  ||  ==  /= <=  >=  <  >
       : //  =  @  ->  =>  ..  ::  <-  !!
       
8.数字: 123  12.3  1.23e5  0o67  0x3A

 字符: 'a' 'A' '\n'
 
 字符串: "character string"
 
 
三.常数

    在函数编程语言中, 函数是一个中心概念, 常数也可看作是常函数. 如下语句:
    
     f = 3
     
    定义了一个常数. f 被定义为3后就不能重复定义 f=5 ,任何时候调用f, 它都返回3. 这就消除了一些边际效应,减少了出错的可能性. 以下代码在函数编程和命令编程中具有完全不同的含义:
    
    a = 2
    b = 4
    c = a + b
    
    在函数编程中解释为: 定义常数a为2, 定义b为4, 定义c为a,b之和.  
    在命令编程中解释为: 给变量a赋值2, 给b赋值4, 求a,b之和赋给c.
    
    定义和赋值的区别在于, 定义不分次序, 赋值有次序, 以上程序在Haskell中完全可以倒过来写:
    
    c = a + b
    a = 2
    b = 4
    
    另外, 定义并不计算, 比如:
    
    d = 3*5
    e = 1/0
    
    在命令程序中, e=1/0会引发一个错误, 在Haskell中只有当计算e时才引发错误.
    
    Haskell的思维更像是人脑的思维而不是机器的思维.
    
    也可以给常数加以类型说明, 比如:
    
    b :: Int
    
    如果没有这一类型说明, 系统自动根据 b=4 推断b的类型为: Integer
    
    Int和Integer区别是Int的取值范围是有限的, Integer的大小是无限的. 因为Integer比Int更普遍,所以在没有明显说明b的类型为Int时, 就自动推断b的类型为: Integer
    
    再举几个例子,在Haskell标准库Prelude中定义的常数中,有两个是:
    
    pi = 4 * atan 1
    otherwise = True
    
    
四.单变量函数
    
    如下语句:
    
    f     (x)=x+2
    double(x)=2*x
    
    就定义了两个简单的函数, 函数的类型由自变量的类型和返回值在类型决定, 用运算符"->"连接.
    
    比如可以用以下语句说明它们的类型:
    
    f      :: Int -> Int
    double :: Float -> Float
    
    表示f是从Int变量到Int变量的映射. 如果没有明显说明, 系统根据函数定义中所涉及到的运算(+),(*)推断这两个函数的类型为:    
    
    Num a => a -> a
  
    这里a是一个类型变量, 属于一个独立的名字空间, Num是一个类, Num a => 表示类型a属于Num类. Num类中定义了(+)和(*)的运算, 继承此类的类型也支持这两种运算. 这样使用类来限定函数的类型, 使函数具有的普遍性. 把类型归为一些类, 实现了类型的多态, 也简化了编程的任务.
    
    在Haskell中函数非常频繁地用到, 通常在函数的定义和使用中省去括号, 直接用两个标识符邻接表示函数作用. 所以f和double的定义可写为:
    
    f x      = x + 2
    double x = 2 * x
    
    调用函数的格式和定义函数的格式基本是相同的, 比如定义函数g如下:
    
    g x = 2 * f x
    
    函数作用的优先极高于其他所有的运算符, 所以2 * f x等价于2 * (f x), 也等价于2 * (f(x)).
    
    函数作用的次序是从左向右的, 所以可以等价地定义g为:
    
    g x = double (f x)
    
    Prelude有一个运算符$的定义如下:
    infixr 0  $
    ($)            :: (a -> b) -> a -> b
    f $ x           = f x
    
    可见, $也是表示函数作用的, 但它的优先级最低, 而且作用次序是从右向左的.所以还可以等价地定义g为:
    
    g x = double $ f x
    
    引入$, 避免了括号的使用, 尤其当$后的表达式很长有多行时使用$是很方便的.
    
    
五. 多变量函数


  严格说来, 一个函数只能接收一个参数, 返回一个值. 但有两种方法可以实现多变量函数.
  
  1.Curried函数
  
  函数接受一个参数后, 返回的也是一个函数, 这个函数对可以接受别的参数. 比如:
  
  add :: Int -> Int -> Int
  add x y = x + y
  
  从add类型可以看出, 有两个"->", 而"->"的结合次序是从右向左, 所以add的类型是:
  
  Int -> ( Int -> Int )
  
  即add接受一个Int参数, 返回一个( Int -> Int )的函数, 这个函数再接受一个Int返回一个Int.
  
  这样的函数就叫curried函数.
  
  2.使用数组
  
  数组就是把几个变量放到一起看成是一个变量, 从而使函数可以输入和输出多个变量. 比如:
  
  add :: (Int,Int) -> Int
  add (x,y) = x+y
  
  数组是Haskell中的一种数据结构, 数组中可以放不同类型的变量, 数目不限但长度固定, 数组的类型就是数组内各元素的类型组合起来构成一种类型.
  
  这两种函数在使用中各有特色, 而且可以用Prelude中定义的curry和uncurry互相转换.
  
  curry          :: ((a,b) -> c) -> (a -> b -> c)
  curry f x y     = f (x,y)

  uncurry        :: (a -> b -> c) -> ((a,b) -> c)
  uncurry f p     = f (fst p) (snd p)
  
  稍作一点解释:类型说明中出现的小写a,b,c等叫类型变量, 表示任意一种类型. f (x,y)表示f接受数组为参数, curry f x y就是(curry f) x y 表示curry f可以接受两个变量为参数. 令 g=curry f, 则 g x y = f (x,y). 可见curry的转换作用, curry的类型表达更清楚和说明了这一点. uncurry也是一样的道理, 其中的fst和snd分别表示取二元数组的第一个和第二个元素.定义如下:
  
   fst            :: (a,b) -> a
   fst (x,_)       = x
   
   snd            :: (a,b) -> b
   snd (_,y)       = y
   
   "_"叫匿名变量, 匹配指定类型任意的输入值, 该值在"="后的表达式中不会用到.
  
    
六. 离散函数
  
   有些函数的参变量只有有限个取值, 比如Prelude中not的定义如下:
   
   not         :: Bool -> Bool
   not True     = False
   not False    = True
   
   not对逻辑变量取反.

   离散的变量可以使用保留字data定义, 比如:
   
   data Direction = Left|Up|Right|Down
   
   这就定义了一种Direction类型的变量, 这种变量的取值只有四个值:Left,Up,Right,Down.
   
   data定义了一个新的类型, type则可以给一个已有的类型取一个别名.比如:
   
   type Point = (Float, Float)
   
   (Float, Float)是容纳两个Float变量的数组的类型, 取别名后既简化了书写, 也附加了含义.
   
   现在看针对离散变量的函数如何定义:
   
   move :: Direction -> Point -> Point
   move Left  (x,y) = (x-1,y)        
   move Up    (x,y) = (x,y-1)
   move Right (x,y) = (x+1,y)
   move Down  (x,y) = (x,y+1)
   
   即分别对应离散变量的每一个取值对函数作相应的定义. 以(x,y)表示位置, 给move输入移动的方向和当前的位置, 就输出了移动后的位置.
   
   再看一个例子:
   
   data Thing = Paper | Stone | Scissors   deriving Show

   beat :: Thing -> Thing
   beat Paper    = Scissors
   beat Stone    = Paper
   beat Scissors = Stone
   
   定义Thing类型有三个取值, deriving Show表示Thing类型继承Show类, 从而拥有的Show的method, Show类的作用是将取值转化为字符串在屏幕上显示. beat定义了三种物品,纸,石头,剪刀之间的输赢关系.
 

   自然数是离散的也是无限的, 以自然数为变量的函数通常用迭代的方法定义, 即函数自己调用自己.举个例子:
   
   fac 0 = 1
   fac n = n * fac (n-1)
   
   这样计算fac n时, 先去计算fac (n-1),有fac n = n * fac (n-1)=n * (n-1) * fac (n-2),如此类推, 一直算到fac 0, 最后的结果是把从1到n的自然数全部连乘起来.
   
   再比如:     
   increment,fib :: Int -> Int
   
   increment x=x+1
   
   fib 1 = 1
   fib 2 = 2
   fib n = fib (n-1) + fib (n-2)
   
   当计算函数时, 按照输入的参数逐一匹配所给的模式, 如果无法匹配时给出错误中断. 对于自然数模式匹配还允许用如下方式定义函数:
   foo (n+1) = n-1
   
   Haskell中预定义的针对字符的函数有:
   isAscii, isLatin1, isControl, isPrint, isSpace, isUpper, isLower,
   isAlpha, isDigit, isOctDigit, isHexDigit, isAlphaNum,
   digitToInt, intToDigit,
   toUpper, toLower,
   ord, chr,等
   
   ord将字母转换为数字, chr反之.
   
   
   
七. 连续函数


   Haskell中整数可以用Int和Integer表示, 实数可以用Float(单精度)和Double(双精度)来表示. 有理数还可用Rational表示, 相当于无限精度的浮点数.
   Prelude中定义了两个在数学上较基本的函数:
   
   1. 常数函数
   
   const          :: a -> b -> a
   const k _       = k
   
   2. 单位函数
   
   id             :: a -> a
   id    x         = x
   
   当函数针对变量的不同取值范围有不同的行为时, 就要用到选择结构. 比如:
   
   3. 绝对值函数
   abs' x = if x>=0 then x else -x    
   
   if ... then ... else ...的结构也可以用"|"(guard)来表达, 上述abs'也可写成:
   
   abs' x |x>=0      = x
          |otherwise = -x  
   
   "|"还可用于更多的分支选择, 比如:
   4. 符号函数
   
   sign x |x>0  = 1
          |x==0 = 0
          |x<0  = -1
          
   绝对值函数和符号函数在Prelude中分别为abs和signum, 其定义是用prime函数实现的.
   下面再举几例子,以熟悉函数的定义方法.                
   
   5. 二次方程求根函数:
   
   root (a,b,c) = (x1,x2) where        
       x1=(-b+d)/(2*a)
       x2=(-b-d)/(2*a)
       dd = b*b-4*a*c
       d | dd>=0 =sqrt dd
         | dd<0  =error "No real root"
   这里where引入一个内嵌的语句块, 在其中定义的函数在外部是看不到的. error函数用来提示出错的信息.
   
   6. 求导函数
   
   diff :: (Float->Float) -> (Float->Float)
   diff f = f’
      where f’ x = (f (x+h) - f x) / h
            h = 0.0001
  为了h的取值可调, 也可以把h包括在参数中:
   flexDiff h f x = (f(x+h)-f(x))/h
    
  把flexDiff h sin 1的取值和cos 1的取值在h=0.001,0.0001,0.00001下比较, 取0.0001的接近程度最好.
  
  7. 方程求根
  利用牛顿法可定义函数为:
  zero :: (Float->Float) -> Float
  zero f = until goodEnough improve 1.0
       where improve b = b - f b / diff f b
             goodEnough b = f b ~= 0.0
             
  其中until是Prelude中定义的执行循环的一个函数, 其定义如下:
  
  until          :: (a -> Bool) -> (a -> a) -> a -> a
  until p f x    = if p x then x else until p f (f x)
  
  until的作用是看条件p x是否成立, 不成立就用f作用x, 返回值替代原来的x, 直到条件p x成立为止.
     
  表示约等于的运算符~=则需要自己定义.
  
  8. 求逆函数
  利用方程求根的结果就可以求逆:
  inverse :: (Float->Float) -> Float -> Float
  inverse g a = zero f
      where f x = g x - a    
      
      
八. 数列和数组

   数列中元素的类型一致, 元素数目可变; 数组中元素的类型任意, 元素数目固定. 可以说数列和数组对数据的抽象做到了性能与灵活性的恰到好处, 有些语言中只提供一种容器, 元素数目可变, 类型也任意, 其结果是无法满足类型完全的需要, 也将低了运算的效率.
   
   数组的使用比较简单, 对于数列来说则大有文章.
   
   1. 数列的构造
   
   数列是用[]和(:)构造的, []是一个空的数列, x:xs的含义是元素x附加到数列xs的前面组成一个更长的数列. 比如, 1:[] 等于[1], 2:3:1:[]等于[2,3,1], 运算符(:)是从右向左运算的. 所有的数列都可以看作是从[]开始, 将各元素用(:)附到上面形成的. 在实际编程中有一些简记法可以快速地构造数列.
   
   a. 列举法
   
   将数列的元素一一列举, 比如: [1,2,3], ['A','B','d'], [[1,2], [4,5,6]]等等, 数列的类型用"[元素类型]"来表示, 这几个例子的类型依次为: [Int], [Char], [[Int]].
   
   b. 给出变化范围
   
   适用于构造等差数列, 比如: [1..5]等于[1,2,3,4,5], ['a'..'d']等于['a','b','c','d']等于"abcd"因为type String=[Char]. 默认的等差为1, 也可以给出前两个元素指定等差, 比如: [2,4..8]等于[2,4,6,8], [2,4..7]等于[2,4,6], [2.5,4..9.5]等于[2.5,4.0,5.5,7.0,8.5,10.0].
   
   c. 描述法
   
   描述法给出数列中元素取值的范围以及所满足的条件, 与数学中集合的描述法是一样的. 例如:
   
   [3*x+2| x<-[3,6,9]] --记号"<-"表示属于,x依次取3,6,9,代入3*x+2,得到数列[11,20,29]
   [x*x| x<-[1..9], x `rem` 3==1] --给出x的范围,还限定x除3余1
   [(x,y)|x<-[1,2,3],y<-[x..3]] --等于 [(1,1),(1,2),(1,3),(2,2),(2,3),(3,3)]
   
   2. 从数列中选取元素
   
   head --数列的第一个元素
   tail --除去第一个元素剩余的数列
   last --最后一个元素
   init --除去最后一个元素剩余的数列
   take n --数列前n个元素
   drop n --除去数列前n个元素剩余的数列
   (!!)n  --第n个元素, 索引指标从0开始
   
   3. 从数列中筛选元素
   
   filter p    --把数列中所有满足条件p的元素取出来组成一个数列
   takeWhile p --从第0个元素起, 取满足p的元素, 遇到不满足条件的元素时停止
   dropWhile p --从第0个元素起, 去掉满足p的元素, 遇到不满足条件的元素时停止
   
   条件p是一个以数列元素为自变量, 返回值为逻辑值的函数. 比如预定义的even,odd判断奇偶性.
   
   4. 常用数列函数
   
   length lst --求数列的元素数目
   reverse lst --将数列中元素次序反过来
   lst1 ++ lst2 --将两个数列连成一个数列
   concat lst  --lst是数列的数列,concat将各子数列一个数列
   
   sum lst  --对lst中的元素求和
   product lst  --lst中的元素连乘
   elem e lst --判断e是否为lst中的元素
   
   or lst    --对类型为[Bool]的lst中所有元素求或
   and lst   --对类型为[Bool]的lst中所有元素求与
   
   zip
   
   5. 高阶函数
   
   map f lst --将lst按照函数f映射得到一个新的数列
   map :: (a->b) -> [a] ->
   map f [] = []
   map f (x:xs) = f x : map f xs
   
   foldr,foldl --给定一种运算和一个初值,将初值和数列中所有元素由此运算连起来计算
   foldr :: (a->b->b) -> b -> [a] -> b
   foldr op e [] = e
   foldr op e (x:xs) = x ‘op‘ foldr op e xs
   
   foldl op e [] = e
   foldl op e (x:xs) = foldl op (e‘op‘x) xs      
   
   示例:
   
   rate   :: [Float]->[Float]                  
   rate ls = map (/s) ls where s=sum ls   
   
   --(/s)是将运算符"/"偏参化,并括起来当作函数使用   
   
   numDigits [] = 0
   numDigits (c:cs) = (if (c >= '0') && (c <= '9') then 1 else 0) + numDigits cs
   
   --典型的以模式匹配和迭代的方法定义数列函数, numDigits 计算字符串中数字的个数
   
   
九. 无限数列

   可以定义无限长的数列, 比如:
   from :: Int -> [Int]
   from n = n : from (n+1)
   
   from2 = from 2    
   
   from n得到的是一个从n开始的无限长的自然数列, 因为Haskell的lazy evaluate或non-strict的特性, 这个定义并不会引起无限次的计算. 对数列进行操作时, 有的函数要用到数列中所有的元素, 用这样的函数操作无限数列就会使计算机不停地计算, 直到内存或堆栈不够用为止; 而有的函数只用到数列的一部分元素, 这时无限数列就派上用场了. 比如:
   
   take 5 from2 => [2,3,4,5,6]
   from2(!!)9   => 11
   takeWhile (\x->x*x<100) from2 => [2,3,4,5,6,7,8,9]
   
   这里用"=>"表示计算结果, (\x->x*x<100) 是一个匿名函数,即用这样的格式表达了函数的输入与输出却不用给函数起名字另行定义.
   
   上述from函数其实可以用给出数列元素变化范围的方法直接得到数列, 比如: [2..], [1,3..]
   Prelude中定义用于生成无限数列的函数还有:
   repeat :: a -> [a]
   repeat x = x : repeat x    --对元素a无限重复
   
   iterate :: (a->a) -> a -> [a]
   iterate f x = x : iterate f (f x)
   {-
   iterate (+1) 3 is [3, 4, 5, 6, 7, 8, . . .
   iterate (*2) 1 is [1, 2, 4, 8, 16, 32, . . .
   iterate (/10) 5678 is [5678, 567, 56, 5, 0, 0, . . .
   -}
   下面再举几个无限数列的应用的例子:
   
   squares = [ x*x | x<-[0..]]
   isSquare n = elem n (takeWhile (<=n) squares)   --判断一个数是否为平方数
   
   fibs = fibgen 1 1   --Fibonacci 数列
   fibgen n1 n2 = n1 : fibgen n2 (n1+n2)
   
   primes = map head (iterate crossout [2..])      --用筛法求素数  
    where  crossout (x:xs)=filter (not.divisible x) xs
           divisible x y = y `rem` x == 0
   
  prime = sieve [2..]         ---改进后的素数数列
  sieve (x:xs) = x : sieve (filter (\y ->y `rem` x /= 0) xs)
  
  有了这些定义后, take 100 prime 就是取前100个素数, prime(!!)1000 就是取第1000个素数, 因为数列的定义是无限的, 数列的计算是有限, 这样就无须为不同的需要定义不同长度的数列, Hakell处理无限数列的能力实在是令人叹服.
  
  
十. 数列排序

    Qucik Sort是对数列元素快速排序的一种算法. 初次见到的版本是:
    
    qsort1 []     = []
    qsort1 (x:xs) = qsort1 elts_lt_x ++ [x] ++ qsort1 elts_greq_x
                where
                  elts_lt_x   = [y | y <- xs, y < x]
                  elts_greq_x = [y | y <- xs, y >= x]
                  
    后来又有人将其写为:
    
    qsort2 [] = []
    qsort2 (x:xs) = qsort2 less ++ [x] ++ qsort2 more
         where less = filter   (<x)  xs
               more = filter   (>=x) xs
 
    可以明显地看到在比较的过程中对数列扫描的两次, 所以我就想能不能扫描一次就把比x大的和比x小的分开, 这就是我的第一个实现这一想法的程序:
    
   qsort3 [] = []
   qsort3 (x:xs) = qsort3 xl ++ [x] ++ qsort3 xr
       where  (xl,xr,_) = until f g ([],[],xs)
              f (_,_,w)=w==[]
              g (l,g,y:ys) |y<=x =(y:l,g,ys)
                           |y> x =(l,y:g,ys)
                           
                           
    但这个程序的效率不高, 然后就逐渐改进:
    
   qsort4 []=[]
   qsort4 (x:xs)=qsort4 xl ++ [x] ++ qsort3 xr
          where (xl,xr)=split (<x) xs
                split f []=([],[])
                split f (y:ys) |f y  =(y:fst (split f ys),snd (split f ys))
                               |True =(fst (split f ys),y:snd (split f ys))    
                               
                                   
   qsort5 []=[]
   qsort5 (x:xs)=qsort5 xl ++ [x] ++ qsort5 xr
          where (xl,xr)=split (<x) xs
                split f []=([],[])
                split f (y:ys) |f y  =(y:l,r)
                               |True =(l,y:r)
                               where (l,r)=split f ys                                                            
                               
   qsort6 []=[]
   qsort6 (x:xs)=qsort6 xl ++ [x] ++ qsort6 xr
         where (xl,xr)=split x xs
               split _ [] = ([],[])
               split e (x:xs) | e>=x  = (x:l,r)
                              | e<x   = (l,x:r)
                              where (l,r) = split e xs
   
   qsort7 []=[]
   qsort7 (x:xs)=qsort7 xl ++ [x] ++ qsort7 xr
         where (xl,xr)=split x xs
               split _ [] = ([],[])
               split e (x:xs) | x<e   = (x:l,r)
                              | True  = (l,x:r)
                              where (l,r) = split e xs
                              
                              
   qsort8 []=[]
   qsort8 (x:xs)=qsort8 xl ++ (x: qsort8 xr)
         where (xl,xr)=split x xs
               split _ [] = ([],[])
               split e (x:xs) | x<e   = (x:l,r)
                              | True  = (l,x:r)
                              where (l,r) = split e xs                           
                              
                              
                              
   qsort9 ls  = qsort' ls []
       where  qsort' []     acc = acc
              qsort' (x:xs) acc = qsort' xl (x:qsort' xr acc)
                 where (xl,xr) = split x xs
                       split _ [] = ([],[])
                       split e (x:xs) | x<e   = (x:l,r)
                                      | True  = (l,x:r)
                                      where (l,r) = split e xs                           
                              
                              
   qsort10 ls = qsort' ls []
       where  qsort' []     acc = acc
              qsort' (x:xs) acc = split x xs [] [] acc
                 where split e [] l r acc = qsort' l (e:qsort' r acc)
                       split e (x:xs) l r acc | x<e  = split e xs (x:l) r acc
                                              | True = split e xs l (x:r) acc    
                                              

   qsort6 对算法的体现最直接, 最容易理解. 以后每一次改动都是为了提高程序运算的效率.
   
   尽管qsort10已经排得很快了, 但 merge sort 可以排得更快.
   
   msort:: Ord a => [a] -> [a]
   msort = treefold merge [] . map (:[])
   
   merge:: Ord a => [a] -> [a] -> [a]
   merge [] b = b
   merge a [] = a
   merge (a:a's) (b:b's)
        | a < b = a: merge a's (b:b's)
        | otherwise = b: merge (a:a's) b's
   
   为了进行检验, 在源文件最开始加入:
   
   import Random
   gen=mkStdGen 60
   lst=take 100 (randomRs (1,100) gen ::[Int])  
   
   生成一个包含100个随机数的数列lst.     
   
   
十一. 排列组合

   排列是把数列的元素的所有可能的排列次序都找出来.
   
   perms :: [a] -> [[a]]
   perms [] = [ [] ]
   perms (x:xs) = concat (map (between x) (perms xs))
       where between e [] = [ [e] ]
             between e (y:ys) = (e:y:ys) : map (y:) (between e ys)  
             
   组合是从数列中取若干个元素所有可能的取法.
                                                                                   
   combs :: Int -> [a] -> [[a]]
   combs 0 xs = [ [] ]
   combs (n+1) [] = [ ]
   combs (n+1) (x:xs) = map (x:) (combs n xs) ++ combs (n+1) xs
   
   这两个算法都是从书上找的. 以下的程序是我自己写的:
   
   maps :: [a->b]-> a ->
   maps [] x = []
   maps (f:fs) x = f x : maps fs x
   
   split :: Int -> [a] -> ([a],[a])
   split 0 ls = ([],ls)
   split _ [] = ([],[])
   split n (x:xs) = (x:xl,xr)
      where (xl,xr)=split (n-1) xs   
   
   perm :: [a]->[[a]]
   perm [] = [[]]
   perm lst = concat $ maps fs lst
      where fs = map f [0..length lst-1]
            f i lst = map (x:) (perm (xl++xs) )
                where (xl,xr)=split i lst
                      (x:xs)=xr
                      
                      
   maps和map的定义非常类似, 执行类似其他语言中for循环的功能, 而until执行while循环的功能.
   
   split将数列分成两个部分, 前半部分包括n个元素, 后半部分为剩余的元素.
   
   perm计算的效率虽不太高, 但是
   
   perm [1,2,3]
   
   输出的结果为:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
   跟自己手工排的结果是一样的. 而
   
   perms [1,2,3]
   
   输出的结果为:[[1,2,3],[2,1,3],[2,3,1],[1,3,2],[3,1,2],[3,2,1]]
   看起来有点乱.
   
   后来对perm改进得:
   
   sp xl [x] = [(xl,x,[])]  
   sp xl (x:xr) = (xl,x,xr):sp (xl++[x]) xr
   
                      
   perm' [x]=[[x]]
   perm' ls= [x:xs|(xl,x,xr)<-sp [] ls, xs<-perm'(xl++xr) ]  
   
   perm'同perm所用的算法和思路是一样的, 但效率已大大提高了.
   
                       
                      
                      
十二. 运算符

   定义一个运算符, 要说明它的结合性和优先级.
   
   infixr 右结合
   infixl 左结合
   infix  不结合
   
   左右都可结合的运算符如 +, * 定义为左结合即可.
   优先级从0到9, 0最低, 9最高
   
   已定义的运算符有:
   
   level 9 . and !!
   level 8 ^
   level 7 *, /, `div`, `rem` and `mod`
   level 6 + and -
   level 5 :, ++ and \
   level 4 ==, /=,<, <=, >, >=, `elem` and `notElem`
   level 3 &&
   level 2 ||
   level 1 (not used in the prelude)
   
   举例:    
                           
   infixr 3  &&                       
   (&&)  :: Bool -> Bool -> Bool
   False && x   = False
   True  && x   = x         

   先定义&&的结合性和优先级, 然后象定义函数一样定义它的功能.
   
   运算符用括号括起来, 可以当作函数使用, 比如:
   
   map (3+) [1,2,3]
   
   map (+3) [1,2,3]
   
   函数名用左引号`引起来, 也可以声明为运算符, 比如:
   
   fac n = product [1..n]
                     
   infix 5 !^!, `choose`
   (!^!), choose :: Int->Int->Int                   
   n `choose` k = fac n `div` (fac k * fac (n-k))
   n !^! k = fac n `div` (fac k * fac (n-k))     
   
   有了这些定义后,
   
   choose 5 2
   (!^!)  5 2
   5   !^!  2
   5 `choose` 2
   
   都给出答案10.  
   
   
十三. 复合函数


   当一个函数的返回值的类型与另一个函数输入值的类型相同时, 这两个函数就可以复合. 在Haskell中两个函数复合用运算符(.)表示. 举几个例子:
   
   f x = (x,2)
   g (x,y)=(x+y)*(x-y)
   h = g.f
   
   sumaux []=[]
   sumaux (x:xs)=x+sum xs : sumaux xs
   sums =reverse.sumaux.reverse
   
   函数复合也可以使用匿名函数, 比如:
   
   foo=not.(\x->even x && x<100)
   
   复合运算满足结合律:
   
   f . (g . h) = (f . g) . h
   
   下面看几个定理:
   
   (map f . map g) xs = map (f.g) xs 即 map f . map g = map (f.g)
   
   map f (xs++ys) = map f xs ++ map f ys
   
   map f . concat = concat . map (map f)
   
   map f . (x:) = (f x :) . map f
   
   map f xs = foldr g [] ys where g x ys = f x : ys
   
   concat xss = fold (++) [] xss
   
   length . combs k = ( `choose` k) . length
   
   sum (xs++ys) = sum xs + sum ys
   
   
   这些定理都不难理解, 也很容易证明. 你也可以自己证明一些其他的定理.

       
十四. 小结

   从前面各节的标题来看, Haskell根本就是在搞数学, 不象是在编程. 其实这正体现了Haskell的一个突出的优点, 它对各种数学概念提供了完美的支持, 我说Haskell是数学家的乐园. 数学是一个基础, 我认为把数学做好的编程语言才有潜力把其他事情做好.
   
   你在作数学题的时候, 从来也没有过把变量看作是存储器, 给变量赋值的概念, 也没有用到for,while循环语句, 而在Haskell中正好抛弃了这些概念. 用Haskell解决问题的思路与人思路非常接近, 比如相当一部分函数以数学归纳法的方式来定义, 对数据的描述性的定义等. 它掩盖了非常细节的问题, 在更高的层次上处理问题. 这样就提高了编程的效率, 提高了代码的可重用性.
   
   Haskell是世界上公认的语法最优美最简洁的一种语言。Haskell语言是写给人看的,而不是写给机器看的。另一方面,这也使得的Haskell的编译技术成为一个难点, 编译后的程序运行速度比C略慢一些。从以人为本的角度来看,程序员的时间比机器的时间更宝贵,所以Haskell是明智的选择。   
   
   以后各节将更多关注于Haskell编程方面的一些特性, 而不仅仅是做算术. Haskell的高效和强大将得到进一步的证实. 由于Haskell主要是在UNIX平台上发展起来的, 专门针对Windows的类库不是很多. 但Haskell的先进性是不容置疑的, 它的发展只是一个时间的问题.
   
   我希望你们已经意识到为什么要学函数编程语言, 欢迎来到精彩的Haskell世界--一个更好的地方.
   
   
十五. 输入输出


   1.输出字符串: putChar, putStr, putStrLn, print,
     输入字符串: getChar, getLine, getContents, interact,
     
   2.文件操作: readFile, writeFile, appendFile, readIO, readLn  
   
       
GHC使用指南

GHC可以把Haskell程序编译为可执行文件. 操作方法如下:

1.到http://www.haskell.org/ghc/下载并安装GHC.
2.用cmd打开一个命令窗口.
3.输入ghc --make file.hs 回车.
ghc为编译器, 必要时给出ghc.exe文件所在的目录, file.hs为被编译的文件, 必要时也
给出它的目录.
file.hs文件中要包含一个函数名为main的函数,运行可执行文件时这个函数被执行.
4.输出文件的文件名为a.out, 将后缀名改为exe, 就可以运行了.
5. 使用ghc -o foo file.hs 可以指定输出文件名, 在此例中将得到foo.exe
  使用ghc -O file.hs     可以优化编译输出
6. 当源程序中使用了某个或多个package时,使用
       ghc -package p_name1 -package p_name2 --make file.hs
  加载所需的包.
7. 使用ghc --interactive 可以打开ghci, 在ghci中使用:set -package name 加载包



[因为今天看如飞的这篇文章看不了,在百度的缓存页里捞出来,贴此方便自己和大家]
posted @ 2009-02-13 16:40 阿里爸爸 阅读(1351) | 评论 (0)编辑 收藏

2008年12月3日 #

 

http://cn.php.net/proc_open的以下这一段就是原来我也在玩的一个想法!很有意思!

启动一堆php子进程,这些子进程全在监听标准输入,主进程有任务时再把数据扔给子进程!这样应该比每次都生成一堆子进程来得节省资源!

 

 

 

jaroslaw at pobox dot sk
28-Mar-2008 06:15

Some functions stops working proc_open() to me.
This i made to work for me to communicate between two php scripts:

<?php
$abs_path
= '/var/www/domain/filename.php';
$spec = array(array("pipe", "r"), array("pipe", "w"), array("pipe", "w"));
$process = proc_open('php '.$abs_path, $spec, $pipes, null, $_ENV);
if (
is_resource($process)) {
   
# wait till something happens on other side
   
sleep(1);
   
# send command
   
fwrite($pipes[0], 'echo $test;');
   
fflush($pipes[0]);
   
# wait till something happens on other side
   
usleep(1000);
   
# read pipe for result
   
echo fread($pipes[1],1024).'<hr>';
   
# close pipes
   
fclose($pipes[0]);fclose($pipes[1]);fclose($pipes[2]);
   
$return_value = proc_close($process);
}
?>

filename.php then contains this:

<?php
$test
= 'test data generated here<br>';
while(
true) {
   
# read incoming command
   
if($fh = fopen('php://stdin','rb')) {
       
$val_in = fread($fh,1024);
       
fclose($fh);
    }
   
# execute incoming command
   
if($val_in)
        eval(
$val_in);
   
usleep(1000);
   
# prevent neverending cycle
   
if($tmp_counter++ > 100)
        break;
}
?>

 

posted @ 2008-12-03 16:22 阿里爸爸 阅读(1219) | 评论 (1)编辑 收藏

2008年11月21日 #

记录一下两个php5实现多任务处理的方式:
一、针对proc_open打开管道的方式
<?php

echo "Programstartsat".date('h:i:s').".\n";

$timeout=10;

$streams=array();

$handles=array();

/*Firstlaunchaprogramwithadelayofthreeseconds,then

onewhichreturnsafteronlyonesecond.*/

$delay=30;

for($id=0;$id<=10;$id++){

 $error_log="".$id.".txt";

 $descriptorspec=array(

  0=>array("pipe","r"),

  1=>array("pipe","w"),

  2=>array("file",$error_log,"w")

 );

 $cmd='sleep '.$delay.';echo "Finishedwithdelayof'.$delay.'".';
echo $cmd."--\n";


 

 $handles[$id]=proc_open($cmd,$descriptorspec,$pipes);

 $streams[$id]=$pipes[1];

 $all_pipes[$id]=$pipes;

 $delay-=2;

}

while(count($streams)){

echo "while------\n";
 $read=$streams;

 stream_select($read,$w=null,$e=null,$timeout);

 foreach($read as $r){

  $id=array_search($r,$streams);

  echo stream_get_contents($all_pipes[$id][1]) . "-\n";

  if(feof($r)){

   fclose($all_pipes[$id][0]);

   fclose($all_pipes[$id][1]);

   $return_value=proc_close($handles[$id]);
echo "--".$return_value."\n";

   unset($streams[$id]);

  }

 }

}

?>



二、针对stream_socket_client打开socket的方式

清单1.同时请求多个HTTP页面

<?php

echo"Programstartsat".date(''h:i:s'').".\n";

$timeout=10;

$result=array();

$sockets=array();

$convenient_read_block=8192;

/*Issueallrequestssimultaneously;there''snoblocking.*/

$delay=15;

$id=0;

while($delay>0){

$s=stream_socket_client("phaseit.net:80",$errno,

$errstr,$timeout,

STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);

if($s){

$sockets[$id++]=$s;

$http_message="GET/demonstration/delay?delay=".

$delay."HTTP/1.0\r\nHost:phaseit.net\r\n\r\n";

fwrite($s,$http_message);

}else{

echo"Stream".$id."failedtoopencorrectly.";

}

$delay-=3;

}

while(count($sockets)){

$read=$sockets;

stream_select($read,$w=null,$e=null,$timeout);

if(count($read)){

/*stream_selectgenerallyshuffles$read,soweneedto

computefromwhichsocket(s)we''rereading.*/

foreach($readas$r){

$id=array_search($r,$sockets);

$data=fread($r,$convenient_read_block);

/*Asocketisreadableeitherbecauseithas

datatoread,ORbecauseit''satEOF.*/

if(strlen($data)==0){

echo"Stream".$id."closesat".date(''h:i:s'').".\n";

fclose($r);

unset($sockets[$id]);

}else{

$result[$id].=$data;

}

}

}else{

/*Atime-outmeansthat*all*streamshavefailed

toreceivearesponse.*/

echo"Time-out!\n";

break;

}

}

?>

如果运行此清单,您将看到如下所示的输出。

清单2.从清单1中的程序获得的典型输出

Programstartsat02:38:50.

Stream4closesat02:38:53.

Stream3closesat02:38:56.

Stream2closesat02:38:59.

Stream1closesat02:39:02.

Stream0closesat02:39:05.

posted @ 2008-11-21 12:09 阿里爸爸 阅读(860) | 评论 (1)编辑 收藏

2008年10月14日 #

     摘要: PHP处理对象部分的内核完全重新开发过,提供更多功能的同时也提高了性能。在以前版本的php中,处理对象和处理基本类型(数字,字符串)的方式是一样的。这种方式的缺陷是:当将对象赋值给一个变量时,或者通过参数传递对象时,对象将被完全拷贝一份。在新的版本里,上述操作将传递引用(可以把引用理解成对象的标识符),而非值。

很多PHP程序员可能甚至没有察觉到老的对象处理方式。事实上,大多数的php应用都可以很好地运行。或者仅仅需要很少的改动。

私有和受保护成员
PHP5引入了私有和受保护成员变量的概念。我们可以用它来定义类成员的可见性。
  阅读全文
posted @ 2008-10-14 01:03 阿里爸爸 阅读(703) | 评论 (0)编辑 收藏

2008年9月9日 #

Mysql Explain 详解


一.语法

explain < table_name >

例如: explain select * from t3 where id=3952602;

二.explain输出解释

+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+

1.id
  我的理解是SQL执行的顺利的标识,SQL从大到小的执行.

例如:
mysql> explain select * from (select * from ( select * from t3 where id=3952602) a) b;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | <derived3> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  3 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

很显然这条SQL是从里向外的执行,就是从id=3 向上执行.

2. select_type

就是select类型,可以有以下几种

(1) SIMPLE
简单SELECT(不使用UNION或子查询等) 例如:
mysql> explain select * from t3 where id=3952602;
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+

(2). PRIMARY

我的理解是最外层的select.例如:

mysql> explain select * from (select * from t3 where id=3952602) a ;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

(3).UNION

UNION中的第二个或后面的SELECT语句.例如
mysql> explain select * from t3 where id=3952602 union all select * from t3 ;
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type  | table      | type  | possible_keys     | key     | key_len | ref   | rows | Extra |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
|  1 | PRIMARY      | t3         | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       |
|  2 | UNION        | t3         | ALL   | NULL              | NULL    | NULL    | NULL  | 1000 |       |
|NULL | UNION RESULT | <union1,2> | ALL   | NULL              | NULL    | NULL    | NULL  | NULL |       |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+

(4).DEPENDENT UNION

UNION中的第二个或后面的SELECT语句,取决于外面的查询

mysql> explain select * from t3 where id in (select id from t3 where id=3952602 union all select id from t3)  ;
+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+
| id | select_type        | table      | type   | possible_keys     | key     | key_len | ref   | rows | Extra                    |
+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+
|  1 | PRIMARY            | t3         | ALL    | NULL              | NULL    | NULL    | NULL  | 1000 | Using where              |
|  2 | DEPENDENT SUBQUERY | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 | Using index              |
|  3 | DEPENDENT UNION    | t3         | eq_ref | PRIMARY,idx_t3_id | PRIMARY | 4       | func  |    1 | Using where; Using index |
|NULL | UNION RESULT       | <union2,3> | ALL    | NULL              | NULL    | NULL    | NULL  | NULL |                          |
+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+

(4).UNION RESULT

UNION的结果。

mysql> explain select * from t3 where id=3952602 union all select * from t3 ;
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type  | table      | type  | possible_keys     | key     | key_len | ref   | rows | Extra |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
|  1 | PRIMARY      | t3         | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       |
|  2 | UNION        | t3         | ALL   | NULL              | NULL    | NULL    | NULL  | 1000 |       |
|NULL | UNION RESULT | <union1,2> | ALL   | NULL              | NULL    | NULL    | NULL  | NULL |       |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+

(5).SUBQUERY

子查询中的第一个SELECT.

mysql> explain select * from t3 where id = (select id from t3 where id=3952602 )  ;
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------------+
| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra       |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------------+
|  1 | PRIMARY     | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |             |
|  2 | SUBQUERY    | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       |       |    1 | Using index |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------------+

(6).  DEPENDENT SUBQUERY

子查询中的第一个SELECT,取决于外面的查询

mysql> explain select id from t3 where id in (select id from t3 where id=3952602 )  ;
+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+
| id | select_type        | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra                    |
+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+
|  1 | PRIMARY            | t3    | index | NULL              | PRIMARY | 4       | NULL  | 1000 | Using where; Using index |
|  2 | DEPENDENT SUBQUERY | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 | Using index              |
+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+


(7).DERIVED

派生表的SELECT(FROM子句的子查询)

mysql> explain select * from (select * from t3 where id=3952602) a ;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+


3.table

显示这一行的数据是关于哪张表的.
有时不是真实的表名字,看到的是derivedx(x是个数字,我的理解是第几步执行的结果)

mysql> explain select * from (select * from ( select * from t3 where id=3952602) a) b;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | <derived3> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  3 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

4.type

这列很重要,显示了连接使用了哪种类别,有无使用索引.
从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL

(1).system

这是const联接类型的一个特例。表仅有一行满足条件.如下(t3表上的id是 primary key)

mysql> explain select * from (select * from t3 where id=3952602) a ;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

(2).const

表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!

const用于用常数值比较PRIMARY KEY或UNIQUE索引的所有部分时。在下面的查询中,tbl_name可以用于const表:
SELECT * from tbl_name WHERE primary_key=1;
SELECT * from tbl_name WHERE primary_key_part1=1和 primary_key_part2=2;

例如:
mysql> explain select * from t3 where id=3952602;
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+


(3). eq_ref

对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY。

eq_ref可以用于使用= 操作符比较的带索引的列。比较值可以为常量或一个使用在该表前面所读取的表的列的表达式。

在下面的例子中,MySQL可以使用eq_ref联接来处理ref_tables:

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column_part1=other_table.column
    AND ref_table.key_column_part2=1;

例如
mysql> create unique index  idx_t3_id on t3(id) ;
Query OK, 1000 rows affected (0.03 sec)
Records: 1000  Duplicates: 0  Warnings: 0

mysql> explain select * from t3,t4 where t3.id=t4.accountid;
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+
| id | select_type | table | type   | possible_keys     | key       | key_len | ref                  | rows | Extra |
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+
|  1 | SIMPLE      | t4    | ALL    | NULL              | NULL      | NULL    | NULL                 | 1000 |       |
|  1 | SIMPLE      | t3    | eq_ref | PRIMARY,idx_t3_id | idx_t3_id | 4       | dbatest.t4.accountid |    1 |       |
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+

(4).ref

对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。

ref可以用于使用=或<=>操作符的带索引的列。

在下面的例子中,MySQL可以使用ref联接来处理ref_tables:

SELECT * FROM ref_table WHERE key_column=expr;

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column=other_table.column;

SELECT * FROM ref_table,other_table
  WHERE ref_table.key_column_part1=other_table.column
    AND ref_table.key_column_part2=1;

例如:

mysql> drop index idx_t3_id on t3;
Query OK, 1000 rows affected (0.03 sec)
Records: 1000  Duplicates: 0  Warnings: 0

mysql> create index idx_t3_id on t3(id) ;
Query OK, 1000 rows affected (0.04 sec)
Records: 1000  Duplicates: 0  Warnings: 0

mysql> explain select * from t3,t4 where t3.id=t4.accountid;
+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+
| id | select_type | table | type | possible_keys     | key       | key_len | ref                  | rows | Extra |
+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+
|  1 | SIMPLE      | t4    | ALL  | NULL              | NULL      | NULL    | NULL                 | 1000 |       |
|  1 | SIMPLE      | t3    | ref  | PRIMARY,idx_t3_id | idx_t3_id | 4       | dbatest.t4.accountid |    1 |       |
+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+
2 rows in set (0.00 sec)

(5).  ref_or_null

该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。

在下面的例子中,MySQL可以使用ref_or_null联接来处理ref_tables:

SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;

(6). index_merge

该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。

例如:
mysql> explain select * from t4 where id=3952602 or accountid=31754306 ;
+----+-------------+-------+-------------+----------------------------+----------------------------+---------+------+------+------------------------------------------------------+
| id | select_type | table | type        | possible_keys              | key                        | key_len | ref  | rows | Extra                                                |
+----+-------------+-------+-------------+----------------------------+----------------------------+---------+------+------+------------------------------------------------------+
|  1 | SIMPLE      | t4    | index_merge | idx_t4_id,idx_t4_accountid | idx_t4_id,idx_t4_accountid | 4,4     | NULL |    2 | Using union(idx_t4_id,idx_t4_accountid); Using where |
+----+-------------+-------+-------------+----------------------------+----------------------------+---------+------+------+------------------------------------------------------+
1 row in set (0.00 sec)

(7). unique_subquery

该类型替换了下面形式的IN子查询的ref:

value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。

(8).index_subquery

该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引:

value IN (SELECT key_column FROM single_table WHERE some_expr)

(9).range

只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL。

当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比较关键字列时,可以使用range

mysql> explain select * from t3 where id=3952602 or id=3952603 ;
+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys     | key       | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+
|  1 | SIMPLE      | t3    | range | PRIMARY,idx_t3_id | idx_t3_id | 4       | NULL |    2 | Using where |
+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+
1 row in set (0.02 sec)

(10).index

该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。

当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。

(11). ALL

对于每个来自于先前的表的行组合,进行完整的表扫描。如果表是第一个没标记const的表,这通常不好,并且通常在它情况下很差。通常可以增加更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。


5.possible_keys

possible_keys列指出MySQL能使用哪个索引在该表中找到行。注意,该列完全独立于EXPLAIN输出所示的表的次序。这意味着在possible_keys中的某些键实际上不能按生成的表次序使用。

如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查WHERE子句看是否它引用某些列或适合索引的列来提高你的查询性能。如果是这样,创造一个适当的索引并且再次用EXPLAIN检查查询

6. key

key列显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。

7.key_len

key_len列显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。
使用的索引的长度。在不损失精确性的情况下,长度越短越好

8. ref

ref列显示使用哪个列或常数与key一起从表中选择行。

9. rows

rows列显示MySQL认为它执行查询时必须检查的行数。

10. Extra

该列包含MySQL解决查询的详细信息,下面详细.

(1).Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了

(2).Not exists
MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,

就不再搜索了

(3).Range checked for each

Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一

(4).Using filesort
看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行

(5).Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候

(6).Using temporary
看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上

(7).Using where
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题
posted @ 2008-09-09 13:15 阿里爸爸 阅读(154110) | 评论 (6)编辑 收藏

2008年7月11日 #

校园里槐花香味弥漫,绿树成荫。门口一阵掌声打破了之前的嘈杂,唐骏微笑着从学生堆里挤出来。

他,曾历任微软中国总裁、盛大总裁,以年薪超过1亿元被媒体称为中国的“打工皇帝”。

“快点,不然就没位置了”一个站在厕所门口,不住的回头看报告厅的女生,朝着厕所门大声喊。“我没吃早餐就冲过来了,可是还是没位置。”一个男生愤愤地说。

唐骏走上演讲台,“我跟你们说一下我的个人密史,是我大学时代的初恋故事。”他神秘的说,台下一片掌声。

他这次是受管理学院院长包国宪教授之邀,做客“全球通”兰州大学管理学院学术论坛,讲述他职业规划的经历。

“在大学里,我很平凡、很普通,普通的让我感动,但我是有追求的。”他略带微笑的说。

本来是380多人的报告厅,现在有700多人,一千多双眼睛直射向唐骏。

三个门口人的密度最大,整个会堂呈三面包围状,前面的同学直接盘腿席地而坐。

唐骏1985年—1990年在日本名古屋大学自动化专业攻读硕士学位。“我考北京邮电大学研究生时是第一名,但没有得到出国留学的机会,”他冷静地说,“我就打电话问有没有剩余的名额,正好北京广播电视学院有一个,我就跑到教育司,李司长说:‘同学,你回去吧。’”

“我没有放弃,”他肯定的说。“每天早上7点,我就跑到教育司门口等李司长,一天、两天、三天,在第六天的时候李司长让我进他的办公室,填了一堆空白资料。”

“我还想要在教育司一直呆到毕业为止,”他笑了笑,“我什么也没做,就是执着。”

1994年,唐骏加入微软,微软当时有12000人,而他只是一个处于末尾的普通的软件工程师。

“在这些超人面前等待?放弃?不,我不放弃,不等待。”他决然的说。

现在英语、德语、日语、阿拉伯语等多语言引擎同时上市,再也不用先下载相应语言的Windows才能看网页了,方便了很多人。

“现在的大学生进入企业就开始抱怨,”他说,“我刚来微软的时候也发现微软有很多问题,但是我没有抱怨,而是利用晚上和周末的时间研究,最后才有多语言引擎的出现。”

“我选择了别人没去做的事情。”他总结说, “在职业生涯中,要学会创造机遇,不是等待机遇。”

“在任何时期、阶段,勤奋是可以弥补不足的,”他双手指挥似的说,“在微软没有人可以站出来说比唐骏更勤奋的。”

2004年2月,唐骏由微软公司退休,同时被公司授予“名誉总裁”称号

“简单+勤奋是我的座右铭,简单做人,勤奋做事。”他笑着说,“要先做人,再做事,偶尔做做秀,人生需要像企业一样经营。”

白色条文衬衣,碎花领带,脸瘦的有点尖,明显的白色上眼皮的他在两个小时的演讲中,每隔两分钟就会有一次笑声或掌声,声音渐小后音响发出砰砰声。

posted @ 2008-07-11 17:45 阿里爸爸 阅读(827) | 评论 (0)编辑 收藏

IT招聘专家和工作场所专家总结了技术专业人员应该掌握的一些具体技能。这些技能会帮助IT专业人员避免工作的低谷和得到薪酬上涨的好处。下面就是让IT人员提高薪酬的10种方法。

  1.熟悉SAAS产品

  IT人员配备和随需应变的咨询公司Bluewolf的共同创始人和负责人Michael Kirven说,SAAS(软件服务)知识在用人要求条件中的比例已经从三年前的5%提高到了35%。拥有这方面知识的人可能很快提高自己的薪酬,无论他们是否知道alesforce、Google Apps或者WorkDay。每一个人都需要知道这些产品如何适合当前的IT架构。

  2.获得SAP知识或者经验

  位于费城的人才和外包服务公司Yoh Services复杂战略和营销的副总裁Jim Lanzalotto称,他支持拥有SAP技术的人,因为SAP技术顾问的需求量和现有人员之间的缺口有3至4万。

  3.获得一个行业的垂直的技术专长

  Kirven说,做一个Java程序员或者一个熟练的.Net开发人员就是一件很好的事情。但是,随着系统越来越复杂,企业不仅需要这些人学些这些编程语言,而且还要了解具体的垂直市场知识,如金融、零售或者媒体,并且了解所有这些知识。

  4.获得一个虚拟化项目

  IT job board Dice网站称,它看到招聘列表中对虚拟化知识人才的需求在过去的六个月里提高了40%,特别是需要了解VMware技术的人。

  5.提高你的商务技能

  Lanzalotto认为,商务经验对于提高IT专业人员的薪金水平是非常重要的。他说,最好的首席信息官不仅仅是一个技术人员,而且应该是能够在技术和业务两个方面都能够工作的业务人员。

  6.获得开源软件产品开发经验

  Kirven说,由于时代已经发生了变化,首席信息官采用MySQL和其它开源软件技术不会有失去工作的风险。事实上,业务人员经常会喜欢开源软件,因为它可能为公司省钱。

  7.更近一步了解能够让你的公司赚钱的技术

  在大型银行或者金融机构工作的人都知道你越接近能够让你的公司赚钱的技术,你的工作岗位对于你的公司就越重要。IT人员也是如此。参与让你的公司增加收入或者节省金钱的项目的IT人员很少会被人忽略。

  8.首席信息官需要架构技能

  Kirven称,IT架构是一个极好的职场道路,不仅因为这是一个高级的职位,而且还因为这些职位几乎完全是不会外包出去的。

  9.付费参加项目管理认证学习的人

  许多研究报名,虽然并非所有的证书都比印刷证书的成本值钱,但是,企业继续付出高价的费用聘用拥有关键证书的人才。其中最最主要的两个项目管理证书是PMP(项目管理专业人员)和PMO(项目管理办公室)。

  10.跳槽

  IT专业人员从一个地方搬迁的另一个地方的比例提高了20%。当你在你的技术专长领域寻求进一步发展时,换一个地理环境也许会有帮助。不同地区对于IT专业人员的技术需求是不同的。

posted @ 2008-07-11 17:34 阿里爸爸 阅读(1282) | 评论 (1)编辑 收藏

2008年7月3日 #

宝洁旗下Tremor公司称他们用新方旧法调和,再配以大量秘制调料,揭开了口碑营销的秘密。 

  药剂师们从不指望偶然配成长生不死药,化学家们不会空耗时日炼铅成金,美国宇航局的科学家们也不会徒劳地修补时间机器。

  可是,宝洁公司倒是有一帮人耗费四年时光,要锤炼出营销魔法∶自然而然的口碑,也就是大家告诉大家。他们努力的硕果是打造了一支营销劲旅—Tremor公司,该公司声称已经揭开了口碑妙方的秘密。Tremor筛选出25万名青少年志愿者,构成庞大网络,先与同龄人接触最新的产品和理念。不用说,宝洁希望这些志愿者能够和周围的朋友们分享他们的新体验。这一招收效甚大,促使Tremor开始瞄准另一个目标市场—妈妈们—来施展逐渐成长起来的口碑营销。

  从这一举措背后可以窥见Tremor创造者的奇思妙想。想想这个名字就知道了∶颤栗(tremor)可能是一阵难以捉摸的情感或思绪,转瞬即逝。在Tremor网站的主页上,总是跳动着令参与者们激动的承诺。

  尽管这支劲旅采用的手段充满神秘色彩,宝洁仍然把它奉为营销科学∶旧法新用,通过以技术为后盾的研究加上创新方法来打造客户关系。这并不意味着宝洁愿意把魔法秘密公之于众,但是在接受《市场营销官》杂志采访时,Tremor的首席执行官史蒂夫·诺克斯确实道出了宝洁研发及其成果的许多内幕。他还谈到了现在口碑营销上的知识缺口及其未来发展方向。

  “在Tremor成立的头几年,我们全力去了解口碑在市场上如何发挥作用,”诺克斯说。而且工作还不止于此。“口碑营销是一门动态科学而非静态科学。”

  有些持怀疑态度的人说,口碑营销绝不可能是科学,硬把口碑同营销扯上关系太牵强。有些批评者认为,大肆夸大口碑营销的作用,妄想产生消费者自发宣传品牌的效果,只可能让营销人面对更大的挑战,因为公众会变得更多疑、更轻视广告宣传。但是宝洁这家全球最大的广告客户,不仅打造了一个口碑营销项目,而且专门成立了一个公司来推动口碑营销,其声势绝对能够淹没怀疑者们的声音。

  Tremor的客户数量快速增加。从2001年起,Tremor开始为母公司和其他公司的产品打造广告宣传活动。现在,Tremor为包括梦工厂在内的电影制作公司、可口可乐和丰田等品牌公司制作口碑营销计划。诺克斯说公司80%的品牌宣传活动中都是为其他公司制作的,但是他彬彬有礼地拒绝透露(或确认)任何客户的名称。

  除了宝洁以外,还有许多公司也在尝试把口碑营销由理想转变为真正可靠的分销渠道。口碑营销协会于2004年成立,拥有会员150 家。协会于3月份在芝加哥召开了第一次大会。随着Tremor和类似的口碑营销模式不断发展变化,许多大公司都开始密切关注这个新潮流了。

  Sprint通讯公司的消费者电子商务总监大卫·迪克凯说∶“我们没有宝洁走得那么远。我们还不确定口碑营销会朝哪个方向发展。但是我们先要充分了解这个领域,如果它繁荣发展下去,我们就可以随时加以利用。”  

  口碑营销第一步∶联络员

  推动Tremor前进的是25万名青少年,宝洁称他们为“联络员”。据诺克斯说,从宝洁的最初研究中得出的主要启示就是,这些“联络员”自始至终活跃在产品为市场接受的过程中,因而他们有别于享有“潮流创新者”之称的潮流先驱和早期采用者。这些“潮流创新者”很了解消费者的需求。虽然他们能够迅速接受新产品和新理念,但是却不一定能构成口碑营销的通途大道;有些潮流先驱有可能成为口碑传播的死胡同,因为他们会把只有自己知道的秘密囤积起来,秘而不宣。

  而联络员却不同,即使他们是最后知道秘密的人,也会马上广而告之,告诉身边的人去关注某个新产品、一首酷歌、新电视节目或是新电影。诺克斯认为,这些人有着真正广泛深厚的社会关系网络,而且很愿意同他人交流。

  Tremor的广告宣传取得成功,全要靠这些联络员们的动动嘴、动动手指(敲键盘),因此宝洁投入了大量时间、设计了种种方法来识别他们。第一步是把青少年吸引到Tremor网站(Tremor.com)来。申请参加者一旦登陆,就有各种问题要回答(例如,每天你和多少人交谈?买了新产品有什么感想?)。通过这些问题可以发现候选人的八项个性特征。诺克斯告诉我们其中三个最重要的特征∶好奇,善于交际,善于游说。例如,一个典型联络员的密友名单上,一般都会有150~200个一有消息就联系的朋友。

  在筛选阶段,大概会有15%的申请者能够通过,这些人被称为Tremor的新成员。而没入选的也会被礼貌地拒绝∶“谢谢您对Tremor的关注。很抱歉,这次我们的申请人数已满。”入选者接着将进入“新兵训练营基地”接受严格的训练。Tremor运用各种新理念、新机会吸引他们。比如,Tremor曾发出一封电子邮件,邀请入选者为某部电影提供创意,邮件的标题就是“像好莱坞大腕那样思考”。

  其间,宝洁的员工通过网络在幕后监视他们是否行如其言。简言之,看看这些孩子怎么处理得到的第一口独一份的美味。接下来的就是Tremor的秘方调料了。有8~10%的最初申请者会获得联络员的身份(占目标群体的1%)。即使是更深入Tremor之后,这些正式成员仍然会受到秘密评估,而他们自己浑然不觉。诺克斯坦然承认了这一细节,可是却给Tremor自称的透明度罩上了一层阴影—对任何口碑营销来说,透明度可能都是引起人们争议的焦点吧。

  诺克斯深信,这个精英群体极具影响力,他们是营销人忽视的一支劲旅。的确,像交友网站Fraudster这样的品牌公司,还有BuzzMetrics等口碑营销公司正在拼命追踪联络员型消费者,又称市场影响者、传导者或是蜜蜂。但是,其他准备开展口碑营销的营销人担心这些影响者获得的影响力太大。

  这种辩论常常使Tremor和 BzzAgent陷于争斗之中。BzzAgent的客户包括家乐氏(Kellogg), 拉尔夫劳伦(Ralph Lauren)和啤酒商 Anheuser-Busch等。这家公司自己没有健全的筛选志愿者的专利体系,它的做法是有多少人要多少人(到目前为止,它已拥已有8.6万名志愿者)。志愿者们在线申请,在线签约参加试用新产品,与亲朋好友及其他人交流对产品的感想,然后写成日记发送给BzzAgent。

  与Tremor不同,BzzAgent认为任何顾客——无论是家庭主妇还是首席执行官——都有可能和别人聊聊最新市场动向,而且大部分人也很乐于通过不同的人获得信息。BzzAgent的首席执行官大卫·巴尔特说∶“在制造口碑方面,市场影响者并不比一般人做得更好。人人都可以成为我们的宣传员。”

  口碑营销第二步∶有价值

  一谈到影响者的问题,大部分营销人都认为,如果传递信息的人没有诚意,口碑营销就是无效的。对Tremor来说,在精挑细选了联络员之后,只完成了可信的口碑营销的一半。公司还必须设法精心修饰产品,以便达到口碑营销的最佳效果。

  联络员的关系是在线形成的。但大多数情况下,联络员和产品之间的纽带是在线下结成的∶公司通过邮局寄发给他们礼品包,有贴画,DVD或是样品。Tremor和品牌代表们多次召开会议,反复讨论这些礼品包以及整个宣传活动,看看它们是否能体现两个要素∶可倡导与可扩大。

  可倡导和可扩大的模式是在理论、心理学知识、宝洁现有数据和Tremor的专利调研几个方面结合的基础上建立起来的。用Tremor的行话来说,当联络员自然地体验某种产品、喜欢上它并和同伴谈论它时,就是在倡导产品。诺克斯解释道∶“当联络员刚开始接触一个新想法,他首先会问自己∶‘这个想法值得我广而告之吗?’ 有价值才是他们在社会上‘畅通无阻’的通行证,因而他们所宣传的必须是自己相信的东西。”

  Tremor不会草率地下结论说一个联络员是否对某个产品有所反应。诺克斯说∶“我们有办法找到品牌值得倡导的关键要素,以及联络员倡导这个产品的理由。”

  Tremor口碑营销模式中的第二个要素是可扩大,即某个产品信息或使用体验很容易为人所道,产品能自然而然地进入人们闲谈当中。诺克斯说∶“找到同时具备可倡导和可扩大潜力的口碑理念确非易事。”

  因此,Tremor在开展广告活动之前,要先在一组联络员当中进行信息测试,来寻找最有效用的信息。诺克斯解释说∶“这样做,使我们在产品进入市场前就能够告诉客户说∶‘看见这八个想法了吗?联络员不会谈论它们的。但是这个呢?这个才是他们的热门话题。’”

  Tremor的广告要出色,关键取决于广告活动开始前所掌握的数据量。就是说,只有精心培育,才会产生大量有价值的热门话题。相比之下,BzzAgent的特色则是拥有一套流畅的反馈系统。BzzAgent培训大批“沟通开拓者”,要求他们每周仔细审阅4,000~7,000份数量可观的业务报告,并分别对每份报告做出总结。最后,再从中筛选出有用的信息绘制成图表提供给客户。

  撇开新品发布前期的精心筹划不谈,诺克斯强调,送给联络员的礼品包当中并没有指定的宣传语或是谈话要点。也就是说,即便Tremor竭尽所能培养联络员对产品的积极反应,这些青少年的行为仍是自发、真实的。可倡导和可放大性的要旨,就是“一些理由,使孩子们在自然而然的情形下对别人说:‘嗨,我跟你说过某某产品吗?’”

  他挑选的字眼儿“自然而然的情形”,在某些营销人听来,可能和“可扩大”及“联络员”这样的术语并不相称。难道人的情感刺激或体验真的可能如此地“收放自如”,像积木一样,可随意地拆分或组合?还堂而皇之地称之为“自然而然”?

  技术与互联网战略公司EchoDitto首席执行官尼科·梅尔认为,自觉的口头宣传并不是真正的口碑宣传。他的公司创立了在线社区,帮助客户提升知名度,筹措资金。梅尔说∶“最成功的营销是润物细无声式的,不为人察觉。” 霍华德·迪安2004年总统大选的网站智囊们备受赞誉,因为他们成功地运用了网志和其他互联网工具,拉拢了大批平民支持者。

  诺克斯非常清楚,当新鲜感消失,一切变得程式化,这些联络员就会逐渐感到厌倦。他说∶“这个问题让我夜不成眠。我必须和这些联络员保持一种关系,鼓励他们一直参与我们的活动。”为了使这些孩子们乐此不疲,Tremor每年只让联络员参加20次活动。

  Tremor还有其他办法防止联络员产生厌倦情绪。开展“影响力活动”,即在新品上市前邀请联络员出谋划策,还请他们为现有产品提建议。在Tremor网站上,宝洁用青少年们对产品产生的影响来鼓舞他们的士气。例如,一条大字标题这样写道∶“你告诉了佳洁士你需要什么样的产品!”在宣传香草和樱桃味可乐的“派对炫生活” 主题活动中,联络员提交了各种广告口号,网站上就打出这样的标题∶“你帮助可口可乐挑选了一个口号,它被贴在瓶上发送给了近百万人!”

  据诺克斯说,这类广告活动本身可提倡和可扩大的程度很高,因为青少年个人与品牌有了直接联系。“联络员们可以对所有的朋友说∶‘我帮那条广告挑选了音乐。’这自然而然就把这些孩子们的话题引向广告所涉及的产品了。”

  又是那个字眼儿∶自然而然。  

  口碑营销第三步∶看回报

  营销人备受印刷品和电视广告低迷回报率所困,不知如何才能贴近对媒体退避三舍的消费者群体。Tremor和其他的口碑营销公司引起了这些营销人的注意。出版商企鹅集团营销副总裁李克·帕斯克切罗,四年前首次试水,委托BzzAgent运用口碑营销宣传推广一本企鹅小说。帕斯克切罗说,他现在正和BzzAgent合作实施第24个口碑营销计划。

  当营销人纷纷转向这个新媒介的时候,他们却没有必要的好办法来衡量它的回报。例如,Tremor的口碑营销差不多在联络员的宣传停止后就同时结束了。诺克斯承认说∶“我能评估口碑从Tremor到联络员的宣传效果,最多还能评估从联络员到他们最亲密的朋友的宣传效果。在此之后,就一无所知了。”

  其他口碑营销公司寄希望于先进的口碑营销度量系统。Intelliseek等广告公司开发出各种方法,通过筛读1,100万个网志、信息板和其他网上社区,在线追踪某个品牌的口碑。在线社交网Friendster自诩拥有1,600万会员,声称能够通过追踪会员们在线联系的原因和方法来测量第二级、第三级口碑营销的效果。BuzzMetrics则提供一系列口碑调研和规划服务。他们开发了一项综合服务,用户申请该服务后,每季度都会收到有关某行业各个子市场中(如营养行业)可识别的影响者在线活动的报告和简报。

  BuzzMetrics目前向七家最大的食品公司提供该项服务。

  BuzzMetrics总裁和首席执行官乔纳森·卡森说∶“上千万的消费者在庞大数码数据支持的环境里参与口碑营销活动,这为口碑营销的衡量带来了巨大的可能性,也带来了营销人渴求的消费者责任感。”

  诺克斯指出,相对而言,Tremor的绝大多数客户更关注的是在采用了口碑营销的领域中销售状况如何,而并不是自己的品牌在网络世界里有多大的反响。销售曲线不断出现高峰,这才是驱使帕斯克切罗与BzzAgent继续合作的原因。

  他说∶“和BzzAgent的很多客户一样,我也不怎么看公司提供的图表。”帕斯克切罗更感兴趣的不是BzzAgent复杂的反馈过程,而是反馈的结果。举例说明,2001年9月11日企鹅出版集团出版了一本名为《神酷的艺术》(The Art of Shen Ku)的书。帕斯克切罗用尽了印刷品广告等各种促销手段,但是该书出版一年仍是无人问津。于是他决定尝试口碑营销,期望能让这本书“起死回生”。六个月之后,销售额翻番。帕斯克切罗说∶“如果要在印刷品广告和口碑营销之间选择,我会选择后者。”

  这些成功的案例促使口碑营销在一个个新领域里遍地开花。Tremor感到对青少年受众采用的方法效果很好,现在决定向更贴近宝洁产品线的“妈妈”市场进军。诺克斯说,Tremor需要修改一些筛选问题,例如,把妈妈们“即时通讯名单中的好朋友数量”改成“参加的机构数量”,而联络员的基本概念则会保持不变。Tremor还在尝试其他的招募方法,以便能够捕获这个对技术不敏感、也不怎么上网的消费群体。

  Tremor和客户把目光投向了口碑营销的下一个应用领域—客户保留。诺克斯一直主张,用口碑营销打造品牌忠诚度,要用可倡导和可扩大模式做基础。他问道∶“是什么原因促使联络员从现在起四个月、或是九个月、或是一年半以内向别人谈论某个产品呢?”“我们正和几个客户合作,利用口碑营销来打造会持续多年的长期忠诚度计划。”

  他当然不会说出这些客户的名字,但是如果现行模式能透露什么的话,这些客户一定会享受到一项慷慨的服务套餐,包含有Tremor专用词、影响者信条和热议话题预测等口碑营销科学的种种术语。


 

posted @ 2008-07-03 11:03 阿里爸爸 阅读(652) | 评论 (1)编辑 收藏

2008年7月2日 #

全文索引在 MySQL 中是一个 FULLTEXT 类型索引。FULLTEXT 索引用于 MyISAM 表,可以在 CREATE TABLE 时或之后使用 ALTER TABLE 或 CREATE INDEX 在 CHAR、VARCHAR 或 TEXT 列上创建。对于大的数据库,将数据装载到一个没有 FULLTEXT 索引的表中,然后再使用 ALTER TABLE (或 CREATE INDEX) 创建索引,这将是非常快的。将数据装载到一个已经有 FULLTEXT 索引的表中,将是非常慢的。

全文搜索通过 MATCH() 函数完成。

mysql> CREATE TABLE articles (
-> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
-> title VARCHAR(200),
-> body TEXT,
-> FULLTEXT (title,body)
-> );
Query OK,
0 rows affected (0.00 sec)

mysql
> INSERT INTO articles VALUES
-> (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'),
-> (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'),
-> (NULL,'Optimising MySQL','In this tutorial we will show ...'),
-> (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
-> (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'),
-> (NULL,'MySQL Security', 'When configured properly, MySQL ...');
Query OK,
6 rows affected (0.00 sec)
Records:
6 Duplicates: 0 Warnings: 0

mysql
> SELECT * FROM articles
-> WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

 函数 MATCH() 对照一个文本集(包含在一个 FULLTEXT 索引中的一个或多个列的列集)执行一个自然语言搜索一个字符串。搜索字符串做为 AGAINST() 的参数被给定。搜索以忽略字母大小写的方式执行。对于表中的每个记录行,MATCH() 返回一个相关性值。即,在搜索字符串与记录行在 MATCH() 列表中指定的列的文本之间的相似性尺度。

当 MATCH() 被使用在一个 WHERE 子句中时 (参看上面的例子),返回的记录行被自动地以相关性从高到底的次序排序。相关性值是非负的浮点数字。零相关性意味着不相似。相关性的计算是基于:词在记录行中的数目、在行中唯一词的数目、在集中词的全部数目和包含一个特殊词的文档(记录行)的数目。

它也可以执行一个逻辑模式的搜索。这在下面的章节中被描述。

前面的例子是函数 MATCH() 使用上的一些基本说明。记录行以相似性递减的顺序返回。 下一个示例显示如何检索一个明确的相似性值。如果即没有 WHERE 也没有 ORDER BY 子句,返回行是不排序的。

mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;
+----+-----------------------------------------+
| id | MATCH (title,body) AGAINST ('Tutorial') |
+----+-----------------------------------------+
| 1 | 0.64840710366884 |
| 2 | 0 |
| 3 | 0.66266459031789 |
| 4 | 0 |
| 5 | 0 |
| 6 | 0 |
+----+-----------------------------------------+
6 rows in set (0.00 sec)
下面的示例更复杂一点。查询返回相似性并依然以相似度递减的次序返回记录行。为了完成这个结果,你应该指定 MATCH() 两次。这不会引起附加的开销,因为 MySQL 优化器会注意到两次同样的 MATCH() 调用,并只调用一次全文搜索代码。

mysql> SELECT id, body, MATCH (title,body) AGAINST
-> ('Security implications of running MySQL as root') AS score
-> FROM articles WHERE MATCH (title,body) AGAINST
-> ('Security implications of running MySQL as root');
+----+-------------------------------------+-----------------+
| id | body | score |
+----+-------------------------------------+-----------------+
| 4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 |
| 6 | When configured properly, MySQL ... | 1.31140957288 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)

MySQL 使用一个非常简单的剖析器来将文本分隔成词。一个“词”是由文字、数据、“'” 和 “_” 组成的任何字符序列。任何在 stopword 列表上出现的,或太短的(3 个字符或更少的)的 “word” 将被忽略。

在集和查询中的每个合适的词根据其在集与查询中的重要性衡量。这样,一个出现在多个文档中的词将有较低的权重(可能甚至有一个零权重),因为在这个特定的集中,它有较低的语义值。否则,如果词是较少的,它将得到一个较高的权重。然后,词的权重将被结合用于计算记录行的相似性。

这样一个技术工作可很好地工作与大的集(实际上,它会小心地与之谐调)。 对于非常小的表,词分类不足以充份地反应它们的语义值,有时这个模式可能产生奇怪的结果。

mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');
Empty
set (0.00 sec)

在上面的例子中,搜索词 MySQL 却没有得到任何结果,因为这个词在超过一半的记录行中出现。同样的,它被有效地处理为一个 stopword (即,一个零语义值的词)。这是最理想的行为 -- 一个自然语言的查询不应该从一个 1GB 的表中返回每个次行(second row)。

匹配表中一半记录行的词很少可能找到相关文档。实际上,它可能会发现许多不相关的文档。我们都知道,当我们在互联网上通过搜索引擎试图搜索某些东西时,这会经常发生。因为这个原因,在这个特殊的数据集中,这样的行被设置一个低的语义值。

到 4.0.1 时,MySQL 也可以使用 IN BOOLEAN MODE 修饰语来执行一个逻辑全文搜索。

mysql> SELECT * FROM articles WHERE MATCH (title,body)
-> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+------------------------------+-------------------------------------+
| id | title | body |
+----+------------------------------+-------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 2 | How To Use MySQL Efficiently | After you went through a ... |
| 3 | Optimising MySQL | In this tutorial we will show ... |
| 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... |
| 6 | MySQL Security | When configured properly, MySQL ... |
+----+------------------------------+-------------------------------------+

这个查询返回所有包含词 MySQL 的记录行(注意: 50% 的阈值没有使用),但是它没有包含词 YourSQL。注意,一个逻辑模式的搜索不会自动地以相似值的降序排序记录行。你可以从上面的结果出看得出来,最高的相似值(包含 MySQL 两次的那个) 最列在最后,而不是第一位。一个逻辑全文搜索即使在没有一个 FULLTEXT 索引的情况下也可以工作,然而它慢些。

逻辑全文搜索支持下面的操作符:“+” 一个领头的加号表示,该词必须出现在每个返回的记录行中,“-” 一个领头的减号表示,该词必须不出现在每个返回的记录行中。

缺省的 (当既没有加号也没有负号被指定时)词是随意的,但是包含它的记录行将被排列地更高一点。这个模仿没有 IN BOLEAN MODE 修饰词的 MATCH() ... AGAINST() 的行为。

< > 这两个操作符用于改变一个词的相似性值的基值。< 操作符减少基值,> 操作符则增加它。参看下面的示例。

( ) 圆括号用于对子表达式中的词分组。

~一个领头的否定号的作用象一个否定操作符,引起行相似性的词的基值为负的。它对标记一个噪声词很有用。一个包含这样的词的记录将被排列得低一点,但是不会被完全的排除,因为这样可以使用 - 操作符。

* 一个星号是截断操作符。不想其它的操作符,它应该被追加到一个词后,不加在前面。

" 短语,被包围在双引号"中,只匹配包含这个短语(字面上的,就好像被键入的)的记录行。

这里是一些示例:

apple banana

找至少包含上面词中的一个的记录行

1.+apple +juice ... 两个词均在被包含
2.+apple macintosh ... 包含词 “apple”,但是如果同时包含 “macintosh”,它的排列将更高一些
3.+apple -macintosh ... 包含 “apple” 但不包含 “macintosh”
4.+apple +(>pie <strudel) ... 包含 “apple” 和 “pie”,或者包含的是 “apple” 和 “strudel” (以任何次序),但是“apple pie” 排列得比 “apple strudel” 要高一点
5.apple* ... 包含 “apple”,“apples”,“applesauce” 和 “applet”
6."some words" ... 可以包含 “some words of wisdom”,但不是 “some noise words”

全文的限制

* MATCH() 函数的所有参数必须是从来自于同一张表的列,同时必须是同一个FULLTEXT 索引中的一部分,除非 MATCH() 是 IN BOOLEAN MODE 的。

* MATCH() 列列表必须确切地匹配表的某一 FULLTEXT 索引中定义的列列表,除非 MATCH() 是 IN BOOLEAN MODE 的。

* AGAINST() 的参数必须是一个常量字符串。

微调 MySQL 全文搜索

不幸地,全文搜索仍然只有很少的用户可调参数,虽然增加一些在 TODO 上排列很高。如果你有一个 MySQL 源码发行(查看章节 2.3 安装一个 MySQL 源码发行),你可以发挥对全文搜索的更多控制。

注意,全文搜索为最佳的搜索效果,被仔细地调整了。修改默认值的行为,在大多数情况下,只会使搜索结果更糟。不要修改 MySQL 的源代码,除非你知道你在做什么!

* 被索引的词的最小长度由 MySQL 变量 ft_min_word_len 指定。查看章节 4.5.6.4 SHOW VARIABLES。将它改为你所希望的值,并重建你的 FULLTEXT 索引。 (这个变量只从 MySQL 4.0 开始被支持)

* stopword 列表可以从 ft_stopword_file 变量指定的文件中读取。查看章节 4.5.6.4 SHOW VARIABLES。在修改了 stopword 列表后,重建你的 FULLTEXT 索引。(这个变量只从 MySQL 4.0.10 开始被支持)

* 50% 阈值选择由所选择的特殊的衡量模式确定。为了禁止它,修改 `myisam/ftdefs.h' 文件中下面的一行:
#define GWS_IN_USE GWS_PROB

改为:

#define GWS_IN_USE GWS_FREQ

然后重新编译 MySQL。在这种情况下,不需要重建索引。 注意:使用了这个,将严重地减少 MySQL 为 MATCH() 提供足够的相似性值的能力。如果你确实需要搜索这样的公共词,最好使用 IN BOOLEAN MODE 的搜索代替,它不遵守 50% 的阈值。

* 有时,搜索引擎维护员希望更改使用于逻辑全文搜索的操作符。这些由变量 ft_boolean_syntax 定义。然而,这个变量是只读的,它的值在 `myisam/ft_static.c' 中被设置。

对于这些更改,要求你重建你的 FULLTEXT 索引,对于一个 MyISAM 表,最容易的重建索引文件的方式如下面的语句:
mysql> REPAIR TABLE tbl_name QUICK;

全文搜索 TODO * 使所有对 FULLTEXT 索引的操作更快

* 邻近(Proximity)操作符

* 对 "always-index words" 的支持。他们可以是用户希望视为一个词处理的任意字符串,例如 "C++"、"AS/400"、"TCP/IP",等等

* 支持在 MERGE 表中的全文搜索

* 对多字节字符的支持

* 依照数据的语言建立 stopword 列表

* Stemming (当然,依赖于数据的语言)

* Generic user-suppliable UDF preparser.

* 使模式更加灵活 (通过为 CREATE/ALTER TABLE 中的 FULLTEXT 增加某些可调整参数)
posted @ 2008-07-02 19:21 阿里爸爸 阅读(3489) | 评论 (0)编辑 收藏

2008年6月5日 #

三种主流WEB架构的开发现状与未来展望

做WEB好几年了,各种语言和技术都稍有涉猎。今天心血来潮,突然想总结一下。其实不论什么技术,什么需求,通常WEB开发就是通过WEB前端管理一个或大或小或独立或分布式的关系型数据库,很多东西都是相通的。这里说的WEB架构,是指WEB应用开发中每种技术独有的资源组织形式(包括文件,数据库,HTTP请求处理等。注意并非OO的开发方式才有架构一说),也许说开发方式更容易让人理解一些。

以下想法主要以PHP实现为示例,但很多体会我想Java,.NET,Ruby开发者应该也很容易理解。最后是我对于刚面世就引起无数人关注的Delphi fo PHP的想法。

  WEB程序的架构基本上可以分成以下三类:

  (一) 基于“WEB页面/文件”,例如CGI和PHP/ASP程序。程序的文件分别存储在不同的目录里,与URL相对应。当HTTP请求提交至服务器时,URL直接指向某个文件,然后由该文件来处理请求,并返回响应结果。

  比如http://www.website.conm/news/readnews.php?id=1234

  可以想像,我们在站点根目录的news目录下放置一个readnews.php文件。

  这种开发方式最自然,最易理解,也是PHP最常用的方式。要注意产生的URL对搜索引擎不友好,不过你可以用服务器提供的URL重写方案来处理,例如Apache的mod_rewrite。

  (二) 基于“动作”(Action)。这是MVC架构的WEB程序所采用的最常见的方式。目前主流的WEB框架像Struts、Webwork(Java),Ruby on Rails(Ruby),Zend Framework(PHP)等都采用这种设计。URL映射到控制器(controller)和控制器中的动作(action),由action来处理请求并输出响应结果。这种设计和上面的基于文件的方式一样,都是请求/响应驱动的方案,离不开HTTP。

  比如 http://www.website.com/news/read/id/1234

  可以想像在实际代码中,我们会有一个控制器newsController,其中有一个readAction。不同框架可能默认实现方式稍有不同,有的是一个Controller一个文件,其中有多个Action,有的是每个Action一个文件。当然这些你都可以自己控制,题外话。

  这种方式的URL通常都很漂亮,对搜索引擎友好,因为很多框架都自带有URL重写功能。可以自由规定URL中controller、action及参数出现的位置。

  另外,还有更直接的基于URL的设计方案,那就是REST。通过人为规定URL的构成形式(比如Action限制成只有几种)来促进网站之间的互相访问,降低开发的复杂性,提高系统的可伸缩性。REST对于Web Services来说是一个创新。

  虽然本文讨论的是单个项目所采用的架构,而REST是为了解决网站之间的通讯问题,但REST的出现,会对单个项目的架构造成影响(很显然你在开发时就要构造规范的URL)。将来混用REST和MVC应该也是一种趋势。RoR提供很好的REST支持,Zend Framework也提供了Zend_Rest来支持REST,包括Server和Client。

(三) 基于“组件”(Component ,GUI设计也常称控件)、事件驱动的架构,最常见的是微软的.NET。基本思想是把程序分成很多组件,每个组件都可以触发事件,调用特定的事件处理器来处理(比如在一个HTML按钮上设置onClick事件链接到一个PHP函数)。这种设计远离HTTP,HTTP请求完全抽象,映射到一个事件。

  事实上这种设计原本最常应用于传统桌面GUI程序的开发,例如Delphi,Java Swing等。所有表现层的组件比如窗口,或者HTML表单都可以由IDE来提供,我们只需要在IDE里点击或拖动鼠标就能够自动添加一个组件,并且添加一个相应的事件处理器。

  这种开发方式有几个优点:

  复用性 -代码高度可重用。

  易于使用 -通常只需要配置控件的属性,编写相关的事件处理函数。

  我个人也挺喜欢这种方式,PEAR就提供了相当强大的HTML_QuickForm,用于在页面添加表单元素及其事件处理函数,还可以与Smarty等模板引擎相结合。这对于项目开发来说是一个补充性的功能,在项目中的某些部份使用QuickForm,有时可以大大加快开发。

  而完全基于组件和事件驱动的开发框架对于PHP来说也已经不新鲜,PRADO就是一个这样的框架,曾经得过Zend编程大赛的头奖。但目前来说很显然Prado所提倡的这种开发方式仍然没有被大部份PHP程序员所接受。为什么呢?

  我觉得主要有以下两个问题:

  (1)效率问题

  这里指的不是开发效率,而是代码的执行效率。众所周知,正常情况下,PHP的执行是相当高效的。但是目前这种基于控件的框架效率都成问题。Prado本身提供了一个缓存机制来缓解这个问题。如果不采用缓存,可以说很多站点根本不能使用Prado这样的框架,比如门户网站,大型论坛等。

  但ASP .NET不太一样,因为它是编译型的框架,最后生成的代码是编译生成的,不需要再次进行中间过程的诸多处理,所以在第一次执行之后速度会很快,执行效率还是很高的。 这是语言层次的功能,Prado无法通过代码层次的努力完全弥补。

  (2)没有强大的IDE支持

  设置控件的属性,添加其对应的事件处理器,看似简单,但控件多了,这也是个繁重的工作。.NET的强大就在于它把程序员从重复的工作中解放了出来,设置属性很方便,事件处理器也会自动添加。Prado目前没有这样的IDE支持。

  总之,这种基于控件的框架比较适合于用户交互较多的,需要对页面中的很多组件设置不同处理操作,但对于性能要求不高的应用。另外,带有组件支持的框架通常对AJAX的支持都较好,比如.NET和Ruby on Rails。

  综上,三种架构基本上可以代表目前的所有主流WEB开发方式,包括PHP,JavaEE,.NET,Ruby/RoR。

目前PHP开发的状况和未来的趋势:

  平时做PHP比较多,特别总结一下PHP开发的趋势。目前在PHP开发中,我们最常用的是基于“文件”的架构,其实也就是一种“面向过程”的开发方式。通常我们写PHP程序的目的就是“快点上线,让程序跑起来”。而且大多数PHP程序员还要和HTML、CSS做近身搏斗,所以如果程序太抽象,调整视觉效果就比较困难。所以对于小项目,这是一个最好的选择。

  但越来越多人认识到,面向对象和MVC框架更能促进代码的复用和分享,而且程序易于扩展,随着程序复杂性的增加这个趋势越明显。所以OO框架层出不穷。目前PHP框架当中最有前景的是CakePHP、Symphony和Zend Framework,各自拥有活跃的社区和庞大的用户群,都在快速成长当中。PHP的框架都避免走Java框架庞大臃肿的老路,致力于快速开发,而且主动模仿和吸收RoR这些优秀框架的新特性。随着PHP5的普及和这些框架的成熟,加上PHP原本开发社区的庞大人数,将来也许又会再产生出一些行业性的标准。

  这种选择适合于中大型项目,特别是需要较大的团队合作和需要长期维护和二次开发情况。个人认为这是将来PHP开发的趋势。

  而对于基于组件和事件驱动的开发方式大多数PHP程序员都不感兴趣。但是也有不少人在做这方面的努力,例如Codegear的Delphi for PHP,就吸引了很多人的关注。如果有强大的商业支持,也许将来在开发市场也会占一席之地。

  我会在下一篇文章介绍D4P的新特性并作评测。

  WEB开发的未来展望:

  随着更贴近HTTP的REST的流行,我觉得像.NET和Java中的抽象组件的方式会受到冲击。因为这些组件并不如它们所承诺的那么方便。未来MVC+REST+RIA的模式应该会比较流行。

  AJAX是一把双刃剑,尽管事件驱动的架构看起来非常适合于处理异步的请求(可以想像页面中存在几个组件,每个组件都可以触发异步请求,对应对服务器端的某个事件处理器,看起来是很理想的一个处理方式),但要为客户端自动生成良好的JavaScript代码是很不容易的,要满足各种浏览器的兼容性要求,还要能够自己进行扩展,以满足项目中千奇百怪的需求。 很多时候我更倾向于使用一些JS框架如Prototype来自己开发各种效果,而不是在服务器端生成。在服务器端生成JS的两个结果,一是对生成的代码不信任,二是人变傻,因为你并不知道真正发生了什么。

  关于WEB开发的个人疑惑:

  为了让开发更简单,我们不得不学习使用复杂的开发工具和框架,这到底是一个进步,还是退步?

  IDE让程序员变聪明还是变傻? 当我们在服务器代码里面就可以设计客户端界面,这是一个进步还是退步?

  举个例子说,微软的ASP.NET AJAX,让我们可以在服务器端设计各种异步的控件。那么程序员甚至可以不会Javascript,不懂AJAX就设计出各种客户端效果。要是哪一天项目需要设计稍复杂的效果,靠IDE和框架无法自动完成,你要怎么办? 到这个时候再来学JS,也许就迟了。更可怕的是,技术在更新和淘汰,可能十年之后,你会发现自己除了各种IDE之后,真正精通的技术很少,脱离了IDE你写一个小程序都要查半天API手册,因为你平时都是依赖“自动补齐”来写代码的! 这样的情景,我想没有人愿意发生。

  也许对于短期开发的项目来说,是一个进步,但对于程序员个人的成长来说,这并不是好事。对工具的依赖,导致了我们对于底层和核心技术的不求甚解,限制了个人的成长。

posted @ 2008-06-05 20:58 阿里爸爸 阅读(1977) | 评论 (5)编辑 收藏

2008年5月23日 #

如果你觉得SVN的cache程序使得你的机器反应很慢的话,那可以参考这个方案.不过可能要改变你以前使用习惯.
这个方案有两部分,第一部分是关闭SVN的cache监视;第二部分是显示文件差异时,使用SVN的“check for modifications”显示差异。
1.关闭SVN的cache监视。即关闭tsvncache.exe这个程序对目录的监视。
具体操作步骤如下:
a) 右击任意目录打开右键菜单,打开"tortoisesvn" => "settings"下的设置窗口
b) 找到"icon overlays"的设置项,将"status cache"设置成"none"
2.使用SVN的“check for modifications”显示差异
具体操作步骤如下:
a) 右击需要比较差异的目录,打开右键菜单,打开"tortoisesvn" => "check for modifications",打开比较差异窗口
注:这样显示文件差异是因为上面关闭监视后,再有修改程序文件,文件夹不再更新修改标识了,无法再通过查看文件平图标来知道是否有文件修改。
 
今天本人这样修改了,感觉机器强多了!不再有explorer疆死的情况了!爽!
 
以下是SVN设置框中具体的设置的介绍(摘自:http://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/tsvn-dug-settings.html)
 

 

图标叠加设置

图 5.43. 设置对话框,外观与样式页面

设置对话框,外观与样式页面

此页面允许你选择TSVN为哪些条目显示图标覆盖。选择网络磁盘可能会非常慢,所以默认情况下不为定位于网络共享中的工作副本显示图标覆盖。你甚至可以取消所有的图标覆盖,但那样做还剩下什么好玩儿的呢?

USB闪存看上去是个特殊情况,因为驱动类型是设备自主标识的。于是有些显示为固定驱动器,而有些显示为可移动磁盘。

By default, overlay icons will appear in all open/save dialogs as well as in Windows Explorer. If you want them to appear only in Windows Explorer, check the Show overlays only in explorer box.

Since it takes quite a while to fetch the status of a working copy, TortoiseSVN uses a cache to store the status in so the explorer doesn't get hogged too much when showing the overlays. You can choose which type of cache TortoiseSVN should use according to your system and working copy size here:

默认

把所有状态信息缓存在一个独立进程中(TSVNCache.exe)。该进程监视所有驱动器的更改,并在工作副本中的文件被修改时重新获取其状态。该进程以最低优先级运行,所以其他程序不会被它挤兑。这同样意味着状态信息并不是 实时 的,因为它需要几秒钟时间处理图标覆盖的变化。

优点: 图标覆盖递归地显示状态,就是说,如果一个处在工作副本深处的文件被修改了,所有途径的文件夹包括工作副本的根目录都会显示出修改的图标覆盖。也因为该进程可以向Windows外壳发送通知,资源管理器左面的树形图通常也会更改。

缺点: 即使你已经不在项目下工作了,该进程仍然持续运行。取决于你工作副本的数量和大小,它将占用10-50 MB的RAM内存空间。

Windows 外壳

缓存在外壳扩展dll中直接完成,但仅仅是为那些当前可见的文件夹。每次你浏览到其他文件夹,状态信息就会被重新获取。

优点: 仅仅需要很少的内存(大约1 MB),并且可以 实时 显示状态。

缺点: 因为仅有一个文件夹被缓存,图标覆盖不会递归地显示状态。在大一些的工作副本下,它在浏览器中显示一个文件夹将比默认缓存模式花费更多时间。而且 mime-type 列将无效。

在这种设置下,TSVN在浏览器里就完全不去获取状态了。因此,版本控制下的文件将不会获得任何图标覆盖。文件夹也仅仅有个“正常”状态的图标覆盖,其他的不会显示,也不会有其他额外的列可用。

优点: 绝对不会占用任何额外的内存,也完全不会减慢浏览器的浏览速度。

缺点: 文件、文件夹的状态信息不会显示在浏览器中。要获知你的工作副本是否被修改了,你需要使用“检查更新”对话框。

若你选择了默认选项,将同样决定如下选择: 在文件夹包含非版本控制的项目时,把文件夹图标覆盖标记为已修改。这个有用的设置可以提醒你已经创建了非版本控制的新文件。

排除路径 是被用来告诉TSVN 不用 在哪些路径下显示图标覆盖和状态列。如果你有些很大的工作副本,而这些工作副本仅仅包含你完全不想改变的库文件,从而你也不需要显示图标覆盖,这时该功能将会很有用。举个例子:

填写 f:\development\SVN\Subversion仅仅 在这个特殊文件夹上取消图标覆盖。你仍然可以在该路径下的所有文件、文件夹上看到图标覆盖。

填写 f:\development\SVN\Subversion* 将在路径以 f:\development\SVN\Subversion 开始的 所有 文件和文件夹上取消图标覆盖。这意味着你在该路径下的任何文件/文件夹上都将看不到图标覆盖了。

包含路径 也使用同样的语法。除了有些反例: 即使该路径处在某个取消图标覆盖显示的特定驱动类型下,或是处在上面的排除路径之下,也依然会显示图标覆盖。

TSVNCache.exe 同样使用这些路径来限制它的扫描。如果你想让它仅仅在某些特定文件夹里监视,就取消所有的驱动器类型,并仅仅包含你允许被扫描的文件夹。

posted @ 2008-05-23 18:08 阿里爸爸 阅读(17902) | 评论 (0)编辑 收藏

2008年4月3日 #

最近把版本管理系统换成git了,果然非常好用,难怪大家都在推荐。

首先不要有心理障碍,那些名词都是吓唬人的。所谓的“非线性开发”无非是指强大的branch和merge的能力,“分布式版本管理”就是说每人自己都有一套本地的repository,不存在一个集中的版本服务器。

给我带来的最直接的好处有:

  1. 傻瓜都会的初始化,git init, git commit -a, 就完了。对于随便写两行代码就要放到SCM里的人来说,再合适不过。也可以拿git做备份系统,或者同步两台机器的文档,都很方便。
  2. 绝大部分操作在本地完成,不用和集中SCM服务器交互,终于可以随时随地大胆地check in代码了。
  3. branch管理容易多了,无论是建立新的branch,还是在branch之间切换都一条命令完成,不需要建立多余的目录。
  4. branch之间merge时,不仅代码会merge在一起,check in历史也会保留,这点非常重要。

工具之所以好,除了方便好用,还在于它帮助并鼓励你做正确的事情。频繁check in是一件很好的事情,好处我不多说了,git就鼓励你频繁check in。branch也是一件好事情,我们大多很怕branch因为它太麻烦了,去掉这层心理包袱,branch可以让我们的开发工作很有条例。

还有一些实用的功能,比如bisect,用二分法来寻找regression,你以前手动做过这种事么?我做过。以后如果要做就不会怕了。还有stash,做hot fix非常方便。

如果正在用svn,劝服所有合作开发者使用git之前,可以先用git-svn,和svn整合得非常好。

分布式版本管理系统取代集中式版本管理系统,只是时间的问题了。

posted @ 2008-04-03 17:58 阿里爸爸 阅读(950) | 评论 (0)编辑 收藏

2007年12月7日 #

一、 二者的出身  
    作为世界最著名的两大CASE工具,Rational Rose和PowerDesigner的名声可谓如雷贯耳。Rose是当时全球最大的CASE工具提供商Rational的拳头产品,UML建模语言就是由Rational公司的三位巨头Booch、Rumbaugh和Jacobson发明的,后来Rational被IBM收购,所以Rose 可谓出身名门,嫁入豪族。而PowerDesigner也有一段好玩的历史,作者王晓昀是一位中国人,在法国SDP软件公司工作时,由于苦觅一个好用的CASE工具未果,干脆自由开搞,整了个AMC*Designor出来,居然一炮打响,在法国卖得个“巴黎纸贵”,后来SDP被Powersoft公司收购,同年Sybase这只大黄雀又吃下了Powersoft这只螳螂,所以PowerDesigner也是惊艳出场,星光四射。

    但两者所走的明星路线却很不相同,Rose出道是时,走的是UML面向对象建模,而后再向数据库建模发展,而PowerDesigner则反其道而行之,它先是一个纯粹的数据库建模工具,后来才向面向对象建模,业务逻辑建模及需求分析建模进军,最终变成“演视歌三栖”明星。

    由于第一印象的影响,所以Rose常常给人的印象还是只是面向对象分析设计的工具,而PowerDesigner给人的印象则还停留在数据库建模工具上。其实,现在的Rose和PowerDesigner都即可以进行数据库建模,也可以进行面向对象建模,只是存在支持上的偏重而已。

二、 二者区别概述
      Rose和PowerDesigner虽然在项目分析设计领域已经成为被高度聚光的明星,但是在具体使用哪款工具的问题上,不同的公司,不同的人,出于成本,习惯抑或个人喜好,往往有自己的判断。由于笔者在不同的公司中被分别要求使用Rose或PowerDesigner进行分析设计工作,所以对二者有着较为细致的体验。

     Rose走大而全,一站式的策略,它没有将数据库设计和面向对象设计清晰地分开,仅以不同的目录来区分。而PowerDesigner将两者划分到独立的模型文件中,分别对应不同的设计环境,并通过模型之间的转换工具建立各模型的关联。即使对于数据库设计模型,PowerDesigner也需要你选择一个具体的数据库产品及其版本,以便工作环境对具体数据库敏感。所以Rose显得大而化之,而PowerDesigner则比较精细和具体化。Rose的逆向工程,文档输出,代码生成等输入输出功能上表现得比较生硬单调,PowerDesigner在逆向工程,特别是文档输出和代码生成这些功能上提供了精细的控制,让用户拥有高度的自由度。
      Rose在操作体验上存在很多需要改进的地方,Rose偏向于让用户用鼠标进行操作,对键盘操作支持不好。而PowerDesigner在用户体验上得分很高,大部分操作都可以通过键盘完成,在充分熟悉其快捷键的前提下,PowerDesigner将给设计者一种行云流水的感觉,用户交互上更加人性化。此外,Rose往往占用更多的资源,容易异常退出,PowerDesigner则显得轻便稳定。所以,我个人对两者的体验就是“Rose笨拙,PD利索”。下面将具体列出Rose和PowerDesigner的一系列的区别,相信大家可以借由这些比较而见微知著,窥斑知豹,以资在选择工具时,提供参考。
三、 模型组织和层次结构上的区别
    1、模型组织Rose将数据库模型和对象模型放在一起,在进行数据表模型设计时,没有特性化的东西。而PowerDesigner将两者分开,其模型组织层级关系是:工作空间->模型类型->具体语言/数据库的模型->包->文件夹->Diagram->设计元素。在创建模型文件时,会让你选择模型类型,选择模型类型后,还可以选择模型类型下语言及版本相关的细分类。不同设计模型对应软件工程的不同阶段,如业务模型和需求模型属于项目需求阶段,而对象模型属于概要和详细设计阶段,数据库模型属于详细设计阶段。它们之间虽然有很强的内在联系,但差异性也很明显,硬将两者放到一起,就象把猴子和猩猩关进同一个笼子,为了兼顾和平衡两者之间的考量,其结果是两者都得不到很好的支持。
 

                                                                                    图 1新建模型窗口(PD) 
                                          

                                                                            图 2新建模型窗口(Rose)

     PowerDesinger可以通过模型转换工具进行数据库建模和面向对象模型的相互转换。但Rose不能将对象转换为表,也不能将表转换为对象。
   
    2、工作空间PowerDesigner有工作空间的概念,一个工作空间下可以同时打开多个设计模型文件;而Rose同时仅能打开一个设计文件,如果在设计时,需要参考其他的Rose设计模型,则需要反复关闭现有模型,打开参考模型,显得设计上比较欠考虑。这个问题上两者的差异恰似Eclipse和JBuilder的区别,Eclipse可以同时打开多个工程,而JBuilder只能同时打开一个工程。
      3、设计界面PowerDesigner的设计界面可以左右上下移动,而Rose只能向右,向下移动,此外。PowerDesigner可以将模型元素放大很多倍,而Rose只能放大到正常倍数,不过Rose的Overview工具可以使用户快速定位到设计区中特定的区域,有点类似于游戏界面中常用的小地图,挺不错;
     
                                                                    图 3 Overview工具(Rose)
   而在PowerDesigner中,你可以通过F8快捷键查看Diagram的总览图,不过只得通过放大操作定位到定位区域。
4  对模型和语言的支持
  ? 对设计模型的支持力度和广度
PowerDesigner对对象模型和数据库建模两者的支持力度已经大抵相等,此外,还支持概念模型、业务模型、需求模型、XML模型、信息流模型、自由模型的分析设计。不过对后面这几个模型的支持比较初级,而且在实际的应用中,这些模型用得也比较少,PowerDesigner的突出亮点还是在数据库建模和对象模型的设计上。

      对于数据库模型,PowerDesigner支持20余种数据库,对于同一数据库的不同版本还提供单独的支持,以便在设计数据库模型时,提供数据库和版本相关的设计。对于面向对象模型,PowerDesigner支持11种主流语言,为对Java 5.0提供单独的支持。
Rose基本上可以说是一个对象模型设计工具,对数据库模型的支持相对粗糙,内嵌的只支持Oracle 8数据库,对其他数据库设计的支持需要通过安装插件的方式获得,且对数据库物理存储参数等较细粒度的内容支持得比较粗糙。Rose的对象模型主要支持Java、VC和VB三种语言。

? 对Java语言的支持
Rose对Java语言的支持更好,不但为不同版本的JDK提供了支持(不过Rose 2003还不支持JDK 5.0),还为Java具体产品及设计模式(如EJB、Corba、Servlet,GOF设计模式等)提供了内嵌性的支持,这些支持直接反应在Rose的主菜单上。正因为如此,使Rose背上的沉重的历史负担,如EJB和Corba这种语言级的东西是易变且不断更新的,如何在这些具体产品的地位和影响已经降低时,对其作出割舍而又保证版本的兼容性,是摆在设计者面前的难题。
PowerDesigner仅提供语言级对象设计的支持,不涉及语言内部的具体产品。其次因为它的设计工作区是和具体的模型类型及语言细分类相关的,而非在主菜单中直接提供支持,所以PowerDesigner在升级时显得更加从容一些。
这也是为什么PowerDesigner能以每年一个版本的速度升级,而Rose在2003版本后,新版本还迟迟投入市场的内在原因,否则以IBM的财力,研发能力不至于对市场反应如果缓慢。

5  输入和输出功能的比较
? 反向工程
从将程序代码转换为设计模型的逆向工程功能上看,Rose更象一个IDE,它会对需要逆向工程操作的程序代码进行深度语义检查,如果存在诸如程序代码引用了类库之外的类,反向工程将失败,而且在报告失败之前,窗口会陷入长时间无响应状态。
PowerDesigner仅对需逆向工程的程序代码进行浅度语法检查,这种浅度语法检查不涉及包,类之间的关联,仅对诸如类名是否和类文件名匹配,是否少了“}” 等语法性的内容进行检查。即便存在错误,PowerDesigner也允许你忽略错误,继续进行逆向工程操作,这种宽松的限制带来了很大的便利。
                               
                                               图 4逆向工程失败选择三种选择(PD)
    忽略错误后,PowerDesigner会尽量修补错误,例如代码中少了对应的“}”,它将会补上,类名和文件名不一致,将忽略类文件名保持类名不变。

    Rose一直宣扬的理念是IDE和设计工程进行双向互通:在Rose中完成模型设计后导出为IDE所用的代码,IDE编码调整后又逆向工程到Rose。理念很美,深具吸引力,但是在实现中,往往很少有开发团队会这样做。一般CASE工具只是在分析设计阶段使用,甚至很大比例的设计师仅把它当成画图的工具。
真正进入编码开发阶段后,将加入大量设计时不涉及的类和方法,如果将这些非骨架性的东西Reverse到CASE工具中,反而会使原来清晰的设计变得雾里花,水中月。所以即使编码时,需要对原分析模型进行调整,一般也是手工去调整设计模型,而不是通过逆向工程去同步,毕竟分析设计是骨架性的,而编码是血肉性的,两者有属性上的区别。如果真的需要频繁进行的代码和UML转换,最好使用类似于Together一样的工具,它嵌入到IDE中,使代码和模型转换方便快捷。

? 文档导出功能
PowerDesigner对文档导出提供了精细的控制,你不但可以对文档所包含的内容项进行设置,还可以对内容项的格式进行设置。如导出的表结构是否包括名称、数据类型、备注等项目,这些项目在表栏中的宽度占比,颜色,字号等等,不一而足。

    PowerDesinger 12.0 还新增了一个多模型文档整合导出的Milti-Model Report模型,允许你以多个模型作为输入生成为统一文档,实现模型设计按阶段分开,文档又统一整合的目的。

    由于PowerDesigner文档导出的设置非常精细,所以要设置好一个文档导出模式实非不易。有鉴于此,PowerDesinger提供了三种常用的导出模板,用户也可以自己定义模板。通过模板可以迅速完成设计模型文档的导出工作。
而Rose没有导出模板的概念,更不能对导出项和格式进行设置,你只能按Rose的系统内置的方式进行模型文档的发布。

? 代码导出
     在导出设计模型的代码时,PowerDesigner提供了精细的控制,不但可以进行对象级别,还可以进行代码级别的控制(如是否要生成字段备注的代码,外键代码在表体代码内声明还是在表体外部声明等),而Rose没有提供代码导出的控制,也只能按其系统内部设置的方式导出代码。
         
                                                              图 5 数据库模型导出设置(PD)

    生成测试数据
    PowerDesigner可为数据表生成批量的测试数据,而且你还可以制定测试数据的生成规则。这个功能给初期项目的开发测试带来很大的便利。Rose中没有提供类似的功能。

posted @ 2007-12-07 19:03 阿里爸爸 阅读(1809) | 评论 (1)编辑 收藏

安装mysql请参考以下文章
http://blog.sina.com.cn/s/blog_4fe1599c01000b7t.html

下面直接记录下配置主从库的操作:
1.在主库建立要同步的数据库,建立主库的帐号和修改主库配置
首先连接上数据库
mysql -S /tmp/mysql-3108.sock
创建测试同步的数据库,"create database sinatest;"
然后建立负责同步的用户
grant all on *.* to ali@"%" Identified by "abc111";


然后修改/data2/ali/mysql3308/my.cnf主库的配置,增加
binlog-do-db=sinatest

2.修改从库配置
然后修改/data2/ali/mysql3309/my.cnf主库的配置,增加
master-host=127.0.0.1
master-user=ali
master-password=abc111
master-port=3308
server-id=2
master-connect-retry=60
replicate-do-db=sinatest
log-slave-updates

3.重启mysql
/usr/local/mysql/bin/mysqld_safe --defaults-file=/data2/ali/mysql3308/my.cnf  --user=root &
/usr/local/mysql/bin/mysqld_safe --defaults-file=/data2/ali/mysql3309/my.cnf  --user=root &

4.在主库创建数据表,检查从库是否同步正确
进入主库,创建数据表
mysql -S /tmp/mysql-3108.sock
CREATE TABLE if not exists ali_test_00 (
  `id` int(11) unsigned NOT NULL auto_increment,
  `my_id` varchar(16) binary NOT NULL default '',
  `my_title` varchar(96) binary NOT NULL default '',
  `status` int(11) unsigned NOT NULL default '1',
  PRIMARY KEY  (`id`),
  KEY `my_id` (`my_id`)
) TYPE=MyISAM;

insert into ali_test_00 values (null,32,"aliwwww",1);
insert into ali_test_00 values (null,32,"aliwwww",1);

然后检查从库是否有该表和表中是否有数据

SHOW SLAVE STATUS;  
SHOW MASTER STATUS; 
slave stop;
slave start;

CHANGE MASTER TO
MASTER_HOST='127.0.0.1',
MASTER_USER='ali',
MASTER_PASSWORD='abc111',
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=0;

posted @ 2007-12-07 18:59 阿里爸爸 阅读(916) | 评论 (0)编辑 收藏

2007年9月26日 #

PHP中使用XML-RPC构造Web Service简单入门


* 作者:heiyeluren
* 时间:2006-03-05
* 博客:http://blog.csdn.net/heiyeshuwu


[ Web Service介绍 ]

Web Service就是为了异构系统的通信而产生的,它基本的思想就是使用基于XML的HTTP的远程调用提供
一种标准的机制,而省去建立一种新协议的需求。目前进行Web Service通信有两种协议标准,一种是
XML-RPC,另外一种是SOAP。XML-RPC比较简单,出现时间比较早,SOAP比较复杂,主要是一些需要稳定
、健壮、安全并且复杂交互的时候使用。

PHP中集成了XML-RPC和SOAP两种协议的访问,都是集中在xmlrpc扩展当中。另外,在PHP的PEAR中,不管
是PHP 4还是PHP 5,都已经默认集成了XML-RPC扩展,而且该扩展跟xmlrpc扩展无关,能够独立实现XML
-RPC的协议交互,如果没有xmlrpc扩展,建议使用PEAR::XML-RPC扩展。

我们这里主要是以XML-RPC来简单描述Web Service的交互过程,部分内容来自PHP手册,更详细内容,建
议参考手册。


[ 安装xmlrpc扩展 ]

如果你的系统中没有安装xmlrpc的php扩展,那么请正确安装。

在Windows平台下,首先把PHP安装目录下的扩展php_xmlrpc.dll放到C:\Windows或者C:\Winnt目录下,
(PHP4的扩展在C:\php\extensions目录中,PHP5的扩展在C:\php\ext目录中),同时在
C:\Windows\php.ini或者C:\Winnt\php.ini中把extension=php_xmlrpc.dll前面的分号";"去掉,然后重
启Web服务器后查看phpinfo()有没有XML-RPC项目就能够确定是否已经正确安装xmlrpc扩展。

在Unix/Linux平台下,如果没有安装xmlrpc扩展,请在重新编译PHP,在configure的时候请加入 --
with-xmlrpc 选项,然后查看phpinfo()看是否正常安装xmlrpc。

(注意:以下操作都是建立在xmlrpc扩张正常安装前提下,请务必正确安装。)


[ XML-RPC工作原理 ]

XML-RPC大致就是整个过程就是使用XML来进行通信。首先构造一个RPC 服务器端用来出来从RPC客户端传
递过来的使用XML封装的请求,并且把处理结果通过XML的形式返回给RPC客户端,客户端就去分析XML获
取自己需要的数据。

XML-RPC的服务器端必须有现成的函数提供给客户端调用,并且客户端提交的请求中的函数和方法必须和
服务器端的一致,否则将无法获取所需要的结果。

下面我进行简单的代码来描述整个过程。


[ XML-RPC实践 ]

服务器端使用xmlrpc_server_create函数产生一个服务器端,然后把需要需要暴露的RPC调用接口进行注
册,接受RPC客户端POST过来的XML数据,然后进行处理,处理结果通过XML的形式显示给客户端。

代码如下: rpc_server.php

/**
* 函数:提供给RPC客户端调用的函数
* 参数:
* $method 客户端需要调用的函数
* $params 客户端需要调用的函数的参数数组
* 返回:返回指定调用结果
*/
function rpc_server_func($method, $params) {
$parameter = $params[0];
if ($parameter == "get")
{
$return = ''This data by get method'';
}
else
{
$return = ''Not specify method or params'';
}
return $return;
}

//产生一个XML-RPC的服务器端
$xmlrpc_server = xmlrpc_server_create();

//注册一个服务器端调用的方法rpc_server,实际指向的是rpc_server_func函数
xmlrpc_server_register_method($xmlrpc_server, "rpc_server", "rpc_server_func");

//接受客户端POST过来的XML数据
$request = $HTTP_RAW_POST_DATA;

//执行调用客户端的XML请求后获取执行结果
$xmlrpc_response = xmlrpc_server_call_method($xmlrpc_server, $request, null);

//把函数处理后的结果XML进行输出
header(''Content-Type: text/xml'');
echo $xmlrpc_response;

//销毁XML-RPC服务器端资源
xmlrpc_server_destroy($xmlrpc_server);
?>

服务器端构造好了,那么再构造我们的RPC客户端。客户端大致通过Socket访问XML-RPC服务器端的80端
口,然后把需要调用的RPC接口封装到XML里,通过POST请求提交给RPC服务器端,最后获取服务器端返回
结果。

代码如下:rpc_client.php
上海保洁:http://www.shwujiao.com.cn
/**
* 函数:提供给客户端进行连接XML-RPC服务器端的函数
* 参数:
* $host 需要连接的主机
* $port 连接主机的端口
* $rpc_server XML-RPC服务器端文件
* $request 封装的XML请求信息
* 返回:连接成功成功返回由服务器端返回的XML信息,失败返回false
*/
function rpc_client_call($host, $port, $rpc_server, $request) {

//打开指定的服务器端
$fp = fsockopen($host, $port);

//构造需要进行通信的XML-RPC服务器端的查询POST请求信息
$query = "POST $rpc_server HTTP/1.0\nUser_Agent: XML-RPC Client\nHost:
".$host."\nContent-Type: text/xml\nContent-Length: ".strlen($request)."\n\n".$request."\n";

//把构造好的HTTP协议发送给服务器,失败返回false
if (!fputs($fp, $query, strlen($query)))
{
$errstr = "Write error";
return false;
}

//获取从服务器端返回的所有信息,包括HTTP头和XML信息
$contents = '''';
while (!feof($fp))
{
$contents .= fgets($fp);
}

//关闭连接资源后返回获取的内容
fclose($fp);
return $contents;
}

//构造连接RPC服务器端的信息
$host = ''localhost'';
$port = 80;
$rpc_server = ''/~heiyeluren/rpc_server.php'';
上海保洁公司:http://www.shwujiao.com.cn
//把需要发送的XML请求进行编码成XML,需要调用的方法是rpc_server,参数是get
$request = xmlrpc_encode_request(''rpc_server'', ''get'');

//调用rpc_client_call函数把所有请求发送给XML-RPC服务器端后获取信息
$response = rpc_client_call($host, $port, $rpc_server, $request);

//分析从服务器端返回的XML,去掉HTTP头信息,并且把XML转为PHP能识别的字符串
$split = '''';
$xml = explode($split, $response);
$xml = $split . array_pop($xml);
$response = xmlrpc_decode($xml);

//输出从RPC服务器端获取的信息
print_r($response);

?>


大致我们上面的例子就是提交一个叫做rpc_server的方法过去,参数是get,然后获取服务器端的返回,
服务器端返回的XML数据是:

This data by get method


那么我们再通过xmlrpc_decode函数把这个XML编码为PHP的字符串,我们就能够随意处理了,整个Web
Service交互完成。


[ 结束语 ]

不管是XML-RPC也好,SOAP也罢,只要能够让我们稳定、安全的进行远程过程的调用,完成我们的项目,
那么就算整个Web Service就是成功的。另外,如果可以的话,也可以尝试使用PEAR中的XML-RPC来实现
上面类似的操作,说不定会更简单,更适合你使用。

简单的使用XML-RPC进行Web Service交互就完成了,部分代码参考PHP手册,想获取详细信息建议参考手
册,如果文章有不正确,请指正。
posted @ 2007-09-26 15:23 阿里爸爸 阅读(690) | 评论 (0)编辑 收藏

2007年9月15日 #

应用服务端口是3333,发现有一端数据处理有问题,想确认网络数据的传输次序,就用tcpdump了,
tcpdump -w data.dmp host server_ip and port 3333

截下来用omnipeek分析,发现大的数据包数据长度总是slice length。查了一下才发现tcpdump缺省只截取一定长度的数据包。
-s 选项可以解决这个问题. -s 0 是指定保存完整的包,如果指定一个非零的数值,那么将会保存这个数值的长度。

tcpdump -w data.dmp -s 0 host server_ip and port 3333
posted @ 2007-09-15 17:10 阿里爸爸 阅读(1752) | 评论 (1)编辑 收藏

所打开的文件
获取方法1:
# ls -l /proc/$PID/fd/

获取方法2:
# lsof -p $PID

内存分配表
获取方法:
# lcat /proc/$PID/maps

堆栈
获取方法:
# pstack $PID

所发出的系统调用
获取方法:
# strace -p $PID

所发出的库函数调用
获取方法:
# ltrace -p $PID

进程继承关系
获取方法:
ps -eo user,pid,ppid,%cpu,%mem,vsz,rss,tty,stat,start,time,wchan,command --forest

运行时dumpcore
获取方法:
# gcore $PID
posted @ 2007-09-15 17:09 阿里爸爸 阅读(1700) | 评论 (1)编辑 收藏

2007年8月28日 #

web2.0网站如何设计UE/UI
这些天总有些负责网站界面的设计人员找我咨询,怎么做用户访谈才感觉不像聊天,怎么样让用户参与到设计中来,得到更多的意见而不是简单的一句还可以或不错之类的评语,原型的改进花费时间总是太长怎么能缩短,设计的时候没什么把握,诸如此类的问题。。我想对此在msn上做的指导大量重复,需要在这里做一些入门级的解释了。。

Q1:首先,用户为中心的设计环节包括哪些活动?
答案:设计--〉原型--〉测试--〉再改进设计--〉原型--〉测试 --〉。。。看出来了吧,这是个迭代过程。。。你的设计没有把握,那么使用测试来验证,发现问题,再快速改进。。

Q2:这样的迭代,什么时候中止,递交给开发呢?
答案:没有完美的设计的,递交给开发前,保证你的设计没有一级易用性问题。否则上线的产品用户骂声一片。。但是还有一些小的bug好改的都改掉,不能改的下一版本吧。什么时候中止,那要看口袋里的钱,还剩的时间和人力等资源限制咯。看得出来吧,这里面肯定有很多的Tradeoff(妥协)的,做UE的和做开发的一定要搞好关系哦,这样,可以多改掉几个bug

Q3: 用户什么时候接触?他们最理想的介入时期是什么时候?
答案:作为UE/UI要记得,永远和用户保持紧密联系。不管项目进展到什么时刻,你都要思考,用户要干嘛,喜欢怎么干,这样的设计他们会不会觉得舒服流畅。要验证答案,那就赶紧去接触他们吧。

Q4:我知道在开发前期的设计工作,要做一些用户研究,问卷调查,用户访谈之类的,到底要研究些什么,出来些什么结果呢?
答案:在设计之前,你要明白的一件事情就是,为谁而设计。围绕这个谁,你需要回答:

1.他们的基本特征,比如年龄段分布,性别特征,家庭,行业,电脑经验,上网经验,收入阶层等等。。

2.你需要找到他们中间最典型的人群,需求最强烈的人群是怎样的一个形象。这个在UCD里面叫做角色提炼(Personas setting)。也许为10万个人设计,你什么都靠猜的,没可能满足10万个人的要求。但是你为这一个或者两个角色来设计吧,他们最典型,他们的需求满足好了,你就离成功不远了。

3.用户在使用你的网站到底舒服不,流畅不,主要是看他的操作习惯,行为方式和网站设计的是不是很匹配。你要研究什么,根本就是典型用户的操作习惯,行为方式,最后获得一个用户模型(User Model)。网站要创造出的用户体验,不是用户对你说,我要怎么样怎么样的,也不是设计者自己在那里想,嗯,这么设计比较容易,两步就能完成,一定很好。。两步就一定好么,你的用户很可能就习惯了走某固定的三步来完成,你的两步,很可能让他们满腹狐疑,忧心忡忡了。。

ok,现在你知道了,出来的结果是什么,用户群特点,典型用户的形象即角色(Persona),然后就是用户模型。。

Q5:知道研究什么呢,该怎么开展研究呢?
答案:用户研究的方法可以很灵活的,常常见到类似聊天一样的,一个问,一个来答,叫用户访谈。还有一些方法,比如问卷调查,焦点小组,数据分析等等。。根据不用的研究内容,还有时间,技术,成本来决定。。
至于怎么研究,一个前提就是,目的性明确。不管你做访谈也好,问卷也好,漫无目的,只会让你对这些形式的有效性产生怀疑。。比如问卷,设计多少个问题,设计哪些问题,你要规划好了。。问卷设计哪几个纬度,每个纬度需要几个问题可以得到结果,什么样的量表合适。。

Q6:项目已经进入开发了,做用户研究来不及了啊。
答案:嗬嗬,来得及来得及,只是要让你的第一批用户多多忍耐了。UCD是迭代过程嘛,已经开发了,你就研究着,准备对第一版本的产品进行测试评估和改进吧。。慢慢来,一个一个的改。

Q7:你所在的team(UI)是怎样跟一个团队(产品策划,程序员等)沟通合作的,又怎样更好的融入到产品的整个过程中的呢?
答:经历过很多种不同的Team,他们处在不同的位置上,常常承担的责任也不一样,因此作事情的方式也完全不一样了。UE在整个产品开发过程中的位置把握准确,相当的重要。关于位置怎么最合适,日后我再专门阐述。目前接触到较理想的工作方式,如何沟通合作,是和产品设计决策者一起工作,将你获得的研究或者评估结果,直接变成设计或建议,传递给产品设计决策者,判断问题的重要性,有哪几种可行的方案,如何改最合适,你们一起探讨。常常,在研究方案是否可行时,你需要跟程序员沟通,提出你的想法,询问是否能实现,实现难度,大致的时间。这样能够保证你方案的可快速执行。这存在很多的沟通技巧。最好的情况就是你, UE人员,要把以用户为中心的思想灌输给他,让他进入你设定的情景,站在你的立场去考虑问题,这样程序员会增加工作的责任感,他甚至可能发挥主观能动性,帮你想到更好的实现方法。。。这样的一种氛围中,整个的团队就像一根绳子往一个方向使劲,都全力想让产品做好,想想,那样的工作多让人充满激情吧。

这只是其中一部分,在你和产品决策者沟通时,甚至还有市场部门的同事参与,一方面,你要代表用户的利益,另一方面,你要试图了解公司希望创造的商业价值,从中找到一个平衡点。这种设计才最容易获得上层的支持,以最快的速度推行下去。可以看看偶翻译的用户体验设计师的职责那片文章。

Q8:界面(原型+设计),交互(包括js),测试等都由一个人做吗?如果不是的话,那么对用户体验的研究又怎样能证明自己的作用?
答:这些工作我都做过,一个人做这种情况其实非常的常见。但是一个人,并不理想,最好,还是培养一个团队。而且有些工作,一个人做不了,必须有协助。这主要看公司的不同状况了。如果是一个人,评估用户体验研究的效果,就可以对你的成绩进行评判了。
如何是一个Team,是好几个人协作完成,如何证明每一部份的工作成效?iceshow是问这个吧。
老实说,我对这个问题没有把握。因为UE的日常工作就是设计-原型-测试评估,是完整的流程,对工作的评估,只能考核整个流程下来的结果。单独一部份工作做得如何,我还没有研究过。。

白鸦在blog里面特意的提到我这个系列,标题的web2.0,应该改掉。我倒不想,出于UE知识的普及,这样的标题适合目标用户群-- web2.0用户体验实践者,可以抓住他们的眼球。这一群能人帮助只是迅速传播普及。另外在用户体验设计方面,之前3篇完全适用web2.0..

今天说说web2.0和1.0在用户体验方面的不同之处,但是,这只是我浅薄的理解,希望可以得到各位资深的实践者们的提点。其实以我的积累,应该是远远不够的。

用户体验包括四个因素:品牌,功能,usability和内容。现在大家常常误认为:用户体验=易用性(或者可用性/usability)。其实不然。

web2.0最不缺的是功能,每一个创业者都是认为自己发现了用户的某一种需求,而市场上没有任何产品可以去满足,因此觉得自己可以开发出具备某些功能的2.0产品。。这方面,不多说什么,只是说一点,细分用户群,必定会成为竞争趋势。。仔细研究了用户群,深入挖掘他们的特点和需求,在最开始就做到高的粘着力,是否更好了?

在品牌上,很多人对这一点的忽略,导致了用户体验的整个盲目。现在我问你,sina,sohu和网易,有什么差别?普通用户可不清楚,都是门户网站。。好像网易开发游戏,sohu还开发了搜索,sina,好像经常做赞助活动。。这就是品牌么?现在问你Nokia和Moto有什么差别?你能回答吧。。品牌和用户体验的关系,是互相影响的。。你用Nokia,发现它简单朴实,好用,还抗摔。就是样子有点。。那么nokia的品牌形象排除了价格因素后就是这样,简单朴实好用机身抗摔,样子一般了点。。现在如果有人推荐你,某个品牌,它是如何的有趣个性时尚,然后你一使用,发现:切,哪点特别的,跟 Nokia差不多,还不如买Nokia。。失败了吧,因为品牌没有独特的个性,带来的用户体验期望值和现实落差,将会让你的目标用户转头而去。。网易相册和其他的相册,有什么差别。。和flikr反正是大大的不同。。

在内容上面。虽然说,web2.0是用户参与,很多网站的内容都是用户来建设。。但是在用户参与之前,你要想,用户为什么要参与。。只因为我没有日记本,你给我一个日记本,我就一定要用你给的这个来写么?用户是否参与,参与程度多少,这些都取决于你现在的内容。。你现在是空的。。鬼知道你这个网站是不是快黄了,我干吗要在这写啊。。你现在很多,但是都是转载的,没几个用户在写。。骗我么?我写了根本就没有几个人看。。好,现在你的内容很多,用户也开始很多了。。但是,天啦,这些内容也未免太广告性了吧。。。或者,用户想,我写了你会不会到处转载啊。。你们这的用户素质怎么样啊。。。而且,形式上,你的品牌,说一点关联性,品牌你标语说时尚个性,网站样子看上去土拉吧唧的,马上用户的信任度就降低了。。

Usability,网站当然要好用了,很迅速的完成内容提交,或者找到目标内容,这是当然的。。但是不是随便一个你觉得交互方式很流畅的网站,都可以完全拷贝复制。幸亏世界如此丰富,不然我们做交互设计的,就跟做数学公式一样了,多没意思,一个套路。。不同的用户,习惯不同的交互方式,他们喜欢什么样子的,这便是用户研究里面要做的一部分工作。。这样的研究结果,帮助你的交互设计具备了自己的个性。。usability测试的结果,是要知道你的目标用户群的看法,发现的问题,而不是科学研究,三步如何变成两步。
 

posted @ 2007-08-28 02:49 阿里爸爸 阅读(660) | 评论 (0)编辑 收藏

2007年7月21日 #

今天一边装着openldap,一边听着电视,正好是快乐男生的颠峰对决!嗯!这些帅小伙唱得都不错!只有在听到王栎鑫   出场时,发现了一个声音!对,那是快乐男声的预告中的那个高音,看过几次那个预告,一直想知道那个高音是什么歌,那个原歌是怎么样的!真是...虽然王栎鑫没唱到预告中的那段高音,但一听就知道就是那首歌。赶紧google一下“王栎鑫”,然后找到一个资料有一个"opera 2",百度了一下,试听!YES!就是它!
接着百度到vitas的其他歌!好好听一下!爽!
在他的音乐里有那种自由的、放纵的快感!爽!
http://www.9sky.com/track/375104.htm
posted @ 2007-07-21 02:51 阿里爸爸 阅读(571) | 评论 (0)编辑 收藏

2007年7月20日 #

 本文出自: http://fanqiang.chinaunix.net/a6/b6/20010626/170400681.html (2001-06-26 17:04:00)

做为眼下最流行的操作系统,Linux已经越来越受到世人的关注。虽然目前Linux的软件还不是很丰富,
替代WINDOWS作为普通PC机操作系统还为时过早,但是在服务器领域,Linux的稳定性,可操作性决不
输于任何操作系统,并且也有优秀的软件支持。Squid就是其中之一。Linux加Squid的组合做为代理
服务器,性能远远超过WINNT加MSPROXY2.0(个人观点),为几百人的小型局域网代理绰绰有余。下
面,我就详细的介绍Squid的安装及使用技巧,希望大家能够喜欢上它。 

1.Squid简介

  Squid是一个缓存internet数据的一个软件,它接收用户的下载申请,并自动处理所下载的数据。
也就是说,当一个用户象要下载一个主页时,它向Squid发出一个申请,要Squid替它下载,然后Squid
连接所申请网站并请求该主页,接着把该主页传给用户同时保留一个备份,当别的用户申请同样的页面
时,Squid把保存的备份立即传给用户,使用户觉得速度相当快。目前,Squid 可以代理HTTP, FTP, 
GOPHER, SSL 和 WAIS 协议,暂不能代理POP, NNTP等协议。不过,已经有人开始修改Squid,相信不
久的将来,Squid能够代理这些协议。

  Squid能够缓存任何数据吗?不是的。象缓存信用卡帐号、可以远方执行的scripts、经常变换的
主页等是不合适的也是不安全的。Squid可以自动的进行处理,你也可以根据自己的需要设置Squid,
使之过滤掉你不想要的东西。

  Squid可以工作在很多的操作系统中,如AIX, Digital Unix, FreeBSD, HP-UX, Irix, Linux, 
NetBSD, Nextstep, SCO, Solaris,OS/2等,也有不少人在其他操作系统中重新编译过Squid。

  Squid对硬件的要求是内存一定要大,不应小于128M,硬盘转速越快越好,最好使用服务器专用SCSI
硬盘,处理器要求不高,400MH以上既可。

2. Squid的编译和运行

  其实现在的Linux发行套件中基本都有已经编译好的Squid,你所作的就是安装它既可。如果你手头
没有现成的编译好的Squid或想使用最新的版本,去ftp:squid.nlanr.net下载一份,自己编译。

  Squid的编译是非常简单的,因为它基本上是自己配置自己。最容易出现的问题是你的系统上没有
合适的编译器,这可以通过安装相应的编译器解决。如果出现其他问题,你可以问一下有经验的用户或
到相应的邮件列表寻找帮助。

  编译Squid之前,最好建一个专门运行Squid的用户和组。我就在自己的服务器上建了一个名为
squid的用户和组,用户目录设为/usr/local/squid。然后su为用户squid并从squid.nlanr.net下载
Squid的源文件到目录 /usr/local/squid/src中,用如下命令进行解压:

  %tar xzf squid-2.0.RELEASE-src.tar.gz

  %cd /usr/local/squid/src/ squid-*.*.RELEASE /

  %./configure

  %make

  %make install

  第一个命令在目录/usr/local/squid/src中产生一个新的子目录/squid-*.*.RELEASE/。命令
./configure会自动查询你的系统配置情况以及你系统中使用的头文件。不加参数的./configure会
把Squid安装在目录/usr/local/squid中,如果你想使用其他目录,用如下命令
./configure --prefix=/some/other/directory,这会把Squid安装在目录/some/other/directory中。
make命令编译Squid,make install命令安装Squid。

  不出意外的话,目录/usr/local/squid中会出现如下目录:

  /bin

  /cache

  /etc

  /logs/

  /src (自己创建的)

  目录/bin中含有Squid可执行程序,包括Squid本身,ftpget等。

  目录/cache包含Squid缓存的数据,其中包含象/00/ /01/ /02/ 以及/03/这样的目录,这些目录
中还有子目录,因为目录多了比在一个目录成千上万的文件中寻找一个文件更容易,速度更快。

  目录/etc中包含Squid的唯一的配置文件squid.conf。

  目录/logs中包含Squid的日志。


3. squid.conf文件的配置

  在安装Squid后,在目录/usr/local/squid /etc中会自动产生一个样本squid.conf文件,文件中
对每一个选项都有详细的说明,用户可以通过修改该文件以满足不同的需要。

  总的来说,有如下几个重要选项:

  ·http_port:设定Squid监听的端口,你最好设一个比较好记的端口号,以便在进行客户机配置
时容易记住。我的机器上端口号设的是8080。缺省为3128。

  ·cache_mem:设定Squid占用的物理内存,根据我的经验,cache_mem的大小不应超过你的服务
器物理内存的三分之一,否则将会影响机器的总体性能。

  ·maximum_object_size:设定Squid可以接收的最大对象的大小。Squid缺省值为4M,我自己入
认为太大,你可以根据自己的需要进行设定。

  ·cache_dir:设定缓存的位置、大小。一般看起来形式如下
“cache_dir /usr/local/squid/cache 100 16 256”。 /usr/local/squid/cache代表缓存的位置;
100代表缓存最大为100M;16和256代表一级和二级目录数。

  ·cache_effective_user:设定使用缓存的有效用户。缺省为用户nobody,如果你的系统中没
有用户nobody,最好建一个或以非root用户运行Squid。

  下面我给出一个最简单的squid.conf文件:

  #squid.conf - a very basic config file for squid

  #Turn logging to it's lowest level

  debug_options ALL,1

  #defines a group (or Access Control List) that includes all IP addresses

  acl all src 0.0.0.0/0.0.0.0

  #define RAM used

  cache_mem 32M

  #defines the cache size

  cache_dir /usr/local/squid/cache 100 16 256

  #allow all sites to use connect to us via HTTP

  http_access allow all

  #allow all sites to use us as a sibling

  icp_access allow all

  #test the following sites to check that we are connected

  dns_testnames internic.net usc.edu cs.colorado.edu mit.edu yale.edu

  #run as the squid user

  cache_effective_user squid squid

  这个配置文件允许所有人使用Squid,创建了100M缓存,使用32M内存,在缺省位置
"/usr/local/squid/cache"缓存数据,所有缓存数据以组squid和用户squid身份保存,端口为3128。
虽然这个配置很不安全,但是它已经能使用了。


4. 运行Squid

  首先以root身份登陆。运行如下命令:

  %/usr/local/squid/bin/squid –z

  该命令会产生Squid所有的缓存目录。

  如果你想前台执行Squid,接着执行命令:

  %/usr/local/squid/bin/squid -NCd1

  该命令正式启动Squid。如果一切正常,你会看到一行输出

  Ready to serve requests.

  如果想后台运行Squid,把它做为一个精灵进程,执行命令:

  %/usr/local/squid/bin/squid

  观察Squid是否运行使用命令:

  % squid -k check

  输出会告诉你Squid的当前状态。


  好了,文章先写到这里,其实这里介绍的都是最基本的东西,Squid有好多高级的功能,
如做WEB服务器的高速缓存,做二级代理服务器,做为防火墙,以及怎样设定过滤规则等,这里
就不详述了,如果有机会再奉献给大家。
 

posted @ 2007-07-20 11:21 阿里爸爸 阅读(1000) | 评论 (2)编辑 收藏

2007年6月26日 #

“下午两点开部门例会。”

  “下班前请大家把这周的工作总结交给我。”

  “明天是报销的日子,大家别忘了把票据带来。”

  “中午大家去哪lunch?”

 
  这不是公司公告栏的留言,不是部门经理给每个员工打的电话,更不是哪位调皮员工从工位上站起来大喊的一嗓子,这些都是时下在公司白领当中最为流行的MSN部门群里最常用的“关键词”。随着“群”这个既熟悉又陌生的东东在MSN用户中的迅速普及,不夸张地说,白领们的工作和生活方式正在悄然发生着改变,甚至于一些公司的商业运作模式也在悄然改变。

  MSN官方群问世之初,人们还以为它不过是MSN的一个插件、或是一个增强版的功能。很少有人注意它,使用者自然更是寥寥无几。但任何新鲜事物都会有好奇者,MSN群也不例外。随着几个“吃螃蟹”之人开始使用MSN群后,MSN群开始已几何级数的速度在MSN用户中传播,截至 2007 年6月MSN群的用户数突破数百万,仅仅用了1年左右的时间,而这一切纯粹是依靠使用者的口碑。微软正是看到MSN群超乎想象的增长速度而带来的具大商业价值,因此计划对MSN群进行大力推广,同时又与MSN群的开发者赢思软件展开更加紧密的合作。

  MSN群是为有群组沟通需求的朋友提供一个固定的网络聊天平台。它的定位来自于MSN mensseger:是一个以商务为导向、多元应用相配合的服务品牌。它最大的宝藏在于牢牢地占据了中国即时通讯市场的高端,把持着数量可观的优良用户,这些用户的一个特性是受教育水平高,他们使用MSN群不以娱乐休闲为主要目的,而更多的是用于工作及与熟悉朋友间的沟通。也正因为如此,MSN群作为工作中的实用工具得以在白领中迅速普及。

  当然,定位准确不仅是MSN群成功的必要条件,也是吸引众多群友使用的主要原因。从MSN群用户来说,每个人可以根据自己的工作内容、个人兴趣来建群和添加到相关群组里。比如你可以按所属的行业来创建或加入同行业的MSN群,同行的专业人士汇集之地,隔行如隔山,在这里就不用担心"对牛弹琴"了,只要将您的真知灼见发挥的淋漓尽致,一定能听到知音的声音;对于相同职业者来说,可以创建职业MSN群,在群中可以更好的沟通、合作、共勉;如果大家都有相同的爱好,那么可以创建兴趣群,这样有着共同兴趣爱好的朋友自然会有着更多的话题可聊,正所谓“物以类聚,人以群分”。

  小安是某广告公司的职员,最近终于按耐不住,投身到牛气冲天的股市。她每天早上9点上班,先浏览各大财经网站的新闻,等到9点半开市,她就紧紧盯着自己的股票动向。公司里面的大部分人都跟她一样,时间长了,老板难免有意见。于是公司屏蔽掉了员工机器上的股票软件。不过还好,MSN还是可以用的。于是大家就建了一个MSN群,只要有人能看到最新的股市动向,马上就可以通过群聊发布信息,大家也可以随时人工查询,真是即安全又可靠。

  上海的Amy是个单身贵族,为了能够认识更多的朋友,她就建了一个“单身派对“交友群,里面全是单身贵族,大家一起聊生活,聊感情,还相互推荐好听的音乐、好看的书,有时还会有人提议一起聚餐,感觉就像有了一个新朋友圈。

  在数据公司任业务总监的卢克先生前段时间一直在为招人而苦恼,他说,招人很好招,但是要想招到合适的人,就太困难了。后来他加入了一个叫“程序员”的MSN群,他不仅能够与业内专业人士建立沟通与了解,又能讨论技术难题。很快,通过在群里面与大家的沟通,他找到了非常满意的工作伙伴。

  人们在都市里生活久了,每个人都会有自己的生活轨迹,当你的生活圈归于平淡时,群的出现或许给了很多人一种调剂,车友们在他们的群里侃爱车,体育迷们在群里论赛事,户外族在群里安排下一次探险……有时候互不相识的人见面也会点头微笑,打个招呼,感觉就像是很亲近的邻居或者很久没有见面的老友,人与人之间又多了一个纯粹交流的平台。(

posted @ 2007-06-26 18:22 阿里爸爸 阅读(443) | 评论 (0)编辑 收藏

2007年6月22日 #

最近理想国际的电梯都在使劲放着诛仙的广告,看得我心痒痒的!前天晚上回家去下载,500M的大文件下载了半天没下完,睡了!昨天在公司全部下完,晚上回家装上后去玩了!
很喜欢小说诛仙,05年看了好几个星期,比较有意思!不知道游戏也能给我们带来惊喜.
听着小齐的歌,开始了!画风还不错!玩了半小时后发现这游戏也就这样!里面除了两个MVP是小说里的,其它就跟那些网游一样!杀怪捡垃圾,换钱买装备!
最后越玩越无聊!

现在的网游都这样,没有新意!就那么两下!诛仙完全没有小说里那个味道,只是一个MVP是诛仙人物的传奇!
搞到两点洗洗就睡了!
posted @ 2007-06-22 18:02 阿里爸爸 阅读(562) | 评论 (0)编辑 收藏

2007年6月21日 #

前两天装了一个什么软件,然后就笔记本不幸中标了!
笔记本被装上了雅虎助手,捆绑安装的,没有任何提示,只是在装完就多了个软件.
当时没在意,后来发现IE访问的时候有点小问题,登陆新浪博客登陆不上,从另一个入口登陆后,发文章又发不了!没办法,只能去用firefox了!
后来想卸载雅虎助手,但是没法卸载,网上搜索了下,比较麻烦,还卸载不干净!这只能说两个字"流氓"!
雅虎助手前身应该是那个臭名远播的3721助手.继承了原来的无耻传统,继续来强奸中国网民的IE.这种行为什么时候才能停止.
中国真应该成立个反流氓软件的联盟,对于那些垃圾软件\垃圾网站全部像Google一样,先提示有流氓软件.

最后谴责下这些制造\传播流氓软件的公司及个人!
posted @ 2007-06-21 10:09 阿里爸爸 阅读(594) | 评论 (0)编辑 收藏

2007年6月12日 #

今天,著名的搜索引擎营销公司SEOmoz发布了2007年度Web2.0评选结果

  SEOmoz 组织25名在Web2.0领域的专家组成一个专业团队,对数百个Web2.0网站进行评估,从41个种类中分别挑选出最受欢迎的前三名。不过此评选只针对英文的Web2.0网站进行,其他语言的Web2.0网站并未出现其中。

  下面是获奖的网站名单:

类别 第一名 第二名 第三名
博客搜索类 Technorati Bloglines Findory
书签类 Ma.gnolia Furl Clipmarks
图书类 Lulu Biblio Library Thing
商业类 Squidoo Instant Bull Shopify
城市搜索和评论类 Yelp Judy's Book Yahoo! Local
分类和目录类 Craigslist Oodle vFlyer
协作写作和文字处理类 Google Docs and Spreadsheets Writeboard ThinkFree
通信类 Meebo Campfire MailEmotion
内容聚合和管理类 Wufoo ProjectStat.us EditGrid
数字存储和远程访问类 Omnidrive Esnips TotoExpress
活动类 Upcoming Eventful Confabb
Feed管理类 Feedburner Attensa BlogBridge
笑话类 Cocktail Builder One Sentence Fuzzmail
游戏类 Arcaplay Games2Web Guess-The-Google
保健类 PEERtrainer Medstory Healia
维基服务类 Wetpaint PBwiki Stikipad
排名和投票类 43 Things Statsaholic Listdump
地图类 Google Maps Wayfaring Frappr
营销类 Intellicontact Conduit PlugIM
整合服务类 Ning Boxxet Coverpop
移动技术类 Twitter Plusmo JuiceCaster
音乐类 Pandora Last.fm Discrevolt
网络桌面类 Goowy Desktoptwo EyeOS
办公应用类 Google Apps Zoho Backpack
慈善事业类 Care2 Donor Choose Be Green Now
图片和数字照片类 Flickr Picasa Picnik
播客服务类 Odeo PodShow PodOmatic
专业网络类 LinkedIn Spoke Xing
提问和建议类 Yahoo! Answers Minti Say-So
房地产类 Zillow HousingMaps iiProperty
零售类 Threadless Etsy WipBox
搜索类 Rollyo Swicki Pipl
社交网站类 Facebook Mingle2 Pipl
社交新闻类 Digg Reddit Newsvine
社交标签类 Del.icio.us StumbleUpon BlinkList
首页类 Netvibes PageFlakes Personalized Google
旅游类 Farecast Kayak RealTravel
视频类 YouTube Dailymotion Metacafe
视觉艺术类 ColorBlender Swivel The Broth
网页开发和设计类 CakePHP Prototype Javascript Framework Yahoo! UI
维基类 YourMinis SpringWidgets Flock

原文: http://www.web2week.com/archives/2007/05/seomozweb20.html
posted @ 2007-06-12 01:42 阿里爸爸 阅读(658) | 评论 (0)编辑 收藏

PC World近日发布了2007年度最佳产品前100名,评选的范围包括电子产品、网站和服务。值得一提的是,其中包含了很多Web2.0网站。

The Top 100 Products, in Ranked Order

  1. Google Apps Premier Edition Review | Vendor Site
  2. Intel Core 2 Duo Review | Check Prices
  3. Nintendo Wii Review | Check Prices
  4. Verizon FiOS Vendor Site
  5. RIM Blackberry 8800 Review | Check Prices
  6. Parallels Desktop Review | Check Prices
  7. Pioneer Elite 1080p PRO-FHD1 Check Prices
  8. Infrant Technologies ReadyNAS NV Check Prices
  9. Apple Mac OS X 10.4 "Tiger" Review | Check Prices
  10. Adobe Premiere Elements 3 Review | Check Prices
  11. Apple TV Review | Check Prices
  12. Samsung SyncMaster 244T Review | Check Prices
  13. BillP Studios WinPatrol Download
  14. HP dv9000t Review | Check Prices
  15. McAfee SiteAdvisor Download
  16. Canonical Ubuntu 7.04 Review
  17. Pandora.com Review
  18. Microsoft Xbox 360 Elite Review | Check Prices
  19. Paint.net Download
  20. Hitachi Deskstar 7K1000 Review | Check Prices
  21. SightSpeed 6 Download
  22. Kayak Web Site
  23. Nikon D40X Check Prices
  24. New York Times Times Reader Vendor Site
  25. Samsung BlackJack Review | Check Prices
  26. Apple iPod (80GB) Test Report | Check Prices
  27. Yahoo Mail Beta Vendor Site
  28. TomTom One Review | Check Prices
  29. Dell UltraSharp 2407WFP Review | Check Prices
  30. Zoho Review
  31. Google Gmail Vendor Site
  32. Sling Media Slingbox Pro Check Prices
  33. Red Octane Guitar Hero 2 Video | Check Prices
  34. Google YouTube Vendor Site
  35. Mozilla Firefox 2 Download
  36. Google Picasa Download
  37. Nikon D80 Review | Check Prices
  38. Skype 3 Download
  39. Aliph Jawbone Review | Check Prices
  40. Shure E500PTH Review | Check Prices
  41. CyberPower Gamer Infinity Ultimate Review | Check Prices
  42. Asus w5fe-2P025E Review | Check Prices
  43. AVS Forum Web Site
  44. Yahoo Flickr Review
  45. Apple iPod Nano (8GB) Check Prices
  46. Nikon Coolpix S50c Check Prices
  47. Dell UltraSharp 2007WFP Review | Check Prices
  48. OCZ Trifecta Secure Digital Memory Card Check Prices
  49. Archos 704 Wi-Fi Review | Check Prices
  50. Lenovo ThinkPad X60 Tablet Review | Check Prices
  51. Canon EOS 30D Review | Check Prices
  52. LaLa.com Review
  53. Google Maps for Mobile Vendor Site
  54. Canon Pixma iP4300 Review | Check Prices
  55. Kaspersky Anti-Virus Review | Check Prices
  56. Microsoft Office 2007 Review | Check Prices
  57. Asus Crosshair Test Report | Check Prices
  58. Digg.com Web Site
  59. Dell XPS M1210 Review | Check Prices
  60. Creative Zen V Plus (8GB) Review | Check Prices
  61. Apple iTunes Download
  62. Gigabyte GA-965P-DQ6 Test Report | Check Prices
  63. Iomega NAS 1TB Check Prices
  64. Fujifilm FinePix F40fd Check Prices
  65. Canon MP600 Review | Check Prices
  66. 37Signals Backpack Review
  67. LG Electronics BH100 Review | Check Prices
  68. Craigslist.org Web Site
  69. BBB.org Web Site
  70. Fujitsu ScanSnap s500 Review | Check Prices
  71. NEC MultiSync 90GX2 Review | Check Prices
  72. Adobe CS3 Review | Check Prices
  73. Dell XPS 410 Review | Check Prices
  74. Meebo Review
  75. SysInternals/Microsoft Process Explorer Download
  76. Wacom Graphire Bluetooth 6x8 Pen Tablet Check Prices
  77. VMWare Player Vendor Site
  78. Emusic Web Site
  79. TiVo Series3 HD Digital Media Recorder Review | Check Prices
  80. Netvibes Web Site
  81. TripAdvisor Web Site
  82. Apple MacBook Pro Review | Check Prices
  83. Avira AntiVir Personal Edition Classic Review | Check Prices
  84. Ning.com Review
  85. Check Point Software ZoneAlarm Internet Security Suite Review | Download Store
  86. SanDisk Sansa Connect Review | Check Prices
  87. VirusTotal.com Review
  88. Flurry Review
  89. Oki Printing Solutions C3400n Review | Check Prices
  90. nVidia GeForce 8800 GTX Check Prices
  91. Microsoft Windows Media Player 11 Download
  92. Netflix Watch Now Vendor Site
  93. Audacity Download
  94. Congoo Review
  95. Wladimir Palant Adblock Plus Download
  96. Buffalo Nfiniti Dual Band Gigabit Router & Access Point Check Prices
  97. Panasonic HDC-SD1 Review | Check Prices
  98. Logitech Harmony 880 Review | Check Prices
  99. Sling Media SlingPlayer Mobile Vendor Site
  100. Shure SE210 Review | Check Prices
posted @ 2007-06-12 01:32 阿里爸爸 阅读(685) | 评论 (0)编辑 收藏

2007年5月31日 #

JSON是一种正在网络上慢慢兴起的数据交换格式。就象AJAX并不是什么新技术一样,JSON也没有提供什么新格式,它基于ECMAScript标准中对ObjectLiteral的定义(ECMA-262, 11.1.5),早就被javascript支持。格式定义非常简单,就是通过一组键值对来定义一个对象。在javascript中,你可以直接将这种格式的数据赋值给一个变量,然后通过键名取值。相对于使用xml来作为数据交换格式,如果要在javascript里使用,首先需要创建一个DOMParser,然后通过DOM接口访问节点对象,非常繁琐,更不用说不同浏览器的实现中DOMParser的实现和DOM接口都有诸多不同。为什么大量的AJAX应用中宁可直接返回一个HTML片断而不是直接把XML交给javascript处理,一个主要原因就是处理XML的过程比较复杂。JSON最重要的贡献就是简化了解析数据的过程。 del.icio.us提供的在网页上显示书签的javascript脚本就基于JSON,看一下这个脚本,再设想一下通过AJAX读取del.icio.us提供的RSS接口来实现这个功能,就能体会JSON的巧妙了。除此之外,更有人提出类似XSLT的JSONT,可以将JSON格式的内容转换成其他形式,虽然还暂时还没有XSLT灵活和强大,至少展示了一种可能性。 JSON解决的另一个传统AJAX中xmlhttprequest不能解决的问题就是跨域链接的问题。基于安全考虑,各种浏览器缺省都不允许xmlhttprequest跨域名链接,abc.com页面上的xmlhttprequest是无法连接def.com的内容的。在网页中,JSON可以采用引入script元素的方式导入数据,html中的script可以指定非本地脚本,跨域链接的问题得以解决。但使用这样的方式导入JSON数据,是一个同步的过程(是否可以用defer属性来实现异步?),这点上不如xmlhttpreqeust灵活。
posted @ 2007-05-31 16:32 阿里爸爸 阅读(1120) | 评论 (1)编辑 收藏

2007年5月30日 #

韦小宝的七位夫人不仅貌美,且来历不同。双儿是一位官宦人家的丫环,曾柔是王屋山强盗的女儿,沐剑屏是沐王府郡主,方怡是沐王府武士,苏荃是神龙教教主夫人,阿珂是李自成女儿,建宁是皇上妹妹。已改编的电视剧《鹿鼎记》现有五个版本,一起来看看影视中韦小宝这三十五位老婆,究竟哪一位是金庸笔下的美女呢?




阿珂
  七位老婆中最美的,原著写道:“韦小宝一见这少女,不过十六七岁,胸口像被一个无形的铁锤重重击了一记,霎时之间唇燥舌干。心道,我死了,我死了,这个美女倘若给我做老婆,小皇帝跟我换位也不干。”



  方怡

  容色晶莹如玉,映照于烛火之下,娇艳不可方物,性格心思隐晦复杂,极具心机。

  



  沐剑屏

  出身沐王府的郡主,七老婆中年纪最小,最为天真.她既有大家闺秀气质,又有书香门第的优雅性格。



  双儿

  对韦小宝忠心耿耿,温顺体贴,韦小宝与她相处最为轻松自在。其实她也是个“雪白脸庞,眉弯嘴小,笑靥如花”的俏丫头。



  建宁公主

  她刁蛮任性,心直口快,未谙世事,却可以为韦小宝放弃荣华,随他浪迹,韦小宝似乎最不喜欢她.两人在打打闹闹中建立的感情别人无法取代。



  曾柔

  书中着墨最少,她一直保留着初见面时韦小宝给她的几粒骰子。这个细节生动刻划了她温柔安静的外表下静默无言的爱。
  李小飞版和张卫健版都没曾柔,但张卫健版中弄出个小金鱼来,王晶大叔的戏不搞点花样就不爽。



  苏荃

  年纪最大,美丽却不打折扣。原著写道:“看模样不过二十三四岁年纪,微微一笑,媚态横生,艳丽无比。”神龙教教主夫人是七个老婆中的领袖人物。

posted @ 2007-05-30 20:34 阿里爸爸 阅读(932) | 评论 (2)编辑 收藏

1.什么是正则表达式


简单的说,正则表达式是一种可以用于文字模式匹配和替换的强有力的工具。是由一系列普通字符和特殊字符组成的能明确描述文本字符串的文字匹配模式。

正则表达式并非一门专用语言,但也可以看作是一种语言,它可以让用户通过使用一系列普通字符和特殊字符构建能明确描述文本字符串的匹配模式。除了简单描述这些模式之外,正则表达式解释引擎通常可用于遍历匹配,并使用模式作为分隔符来将字符串解析为子字符串,或以智能方式替换文本或重新设置文本格式。正则表达式为解决与文本处理有关的许多常见任务提供了有效而简捷的方式。

正则表达式具有两种标准:

·       基本的正则表达式(BRE – Basic Regular Expressions)

·       扩展的正则表达式(ERE – Extended Regular Expressions)。

ERE包括BRE功能和另外其它的概念。

 

正则表达式目前有两种解释引擎:

·       基于字符驱动(text-directed engine)

·       基于正则表达式驱动(regex-directed engine)

Jeffery Friedl把它们称作DFA和NFA解释引擎。

 

约定:

为了描述起来方便,在本文中做一些约定:

1.     本文所举例的所有表达时都是基于NFA解释引擎的。

2.     正则表达式,也就是匹配模式,会简写为Regex。

3.     Regex的匹配目标,也就是目标字符串,会简写为String。

4.     匹配结果用会用黄色底色标识。

5.     用1\+1=2 括起来的表示这是一个regex。

6.     举例会用以下格式:

 

test
This is a test
会匹配test,testcase等


  
2.正则表达式的起源
正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。

1956 年, 一位叫 Stephen Kleene 的美国数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。

随后,发现可以将这一工作应用于使用Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson是Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的qed 编辑器。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。具有完整语法的正则表达式使用在字符的格式匹配方面上,后来被应用到熔融信息技术领域。自从那时起,正则表达式经过几个时期的发展,现在的标准已经被ISO(国际标准组织)批准和被Open Group组织认定。

哇哈哈...不可天下人负我!!!
穷!机子天天蓝屏......
 

 
3. 正则表达式使用祥解
最简单的正则表达式相信大家都已熟悉并且经常使用,那就是文字字符串。特定的字符串可通过文字本身加以描述;像 test这样的Regex模式可精确匹配输入的字符串”test”,但是它也可以匹配this is a testcase,这就不是我们想要得结果。

当然,使用正则表达式匹配等于它自身的精确字符串是没有价值的实现,不能体现正则表达式的真正作用。但是,假如要查找的不是test,而是所有以字母 t 开头的单词,或所有4个字母的单词,那该怎么办?这超出了文字字符串的合理范围。所以我们才需要深入地研究正则表达式。

3.1基本语法
虽然正则表达式并非一门专用语言,但它也有一些特殊的规定,也可以称之为基本语法。

正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。

可以通过在一对分隔符之间放入表达式模式的各种组件来构造一个正则表达式。

3.1.1普通字符
由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。

3.1.2非打印字符
非打印字符也是普通字符,单独列出来便于参考。

哇哈哈...不可天下人负我!!!
穷!机子天天蓝屏......
 
非打印字符参考(有错大家矫正,JS手册都有)
\cx
匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。

\f
匹配一个换页符。等价于 \x0c 和 \cL。

\n
匹配一个换行符。等价于 \x0a 和 \cJ。

\r
匹配一个回车符。等价于 \x0d 和 \cM。

\s
匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。

\S
匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。

\t
匹配一个制表符。等价于 \x09 和 \cI。

\v
匹配一个垂直制表符。等价于 \x0b 和 \cK。

Regex中可以使用非打印字符。\t会匹配一个tab字符(ASC||),\r 会匹配一个回车(0x0D),\n 会匹配一个换行符(0x0A)。应该注意的是:Windows使用\r\n表示一行的结束,而UNIX使用\n 。

同样,我们可以在Regex中使用16进制的ASCⅡ码或者ANSI标准码。在拉丁语中,版权符号的代码是0xA9,所以我们也可以这样来匹配版权符号 \xA9 。另外一个匹配tab的写法是:\x09 。但是注意,第一位的“0”必须去掉。


特殊字符
特殊字符也叫做元字符,保留字符(Metacharactor),在Regex中表示特殊的意义,大部分的意思在不同的上下文中的意义是不同的,这里只列出最普遍的意义。

特殊字符共有11个:
$
匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。

( )
标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。

*
匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。

+
匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。

.
匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \。

[
标记一个中括号表达式的开始。要匹配 [,请使用 \[。

?
匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。

\
将下一个字符标记为或特殊字符、或原义字符、或反向引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。

^
匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。

{
标记限定符表达式的开始。要匹配 {,请使用 \{。

|
指明两项之间的一个选择。要匹配 |,请使用 \|。

在元字符前加 \ 转义符,可以把特殊字符当作普通字符来使用。

比如:如要要匹配 1+1=2 ,正确的正则表达式应该为1\+1=2。否则, + 会被当作特殊字符对待。

除了特殊字符,所有的其他字符都不应该加 \ 。因为 \ 也是一个特殊字符。\ 和普通字符组合在一起也可以创造一种特殊的意义。比如 \d 表示匹配所有的数字。

作为程序员,单引号和双引号不是特殊字符会也许让我们感到很惊讶。但这是正确的。因为我们在编程的时候,编程语言会知道引号之间的哪些字符表示特殊意义,编译器在把字符串x传递给regex解释引擎之前,会把它们处理成regex。比如,在C#中,如果我们要匹配 1\+1=2 ,在程序中我们要这样写: “1\\+1=2” ,C#编译器会把 “\\” ,处理为一个“\” 。同样,如果要匹配 C:\Temp ,首先,正则表达式要这样写 C:\\Temp,然后在程序中我们应该这样写:“ C:\\\\temp”。

哇哈哈...不可天下人负我!!!
穷!机子天天蓝屏......
 
 


3.1.4字符集
        字符集描述了一组字符,Regex解释器会认为匹配字符集中的一个字符就可以认为匹配成功。

字符集用[ ]括起来即可。

        比如gr[ae]y就可以匹配gray或者grey。

        字符集只能匹配一个字符,gr[ae]y就不能和graey匹配。字符集中的字符顺序是任意的,得到的结果都是唯一的。

        可以在字符集中用连字符“-”来表示一个范围。[0-9]的结果和[0123456789]的匹配结果都是相同的。字符集中的范围可以有多种。比如[0-9a-fA-F]表示匹配所有的16进制,包括大小写。也可以把范围和单个字符组合在一起用,[0-9a-fxA-FX]表示匹配所有的16进制或者一个字符X。字符集的顺序不会影响结果。

        在字符集的开始标志“[”后面加上一个“^”符号,表示否定,表示匹配除字符集中定义的字符以外的所有字符。包括非打印字符和行结束符。

        注意:字符集匹配的一个字符,而不是一个位置。所以。q[^u]的意义不是“q后面的字符不是u”。而是“q后面的字符可以是除了u以外的所有字符”。

        q[^u]不会和Iraq匹配。

但是会和Iraq is a country匹配,因为q后面的空格字符是一个“不是u的字符”。

3.1.5在字符集中使用元字符
字符集中的元字符只能是 ‘]’, ‘\’, ‘^’, 和 ‘-‘ 。

其他元字符在字符集中都失去了特殊意义,表示的只是一个普通字符。也不需要用加“\”。

比如:

匹配一个“*”或者“+”,用[*+]就足够了。即使给他们加上“\”,regex解释器也会把他们忽略掉。

 

四种特殊字符的处理:

在字符集中要表示“]”,“^”和“-”需要在后面加上转义符“\”,来表示它们代表的分别是普通字符“]”,“^”和“-”。

也可以把它们放在一个不能表示特殊意义的位置,后一个方法比较好,因为他们不会影响可读性。

“^”
要想匹配一个“^”,可以把它放在除了紧跟“[”的任意一个位置。

Regex
String
Description

[x^]
A string with x and ^.
匹配x或者“^”

 


“]”
可以把“]”放在紧跟着“[”的位置,或者使用否定字符集。

Regex
String
Description

[]x]
A string with x and ]
匹配x或者“]”

[^]x]
A string with x and ]
匹配除了x和”] ”以外的所有字符


“\”
要想把“\”当作一个普通字符来匹配,而不是一个特殊字符,必须把“\”再用一个“\”括起来。


[\\x]
A string with x and \
匹配x或者“\”

 


“-”
连字符可以放在紧跟着“[”的后面,或者正好“]”的前面,或者紧跟着“^”的后面。

 

[-x]
A string with x and -
匹配x或者“-”

[x-]
A string with x and -
匹配x或者“-”

预定义字符集
因为很多字符集是经常使用的,所以Regex解释器预定义了一些常用字符集:

d
[0-9]
所有数字

\w
[a-zA-Z]
表示所有的字符,和文化字体有关

\s
[ \t\r\n]

空格,回车和tab。和文化字体有关

预订一字符集可以既可以用在字符集里面,也可以用在字符集外面。
\s\d
1<space>+<space>2<space>=<space>3
匹配后面紧跟着一个数字的空白符

[\s\d]
1<space>+<space>2<space>=<space>3
匹配一个单独的字符或者一个数字或者一个空白符

[\da-fA-F]和[0-9a-fA-F]的匹配结果是一样的。

 

同样,在预定义字符集前面加一个“^”符号表示否定。它们也有预先定义好的表示:

\D
[^\d]
非数字

\W
[^\w]
非字符,和文化字体有关

\S
[^\s]
非空格,回车和tab。和文化字体有关

在“[]”使用否定预订一字符集时要特别心。[\D\S]不等于[^\d\s]。[^\d\s]会匹配除了数字和空白符以外的所有字符。而[\D\S]会匹配要么不是一个数字,要么是空白符。因为数字不是空白符,空白符也不是数字,所以[\D\S]会匹配任意的字符。

限定符
有时候不知道要匹配多少字符。为了能适应这种不确定性,正则表达式支持限定符的概念。这些限定符可以指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。

下表给出了各种限定符及其含义的说明:

* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。 * 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。刘, "o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
对一个很大的输入文档而言,章节数很轻易就超过九章,因此需要有一种方法来处理两位数或者三位数的章节号。限定符就提供了这个功能。下面的JScript 正则表达式可以匹配具有任何位数的章节标题:

/Chapter [1-9][0-9]*/
下面的 VBScript 正则表达式执行同样的匹配:

"Chapter [1-9][0-9]*"
请注意限定符出现在范围表达式之后。因此,它将应用于所包含的整个范围表达式,在本例中,只指定了从 0 到 9 的数字。

这里没有使用 '+' 限定符,因为第二位或后续位置上并不一定需要一个数字。同样也没有使用 '?' 字符,因为这将把章节数限制为只有两位数字。在 'Chapter' 和空格字符之后至少要匹配一个数字。

如果已知章节数限制只有99 章,则可以使用下面的 JScript 表达式来指定至少有一位数字,但不超过两个数字。

/Chapter [0-9]{1,2}/
对 VBScript 可以使用下述正则表达式:

"Chapter [0-9]{1,2}"
上述表达式的缺点是如果有一个章节号大于 99,它仍只会匹配前两位数字。另一个缺点是某些人可以创建一个 Chapter 0,而且仍能匹配。一个更好的用来匹配两位数的 JScript 表达式如下:

/Chapter [1-9][0-9]?/
或者

/Chapter [1-9][0-9]{0,1}/
对 VBScript 而言,下述表达式与上面等价:

"Chapter [1-9][0-9]?"
或者

"Chapter [1-9][0-9]{0,1}"
'*'、 '+'和 '?' 限定符都称之为贪婪的,也就是说,他们尽可能多地匹配文字。有时这根本就不是所希望发生的情况。有时则正好希望最小匹配。

例如,你可能要搜索一个 HTML 文档来查找一处包含在 H1 标记中的章节标题。在文档中该文字可能具有如下形式:

<H1>Chapter 1 – Introduction to Regular Expressions</H1>
下面的表达式匹配从开始的小于号 (<) 到 H1 标记结束处的大于号之间的所有内容。

/<.*>/
VBScript 的正则表达式为:

"<.*>"
如果所要匹配的就是开始的 H1 标记,则下述非贪婪地表达式就只匹配 <H1>。

/<.*?>/
或者

"<.*?>"
通过在 '*'、 '+' 或 '?' 限定符后放置 '?',该表达式就从贪婪匹配转为了非贪婪或最小匹配。

posted @ 2007-05-30 20:00 阿里爸爸 阅读(1394) | 评论 (1)编辑 收藏

2007年5月19日 #

     摘要: 一、我们可以且应该优化什么?

硬件

操作系统/软件库

SQL服务器(设置和查询)

应用编程接口(API)

应用程序


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

二、优化硬件

如果你需要庞大的数据库表(>2G),你应该考虑使用64位的硬件结构,像Alpha、Sparc或即将推出的IA64。因为MySQL内部使用大量64位的整数,64位的CPU将提供更好的性能。

对大数据库,优化的次序一般是RAM、快速硬盘、CPU能力。

更多的内存通过将最常用的键码页面存放在内存中可以加速键码的更新。

如果不使用事务安全(transaction-safe)的表或有大表并且想避免长文件检查,一台UPS就能够在电源故障时让系统安全关闭。

对于数据库  阅读全文
posted @ 2007-05-19 19:22 阿里爸爸 阅读(1739) | 评论 (2)编辑 收藏

2007年5月10日 #

通过 Bindows™,你可以开发Web页面中的全功能桌面应用程序,而无需任何插件。不论你是喜欢严格地按照最优方法进行 OOP,还是喜欢最近比较流行的 RAD,Bindows™ 都为你提供了开发高效灵活的 Rich Internet Applications 的工具。

Bindows™ 框架提供:

基于类的面向对象 API;
一个完整的窗口系统,带有一组广泛支持的窗体小部件,包括菜单、表单、表格、滑块、量表以及更多;
开发零接触 SOA 客户端应用程序的最好的工具包;
内置 XML,SOAP 和 XML-RPC 支持;
从单用户到企业级的支持。
“富”“瘦”兼备

Bindows 突破了你必须要在富(界面)和瘦(客户端)之间选择的典范。
Bindows 应用程序可以如现代任何桌面应用程序一样华丽同时又极其瘦小(并且是零接触)。Bindows 应用程序是:

华丽的,可定制的,有着桌面般的 GUI 组件
运行于标准的浏览器中而无需任何安装的(零接触)
无需专门的客户端,运行时引擎,或者插件
无依赖性

Bindows 应用程序不依赖于:

服务器 —— 任何服务器(Java,.NET,PHP 等都可以与 Bindows 结合使用)
后端平台 —— 任何后端硬件和后端软件
操作系统 —— 客户端可以使用任何操作系统(只要它包含一个支持的浏览器)
语言 —— 所有的语言都支持。Bindows 支持 Unicode
浏览器 —— 大部分浏览器都支持(比如:Internet Explorer 5.5 及其更高版本,Mozilla 1.4 及其更高版本,Netscape 7.1 及其更高版本,Firefox,K-Meleon 和 Camino)

Bindows 软件开发工具包(SDK)

Bindows 是一个用来编写安全健壮的 Rich Internet Applications 的软件开发工具包(SDK)。Bindows 平台为瘦 Web 客户端提供了丰富的功能。Bindows 应用程序无需终端用户下载 —— 真正的零接触(不使用 Java、Flash 或者 ActiveX)

XML 和 Web Services

Bindows 应用程序通过 XML 文档来定义,并且支持标准的 SOAP Web Services.

Bindows 开发环境

支持企业级项目
跨浏览器、跨平台支持
不依赖于服务器的构架
可以与新的和已存在的资源协同工作
有统一的开发方式

Rich Internet Applications (RIA)

Rich Internet Applications 将现代 PC 桌面程序般的界面与基于 Internet 的构架相结合,使得通过 Internet 浏览器访问到的程序拥有桌面软件一样的功能。RIA 允许 Web 站点在无需终端用户下载的情况下提供复杂的数据处理并有着快速的反应时间。


原文
posted @ 2007-05-10 10:25 阿里爸爸 阅读(1103) | 评论 (0)编辑 收藏

2007年5月2日 #

今天,Sun报告说公司第三季度继续赢利,尽管存储产品的表现持续欠佳。
  
    根据GAAP计算,Sun公司在这一季度净利润为6700万美元,每股收益2美分,这一业绩好于去年同期,2006财年第三季度,Sun的净亏损为2.17亿美元,每股亏损6美分。此前,分析师们估计该公司每股的收益会达1美分。
  
    Sun公司这一财季的收入是32.83亿美元,比去年同期增长3.3%,但未能达到分析师此前预期的34.2亿美元。
  
    Sun公司数据管理部门的收入,包括存储,共计5.5亿美元,同比下降0.2%,致使CEO Jonathan Schwartz在电话会议上抱怨说:“我们的存储业务有所进步,但表现没有达到预期。”
  
    该业绩表明,Sun 还在为它的存储产品做着不懈的努力。该公司已经用41亿美元收购了StorageTek,去年一直在不断改进它的存储业务。
  
    尽管Sun公司的存储业务表现不佳,但它的归档产品和磁带产品表现不错,公司 CEO Jonathan Schwartz希望通过最近的开放其公司NAS源码的决定会扭转目前的局面。他说:“我们会继续开发Solaris,不只是在系统方面,还包括存储方面。”
  
    CEO Jonathan Schwartz还抱怨美国和英国这一财季的业绩。他说:“我们预计第三季度只是季节性的问题----我们在美国和英国的市场处于困境,尤其是三月份。”
  
    Sun公司CFO Mike Lehman 也打算避开财务问题,也解释说是季节性问题,用户延迟购买他们的产品是因为Sun最近与日本富士通的合作。他说:“三月的这一季度一直是一个季节性问题。”“销售速度放缓是上星期Sun与富士通宣布会提供更高性能产品的必然结果。”
  
    针对目前的情况,有分析师说,经历了重大调整的Sun可能正计划做出更大的变动。他说:“我们正密切关注Sun工作人员的一举一动。”
  
    Sun还介绍了它的新产品计划,这一周,该公司正计划推出它的第一个与视频有关的产品,该产品兼具服务器与存储的功能。它是一款新的刀片产品,兼备Intel, AMD, 和 Sun公司自己的SPARC处理器,将在六月份面市,命名为“Constellation”。
  
   在随后的交易中,Sun股票下跌36美分,跌至5.59美元,跌幅为6.06%。 原文
posted @ 2007-05-02 12:59 阿里爸爸 阅读(709) | 评论 (0)编辑 收藏

2007年4月30日 #

     摘要:   很显然,这会造成一些恐慌——-免费开放源代码的要求会威胁到企业Java开发人员的商业模式。但是Sun公司很快就取消了大家的担忧,对于现有Java开发人员来说,软件的发布意味着一切正常。Sun公司如此有信心的原因就在于前面所说的Classpath例外,Classpath例外是为Classpath项目而开发的:它是通过开源编写的Java类标准,也在其它开源Java项目中采用,例如Kaffe。Classpath例外的内容较短,所以也值得一读:

  静态或者动态地将java库和其它模块链接在一起,完成基于此库的组合工作。这样,GNU的GPL规定和条件将覆盖在整个组合体之上。

  作为一种特殊的例外,此库的版权持有者分配给你权限来将用于生产可执行程序的独立模块链接到这一库。无论这些独立模块的授权如何规定,如何复制、发行可执行程序都依赖于你的选择。这里的独立模块是指非来源于或是基于此库的模块。如果你修改这个库,就可以扩展这个例外到你的版本中,然而这并不是必须的义务,如果不想这样做,可以从你的版本中删除这条例外。

  这段话的实质就是关  阅读全文
posted @ 2007-04-30 02:09 阿里爸爸 阅读(755) | 评论 (0)编辑 收藏

[转贴]学编程的人不能不看的好文章 [精华]  摘自中国java开发网

看了下面的这篇文章,深有感触,枣子碰到的问题也是我们大多数程序员的通病,也许我们大多数人都只是在做一些比较小型的软件,对软件运行的效率不在乎,就算对速度和效率在乎的也可能是一些在数据库操作方面的。大家看完了,也许会有很多感想,但这只是我同意枣子的个人观点。
(枣子原创--www.vcroad.net wutao8@263.net)
做为一名大四的学生,我面试过不少的单位,有成功的也有失败的,但是对我来说所有的失败在某种意义上都是一种成功,特别是我下面写的这些,写这篇文章的时候,我已经签了南京的一家软件公司,但是想起今年2月21日我面试苏州台湾的IT公司的经历联想到我们现在
学习编程的一些情况我真的深有感触,这次面试使我深深的体会到了失败但也收获了很多。我要说的将分成三部分,1.是
我面试的具体经过2.是由面试想到的3.现今我应该做的。当然这些话很大程度上是我个人的意见,不可能完全得到大家的赞同,所以
在某些观点上如果哪位朋友觉得跟我的有很大出入,请不要介意,也不要对我攻击,就当我没有说过,欢迎和我联系共同探讨这些问题!我的EMAIL:wutao8@263.net
1.面试经过
大约在年前我接到了台湾瑞晟(Realtek)苏州公司的面试通知,通知我2月21日到苏州工业园区面试,接到面试后的几天我把一些专业
课温习了一遍,特别是C++和数据结构,由于大学几年里,我一直专研这些方面,加上通过了高级程序员的考试,对于一些常用的算法
我差不多也达到了烂熟于胸的地步,当时的感觉是如果问了我这些方面的问题我应该是没有问题的!
21日那天我被安排在4:30面试,由一位技术人员单独给我面试,在问了一些简单的问题之后他给我出了一道编程题目,题目是这样的:
(由于具体面试的题目比较烦琐,我将其核心思想提取出来分解成了两个独立的简单的问题,有可能问题分解的不当,请大家见谅,实际面试了一个的问题但比其复杂很多,而且涉及一些高等数学变换)
1) 写一个函数计算当参数为n(n很大)时的值 1-2+3-4+5-6+7......+n
哼,我的心里冷笑一声!没想到这么简单,我有点紧张的心情顿时放松起来!
于是很快我给出我的解法:
long fn(long n)
{
long temp=0;
int i,flag=1;
if(n<=0)
{
printf("error: n must > 0);
exit(1);
}
for(i=1;i<=n;i++)
{
temp=temp+flag*i;
flag=(-1)*flag;
}
return temp;
}
搞定!当我用期待的目光看着面试官的时候,他微笑着跟我说,执行结果肯定是没有问题!但当n很大的时候我这个程序执行效率很低,
在嵌入式系统的开发中,程序的运行效率很重要,能让CPU少执行一条指令都是好的,他让我看看这个程序还有什么可以修改的地方,
把程序优化一下!听了这些话,我的心情当时变的有点沉重,没想到他的要求很严格,之后我对程序进行了严格的分析,给出了改进了的方案!
long fn(long n)
{
long temp=0;
int j=1,i=1,flag=1;
if(n<=0)
{
printf("error: n must > 0);
exit(1);
}
while(j<=n)
{
temp=temp+i;
i=-i;
i>0?i++:i--;
j++;
}
return temp;
}
虽然我不敢保证我这个算法是最优的,但是比起上一个程序,我将所有涉及到乘法指令的语句改为执行加法指令,既达到要题目的要求而且
运算时间上缩短了很多!而代价仅仅是增加了一个整型变量!但是我现在的信心已经受了一点打击,我将信将疑的看者面试官,他还是微笑着
跟我说:“不错,这个程序确实在效率上有的很大的提高!”我心里一阵暗喜!但他接着说这个程序仍然不能达到他的要求,要我给出更优的
方案!天啊!还有优化!我当时真的有点崩溃了,想了一会后,我请求他给出他的方案!然后他很爽快的给出了他的程序!
long fn(long n)
{
if(n<=0)
{
printf("error: n must > 0);
exit(1);
}
if(0==n%2)
return (n/2)*(-1);
else
return (n/2)*(-1)+n;
}

搞笑,当时我目瞪口呆,没想到他是这个意思,这么简单的代码我真的不会写吗,但是我为什么没有往那方面上想呢!他说的没有错,在n很大很大的时候这三个程序运行时间的差别简直是天壤之别!当我刚想开口说点什么的时候,他却先开口了:“不要认为CPU运算速度快就把所有的问题都推给它去做,程序员应该将代码优化再优化,我们自己能做的决不要让CPU做,因为CPU是为用户服务的,不是为我们
程序员服务的!”多么精辟的语言,我已经不想再说什么了!接着是第二个问题:
2),他要求我用一种技巧性的编程方法来用一个函数实现两个函数的功能n为如:fn1(n)=n/2!+n/3!+n/4!+n/5!+n/6!
fn2(n)=n/5!+n/6!+n/7!+n/8!+n/9! 现在用一个函数fn(int n,int flag)实现,当flag为0时,实现fn1功能,如果flag为1时
实现fn2功能!他的要求还是效率,效率,效率!说实在话,如果我心情好的话我应该能给出一种比较好的算法,但我那时真的没有什么心思
再想了,我在纸上胡乱画了一些诸如6!=6*5!的公式后直截了当的跟他说要他给出他的答案!面试官也没有说什么,给出了他的思路:
定义一个二维数组 float t[2][5]存入[2!,3!,4!,5!,6!},{5!,6!,7!,8!,9!]然后给出一个循环:

for(i=0;i<6;i++)
{
temp=temp+n/t[flag];
}
最后得到计算值!呵呵,典型的空间换时间的算法!
这些总共花了50分钟的时间,还有十分钟我就跟他很随意的聊聊天,聊了一些编程以及生活的问题,那时的我已经很放松了,
因为我知道这次面试结果只有一个:失败。5:30的时候面试官要我等通知,于是我离开了他们公司。这就是面试的整个经过!

2.由面试想到的

真的是很失败啊!我记得那天下好大的雨,气温也很低,我边走边想,从5:30一直走到7:30,全身都湿透了,又冷又饿,但是我只是一直走,脑子里面充满了疑惑,我也想让雨把自己淋醒!看到这里有些朋友可能觉得那些面试题目不算什么如果让自己做的话肯定能全部答对,我肯定相信你,因为我从未怀疑过中国程序员的能力,我认为中国有世界上最好的程序员,我也从未认为自己是高手,所以我做不出来不代表中国程序员比台湾或者别的地方的程序员差,所以我就从我的角度,我的所见所想来谈一些感想:

不错全世界都有优秀的程序员,中国也不例外,但是我疑惑的是:到底中国和台湾或者国外的优秀的程序员的比例到底是多少?台湾我不知道,中国100个程序员里有几个是优秀的呢?我根本算不上,从上面的表现就足以说明一切了!是1个?5个?10个?50个?这个数字我不敢乱猜,恐遭网友一顿痛骂,那么我们国内有多少人学习计算机呢?拿我们学校来说,计算机97级4个班,98级5个班,99级10个班,2000级 17个班,人多了,老师怎么办?我们学校的做法是让研究生上课,然后呢?补考一抓一大把,大把大把的补考费落入了学校的口袋,还说现在的学生素质低!真是好笑,我都不知道学校这么做是为了什么,为国内培养大量的程序员吗?学生们能真正学到计算机知识吗?好了,我敢讲,在我们学校学习编程学生和优秀程序员 (注意我指的是优秀,只会编几个糟烂程序的人算不上)的比例应该是100:0.1
在这种比例下虽然我们中国学习编程的人铺天盖地,但是想想有多少个人能真正为中国软件业发展作出贡献,有多少人能真正写出优秀的程序名扬海外!

我从学习编程以来,不管是自学还是老师指导,从来都是解决问题就好,编出程序来就行,我的疑惑是:我们有真正的强调过程序的效率,程序的质量吗?我们有仔细分析过我们写的东西,看看有没有可以改进的地方,看看有没有简单的方法来达到同样的目的呢?我问心自问,我发现,我从来没有对我写出来的程序进行过优化,最多就是进行详细的测试,然后Debug,但是这就足够了吗?这些天我偶尔发现我曾经写过的一个游戏,那是一年前我刚加入www.vcroad.net做为其中一员时候,感觉应该拿点东西出来,然后花了一个星期的时间写出来的!程序不算复杂,但是用到了不少数据结构的东西,也用到了一些精彩的算法,加上 windows的界面和游戏的可玩性,写完后受到了不少好评,我当时真的很佩服自己!但是现在看呢:没有一句注释,好多丑陋的函数名比如:void chushihua(),好多没有必要的变量,可以用简单语句完成工作的我使用华丽的算法,大量使用全局变量.....,说不好听的话,六百多行的程序除了能运行之外就是一陀屎!如果一年前我能听到一些反面意见的话,大概我能早一点觉悟,但是自从原代码在网站发布以来听到的都是赞美之词,没有一个人向我提出程序改进的意见,这又说明了一个什么问题呢?很值得思考啊!

还有一个疑惑是:我们说的和做的真的一样吗?我在学校的时候曾经受学院指派承办过一个计算机大赛,请了一个老师出决赛的题目,主要是一些算法题目,这个老师可能是我上大学以来唯一敬佩的老师了,从程序调试到打分,对于每个程序都仔细分析其时间效率和空间效率,然后综合打分,四十个人的卷子,老师从下午三点一直调试到晚上十点,在有些写的精彩的语句后还加上批注。我真是高兴很遇到这样的老师并且和他做深入的交流,但在事后,却发生了一件不愉快的事,在比赛中获得第二名的学生找到我,说他程序全部调试成功应该给他满分,并且应该得第一,我说不过他,最后调出了他的原程序和第一名的原程序对比,不错,两个程序都运行的很好,这时,那个同学开口了:“我的程序写的十分简捷明了,仅仅数行就完成了题目要求,而他的却写了一大堆,为什么给他的分多过给我的分。”我当时很是气愤,如果不是老师负责的话,那么现在第一名和第二名的位置真的要互调了,拜托,不是程序的行数越少程序的质量就越高,我记得我跟他大谈这方面的道理,最后说服他了!哈哈,但是我,只能说说而已,我不知道还有多少人一样,说起来头头是道,但心里却压根就从未重视过它!

3.我打算做的!
其实那天我想到的远不止上面那么多,但是我不想再说了,因为我猜想看这篇文章的网友大概都有一肚子的感想,一肚子的抱怨,借用这篇文章发泄可不是我想达到的目的,在上面我把自己骂的一文不值也不是妄自菲薄,但是在某些方面我真的做错了,或者说是偏离了正确方向,现在是矫正方向和重整旗鼓的时候了,就象我前面说过的,我相信中国有世界上最好的程序员,我也相信我的水平不会一直保持现状,我现在就收拾起牢骚真正的实干起来!
真的很巧,就写到这里的时候我在网上偶尔发现了这篇手册,我不知道这预示着什么,但是我想如果我照下面这个基本原则一直踏实做下去,我一定会实现我的理想---一名优秀的软件设计师!

(下面这些文字不是我的原创,是我偶尔在网上发现的,我真的很幸运能看到这些,这篇文章也随着下面的文字而结束,我真心的希望您能从这篇文章中得到启发,这篇文章欢迎大家随意转载,您可以不写作者是谁,但是请您写上www.vcroad.net原创,谢谢您的支持)

作者:金蝶中间件公司CTO袁红岗

不知不觉做软件已经做了十年,有成功的喜悦,也有失败的痛苦,但总不敢称自己是高手,因为和我心目中真正的高手们比起来,还差的太远。世界上并没有成为高手的捷径,但一些基本原则是可以遵循的。

  1. 扎实的基础。数据结构、离散数学、编译原理,这些是所有计算机科学的基础,如果不掌握他们,很难写出高水平的程序。据我的观察,学计算机专业的人比学其他专业的人更能写出高质量的软件。程序人人都会写,但当你发现写到一定程度很难再提高的时候,就应该想想是不是要回过头来学学这些最基本的理论。不要一开始就去学OOP,即使你再精通OOP,遇到一些基本算法的时候可能也会束手无策。

  2. 丰富的想象力。不要拘泥于固定的思维方式,遇到问题的时候要多想几种解决问题的方案,试试别人从没想过的方法。丰富的想象力是建立在丰富的知识的基础上,除计算机以外,多涉猎其他的学科,比如天文、物理、数学等等。另外,多看科幻电影也是一个很好的途径。

  3. 最简单的是最好的。这也许是所有科学都遵循的一条准则,如此复杂的质能互换原理在爱因斯坦眼里不过是一个简单得不能再简单的公式:E=mc2。简单的方法更容易被人理解,更容易实现,也更容易维护。遇到问题时要优先考虑最简单的方案,只有简单方案不能满足要求时再考虑复杂的方案。

   4. 不钻牛角尖。当你遇到障碍的时候,不妨暂时远离电脑,看看窗外的风景,听听轻音乐,和朋友聊聊天。当我遇到难题的时候会去玩游戏,而且是那种极暴力的打斗类游戏,当负责游戏的那部分大脑细胞极度亢奋的时候,负责编程的那部分大脑细胞就得到了充分的休息。当重新开始工作的时候,我会发现那些难题现在竟然可以迎刃而解。

  5. 对答案的渴求。人类自然科学的发展史就是一个渴求得到答案的过程,即使只能知道答案的一小部分也值得我们去付出。只要你坚定信念,一定要找到问题的答案,你才会付出精力去探索,即使最后没有得到答案,在过程中你也会学到很多东西。

  6. 多与别人交流。三人行必有我师,也许在一次和别人不经意的谈话中,就可以迸出灵感的火花。多上上网,看看别人对同一问题的看法,会给你很大的启发。

  7. 良好的编程风格。注意养成良好的习惯,代码的缩进编排,变量的命名规则要始终保持一致。大家都知道如何排除代码中错误,却往往忽视了对注释的排错。注释是程序的一个重要组成部分,它可以使你的代码更容易理解,而如果代码已经清楚地表达了你的思想,就不必再加注释了,如果注释和代码不一致,那就更加糟糕。

  8. 韧性和毅力。这也许是"高手"和一般程序员最大的区别。A good programming is 99 weat and 1ffee。高手们并不是天才,他们是在无数个日日夜夜中磨练出来的。成功能给我们带来无比的喜悦,但过程却是无比的枯燥乏味。你不妨做个测试,找个 10000以内的素数表,把它们全都抄下来,然后再检查三遍,如果能够不间断地完成这一工作,你就可以满足这一条。
posted @ 2007-04-30 01:31 阿里爸爸 阅读(1429) | 评论 (3)编辑 收藏

2007年4月29日 #

     摘要: 一篇无意从网络上找到的文章,发现写得很精彩,于是就将它翻译了 下来。但是有些段子我还是翻译的不怎么的好,请兄弟们见谅了。


当你开启电脑时,它发生了什么?

一台没有软件运行的电脑只是一堆发热的电子器件。当计算机起电启动开始的第一件 事情就是运行一个叫做“操作系统”的特殊程序。操作系统的作用就是帮助其他的程序能够 的控制和访问计算机硬件。

装入操作系统的步骤叫作引导(booting)。(从严格意义上说,引导和自我检查的 处理步骤叫做“自检”)。您的计算机知道如何去引导,因为在其具体的操作方法已经 集成在一块称做 BIOS(或者叫基本输入输出系统)的芯片中了。

BIOS 芯片告诉计算机查看一个合适的地方引导系统,通常这个地方在编号最小的磁盘 上(引导盘)。一个称做引导器的程序(在 linux 下通常是 Grub 或者是 LILO)会被装入 内存,并且启动。引导器的作用就是装入真正的操作系统。  阅读全文
posted @ 2007-04-29 00:50 阿里爸爸 阅读(817) | 评论 (0)编辑 收藏

2007年4月27日 #



crazyegg
的广告已经有大半年了,应该有很多人已经把那个广告都看烦了,疯狂的鸡蛋目的和其它的站点统计工具不太一样,他会提供一个页面的地图,上面显示各个链接被点击的次数,以此帮助我们选择最有效的投放广告的区域,最热门的链接,改善模板,调整布局,etc。而 crazyegg 漂亮的页面设计也应该算是他们的一大卖点。对于 crazyegg 另外两个功能 list(不支持中文)和 heatmap 我感觉用处并不是很大。
Crazy Egg — Reports1156432348871

遗憾的是 crazyegg 的免费用户每月只有可怜区区 5000 的访问数可用,想没有拘束的用下去只有花钱了 :(

其实 Google Analyetics 早就提供了这个功能,就在内容优化->导航分析->网站覆盖图,可不知道什么原因,这个功能被他们做的很不完善,很多链接都没有被统计,用着很不舒服,现在可以勉强用 crazyegg 代替了:p

posted @ 2007-04-27 13:46 阿里爸爸 阅读(993) | 评论 (0)编辑 收藏

2007年4月25日 #

所有产品刚推上市场的时候,都会有时尚群体去体验新产品,过了段时期是观望群体视时尚群体的反响及市场的反应选择性的尝试。最后就是落伍者们大量涌入市场,试用新产品。
我就是属于第二类,观望群体。很多时候喜欢看那些时尚群体及市场反应,反应好的才去用。不好的可能也会去(看看到底烂到了什么程度)。
记得02年的时候,微软的XP刚推出,N多人都在用,觉得很N屁。我用着2000 professional,觉得挺好,过了一年后,发现这个世界疯狂了,都改用XP了!我也开始用XP,感觉确实不错,产品挺好的!
现在vista出来了,好多同事都去体验了把。都说有些功能很牛,就是慢,费资源。我也就懒得去抓腾,等哪天闲了,再去搞搞。人活着就得要折腾。

今天看相关vista的新闻、评论,都说用户还是比较少,各大PC厂商也不主推vista。

今天无事早点睡。
posted @ 2007-04-25 00:40 阿里爸爸 阅读(439) | 评论 (0)编辑 收藏

     摘要:   自由/开源软件是一种有版权的软件,自由/开源软件是一种得到许可的软件。自由/开源软件许可协议(或许可证)是其版权实施的延伸。

  自由/开源软件采用“左版”(CopyLeft)的概念,虽然其“版权”也应考虑到保护“作者对其作品享有权益”的作用,但由于自由开源运动的本质是发扬“自由、开放精神”,把重点放在扩大用户的自由和权益方面,放在用户在再传播(或再发布)时得到扩大的许可授权方面,而不是把重点放在对作者特权的保护方面(如表现为不收版权费,任何人都可自由获得、复制、修改、发布原创作品或升级产品的源代码,淡化作者的特权,甚至“模糊”可执行的“版权”,总之由原作者放弃自己的一些知识产权的权利,向公众公布许可等)。它不同于传统“版权”(即“右版”,CopyRight)在“保护作者对作品享有法定特权”方面所表现的刚性化的特征。

  自由/开源软件的版权理论上属于原创软件作品的作者(writers、authors、developers),以及升级软件作品的后续修改者(贡献者Contributors,志愿者Volunteers),总称为所有者(owners)。  阅读全文
posted @ 2007-04-25 00:26 阿里爸爸 阅读(4789) | 评论 (0)编辑 收藏

2007年4月24日 #

     摘要: 笑话1.(表跟老大抢.......)
亡灵男巫:女妖MM啊,你为什么老是拒绝我呢?
女妖:看看你那身板,俺们老大DK才是我的偶像。人家那技能,太强了。在和我那个的时候,不仅可以加快速度,还能恢复体力那,嘻嘻,人家都不好意思了,我体力不足的时候,还能给我一发C恢复体力,真是好人啊。
亡灵男巫:......什么啊,我吼~~~~~~~~~~~我也有NB的技能啊!我的狂暴技能功效不比老大的差啊!
女妖:可是......到最后你会那个什么尽人亡的.....
亡灵男巫:......贱货,说白了你就是看不起我,啊~~~~~~~~~~~召唤骷髅!把她给我绑了。
女妖:你你,你干什么。(挣扎)
亡灵男巫:还动,残废~~~~~~~~
女妖:DK啊~~~~~~~~
远处DK赶来,见状对女妖喊道:快打我一下。
女妖疑惑的问道:为什么啊,快啊。
DK:表废话,叫你打就快打!
女妖吓了一跳,无奈只得出手打了DK一下........
突然见亡灵男巫化为一股青烟,远处的DK满意的打了个嗝........
笑  阅读全文
posted @ 2007-04-24 16:48 阿里爸爸 阅读(555) | 评论 (0)编辑 收藏

仅列出标题  下一页