Managing an Ordered Core Data Relationship Using NSArrayController - cocoa

All those “NSOrderedSet was added later and thus doesn’t have to play nice with other components” bugs drive me crazy…
(https://twitter.com/kubanekl/status/413447039855640576)
I have two managed objects and an ordered 1:N relationship between them, which is backed by an instance (or more precise a subclass) of NSOrderedSet. I want to manage this relationship using a NSArrayController in order to profit from features it offers (selection management, binding of the content, bindings to views like NSTableView).
Since NSOrderedSet is not a subclass of NSSet, the contentSet binding of NSArrayController doesn't work with that relationship. I found following thread and tried to implement the suggestions mentioned there.
The first suggestion is to use the contentArray binding and a value transformer for transforming the ordered set to an array on the fly. The problem with this solution is the reassigning of the content each time a change is made, which is not what I want.
The second suggestion provided in the mentioned thread is to use the contentArray binding and apply the #array operator to the model key path. I've tried that, but the underlying relationship was not touched at all when adding/removing objects through the NSArrayController.
Another option I found is using sort descriptors with the contentSet binding. This would require making the relation unordered in order to make the contentSet binding work and introducing a new attribute used especially for managing the order. This would furthermore require a custom ordering mechanism to implement and it would mess up the model. Honestly said, I would like to avoid this solution.
My question is pretty clear: Is there any way to manage an ordered Core Data relationship using NSArrayController? If so, which is the best way causing as little pain as possible?

It is indeed very sad that NSArrayController does not come with support for ordered relationships. As a keen observer to the bindings technology I find it sub optimal that it seems that Apple has "abandoned" it without saying anything. The last notable change that Apple introduced with regards to bindings are NSTreeController bug fixes. That was I believe with 10.6/10.7. It seems that Apple does not want to touch the bindings technology anymore. I am not sure why because bindings are really great sometimes. They can be the "90% solution". During prototyping this is fine. I am using bindings where it makes sense and having NSArrayController with ordered relationships support would be something great.
Most of the solutions that have been mentioned already are no real solutions. But this depends. Here is something to think about:
If you are planning to support iCloud then you should not/cannot use ordered relationships anyway because Core Data on iCloud does not support them.
Since ordered relationships are fairly new and the desire for a ordered collection of objects existed long before them, there must be a way in Core Data to mimic ordered relationships. You have already pointed out what 99.9% of the Core Data eating world did before ordered relationships were available: Sort by an additional attribute. You have pointed out that this is messing up the model but I disagree: It is true that you have to add an additional attribute to your model which does not necessarily "represent" true model data. But how many ordered relationships are you planning to have in your model? Usually you don't have that many per application. Even though it feels a bit dirty this is what has been done by lots of people for at least three major releases of Core Data (10.4, 10.5 and 10.6). Even today this solution is used for backwards compatibility or if you want to use iCloud. It is a "pragmatic" solution. Not a nice one but pragmatic. Also please not: Even if you were using ordered relationships the order of your objects has to be stored somewhere. If you are using the SQLite store then having an ordered relationship causes the NSSQLiteStore to create an additional column for you. The column has the name: Z_FOK_$RELATIONSHIPNAME. So by using ordered relationships you are merely doing something that is done for you under the hood anyways. This means that it does not really matter from a pure technical perspective if you are using ordered relationships or an additional attribute. The underlying technical problems remain the same. Ordered relationships are no magic.
If you are planning to go with the "additional attribute" solution be aware that you have to adjust the value of this attribute a lot: Every time the user is changing the ordere via drag and drop you have to modify the value of the attribute. This seems wasteful but it really isn't. Even the worse case: A user who is exchanging the object at row 0 with an object at the last possible row does only cause 2 attribute changes. The complexity of the trivial solution for changes needed to represent any change that can be made by drag and drop in a table view is O(n) where n is the number of selected rows. This is really not that bad since users are usually not reordering 10000000 rows at once and even then there are smarter algorithms out there which are not that hard to implement.
If you are looking the for cleanest solution you should subclass NSArrayController and add a "orderedContentSet" bindings yourself. You can find out how to do that by reading the Cocoa Bindings Programming topic guide. The guide contains an example: https://developer.apple.com/library/mac/documentation/cocoa/conceptual/CocoaBindings/Concepts/HowDoBindingsWork.html (Listing 2). The bad thing about this is that you are subclassing NSArrayController which is usually a no go. Many people tend to subclass NSArrayController for reasons that don't justify subclassing it. In this case however subclassing NSArrayController is justified if you want to go with the cleanest solution.
For 3. there are generic solutions out there which do a lot of the stuff for you. Don't use them.

Related

Laravel Repository pattern and many to many relation

In our new project we decided to use hexagonal architecture. We decided to use repository pattern to gain more data access abstraction. We are using command bus pattern as service layer.
In our dashboard page we need a lot of data and because of that we should use 3 level many to many relations (user -> projects -> skills -> review) and also skills should be active(status=1).
The problem rises here, where should i put this?
$userRepository->getDashboardData($userId).
2.$userRepository->getUser($userId)->withProjects()->withActiveSkills()->withReviews();
3.$user = $userRepository->getById();
$projects = $projectRepository->getByUserId($user->id);
$skills = $skillRepository->getActiveSkillsByProjectsIds($projectIds);
In this case, I couldn't find the benefits of repository pattern except coding to interface which can be achived with model interfac.
I think solution 3 is prefect but it adds a lot of work.
You have to decide (for example) from an object-oriented perspective if a "User" returned is one that has a collection of skills within it. If so, your returned user will already have those objects.
In the case of using regular objects, try to avoid child entities unless it makes good sense. Like, for example.. The 'User' entity is responsible for ensuring that the child entities play by the business rules. Prefer to use a different repository to select the other types of entities based on whatever other criteria.
Talking about a "relationship" in this way makes me feel like you're using ActiveRecord because otherwise they'd just be child objects. The "relationship" exists in the relational database. It only creeps into your objects if you're mixing database record / object like with AR.
In the case of using ActiveRecord objects, you might consider having specific methods on the repository to load the correctly configured member objects. $members->allIncludingSkills() or something perhaps. This is because you have to solve for N+1 when returning multiple entities. Then, you need to use eager-loading for the result set and you don't want to use the same eager loading configuration for every request.. Therefore, you need a way to delineate configurations per request.. One way to do this is to call different methods on the repository for different requests.
However, for me.. I'd prefer not to have a bunch of objects with just.. infinite reach.. For example.. You can have a $member->posts[0]->author->posts[0]->author->posts[0]->author->posts[0].
I prefer to keep things as 'flat' as possible.
$member = $members->withId($id);
$posts = $posts->writtenBy($member->id);
Or something like that. (just typing off the top of my head).
Nobody likes tons of nested arrays and ActiveRecord can be abused to the point where its objects are essentially arrays with methods and the potential for infinite nesting. So, while it can be a convenient way to work with data. I would work to prevent abusing relationships as a concept and keep your structures as flat as possible.
It's not only very possible to code without ORM 'relationship' functionality.. It's often easier.. You can tell that this functionality adds a ton of trouble because of just how many features the ORM has to provide in order to try to mitigate the pain.
And really, what's the point? It just keeps you from having to use the ID of a specific Member to do the lookup? Maybe it's easier to loop over a ton of different things I guess?
Repositories are really only particularly useful in the ActiveRecord case if you want to be able to test your code in isolation. Otherwise, you can create scopes and whatnot using Laravel's built-in functionality to prevent the need for redundant (and consequently brittle) query logic everywhere.
It's also perfectly reasonable to create models that exist SPECIFICALLY for the UI. You can have more than one ActiveRecord model that uses the same database table, for example, that you use just for a specific user-interface use-case. Dashboard for example. If you have a new use-case.. You just create a new model.
This, to me.. Is core to designing systems. Asking ourselves.. Ok, when we have a new use-case what will we have to do? If the answer is, sure our architecture is such that we just do this and this and we don't really have to mess with the rest.. then great! Otherwise, the answer is probably more like.. I have no idea.. I guess modify everything and hope it works.
There's many ways to approach this stuff. But, I would propose to avoid using a lot of complex tooling in exchange for simpler approaches / solutions. Repository is a great way to abstract away data persistence to allow for testing in isolation. If you want to test in isolation, use it. But, I'm not sure that I'm sold much on how ORM relationships work with an object model.
For example, do we have some massive Member object that contains the following?
All comments ever left by that member
All skills the member has
All recommendations that the member has made
All friend invites the member has sent
All friends that the member has established
I don't like the idea of these massive objects that are designed to just be containers for absolutely everything. I prefer to break objects into bits that are specifically designed for use-cases.
But, I'm rambling. In short..
Don't abuse ORM relationship functionality.
It's better to have multiple small objects that are specifically designed for a use-case than a few large ones that do everything.
Just my 2 cents.

aws-sdk-ruby AWS::Record::Base records sharing the same domain

We are using the aws-sdk for ruby, specifically AWS::Record::Base.
For various reasons we need to put records of various objects within the same domain in sdb.
The approach we thought we'd use here would be to add an attribute to each object that contains the object name and then include that in the where clause of finder methods when obtaining objects from sdb.
My questions to readers are:
what are your thoughts on this approach?
how would this be best implemented tidily? How is it best to add a default attribute included in an object without defining it explicitly in each model? Is overriding find or where in the finder methods sufficient to ensure that obtaining objects from sdb includes the clauses considering the new default attribute?
Thoughts appreciated.
It really depends on your problem, but I find it slightly distasteful. Variant records are fine and dandy, but when you start out with apples and dinosaurs and they have no common attributes, this approach has no benefit that I know of [aside from conserving your (seemingly pointless) quota of 250 SimpleDB domains]. If your records have something in common, then I can see where this approach might be useful, but someone scarred like me by legacy systems with variant records in Btrieve (achieved through C unions) has a hardwired antipathy toward this approach.
The cleanest approach I can think of is to have your models share a common parent through inheritance. The parent could then know of the child types, and implement the query appropriately. However, this design is definitely not SOLID and violates the Law of Demeter.

How to programmatically retrieve table selection and table row for Core Data app?

I'm trying to make a Core Data app in which when you select one "Player" in a TableView, and a list of all teammates appears in a second tableView, with a column for how many times those two players have played on the same "Team" (another entity).
This has got me completely stuck, because while I know how to fill up a table from a normal array, using ArrayControllers and Core Data has really cluttered up my view of the situation.
How would you approach this?
Yours is a Bindings problem, not a Core Data problem. :-)
You should definitely get a handle on Cocoa Bindings before dealing with Core Data. This is stated in the docs and is very true.
The subject of your question seems to differ from the body, so I'll answer both.
Showing the Teammates
Core Data aside, assume you have a table representing Player instances. Player has one Team. Team has many players. Therefore, it's inferred that an instance of Player has "team.players" (minus itself) as teammates. Whether you're using Core Data to manage the model or not, this is true of the overall relationships.
If you read through and master Cocoa Bindings, you'll find that this is not hard at all to set up using a basic Master/Detail setup (with an extra array controller for the Detail part, for simplicity). Your Master array controller represents all Player instances, while your detail array controller represents the Teammates - or the Master's selection's "team.players" (minus itself).
The Teammates array controller will have its entity and managed object context set up as usual (see the docs). The "contentSet" will be bound to the Master array controller's "selection" controller key, with "team.players" as the model key path.
The trick is to filter out the Master controller's selected player using predicates. This you can do with the array controller's Filter Predicate. Maybe one with a format of "self != %#", where "%#" represents the Master array controller's selection. I'll leave Predicates (a complicated topic unto itself) to you. Remember, you can set them in code ([myController setFilterPredicate:myPredicate]) or by using bindings. Predicates are independent of Core Data as well.
Getting Selection
Since the array controller is in charge of the array the table represents, it's best to ask the array controller what its selection is. One way is to ask its -arrangedObjets for the objects at its -selectedIndexes.
NSArray * selectedObjects = [[myArrayController arrangedObjects] objectsAtIndexes:[myArrayController selectedIndexes]];
You can also ask it for its -selectedObjects. There are differences between these two approaches that are described by the documentation (API reference and conceptual docs) that you should definitely understand, but asking the controller is the most important concept, regardless of whether you use an NSArrayController or some custom controller that conforms to the and protocols.
Disclaimer: Typed hastily after a social Sake evening. Not checked for errors. :-)

MVC Architecture. Whats in a model?

I am new to MVC but I can already see its benefits and advantages. However, I have a (probably easy to answer) design question:
I have been thinking about models and debating the proper way to structure them. The way I see it there are a few options:
1) Models and table structure have a 1 to 1 relationship...meaning that pretty much for every table there is a corresponding model. The model class has attributes corresponding to the table columns and has whatever methods that are needed (like getters and setters) to manipulate data in the table in whatever way is necessary. This seems like the generic option and I guess I would then have the controller call the models as necessary to perform whatever business function is necessary.
2) Models are tied more closely to the operation of the business logic rather than the data: so for example if on the front end a deletion of a certain object affects multiple tables, the model then 'models' this behavior and interacts with several tables and performs the necessary function. The controller then simply needs to call a single model for whatever business behavior is desired. This is less generic since the models are much more tightly coupled..but seems quicker to implement.
3) Something in between the first 2 options. Or maybe I am completely missing the point.
Hopefully this makes sense! If I am not totally missing the point, I am inclined to think that option (1) is better. Any idea?
Edit: Not that it should matter, but I plan on using Codeigniter PHP MVC framework.
Both are valid implementations, and, depending on your needs, can work well.
Your #1 is essentially describing the Active Record pattern, which is used by SubSonic, Castle, and lots of other ORM implementations.
Your #2 is essentially describing the Entity Framework/Hibernate/LightSpeed approach, where you are dealing with objects that are more conceptually related to your domain rather than to tables. Instead of your objects containing foreign key ID properties, they actually contain the other domain object references, which are then instantiated in an on-access basis.
Both ways are great. The Active Record approach is usually more intuitive for beginners and has potentially less pitfalls. EF-style can save a lot of base-level coding and dealing with FK's directly in code.
Edit: To be clear, what you describe in both situations is data access layer related, rather then strictly model related. However in reality you're pretty close, as most models tend to simply represent one or more of these types of objects.
All of the above.
The approach you use depends on your design philosophy. If you prefer to design your application using business domains and drive that into the database design, then you favor the second approach. If you prefer to build your database first, and then create model classes from the database schema, then you favor the first approach. Both methods are valid ways to build software.
Number 1 is the way to go. Option 2 is really the controller's job. For example, the controller then takes the models and performs actions on them, and passes the results to the view.
Think of it this way:
Model = your data
Controller = business logic
View = display of data and actions
This is highly simplistic, but it's how I picture it in my mind when I go to design a system.
Think of the database as the Model, the business logic as the Controller, and the UI as the View. That may help. It's an overly simplified approach to things, but it gets the data / behavior separation roughly correct.
I don't think it has to be an either/or situation. Your first point is what would be called a Model, but your 2nd point sounds like a View Model, which is most often a composition of various Models and parts of Models that will be sent to the view. The controller is responsible for doing that composition and potentially decomposition when information is sent back from the View.

Which one do you prefer for Searching/Reporting DataTable or DTO or Domain Class?

The project currently I am working in requires a lot of searhing/filtering pages. For example I have a comlex search page to get Issues by data,category,unit,...
Issue Domain Class is complex and contains lots of value objects and child objects.
.I am wondering how people deal with Searching/Filtering/Reporting for UI. As far As I know I have 3 options but none of them make me happier.
1.) Send parameters to Repository/DAO to Get DataTable and Bind DataTable to UI Controls.For Example to ASP.NET GridView
DataTable dataTable =issueReportRepository.FindBy(specs);
.....
grid.DataSource=dataTable;
grid.DataBind();
In this option I can simply by pass the Domain Layer and query database for given specs. And I dont have to get fully constructed complex Domain Object. No need for value objects,child objects,.. Get data to displayed in UI in DataTable directly from database and show in the UI.
But If have have to show a calculated field in UI like method return value I have to do this in the DataBase because I don't have fully domain object. I have to duplicate logic and DataTable problems like no intellisense etc...
2.)Send parameters to Repository/DAO to Get DTO and Bind DTO to UI Controls.
IList<IssueDTO> issueDTOs =issueReportRepository.FindBy(specs);
....
grid.DataSource=issueDTOs;
grid.DataBind();
In this option is same as like above but I have to create anemic DTO objects for every search page. Also For different Issue search pages I have to show different parts of the Issue Objects.IssueSearchDTO, CompanyIssueTO,MyIssueDTO....
3.) Send parameters to Real Repository class to get fully constructed Domain Objects.
IList<Issue> issues =issueRepository.FindBy(specs);
//Bind to grid...
I like Domain Driven Design and Patterns. There is no DTO or duplication logic in this option.but in this option I have to create lot's of child and value object that will not shown in the UI.Also it requires lot's ob join to get full domain object and performance cost for needles child objects and value objects.
I don't use any ORM tool Maybe I can implement Lazy Loading by hand for this version but It seems a bit overkill.
Which one do you prefer?Or Am I doing it wrong? Are there any suggestions or better way to do this?
I have a few suggestions, but of course the overall answer is "it depends".
First, you should be using an ORM tool or you should have a very good reason not to be doing so.
Second, implementing Lazy Loading by hand is relatively simple so in the event that you're not going to use an ORM tool, you can simply create properties on your objects that say something like:
private Foo _foo;
public Foo Foo
{
get {
if(_foo == null)
{
_foo = _repository.Get(id);
}
return _foo;
}
}
Third, performance is something that should be considered initially but should not drive you away from an elegant design. I would argue that you should use (3) initially and only deviate from it if its performance is insufficient. This results in writing the least amount of code and having the least duplication in your design.
If performance suffers you can address it easily in the UI layer using Caching and/or in your Domain layer using Lazy Loading. If these both fail to provide acceptable performance, then you can fall back to a DTO approach where you only pass back a lightweight collection of value objects needed.
This is a great question and I wanted to provide my answer as well. I think the technically best answer is to go with option #3. It provides the ability to best describe and organize the data along with scalability for future enhancements to reporting/searching requests.
However while this might be the overall best option, there is a huge cost IMO vs. the other (2) options which are the additional design time for all the classes and relationships needed to support the reporting needs (again under the premise that there is no ORM tool being used).
I struggle with this in a lot of my applications as well and the reality is that #2 is the best compromise between time and design. Now if you were asking about your busniess objects and all their needs there is no question that a fully laid out and properly designed model is important and there is no substitute. However when it comes to reporting and searching this to me is a different animal. #2 provides strongly typed data in the anemic classes and is not as primitive as hardcoded values in DataSets like #1, and still reduces greatly the amount of time needed to complete the design compared to #3.
Ideally I would love to extend my object model to encompass all reporting needs, but sometimes the effort required to do this is so extensive, that creating a separate set of classes just for reporting needs is an easier but still viable option. I actually asked almost this identical question a few years back and was also told that creating another set of classes (essentially DTOs) for reporting needs was not a bad option.
So to wrap it up, #3 is technically the best option, but #2 is probably the most realistic and viable option when considering time and quality together for complex reporting and searching needs.

Resources