elGringo Posted October 10, 2017 Share Posted October 10, 2017 Hi, dear all. Learning ASP MVC. Question is in implementing MVC pattern in UniGUI framework. I want to understand,starting this discussion -is there any sense of implementing of this pattern in UNIGUI, cause main plus of MVC is better structure of app and better testing -what are concrete ways of implementations, maybe simple examples... -is someone tried? Any effort? Any experience? Share please your thoughts and practices you faced with. As for my thoughts Models code could be in MainModule Views are forms Controllers are separate units... On the other hand - traditional Delphi style codeing to form when everything is coded in form and that is bad practice, because it is good on the start, good as RAD approach, but after dozens of units it become to be a mess, don't you reckon like this? That is the starting point... Quote Link to comment Share on other sites More sharing options...
fredycc Posted October 10, 2017 Share Posted October 10, 2017 There is a project called MVCBr, is based on DMVC I guess and include a example for uniGUI, maybe can help you about it. https://github.com/amarildolacerda/MVCBr It would be great to integrate uniGUI with frameworks like DMVC easily. Regards Quote Link to comment Share on other sites More sharing options...
elGringo Posted October 10, 2017 Author Share Posted October 10, 2017 Thnks, but by your words and experience how is that? Quote Link to comment Share on other sites More sharing options...
elGringo Posted October 11, 2017 Author Share Posted October 11, 2017 ok, it seems to me i am the first who appeal to this theme ) I'm going to do my next project in UniGUI in MVC pattern, i will share my experience here. Quote Link to comment Share on other sites More sharing options...
Jean-Marc Kiener Posted October 11, 2017 Share Posted October 11, 2017 Have no experiences in MVC/UniGui but would be interested too.. Quote Link to comment Share on other sites More sharing options...
davidizadar Posted October 14, 2017 Share Posted October 14, 2017 Hi guys, The theory is beautiful, but practical results are more important. The MVC pattern intends to achieve a clear separation between the user interface and the business logic. This goal becomes paramount when you need to share the business logic when you target several platforms for your user interface. In uniGUI you already have two targets: desktop and mobile (touch). Delphi already provides tools for achieving that separation without having to add unnecessary code. Basically, any Delphi form can be bound to objects in a data module using event handlers and actions. Just by using these tools, you won't need anything else for achieving the separation. The Small Hybrid App in Demos\Touch uses this approach. I hope this helps... Quote Link to comment Share on other sites More sharing options...
elGringo Posted October 15, 2017 Author Share Posted October 15, 2017 Yes! That is the thoughts i waited for ! Delphi has its unique architecture. Form itself has dfm and pas parts that are bounded, the engeneers of Delphi tried to give us more speed in developing soft! So on start we have already structure we can use. Actions and events (procedures and functions of object) are those tools to connect everything to everything. Other question - is how convenient is it? How easy to read and understand this code to new person of project? Experiment shows all! Lets write simple app that just will concat 2 Uniedits here in different patterns and together understand which approach is better! Ok, having eLeft: TUniEdit; eRight: TUniEdit; lResult: TUniLabel; bConcat: TUniBitBtn; 1 st approach is Delphi approach - concat directly using form vars procedure TMainForm.bConcatClick(Sender: TObject); begin lResult.Caption:=eLeft.text+eRight.Text; end; 2d approach is MVC creating models with sync to main unit uModel; interface uses SysUtils, Classes; type TModel = class(TDataModule) private FLeft: string; FRight: string; FResult: string; procedure SetLeft(const Value: string); procedure SetRight(const Value: string); procedure SetResult(const Value: string); { Private declarations } public { Public declarations } property Left:string read FLeft write SetLeft; property Right:string read FRight write SetRight; property Result:string read FResult write SetResult; end; function Model: TModel; implementation {$R *.dfm} uses UniGUIVars, uniGUIMainModule, MainModule,Main; function Model: TModel; begin Result := TModel(UniMainModule.GetModuleInstance(TModel)); end; { TModel } procedure TModel.SetLeft(const Value: string); begin if (Value<>FLeft) then begin FLeft := Value; MainForm.eLeft.Text:=Value; end; end; procedure TModel.SetResult(const Value: string); begin if (Value<>FLeft) then begin FResult := Value; MainForm.lResult.Caption:=Value; end; end; procedure TModel.SetRight(const Value: string); begin if (Value<>FRight) then begin FRight := Value; MainForm.eRight.Text:=Value; end; end; initialization RegisterModuleClass(TModel); end. Model is created in UniMainModule procedure TUniMainModule.UniGUIMainModuleCreate(Sender: TObject); begin FModel:=TModel.Create(UniApplication); end; Sync View to model procedure TMainForm.eLeftChange(Sender: TObject); begin UniMainModule.Model.Left:=eLeft.Text; end; procedure TMainForm.eRightChange(Sender: TObject); begin UniMainModule.Model.Right:=eRight.Text; end; Controller method procedure TController.Concat; begin with UniMainModule do begin Model.Result:=Model.Left+Model.Right; end; full Controller unit uController; interface uses SysUtils, Classes; type TController = class(TDataModule) private { Private declarations } public { Public declarations } procedure Concat(); end; function Controller: TController; implementation {$R *.dfm} uses UniGUIVars, uniGUIMainModule, MainModule; function Controller: TController; begin Result := TController(UniMainModule.GetModuleInstance(TController)); end; { TController } procedure TController.Concat; begin with UniMainModule do begin Model.Result:=Model.Left+Model.Right; end; end; initialization RegisterModuleClass(TController); end. instance of Controller called directly as UniGUI allows it use of MVC approach procedure TMainForm.bConcatClick(Sender: TObject); begin UniMainModule.Controller.Concat(); end; My conclusions -mvc is more difficult in realization -delphi already has its unique structure and there is unique Delphi pattern, no needed to import MVC, but possible -on that small example I easily used already done infrastructure of Delphi components and to concat i just needed to write one string! -as for mvc approach i needed to do a lot of additional work, create new structure in model, sync it to view and view to it, and this sync is not full... in ASP MVC for example not other structure then MVC, so if not use MVC unclear how to organize coding, so in ASP MVC it is necessary to use mvc Approach, in Delphi we can choose, and it is advantage... Maybe in big projects mvc is better, but small test shows lots of additional work... Quote Link to comment Share on other sites More sharing options...
elGringo Posted October 15, 2017 Author Share Posted October 15, 2017 Besides! Firstly I wanted to show code of simple calc like this below in 2 patterns, but I don't even want to think how complicated it to transfer in MVC pattern... unit Main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, uniGUITypes, uniGUIAbstractClasses, uniGUIClasses, uniGUIRegClasses, uniGUIForm, uniEdit, uniGUIBaseClasses, uniButton, uniBitBtn, uniLabel; type TMainForm = class(TUniForm) b8: TUniBitBtn; b9: TUniBitBtn; b4: TUniBitBtn; b5: TUniBitBtn; b6: TUniBitBtn; bOne: TUniBitBtn; b2: TUniBitBtn; b3: TUniBitBtn; eResult: TUniEdit; UniBitBtn10: TUniBitBtn; bEqual: TUniBitBtn; bDivide: TUniBitBtn; bMultiply: TUniBitBtn; bMinus: TUniBitBtn; bPlus: TUniBitBtn; bCE: TUniBitBtn; b7: TUniBitBtn; unilabel: TUniLabel; procedure UniFormCreate(Sender: TObject); procedure digitClick(Sender: TObject); procedure signClick(Sender: TObject); procedure bEqualClick(Sender: TObject); procedure bCEClick(Sender: TObject); private { Private declarations } faIsEmpty: Boolean; fbIsEmpty: Boolean; fcIsEmpty: Boolean; fdIsEmpty: Boolean; fIsSignClickedBefore: Boolean; fIsDigitClicked: Boolean; fa, fb, fc: real; fd: char; foperators: set of Char; procedure nullAll; public { Public declarations } end; function MainForm: TMainForm; implementation {$R *.dfm} uses uniGUIVars, MainModule, uniGUIApplication, System.Generics.Collections; function MainForm: TMainForm; begin Result := TMainForm(UniMainModule.GetFormInstance(TMainForm)); end; procedure TMainForm.bCEClick(Sender: TObject); begin nullAll(); end; procedure TMainForm.bEqualClick(Sender: TObject); begin case fd of '-': fc := fa - fb; '+': fc := fa + fb; '*': fc := fa * fb; '/': fc := fa / fb; end; fa := fc; fbIsEmpty := True; eResult.Text := FloatToStr(fc); end; procedure TMainForm.nullAll; begin fa := 0.00; fb := 0.00; fc := 0.00; unilabel.Caption := ''; faIsEmpty := true; fbIsEmpty := true; fcIsEmpty := true; fdIsEmpty := true; foperators := ['+', '-', '*', '/']; unilabel.Caption := ''; eResult.Text := ''; end; procedure TMainForm.digitClick(Sender: TObject); begin fIsSignClickedBefore := false; fIsDigitClicked := True; if faIsEmpty then begin fa := strToFloat((Sender as TUniBitbtn).Caption); faIsEmpty := false; end else begin fb := strToFloat((Sender as TUniBitbtn).Caption); fbIsEmpty := False; end; unilabel.Caption := unilabel.Caption + (Sender as TUniBitbtn).Caption; end; procedure TMainForm.signClick(Sender: TObject); var s: string; lastSymbol:char; begin fdIsEmpty := false; if fIsSignClickedBefore then begin s := unilabel.Caption; lastSymbol:=s[Length(s)]; if ((s[Length(s)] in foperators) and ((lastSymbol <> (Sender as TUniBitbtn).Caption))) then begin delete(s, length(s), 1); fdIsEmpty := true; unilabel.Caption := s; //fIsSignClickedBefore := false; end else if (s[Length(s)] = (Sender as TUniBitbtn).Caption) then exit; end; unilabel.Caption := unilabel.Caption + (Sender as TUniBitbtn).Caption; s := (Sender as TUniBitBtn).Caption; fd := s[Low(s)]; if fdIsEmpty then exit; if not fIsDigitClicked and fIsSignClickedBefore then exit; fIsSignClickedBefore := true; if (not faIsEmpty) and (not fbIsEmpty) then begin case fd of '-': fc := fa - fb; '+': fc := fa + fb; '*': fc := fa * fb; '/': fc := fa / fb; end; fa := fc; eResult.Text := FloatToStr(fc); fIsDigitClicked := false; end; end; procedure TMainForm.UniFormCreate(Sender: TObject); begin nullAll(); end; initialization RegisterAppFormClass(TMainForm); end. Quote Link to comment Share on other sites More sharing options...
rgreat Posted October 15, 2017 Share Posted October 15, 2017 MVC paradigm is not worth it in most applications. Because it is not effective in terms of Effort vs. Results. But if you have free time - it will make your code cleaner. Maybe. Quote Link to comment Share on other sites More sharing options...
elGringo Posted October 16, 2017 Author Share Posted October 16, 2017 Thanks, rgreat! Clean code is result of experience imho. I code for 3 years, and code of my first year is unclean for me ))) In langs like php it is unclear how to organize code, so MVC is applied as mostly simple and convenient. MVC gives fixed structure but it also takes time to support this structure. I mean - sometimes it is easier to call some small method from view, but structure says - write methods in controller, bind it to view. And you have to. My regards to all readers and writers of topic! Don't hesistate to share your thoughts. Quote Link to comment Share on other sites More sharing options...
Jean-Marc Kiener Posted October 16, 2017 Share Posted October 16, 2017 Hi, Thanks to all who had participate to this topic. Very interesting. So maybe as conclusion we could say: Project: Complex, quality is the top priority (medicinal software, rocket steering ): Use MVC approach. Write test code for automatic test scenes ( "continous integration" ). If you are more then one developer team working on the same project, then this approach would recommended. Project: Not very complicated, quality is important but not a killer argument: Use standard "Delphi" approach. OK? Quote Link to comment Share on other sites More sharing options...
jrp Posted October 16, 2017 Share Posted October 16, 2017 Hello, For MVC the benefits would be great if the code is autogenerated instead of hand coded. Too much efforts needed to code by hand.But code/form generator would benefit all kind of programming paradigm. Even more benefits with the Delphi RAD way.Imagine that when we create a database application, we define datasets (sql, which fields shown in grid, which fields included in insert & edit, field labels, default values, etc) and a few clicks later, for each dataset it will autogenerate *.dfm and *.pas of:- a datamodule that contains the dataset- a form with dbgrid to browse, filter and search the dataset- a form to do insert & edit the datasetand those forms are ready to use and customize.This would save time greatly Quote Link to comment Share on other sites More sharing options...
elGringo Posted October 16, 2017 Author Share Posted October 16, 2017 "Too much efforts needed to code by hand" In delphi Yes for the moment unfortunately, but thanks, delphi has its own structure, that can be used easily "Imagine that when we create a database application, we define datasets " such approach done in ASP MVC when there is DB context from Entity Framework which is alredy automates most of work... Besides - do you use db aware or live bindings designer? Quote Link to comment Share on other sites More sharing options...
rgreat Posted October 16, 2017 Share Posted October 16, 2017 I never use live bindings. It's just bad. Quote Link to comment Share on other sites More sharing options...
wprins Posted October 10, 2018 Share Posted October 10, 2018 A big reason to prefer more decoupled approaches such as MVC, MVP, MVVM, MV* is testability. If all your logic is inside event handlers then typically it's quite hard to properly test and not possible to test entirely in isolation. This may not be a show stopping problem but it is a consideration at least. (Also see for example the "Humble Dialog" pattern and "Humble View".) 1 Quote Link to comment Share on other sites More sharing options...
GerhardV Posted October 10, 2018 Share Posted October 10, 2018 1 hour ago, wprins said: A big reason to prefer more decoupled approaches such as MVC, MVP, MVVM, MV* is testability. If all your logic is inside event handlers then typically it's quite hard to properly test and not possible to test entirely in isolation. This may not be a show stopping problem but it is a consideration at least. (Also see for example the "Humble Dialog" pattern and "Humble View".) Absolutely! Quote Link to comment Share on other sites More sharing options...
elGringo Posted October 10, 2018 Author Share Posted October 10, 2018 Unit testing quite easily maybe done with DUnitX. But "Clean Code" and "Readability" - it is from practice... Which code pattern to use is also good question... Quote Link to comment Share on other sites More sharing options...
Bresler Posted November 5, 2018 Share Posted November 5, 2018 Hi, I'm sorry for be late, I hope this subject still be worm. I had published some time ago a simple post about MVVM in UNIGUI using KNOCKOFF (from Stefan Glienke) adapted to UNIGUI. Here is the link. Post´s Link Since that time, I have been working with this pattern in UNIGUI with TMS Aurelius, and yes, code is cleaner. The limitation I found on this approach is the creation of an adapter for each component. But it is working. I hope this could help. Regards Quote Link to comment Share on other sites More sharing options...
oudouwx Posted December 13, 2021 Share Posted December 13, 2021 On 11/5/2018 at 10:18 AM, Bresler said: Hi, I'm sorry for be late, I hope this subject still be worm. I had published some time ago a simple post about MVVM in UNIGUI using KNOCKOFF (from Stefan Glienke) adapted to UNIGUI. Here is the link. Post´s Link Since that time, I have been working with this pattern in UNIGUI with TMS Aurelius, and yes, code is cleaner. The limitation I found on this approach is the creation of an adapter for each component. But it is working. I hope this could help. Regards Do you have any update on this simple MVVM framework with TMS Aruelius? I am very interested. Thank you. @Bresler Quote Link to comment Share on other sites More sharing options...
Abaksoft Posted December 13, 2021 Share Posted December 13, 2021 Hello, These learned words "Paradigm, MVC PATERN, MVVM, ..." sound good to the ear, But why doing complex, when things could be done easyer ? Delphi is OOP. You can write very clean code with this technic. Just separate your Gui interface from your logic. 1. Design what you want on your uniFrame. 2. Use Object on your events 3. Create a Class on a uniDataModule and describe as well as possible your fields / methods. That what i am doing. I confirm : this makes things a lot easier, especially when reading code later. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.