Loose Coupling in a Web API

Tight coupling occurs when a group of classes is highly dependent on each other Loose coupling involves detaching the classes that integrate with the whole.

This WebAPI has a PersonController. The goal is to create a list of Persons.

  public class Person
  {
      public int Id { get; set; }
      public string Name { get; set; }
      public string Address { get; set; }
      public string City { get; set; }
      public string Country { get; set; }

  }

I created an interface for a PersonService whose goal was to return Persons.

public interface IPersonService
{
    List<Person> GetPersons();
}

A class implementing IPersonService can return the Persons in many ways. For example, it can query a database. In this case, I used a very simple implementation of IPersonService

 
 public class PersonService : IPersonService
 {

public List<Person> GetPersons()
 {
     List<Person> persons = new List<Person>();
     persons.Add(new Person
     {
         Id=1,
         Name = "Herminia Mayert",
         Address = "3 Rafaela Villages",
         City= "3 Rafaela Villages",
         Country = "Ghana"
     });
     persons.Add(new Person
     {
         Id=2,
         Name = "Imogene Skiles",
         Address = "4488 Little Inlet",
         City= "4488 Little Inlet",
         Country = " Guadeloupe"
     });
...
           return persons;

       }
}

Here is the relevant part of the Person Controller.

  [ApiController]
  [Route("[controller]")]
  public class PersonController : ControllerBase
  {
      private readonly ILogger<PersonController> _logger;
      private readonly IPersonService _service;


      public PersonController(ILogger<PersonController> logger, IPersonService service)
      {
          _logger = logger;
          _service = service;
      }

        [HttpGet]
        public IEnumerable<Person> Get()
        {
            _logger.LogInformation("Person API: GetPersons called");
            return _service.GetPersons();
        }
...
}

I included an ILogger to how it supports loose coupling.

In Program.cs, I have PersonService as the implementation of IPersonService.

builder.Services.AddScoped<IPersonService, PersonService>();

I included two implementations of ILogger in Program.cs.

builder.Logging.AddConsole();
builder.Logging.AddCustomLogger();

CustomLogger is a database logger that I wrote. Both the Console and CustomLogger will log.

Loose coupling makes it easier to test. Suppose I want to test the Get of PersonController. I used xUnit and Moq. To set this up

  public class PersonServiceTester
  {
      private readonly Mock<IPersonService> _mockPersonService;
      private readonly ILogger<PersonController> _testLogger;
      private readonly PersonController _personController;

      public PersonServiceTester()
      {
          _mockPersonService = new Mock<IPersonService>();
 
          ILoggerFactory factory = new Microsoft.Extensions.Logging.Abstractions.NullLoggerFactory();
          _testLogger = factory.CreateLogger<PersonController>();
          _personController = new PersonController(_testLogger, _mockPersonService.Object);

      }
...
}

Here _testLogger doesn’t do much because I choose not to test the ILogger functionality.

Here is my Fact in PersonServiceTest

        [Fact]
        public void PersonControllerTest()
        {
            List<Person> persons = new List<Person>();
            persons.Add(new Person
            {
                Id = 1,
                Name = "Herminia Mayert",
                Address = "3 Rafaela Villages",
                City = "3 Rafaela Villages",
                Country = "Ghana"
            });
            _mockPersonService.Setup(s=>s.GetPersons()).Returns(persons);


            IEnumerable actualPersons = _personController.Get();
            Assert.Same(persons, actualPersons);
        }

In this way, using the interface IPersonService makes it helpful to test the PersonController.

We see that the use of interfaces is a help to decouple classes.


Discover more from Schroeder Consulting LLC

Subscribe to get the latest posts sent to your email.

Carolyn Schroeder, Sole Proprietor and IT Consultant

Carolyn worked in a number of Kansas City area corporate environments before establishing her own consulting business. She is dedicated to architecting the best possible solutions to meet the needs of her clients. She is passionate about learning the cutting edge tools necessary to drive business forward.

Let’s connect