首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >访问Groovy中另一个函数中定义的变量

访问Groovy中另一个函数中定义的变量
EN

Stack Overflow用户
提问于 2018-08-14 21:00:09
回答 2查看 1.5K关注 0票数 1

我是Groovy的新手。我有一个函数,在这个函数中我正在写一个要映射的值。

代码语言:javascript
复制
def addTraceEntry(key, value) {
    def traceability = [:]
    traceability[key] = value.trim()
    println "This print happens in function addTraceEntry " + traceability
    }

我还有一个函数需要验证上面的函数是否正常工作。

代码语言:javascript
复制
def testAddTraceEntry() {
    def key = 'test_key'
    def value = 'test_value'
    addTraceEntry(key, value)
    println "This print happens in function testAddTraceEntry " + traceability
    assert value == traceability[key]
}

我使用函数名调用testAddTraceEntry()函数:

代码语言:javascript
复制
testAddTraceEntry()

当我运行这个程序时,我会得到一个错误:

代码语言:javascript
复制
This print happens in function addTraceEntry [test_key:test_value]
Caught: groovy.lang.MissingPropertyException: No such property: traceability for class: HelloWorld
groovy.lang.MissingPropertyException: No such property: traceability for class: HelloWorld
    at HelloWorld.testAddTraceEntry(HelloWorld.groovy:53)
    at HelloWorld.run(HelloWorld.groovy:57)

在函数testAddTraceEntry中,它显然不知道traceability的值,因此它似乎给出了一个错误。

我试图返回traceability的值。

代码语言:javascript
复制
  def addTraceEntry(key, value) {
        def traceability = [:]
        traceability[key] = value.trim()
        println "This print happens in function addTraceEntry " + traceability
        return traceability
    }

但这也产生了同样的错误。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-15 04:45:00

在看到您编写的代码之后,有许多事情值得一提。

首先-变量的范围和封装。让我们暂时抛开技术细节,专注于更重要的事情。在方法addTraceEntry中,可以持久化某些状态,这很好。但是,方法testAddTraceEntry的实现表明,该方法试图了解更多关于addTraceEntry实现细节的方法。它封装(换句话说,隐藏)持久性逻辑(从API的角度来看,您作为调用者,不知道它在映射中持久化键和值),这就是为什么testAddTraceEntry永远不应该假设调用该方法会改变某种结构。如果你这样做,那么:

  • 您的测试方法收缩了副作用,而不是预期的业务逻辑(将数据存储在某种全局映射中)--不要这样做。(永远)
  • 测试阻止测试方法实现的任何发展--想象一下,您决定将密钥和值存储在不同的结构中。您可以在不违反任何API约定的情况下进行测试(您的函数产生相同的结果),但是测试方法将失败,您将不得不修改它。

第二件事--您的addTraceEntry方法总是生成一个带有单个条目的映射。这没有多大意义,如果您调用您的函数4次,您将得到4个映射,其中每个映射包含一个映射到单个值的键。

至少有各种方法可以改进您的方法的实现。您可以做的最简单的事情是实现一个封装用于存储键和值的逻辑的类。考虑以下例子:

代码语言:javascript
复制
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentMap

class TraceEntriesStorage {
  private final ConcurrentMap<String, Object> entries = [:] as ConcurrentHashMap

  def addTraceEntry(String key, Object value) {
    entries.put(key, value)
  }

  def containsTraceEntry(String key) {
    return entries.containsKey(key)
  }

  def retrieveTraceEntryForKey(String key) {
    return entries.get(key)
  }
}

这是一个简单的类,有3个简短的方法。它在内部并发映射中存储跟踪条目(以解决并发访问的问题)。现在,您的测试方法如下所示:

代码语言:javascript
复制
def storage = new TraceEntriesStorage()
storage.addTraceEntry("test_key", "test_value")

assert storage.containsTraceEntry("test_key")
assert storage.retrieveTraceEntryForKey("test_key") == "test_value"

创建该类的一个实例,添加一个条目,并检查方法containsTraceEntryretrieveTraceEntryForKey是否返回预期值。正如您所看到的,在哪里存储这个跟踪条目并不重要--重要的是我们实现的类是否按照预期运行。为了使这个测试方法更好,您可以添加一个断言,在实际插入它之前检查test_key是否没有跟踪条目--这样我们就知道添加跟踪条目会改变类的内部状态。但是,这种方法的好处是,只要我们不违反合同,我们就可以试验和修改TraceEntriesStorage的实现。因为最重要的是,添加跟踪条目必须允许从对象中检索它们。它是如何被储存的,它被储存在哪里-这并不重要。

我希望您发现这个答案很有用,它将帮助您学习Groovy并设计更好的程序。黑客行动愉快!

票数 1
EN

Stack Overflow用户

发布于 2018-08-14 21:52:14

您需要将将返回语句添加到addTraceEntry()与将返回的值赋值到testAddTraceEntry()中的变量相结合。

代码语言:javascript
复制
def traceability = addTraceEntry(key, value)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51849695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档