做产品就是用 Axure、MindManager,做管理就是 JIRA、禅道,真的是走错了。
就像写程序不是学会用编辑器和 IDE 一样。
当结果难以控制,我们就会炫耀过程。
当然,我们都不会对号入座。
说起 .net 网站,还经常会提起 stackoverflow.com,他们在中国有备案:
中文名叫“静态流”,还挺技术的,但是好像有点跑题,为什么不直接叫“栈溢出”呢?
stackoverflow.com 的 alexa 排名是 53,jd.com 则是 21,还有一家传言是采用 .net 技术的网站携程 ctrip.com 排名是 3149,没想到这么后。
有一个农民给地主打工,地主说我给你每个月一石米。
农民却说:“我有一个大胆的想法:你给我第一天一颗米,第二天两颗,第三天四颗,第五天八颗...后面全部翻一倍。”
地主想这农民傻了吧,要这么少,就答应了。
后来农民坚持了十天终于饿死了。
——haOFei
知乎的前端工程师挺有想法,用 svg 做图标和二维码。我同事说知乎对浏览器的要求较高,不支持低版本的浏览器,这也是他们“高端”社区定位的一个方面吧。
刚才在知乎上传了几张图片,竟然要求宽和高都要够 120px,我还写了个小程序放大图片。我认为他们应该在服务端就做好这件事的。
可能他们的前端工程师比较多,后端人手不够吧。
在介绍一个人的成功的时候,往往过分强调一个人的个人能力。某某成功人士孤身一人,白手起家之类的。
我认为这是有偏差的,人是社会性的动物,际遇没法逃脱社会的环境和家庭的情况。只是我们常常会强调正面的影响而忽略反面的影响,比如战火纷飞的国家、不幸的家庭对人的影响是很大的。
最近虽然运气不太好,但是家人帮助了我很多。这是体现在点滴生活中的。
很多人在讨论 .net 的时候,都会拿出京东做例子。支持者说京东能用 .net,说明 .net 很好,只要用得好,可以做大型网站。反对者说京东早期是用 .net 的,但是网站做得很烂,完全不能支撑业务,转投 java 的怀抱之后才好转,所以 .net 不如 java。
其实 web 程序员都知道,一个网站用什么技术,可以在 http 请求和响应中看出来,只要这个网站不是故意去伪装的话。一般网站没有什么动机去伪装自己所用的技术。
web 的早期,几种技术架构的请求链接都不同,java structs 的喜欢用 .action 和 .do 后缀,php 则是 .php,.net 是 .aspx。现在的大型网站一般都会隐藏后缀,因为从链接的设计美学来说,后缀不能表达任何有用的信息。
访问京东的首页:www.jd.com,响应头如下:
那一年,振华高考落榜了,我拍拍他的肩膀,安慰他说:“华仔,不要伤心,人生的路很长,一次失败不代表什么。”
振华擦了擦眼泪,看着我说:“好的,我不伤心,我应该向你学习,你高中考了三年都考不上,从来就没见你伤心过。”
最近看得比较多程序员的博客、微博,相比之下,我对编程是不够虔诚的。
不过想来编程其实给我很多,我以后可能还要花比较多的时间在这项工作上面,毕竟这也是个有趣的事情。
我大学的时候有一次上讲台操作电脑,频繁地用 Caps Lock 切换大小写,台下有同学在笑。是的,我学习计算机知识起步比较晚,那个时候还不会用 Shift 切换大小写。
我小时候学习成绩不好,很自卑,经常怀疑自己,是不是我天生就比别人差呢?
随着自己渐渐长大,我不再怀疑自己,我相信自己就是比别人差。
工作不久,我就指出了领导代码中的一个低级错误,被领导骂了一顿。我愤愤不平,难道仅仅因为你是领导,就可以不分对错吗?
后来经过了多年的职场历练,我对此渐渐释怀——没有错,领导说的都是对的。
我小学的时候对振华说:“等我以后有钱了,我一定不会忘记你的。”
我没有食言,我现在已经不记得他了。
女朋友半夜把我摇醒:“给我说个段子吧,我特别喜欢听你说段子。”“夜深了,睡吧,明天一早给你说,啊。”
闹钟响了,我转过身去准备给女友说段子,发现自己根本没有女朋友。
振华小时候很喜欢汽车,特别喜欢保时捷。我跟他说:“等我以后成功了,我送你一台保时捷。”
现在当然是没送啦,因为我从小就知道自己不可能成功。
今天做了一下手机的前端,才知道默认的情况下手机浏览器会对网页进行缩放。css 中的 px 在手机浏览器里面并不是显示为一个像素。
这是因为手机的像素比 PC 要少,但是密度大,一个像素一般可以作为 PC 上面的两个像素使用。像素密度到达一个水平,就叫做 Retina 屏。
一般的大型网站,都要建一个手机站,编写专门给移动端使用的 css,这样就可以禁用手机浏览器的缩放。
如果一个网页同时要支持 PC 和手机,还是需要使用手机浏览器的自动缩放的。PC 端宽度 600px 的图片,在手机里面无法完全显示,这是不能容忍的。对图片缩小显示,在手机的高密度像素里面效果也很好。可以在 html 里面设置默认的缩放比例,这个博客的比例是 0.55。
刚才因为一些权限的限制,我没法在数据库里面 join 数据,而是把数据复制到本机,用 excel 逐条人肉 join 了一百条数据。
是的,这个方法很蠢。但是如果有一万条数据,我会写一个程序,数据少的话就算了。
如果我们把编程看做是一项工作的话,还是要接受去做一些乏味的事情。虽然这是我们的兴趣,但是也无法保证所有的时间都是快乐的。况且在编程上所做的这些无趣的事,无论如何也比搬砖要好,只要你真的把它当做一份工作。
我记得以前中田英寿说:“踢球是我的工作,我的兴趣是打篮球。”真奇怪。
刚开始工作的几年,我写了一个程序收集整理网上的行政区划信息,我的经理看到了,说:“就这么一点数据,你还不如一条一条去整理呢。”两种方法所用的时间应该差不多吧,他说的也有一定的道理。
乙方的业务员小妹心情很差,因为我公司还没转账,她的绩效没法完成,要被扣工资了。
想不到几千元的订单对一个人影响这么大。
不过我觉得这种情况乙方公司可以灵活一点,这个月底才确定续约,下个月不到账再扣工资也不迟。还好,最后他们的人跟我电话确认订单后,不扣业务员的工资了。
明天就是五一假期了,想不到这么快二零一七已经过了三分之一。
我希望一切可以好起来。
祝大家五一愉快!
我小学的时候做过一次纸质板报,感觉很像现在的网页设计。
我给板报的不同栏目涂上了不同的鲜艳色块,实际内容没多少。我的一个同学的板报则内容丰富,不同的栏目通过间距,字体,灰度的不同去区分,对比起来高下立见。
现在看 web 产品水平的高低,也差不多是这种感觉。
现在的社交应用,要找到“曾经看到过,有一点印象”的信息是比较难的,不知道是不是有些信息,本来就应该随着记忆的模糊而消失。
微博的“未读池”的排序,更加深了找回以前看到过的信息的难度,经常是一刷没了,就再也找不到了。
越长大越孤单,并不是因为你长大导致的,而是因为你的小伙伴长大了,他们发现你这种人并不值得交往。
——@银教授
为了活跃气氛,我每晚在饭桌上都会讲段子,但从来没人笑。我以为是因为我的段子不好笑,后来才知道,是因为我每天都一个人吃饭。
——@银教授
内裤是男人最后的底线。
——野原广志
野比大雄毕业之后找不到工作,于是创立了只有他自己一个员工的“野比大雄”公司,这就是万众创业。
我不赞同什么“努力是为了你夹菜的时候没人敢转盘子”这种话,因为谁夹菜我都不敢转盘子。
像前面的例子 http://bibaoke.com/post/29 那样,阻塞事务的语句是必须的:
--延长处理时间 waitfor delay '0:00:10'
这个语句代表在查询中等待 10秒,这样我们才能模拟并发的情况,如果事务很快执行完毕了,就无法重现并发的情况。
我在网上看到有些例子是使用 C#、Java 等语言启动多个线程去模拟并发,而不是使用阻塞,虽然这样更接近生产环境,但并不利于简化问题。多个线程模拟并发,取决于线程数和事务执行的速度,难以确认并发发生了,而且编码量稍多。
然后是使用 sys.dm_tran_locks 视图去查看锁:
余额问题 http://bibaoke.com/post/24 的处理,还有一种等价方法:
update balance set value = value - 1 where id = 1 and value >= 1
用一个 update 语句表示如果用户余额足够,即扣减余额,数据库会对数据放置排它锁。这样既不会出现余额负数的情况,也不会产生死锁。
相比之前的方案,这个方案更加的简便。
之前的方案则更加的灵活,因为事务的创建和提交一般在 Web 服务器里通过 ODBC 去调用。检查余额是否足够这个查询也可以在多个地方重用,比如在用户使用余额之前,就提醒用户充值。
重复用户问题 http://bibaoke.com/post/26 也有一种等价的处理方法:
insert app_user select '13800002222' where not exists( select * from app_user with(holdlock, updlock) where mobile = '13800002222')
上一节 http://bibaoke.com/post/25 说了一个注册用户的事务没有互斥,导致注册用户失败的问题。
也说了解决方法就是使用 serializable 隔离级别去执行事务:
--开始事务 begin transaction --设置串行式事务 set transaction isolation level serializable --检查用户用户存在 if(not exists(select * from app_user(updlock) where mobile = '13800002222')) begin --延长处理时间 waitfor delay '0:00:10' --添加用户 insert app_user values('13800002222') end --提交事务 commit transaction --查看处理结果 select * from app_user
只是在原来的脚本加了一句:
拿 Web 项目中常见的注册用户场景做例子:
--测试用户表 create table app_user ( mobile varchar(11) primary key ) --添加测试数据 delete app_user insert app_user values('13800001111')
现在新注册一个手机号为 13800002222 的用户:
--开始事务 begin transaction --检查用户是否存在 if(not exists( select * from app_user(updlock) where mobile = '13800002222')) begin --延长处理时间 waitfor delay '0:00:10' --添加用户 insert app_user values('13800002222') end --提交事务 commit transaction --查看处理结果 select * from app_user
上次模拟了 SQL 中并发执行更新余额的语句,出现余额负数的问题:
现在说说它的解决方法。
事务要正确地执行,就需要【隔离性】这个基本要素。更新余额的语句之所以会偏离期望的结果,是由于查询并没有互斥,也就是没有相互隔离:
举一个用户余额的例子,余额可以是现金、虚拟币、积分等,可以看作对数据准确度要求高的数据,一旦出错,就会造成客户或公司的直接损失。
在 SQL Server 建立一个测试表:
--测试用余额表 create table balance ( id int primary key, --用户ID value int --余额 ) --插入测试数据 delete balance insert balance values(1, 1)
ID 为 1 的用户有 1 块钱的余额