<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>N/A - 标签 - 有价值炮灰</title>
        <link>https://evilpan.com/tags/n/a/</link>
        <description>N/A - 标签 - 有价值炮灰</description>
        <generator>Hugo -- gohugo.io</generator><language>zh-CN</language><managingEditor>i@pppan.net (evilpan)</managingEditor>
            <webMaster>i@pppan.net (evilpan)</webMaster><copyright>This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.</copyright><lastBuildDate>Sun, 07 May 2017 22:40:00 &#43;0800</lastBuildDate><atom:link href="https://evilpan.com/tags/n/a/" rel="self" type="application/rss+xml" /><item>
    <title>软件开发的一些&#39;心法&#39;</title>
    <link>https://evilpan.com/2017/05/07/about-programing/</link>
    <pubDate>Sun, 07 May 2017 22:40:00 &#43;0800</pubDate><author>
        <name>evilpan</name>
    </author><guid>https://evilpan.com/2017/05/07/about-programing/</guid>
    <description><![CDATA[<p>从事软件开发也有好几年了,和一开始那个懵懵懂懂的小菜鸟相比,自己也感觉到了
一些变化. 也许是熟能生巧,趟过很多坑,但核心的绝不是这些细节的东西.
打个比方,如果说对某种语言的特性和技巧的掌握属于身法, 那么对应核心的东西,
就叫心法. 没有身法,心法难以实战;但是没有心法,身法再炫也不过是无谓的杂耍而已.
今天,就来讲讲多年浸淫软件开发所感悟的一些&quot;心法&quot;.</p>
<h1 id="三部曲" class="headerLink">
    <a href="#%e4%b8%89%e9%83%a8%e6%9b%b2" class="header-mark"></a>三部曲</h1><p>软件开发,无论是用什么语言,在什么操作系统,都有其本身不变的东西,称之为编程思想.
对我而言,我所遵循的开发思想其实很简单,却都是血泪的经验所汇结而成. 我将其总结为三点:</p>
<ol>
<li>Make it work, 2) Make it clean, 3) Make it fast. 排序分先后,而且缺一不可.</li>
</ol>
<h2 id="make-it-work-使其可用" class="headerLink">
    <a href="#make-it-work-%e4%bd%bf%e5%85%b6%e5%8f%af%e7%94%a8" class="header-mark"></a>Make it work (使其可用)</h2><p>这个规则似乎是显而易见的, 软件开发的目的就是为了解决实际问题. 但是,忘记这个规则的
程序员,也不在少数. 君不见,每次上技术论坛,都有人在问:&ldquo;我是新手,应该学哪门语言?&rdquo;,
或者讨论&quot;XXX语言怎么臃肿复杂难用&quot;,&ldquo;XXX语言怎么语法奇异古怪&rdquo;,等等.</p>
<p>说真的,这些事情重要吗? 我学的第一门编程语言是Verilog,之后转到SystemC做系统仿真,
后来顺其自然地学习了C++,之后才完全转到软件行业. 说这个想说明, 对于新手而言,
第一门学习的语言并不重要, 它的作用是让你了解人与机器的交互接口, 也就是条件,
循环,函数等基本概念. 再者,学习某一门编程语言,最好的办法就是那句至理名言:<code>JUST DO IT</code>,
纠结于语言,平台,难度这些东西反而是本末倒置, 编程首先要明确的事情是你想做什么.
比如想做嵌入式,硬件相关,那C/C++是首选; 想做手机app, 当然是Java(Android)或Objective C;
想做些数据处理,或者小工具简化日常工作,那我会推荐Python;想做网页,除了JavaScript还有其他选择吗?
因此, 忘记网上那些讨论吧. 语言圣战,也许只有新手才会热衷于此. 听闻使用不同开发语言的人会互相鄙视,
比如C++鄙视JAVA, JAVA鄙视Python, Python鄙视JS, 等等, 这让我深感无聊且幼稚.</p>
<p>对于有经验的软件开发人员,太执着于开发语言更是不必要. 既然是有经验,那至少是对各种类型的语言都有所了解,
比如强类型的C/JAVA, 动态类型的Python以及某种函数式语言如Scala或Haskell等. 多种语言之间虽然语法稍微有所不同,
但大体上都能在上述类型中找到很多相似的地方,也就是说,只要稍微花一两周学习语法,应该要能很快投入到团队项目中.
当然对于特别复杂的语言(如C++),多花点时间了解语言特性也是必要的.</p>
<p>总而言之,好的软件工程师,应该要有举一反三,快速学习的能力. 最为重要的,不要忘记自己出手的目的,
那就是Make it work, 客户端应用也好, 服务端组建也罢, 都是为了实现其功能, 对其他服务或者人进行有效而正确的交付.
在这个阶段, 除了功能无需考虑太多其他事情, 不忘初心, 才能免于掉入效率的陷进之中.</p>
<h2 id="make-it-clean-使其整洁" class="headerLink">
    <a href="#make-it-clean-%e4%bd%bf%e5%85%b6%e6%95%b4%e6%b4%81" class="header-mark"></a>Make it clean (使其整洁)</h2><p>代码整洁,是每个软件工程师都或多或少听说过的概念. 但是这个概念又不像第一点那样显而易见.
因为我们即使不管代码整洁与否,程序都能实现最初的功能,交付给老板他也很是高兴. 相反,
如果多花时间在代码的整洁性上,那必然会延时交付,从而会使得老板不高兴.因此, 这一条也是
三部曲中分歧最大的.</p>
<p>当然了,对于软件工程师而言,在时间足够的情况下,几乎不会有人反对代码整洁. 但现实是项目的时间
往往紧迫,而且改善代码质量在短期内也看不出有什么收获. 可是如果不注重,等到项目规模扩大之后,
开发者就会陷入代码耦合,结构混乱,难以拓展和难以维护的屎坑之中.</p>
<p>关于代码整洁,细说起来也是内容庞杂. 在这里可以推荐三本书:</p>
<ul>
<li>&laquo;代码整洁之道&raquo;</li>
<li>&laquo;重构:改善既有代码的设计&raquo;</li>
<li>&laquo;设计模式:可复用面向对象软件的基础&raquo;</li>
</ul>
<p>在软件功能开发结束之后,我们可以优化现有的代码,将其中的模块和逻辑重新整理,使得整体结构清晰明朗,
一些有用的模块,可以独立出来,可以复用到以后的项目之中,以减少重复造轮子的时间.</p>
<p>值得一提的是, 代码整洁往往离不开重构, 而重构又离不开单元测试. 因为只有单元测试有足够的覆盖率,
你才能在改善代码的时候保证不影响现有的功能. 不论是对现有代码的重构, 还是保证新代码的一致性(coding style),
都需要额外花费时间, 但最后你会发现所付出的小部分时间, 会在将来以10x的效率提升而返还.</p>
<h2 id="make-it-fast-使其高效" class="headerLink">
    <a href="#make-it-fast-%e4%bd%bf%e5%85%b6%e9%ab%98%e6%95%88" class="header-mark"></a>Make it fast (使其高效)</h2><p>没人喜欢慢吞吞的代码. 对于面向用户的服务更是如此. 如果每次打开一个APP或者渲染一个页面,都需要5,6秒的时间,
那很可能这个用户就流失掉了. 除去I/O的原因, 程序运行的效率也是一个重要的考量因素.</p>
<p>影响程序运行速度的原因有很多,比如算法的复杂度,内存分配/拷贝的频率,以及系统上下文切换等.
很多时候我们也不能想当然地就进行优化. 正确的做法是通过<code>profiler</code>来进行分析. 现代的集成开发环境(IDE),
应该都会提供对应的profiler. 以Linux的c/c++程序为例, 我们就可以用<code>gprof</code>对应用程序进行分析.
其提供了每个函数的运行时间(百分比)/累计运行时间,调用次数等有用的信息,帮助我们查找程序热点,
从而改善程序的执行效率. 毕竟,根据二八定律,程序运行所消耗80%的时间,大都产生于20%的代码之中.</p>
<p>改善效率,有可能是减少某个具体算法函数的时间复杂度(比如替换random函数),有可能是用引用取代复制减少内存拷贝,
也有可能是增加缓存减少网络/磁盘的IO频率. 具体的方法取决与程序的热点所在. 一些看起来似乎有用的做法,
比如循环展开,函数inline以期减少堆栈开销等, 简直是大腿上把脉——瞎搞.</p>
<h1 id="乱序陷阱" class="headerLink">
    <a href="#%e4%b9%b1%e5%ba%8f%e9%99%b7%e9%98%b1" class="header-mark"></a>乱序陷阱</h1><p>上面讲了软件开发过程中的三部曲,但是有一点非常重要,即三部曲的顺序是严格从上倒下的. 而其中一些乱序错误,
也成为了如今常见的开发阻碍:</p>
<h2 id="提前优化" class="headerLink">
    <a href="#%e6%8f%90%e5%89%8d%e4%bc%98%e5%8c%96" class="header-mark"></a>提前优化</h2><p>如果开发时第一步考虑的不是使其可用,而是使其高效,那么很有可能就掉进了提前优化的陷阱. 相信大家对
&ldquo;提前优化是万恶之源&quot;这句话也不会陌生. 如果开发者在八字还没一瞥的时候就说, 我要弄三级缓存减少数据库访问,
或者我要整合xxx-kqueue支持C1000K的高并发, 那么这个项目可能就危险了. 且不说优化是否能成功地work around,
即便这个针对性的优化达到其性能要求,也未必是最终应用的热点所在. 花了大把时间, 最后可能缓存命中率极低,
或实际最高并发数还不到500, 那这些功夫就有点得不偿失了. 再者,提前的优化为初期开发套上了枷锁,
从某种程度上说,也降低了项目的开发效率.</p>
<h2 id="滥用设计模式" class="headerLink">
    <a href="#%e6%bb%a5%e7%94%a8%e8%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f" class="header-mark"></a>滥用&quot;设计模式&rdquo;</h2><p>上面第二点代码整洁中提到了,软件开发,特别是面向对象的软件开发,其好处在于可以切分模块边界,使得代码可以复用.
但是我却不提倡对此过于执着. 首先想代码能够重用, 就必须给模块提供对应的灵活性, 也就是说单一模块的功能应该尽量
简单且通用. 事实上功能越具体的模块就越难以重用, 只有一些抽象的功能才值得花功夫去提炼.</p>
<p>设计模式, 通常指的是GoF的23中面向对象的设计模式. 有的程序员看过此书后,就急着上手应用,每次项目刚开始,就考虑
要用哪几个模式,这来个Factory,那来个Delegate. 这其实有点本末倒置,无异于拿着锤子找钉子. 设计模式的初衷是
改善代码结构,减少耦合提高扩展性. 这只在项目到了一定规模才会有实际好处, 如果只是中小型项目, 增加的这些间接层,
很有可能反而提高了复杂性,纯属画蛇添足.当然, 如果你是个非常有经验的程序员, 对于这些模式的best practice了然于胸,
在某些情况下一开始就采用某种结构也无不可, 但我还是建议对其采用保守态度, 毕竟&rsquo;Simple is better than complex&rsquo;.
设计模式最好还是在重构的阶段再按情况决定是否采用为好.</p>
<p>除了重构,代码整洁的一个重要方面是编码规范,这倒是要在项目开始前制定好的,比如变量命名,大括号换不换行,用空格还是TAB缩进,
每个公司或者小组都应该有固定的规章,这样可以免去为这些细枝末节的事情操心,从而专心投入功能开发之中.</p>
<h1 id="总结" class="headerLink">
    <a href="#%e6%80%bb%e7%bb%93" class="header-mark"></a>总结</h1><p>综上所述,一个高效的软件开发过程应该是这样的:</p>
<ol>
<li>明确开发需求.</li>
<li>针对需求切分不同功能模块.</li>
<li>针对每个模块编写代码/单元测试.</li>
<li>对每个模块进行结构整理(即重构).</li>
<li>对每个模块进行性能优化(可选).</li>
<li>整合所有模块,如果需要可以再次进行重构,提炼公共部分.</li>
<li>最终测试/交付.</li>
</ol>
<p>最后,这只是笔者的一家之言,对于本人来说确实可以显著提高开发效率, 但每个人的经验和习惯可能并不相同,
也许细节上也会有所不同, 但即便道路不同,我们想要&quot;做出点东西&quot;的心情也都是一样的. 所以需要做的则是摒弃偏见,
兼听并济,取长补短,最终形成属于自己的高效开发模式.</p>]]></description>
</item><item>
    <title>An Elegy on the Death of a Mad Dog</title>
    <link>https://evilpan.com/2016/01/06/an-elegy-on-the-death-of-a-mad-dog/</link>
    <pubDate>Wed, 06 Jan 2016 22:40:00 &#43;0800</pubDate><author>
        <name>evilpan</name>
    </author><guid>https://evilpan.com/2016/01/06/an-elegy-on-the-death-of-a-mad-dog/</guid>
    <description><![CDATA[<p>Good people all, of every sort,<br>
Give ear unto my song;<br>
And if you find it wondrous short,<br>
It cannot hold you long.</p>
<p>In Islington there was a man,<br>
Of whom the world might say,<br>
That still a godly race he ran——<br>
Whene&rsquo;er he went to pray.</p>
<p>A kind and gentle heart he had,<br>
To comfort friends and foes;<br>
The naked every day he clad——<br>
When he put on his clothes.</p>
<p>And in that town a dog was found,<br>
As many dogs there be,<br>
Both mongrel, puppy, whelp and hound,<br>
And curs of low degree.</p>
<p>This dog and man at first were friends;<br>
But when a pique began,<br>
The dog, to gain some private ends,<br>
Went mad and bit the man.</p>
<p>Around from all the neighbouring streets<br>
The wondering neighbours ran,<br>
And swore the dog had lost his wits,<br>
To bite so good a man.</p>
<p>The wound it seemed both sore and sad<br>
To every Christian eye;<br>
And while they swore the dog was mad,<br>
They swore the man would die.</p>
<p>But soon a wonder came to light,<br>
That showed the rogues they lied,——<br>
The man recovered of the bite,<br>
The dog it was that died.</p>
<hr>
<p>Oliver Goldsmith<br>
1766</p>]]></description>
</item><item>
    <title>分叉的分叉</title>
    <link>https://evilpan.com/2015/10/25/falling-apart/</link>
    <pubDate>Sun, 25 Oct 2015 22:40:00 &#43;0800</pubDate><author>
        <name>evilpan</name>
    </author><guid>https://evilpan.com/2015/10/25/falling-apart/</guid>
    <description><![CDATA[<p>每次看到有关穿越（时间旅行）题材的电影或小说，总感觉很厌烦，一来本身无法自圆其说，二来也无法解释一些常见的矛盾如&quot;祖父悖论&quot;。
前几天又看了一部此类型的电影——《X战警逆转未来》，影片本身平平常常，但是由此衍生出现在的这些废话，亦即关于时间穿越的我的一些
想法和可能的解释，权且作为无聊思考的记录，并没有严格的证明。事实上我大学量子力学的期末考试依靠作弊也才70出头，想要给出严格证
明也是不可能的。</p>
<p>首先，如果时间旅行真的可能，必须使得现在已知的悖论得以解决。为此我将世界假定为当下流行的“平行世界模型”，即每一个时刻的世界
都是平行发生的，当我碰到红灯时，有两种选择，一是继续前进，二是等待绿灯；继续前进的我是一个世界的我，姑且称之为世界1；等待绿
灯的我是另一个世界的我，称之为世界2；；两个世界各自平行地向前生长。在世界1里，也许我被车撞倒，进了医院；在世界2里，我通过马路，
正常打卡上班。这只是一种简单假设，实际上由于万物可以无限细分，选择也可以在无限的时间细分，大千世界里又有大千世界，毫不含糊。</p>
<p>为了使问题简单，首先做一点简化。假设W为某一时刻的世界，并且在此时刻之后仅有两种发展的可能，即世界W1和W2，而后者也分别有两种
后续发展W11、W12、W21、W22。假设我们现在所在的世界为W22，并且打算穿越到W以改变当下的境遇（即逆转未来），那么过程应该如何呢？
穿越的方式有两种，一种为肉体穿越，即整个人连同内衣裤都转移到从前；另一种为意志穿越，或者说精神穿越，即尽有类似于灵魂的东西出
现在过去来改变世界运转。肉体穿越不大现实，所以暂且假定为意志穿越，即我现在的意志像灵魂出窍一样回到过去，并且附身于从前（W）的
自己，W的我的灵魂则压入堆栈，暂时失去身体的控制权，由此我就能开始改变世界啦！改变之后，W的灵魂W22出栈，回到W22中，享受修改了的世界。</p>
<p>就这么简单了？刚刚说到世界像分叉一样向前生长，改变了的W是否还会生长到W2进而到我原来意识中的一模一样的W22呢？也许不会，但是
如果没有在穿越的时候大搞破坏的话，应该大同小异。也许回到W22之后会发现有些事变了，生命中会莫名其妙地少了几个人或者多了几个人。
X战警中就是这样的设定，但这是有问题的。原W22的金刚狼灵魂出窍修改了W再回到W22，但回去的W22（暂且成为W22B）已经不是原来的W22（称为W22A）了，
W22A的金刚狼的灵魂强占了W22B的金刚狼的灵魂，那么W22B的金刚狼的灵魂则在那一刻之后永远沉入栈底，这是多么可悲的啊，按照这种理论，还会发现他
在一夜之间性情大变，不觉得奇怪吗？</p>
<p>因此按照平行世界的理论，虽然穿越到过去可以实现，但是也无法改变现在。假设灵魂可以出窍，那么之后他将看到无数可选的世界（处于不同的时间），
改变过去之后会出现一个更好的现在，但是已经有原生的灵魂居住了。事实上根本不用去修改过去，就会有一个和现在类似的但是更美好的世界，与我所
来的世界平行前进，但是幸福是我的，幸福也不是我的。这也解释了我心里的一个疑惑，即为什么未来的我不穿越回来把福利彩票的中奖号透露给我，
因为一则我是如此之多，他根本就无法选择，二则即便透露了，快乐也是我的，他什么也没有。</p>
<p>即便这些方式能解释穿越之后引致的矛盾，此外也还有更加严峻的问题，比如在W22时间结点之后，人类掌握的时间旅行的技术，那么从这一时刻开始，
各种不安分的灵魂就会到处乱窜，从前朴素的灵魂就会不断被压入堆栈，这点又怎么解决呢？反证而言，甚至可能灵魂根本就无法进入过去的人的身体，
无法左右过去的世界，只能在一片苍茫中无形地飘荡。结果是所谓的穿越时间，最终还是沦为一场4D的iMaX原始纪录片观影旅行。</p>]]></description>
</item><item>
    <title>If ——</title>
    <link>https://evilpan.com/2015/10/24/if/</link>
    <pubDate>Sat, 24 Oct 2015 22:40:00 &#43;0800</pubDate><author>
        <name>evilpan</name>
    </author><guid>https://evilpan.com/2015/10/24/if/</guid>
    <description><![CDATA[<p>If you can keep your head when all about you<br>
Are losing theirs and blaming it on you,<br>
If you can trust yourself when all men doubt you,<br>
But make allowance for their doubting too;<br>
If you can wait and not be tired by waiting,<br>
Or being lied about, don’t deal in lies,<br>
Or being hated, don’t give way to hating,<br>
And yet don’t look too good, nor talk too wise:</p>
<p>If you can dream—and not make dreams your master;<br>
If you can think—and not make thoughts your aim;<br>
If you can meet with Triumph and Disaster<br>
And treat those two impostors just the same;<br>
If you can bear to hear the truth you&rsquo;ve spoken<br>
Twisted by knaves to make a trap for fools,<br>
Or watch the things you gave your life to, broken,<br>
And stoop and build ’em up with worn-out tools:</p>
<p>If you can make one heap of all your winnings<br>
And risk it on one turn of pitch-and-toss,<br>
And lose, and start again at your beginnings<br>
And never breathe a word about your loss;<br>
If you can force your heart and nerve and sinew<br>
To serve your turn long after they are gone,<br>
And so hold on when there is nothing in you<br>
Except the Will which says to them: “Hold on!”</p>
<p>If you can talk with crowds and keep your virtue,<br>
Or walk with Kings—nor lose the common touch,<br>
If neither foes nor loving friends can hurt you,<br>
If all men count with you, but none too much;<br>
If you can fill the unforgiving minute<br>
With sixty seconds’ worth of distance run,<br>
Yours is the Earth and everything that’s in it,<br>
And—which is more—you’ll be a Man, my son.</p>]]></description>
</item></channel>
</rss>
