I am new to this and still trying to get a feel for the best way to do things with MVVM. I can't find an answer with Google.
For convenience, I have created extensions on multiple custom classes, e.g.,
public static AppointmentLabel ToLabel(this textblockPatient tbp)
{
return tbp.appointmentlabel;
}
In my MVVM model, I have placed these extensions in the Model as they seem to convert one source of information into another. However, some of the custom classes are UserControls and live in the View. Doing it this way would require the Model to "know" something about the View, as the above textblockPatient is a UserControl.
How is this done within a MVVM pattern? Are extensions considered to be an exception to the pattern?
Thanks for any help.
In my opinion this is not a mvvm related thing. I would suggest that you put your extension classes near to the classes they extend. By doing it so you reach some level of cohesion. Sometimes it make sense to put the extensions in a seperate project. For example if you know you want need that extensions all the time and you want to have a small codebase or faster compile time.
Related
or "How to decouple UI from business logic in Delphi?"
Each target platform has its own set of native firemonkey controls (Windows=VCL, MacOS=TMS mCL, Android=D.P.F, iOS=TMS iCL and D.P.F). The new FireUI (multi-device form designer) is a great solution for styled components, but not for native components because it still requires the same component on the master pane to support all platforms. As you cannot mix them on the same form, it completely breaks the whole idea with Delphi.
A lot of developers would say that Delphi is the broken approach, see "Why FireMonkey is so fundamentally wrong in every aspect". However, the premise for this question is NOT to argue against Delphi, but to get the best results out of what it does offer.
The conclusion is then that for each form in your application you have to make a separate form for each target platform. This leads to these questions:
Challenge 1: How to include different form files in your project depending on your target platform?
Solution 1: include all of them, i.e. MainForm_IOS.pas, MainForm_Android.pas, MainForm_Win, MainForm_OSX.pas, and then use compiler directives inside the files, so only the content of one of the files is active. Disadvantage: a large application can have many forms (we have around 40), so we are talking about a large number of included files.
Solution 2: Do not include them in the project, but instead just place them in seperate folders. Then you can add the matching folder to the search path for each target platform. Disadvantage: They will not show up in the Project Manager, so it will slow down the workflow every time you need to find a file.
Solution 3: Create a project for each target platform. Disadvantage: Every time you add new units or change common project settings you have to (remember to) apply it to all projects.
Update: As suggested in the Malcom Groves video, placing all the business logic in a package will remove the disadvantage from Solution 3. So I consider solution 3 as the best approach.
Challenge 2: How to connect the different device forms to the (same) business logic?
Possible solution: Create a "Helper" class that contains all the code you would normally have in the form unit.
Update: This "Helper class" is actually what the MVVM calls a ViewModel. What I need seem to be a MVVM framework that can support the databinding. I have made another question about that.
Any input and suggestions about best practice are welcome.
For challenge 1:
You can conditionally link in your FireMonkey form resources depending on the compile target:
{$R *.Windows.fmx MSWINDOWS}
{$R *.Macintosh.fmx _MACOS}
etc.
This is excatly what the XE7 Multiview designer does, but I see nothing against using this mechanism to link whole form files conditionally in to your executable. Of course you might also want to ifdef the corresponding units in your project file.
For challenge 2: Just use some form of Model View Controler logic. So your platform dependant forms will talk to a platform independant controler.
I'm having a little bit of a hard time getting into mvvm. I'm writing a simple app, Notebook. I have one viewmodel, it's name is actually ViewModel. It has an ObservableCollection of Notes inside and methods to save and load those from Isolated Storage. My only Model is Note.cs, it implements INotifyPropertyChanged and I'm of course RaisingPropertyChanged.
I've also got two view, both of them are user controls. One to display list of notes and one to edit the one chosen from the list.
My questions are:
Where do I create an instance of my vievmodel?
How should I implement going from the page with list of notes to the page with detailed view after choosing one Note to edit? At the
moment I'm saving the index of Note in App.xaml.cs, going to the next page and setting
the DetailedView DataContext to the right Note in OnNavigatedTo, but
I don't think it's actually the perfect solution.
Where should I save my Notes? I guess Application_Closing in App.xaml.cs is the right place to do it, but I'd have to have my viewmodel as a global object there, is this the right approach?
Additional question:
I have to add possibility to group notes. I guess that class Group with dictionary (GroupName, howManyNotes) is going to be allright since I don't have to be able to for example write all notes from selected group. Do you think there's a better approach I should think about?
Thanks for respones,
Michał.
I would suggest you take a look at Calibrun.Micro which is a great framework for MVVM. You can get some sample from the CodePlex.
I have used that in a bunch of Project, and will give you flexibility in case if your project grows in size.
Google for Caliburn.Micro sample and you will find a number of sample for all technologies like WPF, Silverlight, Windows Store, Windows Mobile.
Caliburn.Micro CodePlex
I am new to Zend Framework. I have a master layout file and I want to add and remove css/js files dynamically. I plan on creating an XML file which contains which controller/actions should have which files added. I was thinking of having the constructor for the controller read the xml file and add the files as required but this seems a bit bad practice. I am thinking it may be better to have this done in the bootstrap class file.
Can anyone tell me if this would be the correct way of doing it and how I may go about doing this please?
The correct way would be to let your views decide which styles/scripts they need. There are view helpers available for this very purpose. This way you separate your representation logic (views, scripts, css) from your application logic (controllers/bootstrap) and your data logic (database,...).
Create your own layout plug-in class . Inside its post-dispatch hook code your own logic .
It is a good idea to load static resources only when you need them!
That said, it seems like a contradiction in your question that you're considering loading these view specific resources during bootstrap. That's much too early, your app has no clue yet about what will be needed.
With the tought of economic lazyness in the background, you should add resources in your views:
if (somecondition)
{
$this->headScript()->addJavascriptFile($this->baseUrl() . '/path/to/your file');
}
else
$this->jQuery()->addOnLoad($someShortjQueryScript);
}
If that's too late for your taste, you can do it in the action too:
$this->view->headLink()->appendStyle($someCSS);
Check out the view helpers, you can do all kinds of things, append, prepend, addOnLoad, add files, scripts, styles, etc.
It doesn't seem like a good idea to me to read a list of files from config. But I may be wrong.
What are good ways of building groups/folders?
I've tried by feature (UI for a feature plus model etc) with a common group. I've also tried by UI, model, etc.
The former keeps like things together which fits the iPhone paradigm nicely. The latter means I jump around a bit more.
What do you think?
The standard Xcode MVC folder structure is as follows.
CoreData : Contains DataModel and Entity Classes.
Extension : Contain One class(default apple class extensions+project class extensions.)
Helper: Contain Third Party classes/Frameworks (eg. SWRevealController) + Bridging classes (eg. Obj C class in Swift based project)
Model : Make a singleton class (eg.AppModel - NSArray,NSDictionary, String etc.) for saving data. The Web Service Response parsing and storing data is also done here.
Services : Contain Web Service processes (eg. Login Verification, HTTP Request/Response)
View : Contain storyboard, LaunchScreen.XIB and View Classes. Make a sub folder Cells - contain UITableViewCell, UICollectionViewCell etc.
Controller: Contain Logic or Code related to UIElements (eg. UIButton’s reference+ clicked action)
It's going to be very project dependent. In my last project I had mostly views, and so I organized the views by view-type.
Organizing code by type
Organizing code by type is ok for small projects but it's not a good practice for big ones.
Just imagine you have tons of files and folders organized by type, and when you work on a single feature, you have to open all of the folders. Which can confuse you and you can get lost many times while you scroll through files.
It looks something like on A.G's & Julian B.'s answers.
Organizing code by feature (intent)
Organizing code by feature (intent) is the best practice for big projects and big teams.
Cause usually teams work on a single feature, and they focus only on a single folder or group of files. They don't necessarily have to know about other features and files.
It looks something like this:
AppDelegate
Features
Feature 1
View Controllers
Models
Views
Logic
Feature 2
View Controllers
Models
Views
Logic
Networking
Models
Logic
Extensions
Resources
Also, to mention, this practice and technique (organizing project by feature) are implemented by the greatest companies around the world.
After I've generated the interface/implementation files for entities of a model file in XCode, I've not found a way to keep any custom code (validation methods, etc...) I've added to those generated files, given the scenario where I've added an attribute to a model entity and need to re-generate the interface/implementation files. Does anyone know of a way to make this happen? I've just been doing the copy/paste shuffle, but there has to be a better way.
Assuming that you're only talking about adding methods, and not new instance variables, I'd recommend using Objective C categories to add additional behavior to your model classes. Here's a blog post along the same lines.
Use mogenerator, which uses the Generation Gap design pattern to prevent your customizations from being overwritten when the code is re-generated.