-
Notifications
You must be signed in to change notification settings - Fork 11
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
Chore: Streamline the architecture of Connective Rooms #647
base: main
Are you sure you want to change the base?
Conversation
* Remove the over-usage of Decorator * Separate interfaces according to the layers of abstraction * Get rid of the bottom-less proxying of InteriorRoom * Adjust un-adapted asynchronous calls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left the comments
UPD: also for some reason the RealmRoom won't start for me at all, did you test your changes?
https://drive.google.com/file/d/1RZpTEF37u6rJTVSWMpG0f8cfz3-oxMyS/view?usp=sharing
Explorer/Assets/DCL/Multiplayer/Connections/Archipelago/Rooms/IRealmRoomStrategy.cs
Outdated
Show resolved
Hide resolved
/// This interface is not connected to <see cref="IConnectiveRoom"/>. | ||
/// It has some common fields but its contract can mutate independently | ||
/// </summary> | ||
public interface IRoomProvider |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the point of IRoomProvider? It doesn't jst "Provide" or it's not being a just source of IRoom, it acts as an object that handles the lifecycle of the room
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has one single purpose: Constructs either a fixed connective room or a dynamic one based on the archipelago.
Regarding the name can you propose a better one? It's not necessary to go by book, anything that would feat its purpose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think IConnectiveRoom suits great, if you are afraid of exposing other implementations we can rename internal one ICoreConnectiveRoom
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The thing is it's not the Room
itself, it's an upper layer that provides one of the rooms according to the inner conditions.
Well, in fact it can be a connective
room in a similar meaning as the factory can be abstract
. But why the core then should be connective?
private FixedConnectionRoomStrategy CreateFixedConnectionRoomStrategy(string adapterUrl) => | ||
new (sharedRoom, webRequestController, adapterUrl); | ||
|
||
private ArchipelagoIslandRoomStrategy CreateArchipelagoIslandRoomStrategy(string adapterUrl) => | ||
new (sharedRoom, identityCache, archipelagoSignFlow, characterObject, adapterUrl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sharing an InteriorRoom can bring possibilities of mutating from different places that can be hard to debug
Why don't isolate it per each instanse?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- According to our application it's not needed to be isolated in every instance
- Having it per instance created the problem with multi-leveled proxies when inside proxy there is another proxy, and so on and so forth: I described it in the PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that can be hard to debug
Not sure if it is hard to debug: the source of InteriorRoom
is streamlined and on purpose I no longer expose InteriorRoom
from the core
private FixedConnectionRoomStrategy CreateFixedConnectionRoomStrategy(string adapterUrl) => | ||
new (sharedRoom, webRequestController, adapterUrl); | ||
|
||
private ArchipelagoIslandRoomStrategy CreateArchipelagoIslandRoomStrategy(string adapterUrl) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember points from you about that this object is factory, why it has hardcoded dependencies and acts as Factory, but named as strategy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, Factory
should not contain a reference to the produced object. But I agree. Possibly it should be a factory, and then it should capture a URL
argument to produce the object. I will change it to see if it is better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to create a factory by book from it but it would require capturing variables (IConnectiveRoom
) and I don't see any sense of doing it when we can keep them in the class.
I don't want to introduce any other layers just because it does not fit the name of Factory
or Strategy
. If you know a commonly accepted name for a type that constructs an entity and holds a reference to it, I am all ears.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can create a IRealmRoomFactory, and inject it inside the object
I don't think merging 2 concerns Factory/Strategy into a single object is a good Idea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I aim for simplicity: I don't see the reason for 2 layers here. It's simply not needed
Explorer/Assets/DCL/Multiplayer/Connections/RoomHubs/RoomHub.cs
Outdated
Show resolved
Hide resolved
Explorer/Assets/DCL/Multiplayer/Connections/Rooms/Connective/IConnectiveRoom.cs
Show resolved
Hide resolved
@@ -1,4 +1,4 @@ | |||
using Cysharp.Threading.Tasks; | |||
/*using Cysharp.Threading.Tasks; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you just commented it, what is it replaced on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed: I described it in the PR: its logic is already contained in InteriorRoom
: no sense of making a proxy over proxy again
/// <summary> | ||
/// No need for any abstractions - it's a unique behaviour that we can't replace | ||
/// </summary> | ||
internal class FixedConnectionRoomStrategy : IRealmRoomStrategy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Define please the "abstractions", something you are naming it and claiming it's bad to have many of it and something not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super simple interface:
- One level - no nesting
- One member
IConnectiveRoom ConnectiveRoom { get; }
, two implementations - Clear purpose: to allow select polymorphic behavior between
Fixed
andArchipelago
realms
The goal of this PR
ConnectiveRoom
and related structuresProblems
№1. Cyclic dependencies on the same interface in
Decorators
Container
onlyBefore:
№2. Over-usage of abstraction, forceful contracts merrying
YAGNI
considerablyDecorators
use. Difficulty to say where is the core and where is not. Pretending the core can be replaced with a higher level entity.Before:
After:
Before:
After:
№3. Hiding different layers of abstraction behind the same contract
The top most-layer:
Before:
After:
Clarification of the core usage
№4. Proxies over-usage
Before:
InteriorRoom
already provides re-assigning functionality butRenewableDecorator
is built to provide this functionality againAfter:
Core
is fully under control of the higher levels.InteriorRoom
is created once on the top-most layer and propagated as an argumentDecorator
: it has gone completelySummary
RenewableArchipelagoIslandRoom
Decorator has gone as it was fully redundant as duplicated the functionality ofInteriorRoom
Archipelago
andGatekeep
were moved to their own layer that stands above the core: with their own contracts as they do not match 100% with the coreCore
is under its own exclusive contract but the interface is not really used because the core was not used in an abstract manner, and no test coverage was provided either.Extra
I introduced a separate multiplayer container to juggle with dependendencies there