分类归档: Programming

编程编程编程。。。

GCC编译优化设置

检查你的gcc版本:

# gcc –version

* 获取你的cpu的型号:

# cat /proc/cpuinfo

* 在/etc/下建立make.conf文件,并根据cpu的型号写入不同内容(注意你的gcc版本必须在3.0以上):

i386 (Intel)

CHOST="i386-pc-linux-gnu"
CFLAGS="-march=i386 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=i386 -O3 -pipe -fomit-frame-pointer"

i486 (Intel)

CHOST="i486-pc-linux-gnu"
CFLAGS="-march=i486 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=i486 -O3 -pipe -fomit-frame-pointer"

Pentium 1 (Intel)

CHOST="i586-pc-linux-gnu"
CFLAGS="-march=pentium -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=pentium -O3 -pipe -fomit-frame-pointer"

Pentium MMX (Intel)

CHOST="i586-pc-linux-gnu"
CFLAGS="-march=pentium-mmx -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=pentium-mmx -O3 -pipe -fomit-frame-pointer"

Pentium PRO (Intel)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=pentiumpro -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=pentiumpro -O3 -pipe -fomit-frame-pointer"

Pentium II (Intel)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=pentium2 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=pentium2 -O3 -pipe -fomit-frame-pointer"

Celeron (Mendocino), aka Celeron1 (Intel)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=pentium2 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=pentium2 -O3 -pipe -fomit-frame-pointer"

Pentium III (Intel)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=pentium3 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=pentium3 -O3 -pipe -fomit-frame-pointer"

Celeron (Coppermine) aka Celeron2 (Intel)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=pentium3 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=pentium3 -O3 -pipe -fomit-frame-pointer"

Celeron (Willamette) (Intel)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=pentium4 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=pentium4 -O3 -pipe -fomit-frame-pointer"

Pentium 4 (Intel)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=pentium4 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=pentium4 -O3 -pipe -fomit-frame-pointer"

Eden C3/Ezra (Via)

CHOST="i586-pc-linux-gnu"
CFLAGS="-march=i586 -m3dnow -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=i586 -m3dnow -O3 -pipe -fomit-frame-pointer"

K6 (AMD)

CHOST="i586-pc-linux-gnu"
CFLAGS="-march=k6 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=k6 -O3 -pipe -fomit-frame-pointer"

K6-2 (AMD)

CHOST="i586-pc-linux-gnu"
CFLAGS="-march=k6-2 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=k6-2 -O3 -pipe -fomit-frame-pointer"

K6-3 (AMD)

CHOST="i586-pc-linux-gnu"
CFLAGS="-march=k6-3 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=k6-3 -O3 -pipe -fomit-frame-pointer"

Athlon (AMD)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=athlon -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=athlon -O3 -pipe -fomit-frame-pointer"

Athlon-tbird, aka K7 (AMD)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=athlon-tbird -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=athlon-tbird -O3 -pipe -fomit-frame-pointer"

Athlon-tbird XP (AMD)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=athlon-xp -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=athlon-xp -O3 -pipe -fomit-frame-pointer"

Athlon 4(AMD)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=athlon-4 -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=athlon-4 -O3 -pipe -fomit-frame-pointer"

Athlon XP (AMD)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=athlon-xp -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=athlon-xp -O3 -pipe -fomit-frame-pointer"

Athlon MP (AMD)

CHOST="i686-pc-linux-gnu"
CFLAGS="-march=athlon-mp -O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-march=athlon-mp -O3 -pipe -fomit-frame-pointer"

603 (PowerPC)

CHOST="powerpc-unknown-linux-gnu"
CFLAGS="-O3 -pipe -fsigned-char"
CXXFLAGS="-O3 -pipe -fsigned-char"

603e (PowerPC)

CHOST="powerpc-unknown-linux-gnu"
CFLAGS="-O3 -pipe -fsigned-char"
CXXFLAGS="-O3 -pipe -fsigned-char"

604 (PowerPC)

CHOST="powerpc-unknown-linux-gnu"
CFLAGS="-O3 -pipe -fsigned-char"
CXXFLAGS="-O3 -pipe -fsigned-char"

604e (PowerPC)

CHOST="powerpc-unknown-linux-gnu"
CFLAGS="-O3 -pipe -fsigned-char"
CXXFLAGS="-O3 -pipe -fsigned-char"

750 aka as G3 (PowerPC)

CHOST="powerpc-unknown-linux-gnu"
CFLAGS="-mcpu=750 -O3 -pipe -fsigned-char -mpowerpc-gfxopt"
CXXFLAGS="-mcpu=750 -O3 -pipe -fsigned-char -mpowerpc-gfxopt"

7400, aka G4 (PowerPC)

CHOST="powerpc-unknown-linux-gnu"
CFLAGS="-mcpu=7400 -O2 -pipe -fsigned-char -maltivec -mabi=altivec -mpowerpc-gfxopt"
CXXFLAGS="-mcpu=7400 -O2 -pipe -fsigned-char -maltivec -mabi=altivec -mpowerpc-gfxopt"

7450, aka G4 second generation (PowerPC)

CHOST="powerpc-unknown-linux-gnu"
CFLAGS="-mcpu=7450 -O2 -pipe -fsigned-char -maltivec -mabi=altivec -mpowerpc-gfxopt"
CXXFLAGS="-mcpu=7450 -O2 -pipe -fsigned-char -maltivec -mabi=altivec -mpowerpc-gfxopt"

PowerPC (If you don’t know which one)

CHOST="powerpc-unknown-linux-gnu"
CFLAGS="-O3 -pipe -fsigned-char -mpowerpc-gfxopt"
CXXFLAGS="-O3 -pipe -fsigned-char -mpowerpc-gfxopt"

Sparc

CHOST="sparc-unknown-linux-gnu"
CFLAGS="-O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-O3 -pipe -fomit-frame-pointer"

Sparc 64

CHOST="sparc64-unknown-linux-gnu"
CFLAGS="-O3 -pipe -fomit-frame-pointer"
CXXFLAGS="-O3 -pipe -fomit-frame-pointer"

好了,这样做后你编译出的程序运行效率将比以前高很多!只要你有时间,你可以把你的系统如 Red Hat Linux 9 的源代码(后缀.src.rpm)全部重新编译一次,你会发现你的Red Hat Linux系统将比原来快一大截!

Read: 1183

C/C++ 经典算法实例

二分查找的代码.

int bfind(int* a,int len,int val)

{

int m = len/2;

int l = 0;

int r = len;

while(l!=m && r!= m)

{

if(a[m] > val)

{

r = m;

m = (m+l)/2;

}

else if(a[m] < val)

{

l = m;

m = (m+r)/2;

}

else

return m;

}

return -1;   //没有找到

}

写出在母串中查找子串出现次数的代码.

int count1(char* str,char* s)

{

char* s1;

char* s2;

int count = 0;

while(*str!=”)

{

s1 = str;

s2 = s;

while(*s2 == *s1&&(*s2!=”)&&(*s1!=’0′))

{

s2++;

s1++;

}

if(*s2 == ”)

count++;

str++;

}

return count;

}

查找第一个匹配子串位置,如果返回的是s1长度len1表示没有找到

size_t find(char* s1,char* s2)

{

size_t i=0;

size_t len1 = strlen(s1)

size_t len2 = strlen(s2);

if(len1-len2<0) return len1;

for(;i        {

size_t m = i;

for(size_t j=0;j            {

if(s1[m]!=s2[j])

break;

m++;

}

if(j==len)

break;

}

return i    }

写出快速排序或者某种排序算法代码

快速排序:

int partition(int* a,int l,int r)

{

int i=l-1,j=r,v=a[r];

while(1)

{

while(a[++i]        while(a[–j]>v) if(j<=i) break;

if(i>=j)

break;

swap(a[i],a[j]);

}

swap(a[i],a[r]);

return i;

}

void qsort(int* a,int l,int r)

{

if(l>=r) return;

int i = partition(a,l,r);

qsort(a,l,i-1);

qsort(a,i+1,r);

}

冒泡排序:

void buble(int *a,int n)

{

for(int i=0;i    {

for(int j=1;j        {

if(a[j]            {

int temp=a[j];

a[j] = a[j-1];

a[j-1] = temp;

}

}

}

}

插入排序:

void insertsort(int* a,int n)

{

int key;

for(int j=1;j    {

key = a[j];

for(int i=j-1;i>=0&&a[i]>key;i–)

{

a[i+1] = a[i];

}

a[i+1] = key;

}

}

出现次数相当频繁

实现strcmp函数

int strcmp11(char* l,char* r)

{

assert(l!=0&&r!=0);

while(*l == *r &&*l != ”) l++,r++;

if(*l > *r)

return 1;

else if(*l == *r)

return 0;

return -1;

}

实现字符串翻转

void reserve(char* str)

{

assert(str != NULL);

char * p1 = str;

char * p2 = str-1;

while(*++p2);         //一般要求不能使用strlen

p2 -= 1;

while(p1    {

char c = *p1;

*p1++ = *p2;

*p2– = c;

}

}

将一个单链表逆序

struct list_node

{

list_node(int a,list_node* b):data(a),next(b) //这个为了测试方便

{}

int data;

list_node* next;

};

void reserve(list_node* phead)

{

list_node* p = phead->next;

if(p == NULL || p->next == NULL) return; //只有头节点或一个节点

list_node* p1=p->next;

p->next=NULL;

while(p1!=NULL)

{

p = p1->next;

p1->next = phead->next;

phead->next = p1;

p1 = p;

}

}

测试程序:

list lt;

lt.phead = new list_node(0,0);

lt.phead->next = new list_node(1,0);

lt.phead->next->next = new list_node(2,0);

lt.phead->next->next->next = new list_node(3,0);

lt.reserve();

list_node * p = lt.phead;

while(p)

{

cout<data<        p = p->next;

}

循环链表的节点对换和删除。

//双向循环

list_node* earse(list_node* node)

{

// if(node == rear) return node->next;    //对于头节点可判断也可不判断。最好加上

list_node* next = node->next;

next->prev = node->prev;

node->prev->next = next;

delete node;

retrun next;

}

//单项循环

list_node* earse(list_node* node)

{

// if(node == rear) return node->next;    //对于头节点可判断也可不判断。最好加上

list_node* p = rear;

while(p->next != node) p=p->next;

p->next = node->next;

delete node;

retrun p->next;

}

将一个数字字符串转换为数字.”1234″ –>1234

int atoii(char* s)

{

assert(s!=NULL);

int num = 0;

int temp;

while(*s>’0′ && *s<‘9’)

{

num *= 10;

num += *s-‘0’;

s++;

}

return num;

}

出现次数相当频繁

.实现任意长度的整数相加或者相乘功能。

void bigadd(char* num,char* str,int len)

{

for(int i=len;i>0;i–)

{

num[i] += str[i];

int j = i;

while(num[j]>=10)

{

num[j–] -= 10;

num[j] += 1;

}

}

}

.写函数完成内存的拷贝

void* memcpy( void *dst, const void *src, unsigned int len )

{

register char *d;

register char *s;

if (len == 0)

return dst;

if ( dst > src )   //考虑覆盖情况

{

d = (char *)dst + len – 1;

s = (char *)src + len – 1;

while ( len >= 4 )   //循环展开,提高执行效率

{

*d– = *s–;

*d– = *s–;

*d– = *s–;

*d– = *s–;

len -= 4;

}

while ( len– )

{

*d– = *s–;

}

}

else if ( dst < src )

{

d = (char *)dst;

s = (char *)src;

while ( len >= 4 )

{

*d++ = *s++;

*d++ = *s++;

*d++ = *s++;

*d++ = *s++;

len -= 4;

}

while ( len– )

{

*d++ = *s++;

}

}

return dst;

}

出现次数相当频繁

编写类String的构造函数、析构函数和赋值函数,已知类String的原型为:

class String

{

public:

String(const char *str = NULL); // 普通构造函数

String(const String &other); // 拷贝构造函数

~ String(void); // 析构函数

String & operate =(const String &other); // 赋值函数

private:

char *m_data; // 用于保存字符串

};

解答:

//普通构造函数

String::String(const char *str)

{

if(str==NULL)

{

m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志”的空

//加分点:对m_data加NULL 判断

*m_data = ”;

}

else

{

int length = strlen(str);

m_data = new char[length+1]; // 若能加 NULL 判断则更好

strcpy(m_data, str);

}

}

// String的析构函数

String::~String(void)

{

delete [] m_data; // 或delete m_data;

}

//拷贝构造函数

String::String(const String &other)    // 得分点:输入参数为const型

{

int length = strlen(other.m_data);

m_data = new char[length+1];     //加分点:对m_data加NULL 判断

strcpy(m_data, other.m_data);

}

//赋值函数

String & String::operate =(const String &other) // 得分点:输入参数为const型

{

if(this == &other)                   //得分点:检查自赋值

return *this;

delete [] m_data;               //得分点:释放原有的内存资源

int length = strlen( other.m_data );

m_data = new char[length+1];  //加分点:对m_data加NULL 判断

strcpy( m_data, other.m_data );

return *this;            //得分点:返回本对象的引用

}

剖析:

能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!

在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求,也是《Effective C++》中特别强调的条款。

实现strcpy

char * strcpy( char *strDest, const char *strSrc )

{

assert( (strDest != NULL) && (strSrc != NULL) );

char *address = strDest;

while( (*strDest++ = * strSrc++) != ‘’ );

return address;

}

编写一个函数,作用是把一个char组成的字符串循环右移n个。比如原来是“abcdefghi”如果n=2,移位后应该是“hiabcdefgh”

函数头是这样的:

//pStr是指向以”结尾的字符串的指针

//steps是要求移动的n

void LoopMove ( char * pStr, int steps )

{

//请填充…

}

解答:

正确解答1:

void LoopMove ( char *pStr, int steps )

{

int n = strlen( pStr ) – steps;

char tmp[MAX_LEN];

strcpy ( tmp, pStr + n );

strcpy ( tmp + steps, pStr);

*( tmp + strlen ( pStr ) ) = ”;

strcpy( pStr, tmp );

}

正确解答2:

void LoopMove ( char *pStr, int steps )

{

int n = strlen( pStr ) – steps;

char tmp[MAX_LEN];

memcpy( tmp, pStr + n, steps );

memcpy(pStr + steps, pStr, n );

memcpy(pStr, tmp, steps );

}

Read: 1808

优化 PHP 建议

src: http://www.phpchina.com/78/viewspace_25713.html

1.如果一个方法可静态化,就对它做静态声明。速率可提升至4倍。

2.echo 比 print 快。

3.使用echo的多重参数(译注:指用逗号而不是句点)代替字符串连接。

4.在执行for循环之前确定最大循环数,不要每循环一次都计算最大值。

5.注销那些不用的变量尤其是大数组,以便释放内存。

6.尽量避免使用__get,__set,__autoload。

7.require_once()代价昂贵。

8.在包含文件时使用完整路径,解析操作系统路径所需的时间会更少。

9.如果你想知道脚本开始执行(译注:即服务器端收到客户端请求)的时刻,使用$_SERVER[‘REQUEST_TIME’]要好于time()。

10.函数代替正则表达式完成相同功能。

11.str_replace函数比preg_replace函数快,但strtr函数的效率是str_replace函数的四倍。

12.如果一个字符串替换函数,可接受数组或字符作为参数,并且参数长度不太长,那么可以考虑额外写一段替换代码,使得每次传递参数是一个字符,而不是只写一行代码接受数组作为查询和替换的参数。

13.使用选择分支语句(译注:即switch case)好于使用多个if,else if语句。

14.用@屏蔽错误消息的做法非常低效。

15.打开apache的mod_deflate模块。

16.数据库连接当使用完毕时应关掉。

17.$row[‘id’]的效率是$row[id]的7倍。

18.错误消息代价昂贵。

19.尽量不要在for循环中使用函数,比如for ($x=0; $x < count($array); $x)每循环一次都会调用count()函数。

20.在方法中递增局部变量,速度是最快的。几乎与在函数中调用局部变量的速度相当。

21.递增一个全局变量要比递增一个局部变量慢2倍。

22.递增一个对象属性(如:$this->prop++)要比递增一个局部变量慢3倍。

23.递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。

24.仅定义一个局部变量而没在函数中调用它,同样会减慢速度(其程度相当于递增一个局部变量)。PHP大概会检查看是否存在全局变量。

25.方法调用看来与类中定义的方法的数量无关,因为我(在测试方法之前和之后都)添加了10个方法,但性能上没有变化。

26.派生类中的方法运行起来要快于在基类中定义的同样的方法。

27.调用带有一个参数的空函数,其花费的时间相当于执行7至8次的局部变量递增操作。类似的方法调用所花费的时间接近于15次的局部变量递增操作。

28.用单引号代替双引号来包含字符串,这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会。当然,只有当你不需要在字符串中包含变量时才可以这么做。

29.输出多个字符串时,用逗号代替句点来分隔字符串,速度更快。注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册中说echo是语言结构,不是真正的函数,故把函数加上了双引号)。

30.Apache解析一个PHP脚本的时间要比解析一个静态HTML页面慢2至10倍。尽量多用静态HTML页面,少用脚本。

31.除非脚本可以缓存,否则每次调用时都会重新编译一次。引入一套PHP缓存机制通常可以提升25%至100%的性能,以免除编译开销。

32.尽量做缓存,可使用memcached。memcached是一款高性能的内存对象缓存系统,可用来加速动态Web应用程序,减轻数据库负载。对运算码 (OP code)的缓存很有用,使得脚本不必为每个请求做重新编译。

33. 当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数。此函数执行起来相当快,因为它不做任何计算,只返回在zval 结构(C的内置数据结构,用于存储PHP变量)中存储的已知字符串长度。但是,由于strlen()是函数,多多少少会有些慢,因为函数调用会经过诸多步 骤,如字母小写化(译注:指函数名小写化,PHP不区分函数名大小写)、哈希查找,会跟随被调用的函数一起执行。在某些情况下,你可以使用isset() 技巧加速执行你的代码。

(举例如下)
if (strlen($foo) < 5) { echo "Foo is too short"; }
(与下面的技巧做比较)
if (!isset($foo{5})) { echo "Foo is too short"; }

调用isset()恰巧比strlen()快,因为与后者不同的是,isset()作为一种语言结构,意味着它的执行不需要函数查找和字母小写化。也就是说,实际上在检验字符串长度的顶层代码中你没有花太多开销。

34. 当执行变量$i的递增或递减时,$i++会比++$i慢一些。这种差异是PHP特有的,并不适用于其他语言,所以请不要修改你的C或Java代码并指望它 们能立即变快,没用的。++$i更快是因为它只需要3条指令(opcodes),$i++则需要4条指令。后置递增实际上会产生一个临时变量,这个临时变 量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种,正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为一个好主意,因为并不 是所有的指令优化器都会做同样的优化处理,并且存在大量没有装配指令优化器的互联网服务提供商(ISPs)和服务器。

35.并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。

36.并非要用类实现所有的数据结构,数组也很有用。

37.不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?

38.当你需要时,你总能把代码分解成方法。

39.尽量采用大量的PHP内置函数。

40.如果在代码中存在大量耗时的函数,你可以考虑用C扩展的方式实现它们。

41.评估检验(profile)你的代码。检验器会告诉你,代码的哪些部分消耗了多少时间。Xdebug调试器包含了检验程序,评估检验总体上可以显示出代码的瓶颈。

42.mod_zip可作为Apache模块,用来即时压缩你的数据,并可让数据传输量降低80%。

Read: 927

[转]重构之美-走在Web标准化设计的路上[深入结构:合理运用div和span。]

src:http://yuntian.cnblogs.com/archive/2006/03/27/359542.html

特意上网搜索了一下,关于div,说法很多。

把div看成是布局元素这种观点我想是最多的,类似有“用div代替table进行布局”、“实战CSS+DIV布局”等等等等,太多了,还有不少 人延用Dreamweaver的定义,称div为层,按Photoshop的层的概念来使用……有朋友干脆就直接称div和span为辅助布局元素。

怎么说呢?虽然我很想说对div类似的这种认识是错误的,div不是一个布局元素,没有一个tag是用来布局的,但是我是对的吗?我也不知道。几乎 所有人对div的宣传都是布局,不管是‘民间’的还是‘官方’的,但是如果我们找根源,中文中,div是一个结构化标签,是一个块级元素。好吧,我们首先 看看div拥有的语义,division(分隔),按语义它的作用是将两个部分分隔开来。然后我们再回到w3去看看怎么定义div和span的:The DIV and SPAN elements, in conjunction with the id and class attributes, offer a generic mechanism for adding structure to documents. These elements define content to be inline (SPAN) or block-level (DIV) but impose no other presentational idioms on the content.

注意到我上面加粗的一句话了吗?W3可没说是 for layout,而是for structure,是结构!因为分隔从而产生(定义)一个代码结构。我想,结构和布局应该是两个概念吧。或许,因为table确实被用于布局了,所以这 种根深蒂固的布局思路又自然而然的转嫁到div上,我曾在很长一段时间里也是这么理解的。但是,现在我要说,这绝对是一个错误并且,这是极度严重的错误!!!这纯粹个人观点个人理解,自己取舍好了。

为什么严重?理解的错误直接导致的就是使用的错误。因为如果按照这个思路,把div作为布局元素使用,那么我认为:

你永远无法固定xhtml!永远陷在css的怪圈中!永远不会去思考和理解结构!永远擦不干净table烙下的痕迹!永远无法接近神(貌合神离的神哈,呵呵)……

或许把div称为布局元素还是为了更好的推行标准,但是却将人们从一个错误带向了另一个错误。两年前我刚接触标准时就在《重构之美》首篇中迷惑过关于改版的事情,虽然随着理解的深入好像有了突破,在我写下xhtml后不变动,然后通过css的技巧来完成新版面。比如像著名的csszengarden。但是很快我又有新的迷惑,一个人这样做好像没什么问题,团队呢?比如如果同样的内容,设计成两个版式,然后交给不同的两个人来写xhtml,会一样吗?就像如果把csszengarden的 形式颠倒一下,基于同一份数据先做好100个设计稿,让100个人按照这个设计稿写100份xhtml,会一样吗?我想按照div布局模式,对于同样的版 式,不同人不同的页面分析都会产生不同的xhtml,更何况不同的版式呢?但是既然表现与结构无关,那么同样的内容不应该有2份以上的xhtml。不要小 看这个问题,对于团队中前后台的有效分离与快速协同,这是关键!我在培训中提出一个观点:最理想的境界是前台闭着眼睛都能知道后台输出的是什么样的xhtml结构代码。那么问题出在哪里?div布局!尤其是在理解了h系列标签不合理之后,体会更深刻。

上篇文章我提出的关于结构应当分为两种:语义结构代码结构。理解了这两个 结构之后,那么div的用处就比较明朗了,稍稍动动脑筋就能想到,用于组织代码结构。所以hx标签的问题我认为经典呢,不要说html了,即便对于 xhtml,大部分的人关心的仍是如何表现,小部分人关心语义结构,很少人去关心代码结构,似乎xml有了,xhtml就不需要代码结构了。但是从hx系 列的问题可以看出并延伸知道W3可一直在关心代码结构,从1.0,1.1直到2.0,一直希望xhtml拥有xml般严谨的代码结构。说到这里再多看 xhtml 2.0的另一个变化,br不再被推荐,应该很好理解了,br的语义是产生一个截断(break),但实际作用是产生一个行,语义结构上仍不完美,所以使用 line进行替代<line>this is one line</line>。同样br也无代码结构可言,如果我想提取第三行的数据如何操作?所以很有可能类似br、hr这类标签都将被废弃。我 琢磨着,xhtml1.x是W3清理表现,将人们往语义结构[Semantic]的方向牵引,而xhtml 2.0则是展示和突出代码结构[structure]。呵呵,您说我琢磨得对吗?瞎猜瞎猜。^_^

回过头来,那么怎么组织?首先对于一个设计稿,一定要不被设计所迷惑和左右,只提取看得见和看不见的数据,然后就扔掉设计稿,先完成数据的语义结构,再添加代码结构(adding structure to documents.), 完成xhtml后,最后一步才是重新拾起设计稿打开css,还原。当然实际做的时候不可能不看设计稿,但是怎么看?只提数据!再说一点,数据在文档中的先 后顺序由什么定?当然是由文档而定,不是由设计稿所定。举个例子,假如有两个栏目,新闻头条和普通新闻。谁在前谁在后,很显然在文档中应该是头条在前普通 在后,这是由UE(用户体验)和栏目轻重的综合考虑决定。但是按照div布局的话,是按照设计稿上前下后左前右后的顺序来决定的,那么如果设计稿中将普通 新闻栏目设计在左栏,头条设计在中栏,文档中普通新闻就跑到头条新闻上面去了。所以我打开一个Web标准站点文档浏览,如果文档的先后顺序是按照页面布局 上前下后,左前右后的顺序而定的,那么我……特例一点,如果一个单屏设计的网站,标题和导航设计在页面下方,那你的文档岂不是最下面才是标题和导航,这是 什么UE?这不是扯蛋嘛。div,div布局的恶果——文档结构仍然在为表现所左右!貌合神离!!

代码结构怎么做?大处按照上篇文章所写,用h系列划分大结构。那么小处呢?这里就要牵涉进div的另外一个概念:块级元素。什么块?模块!用div模块化小处。举例:

<div>
    
<h3><span>用户登陆</span></h3>
    
<div>
       
<label for="name">用户名</label>
       
<input id="name" />
    
</div>
    
<div>
        
<label for="pw">密码</label>
        
<input id="pw" />
    
</div>
    
<p><button /></p>
</div>

这个在[复杂表单]中 提到过的例子,我们来详细分析div在小处如何模块化运用。其实很简单,h3/lable/p是语义结构,然后,对于用户名和相应的输入框显然是不可分割 的整体,那么好了,div将其标识为一个块,对应的密码部分同理。最后,两者一起与标题和按钮又构成一个不可分割的登陆整体,div之。这样拥有很好的语 义结构和代码结构。好的代码结构不仅仅可以便于固定xhtml,便于程序操作节点,还对css提供了很高的自由度。如上例结构,我只需要给最外div一个 class,比如"loginarea"。那么:

我可以这么按节点/路径层层定义下去:.loginarea label{} .loginarea input{} .loginarea div label{} .loginarea div input。如果我需要横向登陆,只需要定义一个关键点:.loginarea div{float: left},如果纵向则去掉这个关键点,模块化的登陆就这么简单。这样还可以省写不少class,尤其对于有些看似复杂的结构其实模块化设计好了,模块内 部是简单的,一个路径定义过去,根本无需class还不会引起样式冲突和干扰,css的可读性也很好。当然这里会涉及到css的技巧,我认为css的技巧 最重要的就是分析页面,页面分析的好,写出来的css简单明了充分利用tag还有多以备扩展,否则class一大堆复杂冗长还会觉得tag不够用又去添加 破坏结构。复杂表单那套系统的css我写了48k,还未做最后优化,全部图片总共只有5K,还全是无损PNG格式。整套系统几十个大模块,又有无限级菜 单、树、页签、弹出,复杂表单,合同,frame,iframe,报表,控件套控件等等乱七八糟什么都有,css加图片全部表现部分可以做到50K以内。 这个项目四个程序员一起开发我一个人顶所有前台,三个月时间,程序员不管任何有关表现部分,我都是玩玩做做就搞定了。中后期,临着交付客户时候我还觉得公 司提供的设计不好,又自己花1天重新设计,花不到2天另外写了一个css,整个系统全变了且以前的设计未丢失。功能不变的情况下界面大换,再大的系统也不 过一个人几天时间,且程序员不用管。这就是Web标准的威力之一!(因为是内网应用,所以我几乎没考虑和照顾浏览器兼容性,没必要,也是快的一个因素)

所以我认为当前各大网站上以各种方式事先列出什么单行一列,两行一列诸如此类的几行几列的div+css布局代码,不好说他们不对,你完全可以去理 解是如何使用css实现几行几列的布局,然后合理运用到自己的结构上。但是如果你按照他提供的代码去套、去添加内容,那么你就错了。不过话说回来,在被一 篇一篇标题着斗大的“布局”两个字的潜移默化下,您还有心思去关心结构吗?所以很多都去琢磨css了,所以这些善意的Web标准推广者还是有错的,包括我 在内,我2004年撰写的《重构之美》代码示例部分带有更大的误导性(好在当初我一再强调代码毫无借鉴的意义,也算在文字上有所弥补)。现在呢?我也不知 道,在路上,在路上……

写很多了,span的合理运用留给Update吧。

2006 3 24-25

Read: 709

[转] 让FireBug 工作于 Firefox 3

src:http://devlicio.us/blogs/brendantompkins/archive/2007/11/20/getting-firebug-to-work-with-firefox-3-beta-1.aspx

Getting FireBug to work with FireFox 3 Beta 1

Just grabbed my copy of FireFox 3 Beta 1 today.. After installation, most of the extensions that I’ve come to rely on aren’t working, which is understandable. One extension, FireBug, is a tool that I simply cannot work without. It’s the best tool I’ve ever found for debugging HTML, CSS, HTTP and JavaScript, bar none. If you’re a web developer working without it, you may find that you’re spending way more time than you have to debugging browser issues.

The problem is, when I tried to install it under FF3, I got the message that it would not run… Here are the steps I took to fix this.

  1. Saved the firebug-1.05-fx+fl.xpi file to disk
  2. Re-named it to firebug-1.05-fx+fl.zip
  3. Opened the zip file, and extracted the file “install.rdf”
  4. Opened “install.rdf” with Notepad
  5. Changed <em:maxVersion>2.0.0.*</em:maxVersion> to <em:maxVersion>3.0.0.*</em:maxVersion>
  6. Saved the file, and replaced the version in the zip file with the new version
  7. Renamed the .zip file back to firebug-1.05-fx+fl.xpi
  8. Drag-drop firebug-1.05-fx+fl.xpi into an instance of FF3.

Voila! I have FireBug with FF3! You can also try this with other extensions, but your mileage may vary.

-Brendan

Read: 915