Function before nomenclature
There is a bit of name interpretation going on here. I suspect you may have gotten things twisted around and are actually missing an additional DTO class.
You have your classes a name, and are now asking us where you should use these classes, based on the name you arbitrarily gave them. That's doing things the wrong way around.
- First you need to know where you're looking (which interaction between which components).
- Then you decide to create a DTO to facilitate data transfer between them.
- Then you name your class after the data it contains.
It makes no sense to name a class and decide its content without knowing where it is going to be used.
DTOs are inbetween layers
Every layer deals with two kinds of objects: the ones they expose, and the ones they consume from their own dependency. Using a common naming scheme:
DATABASE
|
| Entity
V
DAL
|
| Data object
V
BLL
|
| Domain/business object
V
WEB
|
| (View)Model or response object
V
WEB REQUEST
So, the DAL consumes entities (from the database) and exposes data objects (to its consumer, in this case the BLL).
In turn, the BLL consumes the data objects (from the DAL) and returns business objects (to its consumer, in this case the WEB project)
I infer that you are using the "DAL" classes as your actual entities. If you weren't using them as entities, I don't think you would've posted the question as the "DAL" classes would then obviously have no use except to act as the returned type from your DAL repositories - which would preclude the need for your question. Correct me if I'm wrong.
But if DalCustomer
is your entity, then what is BllCustomer
? There are two options here:
- Either it's the data object, i.e. what you intend to return to the BLL, which means that the name isn't good. The object's name shouldn't account for a specific consumer, since any given layer may have several consumers.
- Or it's the business object, i.e. what you intend to return from the BLL to the WEB project (from my example). In this case, you are actually missing a data object type which is returned from the DAL to the BLL.
Returning entities
From a comment you posted:
In my case, DalCustomer is mirror of the tables in DB. [..] I'm thinking to change DAL to return DalObjects to the BLL.
You're asking whether your DAL should return your entity classes.
The short answer is no. Returning your entities would mean that you fail to encapsulate your layer with its own dto objects, which effectively negates a large portion of the layer's purpose.
From the same comment:
BLL will handle conversion to Business Objs,retrieve and fill in nested obj
Just like how the BLL converts the data it consumes (from other project) into its own object (= the business object); the DAL should be doing the same thing. It should take the database entities and it should convert it into its own object (= the data object).
This whole "convert it into your own DTO class" effectively applies to each and every layer. It is not advised to skip it in a layer. Not that it can't be done, but the consequences are usually heavier than the cost of implementation, so it's better to just do it right the first time.
Dependency inversion
There is one caveat here: when you use dependency inversion, then your DAL does actually return a business object.
I can't delve into dependency inversion fully here (the internet is your friend to learn about that), but the short explanation is that with inverted dependencies, the DAL would consume the business layer, instead of the other way around, and therefore be able to use the business object as a return type.
I infer that your situation is not making use of inverted dependencies, but it seemed relevant to mention in case you read or find other examples where a business object is returned by a DAL.
Naming things based on their layer?
I strongly suggest you move away from naming things after the layer they're from, as I suspect it contributed to getting your wires crossed. Instead, name the class for what it is. It doesn't matter that e.g. the data object and the business object have the same class name, since they're in a different namespace anyway.
namespace MyProject.Data
{
public class Customer
{
// ...
}
}
namespace MyProject.Business
{
public class Customer
{
// ...
}
}
Namespaces exists specifically so we don't need to ensure that all our class names are globally unique, as that often becomes a challenge in coming up with either synonyms or superfluous pre/suffixes to keep the names unique.
There are some cases where this means you have to explicitly distinguish between two similarly named classes that are both used in the same file. You can either use their explicit namespaces (which is sufficient if there are only a handful of reference. Or, if it becomes too annoying to do so, you can still opt to locally give them a more distinct name there.
using DataCustomer = MyProject.Data.Customer;
using BusinessCustomer = MyProject.Business.Customer;
public class CustomerMapper
{
public DataCustomer ToDataObject(BusinessCustomer c)
{
// ...
}
public BusinessCustomer ToDataObject(DataCustomer c)
{
// ...
}
}
It's better to only use this unique name in files where it matters, instead of prefixing it into the actual class name and then have to deal with the ugly name everywhere.