I am having some trouble finding the best way to set up my Core Data Model... Let me explain my current situation...
I have four entities
1)Game
2)Team
3)Player
4)PlayerStats
Each Team holds Players, and the teams play Games.
PlayerStats include things such as pointsScored,minutesPlayed,etc just basically stats that are related to things directly in a certain game.
I need to figure out where/when to insert the PlayerStats Entity in the ManagedObjectContext. Obviously each PlayerStats entity has to hold a reference back to the Player entity it came from.
The database needs to be set up such that I can go back and look at a Team then look at its players,then look at the players games it has participated in, then see that players stats for that specific game...
I'm not sure I followed that whole discussion, but I certainly got enough to offer you this advice as an answer.
Do not think of your Core Data model independently. Core Data provides complete object graph management, which includes persistence.
If I were you, I'd sit down with my design, and design the objects, their relationships, and the whole thing without even thinking about core data or a database. First settle on a proper design for all your objects, data, interactions, API, etc., etc.
Then, when you have your design, you should be able to immediately determine your entities, relationships, and attributes. Basically, if your core data model does not just obviously fall out of your design, then your design is probably lacking. Go back and iterate on your design.
You should be able to pretty much complete your entire design without even considering Core Data as much more than an implementation detail.
Related
I was asked to implement CQRS/Event sourcing patterns into a legacy web application, in order to prepare to migrate it from a monolithic/state oriented model to a distributed, service oriented app.
I have some questions on how I can design a Domain oriented code bundle that would connect the legacy entities strongly coupled to database, with a new Event sourced model.
The first things I did were:
writing a small "framework" for CQRS/ES, with classes like AggregateRoot, DomainEvent, Command, Handlers, Messaging, Eventstore, AggregateIds, etc.
trying to group and "migrate" the legacy Entities into some Aggregates to reconstruct all the history and states of the app into EventSoourced Aggregates
plug some Commands dispatching in the old controllers in order to let the app work as is, but also to feed the new CQRS/ES system on the side.
The context:
The legacy app contains several entities, mapped to database, that hold the model layer. (Our domain is Human resources (manpower).
Let's say we have those existing entities:
Worker, with various fields and related entities (OneToOne, OneToMany), like
name
address 1-1
competences 1-N
Society, in which worker works, with various fields and related entities (OneToOne, OneToMany), like
name
address 1-1
hours
Contract, with various fields and related entities (OneToOne, OneToMany), like
address 1-1
Worker 1-1
Society 1-1
documents 1-N
days 1-N
hours
etc.
From this legacy model, I designed a MissionAggregate that holds:
A db independent ID, like UUID
some Value objects: address, days (they were an entity in the legacy model, they became VOs here)
I also designed a WorkerAggregate and a SocietyAggregate, with fields and UUIDS, and in the MissionAggregate I added:
a reference to WorkerAggregate's UUID
a reference to SocietyAggregate's UUID
As I said earlier, my aim is to leave the legacy app as is, but just introduce in the CRUD controller's methods some calls to dispatch Commands to the new CQRS system.
For example:
After flushing newly created Contract in bdd, I want to dispatch a "CreateMissionCommand" to the new command bus.
It targets the appropriate Command Handler, that handles all the command's data, passes it to a newly created Aggregate with a new UUID and stores "MissionCreatedDomainEvent" in the EventStore.
The DomainEvent is indexed with an AggregateId, a playhead, and has a payload which contains the fields necessary to be applied to and build the MissionAggregate.
The newly Contract created in the app has now its former lifecycle, as usual, with all the updates that the legacy app does on it. But I also need to reflects all those changes to the corresponding EventSourcedAggregate, so every time there is a flush in database in the app, I dispatch a Command that translates the "crud like operations" of the legacy app into a Domain oriented /Command oriented pattern.
To sum up the workflow is:
A Crud legacy operation occurs and flushes some changes on the Contract Entity
In just a row of code in the controller, I dispatch a command built with necessary fields (AggregateId of the MissionAggregate... that I need to have stored somewhere... see next problems) to the Domain command bus, so that the impact on the existing code base is very low.
The bus passes the command to the corresponding command handler
The handler loads the aggregate and applies the changes it by calling the appropriate Aggregate method
then after some validation, the aggregate raises and stores the appropriate event
My problems and questions (some of them at least) are:
I feel like I am rewriting all big portions of the legacy app, with the same kind of relations between the Aggregates that I have between the Entities, and with the same type of validations, checks etc.
Having references, to both WorkerAggregate and SocietyAggregate UUID in MissionAggregate implies that I have to build those aggregate also (hence to dispatch commands from legacy app when the Worker and Society entities are flushed). Can't I have only references to Worker's entity id and Society's entity id?
How can I avoid having a eternally growing MissionAggregate? The Contract Entity is quite huge, it has a lot of fields that are constantly updated (hours, days, documents, etc.) If I want to store all those events, I need to have a large MissionAggregate to reflect all those changes; and so I need to have a tons of CommandHandlers that react to all the Commands of add, update, etc. that I am going to dispatch from the legacy app.
How "free" is an Aggregate from the Root entity it is supposed to refer to ? For example, a Contract Entity needs to relate somewhere to it's related Mission Aggregate, like for example when I want to dispatch a Command from the app, just after the legacy code having flushed something on the Entity. Where to store this relation? In the Entity itself, in a AggregateId field? in the Aggregate, should I have a ContractId field? Or should I have some kind of Mapping Table somewhere that holds the relationship between Contract ID and MissionAggregate ID?
What to do with the past? Should I migrate all the existing data through a script that generates Aggregates and events on all the historical data?
Thanks in advance for your time.
You have a huge task ahead of you, let's try to break it down.
It's best to build this new part of the system in isolation from the legacy codebase, otherwise you're going to have your hands tied in every turn of the way.
Create a separate layer in your project for these new requirements. We're going to call it "bubble" from now on. This bubble will be like a greenfield project, with its own structure, dependencies, etc. There will be no direct communication between the bubble and the legacy; communication will happen through another dedicated translation layer, which we'll call "Anti-Corruption Layer" (ACL).
ACL
It is like an API between two systems.
It translates calls from the bubble to the legacy and vice-versa. Its purpose is to prevent one system from corrupting or influencing the other. This way you can keep building/maintaining each system independently from each other.
At the same time, the ACL allows one system to consume the other, and reuse logic, validations, rules, etc.
To answer your questions directly:
I feel like i am rewriting all big portions of the legacy app, with the same kind of relations between the Aggregates that i have between the Entities, and with the same type of validations, checks etc.
With the ACL, you can resort to calling validations and reuse implementations from the legacy code. This will allow you time to rewrite things as needed or as possible.
You may not need to rewrite the entire system, though. If your goal is to implement CQRS and Event Sourcing and you can achieve this goal by keeping most or part of the legacy system, I would say you do it. Unless, of course, one of the goals is to completely replace the old system. Otherwise, keep it; write as less code as possible.
Suggested workflow:
Keep the CQRS and Event Sourcing system in the bubble
Do not bring these new frameworks into legacy
Make the lagacy Controller issue method calls to the ACL
The ACL will convert these calls into Commands and dispatch them
Any events will be caught by your Event Sourcing framework
Results will be persisted to the bubble's database
The bubble's database can be a different schema in the same database or can be a different database altogether. But you'll have to think about synchronization, and that's a topic of its own. To reduce complexity, I recommend a different schema in the same database.
Having references, to both WorkerAggregate and SocietyAggregate UUID in MissionAggregate implies that i have to build those aggregate also (hence to dispatch commands from legacy app when the Worker and Society entities are flushed). Can't i have only references to Worker's entity id and Society's entity id?
How can i avoid having a eternally growing MissionAggregate ? The Contract Entity is quite huge, it has a looot of fields that are constantly updated (hours, days, documents, etc.) If i want to store all those events, i need to have a large MissionAggregate to reflect all those changes; and so i need to have a tons of CommandHandlers that react to all the Commands of add, update, etc that i am going to dispatch from the legacy app.
You should aim for small aggregates. Huge aggregates are likely to degrade performance and cause concurrency problems.
If you anticipate having a huge aggregate, it is best to rethink it and try to break it down. Ask what fields/properties change together - these are possibly a different aggregate.
Also, when you speak about CQRS, you generally lean towards a task-based way of doing things in your system.
Think of a traditional web application, where you have a huge page with lots of fields that are all sent to the server in one batch when the user saves.
Now, contrast it with a modern web app where the user changes small portions of data at each step. If you think about your system this way you'll find those smaller aggregates.
PS. you don't need to rebuild your interfaces for this. If your legacy system has those huge pages, you could have logic in the controllers to detect which fields were changed and issue the appropriate commands.
How "free" is an Aggregate from the Root entity it is supposed to refer to ? For example, a Contract Entity needs to relate somewhere to it's related Mission Aggregate, like for example when i want to dispatch a Command from the app, just after the legacy code having flushed something on the Entity. Where to store this relation ? In the Entity itself, in a AggregateId field ? in the Aggregate, should i have a ContratId field ? Or should i have some kind of Mapping Table somewhere that holds the relationship between Contract ID and MissionAggregate ID?
Aggregates represent a conceptual whole. They are like atoms, indivisible things. You should always refer to an aggregate by its Root Entity Id, and never to a Child Entity Id: looking from the outside, there are no children.
An aggregate should be loaded as a whole and persisted as a whole. One more reason to have small aggregates.
An aggregate can be comprised of a single entity. Or it can have more entities and value objects, forming a graph, but one entity will be elected as the Root and will hold references to its children. Child entities and value objects should not hold references to their parents. The dependency is not bi-directional.
If Contract is an entity inside the Mission aggregate, the Contract should not have a reference to its parent.
But, if your Contract and Mission are different aggregates, then they can reference each other by their Ids.
What to do with the past? Should i migrate all the existing datas through a script that generates Aggregates and events on all the historical data?
That's a question for the business experts. Do they need it? If they don't, then don't implement it just for the sake of doing so. Every decision you make should be geared towards satisfying a business need and generating real value for it, considering the costs and tradeoffs.
Some people say that code is a liability, not an asset, and I aggre to some extent: every line of code you write needs to be tested and supported. Don't write any code that is not really necessary.
Also, have a look at this article about the Strangler Pattern, which shows how to migrate a legacy system by gradually replacing specific pieces of functionality with new applications and services.
If you have a chance, watch this course at Pluralsight (paid): Domain-Driven Design: Working with Legacy Projects. The author presents practical approaches for dealing with this kind of task.
I hope this has given you some insight.
I don't want to spoil your game. Everybody knows how cool it is to rewrite something from scratch. It's a challenge, it's fun, it's exciting. However...
migrate it from a monolithic/state oriented model to a distributed, service oriented app
CQRS/Event Sourcing won't solve any of your problems and it won't help you distribute the app in any reasonable way. If you just generate events on the CRUD operations you'll have a large tangled mess of dependencies between each part. Every part that needs data will have to call a couple of "services" (i.e. tables) to get it, than push data elsewhere, generate events1 that some other parts will react to. It will be a mess. Usually this is called a distributed monolith.
This is also the reason you already see problems with it. These problems won't go away, because you are essentially building the same system in the same way, but this time it'll be more complex.
Where to go from here
The very first thing is always: have a clear goal. You want a service oriented architecture you said. Why? Are there parts that need different scaling, different resources? Are they managed by different teams with different life-cycles? Etc.? Maybe you already have all this, I don't know, but if not, that's your first task.
Then. The parts you do want to pull out can't be just CRUD things. Those will not be independent, so whether your goal (see point above!) is scaling or different team, you won't reach your goal! To be independent you'll have to pull out the behavior with the data, and in a way that the service can operate on its own.
You can't just throw buzzwords at it and hope for the best. I'd suggest to just ignore all the hype and buzzwords and think about the goal you want to reach.
For example: I need a million workers to log their time in under 10 minutes total. So that means I need a "service" to enable worker to log their time with a web interface. So let's create that as a complete independent piece with its own database so it can be scaled to a 100 nodes when it needs to be. Export data to billing automatically every hour or so.
I am trying to learn some Core Data, and i have limited knowledge in general when it comes to databases (which i know Core Data is not, it's an 'Object Graph Manager') so i am in somewhat deep need of some help to figuring out what exactly i need to store, and where. I have three entities that i would like to create in my model:
Team
Player
GameResult
A team has the attribute teamName (string), but a team (in this case) should also have 4 players associated with it. This is where it already gets tricky for me to understand: How do i add/represent players (objects) as attributes within the Team entity?
The Player entity will for now only have an attribute of name as a string and preferably a unique ID(?) - to be able to keep track of individual results later on.
A GameResult however will have a few more attributes:
homeTeam
awayTeam
homeTeamScore
awayTeamScore
dateForPlayedGame
Both homeTeam and awayTeam i imagine should be an instance of a entity type Team which i also do not understand how i could represent. I'm guessing i will need to set up a few relationships as well: a team can have many players (4 in my case) and a player can belong to many teams (not the homeTeam and awayTeam in the same game though).
I would really appreciate some thoughts and guidance on how this model could be set up.
Edit: I should probably have an Entity of Game. Should i have this instead of GameResultand let the gameResult be an attribute of Gameor should i still have GameResultas an entity? What do you guys think? As i mentioned before: I have very limited knowledge about databases (in general)...as everyone can see.
How do i add/represent players (objects) as attributes within the Team entity?
You want to have a "one to many" relationship between Team and Players. Your model, when you create the one-may relationship, will automatically place an NSSet in your managed object that contains a list of players on the team.
The Player entity will for now only have an attribute of name as a string and preferably a unique ID(?) - to be able to keep track of individual results later on.
I know it sounds strange but don't worry about the unique ID. Core Data will handle that for you and you'll never miss it. You have to take this one on faith until you see it in action ;)
Both homeTeam and awayTeam i imagine should be an instance of a entity type Team which i also do not understand how i could represent.
I would probably think in terms of an attribute in the Team entity indicating "Home or Away". But there are other options if you don't like that one. I just think for for something that simple with only two possible values, this is probably the easy thing to do. There is nothing to prevent using the same entity for both.
Edit: I should probably have an Entity of Game. Should i have this instead of GameResultand let the gameResult be an attribute of Gameor should i still have GameResultas an entity? What do you guys think? As i mentioned before: I have very limited knowledge about databases (in general)...as everyone can see.
Not sure what the difference would be. Seems to me like a Game entity that included whatever the attributes are for "Game result" would make sense. A game always has a result and a result is always of a game. So, I don't see why you'd need both.
I don't want to say you're better off without general database knowledge, but you are almost. I had to forget just about everything I knew about SQL Server to be able to grasp Core Data.
The best thing I can say is that once "the light comes on" it will be simple and make perfect sense to you. My biggest problem was in having to unlearn a lot of what I knew about relational databases coming in.
Main thing I can say is remember that everything is about the managed object. You build your relationships into the model, and from then on you're dealing with NSSets of managed objects for the related entity.
Truthfully, it just makes too much sense to be easy to understand ;)
NOTE: One of the best things you can do is tinker with setting up the model, then generate your entity classes Editor | Create NSManaged Object Subclasses. Then study those classes and understand each of the relationship sets in them. That's what made things come clear to me, at least.
GLTY.
I have Meeting objects that form the basis of a scheduling system, of which gridviews are used to display the important information. This is for the purpose of scheduling employees to meetings, and for employees to view what has been scheduled.
I have been trying to follow DDD principles, but I'm having difficulty knowing what to pass from my service layer down to presentation area of system. This is because the schedule can be LARGE, and actually consists of many different elements of the system. Eg. Client Name, Address, Case Info, Group,etc, all of which are needed for the meeting scheduler to make a decision.
In addition to this, the scheduler needs to change values within this schedule and pass it back up to the service layer (eg. assign employees from dropdowns, maybe change group, etc). So, the information isn't really "readonly" - it needs to be interacted with. ie. It's not just a report.
Our current approach is to populate a flattened "Schedule Object" from SQL, which is constructed from small parts of different domain objects. It's quite a complex query. When changes have been made, this is then passed back up to the service layer, and the service will retrieve the domain objects in question, and fire business methods on the domain objects using information from the DTOs.
My question is, is this the correct approach? ie. Continue to generate large custom objects from SQL, and then pass down from Service Layer to Presentation Layer objects that feel a lot like View Models?
UPDATE due to an answer
To give a idea of the amount entities / aggregates relationships involved. (this is an obfuscated examples, so relationships are the important things here)
Client is in one default group
Client has one open case but many closed
Cases have many Meetings
Meeting have many assigned Employees
Meeting have many reasons
Meeting can get scheduled to different groups
Employees can be associated with many groups.
The schedule need to loads all meetings in open cases that belong to patients who are in the same groups as the employee.
Scheduler can see Client Name, Client Address, Case Info, MeetingTime, MeetingType, MeetingReasons, scheduledGroup(s) (showstrail), Assigned Employees (also has hidden employee ids).
Editable fields are assign employee dropdowns and scheduled group.
Schedule may be up to two hundred rows.
DTO is coming down from WCF, so domain model is accessed above this service layer, and not below.
Domain model business calls leveraged by service based on DTO values passed back, and repositories deal with inserts/updates.
So, I suppose to update, is using a query to populate an object which contains all of the above acceptable to pass down as one merged DTO? And if not, how would you approach it? ( giving some example calls to service layer, and explaining a little bit about how you conceive the ORM fetching the data keeping in mind performance)
In the service layer and below, I would treat each entity (see aggregate roots in DDD) separate with respect to it's transactional boundary. I.e. even if you could update a client and a case in the same UI view, it would be best to transactionally modify the client and then modify the case. The more you try to modify in one transaction, the more you can conflict with other users.
Although your schedule is large and can contain lots of objects, the service layer should again deal with each entity (aggregate root) separately and then bundle them together into a new view model. Sadly, on brown-field projects, a lot of logic might be in the SQL and the massive multi-table joins might make this harder to refactor into more atomic queries that do exactly what is needed. The old-school data-centric view of 'do everything you can in the database' goes against everything DDD.
Because DDD is a collection of design ideas and patterns and not particularly a methodology or an architecture, it sounds that it might be too late to try shoe-horn your current application into a DDD application-centric design. It sounds as though your current app is very entrenched in the data-centric view.
If everything is currently being passed up through the layers in one monolithic chunk, it might be best to keep with this style and just expose these monolithic chunks to the people in the other team who wish to consume them, for use in their new app. You might be able to put some sort of view model caching in place (a bit like the caching view model element in CQRS).
In my personal opinion, data-centric, normalised data apps have had their day (they made sense in the 1970s when hard disk space was expensive) and all apps should be moving toward more modern practices. In reality, only when legacy systems are crawling on their knees, will stakeholders usually put up the cash to look for alternatives (usually after stuffing every last server with RAM). It might be possible or best to convince them to refactor small sections at a time.
I´m a little confused about inheritance and relationships in core data, and I was hopping someone could drive to the right path. In my app i have created 3 entities, and none of them have (and are not suppose to have) common properties, but there´s gonna be a save and a load button for all the work that the user does. From my understanding I need to "wrap" all the entities "work" into an object which will be used to save and load, and my question is, do I need to create relationships between the entities? Because I have to relate them somehow and this is what make sense to me. Is my logic correct?
I'm implementing a budget calculator, and for the purpose of everyone understand what my issue is, I´m going to give an practical example and please correct me if my logic is incorrect:
Let´s just say you are a fruit seller, and because of that it´s normal to have a database of clients and also a fruit database with the kinds of fruit you sell. From my understanding I find two entities here:
Client with properties named: name, address, phone, email, etc.
Stock with properties named: name, weight, stock, cost, supplier, etc.
TheBudget with properties named: name, amount, type, cost, delivery, etc.
I didn´t put all the properties because I think you get the point. I mean as you can see, there´s only two properties I could inherit; the rest is different. So, if I was doing a budget for a client, I can have as many clients I want and also the amount of stock, but what about the actual budget?
I´m sorry if my explanation was not very clear, but if it was..what kind of relationships should I be creating? I think Client and TheBudget have a connection. What do you advise me?
That's not entirely correct, but some parts are on the right track. I've broken your question down into three parts: relationships, inheritance and the Managed Object Context to hopefully help you understand each part separately:
Relationships
Relationships are usually used to indicate that one entity can 'belong' to another (i.e. an employee can belong to a company). You can setup multiple one-to-many relationships (i.e. an employee belongs to a company and a boss) and you can setup the inverse relationships (which is better described with the word 'owns' or 'has', such as 'one company has many employees).
There are many even more complicated relationships depending on your needs and a whole set of delete rules that you can tell the system to follow when an entity in a relationship is deleted. When first starting out I found it easiest to stick with one-to-one and one-to-many relationships like I've described above.
Inheritance
Inheritance is best described as a sort of base template that is used for other, more specific entities. You are correct in stating that you could use inheritance as a sort of protocol to define some basic attributes that are common across a number of entities. A good example of this would be having a base class 'Employee' with attributes 'name', 'address' and 'start date'. You could then create other entities that inherit from this Employee entity, such as 'Marketing Rep', 'HR', 'Sales Rep', etc. which all have the common attributes 'name', 'address' and 'start date' without creating those attributes on each individual entity. Then, if you wanted to update your model and add, delete or modify a common attribute, you could do so on the parent entity and all of its children will inherit those changes automatically.
Managed Object Context (i.e. saving)
Now, onto the other part of your question/statement: wrapping all of your entities into an object which will be used to save and load. You do not need to create this object, core data uses the NSManagedObjectContext (MOC for short) specifically for this purpose. The MOC is tasked with keeping track of objects you create, delete and modify. In order to save your changes, you simply call the save: method on your MOC.
If you post your entities and what they do, I might be able to help make suggestions on ways to set it up in core data. You want to do your best to setup as robust a core data model as you can during the initial development process. The OS needs to be able to 'upgrade' the backing store to incorporate any changes you've made between your core data model revisions. If you do a poor job of setting up your core data model initially and release your code that way, it can be very difficult to try and make a complicated model update when the app is in the wild (as you've probably guessed, this is advice born out of painful experience :)
I am currently taking a course that gives an introduction to project planning. It is mostly about how to draw UML diagrams (blegh), but also has a few other topics.
One part in particular keeps bugging me. In the course they describe a method for going from a set of requirements to an initial class diagram, but everything about the method gives me this feeling that it is most definitely not the way to go. Let me first give an example before proceeding.
Let's consider a system that manages a greenhouse company. The company has multiple greenhouses, and every employee is assigned to his/her own greenhouse. A greenhouse has a location and a type of plant being grown in there. An employee has a name and phone number.
Here's what according to the course's method the class diagram would look like:
To me this looks like a database layout adapted for code. When I go about designing a program, I try to identify major abstractions. Like all the code that interacts with the database or the code that is responsible for the GUI are all different parts of the system. That would be what I consider to be an initial class diagram.
I simply can not imagine that this is a common way to start designing the architecture of a project. The classes look ugly, since if you take a slightly larger example the classes will be flooded with responsibilities. To me they look like data objects that have functionality to them they shouldn't have. It does not give me a clue on how to continue from here and get a general architecture going. Everything about it seems obsolete.
All I want to know if there's someone out there that can tell me if this is a common way to get a first class diagram on paper for reasons I am overlooking.
I would say it's reasonable to start with a logical model that's free of implementation constraints. That logical model is not necessarily concerned with physical implementation details (e.g. whether or not to use a database, what type of database, OS / UI choice, etc.) and thus represents just "real" business domain objects and processes. The similarity to a potential database implementation shouldn't be surprising for the simple example.
By understanding your business domain (through the logical model you've started to construct), you will be better placed to subsequently identify, for example, which architectural patterns are appropriate, what screens you need to build, and database elements to design. Possibly, there will be another part of the course that will aid you in this stage.
In practice, you will often know that you're intending to implement, say, a web-based application using MVC with a back-end database, and may look to model the implementation classes in parallel with your business items. For your course to use a method that emphasises the distinction between logical and physical stages doesn't sound unreasonable.
When I go about designing a program, I try to identify major
abstractions
Same principle in UML as well. You represent abstractions and their relationships and due to existing Visual Tools you can do a presentation of a system to stakeholders or even generate automatically stubs from your design.