熵获胜 关于软件架构、设计和工艺的博客 2023-04-02T18:44:58兹 https://www.entropywins.wtf/blog/feed/atom网站/ WordPress 杰伦 <![CDATA[初级开发人员建议]]> https://www.entropywins.wtf/blog/?p=2877 2022-12-20 T14:30:38 Z 2022-09-21T17:33:39Z 在我15年多的发展生涯中,我学到了很多东西,这些东西大大提高了我的效率。在此…

帖子对初级开发人员的建议首次出现于熵获胜.

]]>
在我15年多的发展生涯中,我学到了很多东西,这些东西大大提高了我的效率。在这篇文章中,我将与你分享这些经验。

结构:

  • 通用建议-技术咨询的重要背景和动机
  • 技术建议-主菜
  • 推荐阅读资料-链接到高质量的书籍和博客,这对入门很有帮助

这篇博客文章提到并链接了一些有价值的概念,您可以根据需要进一步探索这些概念。

青少年通用建议

1.代码不是重点

作为开发人员,我们喜欢编写代码。我们大多数人都想得到一个明确的任务。一个有趣的技术难题,不用关注世界其他地方就可以解决。

尽合理的努力确保你解决了正确的问题。引用彼得·德鲁克的话:没有什么比高效地做那些根本不应该做的事更无用的了。尽早并经常收集反馈,通常通过持续向真实用户提供反馈。Be公司 敏捷的.

软件开发成本高昂,现实世界项目的绝大多数工作通常都要进行维护。将此与用户/业务成果这一目标结合起来,最好的代码往往是没有代码引用比尔·盖茨的话:“用代码行衡量编程进度就像用重量衡量飞机建造进度。”

另请参见:雅格尼,亲吻,最后一个负责任的时刻.

2.软件设计事项

在我开发生涯的前5年里,我认为软件设计是为软件架构师或其他具有特殊角色的人设计的。我专注于“完成任务”,并认为软件设计和诸如编写测试之类的实践充其量只是分散注意力。我的代码有效了,我完成了很多事情。或者我是这么想的。

然后我读清除代码,由罗伯特·C·马丁这本书激发了人们对软件设计的关注,并包含了示例和许多技术启发。这本书的核心内容是:“跑得快的唯一方法就是跑得好“换句话说,如果你把事情搞得一团糟,它会拖慢你的速度。另请参见:可交易质量假说,设计耐力假设

学习如何编写设计良好的干净代码当然需要时间和精力。当你开始的时候,你会放慢速度,犯错误。简单并不容易.

3.使用最佳实践

写作测试往往是有益的。有一些例外,但大多数情况下,编写自动化测试很有意义。写作测试是最佳实践的一个例子。

如果你是写测试的新手,只需遵循最佳实践,为所有内容编写测试即可。开始时,盲目遵循最佳实践比遵循自己不成熟的判断要好。随着时间的推移,你将学会如何有效地编写测试,并能够分辨出你的错误和编写测试不值得的情况之间的区别。你也将开始理解测试带来的价值,经历了调试会话的减少和测试带来的无忧重构。发展判断能力后,你将能够超越最佳实践.

这条建议适用于任何初级领域的最佳实践。自动化测试只是一个例子。

一个大问题是,要区分明智的最佳实践和荒谬甚至适得其反的做法是不容易的。由于大多数现有代码一团糟,以及大多数开发人员(包括“经验丰富”和“资深”的开发人员)不知道软件设计基础知识,这使得情况变得更加复杂。这使得有一个好的导师非常有价值。除此之外,根据我自己的经验,有一条建议是要警惕特定于您的语言或框架社区的最佳实践。寻找已经存在数十年的常青建议。

青少年技术建议

我们的重点将放在技术主题上。其他许多领域也很重要,例如健康、幸福、职业和软技能。如果你睡眠不足,并且为一个给你薪水低的有毒老板解决了错误的问题,那么知道如何避免技术陷阱对你没有帮助。

4.写测试

编写自动化测试。可能在编写代码之前编写测试,例如通过测试驱动开发(TDD)。这使得以可重复的方式验证代码是否正确变得容易,从而避免了大量手动重试和调试会话。

你觉得第一次考试很难吗?尝试调试之后。

也许更重要的是,测试为您提供了重构代码的安全网。为了保持代码干净,需要不断重构。如果没有可靠的测试套件,您的代码就更有可能烂掉。

如果代码的设计很差,比如在使用继承进行代码重用或使用静态函数时,编写测试是很困难的。另一方面,如果你有固体没有全局依赖性的类,那么编写好的测试就不那么困难了。

测试设计很重要,因为写得不好的测试会让您慢下来。避免将测试绑定到被测试代码的实现细节或系统结构。避免过度使用Mocks和写得更好的双打测试.

5.不要将继承用于代码重用

这是让人想起“使用最佳实践”部分的最佳实践之一。我的建议是:在开始时,不要将继承用于代码重用。这很少是正确的选择,可能会造成很大的伤害。偏爱组合胜于继承.

6.编写面向对象的代码

写入固体不是的代码愚蠢的。理解这些原则和反模式非常有价值。

实际创建对象。只有静态方法的类不是OO。尽量避免完全使用静态代码。

另请参见:我对SOLID的辩护.

7.编写功能代码

(功能性编程不要与之混淆命令 结构规划

这一点并不是关于如何切换到函数式语言。您可以从OO语言中使用函数样式中获益。最小化状态,尤其是可变状态,以及在你的函数中做一件事。另请参见:功能核心,命令式外壳.

8.使用知情复制

将大块代码复制到多个位置几乎总是不明智的。任何自负的开发人员很快就会了解到这一点,并开始遵循某种形式的不要重复自己(干燥)。不幸的是,有意追求DRY往往会导致过度设计和意外复杂性。这就是DRY的对应词:Write Everything Twice(WET)。WET背后的理念是只在第三次出现重复时进行重复数据消除。

要更深入地了解重复数据消除的成本和好处,请参阅DRY的谬误.

9.类型、名称和注释

尝试编写自文档化代码并避免注释。

每次你写评论的时候,你都应该做鬼脸,感觉自己表达能力的不足罗伯特·C·马丁

评论是危险的,因为它们可以撒谎。代码可以在不更新注释的情况下更改。可以在注释下方添加新代码。该评论可能一开始就错了或不准确。当这种情况发生时,评论不仅变得无用,而且具有误导性。

编写自我记录代码:

  • 在你的功能中做一件事
    • 通过在函数中执行一件事,可以给它一个清晰的名称
    • 感觉有必要通过添加注释来解释函数的不同部分做什么?相反,将每个部分提取到其自己命名良好的函数中。
    • 抽到你掉下来“:如果你能有意义地提取一个函数,那么你可能应该这样做。不要害怕小函数。
    • 命令查询分离
    • 类似于单一责任原则类(固体中的S)
  • 最小化状态
  • 使用类型结合执行代码的测试套件,您可以依赖类型来说明真相。
  • 避免混合类型。避免使用可以是整数、布尔值或字符串的参数或返回值。如果编写只做一件事的聚焦函数,则自然会发生这种情况。
  • 编写测试。一个编写良好且全面的测试套件将向您展示如何使用生产代码以及它的行为。

清除代码作者Robert C.Martin在命名和评论方面有一些很好的经验法则。

青少年推荐阅读

博客

另请参见:开发人员推荐阅读作者:Jeff Atwood

奖励链接

帖子对初级开发人员的建议首次出现于熵获胜.

]]>
0
杰伦 <![CDATA[在MediaWiki中使用PSR-3 Monolog]]> https://www.entropywins.wtf/blog/?p=2856 2022-07-20T11:42:01Z 2022-02-08T16:18:31Z 几年后,您可以使用MediaWiki中的PSR-3 LoggerInterface来记录消息。但你怎么知道…

帖子在MediaWiki中使用PSR-3 Monolog首次出现于熵获胜.

]]>
几年后,您可以使用PSR-3记录器接口在MediaWiki中记录消息。但你如何告诉MediaWiki使用特定的记录器?在这篇技术文章中,我们将研究如何在MediaWiki中使用Monolog记录器。

如果您使用过独白之前,你大概知道如何创建记录器添加处理程序大多数人使用$wgDebugLogGroups($wg调试日志组)。但是,此配置不允许我们将(Monolog)Logger实例注入到MediaWiki中。

相反,您可以使用$wgMWLoggerDefaultSpi,指定创建MediaWiki使用的记录器的服务。你可以使用MediaWiki提供的MonologSpi。但正如你在MonologSpi文档,这里的标准MediaWiki方法可能与您的期望不符。无法注入通过标准Monolog方法创建的Logger实例。

我们可以通过创建自己的迷你Spi实现来解决这个问题。在这个实现中,您可以创建(并缓存)Logger或获取现有的Logger实例。下面的复制稳定示例显示了如何配置MediaWiki以使用现有的Logger实例。

$logger=new\Monolog\logger(“名称”);$logger->pushHandler(new\Monolog\Handler\StreamHandler,__DIR__.'/cache/error.log',\Monolog\logger::error);$wgMWLoggerDefaultSpi=[“factory”=>function()use($logger):\MediaWiki\logger\Spi{return新类($logger)实现\MediaWiki\logger\Spi{private\Monolog\Logger$Logger;公共函数__construct(\Monolog\Logger$Logger){$this->logger=$logger;}公共函数getLogger($channel){返回$this->logger->withName($channel);}};}];

由于Logger是您自己构建的,因此您可以使用Monolog生态系统中可用的所有工具随意配置它。

上述示例使用PHP 7.4。

帖子在MediaWiki中使用PSR-3 Monolog首次出现于熵获胜.

]]>
0
杰伦 <![CDATA[PHP 8.1中的值对象]]> https://www.entropywins.wtf/blog/?p=2848网址 2022-01-30T12:59:53Z 2022-01-30T12:58:58Z PHP引入了许多新功能,允许您使用PHP8.1编写很棒的Value Objects。在…中…

帖子PHP 8.1中的值对象首次出现于熵获胜.

]]>
PHP引入了许多新功能,允许您使用PHP8.1编写很棒的Value Objects。在这篇文章中,你将了解每个功能以及如何将它们组合在一起。

回到2016年的黑暗时代,PHP 7.0发布后不久,我写了一篇PHP 7中缺少博客文章系列。五篇文章中有四篇描述了PHP 8.1或更早版本中不再缺少的功能。PHP7中缺少:值对象就是这些帖子之一。

您可以在中快速回顾什么是Value Object,以及为什么要使用它们PHP7中缺少:值对象.

自PHP 7.0以来的新功能/语法

使用PHP 8.1特性的Value对象

类ContactRequest{公共函数__construct(公共只读字符串$firstName='nyan',公共只读字符串$lastName=“cat”,公共只读字符串$emailAddress=“something”,) {}}$request=新ContactRequest(firstName:'foo',lastName:'bar',emailAddress:'baz');$firstName=$request->firstName;$request->lastName='hax';//失败

奖金

其他令我兴奋的PHP新功能:

帖子PHP 8.1中的值对象首次出现于熵获胜.

]]>
0
杰伦 <![CDATA[新建MediaWiki博客]]> https://www.entropywins.wtf/blog/?p=2673 2019-10-29T05:22:20Z 2019-10-26T04:33:30Z 我很高兴地宣布一个全新的博客,专门介绍MediaWiki和所有与企业wiki相关的内容。半年…

帖子新建MediaWiki博客首次出现于熵获胜.

]]>
我很高兴宣布推出一个全新的博客,专门介绍MediaWiki和所有与企业wiki相关的东西。

半年前我推出了专业Wiki和Karsten Hoffmeyer一起。顾名思义,专业维基是一家提供专业维基服务的公司。我们帮助公司创建和管理wiki,提供培训和支持,并提供完全管理的wiki托管.

今天我们发布了我们的新建博客在上发布了第一篇文章使用Composer安装MediaWiki扩展。此博客将包含维基新闻和长期存在的文章,例如关于作曲家的文章。

近年来,我对在这个博客(EntropyWins)上发布MediaWiki特定的内容犹豫不决,因为它已经演变成了对软件设计的关注。新的专业Wiki博客解决了这个问题,所以您可以期望更多MediaWiki相关帖子又从我这里。

帖子新建MediaWiki博客首次出现于熵获胜.

]]>
0
杰伦 <![CDATA[应用程序作为框架]]> https://www.entropywins.wtf/blog/?p=2495 2021-08-27T15:47:38Z 2019-02-28T07:38:47Z 在框架之上构建和在应用程序之上构建有什么区别?如何…

帖子作为框架的应用程序首次出现于熵获胜.

]]>
在框架之上构建和在应用程序之上构建有什么区别?将应用程序用作框架是如何导致问题的,如何避免这些问题?这就是这篇文章的全部内容。

分离的web应用程序

在典型的web应用程序中,代码处理请求并返回响应。假设我们正在使用web框架来处理常见任务,例如路由。我们还假设框架绑定的成本很高,因此将应用程序与框架分离。控制流如下所示:

执行从框架开始。对于PHP框架,这将在一个类似于公共/index.php然后,框架自举并执行一系列操作。可以放心地假设这些内容将包括路由,并且通常还包括依赖关系构造和错误处理等内容。

框架完成了您希望它完成的任务后,它将控制权移交给您的应用程序。您的应用程序执行一系列应用程序和域逻辑,并与持久性交互。它可能会使用许多库,特别是用于日志记录和数据库访问等基础设施任务。即便如此,控制权仍保留在应用程序中。(框架和库之间的关键区别在于,您控制/调用库,而框架控制/调用您。)您的应用程序也可能正在调用框架并将其用作库。同样,控制权留在应用程序中。

最后,当应用程序完成时,它会将某种结果返回给框架。然后,框架会执行另一系列操作,如模板渲染和翻译。对于web框架,它会发出HTTP响应并结束执行。

这样的应用程序可以让您控制发生的事情,使更改变得更容易。这种风格还可以很容易地与框架解耦。只有两点需要解耦。

我的帖子实施清洁体系结构概述了导致这种应用程序的一种体系结构方法。

框架与应用程序

让我们比较一下当框架和应用程序用作一个/另一个应用程序的基础时,它们之间的区别。

框架本身不做任何事情。没有应用程序或域逻辑。没有一组现有的网页或API端点具有自己的结构和行为。这都是在使用框架时由应用程序定义的。当在用作框架的应用程序之上构建时,您需要处理现有的结构和行为。您需要插入自己的内容,在某些情况下更改现有行为,并在其他情况下完全防止默认行为。

我知道有些“框架”确实提供了自己的现成内容。(例如:网络商店框架。)虽然它们本身可能不是一个完整的应用程序,但就本文而言,它们与用作框架的应用程序是一样的。

插件和扩展

在应用程序之上构建东西并没有本质上的坏处。插件和扩展是一种非常有用的模式。与单个插件点交互的插件可以在适当的时候解耦自己,并且可以控制自己。对于使用多个插件点的较小插件,框架解耦可能不可行,也不值得努力。

这篇文章是关于使用应用程序作为大量代码集的框架基础,这些代码集本身就是应用程序。

作为框架的应用程序

假设我们有一个应用程序,在某个站点上用于某些用例。我们将此应用程序称为FrameworkApp,因为我们将其用作另一个应用程序的框架,该应用程序为另一个站点提供动力。

在FrameworkApp之上构建应用程序时,我们需要注册新的行为并修改现有的行为。为了实现这一点,FrameworkApp需要提供适当的扩展点。这些扩展点通常采用抽象类甚至系统的形式,尽管扩展点的确切性质对于我们的目的并不重要。

这导致了一个非常不同的控制流。FrameworkApp不会调用我们一次,而是调用应用程序处理的每个扩展点。

图中只显示了6个扩展点,尽管可能有100个。

当像这样可视化时,很容易看出与框架的解耦是如何变得几乎不可能的。即使您设法避免与框架耦合代码在您的应用程序中,它的整体结构是仍然由框架定义这意味着您在应用程序中的操作非常有限,需要了解框架才能有效开发应用程序。框架耦合导致的问题不止这些,尽管对这些问题的全面概述超出了本文的范围。

OOP解决方案

偏爱组合胜于继承

-OOP原则

使用应用程序作为框架与使用继承进行代码重用非常相似。

就像构建在充当框架的应用程序之上的应用程序一样,子类可能无法控制,并且可以从基类多次调用。在使用模板方法模式和具有深层继承层次结构时尤其如此。控制流可以到处跳跃,将子类与层次结构上的类解耦几乎是不可能的。

您可以通过使用组合来避免这种经典的继承混乱。这建议了一种摆脱将应用程序用作框架或完全避免这样做的方法:停止将框架视为基类。如果有代码要共享,请使用组合。这样你可以保持控制,可以更容易地解耦并避免DRY的谬误.

就像类层次结构一样,您可以随时添加额外的级别。

不要错过这本书!

在下面注册以获得我即将出版的《清洁建筑》一书的新闻,包括折扣:

 

帖子作为框架的应用程序首次出现于熵获胜.

]]>
0
杰伦 <![CDATA[可读函数:保护子句]]> https://www.entropywins.wtf/blog/?p=2407 2019-04-29T03:15:45Z 2019-01-14T07:44:32Z 保护子句是我最喜欢的一个小技巧,可以简化代码。保护子句是if语句…

帖子可读函数:保护子句首次出现于熵获胜.

]]>
保护子句是我最喜欢的一个小技巧,可以简化代码。保护子句是一个带有返回的if语句。请考虑以下代码:

函数doThing(){var$thing='default';if(someCondition()){$thing=“特殊情况”;}return$thing;}

使用保护条款,我们可以将其简化为:

函数doThing(){if(someCondition()){return“特殊情况”;}return'default';}

这个简化代码中的if语句是一个保护条款。你可以有函数中的多个Guard子句.

简化删除了所有函数中的状态包括第一种形式的代码中令人讨厌且完全不需要的变异。您可以按顺序读取新代码,并且Guard子句之后的代码不会被特殊情况所带来的额外复杂性所污染。

这篇文章是可读函数该系列包含如下一条和两条一般原则:最小化状态做一件事.

帖子可读函数:保护子句首次出现于熵获胜.

]]>
杰伦 <![CDATA[我在书中的一年]]> https://www.entropywins.wtf/blog/?p=2413 2023-04-02T18:44:58兹 2019-01-03T21:47:02Z 2018年,我读的书比以往任何时候都多。以下是我的一些建议和想法。我读了21…

帖子我读书的一年首次出现于熵获胜.

]]>
2018年,我读的书比以往任何时候都多。以下是我的一些建议和想法。

2018年我读的34本书

我读了21本小说和13本非小说类书籍。这些小说都是硬科幻小说或平民科幻小说,而非小说类书籍大多是关于心理学或金融的。

2018年最佳小说

我读的2018年最佳小说的价格是时间的孩子阿德里安·柴科夫斯基(Adrian Tchaikovsky)。这本书让我如此着迷,以至于我每天花5个小时读它,直到看完为止。

《时间的孩子》是一部精彩的科幻小说。它讲述了文明的兴衰,从进化的角度讲述了这个故事。这个故事有很多与……相同天空中的深邃我最喜欢的书之一。

这也让我想起潘多拉之星作者彼得·汉密尔顿(Peter F Hamilton),特别是《潘多拉之星》(Pandora’s Star)中的超级文明是如何从不可想象的深度发展到发动星际战争的。除此之外,这两部小说在语气和重点上都大不相同。

2018年度最佳非小说类图书

我本来打算挑正义的心灵乔纳森·海特(Jonathan Haidt)写的,然后意识到我把它包括进去,打败了自己我2017年的书籍摘要.

正当心灵被取消资格,第一名是生活的12条规则:混沌解药作者:Jordan Peterson。

这本书包含了很多关于个人成长、意义、道德和应用心理学的有用信息。虽然我是在跟谁开玩笑,但它之所以获得第一名,是因为第12条规则是“在街上遇到猫时,要宠猫”。

第二名是神人:明天的简史这本书讲述了人类的状况,我们作为一个物种所面临的挑战,最重要的是,这些挑战的轮廓会是什么样的。

虽然我真的很喜欢《十二条规则》和《人与神》,但我并不喜欢这两本书的最后几章。我读《快速思考与慢速思考》我通过以下方式认识到了忽视持续时间的趋势峰端平均值.了解自己的思维如何偏离轨道是非常有用的。

文化2.0

我读过的21部小说中有13部是同一系列的一部分,因此值得一提:政治作者:Neal Asher。它与文化Iain M Banks创作的《宇宙》。

这本小说普拉多·穆恩讲述了文化如何与好战的伊迪拉人接触的故事。由于失去平衡,该船在与撤退和延迟行动作战的同时,迅速提高了军事生产。等等…我指的是政治、普拉多和运送人工智能。不知道我是怎么把这些搞混的。

也就是说,政治小说缺乏文化小说中某些共同的可怕之处,例如绝对优越的文化船名和滑稽动作。另一方面,普拉多人比文化小说中的任何外星种族都要强大得多,耆那教的威胁也是如此。

我特别喜欢这个系列中后来(最近)的小说。推荐给喜欢在构建良好的宇宙中不断扩大规模的故事的人。

不是书

我读到的大部分内容都是以博客帖子和文章的形式出现的。此外,我还观看了许多教育视频。以下是我花费大量时间或在2018年遇到的一些资源,激发了我的兴趣。

此类统计数据

2018年,我第一次每月阅读1000多页。这样的成就!

每年读取的页数
自2012年末以来每月阅读的页数
我最喜欢最近出版的书

帖子我读书的一年首次出现于熵获胜.

]]>
0
杰伦 <![CDATA[可读函数:做一件事]]> https://www.entropywins.wtf/blog/?p=2392 2018年10月30日下午3:16:11Z 2018-10-30T13:16:11Z 我在编写易于理解的函数时使用的一些技巧和启发法不断出现…

帖子可读函数:做一件事首次出现于熵获胜.

]]>
当我看着其他人的代码时,我应用于编写易于理解的函数的几个技巧和启发不断出现。这篇文章概述了第二个关键原则。第一个原则是最小化状态。以下帖子将包含具体的提示和技巧,通常基于这两个原则。

做一件事

通常,函数的可读性会降低,因为它们正在执行多项操作。如果您的函数Foo需要执行任务A、B和C,那么为每个任务创建一个函数并从Foo调用这些任务。

功能小就可以了。只需在函数中调用3个其他函数就可以了。不要害怕“太简单”的代码或这种风格会让事情变得更难理解(事实并非如此(除非你愚蠢地把事情分割开来))。不要害怕表现。在大多数程序中,函数调用的数量实际上对性能没有影响。有一些例外,但除非您知道您正在处理其中一个,否则不要出于性能原因将这些东西混合在一起。

一级抽象

做一件事包括处理单一级别的抽象。例如,假设您有一个函数,在某些情况下,需要将消息记录到文件系统。

函数doThing(){if(条件){low_level_write_api_call(“写入模式”,$this->somePath,“某些错误消息”);}}

在这里,与函数的其余部分相比,错误消息记录方式的细节处于较低的抽象级别。这使得很难判断函数实际在做什么,因为在更高抽象级别上无关紧要的细节会扰乱高级逻辑。这些细节应该在他们自己的功能中。

函数doThing(){if(条件){$this->log(“一些错误消息”);}}专用函数日志(字符串$message){low_level_write_api_call('write-mode',$this->somePath,$message);}

另请参见

帖子可读函数:做一件事首次出现于熵获胜.

]]>
杰伦 <![CDATA[PHP类型属性]]> https://www.entropywins.wtf/blog/?p=2381网址 2019-08-20T02:35:41Z 2018-10-28T09:07:07Z 最近有很多关于PHP 7.4将带来的类型化属性的炒作。在这篇文章中…

帖子PHP类型属性首次出现于熵获胜.

]]>
最近有很多关于PHP 7.4将带来的类型化属性的炒作。在这篇文章中,我概述了为什么类型化属性并不像一些人认为的那样改变游戏规则,以及它们如何导致糟糕的代码。我首先简要介绍类型化属性是什么。

什么是类型属性

从7.3版开始,PHP支持函数参数的类型和用于函数返回值。在最近几年中,对PHP类型进行了许多添加,例如基本(标量)类型喜欢一串整数(PHP 7.0),返回类型(PHP 7.0),可为null的类型(PHP 7.1)和参数类型加宽(PHP 7.2)。介绍类型化属性(PHP 7.4)因此是一个自然过程。

类型属性的工作方式如下:

类用户{公共int$id;公共字符串$name;公共函数__construct(int$id,string$name){$this->id=$id;$this->name=$name;}}

您可以用两行简单的代码来完成PHP 7.3或更早版本中需要更多样板的操作。在这些版本中,如果您希望具有类型安全性,则需要为每个属性提供一个getter和setter。

私有$id;私有$name;公共函数getId():int{返回$this->id;}公共函数setId(int$id):void{$this->id=$id;}公共函数getName():string{返回$this->name;}公共函数setName(string$name):void{$this->id=$name;}

编写所有这些getter和setter不仅工作量大,而且如果不使用某些工具自动生成代码,也很容易出错。

这些优势就是炒作的全部内容。人们说这将避免我们编写这么多代码。我认为不是,而且我担心那些人会使用类型化属性编写代码的类型。

类型属性的适用性

让我们看看在一个典型的设计良好的OO代码库中我们拥有的一些不同类型的类。

服务是允许执行某些操作的类。记录器是服务,存储库是服务,LolcatPrinters是服务。服务通常需要协作者,协作者通过其构造函数注入并存储在私有字段中。从外面看不到这些合作者。虽然服务可能有额外的状态,但它们通常没有getter或setter。因此,类型化属性并不能让我们在创建服务时避免编写代码,而且它们提供的附加类型安全性可以忽略不计。

实体(DDD术语)封装了数据和行为。通常,它们的构造函数采用一组值,通常以值对象的形式。实体上的方法提供了通过领域语言中有意义的操作来操作这些值的方法。可能会有一些getter,尽管setter很少见。为实体中的大多数值使用getter和setter是一种反模式。同样,在大多数情况下,类型化属性并不能帮助我们编写代码。

价值对象(DDD术语)是不可变的。这意味着您可以有getter,但不能有setter。再一次,类型化属性没有真正的帮助。但真正有用的是PHP语言的一流值对象构造部分.

类型化属性只有在没有公共可变状态时才有用封装(在某些情况下,您在完成复杂的操作后会将其分配给私有字段。)如果您设计得很好,那么符合所有这些条件的代码将非常少。

走向黑暗面

通过将不变性和封装抛出窗口,您通常可以使用类型化属性来压缩代码。此标准值对象…

类名称{私有$firstName;私有$lastName;公共函数__construct(string$firstName,string$lastName){$this->firstName=$firstName;$this->lastName=$lastName;}公共函数getFirstName():string{return$this->firstName;}公共函数getLastName():string{return$this->lastName;}}

…变得更短了

类名称{公共字符串$firstName;公共字符串$lastName;公共函数__construct(string$firstName,string$lastName){$this->firstName=$firstName;$this->lastName=$lastName;}}

服务和实体也是如此:通过放弃封装和不变性,您可以不编写几行简单的代码。

如果您自己或与少数人一起开发一个小型代码库,那么这种权衡实际上可能是有意义的。如果你创建了一个扔掉的原型,然后你真的扔掉了,这也有意义。对于那些不小并且由几个人编写的代码基来说,编写几个简单的getter是为了获得封装性和不变性所提供的优势而付出的低代价。

结论

类型化属性在一定程度上有助于类型安全,在一些罕见的情况下可以帮助减少样板代码。在大多数情况下,类型化属性不会减少所需的代码量,除非您将有价值的不变性和封装属性抛出窗口。由于炒作,我希望许多初级程序员都能做到这一点。

另请参见

帖子PHP类型属性首次出现于熵获胜.

]]>
杰伦 <![CDATA[可读函数:最小化状态]]> https://www.entropywins.wtf/blog/?p=2374 2019-03-01T15:32:43 Z 2018-10-24T04:27:58Z 我在编写易于理解的函数时使用的一些技巧和启发法不断出现…

帖子可读函数:最小化状态首次出现于熵获胜.

]]>
当我查看其他人的代码时,我应用于编写易于理解的函数的几个技巧和启发不断出现。在这篇文章中,我分享了编写可读函数的两个关键原则中的第一个。后续帖子将包含第二个关键原则和具体技巧,通常以这些一般原则为基础。

是什么使函数式编程如此强大?为什么掌握了它的开发人员会说它让他们的生产力提高了这么多?功能范式提供了哪些惊人的特性或功能来实现这种提高的生产力?如果你从来没有研究过函数编程,答案可能不是你所期望的。功能范式的力量并不是来自于新的功能,而是来自于限制我们都熟悉的东西:可变状态。通过最小化或完全避免可变状态,函数式程序跳过了很大的复杂性来源,从而变得更容易理解和使用。

最小化变异性

如果你正在做面向对象编程希望您了解可变对象的缺点。类似的缺点也适用于函数范围内的可变状态,即使这些函数是程序性的程序。考虑以下PHP代码片段:

函数getThing(){var$thing=“默认”;if(someCondition()){$thing=“特殊情况”;}return$thing;}

由于状态可变,此函数不必要地复杂。变量$个东西在整个函数中处于作用域中,并进行了修改。因此,为了理解函数,您需要跟踪分配的值以及该值可能如何被修改/覆盖。通过使用所谓的保护条款:

函数getThing(){if(someCondition()){return“特殊情况”;}return'default';}

这个代码片段更容易理解,因为没有状态。状态越少,在模拟大脑中的函数时需要记住的东西就越少。尽管这些代码段中的逻辑很简单,但您已经注意到偶然复杂性由可变状态创建使得理解代码需要花费更多的时间和精力。即使不进行函数编程,也要以函数方式编写函数。

最小化范围

虽然可变状态特别有害,但非可变状态也有代价。这个函数的返回值是什么?

函数getThing(){$foo=1;$bar=2;$baz=3;$meh=$foo+$baz*2;$baz=平方($meh);打印($baz);返回$bar;}

按照以下方式重构时,判断返回值要容易得多:

函数getThing(){$foo=1;$baz=3;$meh=$foo+$baz*2;$baz=平方($meh);打印($baz);$bar=2;返回$bar;}

要理解返回值,您需要知道最后一次赋值的位置$巴发生了。在第一个代码段中,您需要毫无理由地一直扫描到函数的第一行。您可以通过最小化$巴。如果像在PHP中一样,不能将函数范围值声明为常量,这一点尤其重要。在第一个片段中,您可能会发现$bar=2在你仔细阅读下面那些无关的细节之前。如果代码是常数bar=2就像您在JavaScript中所做的那样,您不需要做出这样的努力。

结论

基于这种理解,我们得出了两条关于函数范围的指导原则,您首先不能完全避免。您应:

  • 最小化可变性
  • 最小化范围

实际上,这是两个非常通用的指令,可以应用于软件设计的许多其他领域。请记住,这些只是作为起点的指南。有时,一点状态或可变性可以帮助提高可读性。

要最小化范围,请尽可能在需要的地方创建它。你能做的最糟糕的事情是在函数的开头声明所有状态,因为这样会使作用域最大化。是的,我在找JavaScript开发人员和大学教授。如果您所在的团队或社区遵循在函数开始时声明所有变量的做法,我建议您不要遵循这种习惯,因为它的有害性质超过了“一致性”和“传统”的好处。

为了最大限度地减少可变性,每次要重写变量时都要停下来,问问自己是否无法简化代码。答案几乎总是你可以通过一些技巧,比如保护条款,其中许多我会在后续帖子中分享。我自己很少改变变量,每1000行代码中只有不到一次。因为每次删除有害的可变性都会使您的代码更容易使用,并且可以立即开始应用这种风格。如果您有幸使用函数范围中包含常量的语言,请使用它们作为默认值,而不是变量。

另请参见

多亏了加布里埃尔·伯克进行校对并提出一些建议。

帖子可读函数:最小化状态首次出现于熵获胜.

]]>