恶梦护士 asa_Java编程噩梦初学者指南

恶梦护士 asa

在日常工作中,我们处理大量问题和挑战,例如“如何保护数据?”,“这是哪种类型?”。 改为“这些概念应该是什么?” 本文并不针对特定的编程问题,例如加密的工作方式或避免SQL注入。 我将不再关注一个主题或一个噩梦,而是回到基础知识,尝试找出我们恐怖的根源。

您将发现更多关于我刚开始编写代码时遇到的编程恐惧的信息。 本文的目的是帮助开发人员改善他们的工作流程,并为他们的一些持续存在的问题找到解决方案。 以下示例适用于Java; 但是,请随时将其应用于您最关心的语言。

返回null作为基本值

根据我在定制软件开发公司的工作经验,对如何处理我们程序的基本方案进行了激烈的讨论。 在这种基本情况下,我们定义了在没有合适结果时函数需要返回的值。 在下一个代码段中,我们必须返回名称包含字符串“ sup”的工作程序,但是当没有名称满足此条件时会发生什么? 一种方法是作为结果返回null,但这隐藏了一些风险。 最大的问题之一是,在您执行其他任务之后从事分配任务的人员可能忽略了这一事实,并尝试以不同的方式使用您的结果,这将导致NullPointerException(清单1)。

List workers = manufactory.getWorkersByCondition(); // returning null
for (Person worker : workers) { // NullPointerException occurs
  // some logic
}

为防止这种情况,您可以返回空的List或任何集合。 此外,您的同事会很高兴,因为他们将能够使用此列表而不会触发异常。

当然,在某些公司中,以空值作为基本值返回是标准的。 如果您的情况是这样,请继续进行下一部分。

检查空值

情况就是这样-您调用了服务或项目的其他部分,并期望它返回特定类型的结果。 将此结果保存在局部变量中,然后使用它。 在检查此变量是否确实有结果之前使用此变量可能会导致类似NullPointerException的问题或逻辑故障。 为避免此类问题,建议检查结果是否为null和/或为空(清单2)。

List shoppingCart = session.getShoppingCart();
if (shoppingCart != null) { // you can add && !shoppingCart.isEmpty()
  // operate over cart
} else {
  // if needed specific operations
}

没有记录您的代码

我们大多数人都讨厌文档或在日常工作中讨厌它,但是在编程中,它可以挽救生命。 我一点也不夸张 我确定您一直处在需要使用某种方法或类但不知道它做什么以及如何使用它的情况下。 在最佳情况下,代码编写得如此出色以至于可以自我解释。 但是,这种情况很少发生。

有不同类型的文档和不同的工具,例如SwaggerDoxygen对于Spring Boot项目文档,可能会有帮助。 以下是一些示例,其中一行注释可以帮助您和开发人员在编写代码后:

  • 当您长时间在项目上工作并返回到旧功能时,几行注释可以指导您为何以及如何配置某些内容。
  • 当您长时间在项目上工作并返回到旧功能时,几行注释可以指导您为何以及如何配置某些内容。
  • 当第三方使用您的API或某种方法时,他们可以确定是否确实需要此功能以及它如何与您的文档一起使用。

关于何时以及如何撰写评论的最佳实践不同,但以我个人的观点,最重要的是:

  • 当您的代码中出现异常情况时,例如“ if”而不是“ else”或复杂的逻辑,您可以注释一下为什么以这种方式进行操作。
  • 当您的代码中出现异常情况时,例如“ if”而不是“ else”或复杂的逻辑,您可以注释一下为什么以这种方式进行操作。
  • 创建某些特定的工具或服务时,可以使用某些文档工具或针对您的语言的文档标准来简要描述重要部分和任何复杂的特性。

下次当您花费数小时进行编码时,请问自己:“我忘了什么吗?”

异常处理

通常,忽略异常处理很诱人,但这将是一个巨大的威胁。 首先,您永远不知道异常可能发生在哪里。 其次,您刚刚破坏了项目结构。 对于初学者和经验丰富的开发人员而言,最佳实践是处理异常,知道何时抛出并捕获它们。

还请参见: 前5种Java测试工具

隐藏异常是处理它们的另一种方式,这可能是一场噩梦。 从个人经验来看,您可能会浪费大量的调试时间,而仅仅是发现某个东西捕获了一个异常,却什么也没有做(清单3)。

try {
  client = clientFactory.getClientBy(username, password, serverURI);
} catch (CustomException ex) {
  logger.error(ex.getMessage(), ex); // this line can save us from painful debugging
}

异常是故意抛出的,因此您需要照顾好它们。 如果需要,您应该将它们扔回去,记录信息,或制定安全的逻辑进行处理。 确保解决引起特殊异常的问题。 如果您不故意处理它,请写一个注释并记录下来,以便其他开发人员了解最新的代码。

尝试自己做所有事情

如果您使用Java,则会知道开发人员可以使用大量的库。 当您遇到问题或正在考虑如何实现特定功能时,重要的是研究适用于您的案例的可用库。 其他开发人员花了数年时间完善这些库。 而且,它们是免费的! 例如,如果您需要日志记录工具,请使用Log4j ; 如果您需要网络库, Netty可能是一个不错的选择。 这些开源库中的一些已成为其领域的标准。

下次当您需要进行一些XML解析或日志信息时,重要的是要问“我是第一个需要这样做的人,还是已经有人实施了解​​决方案?”

释放资源

这尤其针对业务中的新手。 当您打开网络连接或与文件的连接时,完成我们的工作后将其关闭很重要。 否则,我们将阻塞可用于其他用途的资源。

这是开发人员内存不足的示例:在对这些资源进行操作期间抛出异常时。 是的,像FileInputStream之类的实现(如前面提到的文件)具有终结器,该终结器调用close()并释放资源。 但是,这将在垃圾回收周期中调用(并且我们无法预测何时会发生这种情况)。 Java 7 try-with-resources中引入了一些漂亮的技巧(清单4)。

try (Scanner scanner = new Scanner(new File("./description.txt"))) {
  while (scanner.hasNext()) {
    System.out.println(scanner.nextLine());
  }
  // ..more logic
} catch (FileNotFoundException ex) {
  // some safe logic
} catch (CustomException ex) {
  // another safe logic
}

这将处理任何已实现AutoClosure接口的对象,并关闭我们使用的资源,而无需显式调用close()。

内存管理

接下来,我们将简要介绍一下内存泄漏和昂贵的分配。 Java的自动内存管理使开发人员大为欣慰,因为他们不再需要手动释放内存。 但是,了解应用程序内部发生的情况并了解内存的实际使用方式也很重要。 只要我们的程序创建对不需要对象的引用,它就不会被删除; 可能被标记为内存泄漏。

您知道什么是昂贵的分配或垃圾分配吗? 简而言之,就是程序创建连续的短暂活动对象的时候。 这种方法很危险,因为它会导致应用程序性能下降,不断创建和删除不需要的对象。 在下一个代码片段中,我们可以在清单5中看到一个简单的示例。

String answerToEverything = "";
for (int index = 0; index < 100000; ++index) {
   answerToEverything = answerToEverything + "!42!";
}

字符串在这里是不可变的。 因此,要修复此Java代码段,我们将使用StringBuilder每次迭代创建一个新实例(清单6)。

StringBuilder answerOfEverything = new StringBuilder();
for (int index = 0; index < 100000; ++index) {
  answerOfEverything.append("!42!");
}
System.out.print("Answer of everything and beyond " + answerOfEverything.toString());

并发修改

迟早,您将面临ConcuretModificationException并开始搜索杀手er。 当您尝试在不使用迭代器对象的工具的情况下迭代集合时,会发生这种情况(清单7)。

List operationSystems = new ArrayList<>(Arrays.asList("Fedora", "Arch", "Debian", "Manjaro"));

for (String system : operationSystems) {
  if (system.contains("ar")) {
    operationSystems.remove(system);
  }
}

这可能发生在单线程应用程序中,现在假设有一个多线程应用程序。 一个线程正在迭代并使用值查看列表,而另一个线程正在从列表中删除元素。 这可能非常棘手,在使用它时我们需要小心。 为此,我们有诸如同步锁和为并发指定集合的​​实现之类的东西。

重要的是要记住,实际编码之前的阶段同样重要。 如果做错了,您可能会面临一些现实的噩梦。 我将在下面分享我的一些经验和解决方案。

不规划您的解决方案

刚开始编程工作时,我面临的最大噩梦是当我从客户那里收到规范后立即开始实施。 这导致了六个星期的巨大努力,才意识到我正在开发客户从未需要的东西。

还请参见: 21世纪的Java:您是否考虑得足够远?

我的建议是花些时间坐下来,充分了解客户或您的PM / PO的要求。 提出尽可能多的问题,以消除所有不确定性。 与项目的业务目标保持一致。 您应该将解决方案视为更大范围的一部分,以便找到正确的问题。 尝试只编写有用的代码而不会浪费任何时间。 这应该保证积极的反馈。

不遵循代码标准

我陷入的另一个噩梦是没有考虑同事就没有遵循公司标准和编码。 这导致了巨大的误解,并在项目内部产生了很大的压力。 为了避免在这种情况下混淆,我强烈建议您阅读公司的最佳开发实践,并确保您的代码符合要求。

当客户,经理和其他开发人员检查您的代码时,这将有所帮助。 它实际上可能会帮助您获得更多知识并提高您的编程技能。 另外,遵循将要使用的编程语言的编码约定非常重要。

不测试您的代码

我设法吸引自己的另一件事是,在低估了测试之后,花了整个sprint修复了上一个发行版中的错误。 无论您实际上要创建多少行代码,您都绝对必须测试它们如何与项目的其他部分集成。 可以通过对测试样式进行简单的研究,然后选择最适合您的方式来轻松地做到这一点。 您可以使用单元测试,系统测试,集成或任何其他测试样式。

总而言之

错误和技术误解是我们创造的美丽谜团。 我们掌握自己的命运; 究竟是困扰着无休止的发展地狱,还是困扰着福尔摩斯,我们走出这些技术噩梦的方式取决于我们对自己的编码过程的了解程度。

翻译自: https://jaxenter.com/java-programming-nightmares-156749.html

恶梦护士 asa

    原文作者:diluan6799
    原文地址: https://blog.csdn.net/diluan6799/article/details/107254729
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞