Introduction

You'll see examples of code that interacts with OstroJS's features using "facades" throughout the OstroJS documentation. Facades provide classes present in the application's service container a "static" interface. OstroJS comes with a number of facades that provide you access to practically all of the functionalities.

OstroJS facades act as "static proxies" for underlying classes in the service container, allowing for more testability and flexibility than conventional static methods while preserving a succinct, expressive vocabulary. It's alright if you don't completely grasp how facades function behind the scenes; just go with the flow and keep learning about OstroJS.

The @ostro/support/facades namespace contains all of OstroJS's facades. As a result, we can easily access a facade in the following manner:

const Route = require('@ostro/support/route')
const Cache = require('@ostro/support/cache')
Route.get('/cache', function () {
   return Cache.get('key');
});

Many of the examples in the OstroJS manual will utilise facades to showcase various elements of the framework.

Helper Functions

In addition to facades, OstroJS provides a set of global "helper functions" that make interacting with popular OstroJS features more easier. View, response, url, config, and other assistance functions are some of the most commonly used. Each of OstroJS's helper functions is detailed with its associated feature; however, a comprehensive list can be found in the dedicated helper documentation.


Route.get('/users', function ({response}) {
    response.json({
        // ...
    });
});

Route.get('/users', function ({response}) {
    response.json({
        // ...
    });
});

When To Use Facades

There are several advantages to using a facade. They give a concise, familiar syntax that enables you to utilise OstroJS's features without having to memorise large class names that must be explicitly injected or set. Furthermore, they are simple to test because to their unique use of NodeJs's dynamic functions.

When employing facades, however, some caution is required. The most serious threat posed by facades is "class scope creep." Because facades are so simple to use and don't require injection, it's simple to let your classes expand and utilise several facades in a single class. When you use dependency injection, the visual signal that a big function Object() { [native code] } provides that your class is getting too large mitigates this risk. As a result, while utilising facades, keep an eye on the size of your class to ensure that its area of responsibility remains limited. If your class is becoming too large, consider breaking it up into smaller groups.

Facades Vs. Helper Functions

OstroJS contains a number of "helper" functions in addition to facades that may execute activities like as producing views, triggering events, dispatching jobs, and delivering HTTP replies. Many of these assistance functions are equivalent to matching facades. This facade call and this helper call, for example, are the same:

return await require('@ostro/support/facades/cache').get('key');
return await cache('key');

There isn't much of a distinction between facades and helper functions in terms of functionality. You may test helper functions in the same way that you would the equivalent facade. For instance, consider the following route:

Route.get('/cache', async function ({response}) {
    response.send(await cache('key'));
});

How Facades Work

A facade is a class in a OstroJS application that allows access to an object from the container. The Facade class includes the mechanism that creates this task. The main @ostro/support/facades class will be extended by OstroJS's facades, as well as any custom facades you design.

The __call() magic-method is used by the Facade base class to defer calls from your facade to an object resolved from the container. A call to the OstroJS cache system is performed in the example below. Looking at this code, it appears that the static get function on the Cache class is being used:

const Controller = require('~/app/http/controllers/controller')
const Cache = require('@ostro/support/facades/cache')
class UserController extends Controller {
    /**
     * Show the profile for the given user.
     *
     */
    async showProfile({params,view})
    {
        let user = await Cache.get('user:'+params.id);

        return view('profile',{user});
    }
}

Notice how we "import" the Cache facade towards the top of the code. This facade acts as a proxy for accessing the @ostro/contracts/cache/Factory interface's underlying implementation. Any calls made through the facade will be forwarded to the cache service's underlying instance.

If we look at that @ostro/support/facades/cache class, you'll see that there is no static method get:

class Cache extends Facade {
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    static getFacadeAccessor() { return 'cache'; }
}