0

It seems inefficient to go through the whole HTTP process. But I can't really come up with an alternative solution that doesn't involve coupling the code for the API with the code for the public-facing website, which seems to defeat the whole purpose of "dogfeeding" in the first place. So is it possible to skip the overhead of an HTTP request while also avoiding any coupling?

  • 4
    Yup. It's common. And, the HTTP overhead probably won't be your biggest performance hurdle -- unless you're building a "real-time" application. Alternatives depend on where you're connecting from. From a browser? The alternative would be WebSockets (still initiated over HTTP). Between internal systems? It's up to you! ... You could write connectors using a raw socket connections, shell from one box to another, or pass sticky notes around. Your call. – svidgen Mar 12 '18 at 2:33
3

It is totally possible to skip the whole HTTP process and avoid coupling. The question is: do you want that?

Because the only thing you are going to achieve is that you have another process with its own infrastructure and its own hurdles doing basically the same you're doing with your HTTP process.

Do you want to setup a new server? Do you want to invent your own protocol? Will the total be more efficient then what you're currently using? Do you want to support this?

If the answer to all these questions is : "yes", then by all means go ahead and make that infrastructure.

If you're not in the business of making your own protocols then stick with what is easy and well known......HTTP.

On top of that, it's not only about the communication between you and the one consuming your api, it's also about the hard- and software in between. For instance a lot of company networks will block all non-http traffic for security reasons....breaking your non-http api.

0

It's unclear from the question whether or not there is a physical separation between your front-end and API. That is, your application is distributed between two different servers. If this is the case, then using HTTP for communication is a viable option (although other protocols do exist).

It seems to me, though, that you are asking about an application that doesn't have a physical boundary like the one outlined above. In which case a discussion about the goals of decoupling and how a well-designed architecture can facilitate loose coupling may be useful.

First and foremost there is always going to be some level of coupling between your client and the API. Although the goal of dividing your application into distinct conceptual layers (e.g. View -> Application -> Domain -> Persistence) is to foster decoupling in a way that each can change independently of one another, these layers still must communicate. That is, at the boundary between layers, there must exist some shared knowledge in terms of communication (not implementation).

For example, your View layer must know how to compose a valid command for your Application layer (or at the very least know how to ask how to compose a command). What this means is that if you ever change the command signature (the data that must be included with a request) or the query signature (the data returned by a request) in your Application layer, it's likely this change will bubble up to your View layer. This applies to all architectural boundaries and is often the best place to use interfaces to clearly illustrate the communication contract.

The second consideration (of which is the most concern to me) is that an application should not require HTTP to communicate with itself. In fact, a properly designed application should not even be "aware" of the web in general. This makes sense right? The entire point of layering your application with a View as the highest conceptual layer is to enable the "swapping" of the View without needing to change any of the layers beneath it! This affords the existence of many independent Views of your application (console, HTML, JSON, desktop, etc).

Okay, so how does all of that relate to your question? I think the issue we are running into here for your application is that you have defined the contract for communication between layers only in terms of HTTP. That is, there doesn't exists an application-level form of communication. For example, instead of translating an HttpRequest into a more direct command (e.g. FindOrder), you may be using the HttpRequest as the command directly. What this ends up doing is pushing application logic "upward" in a way that your Controller methods are responsible for "carrying-out" the command instead of your domain, thereby resulting in the "code coupling" you mention above. For example:

// OrderController

protected $orderRepository;

public function findOrder( int $orderId ) : ActionResult
{
     $order = $this->orderRepository->find($orderId);

     return $this->view('order', $order);
}

vs.

// OrderController

protected $orderService;

public function findOrder( int $orderId ) : ActionResult
{
    $order = $this->orderSerivce->find($orderId);

    return $this->view('order', $order);
}

Now, this may seem like just a silly semantic difference where I've only just re-named a single variable, but it illustrates a fundamental and very important concept. Your Controllers are really part of your View, not your Application layer. The first example has dependency between the Controller and the Domain via the OrderRepository (making the Controller part of the Application layer), where the second example has the dependency on the Application via OrderService instead (keeping the Controller in the View).

By pushing the implementation of finding an Order "downward" into an application service, we are achieving decoupling. The View layer is only dependent on the IOrderService interface. This interface exists at a conceptually lower level than your Controllers and can be utilized by any number of components (e.g. a method that return the Order in HTML and a method that returns the Order in JSON).

The important take-away of the above is that the contract (interface) for communication between your conceptual layers should be defined in your application. This facilitates re-use between Views.

My assumption is that, on page load, you would like to render as mush as possible server-side, but don't have an Application layer that helps facilitate different Views in a way that prevents code duplication or coupling between Controllers. Re-organizing your application can serve as the solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.