Skip to main content

I'm sorry if the phrasing of the question is a bit unclear but let me try to clarify below. (If anyone can word it better, feel free to edit)

I have a Map instance variable, groups, which is defined as follows with the given type parameters:

Map<Group, Map<Username, GroupMember>> groups

Within the same enclosing class, I have a public method, addGroup(Group group), which is supposed to put a new entry into the groups map. The Group object contains all the relevant information for the entry.

The conundrum here stems from the fact that adding a new element to groups would require that I specify a concrete object for Map<Username, GroupMember> value within addGroup(), thus internally coupling the abstraction with an implementation--clearly in violation of the dependency inversion principle.

My question is then how do I avert this problem? I hesitate delegating the responsibility of defining the object to the caller (i.e. defining the method as addGroup(Group group, Map<Username, GroupMember> groupMembers) for instance) as it chips away at abstraction, may be inconsistent with the constructor injected implementation; and in my opinion, introduces unnecessary coupling with the class implementation details. Perhaps I should reconsider my design. Would appreciate your feedback.


EDIT

Here's where the problem is coming from:

public class Foo {

    private final Map<Group, Map<Username, GroupMember>> groups;

    //...

    public void addGroup(Group group) {
            if (exists(group))
                throw new IllegalOperationException("Group with same name already exists");
            //Declaring a new HashMap within the class (i.e. defining the implementation within a class member)
            groups.put(group, new HashMap<Username, GroupMember>(Map evaluation based on group object)));
    }

    //...
}

Here's what I'm hesitant of doing:

//Passing Map<Username, GroupMember> object decreases abstraction and exposes implementation details
public void addGroup(Group group, Map<Username, GroupMember> groupMembers) {
        if (exists(group))
            throw new IllegalOperationException("Group with same name already exists");
        groups.put(group, groupMembers));
}

Here's part of the definition for Group to further add context;

public class Group {

    private final String name;
    private final String description;
    private final Instant dateCreated;
    private final Collection<GroupMember> members;

    //... Constructor and getters for the fields
}

I'm sorry if the phrasing of the question is a bit unclear but let me try to clarify below. (If anyone can word it better, feel free to edit)

I have a Map instance variable, groups, which is defined as follows with the given type parameters:

Map<Group, Map<Username, GroupMember>> groups

Within the same enclosing class, I have a public method, addGroup(Group group), which is supposed to put a new entry into the groups map. The Group object contains all the relevant information for the entry.

The conundrum here stems from the fact that adding a new element to groups would require that I specify a concrete object for Map<Username, GroupMember> value within addGroup(), thus internally coupling the abstraction with an implementation--clearly in violation of the dependency inversion principle.

My question is then how do I avert this problem? I hesitate delegating the responsibility of defining the object to the caller (i.e. defining the method as addGroup(Group group, Map<Username, GroupMember> groupMembers) for instance) as it chips away at abstraction, may be inconsistent with the constructor injected implementation; and in my opinion, introduces unnecessary coupling with the class implementation details. Perhaps I should reconsider my design. Would appreciate your feedback.


EDIT

Here's where the problem is coming from:

public class Foo {

    private final Map<Group, Map<Username, GroupMember>> groups;

    //...

    public void addGroup(Group group) {
            if (exists(group))
                throw new IllegalOperationException("Group with same name already exists");
            //Declaring a new HashMap within the class (i.e. defining the implementation within a class member)
            groups.put(group, new HashMap<Username, GroupMember>(Map evaluation based on group object)));
    }

    //...
}

Here's what I'm hesitant of doing:

//Passing Map<Username, GroupMember> object decreases abstraction and exposes implementation details
public void addGroup(Group group, Map<Username, GroupMember> groupMembers) {
        if (exists(group))
            throw new IllegalOperationException("Group with same name already exists");
        groups.put(group, groupMembers));
}

Here's part of the definition for Group to further add context;

public class Group {

    private final String name;
    private final String description;
    private final Instant dateCreated;
    private final Collection<GroupMember> members;

    //... Constructor and getters for the fields
}

I'm sorry if the phrasing of the question is a bit unclear but let me try to clarify below. (If anyone can word it better, feel free to edit)

I have a Map instance variable, groups, which is defined as follows with the given type parameters:

Map<Group, Map<Username, GroupMember>> groups

Within the same enclosing class, I have a public method, addGroup(Group group), which is supposed to put a new entry into the groups map. The Group object contains all the relevant information for the entry.

The conundrum here stems from the fact that adding a new element to groups would require that I specify a concrete object for Map<Username, GroupMember> value within addGroup(), thus internally coupling the abstraction with an implementation--clearly in violation of the dependency inversion principle.

My question is then how do I avert this problem? I hesitate delegating the responsibility of defining the object to the caller (i.e. defining the method as addGroup(Group group, Map<Username, GroupMember> groupMembers) for instance) as it chips away at abstraction, may be inconsistent with the constructor injected implementation; and in my opinion, introduces unnecessary coupling with the class implementation details. Perhaps I should reconsider my design.


EDIT

Here's where the problem is coming from:

public class Foo {

    private final Map<Group, Map<Username, GroupMember>> groups;

    //...

    public void addGroup(Group group) {
            if (exists(group))
                throw new IllegalOperationException("Group with same name already exists");
            //Declaring a new HashMap within the class (i.e. defining the implementation within a class member)
            groups.put(group, new HashMap<Username, GroupMember>(Map evaluation based on group object)));
    }

    //...
}

Here's what I'm hesitant of doing:

//Passing Map<Username, GroupMember> object decreases abstraction and exposes implementation details
public void addGroup(Group group, Map<Username, GroupMember> groupMembers) {
        if (exists(group))
            throw new IllegalOperationException("Group with same name already exists");
        groups.put(group, groupMembers));
}

Here's part of the definition for Group to further add context;

public class Group {

    private final String name;
    private final String description;
    private final Instant dateCreated;
    private final Collection<GroupMember> members;

    //... Constructor and getters for the fields
}
added 5 characters in body; edited title
Link
Garikai
  • 173
  • 7

How best to avoid member implementation of class' Abstract/Interface instance variablevariables

added 5 characters in body; edited title
Source Link
Garikai
  • 173
  • 7
Loading
added 212 characters in body
Source Link
Garikai
  • 173
  • 7
Loading
Added more information for clarification and context
Source Link
Garikai
  • 173
  • 7
Loading
Added more information for clarification and context
Source Link
Garikai
  • 173
  • 7
Loading
Source Link
Garikai
  • 173
  • 7
Loading