Reactivecocoa doesn't recognize new instance changes - objective-c

Say I have a View that is bonded to his ViewModel like so:
View:
RAC(self.lbl, userName) = RACObserve(self.viewModel.user, userName);
This will work great! but what happens in cases when I load a new User instance and set it like so:
ViewModel:
-(void) userUpdated: (User *) user {
self.user = user;
}
In this case, the views binding will still be bonded to the old user instance! Did any one come across this and find a better way to solve this except setting all properties of the old user with the new ones...?
Thanks!!

RAC(self.lbl, userName) = RACObserve(self.viewModel, user.userName);
The comma denotes the break between the "static" part (self.viewModel) and the dynamic, changing part (user.userName).
This is a really nice feature of RACObserve, but you could implement this yourself, to modify Leo's answer so that it works with a changing userName: map not into the username, but into a signal of usernames, and then "flatten" that with switchToLatest:
RAC(self.lbl, userName) = [[RACObserve(self.viewModel, user) map:^(User *user) {
return RACObserve(user, userName);
}] switchToLatest];
This simple example isn't very useful, since RACObserve has this built in, but this technique in general is extremely powerful. You will eventually want to map into signals of not-observed-things, so I encourage you to take the time to understand why this works.

Related

Should I create an object of a class or static method to check if a db entry exists?

I'm new to OOP design concepts and was wondering what the correct approach is for the following use case (I'm developing with JavaScript and Mongo but I think the question is a general one):
I have User as a collection/table and have wrapped the interaction with this user with a class. My idea is to abstract away the DB interaction from the main program.
There are cases where I need to check if a user already exists in the DB:
If it does: use the information of this user.
If it doesn't: cary on with the flow and redirect the user to some page
Option 1: Does it make sense to create an instance of the User class just to check if it exists?
Option 2: having something like a static method in the class to do this job, but also doesn't seem right since if the user exist I want to use it's info and I would need to create it again.
Option 1:
let user = new User(name);
if (user.isExist()){
//do something with user properties
} else {
//redirect to /someRoute
}
Option 2:
if (User.isExist(name)){
let user = new User(name);
//do something with user properties
} else {
//redirect to /someRoute
}
Feedback to Option-1 and Option-2
This solution would break the Single-Responsibility and the Open-Closed principle.
When you would model your class you have to think of logic for the User and how to handle persistence-transactions. The persistence-transactions need to be changed when you switch for example from Mongo to SQL..
So lets split the logic into separate classes.
Add a new Class!
I could think of a class UserTransaction which handles the persistence-transactions.
class UserTransaction {
constructor(/*...*/) {/*...*/}
static existsWithTheName(name) {
// ...
}
}
Than your code would look like:
if (UserTransaction.existsWithTheName(name)){
let user = new User(name);
} else {
//redirect to /someRoute
}

How to keep your MVC controllers DRY for Edit->Save->ValidateFail

I've got a Manage User event that takes an an optional userID and displays a user edit screen. There is a manageUserViewModel to go with this screen.
My Manage page has some dependencies - eg, PageTitle, what method to submit to, etc.
If I validate-fail, I need to show the manage screen again, but this time, using the view-model that was passed into the same method.
Supplying these dependencies in the fail scenario isn't very DRY.
How do I step repeating the dependencies? I tried putting them into a separate method, but that does not feel right.
public ActionResult Manage(Guid? UserID)
{
User user = this._UserLogic.GetUser(UserID);
ViewBag.Title = "User List";
ViewBag.OnSubmit = "Save";
ManageUserViewModel uvm = Mapper.Map<User, ManageUserViewModel>(user);
return View("Manage", uvm);
}
[AcceptVerbs("POST")]
public ActionResult Save(ManageUserViewModel uvm)
{
User user = this._UserLogic.GetUser(uvm.UserID);
if (!ModelState.IsValid)
// This is not very DRY!!!
ViewBag.Title = "Manage User";
ViewBag.OnSubmit = "Save";
return View("Manage", uvm);
}
Mapper.Map<ManageUserViewModel, User>(uvm, user );
this._UserLogic.SaveUser(user);
return RedirectToAction("Manage", new { UserID = user.ID });
}
I think you misunderstand DRY. DRY does not mean "NEVER repeat yourself", it means that you should not repeat yourself when it makes sense not to.
Different views have different requirements, and creating a complex structure just to avoid repeating yourself violates other best practices, like KISS, and SRP.
SOLID is interesting because Single Responsibility Principle is often at odds with Don't Repeat Yourself, and you have to come up with a balance. In most cases, DRY loses because SRP is far more important.
It looks to me like you have code here that is handling multiple responsibilities just so you can avoid writing similar code more than once. I disagree with doing that, because each view has different responsibilities and different requirements.
I would suggest just creating separate controller actions, views, and models for each action, particularly if the validation requirements are different for them. There may be a few things you can do (like using Partial Views or Editor Templates) to reduce repetition, but in general don't add lots of complexity just to avoid repetition.
You could add the 'Manager User' Title and 'Save' OnSubmit strings as properties of on the ManageUserViewModel. This means that you would not have to add them to the ViewBag each time you called Save.
You could also make a ManageUserService which could be responsible for the AutoMapper mappings and saving the user.
You code would then look like this:
public ActionResult Manage(Guid? UserID)
{
var uvm = _userService.GetById(UserId);
return View("Manage", uvm);
}
[AcceptVerbs("POST")]
public ActionResult Save(ManageUserViewModel uvm)
{
if (!ModelState.IsValid)
{
return View("Save", uvm);
}
_userService.Save(uvm);
return RedirectToAction("Manage", new { UserID = uvm.ID });
}
Just put the CRUD logic and AutoMapping functionality in the a class called UserService, and instance of which can be injected using Inversion of Control into your controller.
If you don't want to hard-code your string values into the view model itself, then you could add the values to an ApplicationResources file and reference those from the view model.
You will have to find some way to preserve this information between requests, which either means passing it back and forth between the client and server or saving it on the server. Saving it on the server means something like session but this feels a little heavy to me. You could add it to your ViewModel as #Ryan Spears suggested. To me that feels a little wrong, polluting the ViewModel with something that might be considered metadata. But that is just an opinion and I am not discrediting his answer because it is valid. Another possibility would be to just add the extra fields to the parameter list of the action method itself and use hidden fields.
[AcceptVerbs("POST")]
public ActionResult Save(ManageUserViewModel uvm, string title, string onSubmit)
{
...
}
In the form add:
<input type="hidden" name="title" value="#ViewBag.Title" />
<input type="hidden" name="onSubmit" value="#ViewBag.OnSubmit" />
This is essentially the same concept and solution as adding them to the ViewModel except in this situation they are not actually part of the ViewModel.
You can use RedirectToAction() and then export and import your tempdata (to maintain the ModelState) if you're worried about the 3 lines.
Personally I'd find it a lot more readable if you kept the logic in the POST version of the method, as you're performing something slightly different from the GET method, therefore not really repeating yourself. You could you probably keep the two ViewBag variables you have inside the View, and then there's no repetition at all.
As a side note: [HttpPost] now supersedes [AcceptVerbs]
We have come up with another solution that I thought I would share.
This based on the view-model containing info on what actions it can do, but we feel the controller should be specifying these (ie, controlling what actions different links route to) these because we have cases where the view-models are reused across actions. EG, the case where when you edit you can edit a template or an instance of something - the UI is the same, the only difference is the actions you post to/cancel from.
We abstracted away the part of the view-model that contains the data bound properties and the view model that contains other things we need for the view to render. We call the property-only object a DTO - it's not a true dto because it contains validation attributes.
We figure that we might be able to re-use these DTO's in the future for ajax or even XML requests - it, can keep validation DRY.
Anyway - here is an example of the code, we are happy with it (for now) and hope it helps others.
[HttpGet]
[ValidateInput(false)]
public virtual ActionResult ManageUser(ManageUserDTO dto, bool PopulateFromObject = true)
{
User user = this._UserLogic.GetUser(dto.UserID);
if (PopulateFromObject)
Mapper.Map<User, ManageUserDTO>(user, dto);
ManageUserViewModel vm = new ManageUserViewModel()
{
DTO = dto,
PageTitle = Captions.GetCaption("pageTitle_EditUser"),
OnSubmit = GetSubmitEventData(this.ControllerName, "SaveUser"),
OnCancel = GetCancelEventData(this.ControllerName, "ListUsers"),
};
return View("ManageUser", vm);
}
[HttpPost]
public virtual ActionResult SaveUser(ManageUserViewModel vm)
{
User user = this._UserLogic.GetUser(vm.DTO.UserID);
if (!ModelState.IsValid)
{
return ManageUser(vm.DTO, false);
}
Mapper.Map<ManageUserDTO, User>(vm.DTO, user);
this._UserLogic.SaveUser(user);
TempData.AddSuccess(Captions.GetCaption("message_UserSavedSuccessfuly"));
return RedirectToAction("ManageUser", new { UserID = user.ID });
}
The model-binder will set any URI variables into the dto in the get action. My logic layer will return a new User object if a call to getUserByID(null) is made.

MVC 3/EF repository pattern and proper data access

Being rather new to MVC 3 and EF, I'm trying to understand the best architectural approach to developing an application for my company. The application will be a large-scale application that potentially handles hundreds of users at the same time, so I want to make sure I understand and am following proper procedures. So far, I've determined that a simple repository pattern (such as Controller -> Repository -> EF) approach is the best and easiest to implement, but I'm not sure if that is definitely the best way to do things. The application will basically return data that is shown to a user in a devexpress grid and they can modify this data/add to it etc.
I found this article and it is rather confusing for me at this time, so I'm wondering if there is any reason to attempt to work with a disconnected EF and why you would even want to do so: http://www.codeproject.com/Articles/81543/Finally-Entity-Framework-working-in-fully-disconne?msg=3717432#xx3717432xx
So to summarize my question(s):
Is the code below acceptable?
Should it work fine for a large-scale MVC application?
Is there a better way?
Will unnecessary connections to SQL remain open from EF? (SQL Profiler makes it look like it stays open a while even after the using statement has exited)
Is the disconnected framework idea a better one and why would you even want to do that? I don't believe we'll need to track data across tiers ...
Note: The repository implements IDisposable and has the dispose method listed below. It creates a new instance of the entity context in the repository constructor.
Example Usage:
Controller (LogOn using Custom Membership Provider):
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
User newUser = new User();
using (AccountRepository repo = new AccountRepository())
{
newUser = repo.GetUser(model.UserName);
...
}
}
Membership Provider ValidateUser:
public override bool ValidateUser(string username, string password)
{
using (AccountRepository repo = new AccountRepository())
{
try
{
if (string.IsNullOrEmpty(password.Trim()) || string.IsNullOrEmpty(username.Trim()))
return false;
string hash = FormsAuthentication.HashPasswordForStoringInConfigFile(password.Trim(), "md5");
bool exists = false;
exists = repo.UserExists(username, hash);
return exists;
}catch{
return false;
}
}
}
Account Repository Methods for GetUser & UserExists:
Get User:
public User GetUser(string userName)
{
try
{
return entities.Users.SingleOrDefault(user => user.UserName == userName);
}
catch (Exception Ex)
{
throw new Exception("An error occurred: " + Ex.Message);
}
}
User Exists:
public bool UserExists(string userName, string userPassword)
{
if (userName == "" || userPassword == "")
throw new ArgumentException(InvalidUsernamePassword);
try
{
bool exists = (entities.Users.SingleOrDefault(u => u.UserName == userName && u.Password == userPassword) != null);
return exists;
}
catch (Exception Ex)
{
throw new Exception("An error occurred: " + Ex.Message);
}
}
Repository Snippets (Constructor, Dispose etc):
public class AccountRepository : IDisposable
{
private DbContext entities;
public AccountRepository()
{
entities = new DbContext();
}
...
public void Dispose()
{
entities.Dispose();
}
}
What's acceptable is pretty subjective, but if you want to do proper data access I suggest you do NOT use the repository pattern, as it breaks down as your application gets more complex.
The biggest reason is minimizing database access. So for example look at your repository and notice the GetUser() method. Now take a step back from the code and think about how your application is going to be used. Now think about how often you are going to request data from the user table without any additional data. The answer is almost always going to be "rarely" unless you are creating a basic data entry application.
You say it your application will show a lot of grids. What data is in that Grid? I'm assuming (without knowing your application domain) that the grids will combine user data with other information that's relevant for that user. If that's the case, how do you do it with your repositories?
One way is to call on each repository's method individually, like so:
var user = userRepository.GetUser("KallDrexx");
var companies = companyRepository.GetCompaniesForUser(user.Id);
This now means you have 2 database calls for what really should be just one. As your screens get more and more complex, this will cause the number of database hits to increase and increase, and if your application gets significant traffic this will cause performance issues. The only real way to do this in the repository pattern is to add special methods to your repositories to do that specific query, like:
public class UserRepository
{
public User GetUser(string userName)
{
// GetUser code
}
public User GetUserWithCompanies(string userName)
{
// query code here
}
}
So now what happens if you need users and say their contact data in one query. Now you have to add another method to your user repository. Now say you need to do another query that also returns the number of clients each company has, so you need to add yet another method (or add an optional parameter). Now say you want to add a query that returns all companies and what users they contain. Now you need a new query method but then comes the question of do you put that in the User repository or the Company repository? How do you keep track of which one it's in and make it simple to choose between GetUserWithCompany and GetCompanyWithUsers when you need it later?
Everything gets very complex from that point on, and it's those situations that have made me drop the repository pattern. What I do now for data access is I create individual query and command classes, each class represents 1 (and only 1) query or data update command to the database. Each query class returns a view model that only contains the data I need for one specific user usage scenario. There are other data access patterns that will work too (specification pattern, some good devs even say you should just do your data access in your controllers since EF is your data access layer).
The key to doing data access successfully is good planning. Do you know what your screens are going to look like? Do you know how users are going to use your system? Do you know all the data that is actually going to be on each screen? If the answer to any of these is no, then you need to take a step back and forget about the data layer, because the data layer is (or should be for a good application) determined based on how the application is actually going to be used, the UI and the screens should not be dependent on how the data layer was designed. If you don't take your UI needs and user usage scenarios into account when developing the data access, your application will not scale well and will not be performant. Sometimes that's not an issue if you don't plan on your site being big, but it never hurts to keep those things in mind.
No matter what you do, you may consider moving instantiation and disposing of your context to your controller like this:
public class MyController : Controller
{
private Entities context = new Entities();
...
public override void Dispose()
{
context.Dispose();
}
}
You can then pass that context into any method that needs it without duplicating the overhead of creating it.
I disagree that the repository pattern is necessarily bad for the same reason. You create multiple classes to break up your code to make it manageable and still reuse the same context. That could look something like this:
repository.Users.GetUser(userName);
In this case "Users" is a lazy loaded instance of your user repository class which reuses the context from your repository. So the code for that Users property in your repository would look something like this:
private UserRepository users;
public UserRepository Users
{
get
{
If (users == null)
{
users = new UserRepository(this);
}
return users;
}
}
You can then expose your context to these other lazy loaded classes via a property.
I don't think this necessarily conflicts with KallDrexx's pattern. His method simply flips this so instead of
repository.Users.GetUser(userName);
You would have something like
UserQuery query = new UserQuery(repository.Users);
This then becomes an issue of syntax. Do you want this:
repository.Area.Query(value1, value2, ...);
Or this:
AreaQuery query = new AreaQuery { Property1 = value1, ... };
The latter actually works nicer with model binding but obviously is more verbose when you actually have to code it.
Best advice KallDrexx gave is to just put your code I your actions and then figure it out. If you are doing simple CRUD, then let MVC instantiate and populate your model, then all you have to do is attach and save. If you find you can reuse code, move it to where it can be reused. If your application starts getting too complicated, try some of these recommendations until you find what works for you.

RavenDB Catch 22 - Optimistic Concurrency AND Seeing Changes from Other Clients

With RavenDB, creating an IDocumentSession upon app start-up (and never closing it until the app is closed), allows me to use optimistic concurrency by doing this:
public class GenericData : DataAccessLayerBase, IGenericData
{
public void Save<T>(T objectToSave)
{
Guid eTag = (Guid)Session.Advanced.GetEtagFor(objectToSave);
Session.Store(objectToSave, eTag);
Session.SaveChanges();
}
}
If another user has changed that object, then the save will correctly fail.
But what I can't do, when using one session for the lifetime of an app, is seeing changes, made by other instances of the app (say, Joe, five cubicles away), to documents. When I do this, I don't see Joe's changes:
public class CustomVariableGroupData : DataAccessLayerBase, ICustomVariableGroupData
{
public IEnumerable<CustomVariableGroup> GetAll()
{
return Session.Query<CustomVariableGroup>();
}
}
Note: I've also tried this, but it didn't display Joe's changes either:
return Session.Query<CustomVariableGroup>().Customize(x => x.WaitForNonStaleResults());
Now, if I go the other way, and create an IDocumentSession within every method that accesses the database, then I have the opposite problem. Because I have a new session, I can see Joe's changes. Buuuuuuut... then I lose optimistic concurrency. When I create a new session before saving, this line produces an empty GUID, and therefore fails:
Guid eTag = (Guid)Session.Advanced.GetEtagFor(objectToSave);
What am I missing? If a Session shouldn't be created within each method, nor at the app level, then what is the correct scope? How can I get the benefits of optimistic concurrency and the ability to see others' changes when doing a Session.Query()?
You won't see the changes, because you use the same session. See my others replies for more details
Disclaimer: I know this can't be the long-term approach, and therefore won't be an accepted answer here. However, I simply need to get something working now, and I can refactor later. I also know some folks will be disgusted with this approach, lol, but so be it. It seems to be working. I get new data with every query (new session), and I get optimistic concurrency working as well.
The bottom line is that I went back to one session per data access method. And whenever a data access method does some type of get/load/query, I store the eTags in a static dictionary:
public IEnumerable<CustomVariableGroup> GetAll()
{
using (IDocumentSession session = Database.OpenSession())
{
IEnumerable<CustomVariableGroup> groups = session.Query<CustomVariableGroup>();
CacheEtags(groups, session);
return groups;
}
}
Then, when I'm saving data, I grab the eTag from the cache. This causes a concurrency exception if another instance has modified the data, which is what I want.
public void Save(EntityBase objectToSave)
{
if (objectToSave == null) { throw new ArgumentNullException("objectToSave"); }
Guid eTag = Guid.Empty;
if (objectToSave.Id != null)
{
eTag = RetrieveEtagFromCache(objectToSave);
}
using (IDocumentSession session = Database.OpenSession())
{
session.Advanced.UseOptimisticConcurrency = true;
session.Store(objectToSave, eTag);
session.SaveChanges();
CacheEtag(objectToSave, session); // We have a new eTag after saving.
}
}
I absolutely want to do this the right way in the long run, but I don't know what that way is yet.
Edit: I'm going to make this the accepted answer until I find a better way.
Bob, why don't you just open up a new Session every time you want to refresh your data?
It has many trade-offs to open new sessions for every request, and your solution to optimistic concurrency (managing tags within your own singleton dictionary) shows that it was never intended to be used that way.
You said you have a WPF application. Alright, open a new Session on startup. Load and query whatever you want but don't close the Session until you want to refresh your data (e.g. a list of order, customers, i don't know...). Then, when you want to refresh it (after a user clicks on a button, a timer event is fired or whatever) dispose the session and open a new one. Does that work for you?

Encapsulating common logic (domain driven design, best practices)

Updated: 09/02/2009 - Revised question, provided better examples, added bounty.
Hi,
I'm building a PHP application using the data mapper pattern between the database and the entities (domain objects). My question is:
What is the best way to encapsulate a commonly performed task?
For example, one common task is retrieving one or more site entities from the site mapper, and their associated (home) page entities from the page mapper. At present, I would do that like this:
$siteMapper = new Site_Mapper();
$site = $siteMapper->findByid(1);
$pageMapper = new Page_Mapper();
$site->addPage($pageMapper->findHome($site->getId()));
Now that's a fairly trivial example, but it gets more complicated in reality, as each site also has an associated locale, and the page actually has multiple revisions (although for the purposes of this task I'd only be interested in the most recent one).
I'm going to need to do this (get the site and associated home page, locale etc.) in multiple places within my application, and I cant think of the best way/place to encapsulate this task, so that I don't have to repeat it all over the place. Ideally I'd like to end up with something like this:
$someObject = new SomeClass();
$site = $someObject->someMethod(1); // or
$sites = $someObject->someOtherMethod();
Where the resulting site entities already have their associated entities created and ready for use.
The same problem occurs when saving these objects back. Say I have a site entity and associated home page entity, and they've both been modified, I have to do something like this:
$siteMapper->save($site);
$pageMapper->save($site->getHomePage());
Again, trivial, but this example is simplified. Duplication of code still applies.
In my mind it makes sense to have some sort of central object that could take care of:
Retrieving a site (or sites) and all nessessary associated entities
Creating new site entities with new associated entities
Taking a site (or sites) and saving it and all associated entities (if they've changed)
So back to my question, what should this object be?
The existing mapper object?
Something based on the repository pattern?*
Something based on the unit of work patten?*
Something else?
* I don't fully understand either of these, as you can probably guess.
Is there a standard way to approach this problem, and could someone provide a short description of how they'd implement it? I'm not looking for anyone to provide a fully working implementation, just the theory.
Thanks,
Jack
Using the repository/service pattern, your Repository classes would provide a simple CRUD interface for each of your entities, then the Service classes would be an additional layer that performs additional logic like attaching entity dependencies. The rest of your app then only utilizes the Services. Your example might look like this:
$site = $siteService->getSiteById(1); // or
$sites = $siteService->getAllSites();
Then inside the SiteService class you would have something like this:
function getSiteById($id) {
$site = $siteRepository->getSiteById($id);
foreach ($pageRepository->getPagesBySiteId($site->id) as $page)
{
$site->pages[] = $page;
}
return $site;
}
I don't know PHP that well so please excuse if there is something wrong syntactically.
[Edit: this entry attempts to address the fact that it is oftentimes easier to write custom code to directly deal with a situation than it is to try to fit the problem into a pattern.]
Patterns are nice in concept, but they don't always "map". After years of high end PHP development, we have settled on a very direct way of handling such matters. Consider this:
File: Site.php
class Site
{
public static function Select($ID)
{
//Ensure current user has access to ID
//Lookup and return data
}
public static function Insert($aData)
{
//Validate $aData
//In the event of errors, raise a ValidationError($ErrorList)
//Do whatever it is you are doing
//Return new ID
}
public static function Update($ID, $aData)
{
//Validate $aData
//In the event of errors, raise a ValidationError($ErrorList)
//Update necessary fields
}
Then, in order to call it (from anywhere), just run:
$aData = Site::Select(123);
Site::Update(123, array('FirstName' => 'New First Name'));
$ID = Site::Insert(array(...))
One thing to keep in mind about OO programming and PHP... PHP does not keep "state" between requests, so creating an object instance just to have it immediately destroyed does not often make sense.
I'd probably start by extracting the common task to a helper method somewhere, then waiting to see what the design calls for. It feels like it's too early to tell.
What would you name this method ? The name usually hints at where the method belongs.
class Page {
public $id, $title, $url;
public function __construct($id=false) {
$this->id = $id;
}
public function save() {
// ...
}
}
class Site {
public $id = '';
public $pages = array();
function __construct($id) {
$this->id = $id;
foreach ($this->getPages() as $page_id) {
$this->pages[] = new Page($page_id);
}
}
private function getPages() {
// ...
}
public function addPage($url) {
$page = ($this->pages[] = new Page());
$page->url = $url;
return $page;
}
public function save() {
foreach ($this->pages as $page) {
$page->save();
}
// ..
}
}
$site = new Site($id);
$page = $site->addPage('/');
$page->title = 'Home';
$site->save();
Make your Site object an Aggregate Root to encapsulate the complex association and ensure consistency.
Then create a SiteRepository that has the responsibility of retrieving the Site aggregate and populating its children (including all Pages).
You will not need a separate PageRepository (assuming that you don't make Page a separate Aggregate Root), and your SiteRepository should have the responsibility of retrieving the Page objects as well (in your case by using your existing Mappers).
So:
$siteRepository = new SiteRepository($myDbConfig);
$site = $siteRepository->findById(1); // will have Page children attached
And then the findById method would be responsible for also finding all Page children of the Site. This will have a similar structure to the answer CodeMonkey1 gave, however I believe you will benefit more by using the Aggregate and Repository patterns, rather than creating a specific Service for this task. Any other retrieval/querying/updating of the Site aggregate, including any of its child objects, would be done through the same SiteRepository.
Edit: Here's a short DDD Guide to help you with the terminology, although I'd really recommend reading Evans if you want the whole picture.