解惑

解己之惑,解人之惑

第44页共82页

Google面试题解说性能之四:优化无止境

其实在例子二的基础上,我们进一步的分析,可以把缓存10个结果换成缓存100个结果,性能可以得到进一步提升:
public class GoogleFn {
private static int MAX = 13200000;

private static int MAX2 = MAX / 10;

private static int MAX3 = MAX2 / 10;

private static int count(int n) {
int count = 0;
while (n > 0) {
int mod = n % 10;
if (mod == 1)
count++;
n = n / 10;
}
return count;
}

阅读全文

Google面试题解说性能之三:不要小看循环中的任何一个语句

对于任何语言来讲,循环永远是非分布式系统的性能的最大杀手,循环中的任何一个简单的语句对性能都是有影响的,只是影响的大小不同而已。第一个例子中的影响是比较大的,不同的实现方法的时间开销不同,然后这个微小的差异被循环次数放大后就非常的明显(3倍),而第二个例子,其本质是减少了循环执行的次数,虽然总的循环次数是一样的,但是最耗时的操作的执行次数被减少到1/10,所以产生的差异是非常巨大的(8倍)。我们再来看一个很不起眼的微小差异带来的影响:
public class GoogleFn {
private static int MAX = 132000000;

private static int MAX2 = MAX / 10;

private static int count(int n) {
int count = 0;
while (n > 0) {
int mod = n % 10;
if (mod == 1)
count++;
n = n / 10;
}
return count;
}

阅读全文

Google面试题解说性能之二:分析问题

前面我们已经说了字符串运算和数学运算对性能的巨大影响,接下来我们看看分析程序,多思考给我们带来的好处。
如果我们做一个简单的分析就可以知道,在尾数从0到9的连续十个数字中,只有尾数为1的数字的1的个数比其它的数字多,那么我们可以以10个数为单位进行分隔,计算尾数为0的数字包含1的个数,其它的9个值就以此为基础计算:
public class GoogleFn {
private static int MAX = 13200000;

private static int MAX2 = MAX / 10;

private static int count(int n) {
int count = 0;
while (n > 0) {
int mod = n % 10;
if (mod == 1)
count++;
n = n / 10;
}
return count;
}

阅读全文

Google面试题解说性能之一:字符串运算VS数字运算

看到JavaEye上的几个人在讨论算法问题,其中一个就是Google的一个面试题,我也试了一下,而且可能比一般人试得程度更深一些,借这个题目简单的说说几个性能问题。这个是第一个,后面还会继续几个其它的讨论。讨论只是提点一下,主要还是要你自己读源代码并比较不同的实现为什么会有这么大的差别。
注意,程序的运行结果是在JDK1.4.2上的,其它版本的JDK的运行结果可能稍有不同。

先看代码:
public class GoogleFn {
private static int MAX = 13200000;

private static int count1(int number) {
int result = 0;
String target = number + “”;
int index = target.indexOf(“1”);
while (index >= 0) {
result++;
index = target.indexOf(“1”, index + 1);
}
return result;
}

阅读全文

房产证到手

昨天经历的惟一的一件值得高兴的事情就是把房产证拿到手了,把中介的钱付了,物业也过户了,还付了一年的物业费,一个平方4毛5每月。
这次买房和装修的过程中,买房我们非常的小心,因为我们之前听了很多关于二手房买卖的陷阱,我老婆还在一个房地产网站公司里面做过一段时间,所以一路下来我们非常小心,几乎就是谁的话都不信(中介和上家),一定要按照正规的流程走,有一次还特意晚上跑到上家的家里问她的女儿是否同意卖房,因为之前我们从来没有见过她的女儿,只是上家说女儿在读书,很忙。
因为这次买房还算比较顺利,到装修前其实都没有遇到真正的问题,中介和上家说的其实都是实话,所以这次装修老婆说倾向于让那个老板装,我开始很担心,后来跑去老板家看了下,感觉人还是比较可靠的(包括老板的老婆),再想想自己办事一直都太小心谨慎了,这次买房都没有什么,装修应该也不会有什么吧?况且是后付款,也不怕有什么事情,所以后来也就同意了。加之买房的时候查了很多注意事项,实在是比较累,所以就想这次装修就不那么费心休息下好了,结果闹到这个地步

所以人不能想着偷懒,在上海做事情还是按照正规的流程走,合同什么的一定要仔细签。

装修停工

昨天说了脱排和煤气灶的事情,越想越不对,昨天觉也没有睡好,然后老婆在上班的路上提前一站下车,因为她看到一个卖木材的点,进去随便看了下,发现他们给我们做厨柜和衣柜的材料竟然是最便宜的那种双面白高密板,80块钱一块,老婆就赶紧给我打电话,我和岳父商量了下就请假到房子那边去了,那边还在做彩铝的窗子,看了下,很薄的,好像也不太结实,彻底的心寒了,赶紧打电话,和那个老板约好到他的公司谈一下,赶到那个老板的公司一看,彻底无语,就是上海外环以外(三林那边的搅拌厂附近)的一个装修队而已,公司只有两块大众化的那种铜牌,其他的破旧不堪。
我们说了下目前的情况,脱排和煤气灶我们肯定不要,那个老板说可以,他其实也不知道,然后我们说那个彩铝的窗子也不好,他说也不知道,他打电话让那个做窗子的人来了,我们说那个材料和我们当初看的肯定不同,然后问他价格,他说3万3一吨(晕,他把进价说了,虽然我们不太好换算为按照市面上的面积计算方法),我们就说按照面积算多少钱,他想了半天,说200一个平方,我们说再去调查。然后就是谈木材的问题,我们说那些板材我们全部不满意,他说已经用了的没有办法,没有用的可以退。就这样大致谈定,我们就出来继续我们的调查。(谈的过程中让他们打电话告诉手下停工)
我们先又去问了下木材,发现那个确实是最差的,而原来的两家正规的装修公司给的材质都是说杉木板,杉木板是实木板,环保方面没有问题,而那个高密板的环保情况不好,因为中国的标准比国家标准差几倍,所以国外用的人多,国内用的人少,那个卖木材的说,这个板子现在只有一些外地人用(不太喜欢他的那个语气)。
然后拿着他们的彩铝的样品去问,一般的给的是160一个平方,后来快回来的时候又试了一家比较大的店,也是160,但是我们快走的时候她问多少平方,说5个平方以上可以便宜10块,我们说10个平方以上,她说那就140、150左右吧。

最后的结果是:和买彩铝的人谈,150给我们,然后找那个老板,那个老板说随便我们怎么做都可以,让我们找工头,工头说没有接到老板的电话,另外明天有事不能谈,我给一个同事打电话,他建议我们逼出那个老板的底线,和老婆商量了下,感觉已经完全失去信任了,再给他做可能问题更多,打算结算以后另外找人做。明天再继续谈。

惨痛的教训是:无论多熟的人一定要签合同,这样说熟人不是熟人的人就更要签,而我们开始太信任他了,我们几乎是没有过问过,只是说要环保一些的,便宜一些的。主要责任还在我们,太大意了,也没有给别人交待清楚。

他们给过我们一个大致的报价,全包,包括实木地板、厨卫、脱排、煤气灶和热水器一共4万3,装修完一次结清,如果我们真的由他们弄,估计他们的采购成本是1万,人工成本是1万,净赚2万3,天啊

真的有人把我们当傻子

前两天已经开始后悔我们的选择,现在更加离谱的事情来了,那个老板给我们买来了脱排和煤气灶,对我老婆说是帅康牌的,我老婆问了下价格,他不愿意说,说不会超过我们的标准,我老婆说1500左右的就可以了,老板说就那个价格,后来老婆去验货,发现脱排的盒子上印的是帅康小旋风,而煤气灶上是帅康飓风,说明书里面则没有牌子,老婆打了煤气灶的说明书上的两个上海的维修电话,一个无法接通,一个不存在,然后跟老板说了,他说现在没有时间,明天再说。
我回来查了一下,恰好有和帅康小旋风相关的新闻,都是伪劣产品新闻,另外那个帅康飓风的煤气灶假得更直接,说明书上没有具体的厂家名称,上网搜索了下,帅康确实有飓风系列产品,但是全部是脱排。
那个老板真的把我们当作什么也不懂的傻子吗?或者是有心试试我们?或者完全是有恃无恐想宰我们一笔?
但愿我们这次遇到的不是黑社会的

软件开发的最大困难其实在于消除重复代码

这个并不是我一时兴起的胡言乱语,而是我的肺腑之言。如果你仔细的审视一下你所在的项目的代码,你可能会发现其中60%以上的代码是何其的类似,充斥其中的都是类似的判断和循环,在项目的框架或者架构稳定下来以后,项目的工作就是每天重复类似的工作,然后就是这些类似的代码的比例越来越大。如果项目的架构或者框架代码不够好,而某一天有一个需求导致这些代码都要进行某种简单或者复杂的更新,那么你的噩梦就来了。
软件开发的最大困难也就随之出现,如果你的框架足够好,共通的需求只会导致一个或者有限的几个地方的修改,如果框架不好,那么你就准备把那个修改重复几十遍或者几百上千遍吧。衡量一个软件的设计是否足够好,我想最重要的标准就是它能多大程度上消除这样的情况。仅仅有了好的架构其实也不够,开发人员可能会复制一段类似的代码,导致超出框架设计的代码重复,这个就是检验项目管理是否足够好了。

设计一个简单易懂、易于扩展、易于维护的框架并不是很难的,结合OO设计的原则和一些设计模式就可以做到,但是问题并没有结束,如何消除业务代码中存在的类似代码结构才是真正的问题所在。
我没有解决方案

当然,软件开发也并不是只有消除重复代码这一个问题,但是我感觉,如果能够较好的消除代码重复,那么软件的开发效率和质量以及可维护性将更好。
PS:我并没有说完全消除重复代码,代码的重复性是不可避免的,典型的例子就是单元测试代码。

如何设计API?

每个人设计API的思路可能都不一样,而我们公司的一些代码的API的设计很有意思,一个例子:
    public AppGroupConfigValueObj get(UserSession _userSession, AppGroupConfigValueObj invo) throws DataException
    {
        long start = System.currentTimeMillis();
        try
        {
            Long id = (Long) invo.getId();
            if (isDebug() )
                SessionLogManager.getInstance().getLogger(this.getClass()).debug("get group" + id);
            AppGroupConfig eb = this.appGroupHome().findByPrimaryKey(id);
            if (isDebug() )
                SessionLogManager.getInstance().getLogger( this.getClass() ).debug("Get( UserSession _userSession, AppGroupConfigValueObj invo) elapsed time = "+ (System.currentTimeMillis()-start));
            return get(eb, invo);
        }
        catch (Exception e)
        {
            throwException(e);
        }
        return null;
    }

    private AppGroupConfigValueObj get(AppGroupConfig eb, AppGroupConfigValueObj invo)
            throws Exception
    {
        AppGroupConfigValueObj vo = (AppGroupConfigValueObj) ServerUtil.getValueObj(eb);

        if (invo.getApps() != null)
        {
            Collection collection = eb.getApplications();
            if (invo.getApps().getCount() == 0)
                vo.setApps(new ValueObjList(collection.size()));
            else
            {
                Iterator it = collection.iterator();
                while (it.hasNext())
                {
                    AppConfig a = (AppConfig) it.next();
                    vo.addApp((AppConfigValueObj) ServerUtil.getValueObj(a));
                }
            }
        }
        return vo;
    }

解释一下,这个API的功能是这样的,主要参数AppGroupConfigValueObj 是一个Map结构的对象,另外包含一些父子关系,如果你需要的是一个轻量级的结果,那么传入的对象只需要设置ID就可以,典型的用法是这样的:
get(cuSession, new AppGroupConfigValueObj(appGroupId))
如果你需要一个重量级的结果,也就是需要它的一些子表的数据,那么就要设置子表的关系,并添加一个空的对象:
                    AppGroupConfigValueObj appVo = new AppGroupConfigValueObj(appGroupId);
                    appVo.addApp(new AppConfigValueObj());
                    get(cuSession,appVo);
还有第三种用法,就是你希望那些子表数据不填充,但是需要知道子表数据有几个,那么你的调用代码就是:
                    AppGroupConfigValueObj appVo = new AppGroupConfigValueObj(appGroupId);
                    appVo.setApps(new ValueObjList());
                    get(cuSession,appVo);

我不知道这种做法源自何处,但是很明显是原来的某位高人,而比我资历更老的一些同事沿用了这个做法并且没有在文档中记录这种方法,当我苦苦寻找一个简单的get(cuSession, appGroupId)方法时没有任何结果,最后看其它部分的代码才知道了这个诀窍。

如何替换\

以前也经常遇到这个问题,但是没有找到解决方案,今天再次遇到这个问题,搜索了下没有什么头绪,很多答案试验了下都是错误的,不得已,自己试吧,最终的结果是:
replaceAll("\\\\", "\\\\\\\\")
就是把字符串中的\替换成两个\,呵呵,变态吧。

« 更早的文章 更新的文章 »

© 2025 解惑

本主题由Anders Noren提供向上 ↑