Large applications without ORM?

Well I am sure they are the same thing. I remember asking a question about Entity vs Domain Model quite some time ago in this thread:

And I got this answer from Jeff Mott:

So yeah, domain models and entities are essentially the same thing, or more precisely entities are domain models with identity. Since almost all domain models have identity(ID), the name domain model and entity are used interchangeably. Entity is a term DDD invented to represent domain model.

Umm I think a rule of thumb is that all properties should be private or protected? I dont use public properties anymore, except when I assign a closure to it to effectively make it a method.

The model can then be used to solve problems related to that domain.

Problems might be “finding products based on search criteria” or emailing someone when a product comes back into stock. This all part of the domain model and would not belong in an entity class.

Entities are certainly part of the domain model, but so is all the processing logic which acts on those entities.

Indeed. But when you are dealing with entities, you will usually have public properties. In this regard we can consider storing those properties (and possibly validating them) as a responsibility.

Entities are part of your domain model. If you do a search you’ll find that it’s quite a common misconception that the M in MVC is represented by an entity (often an Active Record object) whereas the Model is actually a layer, which can be comprised of various objects (entities, value objects, services etc) as TomB points out.

As for the SRP, keep in mind that the SOLID principles are guidelines intended to help you make good design choices. You can’t follow them like a recipe… they need to be applied according to the programmer’s judgement, and with practicality in mind. Remember that part of applying the SRP is asking ‘how many reasons does this class have to change?’ Placing a behaviour in a certain class might technically seem like it’s adding another responsibility (which can be subjective anyway) but if it’s unlikely to cause problems down the line and it makes your code easier to understand then it might be justified.

On a related note, I just want to say that one idea that seems to crop up in these sorts of threads is that there is One True Way™ to architect web applications. It seems to me that practicality and business value is sometimes forgotten in the push towards theoretical purity. Some applications just don’t warrant full-blown DDD practices/architecture… sometimes an Active-Record ORM, with little to no logic in the entities, is all that is required. In fact, I’d be willing to bet that the majority of PHP apps that get built are basic CRUD apps like this.

Yet another example of why arguing over terminology is boring and unproductive.

In Domain Driven Design, the domain model consists of entities and value objects. Contrary to a previous post, domain entities have an identifier by definition.

In the PHP Doctrine 2’s ORM library, objects mapped to the database are called entities.

Entity is an over loaded term to say the least.

Can the two types of entities be the same object? You bet. Can they be different? Of course.

Could someone find a 35 year old document with a completely different definition? I’m sure they could.

Well, that’s why I said global within the object scope not whole application :wink:

Okay, so how do you unit test Product::getFinalPrice() if the method’s result depends on hidden private data?

This is a good assumption, I agree, but what if the actual database table contains 50 fields? The entity class gets the same 50 fields by default - yes, I can change it and split the class into separate ones but that can complicate the system because the mapping is no longer 1:1 and there’s a difference between the db and the entities. You might say this is object-relational mapping at work but if I kept the entities anaemic I wouldn’t have to worry about them having 50 fields as the fields alone don’t create multiple responsibilities. The responsibilities/behaviours would live in separate classes.

Yes, this is what I think is true and I’ve never actually gave much thought to what the Model is and treated it more or less equivalent to an Active Record, Data Mapper or some data store access.

From what I have read so far the Model layer generally consists of these parts:

  1. Services - this is the outer layer of the Model that exposes an interface (business logic) for use by controllers and views.
  2. Data Access Layer - this is used by the services to communicate with the database or other data store.

(I’ve found that various experts name these layers a bit differently so I’m not sure if the terminology is exactly right)

Services communicate with the Data Access Layer but do not communicate with the database directly, therefore the database can be swapped without changing anything in the Service layer. What’s more, I think that Data Mappers with their entity classes belong to the Data Access Layer - just like Active Record. Also, it looks like we can get rid of the Data Mapper or Active Record and just use plain SQL in the Data Access Layer and still the Services will continue to function properly - which gets me to the gist of this thread that I could possibly use no ORM and still have my business logic residing nicely in the Service layer in an OO way.

Let’s consider a very simple case of a CRUD application. This would be the service - most probably used by the Product Controller:

class Product {
    
    private $productDataAccess;
    
    public function __construct(ProductDataAccess $productDataAccess) {
        $this->productDataAccess = $productDataAccess;
    }
    
    public function listAll() {
        return $this->productDataAccess->fetchAll();
    }
    
    public function get($id, $customerType) {
        $product = $this->productDataAccess->getById($id);
        
        $priceCalculator = new PriceCalculator($customerType);
        $product['final_price'] = $priceCalculator->calculate($product['price']);
        return $product;
    }
    
    public function create(array $data) {
        return $this->productDataAccess->insert($data);
    }
    
    public function update(array $data, $id) {
        return $this->productDataAccess->update($data, $id);
    }
    
    public function delete($id) {
        return $this->productDataAccess->delete($id);
    }
}

This interface conforms to business requirements of the application. The service is not aware of the data storage type (not even mappers), it only uses the data access object to get or update data. We also now have the price calculation tucked away in a separate class that has clear dependencies and is easy to test.

The only problem I have - is there a better way to instantiate the PriceCalculator instead of the new keyword? Injecting it from the controller or view seems weird.

Then my data access class could be like this:

class ProductDataAccess {
    
    private $db;
    
    public function __construct(Connection $db) {
        $this->db = $db;
    }
    
    public function fetchAll() {
        return $this->db->fetchAll("SELECT * FROM product ORDER BY name");
    }
    
    public function getById($id) {
        return $this->db->fetchAssoc("SELECT * FROM product WHERE id=?", [$id]);
    }
    
    public function create(array $data) {
        return $this->db->insert('product', $data);
    }
    
    public function update(array $data, $id) {
        return $this->db->update('product', $data, $id);
    }
    
    public function delete($id) {
        return $this->db->delete('product', $id);
    }
}

Here I’m using almost plain SQL with the use of a Connection object similar to DBAL, but I might just use plain PDO. Or, I might use a Data Mapper or Active Record. I’m keeping the data access part separate from my business logic in the services.

What do you think of this approach? I’m aware that probably there are many proper ways of how to structure the Model layer and this just an example. My goal here is to combine the OO layer (business logic) with relational data access logic - and actually, making the data access logic independent.

BTW, here are some articles I’ve found on which I’m basing my findings:

  • ActiveRecord does not suck by Bill Karwin (also some good stuff in the comments). Although he mostly talks about Active Record as an example I think it applies to Data Mapper as well, even though there is obviously less coupling in Data Mapper.
  • The Anaemic Domain Model is no Anti-Pattern, it’s a SOLID design - he talks about how Anaemic Domain Model (ADM) is often better than Rich Domain Model (RDM). But I don’t think this means that the whole Model should be anaemic - to me he simply names the parts of the Model differently than other people and seems to be treating services as being outside of the Model. But nevertheless, he makes a good point, IMO.

But, where is the Product entity in all that? The Product class doesn’t build a product entity. It builds arrays for products or accesses and operates CRUD functionality in a data access layer, and they all work with arrays and not Product objects (the actual product entities). And, if I were to name this class, I’d call it ProductCrudService or something similar and not just Product.

And, assuming we are building an e-commerce application with products, what about a User, a Shopping Cart, a Rating, a Comment, a Catalog and all the other objects we’d need to make it work? I would imagine, we would have to write similar CRUD service classes for all these objects too, right? If yes, I’d raise my hand and ask, “Ehem…um…aren’t we badly breaking DRY with this design?” :smile:

This part of the Doctrine ORM about using objects demonstrates a bit better what I am talking about. It works with entities and it has an entity manager, which does the “CRUD” heavy lifting for us. Annnnd…for any entity we’ve programmed in the system. So, we can define our Product entity once and use the EM to fill that entity (or many of them) with data from the database or save entities, create new ones, etc. etc.

Scott

Yes, sorry, I should have named the class differently for clarity, it should be ProductService (unfortunately, this forum won’t allow me to edit now).

The thing is we don’t have a Product entity at all because in this setup we don’t need one! The whole point is that if you were to use Doctrine then you would access it in the data access layer - and there you would have entities because Doctrine works on entities. But the service layer is independent from how you access the database - whether it’s Doctrine or any other method, therefore it’s also independent from entities’ existence.

Well, how else are you going to provide these CRUD operations other than creating them in the service (or some other class within your Model)? If you don’t want to do that then the only alternative I can think of is communicating with the data access layer (like Doctrine) directly in the controllers - but then I’d say your controllers are doing too much. Or do you know another way of doing this? Somehow, somewhere your Model layer has to provide the methods for actions that the business side of your application requires. In such simple cases those methods will overlap with the controller actions but not always. That’s why I wouldn’t call the class ProductCrudService but simply ProductService, because the service might do many other things which are not CRUD, like notifying users of a new product, getting statistics of a product and whatever your application needs to do.

Well, that is fine but the whole point of what I was trying to achieve is to make the application independent from the data access layer - you would work with the entities only in the data access layer while the controllers and even the services do not know anything about how you access the data. In this setup the entities will contain less behaviour than usual - in most cases no behaviour at all because all business logic would reside in the service layer.

Yes, I agree all this looks like repeating similar code, especially for simple CRUD so I don’t think for simple applications it is worthwhile to go as far with the number of layers. However, I think this may provide flexibility in the long run. The most important part, I think, is to get away from simply throwing Doctrine (or whatever my favourite ORM is) into the application and using it as my Model because then:

  • my Model doesn’t have a clear interface that conforms to the requirements of my application as the whole Doctrine (or EM) interface is available to the controllers
  • the business side of my Model is tightly coupled to the ORM and it’s hard to reuse its parts in another application which uses another ORM or some completely different system

Isn’t that also a goal of an ORM. If you wanted, you can add an additional layer between your controllers and the ORM, which will add more behavior to your entities, for your domain model. Doctrine has the feature of the repository, which can add more behavior to an entity and aggregate often used queries into methods for working with the entities. This could also be a place to add your priceCalculator class.

Scott

Nope, that’s not the definition of global. Global state is meant for data that can be accessed from anywhere in your application/script. Because you have no idea where global variables come from, its confusing and you may accidentally overwrite it. A private data field can only be accessed from the very object itself, your very object/class controls how its accessed and manipulated. Its encapsulation, not global state.

I dont see why this is a problem. The method Product::getFinalPrice() only uses private properties from the product object, it does not have dependencies on global variables or singletons. Just create a product object, inject the values of netPrice and tax by its constructor or setter methods, and test it the way you want. I have no idea why its hard to test a method that does not depend on external parameters or global states.

If your database table contains 50 fields, it means your database table is either poorly designed or containing too many irrelevant fields for your entity. In the former case, you should just design your database table properly. From OOP’s point of view, its better to design your model/domain layer first, before creating your database. You should think that a database table is a storage medium for your model/entity class, not that your model/entity class is a representation of the database table. In a word, your database is servant to your model, not the other way around. If you follow good OO design principle, you shouldnt end up with model/entity classes with 50 fields, and therefore the resulting database table wont have so many columns either. In the latter case, when your database table contains irrelevant fields for your entity(ie. single table inheritance pattern), you should just pull whatever data fields you need for your models, and not everything in the database table.

Nope, the controllers are not doing too much, these are exactly what CRUD controllers are supposed to do. They create data mappers or repository objects, use them to manipulate domain models, and renders views to show off such changes/responses. Your domain models aint supposed to persist its own data, instead this job is left over to the data mappers/repositories. In most cases, your controllers wont even need to interact with the domain models directly, instead they always use the data mappers/repositories as intermediary. You may see this article(in ASP.NET environment, but you should be able to understand) as an example of how the controllers interact with repositories:
http://www.codeguru.com/csharp/.net/net_asp/mvc/using-the-repository-pattern-with-asp.net-mvc-and-entity-framework.htm

I also know about the rule to keep classes small and that having too many properties is a good sign a class is doing too much, but I have to disagree a bit with entity objects following this rule to the tee. I work on a CRM system where we have well over 200 fields in our case object and although I would admit we probably have a good bit of unnecessary information in the case object, we’d never be able to slim down to below 50 fields. In fact, the underlying database table has at least 8 or 9 system fields itself, which the normal user doesn’t see. There is even a secondary table for meta data too. So a lot going on, just for one object type.

Sometimes, the object in a domain is fairly complex and splitting the properties out to different classes for the sake of having small classes is not completely appropriate (is it ever really?). If you need a lot of properties to model an object in a domain, then the entity for those objects will be big and have a good number of properties. They aren’t god classes, they are simply fat and complex objects.

Scott

It’s not for the sake of having smaller classes, its for a good reason. If your class has 50 fields/properties, it clearly means that your class is doing too much. I am actually a bit curious at what this database with 200 columns look like. If you dont mind, would you show me the structure of this database table?

But, properties aren’t doing anything. They only hold values. The methods in any object are the behavior and the “doing” part of an object. We are also talking about entities, which are related to database tables. And in the case of our “Case” object, a lot of the data is denormalized too. I’ll grant that. However, 95% of the fields are necessary for the Case processes, either for informational or process control purposes. I’ll also admit, the system we are using also has record types, so not every field is used for every case. (and what the metadata table is used for). But, the main case record type has well over 50 fields and it must be that way for the case process to work. Here a clip from the “fields” screen of our case object. The fields on the left are default fields predetermined by the system. The fields on the right are the custom fields we’ve added for our processes.

Scott

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.