2017年9月从上家公司离职到现在,足足有1年半了,现在我把这一年半摸爬滚打总结出来的经验传授给大家。咳咳,开玩笑的,我也在不断的学习中,不敢妄自尊师,写这篇文章主要是想把自己的一些看法和想法以及处理项目的方法分享出来一起交流,说不定会遇到高人指点,突破瓶颈。

创业,九死一生,别说能不能赚钱,能把项目做出来上线已经不错了。所以没有背水一战的决心,真别趟这塘浑水。虽然自个儿做项目很自由,但要做好与孤寂为伴的准备,而且,改需求是必须的,等你真做起来了,很多时候,自己都想砍自己。更重要的是,要有恒心,做事不能半途而废,要废,就要在一半之前就给废了,止损。

我在上家公司呆的是前端岗位,担任待定架构师,在公司做前端是没有架构师这个职称的,所以“待定架构师”是我自己取的[/手动滑稽]。我想做架构师,但是没有后端的工作经验,所以,离职出来历练历练,要不然,一幌到了35岁,怎么被辞退的都不知道。

本文讨论的是个人开发的小项目,对刚入行的小白应该会有些启发,对于每天要处理上百万数量级系统的大神可能没什么助益。

需求

学会使用辅佐工具去梳理需求

不管做什么项目,都应该先清楚自己要做什么,然后才去思考怎样做。所以,思维导图和原型图是很重要的。我不是专业的需求分析师,高级点的原型设计软件基本没用过,只会画画脑图,写写流程,推荐使用百度脑图ProcessOn,在项目开始之前理清思路,少走弯路。

  • 我创业初期构思要做一个APP在淘宝上卖的百度脑图

  • 我当时想要做的APP原型图部分,用ProcessOn画的

虽然画得很简陋,但,至少能让自己心里有底,大概知道要做点什么,不至于无所事事,终日惶恐,不知所措。

这里推荐两个画时序图的网站,在v2ex看到大神们用的

PlantUML原版 http://plantuml.com/zh/

大神汉化版 http://haha98k.com/

不要执着于设计完美的原型图

事实上,你的脑图是不可能画得很详细的,问题往往会在项目开发过程中渐露头角,项目进展时间越长,问题就会越多越复杂。所以,项目构思完之后尽快动工,去搭建项目架构。

很多时候,你在原型上花尽心思,自认为滴水不漏的设计,到了项目实施的时候,很可能会成为项目进展的最大阻碍。想实现这个功能,但是要花费很多时间,如果放弃这个功能嘛,又已经花了很多精力去设计。就是那种一桌子菜,为了开一罐死活打不开的老干妈,菜都凉了的感觉。遇到这种情况,要懂得取舍,果断放弃。

我就曾经因为想做桌面应用的自动升级功能折腾了一周,最后弃坑改成 Web应用。

以前在公司,如果我觉得某些功能不合理,或者太难实现影响进度,我会去和需求人员讨论,说服领导变更方案。现在霸气点,直接把需求砍了。注意,是砍功能,不是砍人哈。

考虑项目完成后的事情

想清楚要做什么后,也要思考思考做完后的结果是什么,也就是自己的最终目标。例如:

  1. 赚钱,迎娶白富美。最俗最现实的目标。

  2. 从项目中吸取经验,提升技能,找份好工作。

  3. 享受编码带来的乐趣。

如果你的目标是1,那么你必须要认真的去思考销售渠道和营利模式。

如果是2,那么你就不用管做出来的东西有没有人要,难度越大越要挑战。

如果是3,你现在应该沉溺于你的代码中,不可能看到这篇文章的。

我的第一个项目,就是上面两张图设计的项目,做了3个月,果断放弃了,因为市面上这类产品已经很多很成熟,饿了么、美团,是不是有点像?这个项目最失败的地方在于我在原型设计上花费太多时间,以及怎样销售、怎样推广到市场,有什么优势可以让商户用我的产品这些问题都没有考虑。

所以,我这一年半最终的产品是另两个项目——好货记和客咨宝,两个产品的完成时间差不多各两个多月吧,一年半里更多的时间是花在运营和推广上。

不要闭门造车,要敢于接触陌生

现在是互联网时代,能从互联网拿到的信息,都不要怕多。想到要做什么,就去网上找,参考别人的经验。因为人,甚至世界上所以的现代生物,都是进化而来的,进化就需要积累。这句表达有点云里雾里,请原谅我措词不佳。我想说是的,人对于陌生事物往往会产生愄惧,对不可预知的结果不敢随意触碰。

比方说,我上高中那会,教室讲台有一台电脑,很多同学经常偷偷撬锁打游戏。有一次,我和一同学在玩拳皇,游戏突然卡了,我那时不懂电脑,只会按几个方向键。同学去点“注销”,我拦住了,因为我不知道点了这个按钮之后会发生什么,生怕“注销”会把老师的课件都删了。因此我建议重启电脑。同学没管我,坚决点了下去。这我才知道注销是切换用户。

虽然人类是高级动物,毕竟怎么说,也是动物。事实上,人类的所以行为,都是应激反应,只不过比草履虫高级无数倍。我现在在写这篇文章也是出于某种刺激的回应,而这个回应要比草履虫的回避运动要复杂得多,要出洞N多细胞,包括运动细胞(写)脑细胞(思考)等等并花费好几天时间去回应这个刺激。

我生物学得不咋样,专业名词不太会用,大家能理解就好。这里科谱一篇知乎的文章,我觉得挺有意思,大家不妨去看看《人类有没有可能是被设计出来的?》

我也相信人类不是被神设计出来的,而是环境达到了生物存活的条件产生了生物,从而进化成人类。既然这样,那灵魂存不存在?人类为什么会有情感?

这种问题可能现在还没有人能确切肯定地回答,就算现在有了答案,随着科技的发展和人类认知的提升,都可能会把现有的答案推翻。所以,我就说说我的个人见解,完全是脑细胞胡乱碰撞产生的解释。

灵魂应该是不存在于本身个体里的,意思是说,我的灵魂不在我这里,而是在你那里。而且我的灵魂不止一个,有多少人认识我,我就有多少个灵魂。因为灵魂不过是他人对我的认识,是我的存在对别人产生的影响罢了。

这样恰好从另一个角度解释了臧克家的“有的人活着,他已经死了。有的人死了,他还活着”,还有《寻梦环游记》有句话说“真正的死亡是世界上再没有一个人记得你”。但是,“我是谁?我从哪里来?要往哪里去?”至今还是无法解释。自我晓事以来,也常常问自己,为什么世界上会有我?

撇开哲学不说,我们来聊聊感情。人的大脑是一刻不停地运作的,记忆碎片会不停地碰撞从而产生新的画像,我们就是通过这些画像去了解世界,创造世界,这里说的画像不是真的画像,而是包括了看闻听触等所有感觉。当

我们受到外界刺激时,例如看到什么,听到什么,触碰到什么时,我们大脑的记忆会深刻、感到真实。当没有外界刺激,例如睡着了,感触器官都休息了,记忆碎片就会产生梦。

再说情感,就是大脑神经碰撞产生的另一种感官,区别于看闻听触,它的产生直接来源于大脑,是眼耳口鼻这些器官感觉的综合表现。以前听说人类和牲畜的最主要区别是人类有感情,其实不然,猫狗鸡鸭也是有感情的,只是没有人类表现得那么强烈。

人类很渺小,所有认知都局限于他所活动的空间,对未知事物的解释,仅能通过已知事物的联想瞎猜,猜中就是真理,猜不中就是谬论。宇宙到底有没有边界,如果有边界,那么宇宙外面是什么,如果没有边界,你能想像无限是什么样子的吗?

我们都知道 10 / 3 小数点后是无尽的3,圆周率是无限不循环小数,难道这些就是无限的样子?抑或宇宙其实是有边界的,宇宙的外面是原子,就像两面镜照在一起,镜子的里面是镜子,镜子的外面还是镜子,只是人类目前还没有这个能力去触达宇宙的边界。

胡乱扯了一通,总结来说就是,你不敢去探索陌生的世界,你就永远只能活在狭窄的世界。我做好货记之前对进销存也是一窍不通,因为身边有很多做生意的朋友,所以我决定去试一试,尽管这个市场竞争很大,总会有吃剩的蛋糕的。

为了了解这个行业,我研究了好多款进销存,金蝶智慧记、账王、易订货、易特进销存、管家婆,还有好几款我都记不起什么名字。最后把它们比较通用的几个功能筛选出来完成了好货记。因为每个行业对进销存的要求都不一样,所以我只做了基础版,以后针对某个行业去定制也比较方便。如果我不去接触这些陌生的软件,可能现在也不理解什么是采购、什么是盘点。

开发

用自己最熟悉的技术

相信没有哪个项目不是时间赶工作量又大的,就算是自己的个人项目,也应该给自己一点压力,否则等你的项目出来,这个世界已经变了。用自己最熟悉的技术可以让项目写得顺手,同时信心倍增。

我是前端出身,对 js 最了解不过,所以选了用 Nodejs 写后端。起初还担心 Nodejs 会有性能问题,毕竟只用它写过工具,没做过服务。后来证实,50多人同时在线,用 Socket.io 互发消息,服务器是 i3 处理器,4G内存的 windows7 系统,丝毫不觉得 Nodejs 有什么压力。

而且在网上查到的数据,Nodejs 每秒可以响应上万个请求,像我这样的小项目,根本不需要考虑后端的性能问题,除非代码写得特别烂,循环没结束条件之类的,自己把自己给绕死了。

前端三大框架,Vue 最易上手,而且接触 Vue 也有一段时间,就不去折腾 React 和 Angular 了。数据库,一开始选了 SQLite ,它体积小,容易安装,又是我上大学时学过的关系型数据库,虽然网上更流行 NoSQL 与 Nodejs 搭配,但是为了赶项目,我还是保险选了关系型数据库。

后来,实践开发,发现并发一高,或者连续密集请求数据库,SQLite 很容易出现死锁,所以最后还是乖乖用老牌子 MySQL 。

前端项目搭建我没有用流行的 webpack,而是用了自己写的 JTaro-Module 来管理模块,原因很简单,自己写的东西自己都不用,说不过去。况且我已经习惯了在 HTML 里找组件对应的文件,这是 JTaro-Module 的一个特点,如下图

每个组件都带有 jtaro 前缀标记,例如jtaro_pages_layout对应的是/pages/layout.js文件,jtaro_common_content对应的是/common/content.js,随着时间推移,项目逐渐庞大,我再也不怕找不到上周写的组件了。

当然,如果你熟悉的技术已经明显落后于这个时代,学习新技能是在所难免的,生搬硬套只会毁了自己。起初,我只在写 Nodejs 时用 ES6+ 语法的,写 Vue 组件始终用 ES5,就是为了兼容更多浏览器,后来渐渐发觉,写 ES5 的效率远不及 ES6+,而且还要时刻留意不要在浏览器端写 ES6,一个字,真TM累。

为了解决这个问题,学了一天 babel.js,把它搞到打包工具里去,妈妈再也不用担心我写错语法了。前端用 ES5,后端用 ES6,都是 js,两边开工,大脑都切换不过来,就更不用说后端用其它语言了。所以,个人开发,用 Nodejs 写后端,绝对省心省事。

再说我一个写前端的,把工作从后端挪到前端,效率肯定会有所提升。所以我把能交给前端的工作都交给前端,后端只负责增、删、改、查和权限校验,排序、筛选这些工作都在前端做。这样一来,服务器的压力降了不少。打个比方,本来只支持1000人同时在线的服务器,现在可能可以支持2000人同时在线。所以现在前端的工资越来越高也是有道理的。

编写可测试的代码

印象中,我读过一篇文章,标题就是《编写可测试的代码》,当时没看懂,现在网上很多类似的文章,一搜一大箩筐,建议看看。直到我在开发客咨宝时遇到一个问题,才意识到编写可测试的代码的重要性。

遇到的问题是这样的:“我开发了一个权限功能,部门主管只能看到自己部门以及子孙部门的数据,不能看到兄弟部门和父级部门的数据。理想是美好的,现实是客户发现了兄弟部门看到了自己部门的数据。”即是,我写的这个功能有bug,我要拿这个获取部门的方法出来测试。如果不单独拿出来,整个系统一起测,要修改很多遍数据库,工作量很大。单独测试一个函数的功能,就叫单元测试。所以编写可测试的代码,模拟些数据来测试,毋庸置疑是提高工作效率的一个办法。

  • 业务代码 /server/staffment.mjs

/** 获取部门及子部门
* @param id Number 要查找的部门ID
* @param staffments Array 所有部门的数据
* @return Array 一维数组,部门及子部门id
*/

export function getStaffment (id, staffments) {
...
}

  • 测试代码 /test/getStaffment.mjs

import { getStaffment } from '../server/staffment.mjs'

// 捏造的部门数据
const d1 = [{
id1,
parent_id0
}, {
id2,
parent_id1
}, {
id3,
parent_id2
}, ...]

// 获取ID为2的部门及子部门数据
const r1 = getStaffment(2, d1)
// 比较实际与预期结果
console.log(r1.join(',') === '2,3')

如果 r1 的结果与预期一致,表明这个测试用例是成功的,如果输出的是 false,就要检测 getStaffment 方法哪里出了问题。

当然这里只是演示一下简单的写测试用例的方法,实际项目,要捏造很多数据,要考虑很多情况,例如:parent_id 比 id 大,并列多个 parent_id 相同的部门等等。如果要系统化的去做测试,建议学习一下自动化测试,我不是测试领域的专家就不多嘴了,怎样编写可测试的代码,这里给两点建议:

  1. 一个函数只负责一件事。例如,获取部门的方法只获取部门,不要把计算权限的代码也混进去

  2. 可导出。可以用 export 导出,让测试文件引用。那些私有方法,简单得不用测试的就没必须导出

这里有一篇阮老师的《函数式编程初探》建议去看下,函数式编程有利于代码的测试和排错。当然,不要为了写函数式而写函数式,面向对象编程在某些场景也十分重要。

能实现功能的陌生技术也应该去尝试一下

多掌握一项技能就多一条出路。不要因为只会写 Nodejs 就所有功能都用 Nodejs 做。如果想做一个功能,但是尚未有人用 Nodejs 实现,或者 Nodejs 做的版本不够好,而有其它语言已经实现了且相当完善,这时候应该考虑一下能不能用 Nodejs 调用其它语言写的功能。

我就吃过这样一回亏。要做 Excel 导入导出的功能,有两个方案:

一、js-xlsx, JS 语言写的。免费版,不能保存模板原有格式,收费版才能保存模板原有格式;

二、Excelize, GO 语言写的。完全免费,完善强大,可以保存模板原有格式。

因为我只会 JS,所以选了 js-xlsx,放弃模板原有格式。还没赚钱,不敢乱花钱。后来做“导出自定义Excel”功能,实在没办法,对于一个没资本的人来说,唯一可以换钱的就是时间。

于是便硬着头皮学了一周 GO,然后用 GO 编写“导出自定义Excel”的功能。GO 语言最终产物是一个可执行文件,用 Nodejs 去调用即可。前面用 js-xlsx 已经完成的功能,我也没去改成用 Excelize 重新实现,过去了的,没毛病就不要去改,把握项目进度才是重点。

不要盲目前瞻,要把基本功打好

ES6 已经流行了好一段时间,前端面试基本都有问到,从而很少人会再回去关注 ES5,甚至 ES3,这是很不好的现象。如果不打好基础,前人已经解决了的问题,我们又会重新折腾一番。

拿我的一次开发打印功能来说,在谷歌浏览器,执行window.print()就会弹出打印预览的窗口,但这个预览窗口是整个页面的,而我只想打印页面中的一个表格。

开发这个功能的时候,我忘记了 css 的媒体查询有针对打印的样式,css2 就已经支持。用@media print设置打印时除了要打印的内容,其它全部隐藏即可,而我,则大费周章的创建 iframe 把要打印的内容复制进去。

还有实现打印多页保存页头和页脚的功能。即一个很长的列表,要分几页才能打印完,每页都要有相同的页头和页脚,而在浏览器里只显示一个页头和页脚。而我的解决方案是,限制了打印条数,超过 1 页的,要手动另建一页才能打印。

后来在一篇博客里看到,用 table 就可以轻松解决这个问题。thead 和 tfoot 都会在每个打印页出现。读书时老板就教我们不要用 table 来布局,所以我一直以为 table 基本是废了,没用的,没想到用于显示数据和打印是多么的强大。

平时有空就多看看经典文章,看不懂没关系,要用到的时候说不定就想起来了。有些时候可能旧技术比新科技还实用。

过滤用户输入

所有用户输入都是不可靠的,所以必须对用户的输入进行过滤,保证传给数据库的字段是符合数据库定义的。

我做了一个用 Excel 批量上传数据的功能,功能包括过滤重复电话号码,但客户老是发现有重复的数据。而我,怎么也重现不了。后来让客户把他的 Excel 发我,才发现,他的数据都是从别处粘贴进 Excel 的,有的数据识别成数字,有些识别成字符串,而恰好有相同的电话号码,一个是数字,一个是字符串,我在去重的时候没进行格式转换自然就认为是两个不同的电话号码,传到数据库,都转成了数字格式,就重复了。

储存数据类型错误是个小问题,受到 XSS 攻击才防不胜防。如果要做安全级别高的系统,应该对所有请求进行校验,只要不符合预期值的都拒绝访问。

不要把代码写死

不要把代码写死,作为开发人员,我们经常这么说,但是怎样才叫“不要把代码写死”?

例如,我们要定义一个数据库字段来保存“2019-03-20”这样的一天时间,应该把字段定义成CHAR(10)吗?看上去,好像真没毛病,但是这就叫做把代码写死了。因为把时间固死是10位了,如果某天,需求要保存到分钟,怎么办?再扩展几位吗?再后来要精确到秒呢。

如果真这么做,拿历史数据的时候就会出现3种格式的数据,出现bug的机率就大。所以一开始就应该把时间保存成时间戳1553040000000,把字段定义成BIGINT UNSIGNED,不管以后需求要什么样的时间格式都可以用时间戳转换。

再如,我们画一个表格

<table>
<tr>
<th>序号th>

<th>姓名th>
tr>
<tr v-for="(d, i) in data" :key="i">
<td>{{ d.index }}td>
<td>{{ d.number }}td>
tr>
<tr v-if="d.length === 0">
<td colspan="2">暂无数据td>
tr>
table>

后来要加一列操作,修改如下

<table>
<tr>
<th>序号th>

<th>姓名th>
<th>操作th>
tr>
<tr v-for="(d, i) in data" :key="i">
<td>{{ d.index }}td>
<td>{{ d.number }}td>
<td><button @click="del(d.id)">删除button>td>
tr>
<tr v-if="d.length === 0">
<td colspan="2">暂无数据td>
tr>
table>

是的,我们很容易就会把暂无数据里的 2 忘记改成 3,我们开发的时候经常用模拟数据,很少会观察无数据的情况,这样就会导致上到生产,客户会看到“暂无数据”一行少了一块。

我们可以把colspan的值让它自己计算

export default {
data () {
return {
th: ['序号', '姓名', '操作']
}
}
}

<table>
<tr>
<th v-for="t in th">{{ t }}th>

tr>
<tr v-for="(d, i) in data" :key="i">
<td>{{ d.index }}td>
<td>{{ d.number }}td>
<td><button @click="del(d.id)">删除button>td>
tr>
<tr v-if="d.length === 0">
<td :colspan="th.length">暂无数据td>
tr>
table>

要积累很多的项目经验才能做到不把代码写死,光看几个例子是不行的。关键是要多练多思考。

正确对待开源项目

我们要把项目组装起来,为了节省时间不重复造轮子,使用开源项目是在所难免的,我做的项目就用到了 Vue、axios、rollup、js-xlsx、Excelize、uglify-js、crypto-js、babel 等等列举不完的开源项目。

我们对待开源项目应该保持一种敬畏之心,相信开源项目会按照它的文档描述那样工作是应该的,但是我们不能一味的信任或者一味的猜疑。如果发现开源项目有 bug,应该报告给该项目的维护者,而不是嗤之以鼻。

Vue 的粉丝很多,黑粉也不少,三大框架谁优谁劣的口舌之争我也看过不少。可是,这并不是我们该关心的问题,我们熟识哪个框架就用哪个框架,能把项目做起来,养活自己才是硬道理。不过话说回来,开发这工作百般无聊,偶尔看看前端娱乐圈的无谓之争也挺放松心情的。

我也是一名开源项目作者,也曾经深深的感受过恶意。前两年我在 IScroll 群上推广 JRoll,本意是想告诉大家,IScroll 的作者已经不维护 IScroll 了,还有 JRoll 可以用。JRoll 是我的一个用于 H5 移动端可替换 IScroll 的滑动插件。后来,群上有位仁兄问我,用我的 JRoll 很卡,怎么办?

我让他把代码发我,一看,傻眼了,300张图片一次性全部渲染出来。我跟他说可以用 JRoll 的 Infinite 插件分批加载。他让我帮他弄,我把 JRoll 官网上的例子发他后就没理他。

见我不帮他,他便开始恶语相加,至于他说了些什么我就不去翻记录了,当然他也不是一撇烂嘴什么恶毒的话都说,大概就是说了些这是 IScroll 群,就你那破玩意自己建个群去,写的什么垃圾之类的话。“恶语相加”是形容我当时感觉良心被狗吃了的心情。

后来群上其他成员按耐不住,一边倒是帮我说话的,还有个人加我跟我私聊说,像您这样的大神是不应该出现在这种群上的。然后我就很开心的退了群。

后来我也没建 JRoll 的群。因为我明白了一个道理,不是每个人都值得帮,建群只会徒增烦恼,更何况 JRoll 并没有给我带来多少收益,开源4年了,大概就收到了几千块赞助费,都是有偿要帮人家解决问题的。

再说一个不值帮的案例,我在健身房遇到一中年大叔,想想我也中年了,他就是那种比我还要大10岁的中年老叔。见他双臂拉环,不站马步,不挺腰板,用一股死力往下拉,我过去跟他说,这样练会伤身,我示范一下给你看。

结果他语气很不友好:“我还没练完,你一边等着”。这。。。好吧,我又不稀罕这器材,您继续。还好他块头比我大,不然我就动手了。

说到健身,不管你是创业还是打工,反正你想赚钱,就必须要锻炼身体,不然再怎么努力,也不过是把健康提现罢了,以后想用金钱挽回健康是要打折的,利息还很高。

再次明确一下对待开源项目的态度:

1、任何项目都不可能完美,不要执念大神写的就一定没问题。我有一同事就是坚信 IScroll 的 freeScroll 选项没问题,导致白加了3天班。而我去研究 IScroll 的源码,写出了 JRoll。

2、出了问题不要抱怨,有能力就去提交贡献,没能力就去提交问题,当然也可以选择不屑一顾,但不要浪费时间去争论无意义的事情。

3、开源不等于免费,可能人们经常把“免费”和“开源”这两个词放在一起,所以大家觉得开源就是免费。事实上是,写了免费开源的才是免费,没写免费的开源项目,都是收费的。不可能开源作者个个都是神,不用吃饭也能工作的吧。

敏捷开发,尽快把项目跑起来

我们要建个小目标,比如先赚它一个亿。小目标是必须的,有没有一个亿,看能力。做项目,一定要先把基本能用的框架搭起来,然后再逐渐添加业务。长期看不到成果,士气就会怠懈,工作效率降低,工期延长,看不到成果,进入死循环。

拿我做客咨宝做例子来说,这是我和一同学一起做的项目,我负责技术和运维,他负责需求和销售。一个客户资料管理系统,虽说简单,包含的内容也不少,工作流水线、客户数据统计、最佳员工评选,大致可以分成这3部分。

如果全部做完再上线,起码得3个月,而且中间肯定会有很多变动,全部做完再给客户看就会出现浪费劳动力的问题,该做的没做,不重要的反倒都做了。

我做客咨宝的时候是参考同学给的一个系统,那个系统很多功能是他们不需要的,需要的功能又没有。

  • 第一步,明确需求。他先给了我一份 word 文档,标记了哪些是要做的,哪些是不用的。然后我再把那份 word 文档圈圈画画,用红字标记疑点,他再作答,这样一份需求文档基本完成。

  • 第二步,快速开发。我把影响主要工作流程的模块梳理一遍,建立数据库。主要就是上述的工作流水线部分。包括的功能模块有:用户登录、部门管理、录入客咨、编辑客咨状态,这样一精简,工作量就没那么吓人,两周搞掂。用户修改密码、删除部门、删除客咨这些功能都没做。

  • 第三步,交付。工作只完成了10%左右,已经部署给我同学看了。他会把整个主线流程测试一下。然后提出修改。等我收到反馈可能是两三天之后的事。这期间,我可以把用户、部门、客咨的修改删除功能给干了。

  • 第四步,继续迭代。第一个版本交付之后,同学已经拿这个半成品系统在他们公司用起来了。他们遇到问题,我再远程处理,解决 bug,升级系统。有问题的数据直接修改数据库改正。就是这样边人力运维边迭代开发完成整个系统。

说到人力运维,我真去过一家外包公司,所幸我不是和他们一个项目。他们确确切切是不打折扣的人力运维。他们系统每天都会收到有问题的数据,然后人工审核修正。

系统太旧,没人肯去追踪这个 bug,只能加岗位安排人员去跟进有问题的数据。所以,前面说到的编写可测试的代码是多么重要,如果你解决不了 bug,就得天天人力运维,根本没时间去开发下一个功能。

古时候打仗,兵马未动,粮草先行。现在做项目,数据好比粮草,没有数据,前端就没有东西展示,空荡荡,样式也不好调。所以,建议先做后端,把调用数据的接口都搞出来再做前端。

分享一个我做登录功能的方法,可以持久化登录,也实现异地登录把原地踢出的功能。参考了几篇文章,然后凭自己半吊子的后端水平设计的。

  1. 前端发送用户名和sha1加密过的密码

  2. 后端检验用户和sha1加密过的密码,数据库保存的也是sha1加密过的密码,所以直接比较即可。密码字段是固定40位,也不用限制用户对密码框的输入长度。为安全起见,也顺带把客户端ip保存起来。校验成功,返回一个token,随机生成即可,最好是由字母和数字混合生成,6位以上

  3. 校验失败,返回错误信息

  4. 前端把token保存起来,放在cookie或localStorage都可以,前端请求数据时带上token

  5. 校验token和客户端ip,成功则返回数据

  6. 失败则返回登出信息

个人项目就没必要搞接口签名这套复杂的流程了。

关爱协作开发人员

这是题外话,人与人之间交流应该相互尊重、相互体谅。

创业这段时间,我接过3个半月的外包,赚点外快。期间有位新人加入项目,他过来问我一些关于项目的情况。其实我脾气还算可以的,但是他一过来就称兄道弟,勾肩搭背,脸贴脸地说话,关键是他抽烟也有口臭,我一直憋着气听了一路,实在忍不住,就好不客气的说,我很忙,有事QQ聊。

人与人之间应该要保持一点距离,毕竟久坐的人有口臭,多动的人有体味,活着已经是件不容易的事,就不要再互相伤害了。

还有一件事,是我的疏忽。这个外包项目,前后端都是一个 SVN 仓库的,前端在后端仓库的一个文件夹里。后端要发布时,就直接把前端打包好代码压缩成 zip 上传到生产服务器。

每次都上传好久,而且 zip 包越来越大,峰值达到 70M。后来一次偶然的机会,后端同事休假了,我帮忙压缩上传。才发觉不对劲,前端代码怎么这般大,通常不包括图片资源的话,超过 2M 已经不得了了。

查了一下差点吐血,把 .svn 的文件都压缩进去了。如果前后端大家平时多交流一下,就不至于浪费了这么久的时间和精力。除去环境和依赖包,后端的代码应该也不会很大,反正我写的项目,后端代码体积还不足前端的十分一。

推广

关于推广,我没什么好的建议,就随便聊聊,我现在还在推广这条路上摸索着。

  • 我写过爬虫爬取互联网上企业官网留下的电子邮箱,然后自己搭建邮件服务器去发广告邮件。发一万封,大概只能带来10个访问量。效果如同石沉大海。当然,我有做去重处理的,保证每个邮箱都只会收到一次我的广告邮件,发件频率是1分钟10封,绝对不会造成网络拥堵。我不建议大家这么做,因为我爬取了5万条数据,除去重复和无效的,剩下不到2万条。关键是效果不咋地。难度大,成效低。

  • 给钱给百度、广点通、抖音、微博这些平台。烧钱,反正我是没这钱去烧的。我有一同事试过每月5千块钱的烧,效果还不如到街上发传单。心痛。难度低,成本高。

  • 在开源中国,V2EX,掘金,51CTO,CSDN等各方博客平台写文章,攒关注。目前我是这么做的,多分享一些对他人有用的文章,也可以帮到自己。难度适中。

  • 做 H5 小游戏,分享续命这类玩法,传播速度应该很快,但是自己要有广告传媒的企业资质,不然很难做下去。难度高。

说到企业资质,如果要办公司,建议大家去找中介,自己折腾很累,还不一定能办下来。我就折腾过,熬不住,还是花了几大千给中介。申办企业不是闹着玩的,每个月都要报账,自己不懂会计,还得给钱让人家办。不报账,就会被工商局记黑名单。不经营的公司一定要注销,搞不好,就会在国家征信系统记下不良纪录,影响贷款、出国等等。

好了,断断续续说了这么多,也不知道大家有没有收获。至此,敬礼,向自己逝去的一年半致敬。

本文转载自【开源中国】

公众号内回复“1”带你进粉丝群

作为一个开发者,我创业了相关推荐

  1. 一名iPhone开发者的创业经验 (转)

    转自CocoaChina,作者系johnqh同学 1.整体市场 我准备写至少两篇.本篇为对iPhone的整体的看法.以后会写对中国AppStore市场的看法,市场销售的看法,和在中国开发的看法. 先自 ...

  2. ios中一个开发者证书如何创建多个app应用

    大家可能会遇到在外包公司只有一个开发者证书却要发布打包很多应用的情况,我也遇到这个坑,在网上上查资料和问别人也无解的情况下,周末拿公司证书来测试总算理解了. 首先如果你有了一个开发者证书,而且发布过应 ...

  3. [置顶] 也论百度轻应用--一个开发者的吐槽

    做为开发者,今天想收集关于百度轻应用的资料,看了百度百科:http://baike.baidu.com/link?url=ijl7IZ4nXaWfMD5sA74y5mPkKCkBd1-As_cMqhY ...

  4. 如果一个普通人想创业或是干点副业赚钱,应该去赚谁的钱?

    如果一个普通人想创业或是干点副业赚钱,应该去赚谁的钱?能够去赚谁的钱呢?从一个年赚百万的姐们那里得到了答案. 这姐们是做互联网个体创业的,说的通俗点,就是早期干微商的,现在交社交电商.社区团购什么的. ...

  5. 今年一个偶然的创业,就改变了我的人生

    今年一个偶然的创业,就改变了我的人生. 今年一个偶然的机会接下了一家别人转让的 菜 鸟 驿 站,记得刚投资的时候,那是最忙碌的时候,货物积压成堆,而且新到的货物把之前很多没取的货物压的死死的. 我还记 ...

  6. CSDN 蒋涛对话英特尔中国区董事长王锐:我愿是当代的一个开发者

    作者 | 何苗 出品 | CSDN(ID:CSDNnews) 数字化浪潮已经席卷各行各业,计算能力渗透了生活的方方面面,跨越现有的新兴设备,将一个新的世界逐渐展开在眼前.面对不断升级的技术力量,开发者 ...

  7. macbook pro python开发_年轻人第一台 Mac,来自一个开发者的 Macbook Pro 2019 16寸简评...

    从工作开始,一直就想买个 Mac,但是一直没有买成,虽说有公司配发的 Mac(这也让我从 Macbook Pro 2015 13寸到 Macbook Pro 2017 15寸,到 Macbook Pr ...

  8. 苹果M1芯片为何如此快?一个开发者的解释

    苹果M1芯片为何如此快?一个开发者的解释 This Is Fast But The Best Is Yet To Come You may have wondered why the Apple M1 ...

  9. 知识付费真的是一个好的创业项目吗?能兼职做吗?

    我觉得一个好的创业项目要符合以下几个特点: 1,市场需求广,且这个市场需求永远不会被满足 (比如减肥行业,理财行业,教人赚钱,教人创业的行业) ,因为没有一款产品能够让所有人减肥成功,让所有人理财成功 ...

  10. iOS 一个开发者账号 多台Mac 共用

    iOS 开发者账号有时候需要多台Mac 一起用.这个时候就得要证书了, 首先如果一个账号能在第一台电脑上能正常使用了.那么这时就可以把相应的证书导出来,再台PC的时候也可以用. 先导私有的证书.这个是 ...

最新文章

  1. ideal如何快速导入import_Spring的@Import注解详解
  2. python数据处理_时间序列数据处理python 库
  3. 2020年北大中文核心期刊目录_中文核心期刊目录汇总(2020年4月发布)
  4. r 语言 ggplot上添加平均值_R语言自定义两种统计量度:平均值和中位数,何时去使用?
  5. H5 input输入限制最大位数,和调用小键盘需求发生冲突的解决办法
  6. EasyUI Numberbox 数字框(限制仅输入数字)
  7. 2022牛客寒假算法基础集训营6 签到题5题(附基础集训营4-6签到题总结)
  8. Apache Spark机器学习3.3 特征准备
  9. [转]如何撰写学术论文
  10. cf进入服务器未响应,win7系统玩cf未响应的解决方法
  11. SCP不会覆盖已有文件
  12. 用计算机怎么谈黑人团队,光遇黑人抬棺乐谱怎么弹奏 计算机演奏乐谱16
  13. android手机存储全面解析汇总
  14. 六 R语言barplot条形图之带误差棒的对称条形图及相关性分析结果分布
  15. docker commit镜像以及数据卷技术
  16. win7下java用jdbc驱动来连接sql server的方法 (转载)
  17. rabbitmq设置手动ack报错:Channel closed; cannot ack/nack
  18. 友盟推送服务器配置文档,友盟使用指南
  19. 长亮科技正式加入openGauss社区
  20. 多码头多式联运集装箱港口的全局规划

热门文章

  1. 三菱PLC开发环境搭建笔记
  2. 智能网联汽车 自动驾驶功能场地试验方法及要求
  3. python混合线性模型_如何在Python statsmodels中有多组线性混合效应模型?
  4. js 图片上传和二进制上传
  5. 根据 轮播图背景色 自动填充剩余背景色的 走马灯
  6. PCA主成分分析/LDA线性判别分析/CCA典型相关分析 对比
  7. simulink如何更新版本的文件(mdl或slx),How to load models created with a newer version of Simulink
  8. Linux CPU负载率的计算方式
  9. cadcene17.4软件汉化
  10. 单片机C语言程序设计基础知识全解析