小规则让你写出漂亮又高效的程序

本文来自肥宝游戏,引用必须保留文末二维码!!!

好几天没写文章了,周一整理自己刚修好的旧电脑,发现一本书《高质量C++编程指南》。因为最近在写游戏服务端的战斗,所以这个立刻就吸引肥宝了。看了几天,深深感觉获益良多啊。于是把笔记和自己的经验写下来,分享给大家。

一、写出漂亮易读的程序

中学时代上课很喜欢做笔记,但是肥宝几乎没看过自己的笔记,不是肥宝懒,是因为肥宝字太丑了。

后来成为一个程序员,以为这些代码都是电脑输出,统一字体,就不用这么纠结了。谁知道代码更需要写得漂亮,因为需求是不断在变化的,bug也是不断地涌现。无论出于工作还是学习,你总会经常看回自己写的代码,比起中学时代看自己的笔记的概率高多了。

可能一个功能,在开始的时候会经常看到,不会觉得难看,但是一周之后呢?一个月后呢?一年后呢?更离谱的是,有一次肥宝收到一个以前的工作的人的电话,问肥宝代码的问题,那个时候肥宝都离职了几个月了。就算现在,旧的游戏依然会有新的人维护,他们经常拿肥宝一两年前写的代码来问肥宝。肥宝觉得维护一些写得丑的代码,跟自己每天被迫跟一个300斤的大肉参来个法式湿吻那么恐怖。

怎样才算漂亮的代码,怎样才算丑的代码?下面给出一些小规则:

文档的结构:

【1】头文件用来声明,cpp文件用来定义。声明和定义分开,不但可以让代码更清晰、方便阅读,同时,如果在某些场合,代码不能公开,只向用户提供头文件和二进制的库即可。通常这样的情况下,头文件和源文件是在不同目录的

【2】为了防止头文件被重复引用,应当用 ifndef/define/endif 结构产生预处理块。这个宏定义必须讲究,如果重复了,可能会出现莫名其妙的问题。肥宝个人习惯是工程名+目录+文件名。

例如:

#ifndef _GateApp_Role_Player_H_
#define _GateApp_Role_Player_H_
//代码实现在这里。。。
#endif  

【3】用#include<file>引用标准库头文件(编译器从标准库目录开始搜索),用#include"file.h"引用其他文件(编译器从工作目录开始搜索)

【4】一般情况下h文件只写声明,不写定义。写内联函数时不要包含for,递归等复杂操作,不要超过5行。因为消耗很大,而且调试不方便。

【5】尽量少用局部变量。

【6】按照实际意义区分目录,一个目录内超过10个文件,要考虑是否拆分。

程序的风格:

良好的格式有助于阅读和维护。一般情况下,我们使用的IDE,入Visual Studio、Eclipse、XCode等,本身生成的代码都是符合良好的风格的,尽量使用代码提示功能,有助于形成良好风格。肥宝平时用得比较多的是Visual Studio,所以下面的风格也是这个软件的。

【7】在每个类声明之后加空行,每个函数定义结束之后都要加空行。

【8】在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。

【9】一行代码只做一件事情,只定义一个变量,只写一条语句。这样的代码容易阅读,并且方便于写注释。

【10】if 、for 、while 、do  等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加 {}。这样可以防止书写失误。

【11】尽可能在定义变量的同时初始化该变量(就近原则),放久了很容易忘记。

不良风格的代码:

int attack, defense, life; // 攻击、防御、生命,同时声明多个变量,没有初始化
int hurt= attack - defense;   life -= hurt; //执行多条语句
if (life < 0) onDeath();
for (int i = 0;  i < 10; i++)  findNext();
processNext();  

良好风格的代码:

int attack = 0; // 攻击
int defense = 0; // 防御 --跟上下联系紧密,不加空行
int life = 0; // 生命    

int hurt= attack - defense;
life -= hurt;

if (0 >= life)
 {
    onDeath();
 }  

for (int i = 0;  i < 10; i++)
{
      findNext();
}                                                     

processNext();  

【12】关键字之后要留空格。

例如 const 、virtual 、inline 、case  等关键字之后至少要留一个空格,否则无法辨析关键字。

例如 if 、for 、while 等关键字之后应留一个空格再跟(,以突出关键字。

【13】函数名之后不要留空格,紧跟‘(‘,以与关键字区别。‘(‘向后紧跟,右括号、逗号、分号向前紧跟,紧跟处不留空格。,之后要留空格,如Function(x,  y,  z) 。如果‘; ’不是一行的结束符号,其后要留空格,如 for (int i = 0;  i < 10; i++)

【14】赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符, 如“= ”、“+= ”      “>= ”、“<= ”、“+ ”、“* ”、“% ”、“&& ”、“||”、“<< ”,  “^ ”等二元操作符的前后应当加空格。

【15】一元操作符如“!”、“~ ”、“++ ”、“-- ”、“& ”(地址运算符)等后不加空格。

【16】“[]”、“.”、“->”这类操作符前后不加空格。

【17】对于表达式比较长的 for 语句和 if 语句,为了紧凑起见可以适当地去掉一些空格。

如 for (i=0; i<10; i++)和 if ((a<=b) && (c<=d)) ,或者太长的话可以适当换行。

void Func1(int x, int y, int z);          //  良好的风格  

 void Func1 (int x,int y,int z);           // 不良的风格  

 if (year >= 2000)                         //  良好的风格  

 if(year>=2000)                            // 不良的风格  

 if ((a>=b) && (c<=d))                     //  良好的风格  

 if(a>=b&&c<=d)                            // 不良的风格  

 for (i=0; i<10; i++)                      //  良好的风格  

 for(i=0;i<10;i++)                         // 不良的风格  

 for (i = 0; I < 10; i ++)                 // 过多的空格  

 x = a < b ? a : b;                        //  良好的风格  

 x=a<b?a:b;                                // 不好的风格  

 int *x = &y;                              //  良好的风格    

 int * x = & y;                            // 不良的风格    

 array[5] = 0;                             // 不要写成 array [ 5 ] = 0;  

 a.Function();                             // 不要写成 a . Function();  

 b->Function();                            // 不要写成 b -> Function();  

【18】程序的分界符‘ {’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。

这个是C++的风格,java的风格是{紧跟出现前的代码

【19】 { }之内的代码块在‘{’右边一个制表符处左对齐。

不良风格:

void Function(int x){
 // program code
    }
 if (condition){
    }
else{
}

for (initialization; condition; update){
// program code
    }

while (condition){
    }

良好风格的代码

void Function(int x)
{
     // program code
}                                                       

if (condition)
{
    // program code
}
else
{
     // program code
}  

for (initialization; condition; update)
{
     // program code
}  

While (condition)
{
    ?// program code
}

如果出现嵌套的{},则使用缩进(按Tab键)对齐,如:

{
    {  

    }
}  

【20】代码行最大长度宜控制在 70 至 80 个字符以内。代码行不要过长,否则要拉来拉去很麻烦

【21】长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整齐,语句可读。表达式内尽量不要套多层表达式。

if ((crit >= 100)
&& (block <= 100)
&& (wreck <= 100))
{
    attack *= 2;
}

virtual CPoint changeToNewPoint(CPoint attackPoint,
                                CPoint defensePoint);

for (SeqCPlayer::iter iter = player.begin();
    iter != player.end();
    iter++)
{
    check();
}

注释

程序块的注释常采用“/*…*/”,行注释一般采用“ //…”。

【22】注释是对代码的“提示”,而不是文档。注释风格统一。

【23】 如果代码本来就是清楚的,则不必加注释。

【24】边写代码边注释,改代码后要同时修改注释

【25】 注释应当准确、易懂,防止注释有二义性。 错误的注释有害。

【26】 尽量避免在注释中使用缩写,特别是不常用缩写。

【27】 注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。在VS中,在上方注释后,下面所有代码的提示都受到影响的,所以优先放后方

【28】 当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处加注释,便于阅读。

【29】 对于思路复杂的代码,可以把思路写在注释里面,否则别人看起来很蛋疼。另外一些设计思想也应该写下来。

对于一些业务多变,而且往往不合常理的需求,一定要多写注释。例如游戏代码中,很多策划特意要求做的特殊处理,有的是为了坑玩家,更多的是为了体验。这东西看代码是看不到任何思路的。当你发现某个地方明明可以用很简洁的代码写,却硬是要用一些很傻比的方法的时候,很可能不是那个人没经验或者偷懒,而是策划要求造成的。所以像游戏这种系统,一定要多谢注释,但改的时候一定要跟着改,否则,呵呵呵呵呵呵呵呵呵呵呵。

类的风格

【30】 类的public函数写在前面,private数据写在后面。不要把什么都往一个类里面扔,要注意这个类本身的含义。

命名

命名并没有统一的标准!很多公司都有自己的一套标准。

【31】标识符应该可以望文生义,长度尽量小,信息尽量大

【32】 命名规则尽量跟系统风格保持一致

【33】 不要出现紧靠大小写区分的标识

【34】 尽量不要出现标识符完全相同的局部变量和全局变量

【35】 同一个项目的代码下,即使在不同工程内,也不要出现完全相同的文件名称,这是VS的一个bug,调试起来会在同名文件间跳来跳去。

【36】 变量的名字应使用名词或者形容词+名词,函数的名字应该使用动词或者动词+名词

【38】 使用反义词去命名互斥意义的变量或函数

【39】 尽量避免使用数字

下面是肥宝所在的项目的一些规范:

(1)类名开头大写,结构以S开头,类以C开头,数组用Seq开头,字典类型用Dict开头,指针用Ptr结尾。

(2)变量和参数用小写开头,之后每个单词开头大写。变量名一般就不加类名这些前缀后缀了。

游戏代码的命名是个蛋疼的事情,作为游戏程序员,碰到的很多名词是无法翻译的。例如诛邪、神兽、涅槃、貔貅、修为、境界、法力,很多很多,有些时候你可能翻译了一个单词出来,过几天一个新的功能,你会发现意义好像差不多的。这个时候我们经常会用拼音,通俗易懂啊。

还有个更蛋疼的事情,游戏的功能是多变的,策划的需求一天一个样,例如某个货币叫做荣誉,做好了功能,过几天这个荣誉要改名为修为,另外的地方突然有个货币叫做荣誉。这个时候你不得不跟着把名称也改掉。否则过一个星期,没几个人看得懂,而且跟客户端,PHP后台,运营等交流也很蛋疼,大家无法同步。所以,命名的时候不一定要按他们给出来的来命名,最好用一些跟中性的而又不违反语义的单词,另外自己弄一张汉语-英文-功能对照表。还有文档的功能名称通常跟上线后的功能名称完全不同的。

二、从习惯开始优化程序的性能

表达式和基本语句

【40】如果代码行中的运算符比较多,用括号确定表达式的操作顺序,避免 使用默认的优先级。

【41】 不要编写太复杂的复合表达式。

i = a >= b && c < d && c + f <= g + h ; // 复合表达式过于复杂

【42】不要有多用途的复合表达式。

d = (a = b + c) + r ;

【43】不要用数学表达式的方法来写程序中的表达式

if (a < b < c) // a < b < c 是数学表达式而不是程序表达式
//并不表示
if (( a < b ) && ( b < c ))
//而成了
if ( (a <b) < c))

【44】不可将布尔变量直接与 true、false 、 1、0 进行比较。

bool isPlayer  = ture;
if (flag) // 表示 flag 为真
if (!flag) // 表示 flag 为假
//其它的用法都属于不良风格,例如:
if (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)

【45】应当将整型变量用“==”或“!=”直接与 0 比较。而且最好把0写在左边,其他数字也是

int life = 0;
if ( 0 == life)
if ( 0 != life )
if ( life == 0 )//容易写成 if ( life = 0 ),而且不会报错
//不可模仿布尔变量的风格而写成
if (value) // 会让人误解 value 是布尔变量
if (!value)

【46】不可将浮点变量用“==”或“!=”与任何数字比较。 因为float和double都有精度限制。

double x = 0;
if ( 0.0 == x )//隐含错误的比较
if ((x >= -EPSINON) && (x <= EPSINON)) //其中 EPSINON 是允许的误差(即精度)。

【47】指针变量与Null比较,最好不直接写。(其实肥宝一直习惯直接)

//推荐:
if (p == NULL) // p 与 NULL 显式比较,强调 p 是指针变量 i
if (p != NULL)
//不推荐
if (p == 0) // 容易让人误解 p 是整型变量
if (p != 0)
if (p) // 其实肥宝推荐这个,写这么久难道不知道这是指针么。
if (!p)

循环语句的使用

【48】长循环放里面,短循环放外面,因为会打断循环体,

#include "Test/TestManager.h"
#include "Map/Point.h"
#include <time.h>
#include <iostream>
#include <math.h>

using namespace CppServer;

void doSomething()
{
    SPoint p;
    p.x = 1;
    p.y = 1;
    int dist = p.x * p.x + p.y * p.y;
    dist += p.x;
    dist += p.y;
    dist = (int)sqrt(dist);
    SPoint p2;
}
void CppServer::CTestManager::test1()
{
    int n = 100;
    for (int m = 100; m <= 100000; m += 1000) {
        {
            clock_t startTime = clock();//开始时间
            for (int i = 0; i <= m; i++) {
                for (int j = 0; j <= n; j++) {
                    doSomething();
                }
            }

            clock_t endTime = clock();//结束时间
            std::cout << "多重循环1 i :" << m <<" j:"<<n << " time:" << (endTime - startTime) << std::endl;
        }

        {
            clock_t startTime = clock();//开始时间
            for (int i = 0; i <= n; i++) {
                for (int j = 0; j <= m; j++) {
                    doSomething();
                }
            }

            clock_t endTime = clock();//结束时间
            std::cout << "多重循环2 i :" << n << " j:" << m << " time:" << (endTime - startTime) << std::endl << std::endl;
        }
    }
}

为了验证这个效率具体差别到什么程度,写了一段测试代码,发现上万次循环的时候才有几毫秒的差别,可能dosomething函数太简单的原因。不过肥宝觉得有些时候比较难把短循环抽出去的话,就没必要太刻意了。

【49】不可在 for 循环体内修改循环变量,防止 for 循环失去控制。尤其注意erase的用法

我们游戏服务端宕机有一半是这个引起的,每次新人来了都跟他们说,说了还是会犯错。

typedef std::vector<CPoint> SeqCPoint;
typedef std::map<int, CPoint> MapCPoint;
SeqCPoint points;
MapCPoint pointMap;
for (SeqCPoint::iter iter = points.begin();
    iter != points.end();
    )
{
    if(xxx)
    {
        points.erase(iter);//erase后,指针会跳到下一个
    }
    else
    {
        iter ++;
    }
}

for (MapCPoint::iter iter = pointMap.begin();
    iter != pointMap.end();
    iter ++;)
{
    if(xxx)
    {
        pointMap.erase(iter);//erase不需要特殊处理
    }
}

【50】 switch语句中每个case后面必须加break,必须加defualt。

【51】 少用慎用goto。

肥宝觉得,业务层的代码,直接禁用吧!

常量

【52】尽量使用常量来表示程序中经常出现的数字或字符串

const float PI = 3.14159; // C++ 语言的 const 常量

【53】 需要对外公开的常量放在头文件,内部使用的放在源文件。

很多人喜欢把常量放在同一个文件中,但是多了之后改动一下,多个地方要编译。我们游戏曾经加一个错误码要编两个小时,后面改成配置了,这个自己把握吧。

函数

【54】函数声明是,参数要写完整,命名要恰当。

【55】 参数最好加上&,可以大量节省对象构造和析构的时间。

SPoint CMapManager::changeAbsolute2Relative(SPoint& originPoint, SPoint& changePoint)
{
    SPoint rePoint;
    rePoint.x = changePoint.x - originPoint.x;
    rePoint.y = changePoint.y - originPoint.y;
    return rePoint;
}  

就这样一个函数,没加&的时候,执行时间是现在的三倍,可以看肥宝前一篇文章MMO游戏技能攻击区域的计算3--效率分析

【56】只做传值的参数最好加上const

【57】不要使用太多参数,参数太多,可以弄一个结构包起来,让程序清晰。

【58】尽量不要使用类型和数量不确定参数

【59】默认参数要慎用,而且不要太多。

例如:

bool checkCanAttack( int life,   int distance = 0 )
{
    if ( life > 0  )
    {
        return false;
    }
    doOther();
    return true;
}
checkCanAttack(100, 100);

后来因为业务变化,函数改成

bool checkCanAttack( int life, bool isFighting = false, int distance = 0, int maxDistance = 0)
{
    if ( life > 0 && !isFighting)
    {
        return false;
    }
    return true;
}
checkCanAttack(100,   100);//原来的使用并没有因为函数参数改了而出错,如果大量使用到,很容易出错而且无法调试

因为调用地方太多,有的地方改漏了,在外网正式服出现了问题被人投诉才知道。

后来肥宝的解决办法是把默认参数都去掉,然后一个个找错,是在没办法了。

返回值

【60】 函数返回和函数名字在语义上要一致

例如:

bool isWeekDay( int day )//判断是否是周末
{
    if( day == 6 || day == 0)
    {
        return false;//应该返回true,但是却返回false
    }
    return true;
}

写的人不会觉得什么,但是用的人可能就会用错了。

【61】在函数体内,容易出现return或者throw的分支尽量写在前面,可以省掉剩下的判断

【62】如果返回值是一个对象,要考虑效率

//效率高,直接在函数外部构造了
return String(s1 + s2);
//效率低,需要经过构造,传递,析构
String temp(s1 + s2);
return temp;
当然,这个对基础类型没什么作用
return 1 + 1;
int temp = 1 + 1;
return temp;

基础类型并没有构造这些步骤,省不了多少,看情况那种简洁用哪种。

【63】函数功能要单一,不要设计多用途的函数

【64】函数体规模要小,50行内,超过了最好拆分一下。

内存管理

【63】内存没分配成功,通常用指向这个内存的指针检测是否为空。

肥宝觉得,内存分配不成功,后面的处理已经不重要了。整个系统内存都爆了,宕机什么的是必然的了。然后运营会收到各种投诉,查错,赔偿,维护一大堆事情陆续有来。

【64】内存后,要养成初始化的习惯。

不要以为检测一个数字为负数就能确定还没初始化,如果碰上重复使用的那块内存,真的不知道是什么。

【65】动态内存的申请与释放必须配对,防止内存泄漏。

【66】用 free 或 delete 释放了内存之后,立即将指针设置为 NULL,防止产 生“野指针”。

【67】指针消亡,并不代表指向的内存被释放,内存被释放,并不代表指针为null。

【68】指针声明的时候,要么指向具体内存,要么设置为null,否则是随机值,可能if(p == Null)不起作用的。

【69】new一个对象的代价大,还是初始化后重用的大呢?

    struct SPoint
    {
        void init();
        int x;
        int y;
        int z[100000];
    };

    void SPoint::init()
    {
        x = 0;
        y = 0;
    }

    int count = 10000000;
    {
        CppServer::SPoint p;
        clock_t startTime = clock();//开始时间
        for (int i = 0; i <= count; i++) {
            //p.init();
            p.x = 1;
            p.y = 1;
            int distance = sqrt(p.x * p.x + p.y * p.y);
        }
        clock_t endTime = clock();//结束时间
        std::cout << "time:" << (endTime - startTime) << std::endl;
    }
    {

        clock_t startTime = clock();//开始时间
        for (int i = 0; i <= count; i++) {
            CppServer::SPoint p;
            p.x = 1;
            p.y = 1;
            int distance = sqrt(p.x * p.x + p.y * p.y);
        }
        clock_t endTime = clock();//结束时间
        std::cout << "time:" << (endTime - startTime) << std::endl;
    }

结果效率一样,但是如果执行了上面被注释的init函数后,时间消耗大大提高。初始化可能更加占消耗

【70】内联函数是用于实现的,声明的时候不用写。在头文件实现的函数自动成为内联函数

【71】 重载、内联、缺省参数、隐式转换等机制展现了很多优点,但是这些 优点的背后都隐藏着一些隐患。

不要总是想着用什么高级方法,不要为了用而用。很多时候,先写出来,后面再优化就好了。当然,可能还没写好,需求就变了。

【78】类的构造函数和析构函数可能有很多隐藏的操作,不一定适合做成构造函数

构造函数、析构函数、赋值函数

【79】赋值函数只是位拷贝而不是值拷贝,如果其中有指针就很可能出问题。而且会造成内存泄漏。

【80】构造函数有个特殊的初始化方式叫“初始化表达式表”(简称初始化表),初始化表在函数参数表之后,在函数体{}之前。

如果类存在构造关系,必须在初始化表里面初始化。

带有const的属性必须在初始化表里面初始化。

一个类初始化的时候,如果属性不是基础类型,放在初始化表来初始化,效率更高。

其他的建议

【81】不要一味提高效率,应该更多考虑程序的可读性,可维护性。如果你也是做游戏的话,很可能你的游戏根本没几个人玩,永远碰不到这个瓶颈,哈哈哈哈哈!

【82】优化程序的时候,要充分考虑游系统的特性,找出瓶颈所在。例如一个MMO游戏,在初期推广的时候,很多新玩家,经常在某个时段某个功能很多人同时玩,这个要注意。到了后期的功能,可能会很少人接触,但是在后来往往有很多跨服功能,几乎所有玩家在同一个服玩,这些都是要考虑的问题。

【83】最好的优化应该是从业务级别开始。很多东西计算量固定在那,怎么减都减不了的。需要考虑从业务级别入手。

【84】先优化数据结构,再优化算法

【85】有时候时间效率和空间效率对立,要做出折冲的方案,私人告诉你,现在内存很便宜,硬盘更便宜。但是系统启动读数据,可能会很慢很慢。

【86】避免编写技巧性很高代码。

【87】当心变量发生上溢或下溢,数组的下标越界。

【88】尽量使用标准库函数,不要“发明”已经存在的库函数。

【89】尽量不要使用与具体硬件或软件环境关系密切的变量。

最后:

还有很多很多的优化方式,不过限于本人的水平,只整理了这么多。路很长,道无涯,苦练七十二变,才能笑对八十一难,努力吧,少年!

时间: 2024-08-02 00:36:48

小规则让你写出漂亮又高效的程序的相关文章

小规则让你写出美丽又高效的程序

本文来自肥宝游戏,引用必须保留文末二维码! ! ! 好几天没写文章了,周一整理自己刚修好的旧电脑,发现一本书<高质量C++编程指南>.由于近期在写游戏服务端的战斗.所以这个立马就吸引肥宝了.看了几天,深深感觉获益良多啊. 于是把笔记和自己的经验写下来,分享给大家. 一.写出美丽易读的程序 中学时代上课非常喜欢做笔记.可是肥宝差点儿没看过自己的笔记.不是肥宝懒.是由于肥宝字太丑了. 后来成为一个程序猿,以为这些代码都是电脑输出.统一字体.就不用这么纠结了.谁知道代码更须要写得美丽.由于需求是不断

Markdown写出漂亮类图

我们经常使用到UML类图,常用工具软件不是那么的好用顺手.有没有想过Markdown简单标记语言也能写出漂亮类图?分享一个Jext开源插件扩展JIRA时画的类图. @startuml Title "到期工作日天数" 内置DueWorkdaysField ..> DueWorkdays 预定义DueWorkdaysField ..> DueWorkdays DueWorkdays ..> WorkdayHelper DueWorkdays ..> HistoryH

写出漂亮的代码之主属性方法

一个好的代码规范可以让你的代码更容易读懂和修改,在这里我介绍下我在一个类中书写代码时的方法. 因为这个方法的主角是属性,所以我把这个规范叫做,主属性方法. 我分为三部分:字段,属性和方法.字段写在最顶端,属性次之,方法最后. 字段里的内容大多是常量: 属性:什么时候需要属性?方法返回值使用率很高,就需要建立属性,把方法返回的值赋值给属性:方法中多次使用的内容,我把使用量超过2次的内容都新建一个属性并且赋值给它:什么时候给属性值呢?如果是获取方法的返回值,就在return的上一行:如果不是方法的返

10个小技巧助您写出高性能的ASP.NET Core代码

今天这篇文章我们来聊一聊如何提升并优化ASP.NET Core应用程序的性能,本文的大部分内容来自翻译,当然中间穿插着自己的理解,希望对大家有所帮助!话不多说开始今天的主题吧! 我们都知道性能是公共网站取得成功的关键因素之一.如果一个网站的响应时间超过3秒,那么用户通常不会再此光顾(此网站).谷歌,Bing,百度以及其他搜索引擎也更倾向于推荐优化后的,移动友好的以及响应速度更快的网站. 作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/10507984.

实验1 C语言程序设计初步(写出你的第一个程序!)

15.00 Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE Question 编写一个程序,输出以下信息(第一行和最后一行各有20个“*”): ******************** Very Good! ******************** Code 01 #include <stdio.h> //<stdio.h>为标准输入与输出头文件 02 int main(void) //主函数形式的辨析见下图03 {

10个编程小技巧,教你写出高质量代码!

你会写代码吗你会写高质量代码吗你知道怎么写高质量代码吗不要一上来就开始写代码想清楚,再动手今天,分享10个写代码的小技巧教你写出高质量代码↓↓↓ 1.重构思维模式 不要一上来就开始写代码,要掌握尽量多的重构方法,重构思维方式,掌握重构并不一定是要对原来代码的重构,而是让自己在操作之前就想好该怎么去进行. 2.搞清需求再动手 看到需求之后,肯定多多少少会有一些问题,或是理解上的错误,或是功能实现上的问题,这时,必须要交流清楚,否则,后续将会有更多问题. 3.文档也要写 可能不少人觉得文档没人看,写

前端开发:如何写一手漂亮的 Vue

前几日听到一句生猛与激励并存,可怕与尴尬同在,最无奈也无解的话:"90后,你的中年危机已经杀到".这令我很受触动.显然,这有些夸张了,但就目前这日复一日的庸碌下去,眨眼的功夫,那情形就会在这骨感的现实面前,悄然的被显现.所以,越发体验到,当必要有计划的去做,去写,去玩,去嗨,利用好这荷尔蒙分泌还算旺盛的时光,去厚积去博取,去发现去折腾:让自己的生命不在仅是工作与惆怅,还有时间分与"诗和远方".不用分析,就知道这该如何去做,高效去完成工作,然后去学着优雅地生而活.目前

能写出这样的文章,还会有心继续做程序猿吗?

编者(就是我啦,坤哥,超级表格创始人)按: 我看电影前喜欢先看影评,经常惊叹于他人的精辟分析.我写不出来,纵使我也有满腹意见.没想到的是,我们的程序猿小凯,已然写出了我写不出来的"精辟影评".想到这,我很得意,因为可以对这个"作家"吆喝:小凯,你这厮给我改bug去,超级表格的团队模块发现了漏洞! 扯淡技术哪家强?<秘术>周末隆重登场.这个电影倒也不是通篇扯淡,起码告诉了女同胞们三个很深刻的人生感悟:一,小白脸都是坏人:二,汉奸发型的都是坏人.三,说自己不

理解CacheLine与写出更好的JAVA

今天查了很多资料,主要是想搞清楚写JAVA和CacheLine有什么关系以及我们如何针对CacheLine写出更好的JAVA程序. CPU和内存 CPU是计算机的大脑,它负责运算,内存是数据,它为CPU提供数据.这里之所以忽略其他存储设备是为了简化模型.假设我们面对的是具有两个核心的CPU,那么我们的模型大概如下面的样子: CPU计算核心不会直接和内存打交道,它会直接从缓存拿数据,如果缓存没拿到,专业点说即缓存未命中的时候才会去内存去拿,同时会更新缓存.这个过程CPU不会仅仅读取需要的某个字节或