在此文开篇之处先特别申明,此文在有些人的眼中会有广告的嫌疑,但是本人不想将其作为一个广告宣传的文章,在此提到软件内容部分请大家予以谅解和包含,作为时间不算短的程序员给大家分享一些自己开发吉特仓储管理软件相关的经验和坑,当然还有一些自己从中获利的方式,不能说给大家指条明路吧,算是作为程序开发人的相互经验交流。
此文本来想写在国庆假期之前的,但是那段时间公司事情刚好很忙,所以没有来得及写此文。当时要搞Solr搜索引擎,因为自己不熟悉java程序所以在弄得过程中有些费力,而且自己本身也不是一心苦心专研程序技术的人,但我绝对是一位苦心专研程序的人,虽然最终也没有什么大的成果。去年公司没有干之后,一直到今年现在我一直在想为何我们公司会做不下去,就连一个小公司都做不下去,其实我们也很努力,我们也很拼命,创业之初一周基本上四天会睡在办公室,每日每夜的做项目,那个时候是有客户的,但是到了最后发现每个项目都不赚钱,为什么时间太长了,不能快速解决客户问题【这只是其中一个很小的原因】,当时确定了公司的方向就是要做仓储物流制造方面的软件产品。虽然我知道这个行业竞争很大,很多人说现在的市场有很多成熟的产品,这个不说我也自然明白,每个人都有自己的想法,也有自己针对的市场方向,我们在此不多说。
一. 深入一个行业
最开始做开发的时候涉及到过好多行业,汽车零配件,金融单位,游戏行业,房地产行业,一直做着感觉最终除了会写代码好像啥也不会,一个行业的套路你都还没有弄清楚感觉你就落伍了(主要是干个几年感觉工资跟不上了,只能跳槽增加工资咯,其实我跳槽没有一次是加过工资的,因为我胆小,只要认为自己过得去就行了,最重要的是觉得自己干的值)。不是每个技术员都可以开公司的,但是很多技术员都给别人做过私活,感觉工作之余赚点小钱还是很不错的,在此之前我也干过感觉挺牛逼的.其实后来我也做的少,我也去问过很多人他们基本一致的答案:私活真的是赚的辛苦钱,每天没日没夜的,真不如上班。 这个的确是如此的,我已人格保证, 所以现在刚出道的程序员们如果手上没有什么货的话,真的不要轻易去接什么私活。
1. 你跳槽那么多次,多少年之后你发现你比别人强在哪里?
这个问题好容易戳人的心窝子,特别是做过外包的同学感触肯定很深,今天这个项目需要我那我不顾一切扑上去,下一个项目需要我被迫扑上去。国庆回家的时候,火车上三个湖南小伙,听聊天得知是干程序的,其中一人说我做过某某军工企业的什么软件,我做过某某银行的什么软件,我还做了某个*企业什么的软件, 其实我只是听听,我基本知道这个小伙是干外包项目的,然后还有一个携程的小伙,他们聊了很多我一直不说话,但是他们都谈到了一个问题就是这些年下来感觉除了会写代码,好像就干不了其他的,如果换了一个行业或者一个项目组又好像从头开始了。
其实这就是问题的所在,因为你在短期内不断的在切换你不熟知的领域,你还没有足够的时间来深入了解这个行业的特性,也就使得你不能够在这个行业成为专家,所以你最终的结果就是可替代性很强,程序员现在大把大把的,上海地铁上随便抓一大把,替换你分分钟的事情,就说携程招人和离职的速度来看就足以说明这个问题。在此之前我也有过类似的感受,感觉到头来啥啥都不是,我等天之愚钝之人不可能做到技术牛逼之人,发挥不了自己的智商。那就只能在某个小的领域专心做事,做精做强。
之前我特别羡慕一个朋友,他是做销售的,其实他所做的事情远不是一个销售人员能够达到的了,他之前是做货架,自动门等销售的,一直做了十来年吧,后面我经常跟着他一起去跑客户,我说让他带我我见世面,到客户那边之后他所做的事情远不是销售给客户介绍产品,推荐价格。到了客户仓库他会给客户做专业的仓库规划测量,他随身带着卷尺,测距仪,黄胶带等等一系列东西,俨然就是一个工程师的范,事情做得非常的专业到位,但是我见他很少直接给客户推荐某个产品,然后还会给客户给出规划的图纸设计图。当时我很是惊呆,这个销售的确做的到位,后面我问他是不是学这个行业的,他说他从来没有学过这些,只是在这个行业一直做就慢慢的专业了。再后来我有认识了另外一个做同样销售的销售员,他也就是一个普通的销售员了,我跟他去看客户现场他也就只知道拿着产品说明书给客户介绍产品了,差距自然不说,后面这位就没有干这一行了,我问他为什么,他说这个行业赚不到钱。那个朋友现在上海儿女双全,有车有房,相信比一般的程序员要好很多的。后面他说自己做货架销售,在他们公司做了一个业绩全国第一,好像是这样的。总之给我的感觉他做这个事"专业",他也给过我一个建议:“好好的干一行”
2. 你为什么成为不了专家?
什么是专家, 我个人觉得就是在这个行业有资深经验, 专 就是专业, 家 不好怎么解释,反正画家,书法家等比较有威望吧,最关键的是能够在关键时刻关键点起到关键作用, 当然不能说我们国家某某部门某某专家了,这种话不要多说。专家能够刻画到点子上,戳中要点一针见血,找出良方,这就是专家。专家除了苦学那就是经验积累,遇到的问题越多后面你能够解决问题的几率就越大,久而久之你就是专家了。其实现在很多做技术的今天学.NET,明//代码效果参考:http://www.zidongmutanji.com/zsjx/357797.html
天又是Java,再来说PHP(拍黄片)是世界上最好的语言, 久而久之其实他也就是一个普通写代码的,干了10年还是只能写浅显的代码。二. 项目开发你为何这么慢
我自己一句有一句调侃自己的话:"每个人都说时间就是金钱,你的时间真的值钱么,如果在特定的时间内你没有创造价值那么你的时间就不值钱" 。 好像有点过分,但对于我自己来说是有道理的
1. 为何一个简单的进销存你都要做三个月
这是我当年遇到的很现实的问题,先不说价钱问题。别人一个月就可以上线运行,为何你一个简单的进销存要做三个月,我们仔细罗列这些功能:(1) 系统设置 (2) 用户管理 (3) 部门管理 (4) 角色管理 (4)产品管理 (6) 价格管理 (7) 客户管理 (8) 供应商管理 .....我实在不想说下去了,简单的进销存确实不止这些功能,在怎么简单你得让客户流程能够跑起来才行啊。
再从技术方面考虑: 这得有多少张表啊,数据库操作好多代码啊,还要设计前段UI,做的交互性好还要大量的JS,想想这些工作量3个月真的一点不多。唉,为什么我就没有一套可以复用的东西呢?
对的,因为你没有可以复用的东西,所以你慢,你项目进度不能快也就在情理之中了
2.怎么就没有公共组件
等你确定好做一个行业软件的开发之后,技术体系基本确定之后,开发还是慢啊。我要弹出框,系统规划中没有这个组件,我要从网上找。 好多个页面要选择用户信息,弹出页面,第一个页面凑合着做吧,忍了,又来一个这样的页面需求,又忍了, 越来越多,忍无可忍,这种业务组件你为何不封装成公共的呢。
; (function ($) {
$.fn.ProductDialog = function (options) {
var defaultOption //代码效果参考:http://www.zidongmutanji.com/zsjx/481333.html
= {data: {},
Mult: true,
EventName: "dblclick",
callBack: undefined
};
defaultOption = $.extend(defaultOption, options);
var DataServer={
Server: function () {
var config = (function () {
var URL_GetList = "/Storage/ProductAjax/GetList";
return {
URL_GetList: URL_GetList
};
})();
//数据操作服务
var dataServer = (function ($, config) {
//查询分页列表
var GetList=function(data,callback){
$.gitAjax({
url: config.URL_GetList,
data: data,
type: "post",
dataType: "json",
success: function (result) {
if(callback!=undefined typeof callback=="function"){
callback(result);
}
}
});
}
return {
GetList: GetList
}
})($, config);
return dataServer;
},
PageClick:function(PageIndex,PageSize){
$.jBox.tip("正在努力加载数据...","loading");
var Server=DataServer.Server();
var search={};
search【"PageIndex"】=PageIndex;
search【"PageSize"】=PageSize;
Server.GetList(search,function(result){
DataServer.SetTable(result);
$.jBox.closeTip();
});
},
SetTable:function(result){
current.find("#tabInfo").DataTable({
destroy: true,
data:result.Result,
paging:false,
searching:false,
scrollX: false,
bAutoWidth:false,
bInfo:false,
ordering:false,
columns: 【
{ data: 'SnNum' ,render:function(data, type, full, meta){
return "";
}},
{ data: 'BarCode'},
{ data: 'ProductName',createdCell:function(td, cellData, rowData, row, col){
if(!git.IsEmpty(cellData) cellData.length>10){
$(td).popover({container:"body",content:cellData,trigger:"hover",placement:"bottom",delay:{show:500}});
}
},render:function(data,type,full,meat){
return git.GetStrSub(data,10);
}},
{ data: 'Size',render:function(data,type,full,meta){
return git.GetStrSub(data,10);
},createdCell:function(td, cellData, rowData, row, col){
if(!git.IsEmpty(cellData) cellData.length>10){
$(td).popover({container:"body",content:cellData,trigger:"hover",placement:"bottom",delay:{show:500}});
}
}},
{ data: 'CateName'},
{ data: 'UnitName'},
{ data: 'MaxNum'},
{ data: 'MinNum'},
{ data: 'AvgPrice'},
{ data: 'Display',render:function(data,type,full,meta){
return git.GetStrSub(data,10);
},createdCell:function(td, cellData, rowData, row, col){
if(!git.IsEmpty(cellData) cellData.length>10){
$(td).popover({container:"body",content:cellData,trigger:"hover",placement:"bottom",delay:{show:500}});
}
}}
】,
aoColumnDefs:【
{ "sWidth": "15px", "aTargets": 【0】 }
】,
oLanguage:{
sEmptyTable:"没有查询到任何数据"
}
});
var pageInfo=result.PageInfo;
if(pageInfo!=undefined){
current.find("#myMinPager").minpager({ pagenumber: pageInfo.PageIndex, recordCount: pageInfo.RowCount, pageSize: pageInfo.PageSize, buttonClickCallback: DataServer.PageClick });
}
DataServer.BindEvent();
},
BindEvent:function(){
if(defaultOption.Mult){
current.find("#tabInfo").find("input【name='item_all'】").click(function(event) {
var flag=$(this).attr("checked");
if(flag){
current.find("#tabInfo").find("input【name='product_item'】").attr("checked",true);
}else{
current.find("#tabInfo").find("input【name='product_item'】").attr("checked",false);
}
});
}
else{
current.find("#tabInfo").find("input【name='item_all'】").hide();
current.find("#tabInfo").find("input【name='product_item'】").click(function(event) {
current.find("#tabInfo").find("input【name='product_item'】").attr('checked', false);
$(this).attr("checked",true);
});
}
//搜索
current.find(".search").find('button【data-command="Search"】').click(function(event) {
DataServer.PageClick(1,10);
});
},
GetSelect:function(){
var list=【】;
current.find("#tabInfo").find("input【name='product_item'】").each(function(i,item){
var flag=$(item).attr("checked");
if(flag){
var value=$(item).attr("data-full");
list.push(JSON.parse(value));
}
});
return list;
}
}
var submit = function (v, h, f) {
if (v == 1) {
var list=DataServer.GetSelect();
if(list==undefined || list.length==0){
$.jBox.tip("请选择产品","warn");
return false;
}
if (defaultOption.callBack != undefined typeof (defaultOption.callBack) == "function") {
if(defaultOption.Mult){
defaultOption.callBack(list);
}else{
defaultOption.callBack(list【0】);
}
}
}
};
$(this).bind(defaultOption.EventName, function () {
$.jBox.open("get:/Storage/Product/Dialog", "选择产品", 850, 600, {
buttons: { "选择": 1, "关闭": 2 }, submit: submit, loaded: function (h) {
current=h;
DataServer.PageClick(1,10);
}
});
});
};
})(jQuery);
选择产品的公共组件
类似于这种的组件,在项目中有大量使用,如果能够做到全局公共并且方便使用这就是极佳的。最终形成组件也是有发展历程的: 开始只是一个简单的额对话框显示表格并且选中产品,慢慢的又有更多的需求,比如要能够搜索,要能够分页,要支持多选以及单选等等,双几行能够自动选择等一系列问题。其实你做好了公共组件在后期的开发中也就省事了。
3. 代码的套路
10个人就有10种代码风格,这种相互改代码会让人崩溃,人员的离职,没有文档和注释的说明,字段和数据库的对应不起来,各种让人吐的问题。不要太多的花样,定义好套路,所有的代码必须遵循这种套路你会快很多,最关键的是找bug的速度回快很多。
/
财务管理-应收实收
*/
var FinanceBillManager = {
Server: function () {
var config = (function () {
var URL_Add = "/Finance/BillAjax/AddRec";
var URL_GetList = "/Finance/BillManagerAjax/GetList";
var URL_GetDetail = "/Finance/BillManagerAjax/GetDetail";
var URL_Delete = "/Finance/BillManagerAjax/Delete";
var URL_Cancel = "/Finance/BillManagerAjax/Cancel";
var URL_Audite = "/Finance/BillManagerAjax/Audite";
var URL_ToExcel = "/Finance/BillManagerAjax/ToExcel";
var URL_AddPay = "/Finance/BillAjax/AddPay";
var URL_PayDetail = "/Finance/BillAjax/AddRec";
return {
URL_GetList: URL_GetList,
URL_Add: URL_Add,
URL_Delete: URL_Delete,
URL_Cancel: URL_Cancel,
URL_Audite: URL_Audite,
URL_ToExcel: URL_ToExcel,
URL_AddPay: URL_AddPay,
URL_PayDetail: URL_PayDetail,
};
})();
//数据操作服务
var dataServer = (function ($, config) {
//查询分页列表
var Add=function(data,callback){
$.gitAjax({
url: config.URL_Add,
data: data,
type: "post",
dataType: "json",
success: function (result) {
if(callback!=undefined typeof callback=="function"){
callback(result);
}
}
});
}
var GetList=function(data,callback){
$.gitAjax({
url: config.URL_GetList,
data: data,
type: "post",
dataType: "json",
success: function (result) {
if(callback!=undefined typeof callback=="function"){
callback(result);
}
}
});
}
var Delete=function(data,callback){
$.gitAjax({
url: config.URL_Delete,
data: data,
type: "post",
dataType: "json",
success: function (result) {
if(callback!=undefined typeof callback=="function"){
callback(result);
}
}
});
}
var Cancel=function(data,callback){
$.gitAjax({
url: config.URL_Cancel,
data: data,
type: "post",
dataType: "json",
success: function (result) {
if(callback!=undefined typeof callback=="function"){
callback(result);
}
}
});
}
var Audite=function(data,callback){
$.gitAjax({
url: config.URL_Audite,
data: data,
type: "post",
dataType: "json",
success: function (result) {
if(callback!=undefined typeof callback=="function"){
callback(result);
}
}
});
}
var ToExcel=function(data,callback){
$.gitAjax({
url: config.URL_ToExcel,
data: data,
type: "post",
dataType: "json",
success: function (result) {
if(callback!=undefined typeof callback=="function"){
callback(result);
}
}
});
}
var AddPay=function(data,callback){
$.gitAjax({
url: config.URL_AddPay,
data: data,
type: "post",
dataType: "json",
success: function (result) {
if(callback!=undefined typeof callback=="function"){
callback(result);
}
}
});
}
return {
Add: Add,
GetList: GetList,
Delete: Delete,
Cancel: Cancel,
Audite: Audite,
ToExcel: ToExcel,
AddPay: AddPay,
}
})($, config);
return dataServer;
},
PageClick:function(PageIndex,PageSize){
$.jBox.tip("正在努力加载数据...","loading");
var Server=FinanceBillManager.Server();
var search=FinanceBillManager.GetSearch();
search【"PageIndex"】=PageIndex;
search【"PageSize"】=PageSize;
Server.GetList(search,function(result){
FinanceBillManager.SetTable(result);
$.jBox.closeTip();
});
},
Refresh:function(){
var PageSize=$("#mypager").pager("GetPageSize");
var PageIndex=$("#mypager").pager("GetCurrent");
$.jBox.tip("正在努力加载数据...","loading");
var Server=FinanceBillManager.Server();