So in a way I need a setter or a method that is only available to one (or a few more) classes. As far as I know this is common in some other languages as friend classes. I tried to simplify the example below. It's not the real case, and it's a bit more complicated. But I have to make sure that two properties in two different classes keep in sync. I.e. I'm using Entity Framework, and these properties are being synced to the Database.
public class UserGroup
{
List<GroupMember> _Members;
int _AcceptedMemberCount; // this is being synced to the database on save for performance reasons.
public void Join(User user)
{
var member = GetOrCreateMember( user );
member.State = MemberState.Accepted;
UpdateAcceptedMemberCount();
}
public void Ban(User user)
{
var member = GetOrCreateMember( user );
member.JoinState = MemberState.Banned;
UpdateAcceptedMemberCount();
}
private GroupMember GetOrCreateMember(User user)
{
// Creates a GroupMember from User,
// and add it to _Members if it doesn't exist.
}
private void UpdateAcceptedMemberCount()
{
_AcceptedMemberCount = _Members.Where(m => m.State == MemberState.Accepted).Count();
}
}
public class GroupMember
{
public MemberState State { get; internal set; }
}
Alternatives that I know
Using internal
disadvantage is that the property is still available to all the other classes in the same assembly. I.e. I have an assembly with my business models and entities. Making a separate assembly would complicate the code, especially when you're using Entity Framework, and need to start splitting the entities over multiple assemblies.
Adding a SetState(UserGroup userGroup) to GroupMember
... that does some extra manual checking if the UserGroup has done it's work. Like checking if the User has been added as a GroupMember to _Members. Feels really ugly, and more code to maintain that could get out of sync and break down in the future.
Using nested classes (See: https://stackoverflow.com/a/10507130/647845)
- Does not really work well with Entity Framework.
- Makes the code more verbose (always adding the parent class as a prefix when working with a GroupMember).
- GroupMember is an important standalone class in this application. Hiding it behind a parent class for just this reason feels bad.
- Has limited use, because every class can only have one hierarchy of outer classes.
Document it in the method summary, and ignore it
And just hope that everyone reads it, and never starts fiddling with the State of a GroupMember manually. The disadvantages of that are probably clear :)
Question
I can't imagine this is a really weird example, and lots of applications must have the same problems. What is the best practice here? How is this commonly solved?
Thanks in advance,