is there any way to "inline" (not embed) an entity into a projection without manually copying the getters and keeping em manually in sync?
Example:
Entity
f1
f2
f3
Projection
#Inline(Entity.class)
becomes:
Projection
getF1()
getF2()
getF3()
The only way I see is to implement the Projection in the Entity but this does not match very well with my usage of Lombok and it no longer works if the Projection has additional fields which the enitiy has not (It would require an additional interface).
Any ideas?
Not really sure what you are trying to achieve by this - projections are there for providing different view on data - so they will in many cases not totally match your entity structure. If you are worried about the code duplication you can have a common interface that both your entity and the projection extend/implement.
This is what I do now, using a common interface for Entity and Projection.
This interface contains only the getters relevant for the projection.
Related
I've recently started developing in .NET core.
When developing I encountered the situation that I have to make very similair models that aren't quite the same. For example, let's talk about a booking model:
Frontend: Here I need a model that gets posted as a JSON to my backend and gets deserliazed to a sort of FrontendBooking model.
Backend: I need to add Customer data to the booking, therefore I need to add fields like: CustomerName and CustomerAddress, based on their CustomerId. The backend needs to provide this data, I do not want the frontend to determine these fields. I combine these models to prepare it for an API call. To a model called RequestBooking.
API: I sent RequestBooking to an API and get a response with a similair object that has for example a Status and BookingId added, this was added to the model by the API. So I need to deserialize this to an object called: ResponseBooking.
Database: Finally I wish to store the object to a database, not all properties of the model are relevant however, therefore I create another model called: DatabaseBooking and store this to the databse.
When a property is added, removed or changed. Then I'll have to change it for each of these models.
Is there a design pattern or some other solution, so this is more manageable?
Also, what is best practise for naming these models? Naming them all Booking doesn't feel quite right and adding what they're used for doesn't feel quite right either.
Thanks in advance.
Well, in general you will need different (although similar) models at least at these levels:
Server: here you can make use of Domain Driven Design. You will have an object Booking that is responsible for its logic and contain all properties and methods like e.g. MarkAsCancelled. You can use Entity Framework to use the same object in the database, which will correspond to a database table. EF allows you to mark some properties as not being saved in the DB. Also you can set up EF in the DbContext class and thus not use DB specific attributes in the class. So one object for DB and backend business logic.
API: obviously you cannot send your domain object to the API, e.g. REST. In the API you may want to combine properties of several domain objects or hide some properties. You will have to define a set of Data Transfer Objects (DTOs), e.g. BookingDto. How to convert your domain objects to DTOs? Solutions like AutoMapper may help. You just set up convertion rules once.
Now you can describe your API in e.g. Swagger. With Swagger Codegen you can than generate code for your server (.net) and client (e.g. JS).
In the end you will have to support the following:
API definition (e.g. Swagger). Code for server DTOs and client
objects is autogenerated. You modify API definition once, both sides
get new objects.
DDD Models that also are used for the Database. They
may be faily independent from your DTOs. Mapping is handled for you
semi-automatically by e.g. Automapper
All said is just a suggestion. All the layers and number of objects can and should be adapted to the specific needs of your project. E.g. you may want to use separate objects for the database if you are not using a relational mapper like EF or do not want to mix DB and logic.
Is it possible to tell if a schema is being used to denormalize data or if it's being used to normalize data from within the processStrategy and idAttribute methods of the schema definitions?
It would be easy to determine this later but I am curious if it is possible from within these methods. This would allow me to normalize / denormalize using the same schemas rather than creating a new schema for each process, as described in the solution here.
processStrategy is only used during normalization.
Otherwise, no.
I want to avoid getters/setters hell in my entities (here is the reason: http://ocramius.github.io/doctrine-best-practices/#/53), but both most popular admin panel generators:
Sonata and DoctrineORMAdminBundle
https://github.com/javiereguiluz/EasyAdminBundle
need getters and setters to render view.
My idea is to create DTO object instead (http://ocramius.github.io/doctrine-best-practices/#/57) and then use named constructors to create entities. I want to call named constructor inside my service. What is the best way to force admin panel generators to use my DTOs to persist/update data, can you give me an idea and/or example of good practices in that case?
The only way I imagined is to use DTO instead of real Entity, call prePersist/preUpdate hooks and use custom service, but it looks confusing.
One of the most important aspect of DDD is to correctly identify your bounded contexts (usually aligned with your sub-domains) and determine the appropriate technologies and architectures to use within those.
An admin panel sounds like something generic that would be very CRUD in nature. If that's the case then don't try to fight it and embrace CRUD within that BC. Trying to implement a pure domain model in a BC where it isn't needed would make things more complicated than they need to be.
However, if you determined that the complexity justifies a domain model then I would advise against using a code generator. Properly modeling the reality of a complex domain is not an easy task, and certainly not one that could be achieved by a tool.
Would it be possible to create a similar entity based on another one? For example, what if I'd like to have user specific tables that are based on one entity. Without any ORM I would just create the same table with a different prefix and do the queries on the table with the specific prefix.
Not sure how to tackle the problem with Symfony 2.5 and Doctrine and I just can't find a concrete example anywhere around, but seems like the solution might be around the Doctrine Event Manager and the Load ClassMetadata event. I just can't make sense out of the documentation.
Without exactly knowing how your schema looks or what you're trying to achieve, it's hard to give a precise answer. But let's try:
If you have two entities which share a common set of properties, but differ in others, you basically do the typical OOP inheritance thing, you create an abstract parent class with the common stuff, and two children with their specific properties.
In Doctrine, there are different inheritance strageties. Read about them at http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html
Each of them has their pros and cons. Basically, you can select if you want everything to be in one or in two tables. Set up a test case and check what works better for you.
Note: The class properties in an abstract superclass (no matter which strategy) must always be private.
I really like where symfony 2 is headed, I just really dont like doctrine, I love codeigniters active record db system, is there anyway I can completely remove doctrine from symfony and replace it with a DAL like of codeigniters ?
Doctrine 2 is a pure Data Mapper pattern implementation. Its advantage over Active Record is that you don't have to bend your model to a database schema or vice versa. In most cases your model and schema may evolve separately; you'll need to update the mapping metadata only.
Plus you don't have to extend/implement any special classes/interfaces. Your model consists of POPOs (Plain Old PHP Objects) and the mapping is managed by an external object — an entity manager. This allows for good OO design on the PHP side and good schema design on the database side.
So, I suggest you rethink your desire to go back to Active Record. It may take some time for the paradigm shift but it's worth it.
The thing that Doctrine is a default choice doesn't mean it's the only one. It's not tightly coupled to Symfony and can be replaced.
Symfony provides sensible defaults but gives you the freedom to change them.
For example, you might use Propel. It implements Active Record (as opposed to Doctrine2).
You can write your own ORM implementation if you'd like to.
Note that apart from ORM, Doctrine has some useful helper libraries. For example annotation reader is used in Symfony to parse annotations. If you use them you'll need this part of Doctrine.