Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Refactor or extend Atoms by a new Map interface #562

Open
Meerownymous opened this issue Oct 28, 2023 · 1 comment
Open

Proposal: Refactor or extend Atoms by a new Map interface #562

Meerownymous opened this issue Oct 28, 2023 · 1 comment
Labels

Comments

@Meerownymous
Copy link
Collaborator

Meerownymous commented Oct 28, 2023

Some weeks ago, we had a discussion about Stack overflow issues with the decorator pattern, when nesting too many objects.

The origin was Map.Joined object. See this line.
It is not necessary to nest many objects here of course. However, the decorating is a desired practice and should normally work fine.

I found another issue with the nesting, regarding efficiency. The Stack overflow shoed that these operations are too costly in their current implementation.

I came across the MapInputEnvelope and it makes use of the Joined object. With the current implementation, every Joined object will copy the whole map. In some libraries, MapInputs are used a lot and this does slow the objects down.

The fix that I would suggest is to replace or cointroduce an own map interface.

    public interface IMap<Key, Value>
    {
        Value this[Key key] { get; }
        Func<Value> Lazy(Key key);
        ICollection<Key> Keys();
        IEnumerable<IPair<Key, Value>> Pairs();

        //Decorating method
        IMap<Key, Value> With(IPair<Key, Value> pair);
    }

Since the Atoms objects are all readonly, the IDictionary interface is overloaded with a lot of unusable methods anyway.
This simpler interface offers a decorating method "With". Depending on the implementation, this can be used to extend an existing internal Dictionary instead of building new ones. It is still decorator pattern and does not allow direact manipulation, leaves the responsibility to the object itself which follows all principles.

I did a comparison test in an experimental fork of Atoms.

Performance measurements showed that while adding 100-200 MapInputs is the maximum until crashing the Stack, the new object has no upper bound. While the 100 inputs took about 40ms, It took only 1ms to do it with the new object. It rose to 3.5ms when adding 5000 objects, a significant change.

The map object has another advantage as it does not allow enumerating all values, only pairs - so the current security checks of LazyMap can be omited.

@Meerownymous
Copy link
Collaborator Author

Meerownymous commented Nov 8, 2023

In the meantime, I have released a working nuget of the fork.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant