Here is a very basic example of what I am trying to do. In reallity there are more relations but not something extreme or memory heavy.

public class ClassA : ISomething
    public double property { get; set; }
    public ClassB classb { get; set; }

public class ClassB : ISomething2
    public double Length { get; set; }

public class MyProject : BaseProject
    public IEnumerable<ISomething> ISomethings { get; set; }
    public IEnumerable<ISomething2> ISomethings2 { get; set; }

The issue here is that I have to keep a list of MyProject.ISomethings2 and then classb property of ClassA to reference only an existing item in MyProject.ISomethings2 list. The hard thing here is that:

  • Removing an item from ISomething2 should remove all references to it (classb property of ClassA instances to be set to null)
  • Prevent other developers setting classb property to a non existing object in list or a new user created object.
  • Objects in MyProject.ISomethings2 could be added without having to be referenced from elsewhere.

These classes are used for project description not database stuff. Like when you open a project file for an application. So changing a property in classB should be visible to all since it is the same object reference. Is there a pattern to achieve what I want without much coupling? Alternative designs/approaches are also welcome.

  • It is not clear at all what you are talking about. It seems to me that there might be mistakes in your wording. For example, are you sure you meant to write "Removing an item from ISomething2" and not "Removing an item from MyProject.ISomethings2"? – Mike Nakis Mar 6 '15 at 14:53
  • "Objects in ISomethings2 can exist without being referenced." -- obviously, if they exist in ISomethings2, then they are referenced. So, you probably mean to say "without being referenced elsewhere". You really should be more specific and more accurate in your wording. – Mike Nakis Mar 6 '15 at 14:55
  • Yes I mean MyProject.ISomethings2. I'll try to edit it. – GorillaApe Mar 6 '15 at 15:02
  • 1
    The names you choosed in your example make it very hard to understand. – Tulains Córdova Mar 6 '15 at 15:10

Is there a pattern to achieve what I want without much coupling?

Not really, since at its core what you want to do "when X happens, I want to do Y to these other things" is coupling by definition. Which also makes this a rather undesirable design for the problem at hand.

If I had to work with this, I'd start by looking to make the classes immutable (publically at least) and controlled by the project. If you can't set the classb property on the object, there's no way to set it to be invalid. Instead the project class can do that (along with validation rules, and possible optimizations like reference counting perhaps).

But honestly, I would try very hard to not work with this. Project here is a manager of the other objects. Forcing class instances to be in some external collection is gross and unweildly. Occasionally it's somewhat necessary (games especially do this), but it should be avoided where possible and used with care otherwise. Without knowing more about the problem you're trying to solve, I can't say for sure which bucket this falls in.

  • a similar example: you let user create wheel specifications and then you let user to choose for each car the desired wheel spec. deleting a wheel spec should leave car with null wheel . – GorillaApe Mar 6 '15 at 15:43
  • in databases it is easy to solve though – GorillaApe Mar 6 '15 at 15:44
  • @parhs - Just because the specification is no longer available doesn't magically eliminate wheels out in the world. – Telastyn Mar 6 '15 at 15:54

Note: I'm assuming the language is C#. If it's Java, similar mechanisms should exist as well.

  • If you want to track changes to the properties of ClassA, you can use INotifyPropertyChanged.

  • If you want to track changes to the ISomethings2 sequence, instead of IEnumerable<T>, use ObservableCollection<T>.

  • If you just need to keep ISomethings2 sequence in sync with ISomethings, rewrite the property as:

    public IEnumerable<ISomething2> ISomethings2
            return this.ISomethings.Select(c => c.classb);

If this doesn't give you an answer, consider editing your question. Its actual form is very unclear because of the lack of proper terminology and cryptic names of your example. Also note that you currently cannot remove anything from ISomethings2, given its type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.