2016年5月14日星期六

sql内置序列号对象SequenceNumber

最近有一个需求,就是对不同类型的用户生成不同区间段的8位邀请码,而且邀请码是纯数字格式,并保存到对应的用户表中,其实使用代码实现的逻辑是:
  1. 根据用户类型找到当前最大的邀请码;
  2. 将当前最大的邀请码+1得到新生成的邀请码;
  3. 保存到数据库中;
但是这样不仅逻辑麻烦,性能差,而且需要考虑到并发量大时多线程的处理,数据库中的SequenceNumber就更适合我们这种情景

SequenceNumber在sql server中是2012版本才引入的,官方文档的说法是有以下几种用途:
  • The application requires a number before the insert into the table is made.
  • The application requires sharing a single series of numbers between multiple tables or multiple columns within a table.
  • The application must restart the number series when a specified number is reached. For example, after assigning values 1 through 10, the application starts assigning values 1 through 10 again.
  • The application requires sequence values to be sorted by another field. The NEXT VALUE FOR function can apply the OVER clause to the function call. The OVER clause guarantees that the values returned are generated in the order of the OVER clause’s ORDER BY clause.
  • An application requires multiple numbers to be assigned at the same time. For example, an application needs to reserve five sequential numbers. Requesting identity values could result in gaps in the series if other processes were simultaneously issued numbers. Calling sp_sequence_get_range can retrieve several numbers in the sequence at once.
  • You need to change the specification of the sequence, such as the increment value.

在我们的项目中用法如下

代码块

CREATE sequence dbo.SequenceInvitationCodeForAgent
as int
Start with 30000001
Increment by 1
MaxValue 39999999
MinValue 30000001

CREATE sequence dbo.SequenceInvitationCodeForFundPartner
as int
Start with 60000001
Increment by 1
MinValue 60000001

CREATE sequence dbo.SequenceInvitationCodeForRY
as int
Start with 20000001
Increment by 1
MaxValue 29999999
MinValue 20000001
每次得到新的邀请码只需要运行SELECT NEXT VALUE FOR MySequenceName就可以得到了,就是这么简单,而且不必考虑多线程的问题

2016年2月3日星期三

2015年终总结

拖了很久没有动笔,本来想想算了,反正也不会有人看,写了也没什么用,但今天看到一个订阅很久的人更新了博客,题目也是年终总结,心想这两天上班也没什么事情,还是写写吧,也算给自己一个交代。
其实现在回过头来看看,自己仿佛没什么改变,也没什么进步,但是再仔细想想14年底的自己,又好像有很大的不同。也许世事就是这样,不识庐山真面目,只缘身在此山中。
2015年: 
1. 不知是没有记录还是真的没有看书,我在豆瓣上的15年看的第一本书居然是10月份记录的,好在12月份拼命的看,总算在元旦之前完成了平均每月一本的成绩; 
2. 全家到香港旅游了一次,也算是出了次国吧; 
3. 购置了Macbook Pro和iphone 6sp; 
4. 将查歌词api站点用python改写并部署到linux服务器上,站点很小,脑中有几个想做的项目可是都是开了个头就搁置了,希望明年完成; 
5. 没有学习新语言,C#和python都进步了,并使用了一些新东西,比如mongodb,redis,memcache,angularjs,一些库; 
6. 由于上班路程远,每天起早贪黑,基本没有时间锻炼,身体大不如前,人也胖了许多; 
7. 博客写的数量比预期少,主要是自己真的学过之后觉得太不值得写了,加上人也懒,这个希望明年改善吧; 
8. 将梯子转移到vultr供应商日本节点,速度比搬瓦工快了许多; 
9. 教团队的人翻墙并提供自己的梯子给他们; 
10. 带了个新人,刚毕业的小朋友,令我最欣慰的是他能坚持翻墙,独立思考,有自己的想法,可惜跟主管吵了一架后就再也没来了;
希望明年可以: 
1. 学习并掌握es6语法,前端框架react.js; 
2. 进一步熟悉linux和mac系统; 
3. 平均每月一本书,一个月到两个月一篇博客; 
4. 有时间学学swift(已经很没底气了); 
5. 出国游; 
6. 继续未完成的项目; 
7. 换一个离家近,有追求,工资高,福利好的公司;

15年其实不是特别开心,尤其是后半段,因为对于产品和技术的不同观点,很多想法都与目前公司采用的背道而驰,而做为一个技术人员却没有任何话语权,很多时候提出的建议与观点都被否决了,没有理由。而我们做为产品实现环节的最下游却要为产品的低能买单。每次做一个新任务都要改两遍以上才能做完。
能记住的建议如下: 
1. 建议公司设立vpn,可以支持远程办公,vpn建立,但是远程办公被否决,这个我能理解; 
2. 提出用我自己的mbp办公,只要公司提供显示器就好,被拒绝; 
3. 提出使用团队协作工具流程化管理,使用过一段时间开源中国的team,但是后团员不再使用; 
4. 实时通讯提出用azure的service bus(因为我们公司用azure),被拒绝,主管最后自己找了网易的polemo,github上最后更新日期是两年前; 
5. 消息队列提出用redis或azure,主管让老实使用windows自带的消息队列,这个任务做的极其消沉; 
6. 前端曾提出用react,主管拒绝,并要求我们使用angular.js框架,现在有意让我们改用react; 
7. 对于产品的逻辑混乱,文档的错误丛生,提出让程序员提前参与任务制定,被拒绝; 
8. 做任务中对于错误流程与逻辑的更改,大概一半被接受一半被拒绝;
所以在15年最后的几个月里,我经常想,是不是做个技术人员还不够,因为没有什么公司是技术人员可以有决策权的,就算技术方面的也没有。只有你到了一个高的位置之后,才有一定的话语权。鉴于此,我是不是又要重新计划职业目标,向上游与高级职位上改变。
努力吧。

2015年9月23日星期三

在windows上用IIS搭建memadmin站点

memcache是使用比较广泛的缓存应用,之前在使用时觉得想要查询之类的非常困难,必须要使用命令行或者写代码,所以想写一个管理的页面应用,但是正好发现了memadmin这个货,正好是做这个的,于是直接搬过来使用就好了,下面是我部署的步骤,记录一下备忘,本来想部署在linux主机上,但是领导非要部署在windows上,还指定必须IIS。。。
  1. 下载需要用到的东西 
    • php-5.6.13-nts-Win32-VC11-x86.zip 下载
    • php_memcache-3.0.8-5.6-nts-vc11-x86.zip 下载 
      解压放入php\ext目录
    • memadmin-1.0.12.tar.gz 下载
  2. 配置php 
    • \php.ini-development复制出一份命名为php.ini
    • 配置相关必要选项,具体见php文档
  3. 配置IIS 
    • 处理程序映射 - 添加模块映射 - 
      *.php FastCgiModule D:\php\php-cgi.exe PHP_via_FastCGI 
      请求限制 - 仅当请求映射至以下内容时才调用处理程序 - 文件或文件夹
  4. 配置memadmin站点 
    • \config.php文件中配置登录memadmin的管理员用户名密码
  5. IIS中添加站点,默认文档中添加index.php

这样就好了,做完回头一看其实很简单,只要php和php_memcache的版本不搞错就好 
其实用linux更简单,有机会再弄个linux版的

2015年9月5日星期六

学习部署flask站点

前段时间工作有点闲,抽出一天时间把之前的chageci的api站点用python代码重构了一遍,使用了简单的flask框架,代码量锐减,少的我都不好意思分模块了,直接在一个py文件中搞定。
但是由于自己没学明白,只会编码而不会部署,加上linux不熟练,所以写好了代码就一直放在那里没去管它,直到叶同学跟我唠叨说要一起弄个vps做东西,我只好硬着头皮去研究flask的部署问题,没想到居然也一天搞定了,下面说说步骤。
  1. 开虚拟机 
    我是在azure上开了一个ubuntu的A1主机,几乎是最低配置了,跑两个个超低流量的api站点够用了
  2. ssh 
    单位用的是windows电脑,客户端用的是securecrt(原谅我用的不是正版,只是找一个熟悉linux的同事要的);家里用的是mac电脑,直接命令行就可以ssh连接了:ssh -p port user@ip
  3. 部署python环境 
    虽然连上了linux服务器,但是对linux命令还是抓瞎,一边google一边做。ubuntu跟mac一样已经安装好了python环境,而且python3也有,挺不错。
    • 安装pip sudo apt-get install python3-pip
    • 安装virtualenv sudu pip3 install virtualenv
    • 到项目目录 cd myapp
    • 创建python3虚拟环境 
      virtualenv -p /usr/bin/python3 venv 
      source venv/bin/activate 
      pip3 install package-name 
      此时环境都安装完毕,用python3 app.py运行可以测试效果
  4. web容器gunicorn 
    gunicorn是运行python站点的容器,可以多线程运行,是专门处理web请求的,而我们的代码则只需要专注于处理逻辑。 
    安装 sudu apt-get install gunicorn 
    运行 gunicorn app.py 
    这样就默认运行在本地的8000端口了,访问http://127.0.0.1:8000就可以直接访问到我们的站点,而如果需要指定一些东西可以添加参数gunicorn -w 4 -b 0.0.0.0:8000 -p rocket.pid -D api:app,-w是指定线程数,-b是监听ip和端口,如果制定为0.0.0.0则可以外网访问,但是不建议这样做,最好用默认的127.0.0.1,然后前面再添加一层反代,-D是添加为守护进程,这样在ssh超时后仍然可以运行(就像winservice)
  5. 反向代理 
    以前用过nignx,配置比较容易,但是同学上的是apache,似乎比nignx难一些,于是让他帮我配好一个反代站点,我也没管了。
  6. 后续问题 
    程序在本地运行速度很快,可是到了服务器上却很慢,差不多要几十秒,后来发现我们的程序都需要发起http请求,看日志发现这个请求消耗了几乎全部的时间,但是直接在服务器的浏览器中请求该域名却很快,原来服务器默认开通了ipv6,所以解析域名时先进行ipv6的解析,时间都消耗在这里了,把ipv6禁用掉就好了

总结

linux还是很好用的,看着命令行界面下运行任何程序都那么快,心里还是有不小的快感,学会了一些常用的命令 lspskillrmtouch 
退出virtualenv环境的命令 deactivate 
使用了vim直接编辑代码测试问题,最常用的ddi-wq-q!
最后利用周末时间详细看了一遍一个flask的文档,以前看到过,觉得看不懂,没看下去,现在看几乎全是干货,受用匪浅,强烈推荐 
https://spacewander.github.io/explore-flask-zh/index.html

由于我的站点是很简单的微信公众账号的api,昨天看了一下,新增了4个用户:)

2015年4月11日星期六

一次数据库恢复

晚上上着线,领导突然轻声跟我说,我执行了这个。。。然后指着屏幕上的一句DELETE语句,我瞬间明白了,这是错删数据了,好吧,苦逼的我只好去折腾数据恢复工作,谁叫咱是专业擦屁股的呢。
先想想吧,数据库是SQL Server,有日志,可以从操作日志找到记录并恢复,不过这个我没做过,业务不熟;另外我们有备份,每天一个完整的,20分钟一次增量的,许久没做了,业务有点生疏,但是还算做过,心里有底,于是决定采用这种方式。
下面还是贴上代码吧:
restore database RY_20150410 from disk = 'E:\sqlback\RY_backup_2015_04_10_040001_5063465.bak' with norecovery,
MOVE 'RY' TO 'E:\sqldatatemp\AdventureWorksCopy_Data.mdf', 
MOVE 'RY_log' TO 'E:\sqldatatemp\AdventureWorksCopy_Log.ldf';


restore log RY_20150410 from disk = 'E:\sqlback\log\RY_backup_2015_04_10_042001_3408063.trn' with norecovery
restore log RY_20150410 from disk = 'E:\sqlback\log\RY_backup_2015_04_10_044001_9740908.trn' with norecovery
restore log RY_20150410 from disk = 'E:\sqlback\log\RY_backup_2015_04_10_050001_5706013.trn' with norecovery
.
.
.
restore log RY_20150410 from disk = 'E:\sqlback\log\RY_backup_2015_04_10_184002_3865400.trn' with norecovery


select state_desc,name,user_access_desc from sys.databases where name='RY_20150410'

--之前的恢复语句后面都加了with norecovery,就是指定恢复点,但是不进行实际的恢复
--最后恢复整个库
restore database RY_20150410 with recovery
还好我来这家公司之后做的第一件事就是做了数据库的备份计划,数据备份这东西不用的时候永远体现不出价值,一旦需要用了,那价值是无穷的。

2015年2月28日星期六

angularjs与bootstrap搭配,radio标签的checked无法更新到ngModel的问题

最近系统有很大的架构调整,组内没有专业前端,于是我这个半桶水被派去做前端任务,而且在我刚刚熟悉knockout的时候放弃,使用从未用过的angular框架,看着那道高高的学习曲线苦不堪言。
任务中涉及到大量的表单提交,而且同页面可能根据选项的不同而得到不同的表单项,对于这个我提出动态表单的想法,通过后端接口得到具体表单中的项类型、名称、属性、长度、正则等信息,然后前端通过类型判断生成不同的html。一查文档angular中的directive好像就是干这个事的,但是基本上都是一个标签,比如一个<icon> </icon>。而我的目标则是整个<form> </form>
想法不错,可是由于学艺不精,这个用angular我实现不出来,但是C#咱们熟啊,先用C#代码实现动态表单的工作,在使用ng-model绑定模型时发现radio类型的标签模型中获取不到值,经过测试发现还是bootstrap的老问题,该$('input')[0].checked=true,但是attr('checked')却是空,想了几个办法,后来发现一个最为简单暴力的,就是在外层的label上添加一个ng-click方法,直接将该值赋给对应的model。 
ng-click="formData.@input.Code=@radioData.Value"
@foreach (var radioData in input.InputSource)
{
    <label class="btn btn-primary" ng-click="formData.@input.Code=@radioData.Value">
        <input type="radio" name="@input.Code" value="@radioData.Value" autocomplete="off" ng-model="formData.@input.Code">@radioData.Name
    </label>
}
现在学angular貌似有点晚了,最近都是推崇其他的前端框架,像react、vue等,今天居然看到google自己也推了另一个框架叫polymer,感觉有点完全学不过来的节奏啊,不过先学通一个再学别的应该不难,如果熟练掌握了angular我也可以说自己是个基本合格的前端了吧。那个动态的form如果我能实现一定放到github上,希望有朝一日那么牛逼。

2015年1月17日星期六

以json格式发送对象集合作为参数的方法

一个页面,要同时修改多条数据,我们不可能向后端post多次来实现,可以一次post一个列表的形式将所有的数值都传给后端,然后后端统一处理。
先说前端,使用ajax技术post一个json对象是一个不错的方式,而我们的前端使用了knockout,viewModel正好也是json格式,而且knockout中还有一个ko.toJSON(viewModel)方法,非常简单,唯一需要注意的是在请求头中添加Content-Type: application/json,后端即可以自动反序列化为对象列表
var data = ko.toJSON(viewModel);
$.ajax('url',{
    'data': data,
    'type': 'POST',
    'contentType': 'application/json' 
});

再说后端,只要定义的接口参数中放入结构相同的列表就可以了
[HttpPost]
public ActionResult AfterCreditRepayNotifyDetailEdit(IList<AfterCreditRepayNotifyDetail> details)

以上过程在postman中测试是这样的: 
使用postman通过post方式传送json参数

2015年1月10日星期六

2014年总结与2015年目标

2014年已经过去了,这一年对我来说变化特别大,由于最后两个月换了工作,比原来忙了不少,所以也很少写博客了。在别人纷纷回望自己的一年时,我却累的不想打字,这个周末简单罗列一点,算是对自己过去的一年有个交代吧。
2014年经历的: 
1. 职业转型,没能转为希望的产品经理,却成了个专职程序员; 
2. 这一年,自己写过文档、画过原型、架设过服务器、接触云、从数据库到前端js代码,学了不少东西,感谢老叶的放纵,让我野蛮成长,也感谢老蒋的看重,将到带到新的平台; 
3. 自己写了个微信服务号程序,毫无宣传的情况下居然还有好几十号人订阅; 
4. 收入增加,能稍微改善点生活; 
5. 离开待了9年的公司,没有收到一句祝福与挽留,最后跟一个贱人吵了一架; 
6. 过年时带丁丁去了东北,丁丁很喜欢那里,也出奇的适应; 
7. 听了一场逼哥演唱会; 
8. 感谢所有容忍我一年的人;
现在的自己,年轻的面容早已不在,每天坐地铁时对着玻璃中自己大大的眼袋,心里也万般无奈,再该打拼的年纪自己选择了玩,现在只能还债,还好老天还算公平,晚努力总比不努力好,希望自己新的一年能有新的进步。
2015年计划如下: 
1. 购买VPS并搭建vpn与shadowsocks; 
2. 深入学习javascript,熟悉一个以上前端框架,比如Angular或React; 
3. 学会一门新的编程语言,比如php或swift; 
4. 入个MBP高配并掌握Mac系统; 
5. 锻炼身体; 
6. 每个月写一到两篇博客; 
7. 技术上继续学学学; 
8. 重构公司的系统,如果可能加入自己的产品想法; 
9. 忘记该忘记的,记住该记住的;

2015年1月5日星期一

javascript通过UserAgent判断访问设备

最近做的手机分享html页面中,有下载APP的按钮,需要判断访问设备是ios还是android系统,从而到对应的市场下载应用。
方法其实很简单,js判断userAgent中是否包含iPhone即可,再准确一点再判断个android还有分辨率之类的,但是我图省事就没做,代码如下:
function appDownload(){
    if(navigator.userAgent.indexOf("iPhone")>=0){
        location.href="https://itunes.apple.com/us/app/jin-rong-guan-jia100/id920332764?l=zh&ls=1&mt=8";
    }
    else{
        location.href="http://www.rongyu100.com/Uploads/Apps/FinaManager.apk";
    }
}
按钮点击时调用appDownload函数即可:
<a href="#" onClick="appDownload();" class="down pt-page-scaleUp">立即下载</a>

2014年11月7日星期五

比较两个数据库的不同

由于正式库与测试库有些改动未能同步修改,导致结构上有不同,安装了数据库比较工具,可是不怎么好用,而且正版需要付费,试用版功能又不全,搜索stackoverflow时发现了这个,感觉简单好用,自己之前怎么就没想到呢。
--比较两个数据库的不同
DECLARE @Sourcedb sysname 
DECLARE @Destdb sysname 
DECLARE @SQL varchar(max) 

SELECT @Sourcedb = 'AAA' 
SELECT @Destdb = 'BBB' 

SELECT @SQL = ' SELECT ISNULL(SoSource.name,SoDestination.name) ''Object Name'' ,
                CASE WHEN SoSource.object_id IS NULL THEN SoDestination.type_desc +  '' source库中不存在 -- ' + @Sourcedb + ''' COLLATE database_default 
                     WHEN SoDestination.object_id IS NULL THEN SoSource.type_desc +  '' Destination库中不存在 -- ' + @Destdb + ''' COLLATE database_default 
                     ELSE SoDestination.type_desc + '' 双方一致'' COLLATE database_default END ''Status'' 
                FROM (  SELECT  *
                        FROM ' + @Sourcedb + '.SYS.objects  
                        WHERE   Type_desc not in (''INTERNAL_TABLE'',''SYSTEM_TABLE'',''SERVICE_QUEUE'')) SoSource FULL OUTER JOIN
                     (  SELECT * 
                        FROM    ' + @Destdb + '.SYS.objects  
                        WHERE   Type_desc not in (''INTERNAL_TABLE'',''SYSTEM_TABLE'',''SERVICE_QUEUE'')) SoDestination ON SoSource.name = SoDestination.name COLLATE database_default AND SoSource.type = SoDestination.type COLLATE database_default 
                WHERE   SoSource.object_id IS NULL OR SoDestination.object_id IS NULL
                ORDER BY isnull(SoSource.type,SoDestination.type)' 
EXEC (@Sql)
发现sys.objects表中不包含索引,于是再写了一个查询sys.indexes的,具体需要哪些字段还需要修改。
DECLARE @SQL VARCHAR(max)
DECLARE @ADB sysname
DECLARE @BDB sysname

SET @ADB = 'AAA'
SET @BDB = 'BBB'

SET @SQL = 'SELECT  CASE WHEN A.object_id IS NULL THEN ''' + @BDB + ''' + CONVERT(VARCHAR(100),B.object_id) + ''' ''' + B.name
            WHEN B.object_id IS NULL THEN ''' + @ADB + ''' + CONVERT(VARCHAR(100),A.object_id) + A.name
            ELSE A.name + '''双方一致''' END AS Result
    FROM    ''' + @ADB + '''.SYS.indexes A FULL OUTER JOIN
            ''' + @BDB + '''.SYS.indexes B ON A.name = B.name
    WHERE   A.object_id IS NULL
            OR B.object_id IS NULL'
EXEC (@Sql)

悬浮按钮

需要在一个浏览页面添加编辑的按钮,看了下页面,有点长,右侧比较空,所以想在页面右侧添加一个悬浮按钮,由于对css不熟,在网上搜了一下,都是特别费事的。自己冷静下来想了想,不就是对上方和右方的相对位置吗,css完全可控制,按钮就用a好了,直接链接到编辑页面去,最省事。
<div style="position: fixed; z-index: 999; right: 15px; top: 150px; ">
</div>
z-index是控制层的,数值越大越靠上,最后div里面加个a就好了,就是这么简单。 
另外发现css中选择器会有选不中的情况,这时带上上层结构就可以了,可能是css之间有冲突。

2014年10月22日星期三

坑爹的azure - windows 2012打开framework3.5功能

早就听闻azure坑,今天总算被坑到了。
新建了个Windows 2012 R2的虚拟机,在系统中需要安装framework3.5功能,可是2012又不像2008那样直接选中打开此功能就可以,微软你确定这样出尔反尔毫无立场的变化好吗,于是我花了一下午的时间在试验各种方法上。
经测试以下方法都是错误的: 
- 指定本地安装源 
- 修改DNS 
- powershell安装
最后我打开了windows update,打过补丁之后再打开framework3.5功能居然奇迹般的好了。

2014年9月30日星期二

One Flew Over the Great Fucking Wall

昨天名为instagram的著名图片社交app被墙,据我猜测可能是因为最近instagram上直播香港关于人权、普选的抗议活动越来越多,为了防止广大墙内的国人被恶意境外势力影响愚弄,伟大的中央政府紧急在GFW上屏蔽了这个全球最火的社交应用,再一次捍卫了我人民民主专政的纯洁。

首先我得承认我是instagram的重度用户,如果不是特别累每天都要刷个至少3次,我喜欢上面全世界各地的人们分享的美图,有专业的摄影师用专业的器材拍出令人震撼的照片,更多的是普通人用手机拍的生活,微信的朋友圈就是copycat这个(PS:总有人说微信是个伟大的产品,我真不觉得,里面的每一个功能都是照搬过来的,如果没有腾讯强大的用户数量和伟大的墙,微信真的做不大,这个以后再说)。
我最喜欢在insta上看冒险、生活、风景、人像这几类的照片,通过这些照片感受自己可能一生都没有机会到达的地方、一辈子无法遇见的人,体会其他人的生活,学习摄影的构图、光线等等。而这个app做的又非常棒,简洁、高效,每一个功能都不可或缺,每一个操作都非常自然,从产品与技术的角度来说,这是一款非常棒的产品,从内容的角度来说,可以说insta是twitter的图片版,而图片更能令人产生深刻的印象,这样一款产品没法让人不喜欢。
可就在twitter、facebook、google+这些社交网站一个个被墙之后,instagram也加入了这个行列,正面上说明其已经具有可以与一线公司竞争的实力,可也注定失去了中国的份额,墙内市场肯定会被模仿者瓜分掉,LOFTER虽然用户体验非常不错,但是从见识上来说我更倾向于instagram。当然这些是次要的,主要的是墙内政府的态度,记得习大大在上台之前外媒普遍叫好,上台后实行的一些改革也有很多鼓掌者,我不懂政治,不懂得这里面的利弊,但是作为一个人,我可以感受到自己的生活,现在与过去并没有实质性的转变,广东一个人告中国联通不让访问google,意料之中的败诉之后回到家中马上就来了police将其带走;李大眼因为批评政府被迫到美国躲避;侩子手赵白鸽堂而皇之的去赴任红会,墙内的愚民每天更多的是在微博上狂欢,而不是探索这个未知的世界,当“老公,艹我”大行其道,而“正义、真理、民主、自由”这些词再也不见时,这个国家这个民族还有未来吗。
从接触到的香港人来看,他们自信、干净、小气,对内地人有点优越感,虽然有时候对他们有些不爽,但是对于他们游行的活动,我完全支持,任何反民主反自由反人类的事物最终都将被推翻,希望港人自强不息,这次社交网络被墙,肯定是有一些行动不希望墙内人看到,愿港人平安。最有引用飞越疯人院的名字,愿我们都有One Flew Over the Great Fucking Wall。

2014年9月26日星期五

谈谈iphone6的大屏对用户使用习惯与APP交互方式的改变

这个月初,大屏iphone终于千呼万唤始出来,一口气推出了4.7和5.5寸屏两个版本。在乔老爷坚持了几年“手机好不好,不能比大小”的原则之后,库房总管终于向市场妥协,顺势而为推出大屏手机。虽然现在的iphone已经走下神坛,不再是手机业界无法企及的高度,但每次推出的新品仍然是东西两半球最好用的智能手机,没有之一。随着越来越多的人选择大屏肾6,那么它也将会改变人们的一些手机使用习惯,以及一些app的交互方式。

更多的双手操作

虽然现在每个大屏手机厂商都考虑到了单手操作的问题,但是真正完美解决的可以说没有,苹果也一样。男性尚且无法完全hold住,手小的女性又喜欢用大屏看韩剧的就更无法驾驭了,于是双手操作肯定成为必然,当然这对于那些从安卓转移过来的用户说基本不是问题,因为他们已经过了适应期。双手操作多了也会有一些麻烦,比如公交车上不好抓扶手了,比如拍照或视频时一只手抓不住,希望以后不要听到车主因为发信息双手脱离方向盘发生事故,罪魁祸首竟是大屏iphone6的新闻吧。

更多的下半屏的交互

很多app中的一些菜单,比如分享功能,有的多的可能几乎占满整个屏幕,如果在大屏iphone上估计这样的交互是不合理的,毕竟人家官方都把电源键挪到侧面了。所以以后这类菜单应该尽量只占用下半屏就好,因为屏幕宽了,每排可以多放几个,所以改起来应该很简单。而我最希望的是上拉的快捷工具可以放置更多。

更多的手势操作

苹果的Magic Mouse是个怪物,喜欢的人非常喜欢,厌恶的人非常厌恶,但是无论多么厌恶的人都必须承认它上面强大手势操作,这也是这款鼠标最大的特点。而且苹果笔记本的触摸区,以及Magic Trackpad都可以使用同样的交互方式。如果大屏手机上也能够实现一部分手势操作,对于重度苹果用户来说是非常舒服的事情,而且大屏也有这个条件。之前的优酷视频上已经支持一些手势操作,所以用户体验得到质的提升,但那还是停留在app层面的,如果系统层面直接支持的话,相信很多app的界面都会做很大的调整,而使用者用起app来都像是在“打飞机”。

更多的分屏应用

记得以前安卓刚出来3.0版本时是为了大屏机器推出的,当时很多应用都有一个对应的大屏版。ipad推出后,ios的应用也有iphone版和ipad版,比如qq,在ipad上就是左边显示好友列表,右边显示聊天窗口,比手机qq方便,这就是典型的分屏应用。而iphone6尤其是plus的尺寸已经允许做这种尝试,比如邮件app、笔记app等等,在横屏时就可以作为分屏显示,用户则会获得更少的操作及更多的信息。

更多用于存放大手机的空间

以前iphone都是直接插裤子口袋里的,换成大屏之后会很不舒服,而且很多网站都评测了iphone6更容易变弯,如果不想让其他厂商用户开启群嘲模式,那么最好把手机放在包里的专有空间,据小道消息以后的哎呦喂和哭去都会加装一个内袋,按照iphone的屏幕大小分为3个版本,对于这个本人不负半点责任。


不管怎么说,iphone都是一个好产品,一个改变世界的产品,一个能让大部分用户满意的产品,时代总会发展,也许未来的手机又会回到一个百家争鸣的时代,让我们一起拥抱变化吧。

2014年9月16日星期二

使用godaddy+dnspod注册域名并解析的过程


由于公司就是有这种业务,以前朋友购买域名空间邮箱什么的,我都是直接在公司注册的,但是国内注册域名有很多阻碍,程序员们基本都不会选择国内注册服务商,于是狗爹和name成了首选,还有一些直接走淘宝的,都不需要任何证件和备案,麻烦与风险少了很多,今天自己试着走了一下注册全过程,还是很简单快速的,记录下来给需要的朋友使用。

godaddy注册域名

  1. godaddy注册;
  2. 使用搜索框搜索自己心仪的域名;
  3. 添加购物车然后付款,付款时会遇到点小麻烦,因为godaddy目前不翻墙没法访问,而翻了墙又是国外的IP地址,于是狗爹就认为不是中国的用户,所以支付宝会不成功
  4. 在此网站可以拿到狗爹的优惠码,使用这里的优惠码就可以使用支付宝付款了

dnspod添加解析

  1. dnspod注册;
  2. 添加域名;
  3. 在域名下面添加记录;
  4. godaddy登录后点击domain下的Lauch按钮 图片描述在对应域名右方的下拉菜单中选择“Set Nameservers” 图片描述弹出层中选择“Custom”后,下面点击“Add Nameserver”按钮 图片描述  在这里将dnspod默认的@记录填上即可,之后的一切解析都在dnspod中操作即可,比如像这个博客添加blog域名就是添加CNAME记录。


整个注册+解析过程不超过两个小时,如果是熟手的话估计10分钟就可以搞定,比国内供应商注册快了不知道多少倍,而且价格也便宜,以后是不是可以开个代理呢。。。