IRepository 和相关数据?

IRepository and Related Data?

几个星期前,我刚刚接受了一次工作面试测试,问题是我几乎解决了所有问题,除了一点,在这一点上,我想这是不可能解决的。但我肯定是错的。

本题涉及相关数据。我们的服务器 API,IRepository,只会 return 一个节点及其直接子节点(例如,假设 FakeRepository 正在从数据库加载。您不能为此测试更改 FakeRepository 中的代码)。

假设 NodeManager 是客户端代码。

We want to make sure that there is only ever one instance of a specific object on the client, so that our client has a consistent view of data in our application. The test “LoadingNodeB_ShouldAlwaysReturnTheSameInstance()” demonstrates this problem. Modify the code in the NodeManager so that this test passes.

所以,我们有这个 IRepo

namespace TestRecruitment.Repository
{
    public interface IRepository
    {
        Node GetNodeAndImmediateChildren(string nodeName);
    }
}  

在一个测试项目中,我们有一个加载信息的假存储库。

using System;

using TestRecruitment.Repository;

namespace TestRecruitment.Test.Repository
{
    public class FakeRepository : IRepository
    {
        /// <summary>
        /// YOU MUST NOT CHANGE THIS METHOD
        /// </summary>
        public Node GetNodeAndImmediateChildren(string nodeName)
        {
            switch (nodeName)
            {
                case "Node A":
                    // do not modify this
                    var nodeB = new Node { Name = "Node B" };
                    var nodeC = new Node { Name = "Node C" };
                    return new Node { Name = "Node A", ImmediateChildren = new[] { nodeB, nodeC } };
                case "Node B":
                    // do not modify this
                    var nodeD = new Node { Name = "Node D" };
                    var nodeE = new Node { Name = "Node E" };
                    return new Node { Name = "Node B", ImmediateChildren = new[] { nodeD, nodeE } };
                case "Node E":
                    var nodeA = new Node { Name = "Node A" };
                    var nodeF = new Node { Name = "Node F" };
                    return new Node { Name = "Node E", ImmediateChildren = new[] { nodeA, nodeF } };
                default:
                    throw new ApplicationException("Unknown node");
            }
        }
    }
}

问题是您只能更改存储库,不能触及任何其他代码。

using System.Linq;

namespace TestRecruitment.Repository
{
    public class NodeManager
    {
        private readonly IRepository _nodeRepository;

        public NodeManager(IRepository nodeRepository)
        {
            _nodeRepository = nodeRepository;
        }

        public Node GetNodeAndImmediateChildren(string name)
        {
            return _nodeRepository.GetNodeAndImmediateChildren(name);
        }
    }
}

嗯,就是这样。

任何帮助将不胜感激,我只是想知道如何解决它。

我创建了一个 github 存储库 https://github.com/rothariger/TestRecruitment

此致!

假设节点由其名称唯一标识,确保您 return 同一实例的一种方法是在客户端保留本地缓存并每次维护 Node.ImmediateChildren 集合调用存储库:

public class NodeManager
{
    private readonly IRepository _nodeRepository;

    private readonly Dictionary<string, Node> _cachedNodes = new Dictionary<string, Node>();

    public NodeManager(IRepository nodeRepository)
    {
        _nodeRepository = nodeRepository;
    }

    public Node GetNodeAndImmediateChildren(string name)
    {
        var repositoryNode =_nodeRepository.GetNodeAndImmediateChildren(name);
        UpdateCache(repositoryNode);
        return _cachedNodes[repositoryNode.Name];
    }

    private void UpdateCache(Node repositoryNode)
    {
        AddOrUpdateChildrenCollectionInCache(repositoryNode);

        foreach (var childNode in repositoryNode.ImmediateChildren)
        {
            AddOrUpdateChildrenCollectionInCache(childNode);
        }
    }

    private void AddOrUpdateChildrenCollectionInCache(Node repoNode)
    {
        if (_cachedNodes.TryGetValue(repoNode.Name, out var cachedNode))
        {
            cachedNode.ImmediateChildren = repoNode.ImmediateChildren;
        }
        else
        {
            _cachedNodes.Add(repoNode.Name, repoNode);
        }
    }
}