Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

API architecture

I am in the process of designing an API. I would like to know if what I have come up with is a good solution:

I have a respository type of data layer that talks to a database by converting business classes into entities(generated from LLBL GEN, I didn't want to use the entities directly as my business objects because I wanted to keep them simple and allow me to swap out to Entity Framework or some other mapper is I needed to)

I have a WCF service layer that I'm using as a type of facade. It calls the respository layer and converts the business objects to DTOs and passes them through the API service call via a message to the client. The client can be an ASPX website, Silverlight app, WPF app, or even a WP7 app. The problem I keep runnnig into is when I want to run business logic I have to send the DTO back to the WCF service and then back to the client. This doesn't seem "right" to me. I can't put business logic in the DTO because that defeats the purpose. But if I want business type code to run on the client I have a lot of duplication of code throughout my different clients.

My business layer does not know of the data layer, my data layer knows of the business layer and my facade layer knows of the data layer and the business layer and the DTOs. Is this a bad design for an API? And can anyone offer me any suggestions? I have only learned of enterprise level apps through reading different articles online.

Thanks!

like image 986
adminJaxon Avatar asked Dec 20 '10 15:12

adminJaxon


2 Answers

Relations between layers

If I understand your design well, the business layer does not know of (=does not use) the data layer, and the facade actually interconnects them by translating DAOs into DTOs and vice-versa.

You should consider a rather different approach: Define interfaces for all data-related objects (regardless if DAOs or DTOs) and use an Inversion-of-Control container to weave the business layer and data access layer together. The reason is that in your design you might quickly run into the inability to retrieve additional data in right in the business layer. You'd end up with the facade substituting this lack and hence doing too much actual business logic.

In case you make a clear connection between the business layer and the underlying data layer, while separating them with well-designed interfaces and an IoC container, you prevent this problem while maintaining good and concise internal design.

Usage of DTOs

I think it's alright that you have to pass the DTOs back to the back-end of your app. In your case the purpose of DTOs is (1) to supply information for the presentation layer, and (2) to provide a way of passing modified or new data to the back-end for further processing. DTOs for cases (1) and (2) need not be the same. Hence if it makes sense, you can pass to the back-end just a DTO representing a subset of the whole information.

However, the back-end shall return a new DTO after processing, which, again, needs not to be the same DTO as the input DTO. This way the presentation layer can easily adapt to changes made by the back-end into related parts of the whole object.

Imagine a simple Get / Update API such as this one:

CustomerDTO GetCustomer(int customerID);

CustomerDTO UpdateCustomerAddress(int customerID, AddressDTO address);

CustomerDTO UpdateCustomerPrimaryContact(int customerID, PersonDTO primaryContact);

You are using an ID to identify a customer and passing in a DTO that represents a subset of the customer record to be updated (regardless of the underlying data architecture). The out DTO represents the customer as a whole, simplifying the presentation-layer's task of updating the information shown to the user. The advantage is the back-end does not need to know which subset of customer data the presentation layer actually needs, and the presentation layer can pass the back-end only those parts that were really modified.

Update — technical note: Consider using a tool like AutoMapper (C#) to automate translations between DTOs and DAOs. While this matter is a subject of technology used, generally this approach saves a lot of manual work and is able to eliminate hard-to-discover bugs. Having such an object translation automation in place helps promote better design practices and allows you to produce more-specialized and hence semantically more accurate DTOs.


Disclaimer: While this is a rather general question, my recommendations may not seem right in respect to further details of your application which are not covered in your question.

like image 101
Ondrej Tucny Avatar answered Sep 22 '22 14:09

Ondrej Tucny


My business layer does not know of the data layer, my data layer knows of the business layer and my facade layer knows of the data layer and the business layer and the DTOs. Is this a bad design for an API?

No layer should know about the layer above.

I have a WCF service layer that I'm using as a type of facade. It calls the respository layer and converts the business objects to DTOs and passes them through the API service call via a message to the client. The client can be an ASPX website, Silverlight app, WPF app, or even a WP7 app

Theres a design principle called You Aint Gonno Need It which is the almost the same thing as Keep It Simple (and) Stupid.

They both is all about NOT adding features that you might need. If you start with only having a website that uses the service layer, then simply use it directly without a WCF service.

If you need a WCF service later on, then add it later.

If you are defining the services using interfaces it's quite to swap a implementation that you are using directly to a WCF service implementation. (if you are using a IoC container)

Concretes vs interfaces

You should always put the interfaces and business objects in a separate assembly from implementations (classes) to make it easier to swap implementations of each layer. It's a design pattern called Separated interace which you can read about here: http://martinfowler.com/eaaCatalog/separatedInterface.html

like image 44
jgauffin Avatar answered Sep 21 '22 14:09

jgauffin