1

Let's assume we have the following class:

public class Employee
{
  public string Name { get; private set; } 
  public string Team { get; private set; }

  public Employee(string name, string team)
  {
    this.Name = name;
    this.Team = team;
  }

  public void UpdateName(string newName, string updatedBy)
  {
    this.Name = newName;

    this.Update(updatedBy);
  }

  public void UpdateTeam(string newTeam, string updatedBy)
  {
    this.Team = newTeam;

    this.Update(updatedBy);
  }

  private void Update(string updatedBy)
  {
    // and do something with updatedBy
  }
}

Is there a better way in C# I can enforce a method (e.g. UpdateTeam to call Update method and pass it a string parameter - e.g. updatedBy)?

Of course there is no such syntax, but just to illustrate what I mean:

public class Employee
{
  // ...

  public void UpdateTeam(string newTeam, string updatedBy) : Update(updatedBy)
  {
    this.Team = newTeam;
  }

  private void Update(string updatedBy)
  {
    // and do something with updatedBy
  }
}

Edit: I know about the 'Template' pattern, it's NOT what I need.

hyankov
  • 4,049
  • 1
  • 29
  • 46
  • Not declaratively - you can verify that you get the right _results_ with unit tests but there is not a mechanism to enforce a specific _implementation_. – D Stanley Jul 13 '16 at 16:01
  • You could look into [Aspect-oriented programming](https://en.wikipedia.org/wiki/Aspect-oriented_programming) with a tool like Postsharp. – DavidG Jul 13 '16 at 16:05

4 Answers4

1

I believe that models should be lightweight and there is no place for business logic inside model classes. You should consider extracting business logic in a separate class. This concept may help:

public class UpdateNameCommand : ICommand<UpdateNameContext>
{
    public void Execute(UpdateNameContext context)
    {
        UpdateEmployeeName(context.NewName);
        UpdateTeam(context.UpdatedBy);
    }

    private void UpdateEmployeeName(string name)
    {
        // ...
    }

    private void UpdateTeam(string updatedBy)
    {
        // ...
    }
}

public interface ICommand<TContext>
{
    void Execute(TContext context);
}

Where command context is a simple class that is responsible to pass data to the command and (if needed) receive results after command execution.

It not necessarily should be a command but any separate class that is responsible for business case. And other programmers should use it to perform this specific action. This class (or method) should encapsulate necessary logic and exposes simple interface for calling from the outside.

Good reading about SOLID principles. The described approach covers at least 2 principles and maybe more depending on your application needs:

S - Single responsibility
O - Open/Closed principle

Andrei
  • 42,814
  • 35
  • 154
  • 218
  • Thanks for your response. But I feel that the business logic related to that object, belongs exactly in the object, as in my example. Isn't that the core principle of the Object-Oriented Programming? I don't think I violate the 'S', because the exposed methods still serve the same responsibility - maintaining the Employee object. If I am to extract this logic into a Command/Handler pattern, we are effectively moving from OOP (rich model), to Procedural programming (anemic model). – hyankov Jul 13 '16 at 20:00
  • @HristoYankov it's your opinion and I respect it. I am just a believer that models should be lightweight. I also prefer to keep business logic separate from models. I think in a real world applications there will be a lot of business logic related to model and if you put all of it in a single class, it will be too much for `single responsibility`. Even now you have UpdateTeam method that actually belongs to a Team class and not Employee. Very controversial and it's just my opinion. – Andrei Jul 13 '16 at 20:09
  • Sorry, I named it badly. It has nothing to do with managing another object (i.e. Team). Should have called it 'Age' or something. Regardless, I like your command approach. – hyankov Jul 13 '16 at 20:14
  • @HristoYankov thank you. And I am not criticizing your approach. Everyone has preferences. Hope you will fine a good way to workaround your problem. Martin suggested AOP, it might help you. – Andrei Jul 13 '16 at 20:22
0

Add code to your setter of Name and Team that it will set an internal property and then call Update.

UpdatedBy should be in another class. Your now mixing 2 responsibilities into one class.

RvdK
  • 19,580
  • 4
  • 64
  • 107
0

No, there is no better way than what you already suggested. :)

Of course there are some other ways to do it (setting a property instead of calling a method, perhaps even calling an event, but in all cases you need add that call manually.)

You might want to consider AOP. AOP lets you define a special attribute which can call a method before or after your public method is called. Of course you still have to add that attribute manually.

For more information about AOP, take a look at: https://www.postsharp.net/

Martin Mulder
  • 12,642
  • 3
  • 25
  • 54
0

Maybe you could try to use Aspect-Oriented Programming. It seems like AOP can help you. One of definition would be:

An aspect is a common feature that's typically scattered across methods, classes, object hierarchies, or even entire object models. It is behavior that looks and smells like it should have structure, but you can't find a way to express this structure in code with traditional object-oriented techniques.

So, you need to do extra job by changing name or team. That "extra job" should not be mixed with your code, because of cleanness of you design.

There is one very nice post here: What is aspect-oriented programming?

Community
  • 1
  • 1
Marko Krstic
  • 1,417
  • 1
  • 11
  • 13