Prev: Microsoft ending newsgroup support
Next: Microsoft Responds to the Evolution of Online Communities
From: RB on 5 May 2010 09:50 >That should cover it. Don't forget "if (UpdateData(TRUE)) { transfer >from view to doc } ("if" is important, that's how UpdateData is >supposed to work). Also, don't forget to call UpdateAllViews upon the >change to the document (that's how doc/view is supposed to work). >Goran. Thanks Goran, that is a good point, and a weakness of mine, especially when getting experimental code for posting (no excuse, just honesty)
From: RB on 5 May 2010 10:55 > I consider using data variables to be a serious design error. I avoid them entirely. You > should think about whether or not their existence makes sense. I consider the whole > UpdateData mechanism to be a seriously deep design failure. I have yet to find a reason > that it could ever make sense within the context of a dialog or CFormView-derived class. > Their only value, which is marginal at best, is for a very limited subset of control types > (edit controls, static controls, and check boxes; they are completely useless for any > other kind of control) > **** Well, Joe first I must thank you for giving me what I asked for (as usual ) but the context of the above pretty much flys right over my head. When you read this you probably are either laughing or sighing. But without burdening your super helpful energetic input methods, could you briefly elaborate on specifically you mean by not using data variables ? Are you referrering to data variables for the controls ? And I am correct in surmizing that you directing me further as to how to implement this in the rest of your reply below ? > **** > Probably the wrong decision. What I do is keep the values in variables in the > CDocument-derived class. In the serialize routine I simply call UpdateAllViews() > using a > specific lHint and pHint value which are not (0,NULL), and when this particular > combination is detected in my OnUpdate handler, I simply use operations like > GetWindowText, GetCurSel, and similar operations to copy the values out of the controls > and place them in variables in the CDocument-derived classs. In this way, onlly the > document understands how to read and write the data, and there is never any use of streams > in the view. Data transfer to and from the document are managed by the document class, > which is where it should be handled. > When the CFormView starts up, the OnInitialUpdate loads the controls from the variables in > the CDocument-derived class. > > I do not believe in the DDX and DDV mechanisms at all, except for the DDX_Control calls to > bind the controls to control variables. > **** Ok.... I will have to dwell on this awhile. >> At first I thought I could just make the view class a friend of the document, > **** > NO!!!! This would require the CDocument-derived class know about the views, and this is > COMPLETELY WRONG!. Use UpdateAllViews to handle the transfer, as described. > NEVER include a view header file in the document class; if you think you have to, your > design is wrong! > ***** Ok, I had a feeling as such > *** > I consider writing UpdateData to be a fundamental design error. It is based on a set of > myths that I simply do not believe; that it makes sense to EVER transfer *every* data > value either to the controls, or from the controls. This has nasty implications when the > values interact. Read my essay on Dialog Control Management on my MVP Tips site. > **** Ok I will check Tips site out >**** >> DocPtr->InletA->dInvert_In_1 = m_Invert_In_1; >> DocPtr->InletA->dInvert_Out_1 = m_Invert_Out_1; >> DocPtr->InletA->uiInletNum = m_InletNum; > *** > THis is incosnsitent with your declaration; it should be > DocPtr->InLetA.dInvert_In_1 = m_Invert_In_1; > > because InLetA is not a pointer > **** Yes that is correct, your eagle eye caught it. While we are here would you be so kind as to tell me how I might write this if I changed InletA to an array of structs as in Inlet InletA[10]; In other words how would I first even declare properly the StructArrayPtr? Inlet* InletA[10]; I sense this would only be an array of pts and not what I want. And then how would I properly write the update code ? DocPtr->InletA[2] ?? dInvert_In_1 = m_Invert_In_1; -------------- And finally to this last input (below) from you. I am saving this and will study over it. But I have the following questions: 1. If I implement the below then I surmise I should call the OnUpDate from my OnEnter handler ? (from a control button click) 2. Notwithstanding the previous input you have given me, is there an additional key directional thought focus item that you could give me as why this method is better than, or safer than, or logistically better than using DDX ********** > I would do it using approximately the same idea, but do it in the OnUpdate handler: > > void CMyView::OnUpdate(CView * view, LPARAM lHint, CObject * pHint) > { > if(lHint == 0 && pHint == NULL) > { > CView::OnUpdate(view, lHint, pHint); > return; > } > switch(lHint) > { /* lHint */ > case VALUES_TO_DOCUMENT: > { > CMyDoc * DocPtr = ...etc. > DocPtr->SetInvertIn(...); > DocPtr->SetInvertOut(...); > DocPtr->SetInletNum(...); > // I prefer to use set/get methods rather than directly access variables > // I might also do this as > // DocPtr->SetInLetValues(..., ..., ....); > // and not worry about the specification of the structure at all! > } > break; > case ... > break; > default: > ...maybe ASSERT(FALSE) here....your choice > break; > } /* lHint */ > } // CMyView::OnUpdate ************
From: Joseph M. Newcomer on 5 May 2010 15:12 See below,,, On Wed, 5 May 2010 10:55:47 -0400, "RB" <NoMail(a)NoSpam> wrote: >> I consider using data variables to be a serious design error. I avoid them entirely. You >> should think about whether or not their existence makes sense. I consider the whole >> UpdateData mechanism to be a seriously deep design failure. I have yet to find a reason >> that it could ever make sense within the context of a dialog or CFormView-derived class. >> Their only value, which is marginal at best, is for a very limited subset of control types >> (edit controls, static controls, and check boxes; they are completely useless for any >> other kind of control) >> **** > >Well, Joe first I must thank you for giving me what I asked for (as usual ) but the >context of the above pretty much flys right over my head. When you read this you >probably are either laughing or sighing. But without burdening your super helpful >energetic input methods, could you briefly elaborate on specifically you mean by >not using data variables ? Are you referrering to data variables for the controls ? *** Control variables would NEVer be public; it is a complete failure of the IDE design (one of many too numerous to elaborate on here) to default to "public" for a control varfiable or for an event handler. It goes beyond completely stupid into the realm of deeply irresponsible I attrribute it to a lack of adult supervision of designs, the basic contrast here is class CWhatever : public CView { public: int SomeValue; } CWhatever * p; p->SomeValue = 3; and the setter/getter model: class CWhatever : public CView { protected: int SomeValue; public: void SetSomeValue(int newvalue); int GetSomeValue(); }; By having the functions, you can do many things, e.g., void CWhatever::SetSomeValue(int newvalue) [ if(SomeValue == newvalue) return; SomeValue = newvalue; if(GetSafeHwnd() != NULL) Invalidate()l } CWhatever * p; p->SetSomeValue(3); A common childish belief is that the setter/gerr code is "less efficient" than straight assignmen to a member variablet, which means that there is a belief that a couple nanoseconds to do the call and return actually matter; also, modern compiler using Link Time Code Generation (LTCG) will actually generate the code inline anyway, so the rationale never made sense in the past and certainly doesn't make sense today. Such myths are created by PDP-11 programmers who still teach programming but who never grew up. Note that the setter does not need to know if the implementation needs to do anything in response to the change; the setter just calls SetSomeValue and Magic Happens. joe ***** >And I am correct in surmizing that you directing me further as to how to implement >this in the rest of your reply below ? > >> **** >> Probably the wrong decision. What I do is keep the values in variables in the >> CDocument-derived class. In the serialize routine I simply call UpdateAllViews() >> using a > specific lHint and pHint value which are not (0,NULL), and when this particular >> combination is detected in my OnUpdate handler, I simply use operations like >> GetWindowText, GetCurSel, and similar operations to copy the values out of the controls >> and place them in variables in the CDocument-derived classs. In this way, onlly the >> document understands how to read and write the data, and there is never any use of streams >> in the view. Data transfer to and from the document are managed by the document class, >> which is where it should be handled. >> When the CFormView starts up, the OnInitialUpdate loads the controls from the variables in >> the CDocument-derived class. >> >> I do not believe in the DDX and DDV mechanisms at all, except for the DDX_Control calls to >> bind the controls to control variables. >> **** > >Ok.... I will have to dwell on this awhile. **** See my essays on the use of control variables, dialog control management, and the use of constraint-management patterns on my MVP tips site. ***** > >>> At first I thought I could just make the view class a friend of the document, >> **** >> NO!!!! This would require the CDocument-derived class know about the views, and this is >> COMPLETELY WRONG!. Use UpdateAllViews to handle the transfer, as described. >> NEVER include a view header file in the document class; if you think you have to, your >> design is wrong! >> ***** > >Ok, I had a feeling as such > >> *** >> I consider writing UpdateData to be a fundamental design error. It is based on a set of >> myths that I simply do not believe; that it makes sense to EVER transfer *every* data >> value either to the controls, or from the controls. This has nasty implications when the >> values interact. Read my essay on Dialog Control Management on my MVP Tips site. >> **** > >Ok I will check Tips site out > >>**** >>> DocPtr->InletA->dInvert_In_1 = m_Invert_In_1; >>> DocPtr->InletA->dInvert_Out_1 = m_Invert_Out_1; >>> DocPtr->InletA->uiInletNum = m_InletNum; >> *** >> THis is incosnsitent with your declaration; it should be >> DocPtr->InLetA.dInvert_In_1 = m_Invert_In_1; >> >> because InLetA is not a pointer >> **** > >Yes that is correct, your eagle eye caught it. While we are here >would you be so kind as to tell me how I might write this if I changed >InletA to an array of structs as in >Inlet InletA[10]; > In other words how would I first even declare properly the StructArrayPtr? **** In this case, I'd definitely use setters and getters! ***** > >Inlet* InletA[10]; I sense this would only be an array of pts and not > what I want. **** I have a strong belief that if you ever write a declaration in C++ of the form type name[complie-time-constant] you are not using C++ correctly., Instead, consider CArray or std::vector implementations! Preferrably the latter. ***** >And then how would I properly write the update code ? >DocPtr->InletA[2] ?? dInvert_In_1 = m_Invert_In_1; **** DocPtr->inLetA[2]->dInver_In_1 = because InLetA[2] is a pointer type! But you shouldn't be writing code like this! Not in C++. Using setters and getters, you might do int n = DocPtr->Add(...something...?); DocPtr->SetInvertIn(n, ...expression...); Much cleaner, and avoids all kinds of nasty problems. For example,your setter can implement array bounds checks and be a BOOL; return FALSE if there is a bounds error, and you can write VERIFY(DocPtr->SetInVertIn(,,.)); and it will catch bugs during debugging, and at least not do overruns on release, **** >-------------- >And finally to this last input (below) from you. I am saving this and will study >over it. But I have the following questions: >1. If I implement the below then I surmise I should call the OnUpDate from > my OnEnter handler ? (from a control button click) **** OnUpdate is called by the framework (usually, with NULL,0,NULL) during the view setup, so you don't need to worry about it. If called with other than (0, NULL) as the last two arguments, you use this to determine if you must capture the values to the document, or the document has new values to be placed in the controls, etc. **** >2. Notwithstanding the previous input you have given me, is there an > additional key directional thought focus item that you could give me as > why this method is better than, or safer than, or logistically better than > using DDX **** DDX does not allo for you to detect or react to interacting changes; e.g., setting the check box enables the dropdown list. If you start distributing this code throughout your dialog/formview, eventually the code diverges, and you end up with six different algorithms, none of which are quite right. My constraint-management pattern means that there is exactly ONE place where interactions are managed and predicates are evaluated. And DDX doesn't work right for dropdown lists, list controls, tree controls, etc. so using it only in the very limited cases it works in fools you into thinking it makes sense. joe **** > >********** >> I would do it using approximately the same idea, but do it in the OnUpdate handler: >> >> void CMyView::OnUpdate(CView * view, LPARAM lHint, CObject * pHint) >> { >> if(lHint == 0 && pHint == NULL) >> { >> CView::OnUpdate(view, lHint, pHint); >> return; >> } >> switch(lHint) >> { /* lHint */ >> case VALUES_TO_DOCUMENT: >> { >> CMyDoc * DocPtr = ...etc. >> DocPtr->SetInvertIn(...); >> DocPtr->SetInvertOut(...); >> DocPtr->SetInletNum(...); >> // I prefer to use set/get methods rather than directly access variables >> // I might also do this as >> // DocPtr->SetInLetValues(..., ..., ....); >> // and not worry about the specification of the structure at all! >> } >> break; >> case ... >> break; >> default: >> ...maybe ASSERT(FALSE) here....your choice >> break; >> } /* lHint */ >> } // CMyView::OnUpdate >************ > Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm
From: RB on 6 May 2010 10:08 Oh ok, if I get the jest of input you are saying to make all data vars either protected or private and use getter setter funcs to access and/or change them. Well that makes sense, I can't argue with that. And I can see the advantages to such as opposed to just assignment by any means, DDX or otherwise. However I am still a bit out in left field on your latest instruction on CArray or std::vector, and not just because I have never used either one of them, but why is the structure array not ok if I access it using setter getter paradigm. I am trying to write a calculator of pipe inverts and the struct type seems to fit what I need. But I have many manholes and need a structure array to reference all of them. And by the way just for my knowledge. I see what you told me about assigning the structure array member using a structure array ptr, DocPtr->InletA[2]->dInver_In_1 = But how would a person declare a ptr to a structure array. Struct InletA[10]; Inlet* InletA[10]; I don't think this is it ?? Inlet (*InletA)[10]; ?? How would one do this ? ( I am at work now and do not have access to my compiler so my suggestions may have given me errors to answer my questions, but none the less would like your input on this )
From: Joseph M. Newcomer on 6 May 2010 16:58 See below... On Thu, 6 May 2010 10:08:28 -0400, "RB" <NoMail(a)NoSpam> wrote: >Oh ok, if I get the jest of input you are saying to make all data vars >either protected or private and use getter setter funcs to access >and/or change them. Well that makes sense, I can't argue with that. >And I can see the advantages to such as opposed to just assignment >by any means, DDX or otherwise. > >However I am still a bit out in left field on your latest instruction on >CArray or std::vector, and not just because I have never used either >one of them, but why is the structure array not ok if I access it using >setter getter paradigm. **** Generally, because there is no bounds checking done in pure C. Also, it puts large objects on the stack (there was some example of this posted here a few weeks ago, where somebody had a local array of 17x17xmassive structure on the stack and was getting stack overflows). Overall, the advantage of CArray or std::vector is that the stack space consumed is very small (a few bytes) and the data is always on the heap. ***** >I am trying to write a calculator of pipe >inverts and the struct type seems to fit what I need. But I have many >manholes and need a structure array to reference all of them. **** If you don't know how many you have in advance, a compile-time-constant array is a Really Bad Idea. Either you need to make it big enough to hold the absolute maximum you might ever encounter (consuming massive stack space) or be prepared to deal with the fact that the program is not adequate to the task because the array bounds, which must be set at compile time, are too small. CArray::SetAt will let you set any array element, and do bounds checking, and CArray::SetAtGrow will expand the array to the specified size. CArray::Add will expand it until memory exhausts. There are analogous features for std::vector. The old-fashioned array declared on the stack is just that: old-fashioned, replaced by far more flexible, robust, and powerful alternatives. The key here is to stop thinking like a C programmer and start thinking like a C++ programmer. **** >And by the way just for my knowledge. I see what you told me about >assigning the structure array member using a structure array ptr, >DocPtr->InletA[2]->dInver_In_1 = >But how would a person declare a ptr to a structure array. >Struct InletA[10]; >Inlet* InletA[10]; I don't think this is it ?? *** This declares an array of pointers to structures, but you actually have to make sure the elements you care about are initialized with pointers that point to actual instances of the structure, otherwise you will have serious errors in the code. e.g. Inlet* InletA[10]; InletA[2]->whatever = 0; // access fault if you are lucky! The above fails because InletA[2] has no valid value (in debug mode, it is initialized to 0xCCCCCCCC if it is declared on the stack, 0xCDCDCDCD if it is on the heap) You would have to do Inlet * InletA[10]; InletA[2] = new InletA; NOW you can write InletA[2]->whatever = 0; because there is a real object there. But I would never write code like this. I might do CArray<Inlet> InletA; InletA.SetSize(10); and now I can write InletA[2].whatever = 0; or I might write std::vector<Inlet> InletA; InletA.resize(10); The choice of using objects or pointers to objects is another dimension of design, but first you have to start programming in C++, not primitve 1975-style C. joe ***** >Inlet (*InletA)[10]; ?? How would one do this ? >( I am at work now and do not have access to my compiler so my > suggestions may have given me errors to answer my questions, > but none the less would like your input on this ) > Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: Microsoft ending newsgroup support Next: Microsoft Responds to the Evolution of Online Communities |