5

In my little WinForm app, intended to practice as a hobbyist, I'm using this code to pass data from the View to its Presenter:

public event Action<object, string, string?>? SearchInAlbums;
    private void Btn_SearchInAlbums_Click(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(cmbSearchContext.SelectedValue.ToString()))
            SearchInAlbums?.Invoke(this, Txt_Search.Text, cmbSearchContext.SelectedValue.ToString());
    }

Then in the listener of this event, the Presenter, I can write code like this:

        public void OnSearchInAlbums(object? sender, string searchPhrase, string? tableName)
        {
            if (!string.IsNullOrEmpty(tableName))
            {
                _albumList = _albumRepository.GetAlbumsByValue(searchPhrase, tableName);
                SetGridViewBindingSource();
            }
            else
            {
                _mainView.Message =
                    "No records were affected: the table name was NULL or EMPTY (no table name)";
            }
        }

This way this consumer (Presenter), doesn't have to ask for data - instead it gets it and then tells the Repository what to do with it. This way, in my mind, I have enforced the "Tell Don't Ask" principle.

But, I see nobody using code like:

public event Action<object, string, string?>? SearchInAlbums;

Instead, they all use:

public event EventHandler SearchInAlbums; //or something similar

By doing the latter, the presenter is forced to ask for data from the view and therefore the TDA principle has been broken. I'm a hobby-learner, so I don't know. What is the take by more experienced programmers? Am I actually doing things right here? Or am I using concepts wrong?

Teachers on YouTube always ask for data from the View of the Presenter, totally ignoring the TDA principle. Maybe that's normal in this case. But I wouldn't know why as it strikes me as unnecessary.

Valmont
  • 193

2 Answers2

6

But, I see nobody using code like:

 public event Action<object, string, string?>? SearchInAlbums;

Instead, they all use:

 public event EventHandler SearchInAlbums; //or something similar

By doing the latter, the presenter is forced to ask for data from the view and therefore the TDA principle has been broken.

Em, no. If you create a special SearchEventHandler with specific event args, like

public delegate void SearchEventHandler(object sender, SearchEventArgs e);

then you can pass all the data you like in the SearchEventArgs object and implement "tell don't ask" just as with a delegate declared by the Action syntax.

Note Action<...> was introduced with .Net Fw 3.5, whilst EventHandler is much older, it was available already in .Net Fw 1.1 and is still used extensively inside Winforms itself. That is probably the reason why you find more examples with the EventHandler syntax. Today, I guess I would prefer Action<object, string, string?> when it helps to avoid boilerplate code, and when I don't need a uniform implementation where each handler derives from EventHandler.

Doc Brown
  • 218,378
2

Teachers on YouTube always ask for data from the View within the Presenter totally ignoring the TDA principle

Well, maybe you took TDA a bit too far. Tell don't ask is a motto for us to improve the cohesion and encapsulation of the components. For example

class GridView {
  public visible: true;
  public enabled: true;
  public doSomething(): void { .... }
}

class Presenter { private grid: GridView; public doSomething(): void { //breaking TDA: poor encapsulation and asking for info the grid already knows. if(this.grid.visible && this.grid.enabled){ this.grid.doSomeThing(); } } }

Would be better if

class GridView {
  private visible: true;
  private enabled: true;
  //high cohesion and encapsulation
  public doSomething(): void { 
     if(this.visible && this.enabled){
       //then ...
     } 
     //otherwise ...
  }
}

class Presenter { private grid: GridView; public doSomething(): void { //Compliant with TDA, the presenter is telling "grid", to do something this.grid.doSomething(); } }

Am I actually doing things right here? Or am I using concepts wrong?

Technically, it's correct, but you might not have weighed the pros and cons of each solution. Essentially, this code is neither taking 40h/week of your time nor under the same pressure as a real-world project (frequent, unexpected and WTF changes).

If I got it right, EventHandler SearchInAlbums seems more convenient because extending the event handling to custom events only takes you to extend EventArg vs changing signatures, which is in many cases a considerable drawback.

In other words, passing Event-related data is fine using a derived class from EventArgs

Laiv
  • 14,990