如何在团队成员之间传播对通用编程的认识?


20

我住在一个人们相信的环境中:

  1. Java泛型是专门用于库编写而不是实际编码的功能。
  2. C ++是一种OO编程语言;template是可选的和可避免的功能

但是,这些人高度依赖使用通用编程编写的库(例如STL,Java容器)。如果我使用templates或编写代码generics,则代码审阅者很可能会拒绝它,并会以“正确/可理解/优雅”的方式发表评论以编写代码。

这种心态适用于普通程序员到高级经理。没有出路,因为90%的时间里,这些人都有自己的游说手段。

解释它们的最佳方法是什么(不被割断),同时编写构成OO和通用编程的代码的实用方法是什么?


11
祝你好运,但你可能将不得不离开,如果你希望你的方式..
松饼人

3
@TheMuffinMan,你是对的。我离开了那个工作场所,现在有了自己的公司。在这里,我可以完全控制编码!
iammilind

Answers:


14

世界上仍有一些人在“普通编码”中使用jave泛型。我可以相信C ++模板,但是泛型?他们甚至都不难学习/使用。认真地说,Java和C ++的最佳功能分别是泛型和模板。

说服人们做事的最好方法是提出令人信服的论点,保持不威胁和正确。

只要您不做诸如使用模板作为编程语言之类的事情,参数多态性(泛型/模板)几乎肯定是好的。

1.避免代码重复。

这是显而易见的,但是多态代码是通用代码。这就是为什么它被称为泛型。

2.支持更好的静态检查。

没有参数多态性,您最终会写出类似public Object clone()public boolean equals(object b)不仅仅是可憎的东西,它们的类型不提供有关其操作的信息,并且最终会在整个地方抛出异常。参数多态性的替代方法是在各处投射

3.非参数多态性OOP代码基本上无法正确处理“二进制方法”。

您经常使用这些。

4.最佳做法

在Java中,使用泛型被认为是最佳实践(请参阅Josh Bloch的Effective Java)。诸如Sutter和Alexandrescu之类的C ++主要思想家也鼓励使用模板来解决各种问题。

5.它符合OO范式。

人们通常不会注意到这一点,但是子类型和泛型的结合产生了一个系统,它比仅包含一个系统的任何系统都更强大的表现力和面向对象。

考虑Scala的mixin。这是一个很好的功能,可让您将组件中的对象拉在一起。泛型和模板可以模拟其中一些好处。例如,假设您的一个对象使用数据库。好的设计可以使您将数据库访问权限抽象到一个单独的类中。如果操作正确,这不仅使您可以模拟数据存储(可测试性的关键),还意味着您可以添加替代实现,例如新的no-sql数据库。但是,在这里您可能会遇到问题,无论您使用哪种实现方式,都将获得业务对象的不同功能。

泛型抢救!

   public class Business<S extends Datastore>{
      private S store; ...
   }

现在,您可以Business根据使用数据库特定功能的能力开始静态区分对象。您仍然需要一些运行时检查和强制转换,但是您可以开始构建更好的代码。

6.普通代码不存在。

编程领域中只有三件事:

  1. 图书馆
  2. 配置,以及
  3. 错误的代码。

如果您不像代码库那样考虑您的代码,那么当您的项目要求发生变化时,您将面临严重的麻烦。架构(可以说)是设计好的API的艺术。

我觉得这种态度令人震惊。在习惯使用参数化类型进行编程之后,不使用它们只会使一切变得很痛苦。而且,Java和C ++有很多粗糙的地方,它们可以帮助补救。


7
我喜欢这个概念normal code不存在,只存在三种:librariesconfigurationsbad code。这是一个理想主义者的推理,尽管您可能仍要向您的同事解释,尽管他们可能不如您理想。我确实同意,但是一旦掌握了参数,使用参数化类型就很棒了。
Spoike 2011年

3
哎呀,即使您不将C ++模板用于模板元编程目的,它们也不难使用。:-)
In silico 2011年

-1表示建议所有决定不使用泛型的人都是因为不知道该功能的工作原理而这样做。
tp1

考虑到潜在的滥用可能性,我想说限制/不使用泛型/模板可能是一个更好的决定,值得您信赖。
Ryathal

拒绝将泛型/模板用于大规模软件工程的人们会意外地并且不可避免地会构建“第二语言”,即一种在Java上运行的解释器,它可以实现他们所想的任何“业务语言”。en.wikipedia.org/wiki/Inner-platform_effect
rwong 2014年

16

这是更笼统的问题的一种特殊形式:“您如何说服上司开始使用更新更好的技术/制造方式?”

不幸的是,我认为您不能做到,而且我不确定您应该这样做。根据定义,这是他们的选择,因为他们会按照您选择的某种方式(而不是以您喜欢的任何方式)付钱给您。您能做的最好的事情就是建议使用这项技术,很多人正在使用它,并且这似乎是未来的方式。您甚至可能想提一提他们当然应该已经知道的事实:对于人们来说,最好不要让他们的技能停滞不前。就是这样:如果他们不购买,您将无能为力。

他们可能还有其他您没有的考虑因素,因为您没有在他们的层面上进行思考。您以工程师的身份思考,他们可能在业务方面甚至在人力资源方面都在思考。

  • 仿制药(或其他药物)会提高其产品的价值吗?可能不会。

  • 仿制药(或其他药物)是否会使已经雇用他们从事工作的人们变得更加困难?是。

  • 仿制药会缩短上市时间吗?如果唯一的工程师是您,也许是。但是,如果需要在编写另一行代码之前就对一大堆工程师进行泛型知识的教育,则不会。

因此,您可能只考虑换工作。在我的上一份工作中,我是第一个在Java中使用泛型的人,幸运的是,它们对此没有问题。他们担心泛型会使代码“更难阅读”,但它们让我随心所欲。找到这样的工作。


9

在进行任何审查之前,我会先将泛型的优点传播给代码审查者和其他同事:

1)通过允许您指定泛型类或方法所作用的类型,泛型功能将类型安全的负担从您转移到了编译器。无需编写代码来测试正确的数据类型,因为它是在编译时强制执行的。减少了类型转换的需要和运行时错误的可能性。

2)泛型提供了类型安全性,而没有多个实现的开销。

因此,[1]和[2]降低了代码出错的风险。这样可以节省开发人员时间,从而节省公司资金。

如果可读性成为问题,那么使用通用类型的尴尬可能会受到影响。这是您可能要扩展编码准则的原因之一。这可以在工作日的上下文中完成,而不仅仅是扩展库(但是,这是一种随身重构的想法,并在代码中标记了库的可能候选方法,以便以后轻松识别)。因此,没有理由不在工作环境中使用它们。

我将添加一些关于其他程序员在泛型方面没有问题的声明:泛型在Java和C#等许多其他语言中得到了广泛使用。没有这种类型的安全构建块,任何认真的程序员都会发现生活困难。

但是,您可能要考虑一些开发人员可能还不适应。管理层过去可以做出有意识的决定来保护项目,从而将这些小问题排除在危险区域之外。在这里,无罪和有罪通常都会受到指责,因为很少进行足够的分析或微观管理。

如果您提出了很好的理由,但没有得到合理的回应,那么您就会秘密地寻找另一家重视编程的公司。


7

除非您是架构师/技术负责人,否则很难要求您使用泛型/模板。您确实应该在代码审查之前就提出通用/模板解决方案,最好是在开始实施之前。

您可以做的是演示为什么在某些情况下应使用泛型。如果您能证明其好处,那么您的同事可能会同意。您应该使用泛型/模板的可能原因如下:

  • 它应该让您减少重复性任务的代码
  • 它使程序员的工作更轻松
  • 它实施解决方案架构师设置的模式
  • 它封装了通用功能,这将迫使程序员不要复制粘贴代码(即避免双重维护问题)。
  • 将来可以合理地证明您的代码(尽管很难以此为依据)

在一个最近的Java项目中,我成功添加了一些通用抽象类,因为它满足了一些基本的条件:它使团队中的其他人更轻松,执行了架构师已经提出的模式,并拥有了一些程序员不需要的通用代码。复制和粘贴。架构师写的这是一个简单的模式,即有能力的人仍然犯错(由于实际系统的复杂性),但是泛型标记了哪个类去哪里。

显然,在不违反保密协议的情况下,我无法展示真正的例子。但是,作为我所做的一个例子,是要制定策略模式并使用泛型强制执行。因此,这是策略模式:

在此处输入图片说明

为了使程序员能够实施此模式,您可以添加泛型类型Context,使其应使用具有Strategy类型的内容。从代码角度来看,在Java中看起来像这样:

// declare the generic Context class that has a type "S" 
// that is an upper bound class of Strategy
public class Context <S extends Strategy> {
    S strategy;

    // Constructor with an initial strategy
    public Context(S initialStrategy) {
        this.strategy = initialStrategy;
    }

    public void doSomething() {
      strategy.execute(); // assumes that Strategy has an execute() method.
    }

    public void setStrategy(S strategy) {
        this.strategy = strategy;
    }
}

据我所知,您几乎可以使用任何模式进行此操作。为了对代码设计有信心,请确保可以使用单元测试来测试通用/模板设计,以确保其有效。

如果您的同事不喜欢这个主意,那么请不要将其个人化,这可能不是您认为容易的解决方案。这就是为什么您应该在开始实施之前提出通用/模板解决方案的原因。您仍然必须与同事一起以不同的方式解决实际问题。


爱图!您使用了哪个工具?
yannis 2011年

@YannisRizos我使用yuml.me从文本输入创建图表。不过,目前Beta版服务尚有漏洞(您可以使用生成的链接将生成的图片上传到帖子中)。
Spoike 2011年

加入了书签,谢谢分享。尽管我真的不想再学习另一种语法,但是它很简单,它看起来很酷,我会在某个时候尝试一下。
yannis 2011年

@YannisRizos哦,我经常忘记自己的语法。这就是为什么有一个方便的示例页面的原因。我发现用yuml编写简单的类图比使用Visio更快。
Spoike 2011年

@YannisRizos yUml是一个很酷的工具。这是您可以使用它的其他一些示例:carnotaurus.philipcarney.com/tagged/yUML
CarneyCode 2011年

4

总是有几种方法可以做相同的事情。如果您对模板的使用是对模板的滥用,那么它将使代码审查失败。

但是,如果您的代码由于无法理解模板而无法通过审核,则问题可能是不同的。在这种情况下,建议他们(以一种很好的方式)学习模板。


4

您在这里处理的是一些偏见。人们更喜欢现状,已经发展了集体思维,并且进行了几次争论,以使人们更加坚定自己的信念。

这里最有效的策略之一是专注于微小的胜利。我读了一本书中的以下示例:作者是一位坚定的非Apple用户。她不喜欢他们,她不希望与他们有任何关系。她与支持苹果立场的人进行了多次讨论,每一次讨论都将她的脚跟推得更深一些。然后有人给她买了一个iPod shuffle,那样,她的偏见消失了。这并不意味着她只想购买苹果产品,但坚强而根深蒂固的反苹果立场已被更加平衡的观点所取代。有妥协的余地,她最终慢慢地完全转向了苹果。

因此,不要试图一次说服所有人:这将产生相反的效果。专注于一件小事情,其余的事情将自己发生。只是摆脱争论的两面性,使人们可以一点一点地跨越,而不是一次全部跨越。

需要重点关注的具体点取决于您的情况,但这是一个主意:在库和“真实代码”之间进行草图划分似乎很不自然。在我看来,编写应用程序的程序员应将80%的时间花在自己正在编写的应用程序类型的库上,而20%的时间则用该库来构建应用程序。所有值得保留的代码都应视为一个库。我建议您的上司将您的某些代码概括到内部库中(如果还没有的话)。按照他们自己的逻辑,他们应该为此使用泛型,并且根据以上估算,您的代码中有80%可以最终存储在库中。一旦让每个人都从另一侧使用泛型,他们应该习惯了,偏见也将消失。


谢谢彼得,这是一个非常有见地的答案。您的想法不仅适用于我的问题,也适用于我们日常生活的一般哲学。
iammilind

2

注意“可理解”。如果代码检查者没有看到泛型的好处,那么所有<<<>>>-stuff都是无法理解的噪音,这是不必要的。

我建议您查看一下您的错误数据库包含的实际上,当前的错误(已打开或近期已修复)的数量,这些错误可以通过使用泛型来避免。查找ClassCastExceptions。

还要注意,如果您没有使用泛型可以避免的错误,那么您的同事会指出您不需要它们。


2

我会很容易做到这一点。几年前,我从Java 1.4迁移到1.6,而泛型确实引起了轰动。如果您尝试处理一些Collections,Maps和其他结构,那么它非常简单且非常有用。但是,编写将通用数据作为参数,对其进行处理并将其快速传递给其他类的类,将造成极大的混乱。使这一切都变得使我感到非常满意,但我想知道是否值得花费额外的时间和精力。我还担心很多Java程序员可能永远无法真正掌握它。

到目前为止,我的一般旅行中还有一些随机的想法:

  • ClassCastExceptions在运行时发生,但它们通常出现在前几次运行中,并且易于修复。
  • 我阅读过的有关泛型的每篇文章都指出,有时它们只是不起作用,您需要@SuppressWarnings(value="unchecked")偶尔使用。您如何知道自己是否超出了泛型的范围,还是只是愚蠢而需要加倍思考?
  • @SuppressWarnings(value="unchecked")仅适用于一条线可能很难。
  • 我向我的一门课添加了一些奇特的泛型。我认识几个程序员,他们可以在我对该类进行泛化之前对其进行增强,而这些人永远都不会碰过它,之后再进行干净的编译。

泛型已经清理了我的代码,并警告我太多麻烦,以至于我拒绝它,但是我也看到增加了开发时间,花了更多的时间在培训上,并且Java程序员被迫放弃使用C#,C和Visual Basic。 ..或Java 1.4。我专注于编写您的同事可以理解的代码。如果您可以使用一些可以理解的泛型,那就太好了。我将Java泛型视为尚未发现的机会/问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.