2017年总结——当然还有牢骚

最近两年都是1月写总结,今年差点忘记了。

基本是因为忙耽误的吧,所以还算是好事。

2017年总的来说,是触底反弹的一年,也是动荡的一年。

16年底换部门到了大客户销售部门,新总监是11月空降的,1月就先走了一个销售。留下了一个(大)窟窿。大客户销售部门的特点是单子少,周期长,金额高,丢了一个就得再等几个月,走了一个销售至少影响几个月,于是新总监就开始打我和另外2个技术背景手下的主意,想让我们跑销售。

2月是春节月,春节折腾完就中旬了,3个技术背景的,一个特别的反对当销售,一个很Open,让做什么做什么,我是居中,到不是想和总监对着干,因为走了的销售区域在南方,我鞭长莫及,就算我想干,我其他几个销售也不让我动他们的客户。

3月,情况已经很明显了,新总监完全无力压制几个老销售,今年的情况相当不好,有市场的原因,有前几年的影响,新总监无力回天。人在北京,不知道新总监在上海做了哪些具体的尝试,不过显然效果不明显。

4月,老婆想出去旅游,正好我也想散散心,先订了3月没有成行,于是4月忙活完CIMT,去了趟巴厘岛,效果还是很明显,心情好了不少。觉得之前心情不好固然有工作不顺的原因,自己不会放松调节也是原因。

5月,又走了一个老销售,新总监前任及下属,这个走得影响还是很大的,1月销售走了后就一直没有招到人,又走了一个销售就走了一半了。

6月,大客户这边已经确定无法完成任务了,新销售终于招到位了,新总监也终于下定决心不继续熬了,月底也辞职了。作为小兵,这种事情还是让人挺无语的。

7月,做售前支持的,最怕的就是新销售,自以为是又屁都不会,自以为是到无所谓,哪个销售都是这样,不会就惨了,什么都需要别人做,各种风险又不知道。再加上总监辞职,这个磨合相当地痛苦。老板还特意打了次电话问这些事,处理得特别不职业。大客户销售部门基本是散了,把几个PSM放到销售这管,几乎变成了纯销售,老板估计目的也没达到,就借这个机会把所有的PSM合并到了一起,于是我又换了一个领导Z。总之这个月很动荡。好消息也有,老婆确定怀孕,等了几年总算是来了,伴随着坏消息,先兆流产,在家陪了一个礼拜。

8月,继续和新销售斗争,我是真心想帮他融入环境,结果反而差点成了仇人,这点我要反思了,从R到新总监,再到新销售,最近这两年每个新来的领导和同事我都是很“真诚”地去沟通,结果效果都不好。换位思考一下,我如果去了一个新环境,有人和我交浅言深地说一些东西,我肯定也会有防御心理,觉得他不怀好意。可能也是因为我从来没有换过环境吧。

9月,财年即将结束,销售部门也算是大变,职责,区域,客户都有了改变,跑了好几趟柳州,常熟,完全是浪费时间,没有销售经理Coach的新销售做事情简直是蒙眼碰运气。工作重点逐渐从大客户转到了区域销售,这也是新领导Z的方向。

10月-12月,换了部门后,因为某个项目出了些问题,走了个项目经理,领导要填窟窿更忙了,这段时间也是区域比较忙的,跟着跑了几个客户,几个研讨会。老板对新部门有3个很具体的要求,其中一个要求12月底截止日期,真正到了12月才有时间干,突击了一下,勉强算是赶上了节点,还有一个要求3月底,也顺带做了些。Z的风格其实早就了解,总算不和空降领导共事,磨合得还是快一些,最大的困难是Z完全不懂我们这块的业务,而且喜欢讨价还价,你说10天能做完,他就问你3天行不行,最后7天成交。时间长了,磨合好了,我肯定会多说,但是现在,只能先把活干粗一点吧。

 

 

2017年买的书

左边的都是最近一个月买的,几乎全是下半年买的,从这点看来,上下半年的工作节奏的确不太一样。

本来想回次天津,被父母以雾太大,和重感冒别传染为理由拦住了。无形中多了一天的空闲时间,正好可以写写年终的总结了。

前端工程师

最近一个月,快成前端工程师了。

自从开始用BS解决现在的一些问题,就在补各种前端知识,从我买书的节奏就能看出来我对这个问题了解的深入程度。

第一次——ASP.NET入门经典,这时还没意识到前端的重要性,觉得用默认的模板,弄弄后端就OK了。结果这本真的是入门经典,介绍了WebForm,MVC,WebAPI,但是并没有结构性的深入。

第二次——ASP.NET MVC 5高级编程(第5版) & HTML5+CSS3从入门到精通,时隔一周发现已经用MVC就继续用下去,而且也算好学,要单独买一本介绍MVC实现的。另外在用Razor写View的时候,如何让页面看起来不这么难看也需要学习一些css的知识,还要补补HTML的知识。结果后端的问题基本上是解决了,但是一些功能又必须由前端实现(jQuery),而且那本HTML5+CSS3真的是只介绍HTML5和CSS3,完全没讲我想知道的……。

第三次——和第二次隔了10天,这次基本把问题都解决了,首先是Bootstrap入门经典,ASPNET?MVC5集成的是Bootstrap 3.0,实际上了解css是必要的,但是并不能解决我对排版的需求,直接看这个更方便……然后是Web设计与前端开发秘籍:HTML CSS JavaScript jQuery 构建网站,二本套装,讲这四个东西,这是我最近买的书了印刷排版最良心的,如果时间够,从头到尾看下来估计都不会有什么问题,和看网页+PPT效果一样。最后还买了本精通Python网络爬虫:核心技术、框架与项目实战,有些数据要从内网的网页上爬下来,为了图省事准备学学scrapy。

最近几个礼拜弄这些自己不擅长的东西,压力也比较大,也解决了不少问题,元旦过后有时间再整理一下解决的过程,纪录下来。

笔记:ASP.NET MVC 个人用户认证

起因:要上线一个内部的小系统,于是就动手实现,不过以前属于纯玩票,现在毕竟要实际用的东西,认证就要做了,后期要把认证绑到公司域的AD上,但是现在没有权限的情况下,内部测试只能用本地的认证系统了。

开始在完全搞不懂MVC这部分的情况下,想得蛮简单,小范围测试只需要几个人,手动创建完帐号字典,连数据库都不用,直接明文一验证就完了。结果发现框架里已经提供了比较完事的认证系统,就直接用吧,但是不会用……

经过一些时间的搜索,先记录一下。

首先依赖数据库,会使用LocalDB在App_data目录下生成一个mdf的LocalDB文件,一共5张表,用户的,用户组的,映射关系什么的,开始可以先不管。

在创建完框架直接调试,可以进入注册页面,先注册一个帐号,会要求用邮箱,密码也有复杂性要求,这部分如果要修改可以在App_Start\IdentityConfig.cs文件里修改PasswordValidator。

创建完,会发现本地数据库的表AspNetUsers里会多一个用户。当然密码不会用明文存……

然后我的需求1是帐号密码可以由我一个人创建,2是其他人可以登陆,但是不能创建新帐户。

尝试1:直接修改数据库,添加条目,发现AspNetUsers表里的ID是hash值,手动创建其实修改成数字应该也可以,不过显得不专业,放弃。

尝试2:注册、注销,循环注册多个帐户,太傻,放弃。

尝试3:登陆完注册导航按钮消失,直接输入url可以不?可以……这个办法已经可以了,偷懒的话可以把注册代码的注册成功后登陆注销,弄完帐户后再恢复。就下面这行

 await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);

需求1解决,需求2搜了点文章,解决这个问题的同时让我对MVC三个层次的工作方式又理解了一些。

解决办法:

  1. 让注册页必须由一定权限的人登陆,无权限的人会提示登陆,登陆完再验证权限。在AccountController.cs的Register部分注销匿名,添加Roles控制,即只允许Admins用户访问这个页面。
  2.         //
            // POST: /Account/Register
            [HttpPost]
            //[AllowAnonymous]
            [Authorize(Roles = "Admins")]
            [ValidateAntiForgeryToken]
            public async Task<ActionResult> Register(RegisterViewModel model)

    这时候如果调试,会发现所有人都无法访问这个界面,会提示你登陆,然后就看不到了。查了下Account下的几个代码,好像没有集成用户组管理的页面和代码。于是在数据库里手动添加。
    在数据库的AspNetRoles表里添加ID为1,Name为Admins的条目,以及ID为2,Name为Users的条目。
    在数据库的AspNetUserRoles表里,将刚注册的用户的ID(Hash值)添加到这里的UserID,RoleID为1,就可以设定这个用户的Roles为Admin了。添加的其他用户可以手动分配为2(Users),或者像我一样没需求的,可以不分配。

通过这个问题的搜索学习,还了解到了一些MVC的设计思路,之前自己瞎玩的时候搞得一团糟,几乎把所有的代码都放到了View层,虽然也尝试把数据结构放到了Models,但是还是耦合到一团球。

我之前理解路由(当然是错误的理解),Control层只是起到转发Action的作用,并实现一些数据处理,而且这些数据处理都是手写的,但是在研究注册页的注册按钮如何工作时,我凌乱了,半天没理解怎么弄的,找到了一个stackoverflow的高分回答,解释了一下Model和Control的Binding关系,读了两遍,再回去看代码,果然就明白了。

模型基本上只提供了一个数据结构,而且基本只是数据的值,不包含函数(方法),View在提交Post的时候,调用的是同一个路由,所以开始看的时候莫名的觉得这个页面既显示注册界面,又完成了注册功能。然后找到Controller的时候,虽然明白了Controller如何完成功能,但是又不明白这些数据结构是如何传递的。相对的,也不明白Model是如何在这里面起作用的。

这些能活下来的框架和设计,都是相对简单且实用的,理解起来其实并不是太困难,但是需要一些点拨和经验。

 

伪技术贴:暗黑3死灵鼠标宏替代软件

暗黑3的机制现在很搞笑,很多Build要依靠大量高频率的点击来实现,所以导致了鼠标宏的出现,而且官方态度很暧昧,从来不承认这种辅助的合理性,也从来没封禁。

我了解使用这个东西的风险,所以自己写了个类似的东西,分享出来,如果能帮助到有类似需要的人最好,不过请使用的人自己承担风险。

源代码

下载点这个

界面就是三个时间间隔,后台是两个快捷键,按Ctrl+B一次,开始无限循环按3,再按Ctrl+3一次,停止无限循环,这个我用在吞噬技能上。对应界面的时间间隔3。注:开始想用Ctrl+3作为快捷键,但是这意味着在连续按3的情况下,只要按了Ctrl键,就等于按了Ctrl+3,就停下来了,所以一直纳闷为什么一放死地吞噬就掉了……Orz

另外一个快捷键是Alt+2,表现为按一次2,然后无限按1,按1的频率间隔是时间间隔1,整个时间持续为时间间隔2。这个对应为死地(设为2号技能)10秒里,不停地按1(尸矛)。

工作优先级

最近不是特别忙,心态上的。

最近2个月没有一个礼拜不出差的,每月基本都有14、5天不在家,老婆怀孕5、6个月心情也不是很平稳,又到了年底事情多的时候,按理应该挺忙挺慌,但是就是没有以前急迫的感觉了。

最主要的改变应该是自己吧,首先是工作和生活尽量分开,出差回来后的晚上和周末绝对不要坐电脑前,无论是工作还是打游戏放松。只要陪老婆的绝对时间够了,无论是看电视逛街还是发呆,结果都不差。

然后就是工作,自己安排工作不要安排或承诺2周以上或以后的事情,领导安排的工作,以及认为重要的事情,订好时间计划,严格保证执行。日常工作做好,如有时间来不及,做好解释工作,寻找解决方案,不能简单的拒绝。对于份外工作,和甩锅,不积极,不主动,不反应。

加班,首先周六日没有以前整天干活的情况发生了,有紧急情况还会忙一会,或者老婆自己有事的时候也能抽空干点活。每天的8小时以外,如果有事情需要做,我要先反思一下为什么今天需要加班,是我耽误了白天的进度,还是被其他事情干扰了,干扰项是否是足够重要的?一定需要加班解决,还是可以安排到明天。总之,加班是救急不救忙。

走自己的路,让别人说去吧

年轻的时候,除了大四那一年由于考研工作都不顺,比较灰心,其他的时间都是不可一世,没什么本事还是牛逼哄哄,那时候念叨这句话,就是我很牛逼,所以我就这么着,管其他人怎么着。

但这次不是,刚才突然有点想法,但是又很抽象,就想着怎么用语言总结一下,然后就出来这么一句。

起因是某个同事,因为某个事情找我支持,还有一个礼拜就要投标了,我却决定劝他放弃这个项目。当然问题出在我身上,我一直没有给出绝对明确的“放弃吧”,直到今天。我总是习惯于把人和事情结合到一起看,假设每个环节都有强大的逻辑处理和异常处理功能,就像组织良好的代码一样,但是实际上不是的,销售不会因为一些理性的判断就放弃项目,技术人员也不会因为项目很重要就冒风险,就算有,这样的人也会逐渐被淘汰掉,好的流程不会让问题在流转的过程中无声的消失掉,而是通过各种触发条件被激活,再由有关键权限的人做判断,做判断的方法和态度也就是企业文化了。

现在反思一下,当初虽然给出了No,但是没有力度,应该让销售觉得,如果不找领导压我,我就不会改变主意,这也就是把风险和问题,提前暴露,并交由足够权限的人妥善处理。

我现在还没有找准确这个度,这个风格,也就是我还没有找准现在的路,当然只是指这份工作,这个岗位上的,一旦找准了,就要坚持下去,冲突也好,愉快地合作也好,必须是符合我的工作范围,符合我的屁股的位置的。

迎接新财年

离新年春节还有三四个月,不过公司级别的财政年度已经结束了,对于工作上,10月已经是新的一年了。9月份真是忙到昏天黑地,看看8月份的blog上还有闲暇研究一下解析几何,这次更新就只能等到国庆假期了。

这一两个月,感觉自己的变化非常大,和过去2年的动荡有关系,终于能看到一个相对稳定的阶段,也就有了总结和展望的前提。虽然总结的时候,看到的更多是自己愚蠢的一面,不过no pain no gain,如果吸取教训更重要,32岁,虽然已经不年轻,但是还有时间,还有机会。

抛去楞头青和犯得蠢不提,最近2年积累太少,一是input少,二是output少,过去做技术工作,遇到什么问题就学什么,同事和客户问什么,就说什么,输入输出都有。现在做两边不靠的工作,需要学什么要自己去总结,一些经验如何归纳也要自己抽空做,实际上无论输入输出都没怎么弄,就会有种虚浮的感觉。

还有时间管理,一直有个想法,要把每天和每周的工作提前计划好,然后严格执行,但是一直没有成功。新财年,还是想要试一试,目前看来,负责的东西有点多,按照之前的经验,一个人不可能干完,对于完全没可能的?事情,只能想办法尽可能地提高效率,尽量完成度高一些,另外一方面,完不成的情况下,也要有足够的取舍,以及证据说明自己尽力了。

业余时间,想多看看书,过去两年一直在看工具书和网络小说,17年底,找一些严肃小说看吧,看点苦大仇深的调节一下,总看爽文也不行。

放弃使用MathNet的Spatial库

这个库也只是更新到0.4,而且更新的非常慢,感觉项目基本停滞。

这次主要的目的之一也是锻炼自己,那么参考代码重新实现也对我自己更有利。

里面的一些结构非常值得参考,一些函数可以直接拿来用,不过这个库还是像通常能见到的库的一样是纯几何的,而不是我想实现的测量上的,所以还是要保留自己的一些思路。

另外就是目前在补回归分析的课,还有解析几何的课(高数下)。最近要花一些时间在这些基础上,代码要少写一些。

两个向量的叉积实现

需求是,根据坐标系的两个轴(向量),求出另外一个轴,由于我高数下(解析几何)不及格,所以一直没有想起来对应的定义。之前自己解决的办法是,求出这两个向量构造的平面,然后平面的法向就是解。

今天在写我的GDTGeometry库时又遇到这个问题,这次先去翻了翻新买的高数下教材,发现这就是向量叉积的定义,可惜当初并没有记牢。于是想直接在MathNet库里找,结果里面只有multiply(点积)和pointwise-multiply(逐点乘积),又特意找了下翻译叉积是Cross-Multiply,我觉得像基础课的很多定义,应该加上英文注释。

搜了下mathnet cross multiply,找到了stack overflow上的一篇问答,这个函数在Iridium子库里实现,不过这个库已经太监了,而且2012年就太监了,到现在还没有整合到numerics(主库里),简直是无语,我很想说这么个简单的功能我commit一个patch吧,不过仔细想了下,问题应该出在叉积通常只用在3维空间里,低维和高维的推广好像都有点问题。

overflow上的回答里已经有了我要的代码:

    using DLA = MathNet.Numerics.LinearAlgebra.Double;

    public static DLA.Vector Cross(DLA.Vector left, DLA.Vector right)
    {
        if ((left.Count != 3 || right.Count != 3))
        {
            string message = "Vectors must have a length of 3.";
            throw new Exception(message);
        }
        DLA.Vector result = new DLA.DenseVector(3);
        result[0] = left[1] * right[2] - left[2] * right[1];
        result[1] = -left[0] * right[2] + left[2] * right[0];
        result[2] = left[0] * right[1] - left[1] * right[0];

        return result;
    }

针对三维向量。

推导在高数下教材上有,和我一样数学差的可以去查。结论是

\[c=a\times b=\begin{vmatrix}i&j&k\\a_x&a_y&a_z\\b_x&b_y&b_z\end{vmatrix}\]

所以

\[i_c=\begin{vmatrix}a_y&a_z\\b_y&b_z\end{vmatrix}\]

\[j_c=-\begin{vmatrix}a_x&a_z\\b_x&b_z\end{vmatrix}\]

\[k_c=\begin{vmatrix}a_x&a_y\\b_x&b_y\end{vmatrix}\]

开始想把这部分写成DenseVector的扩展函数,后来想想既然只能用在3维向量上,就放到自己的Vector(三维)类里了。