Facades should not have Working Plumbing
Tags: architecture, codesmell, refactorit
Published: 2019-09-15 03:26:25

In this short article we discuss the role of facades in application architecture, some common problems encountered, and proper solutions for these problems.

Like fake buildings on a movie set, facades in software are a nice exterior representation of something complex. In terms of software, this means a single class that contains public API methods in one place for others to call. Unfortunately, this is often abused.

Put another way, if a facade is an exterior wall of a building, that wall should not contain a furnace, air conditioner, fuse box, and power distribution system. That's not to say the system doesn't need these things, just that they belong in their proper place, not bolted onto the public-facing API.

We'll be discussing a `ResumeFacade` containing several methods already.

![Resume Facade](https://thepracticaldev.s3.amazonaws.com/i/mvdh7ij7fzsbtwlq31v7.png)

Ideally each method in this facade should hand off responsibility to a dedicated object, making the `ResumeFacade` class a central coordinator of resume-related activities.

Unfortunately, what often happens in these types of classes is that someone needs a new method added to the facade and the developer adding that method simply implements the method inside the facade. 

So, for example, someone might add the following method:

```cs
public IEnumerable<JobInfo> FindJobsMatchingResume(
  ResumeInfo resume, 
  UserInfo user) 
{
  // Create a database connection

  // Do a query against the database

  // Translate results into simple objects

  // Return a list of matching objects
}
```

In an efficient codebase, this could be anywhere from 5 - 35 lines of code long. That's not too bad, right?

Well, now we want to add error handling and request validation, so our code now looks like this:

```cs
public IEnumerable<JobInfo> FindJobsMatchingResume(
  ResumeInfo resume, 
  UserInfo user) 
{
  try {
    ValidateUser(user);

    // Create a database connection

    // Do a query against the database

    // Translate results into simple objects

    // Return a list of matching objects
  }
  catch (SqlException ex) {
    // Custom handling goes here
  }
  catch (AuthenticationException ex) {
    // Custom handling goes here
  }
  catch (InvalidOperationException ex) {
    // Custom handling goes here
  }
}
```

As you can see, things start to pile up, so even if your code was very efficient, it now has a lot more boilerplate logic. Possibly you could move that logic upstream to the caller, but if you can't, your facade is growing quite a bit.

Let's say that the next sprint some new business logic comes around on filtering and sorting job matches for resumes and you now need to do more logic inside of the method. Your code just grew yet again.

These types of classes tend to grow significantly due to common causes such as:

- New methods being added to represent new capabilities being offered
- Additional error handling needed
- Additional business logic
- Changes required for bugfixing existing logic

Before you know it, your methods are 50 lines long or worse and you have an awful lot of them. You're now far from a very cohesive set of very short methods. Maybe you solve this by extracting private methods for things to call and your methods aren't that large, but this makes your method count problem even worse.

As a general rule, I like to have methods that are no longer than 20 lines of code and classes that are no longer than 250 total lines. With facades, I aim for closer to 10 lines of code per method and accept a larger number of public methods.

The solution for rapidly growing facades is for the facade to be simply a coordinator between various objects, responsible for chaining things together and packaging together appropriate responses for external callers.

In the case of our example, the refactored method might look like this:

```cs
public IEnumerable<JobInfo> FindJobsMatchingResume(
  ResumeInfo resume, 
  UserInfo user) 
{
  try {
    UserRepository.Validate(user);

    var analyzer = new ResumeAnalyzer();
    var keywords = analyzer.Analyze(resume);

    return JobsRepository.FindJobsMatching(keywords, resume.YearsExperience);
  }
  catch (ResumeAnalyzerException ex) {
    // Custom handling goes here
  }
  catch (AuthenticationException ex) {
    // Custom handling goes here
  }
}
```

In the above example, we still have a lot of error handling logic in the facade, but that's part of the facade's core responsibilities in this case - responding to internal errors in an externally-acceptable way.

The key thing here is that we're outsourcing the core logic to dedicated classes. This keeps the facade simple, easy to read, and easy to maintain. It also makes it easier to swap out different implementations of various pieces of business logic as needed.

---

Facades have an important place in application development, but that doesn't mean they get to be god objects spanning thousands of lines of code. Keep your facades simple coordinators and your architecture will be all the better for it.