给我看一个解决方案,开发人员不会因为这个问题而争论,所以我给你喝啤酒



有两个不可调和的阵营。有人说:您必须准确,胜任地描述自己的所作所为。每次提交都是完整,有意义的工作。如果您不能对提交进行清晰,简单的描述,那么您将提交错误的提交。

其他人则认为您可以随意进行提交,这是您个人工作流程的一部分。但是详细描述了请求池:完成了什么,如何完成了,为什么完成了。经过测试,问题解决了,您应该注意什么。

我是第二种方法的坚定支持者-将我的工作分解为微型部分是很不方便的。我承担了一个小任务,随机浏览代码库,尝试并按顺序进行更改。如果我可以单击一个按钮,并且我的工作将被重组为良好的提交,则可以单击它。但是没有按钮,但是我不想伤自己。同时,我在描述请求池方面达到了一定的技巧。我碰巧弄清楚了Microsoft中的代码(通过outstaff,它不算在内),在那里我得到了处理请求池的最高标准。多年以来,我一直在发展这种做法。通常,我设法说服团队使用这种方法。

但是在上一份工作中,我很生气-坚定的详细承诺支持者。哦,我们吵了很久。我的下属职位发挥了作用,Sovkovsky与主要事情保持一致的习惯不容易闭嘴。我不像往常那样坚定,被放在两把刀上。堆积,但不确信。



如果开发商突然联合起来组成一个政府,制定规则并开始宣布某些方法被禁止,那么内战将在第二天开始。所有这些都是因为在开发人员的世界中,人们对目标是可以衡量的。真理与人类的感知无关。而且,如果这一切都存在,则意味着其中一名争议者显然在客观上是错误的。

我的第一个严重的工作纠纷发生得很早。我仍然是一个绿色的六月,他认为他是中等水平的人,的确是一个非常酷和聪明的开发人员。我团队中的一位真正的开发人员投了PR。我们的做法是,所有团队成员都要编写审核代码。我打开代码,几乎立即看到了问题。一个人为一些用数字写的函数编写了一个测试。因此,他喂给她0、1000和随机(0、1000)。

那时,我非常敏锐地感到其他队友将我视为一个愚蠢的新人。他等了一会儿,用他的视野给他们涂抹。我很幸运-测试随机!

我不是很了解单元测试的理论,但是我读了几本书,并牢记-在相同代码库上进行相同的单元测试应该得到相同的结果。我花了大约一个小时来思考该评论,以使其看起来没有毒害,但事实表明,只有昨天才被教数的猴子才能做出这样的决定。最后,当然,他看上去非常愚蠢,就像昨天的实习生所想象的一切一样,他们想象自己是开发者。

第二天,我意识到自己已经打开了通往地狱的门户。我的评论还有一百多个。在一天的剩余时间里,我们是由六个猴子组成的团队,而不是由六个开发人员组成的团队。尽管每个人都是俄罗斯人,但我们在PR本身就用英语争论。话语不足时,他们打电话了。他们通过链接,书中的名言,书目或研究向对方投以自己的感情。一位同事用英语词典中的截图回答了我的评论之一,以嘲笑我的英语。但是我们还没有妥协。

这个问题很复杂。一方面,我们都根本不知道此参数是什么原因,我们的功能将其从没有坞站的内部网络传递给了另一个参数。因此,从理论上讲,该函数可以落在任何值上,这意味着测试可以捕获该值,然后我们可以预料到产品上的错误。另一方面,我们已经遇到了随机降低构建的问题。因此,如果项目在本地构建并且崩溃了,我们会愚蠢地订购新的构建,而不会查看任何日志。毕竟,构建花费了四个小时,并且直到它通过CI为止,没人会看拉请求。

此外,汽车经常很忙-在仍要订购时订购零件要比寻找潜在的“问题”(在集成测试中几乎总是出现飞行超时)要务实得多。这意味着即使随机测试失败了,我们也不会关注。

一切都在下一个交易中解决了。我们给整个团队打了电话,并持续了半个小时-用俄语。我们没有注意到我们的美国开发经理是如何加入电话会议的,并继续互相争吵,以高调说话。直到他们听到“嘿,这绝对不重要。只需按原样合并即可。”我不知道他之前听了我们多长时间,以及他了解我们在说什么,但我们突然停止了争论。他们冻结了,忘记了它。分开了和平,但没有被说服。



从那时起,我积累了丰富的经验,可以理解-但一点也不在乎随机,障碍或边界情况。该死的单元测试会干扰-我们将重写。一切都比整天吵架要好。但是,如果您以为自己处在理想的世界中,那么总是只需要做出更正确的决定,那我就不知道该怎么做。我们冻结了测试的随机性,现在我认为这是选择可靠性的选择,但不利于开发的便利性。

前几天,我面临着类似的困境。我玩了新的时间码,写了可以像这样使用的东西

// LessThan<T>  MoreThan<T> -    ,   . 
// ,        

//      , 
//   ,   100
const consumeNumberLessThan100 = (v: LessThan<100>) => 
    doWork(v);

//     ,   100
const consumeNumberMoreThan100 = (v: MoreThan<100>) => doWork(v);

const sample = (x: number) => {

    //     check  , 
    //   x  100
    //  "<"  ">"  , 
    //     -   
    const lessThan100 = check(x,'<', 100);

    if (lessThan100) {
        //     -  
        //       
        //    ,  lessThan100  - LessThan<100>
        //    
        consumeNumberLessThan100(lessThan100); 

        //   -  ,   , 
        //  ,   > 100.
        consumeNumberMoreThan100(lessThan100);
    }

    const moreThan100 = check(x, '>', 100);

    if (moreThan100) {
        consumeNumberMoreThan100(moreThan100); // 
        consumeNumberLessThan100(moreThan100); // 
    }

    consumeNumberLessThan100(x); // 
    consumeNumberMoreThan100(x); // 
}

我认为,该死,这非常酷-因此您可以在早期阶段捕获大量错误。我的价值限制工具的设计很糟糕,但目前仅是一个概念。将来,您可以轻松地对其进行扩展,构建功能强大的DSL并为编译阶段保证的参数匹配制定非常复杂的条件。我弄清楚了它如何增加任何代码库的可靠性,振作起来,并向各种熟悉的开发人员发送了一个代码段。

意见再次分歧,不符合我的方向。不支持复杂化,过度工程化,每个人都将在eni的帮助下阻塞您的警卫。不可读。实验良好对当前项目不利。使用的例子是从手指上画出来的。开始做生意,菲尔。

支持该方法的人说,是的,如此可靠。越早发现错误,越好。另外,如果编写的函数数量有限,则仍然需要编写检查,但是它仅在运行时有效,并且会增加函数体内的代码量。

现在,我比以前更聪明了,并且学会了听见争论。我想象自己在一个真实的项目中编写了一个受我的类型保护的函数。就像每个使用它的人一样,我在问这到底是什么。在弄乱了芯片之后,他们如何开始用自定义的,看上去很烂的DSL覆盖代码库。当我们检查三百次时,实际上永远不会超过允许值的值。这种方法真的很糟糕,可以解决或解决一些问题,但是例如

consumeNumberLessThan100(90);

请勿以任何方式平滑。我必须向编译器证明90小于100。我将提供任何活动,结果是

consumeNumberLessThan100(assert(90, '<', 100)); 

看起来不是很酷。所有反对的论据都在手,但它们并不矛盾。事实证明,这是一个难题–易于开发或可靠性。在这里,我们陷入了陷阱,我们开始认为我们需要计算那里有什么样的便利和那里有什么样的可靠性。但是开发中的便利性和可靠性是非常非常复杂的事情。它们包含数千个参数。

例如,当IDE在一对输入的字符上为您编译代码,易于阅读的代码,无需查看文档即可更改方法的功能时,便很方便。当编译器未加载静态分析时,构建速度很快,文本编辑器立即呈现字符。但是,当编译器为您检测并突出显示错误时,这也很方便。这也是可靠性。这又是由大量完全不同的事物组装而成的。

您必须坐下来计算项目将持续多长时间,它将朝哪个方向发展,在人类历史上有多少人将调用您代码库的一种或另一种方法,开发人员将在这里工作。这是无休止的问题清单,其中有一半无法计算出正确的答案。你猜吧



有一次,一个朋友问我准备一些技术问题,以接受Andrei Breslav的采访。我去了科特林码头,发现了设计中的争议点。和其他地方一样,他们在那里。但是我最感兴趣的是处理异常的方法。 Kotlin中的异常处理程序是一种表达方式,一种功能齐全且可靠的方法。那仅仅是为了处理错误是没有必要的。这将所有可靠性降为零。这很有趣,因为在码头上,开发人员并不太愿意解释他们的选择:“有研究表明,强制性错误处理大大降低了开发人员的生产力,并且错误率略有下降”。

我疯了,如果不知道在无法正常工作时该怎么办,该怎么写代码呢?如果您不知道如何处理该异常,请不要处理-不是解决问题的方法,而是搁置。在某些时候,代码将脱落,并且始终存在的问题将导致原本可以预期的损坏。

但是,不需要逻辑上的反对,您可以只进行统计。对于Kotlin开发人员来说,研究打破了逻辑,因为他们有一种哲学。他们的哲学是实用主义。铁性,牢不可破的实用主义,始终贯彻于此编程语言的所有功能之中。看到Haskels / Idris的理想主义者和写golang的govnokoders的行为完全一样。合理折衷的原则主导着F#代码库。而且没有感觉到其中之一是对的,其余的都是傻子。

所有这些人都比像我这样的人聪明得多,经验丰富,而且他们似乎早就知道您正在为自己建立一种哲学,然后您只需遵循它。因为任何哲学的杀手feature都是解决难题。

因此,哲学出现在IT的所有领域中,而哲学与单一和真实客观性的概念恰好相反,因为哲学可以为自己选择主观真理。

我们每个人都有自己的哲学-不能用一个字形容,这是一套复杂的决策模式。而且我们经常更改或扩展它们。实际上,事实证明您有一个具有自己理念的项目,该项目是使用具有自己理念的编程语言编写的,使用的框架和工具各有其自己的理念。开发人员编写该项目,每个项目都有自己的理念。每次您需要做出某种决定时,只有多种情况会影响要做出的决定。不是复杂性管理,不是经验,不是方法,不是知识,而只是偶然。

所有这些项目都有效。开发人员要解决的所有任务中,最大的一部分是消除其他开发人员的错误所带来的后果,但是项目可以解决人们的问题。聪明的人会提出实践和架构模式。具有强大的类型控制和契约的编程语言-一切,如果只有开发人员很少犯错的话。每天我在工作中打开Edge Board,我发现错误比任务多。每个错误都在哪里,这是另一个管理复杂性的废话开发人员。

开发哲学只是选择进入决赛的方式。但是,如果没有哲学,而只有纯粹的客观逻辑,那么任何争论都将归结为万能的创造者和难以承受的难题。



我从事开发工作已经很长时间了,即使我从根本上不同意,我也学会了如何做他们所说的话,并开始编写超详细的提交。我的狂妄是一个真正的吸血鬼。它不仅需要描述-他要我写每个文件的功能,原因,执行方式。 commit提交什么问题?

我添加了八个额外的提交,对请求池的相同详细描述-我喜欢kapets。从那时起,我们几乎没有从事这个特定​​的项目,但是我不时去那里欣赏这些承诺。说真的,真的,真的很酷。在我自己的项目之外的所有其他项目中,我现在都采用这种方法。

对我来说,重建工作流程非常困难。一个半月过去了,我仍然很难编写这样的代码。但这似乎值得。

或不。老实说我不知道​​。而且我不知道这是否绝对值得,这是否会让我两个月大白痴。我学会了不做这样的事情,大约有十个人在世界上某个地方走来走去。他们是白痴吗?我不这么认为。



我的播客

All Articles