1

The base class (in the base lib, not owned by me), has upgraded its code and add a new method to support additional use cases.

This is the existing method signature in the base class:

public void Alert(string someAlertString);

With the new release, the base class is supporting a list of AlertObject (at some point the base class might deprecate the string alert)

public void Alert(List<Alert> alertObj);

The base class in lib looks something like this:

public BaseClass {
   public void Alert(string message) {
     //Print msg on the UI.
   }

   public void Alert(List<Alert> alerts) {   <-- New Addition.
     // Loop through each alert and show the list of messages.
   }

   // Other methods.
}

On my side of the code, I have the alert in multiple places in multiple subclasses (>500 alerts), like this:

public SubClass: BaseClass {

    public void Execute(){
       // Execute some logic
       Alert("This is a warning message."); <-- Call base calls alert
    }
 }

I want to update all these alert statements to use an AlertObject (and I want to add category only to the new alerts, old alerts can continue using the default category):

public class Alert {
   public string message {get;set;}
   public string category {get;set;}
}

One way to do this is to define a helper class which takes the existing string and return a List of AlertObject:

public static class AlertHelper {
   public static List<Alert> getNewAlert(string msg, string category="Not Defined") {
      Alert a = new Alert();
      a.message = msg;
      a.category = category;
      return new List<Alert>() { a };
   }
}

Then I can replace all the instance of my Alert with:

base.Alert(AlertHelper.getNewAlert("This is a warning message."))

The one problem I see here is that as the Alert class (in a separate lib) keeps adding properties to support more detailed alerts, I need to keep updating my helper class, and potentially all the places where I call helper class.

I was wondering if there is a better way to design this.

3 Answers 3

3

One of the best features of an external library can have, is non-changing signatures. If you keep changing the signature of a much used feature in a library, then it would be easier to have it built into the consumer.

To me, it sound like the extra functionality, should be in the library class. Without changing the signature of the existing method. Something like this:

public class AlertsLibrary 
{
    // Base method remains the same, though with category added. 
    // The default value ensures that old code does not need change.
    public void Alert(string alertMessage, string category = "Not defined") 
    {
        ...
    }

    // Overload to allow a list of messages, but still handled with the base method.
    public void Alert(IEnumerable<string> alertMessages)
    {
        foreach(var msg in alertMessages) 
        {
            Alert(msg);
        }
    }

    // You can even overload with an alert object if you'd like (must be in the library as well)
    public void(Alert alert) 
    {
        Alert(alert.Message, alert.Category);
    }
}

You could then also make methods which takes an IEnumerable<Alert> and calls the base method a number of times. This would allow all the features you describe, without breaking any old code.

1
  • Is this a class you're suggesting the OP write, or the authors of the library write / update?
    – mmathis
    Commented Apr 6, 2020 at 12:30
0

First, you don't need any helper class: a=Alert.of("alert msg") is less wordy and you keep all things related to Alert in Alert class.
Second, you could use extension methods to implement such behavior without changing third-party lib.
Later you could change implementation of this method to conform new properties in Alert. Since it will receive a String as parameter and return same Alert, you don't need to change each line where you call Alert.of()

Another way to get more control is to create own AlertAdaptor extends Alert and use it. You could encapsulate many things in it in order to protect callers from changes in third-party lib.
More defensive way would be AlertAdaptor extends Alert implements IAlert where IAlert would include methods you need from Alert. In that case you don't use properties and fields from Alert but methods from your own interface, so when Alert.message become Alert.shortMsg all you will need is to write single line in AlertAdaptor.
But defense will cost your efforts: you'll need to modify IAlert each time when library introduce useful feature for Alert.

0

I can’t see what makes you think the old method would be deprecated and that there is any reason to replace any of the existing calls.

If you have a situation where the new call would have simplified your code or would have improved your UI then use it - if the old interface worked then keep it.

Changing five hundred calls and having your change rejected in a code review wouldn’t be my idea of fun.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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