OOP principle wrong?
-
Yes, and math is about way more than 1 + 1 = 2. OOP is about data encapsulation. If you have a single publicly defined data member in a single class than you have, in fact, introduced a non-OO element into your overall architecture. There may exist good, professionally valid, reasons for doing that, but saving keystrokes is not among them. You should at least be aware that your design cannot be trully described as OO. Your marketing guys might sale it as OO, but you as as the programmer, should not delude yourself. Again, OOP is not the answer to all problems, but if you need procedural code, don't dress it up as OO. After all, typing "class" is a waste of five keystrokes.
OOP is about data encapsulation And beyond. OOP is, as the name mentions, all about objects. A class itself is an object, but the members of a class are objects on their own. It's not a big deal or a problem to give the knowledge of such an object to another class? I even understand that you create a Get and a Set function for such a member, suppose you wish to give another object the ability to change the member, and do some extra stuff for yourself in the Set-function? I can understand that a private member has protected get- and setfunctions, so the derived classes can retrieve and set the value of the member, but don't have direct access to the member itself. Think of an object as a black box filled with information. You don't have to know how it works, you just need to know that is works. If you send a request to such an object, you can be certain that the result you receive from the object after processing is a valid result. And nobody cares if one or more of the members of that object are private, public or virtual, as long as they don't change the state of the object itself. At least, that's my thought. I might be wrong, ofcourse -- Alex Marbus www.marbus.net
-
I remember reading in many books and being tought at uni that when programming in the OOP style we should use get and set methods to read and write properties. Supposedly this controls access to the variables. Now that I have left uni and dont have anyone marking my work anymore, I have left this principle where I think it belongs - not existing. I myself have never had any problems accessing a variable by accident (might be because my code has never exceded 3000 lines) Forgoing this principle has made my code much easier to read, and less to type. What do you think?
While you might be a great programmer and be able to keep track of how to validate each member outside of the class, the next guy who has to maintain your code might no be... write you code like you would you UI, idiot proof :) Have a good one, -Ben "Its funny when you stop doing things because they’re wrong, but because you might get caught." - Unknown
-
I remember reading in many books and being tought at uni that when programming in the OOP style we should use get and set methods to read and write properties. Supposedly this controls access to the variables. Now that I have left uni and dont have anyone marking my work anymore, I have left this principle where I think it belongs - not existing. I myself have never had any problems accessing a variable by accident (might be because my code has never exceded 3000 lines) Forgoing this principle has made my code much easier to read, and less to type. What do you think?
I recently read an article that stated using get/set methods is not OO. If you need to get() a variable to perform a given task you should give the object the data necessary to do it for you. This makes perfect sense, only the object should know about its state (variables) and only it should know how to perform tasks related to its state. However, I am torn between what should be done in a doc/view pattern. Should the view give the doc a canvas to render onto or should the view know the state of the doc and render it. E.g. // bare in mind this is a oversimplification class Doc { public: void Draw(CDC *pDC); private: CString m_text; }; void View::OnDraw(CDC *pDC) { pDoc = GetDocument(); pDoc->Draw(pDC); } // or ////////////////////////////// class Doc { public: CString * GetText(); private: CString m_text; }; void View::OnDraw(CDC *pDC) { pDoc = GetDocument(); pDC->TextOut(0, 0, pDoc->GetText); } The first version allows the doc to change without requiring the view to change also. However, it would require a separate method for each rendered style (DrawBarGraph, DrawPieChart, etc.). The second version is closer to the MVC pattern (except that the controller and the view are integrated, which has always bothered me). It permits the view to render the doc whatever way the view should (CBarGraphView, CPieChartView, etc.). What to do! P.S. Sorry for the long post.
-
OOP is about data encapsulation And beyond. OOP is, as the name mentions, all about objects. A class itself is an object, but the members of a class are objects on their own. It's not a big deal or a problem to give the knowledge of such an object to another class? I even understand that you create a Get and a Set function for such a member, suppose you wish to give another object the ability to change the member, and do some extra stuff for yourself in the Set-function? I can understand that a private member has protected get- and setfunctions, so the derived classes can retrieve and set the value of the member, but don't have direct access to the member itself. Think of an object as a black box filled with information. You don't have to know how it works, you just need to know that is works. If you send a request to such an object, you can be certain that the result you receive from the object after processing is a valid result. And nobody cares if one or more of the members of that object are private, public or virtual, as long as they don't change the state of the object itself. At least, that's my thought. I might be wrong, ofcourse -- Alex Marbus www.marbus.net
Let me add a little more to the above.... OOP is about visibility and responsibility. What happens when change occurs? You will basically have to trace back through everything and make changes however, if you have properly defined visibility and responsibilities your changes should be isolated. The Law of Demeter becomes very important in this respect!
-
If you are not using Get/Set on the data in your classes than, simply put, you are not doing OOP. Which is fine, as long as you undertand that. OOP is NOT the best solution to all problems. But programmers who think they are doing OOP when in fact they are not ARE a BIG problem in the industry. I am currently responsible for a large legacy codeset left behind by someone with an attitude very similar to yours. Public data in every class, used globaly in a rather large application - an absolute disaster. A programmer's job is to manage data, OOP is simply a technique which sets a standard for how to do that (a standard which C++ unfortunantly makes very easy to break). If you do not understand that, become a network quy or a QA guy or something.:mad:
And then of course, MFC is not object-oriented, and ATL is not, and all functions must be virtual etc... We heard it many times. If I may throw my vote - when a new programmer is learning OOP, he should definitely use Get/Set technique. Once he has learned it, he can be use getters and setters much more selective - without breaking OOP. If OOP did not have practical exceptions, there would be no "const_cast" operator. Win32/ATL/MFC Developer Oslo, Norway
-
I remember reading in many books and being tought at uni that when programming in the OOP style we should use get and set methods to read and write properties. Supposedly this controls access to the variables. Now that I have left uni and dont have anyone marking my work anymore, I have left this principle where I think it belongs - not existing. I myself have never had any problems accessing a variable by accident (might be because my code has never exceded 3000 lines) Forgoing this principle has made my code much easier to read, and less to type. What do you think?
Hi, I think the idea of get/set helps in several ways: 1) you can use it to help debugging (ie. easy trace statements on cariable access) 2) you can use it to hide the underlying implementation for instance using GetColour(int nIndex) rather that MyPicture.Colours.GetAt(myPos) means that if you decide to change over from MFC collections to STL for instance, you only have to change the GetColour() function rather than the entire code base. Hope that helps, Andrew.
-
Small point, but it does not imply this in totality. The internal variables and variables that need validation so a set method is a necessity would be private. But this is a stupid point of mine, having them all as get and set and is for booleans makes life easier for developing as we dont have to worry about whether a variable is public or private since they are all accessed with get. I've noticed a lot of programmers would program a Point class like this though: public class point{ public int x,y; public point(int x, int y){ this.x = x; this.y = y; } } so maybe simple endpoints in code its allowed????
It's called "discipline". I know this might be a rather extreme example, but... If you're willing to let something like this by, where do you draw the line at proper coding technique? At what point do you come to the decision that Get/Set methods would be a better idea?
-
Let me add a little more to the above.... OOP is about visibility and responsibility. What happens when change occurs? You will basically have to trace back through everything and make changes however, if you have properly defined visibility and responsibilities your changes should be isolated. The Law of Demeter becomes very important in this respect!
How could I forget that :) Thanks Ed :rose: -- Alex Marbus www.marbus.net
-
I recently read an article that stated using get/set methods is not OO. If you need to get() a variable to perform a given task you should give the object the data necessary to do it for you. This makes perfect sense, only the object should know about its state (variables) and only it should know how to perform tasks related to its state. However, I am torn between what should be done in a doc/view pattern. Should the view give the doc a canvas to render onto or should the view know the state of the doc and render it. E.g. // bare in mind this is a oversimplification class Doc { public: void Draw(CDC *pDC); private: CString m_text; }; void View::OnDraw(CDC *pDC) { pDoc = GetDocument(); pDoc->Draw(pDC); } // or ////////////////////////////// class Doc { public: CString * GetText(); private: CString m_text; }; void View::OnDraw(CDC *pDC) { pDoc = GetDocument(); pDC->TextOut(0, 0, pDoc->GetText); } The first version allows the doc to change without requiring the view to change also. However, it would require a separate method for each rendered style (DrawBarGraph, DrawPieChart, etc.). The second version is closer to the MVC pattern (except that the controller and the view are integrated, which has always bothered me). It permits the view to render the doc whatever way the view should (CBarGraphView, CPieChartView, etc.). What to do! P.S. Sorry for the long post.
IMHO, a View should have knowledge of a Doc, and a Doc definately not of a View. The view needs to know about the doc, because it needs to draw the contents of the document. The document has nothing to do with the view, because it doesn't have to know what should be drawn, and on what device context. For that matter, the Doc should contain no functions related to displaying or printing a document. The doc only needs to known what it should do with members (objects) belonging to a document itself, and ofcourse related functions such as serializing etc. I'm certain you can't always have a perfect OOD or OO application, but you can at least try as hard as possible. Unfortunately, OO means in most cases loss of performance. Two things you have to think of.. speed and maintainability.. hard to choose. -- Alex Marbus www.marbus.net
-
If you are not using Get/Set on the data in your classes than, simply put, you are not doing OOP. Which is fine, as long as you undertand that. OOP is NOT the best solution to all problems. But programmers who think they are doing OOP when in fact they are not ARE a BIG problem in the industry. I am currently responsible for a large legacy codeset left behind by someone with an attitude very similar to yours. Public data in every class, used globaly in a rather large application - an absolute disaster. A programmer's job is to manage data, OOP is simply a technique which sets a standard for how to do that (a standard which C++ unfortunantly makes very easy to break). If you do not understand that, become a network quy or a QA guy or something.:mad:
I think someone taught you the wrong definition of OOP. OOP says nothing about Getters or Setters, but rather interfaces. Treating instances (objects) of a type (class) as single entities with their own state. OOP is designed to model the way we work with things in real life. For instance, your Television set has many things which are getters/setters, such as the channel changer or volume control, however it also has "public data" in the form of the speaker and picture tube. We, the object client have direct access to this data without having to manipulate an interface to do so. Imagine if we had to flip a switch evertime we wanted to get a frame of image data or a cycle of sound. When it makes sense, public data is perfectly acceptable and doesn't violate encapsulation. Encapsulation only makes sense when dealing with object state, and seldom with object data. Does exposing m_pMainWnd in CWinApp violate encapsulation? Not really, since if you are accessing it from outside the CWinApp derived class, that means the MainWnd exists, and it's not going to change (if using the framework as designed). Further, changing the pointer doesn't effect CWinApp's internal state, so there is nothing to update. My point is really that encapsulation is something important, but it only really applies when you need to encapsulate something.
-
I remember reading in many books and being tought at uni that when programming in the OOP style we should use get and set methods to read and write properties. Supposedly this controls access to the variables. Now that I have left uni and dont have anyone marking my work anymore, I have left this principle where I think it belongs - not existing. I myself have never had any problems accessing a variable by accident (might be because my code has never exceded 3000 lines) Forgoing this principle has made my code much easier to read, and less to type. What do you think?
I think you've missed a VERY big point of OOP....data hiding. I often tell OOP beginners that if I see more than a few Get/Set type methods for anything but a container class, I know that they didn't write it properly..... I prefer to "inject" data or other objects into your object and avoid trying to get data back out of the object. Why?? Well data is usually not worth much, but information is! The data placed into anything but a container object should typically be used to generate information rather than spitting it back out in its original form. Another benefit of avoiding public data: You can "force" the way that data is injected into your object. If, for example, the object has 5 members, it is possible (as has frequenctly been the case in my code) that in one case you set 3 of the values, but in another case, only 2 specific values should be set....buy using a method which takes 3 values in one case, and 2 values in the other, you can make sure that the user of your class (which may be you a year later) uses the class properly. Using these ideas, I reworked a co-workers code...he told me he used public data because he just wanted something that was easy to work with....as a result, he had functionality spread throughout 10 classes with a fair amount of similar code in multiple places. When I was done, not only was it much easier to use the class (by his admisssion, not my judgement), but it also meant that the code base was much smaller (about 2000 lines of code were removed from a section of code with 5000 lines to begin with).
-
I think you've missed a VERY big point of OOP....data hiding. I often tell OOP beginners that if I see more than a few Get/Set type methods for anything but a container class, I know that they didn't write it properly..... I prefer to "inject" data or other objects into your object and avoid trying to get data back out of the object. Why?? Well data is usually not worth much, but information is! The data placed into anything but a container object should typically be used to generate information rather than spitting it back out in its original form. Another benefit of avoiding public data: You can "force" the way that data is injected into your object. If, for example, the object has 5 members, it is possible (as has frequenctly been the case in my code) that in one case you set 3 of the values, but in another case, only 2 specific values should be set....buy using a method which takes 3 values in one case, and 2 values in the other, you can make sure that the user of your class (which may be you a year later) uses the class properly. Using these ideas, I reworked a co-workers code...he told me he used public data because he just wanted something that was easy to work with....as a result, he had functionality spread throughout 10 classes with a fair amount of similar code in multiple places. When I was done, not only was it much easier to use the class (by his admisssion, not my judgement), but it also meant that the code base was much smaller (about 2000 lines of code were removed from a section of code with 5000 lines to begin with).
I agree with you, for the most part. However, I think you're thinking too much about business logic and not so much about things like GUI framework classes and the like which don't provide "information" but rather provide structure to your application. Of course, most of the work I do is structural in nature. For instance, much of my work is front end development for laser machining systems. While there's a lot of backend work as well, the majority of our work is visual (but hooked into real-time data).
-
I think someone taught you the wrong definition of OOP. OOP says nothing about Getters or Setters, but rather interfaces. Treating instances (objects) of a type (class) as single entities with their own state. OOP is designed to model the way we work with things in real life. For instance, your Television set has many things which are getters/setters, such as the channel changer or volume control, however it also has "public data" in the form of the speaker and picture tube. We, the object client have direct access to this data without having to manipulate an interface to do so. Imagine if we had to flip a switch evertime we wanted to get a frame of image data or a cycle of sound. When it makes sense, public data is perfectly acceptable and doesn't violate encapsulation. Encapsulation only makes sense when dealing with object state, and seldom with object data. Does exposing m_pMainWnd in CWinApp violate encapsulation? Not really, since if you are accessing it from outside the CWinApp derived class, that means the MainWnd exists, and it's not going to change (if using the framework as designed). Further, changing the pointer doesn't effect CWinApp's internal state, so there is nothing to update. My point is really that encapsulation is something important, but it only really applies when you need to encapsulate something.
Well, I think you and I fundamentally disagree on the issue. As one of the few old C guys who eagerly adopted the OOP paradigm I frankly think that modeling "the way we work with things in real life" is malarky. Programming of any kind is an excercise in the controlled management of data. OOP is a philosophy about how data should be managed. (Notice the "period" at the end of that sentence.) It does provide those who wish to model the real world with a more convenient conceptual framework than, say, assembly language does, but you could, in fact, model the real world in assembly language, or even machine language if you wanted to. Different languages enforce the principles of that philosophy to lesser or greater degrees, but the philosophy is the same - encapsulation, inheritance, polymorphism. The "interface" is obviously fundamental to that process, but some sort of "get/set" methodology is fundamental to that interface. Furthermore, MFC is a perfectly awful example of OOP and the example you cite is one of many that could be cited. I would not second guess the guys at Microsoft. They made the decisions they did for, I am sure, sound engineering reasons. But, yes, exposing m_pMainWnd, for example, does diminish MFC's claim to be truly OO as you will find out if the next guy you hire adds a view to the app which has this: AfxGetApp()->m_pMainWnd = NULL;. A true OO design would simply not allow that. Finally, if your design does not require encapsulation than, generally speaking, you should not be wasting your time with the inherent overhead of OOP.
-
IMHO, a View should have knowledge of a Doc, and a Doc definately not of a View. The view needs to know about the doc, because it needs to draw the contents of the document. The document has nothing to do with the view, because it doesn't have to know what should be drawn, and on what device context. For that matter, the Doc should contain no functions related to displaying or printing a document. The doc only needs to known what it should do with members (objects) belonging to a document itself, and ofcourse related functions such as serializing etc. I'm certain you can't always have a perfect OOD or OO application, but you can at least try as hard as possible. Unfortunately, OO means in most cases loss of performance. Two things you have to think of.. speed and maintainability.. hard to choose. -- Alex Marbus www.marbus.net
If the View class is aware of the data in the Doc class shouldn't Doc's members be private without accessors and the view be a friend? The View has to be aware of the data to render it anyway; and the View should only be accessing Doc's members, not modifing them. (This design is defeated by the view and the controller being integrated in CView, but for argument's sake.) The design is always specific to the task. The trouble is predicting how the class will be used in the future. E.g.
// The difference is Square is an object and Doc/View is a design pattern.
class Square
{
public:
void Draw(CDC *pDC);
protected:
CRect m_rect;
};class Doc
{
// accessor or public member irrelevant to this example.
public:
Square m_shape;
};void View::OnDraw(CDC *pDC)
{
Doc *pDoc = GetDocument();
pDoc->m_shape.Draw(pDC);
}This makes Square responsible for rendering itself and allows Square to change as needed. For example, I decide to add color to the Square. Only Square::Draw() needs to be modified to add color, not all the Views (and who knows what else) using Square. The alternative would require each View be modified to display the Square in color. This would allow more control over the display.
-
I agree with you, for the most part. However, I think you're thinking too much about business logic and not so much about things like GUI framework classes and the like which don't provide "information" but rather provide structure to your application. Of course, most of the work I do is structural in nature. For instance, much of my work is front end development for laser machining systems. While there's a lot of backend work as well, the majority of our work is visual (but hooked into real-time data).
I agree that a GUI framework provides structure, but for the vast majority of GUI work, I don't want to "get" something....I want to set it....so from this perspective, the class which I'm setting is providing information....and in this case its the GUI which the user sees. Now there comes a time when what the user enters must be pulled from the screen, keyboard, mouse, or other device....well I've found that compared to the amount of information I have to give an application to display something, getting it back is fairly easy. I also do a fair amount of GUI work....and I find that it conforms to OOP very well....remember than OOP has three 3 major requirements: Inheritance Polymorphism Data hiding Last year I went through the code of a co-worker...he swore he was doing OOP developmet....but he never used Inheritance beyond what the MSVC class wizard provided for forms and dialogs, and as a result never created a class which contained a virtual function of his own. All his dialog variables were public members, and it was hard to determine what needed to be set in the dialog where there were multiple conditions. What further compounded this was that his dialogs were "dumb"....they couldn't take something like a recordset and populate themselves.....so the the calling class had to know exactly what the dialog could take and how it had to be taken rather than letting the dialog do it for itself. As a rule of thumb, I've found that we developers don't use OOP techniques...instead we conform to "Wolfensbergers Law" (hey....I thought it up so why can't I name it after myself!?!) Wolfensberger's Law: The benefits of OOP techniques increases as more features or more complexity is required. Many problems start out being easy to solve using non-OOP techniques, but over time may need to be reworked to make the code maintainable. Its not important if you start out with an OOP solution...its only important that you convert to an OOP solution early enough to keep from wasting time and effort maintaining the non-OOP solution.
-
I agree that a GUI framework provides structure, but for the vast majority of GUI work, I don't want to "get" something....I want to set it....so from this perspective, the class which I'm setting is providing information....and in this case its the GUI which the user sees. Now there comes a time when what the user enters must be pulled from the screen, keyboard, mouse, or other device....well I've found that compared to the amount of information I have to give an application to display something, getting it back is fairly easy. I also do a fair amount of GUI work....and I find that it conforms to OOP very well....remember than OOP has three 3 major requirements: Inheritance Polymorphism Data hiding Last year I went through the code of a co-worker...he swore he was doing OOP developmet....but he never used Inheritance beyond what the MSVC class wizard provided for forms and dialogs, and as a result never created a class which contained a virtual function of his own. All his dialog variables were public members, and it was hard to determine what needed to be set in the dialog where there were multiple conditions. What further compounded this was that his dialogs were "dumb"....they couldn't take something like a recordset and populate themselves.....so the the calling class had to know exactly what the dialog could take and how it had to be taken rather than letting the dialog do it for itself. As a rule of thumb, I've found that we developers don't use OOP techniques...instead we conform to "Wolfensbergers Law" (hey....I thought it up so why can't I name it after myself!?!) Wolfensberger's Law: The benefits of OOP techniques increases as more features or more complexity is required. Many problems start out being easy to solve using non-OOP techniques, but over time may need to be reworked to make the code maintainable. Its not important if you start out with an OOP solution...its only important that you convert to an OOP solution early enough to keep from wasting time and effort maintaining the non-OOP solution.
With GUI's (especially Windows) you often DO need to get something. For instance, if you want to modify the caption of the title bar, you need to first get the caption then modify it, then reset it. Of course you could hold onto your own copy of the caption, but that introduces another variable which can become desynched to the current state of the title if that title gets set somewhere else. I prefer to keep as few state objects as possible and rely on the objects to keep their own state, so rather than keep my own string with the title, I extract the title from the titlebar and modify it. Or I check the value of the checkbox first then use that to determine my state rather than keeping a boolean seperate from it. So, indeed, i think it is good to get data from objects in many circumstances, since doing so reduces the likelihood of error in other ways.
-
Well, I think you and I fundamentally disagree on the issue. As one of the few old C guys who eagerly adopted the OOP paradigm I frankly think that modeling "the way we work with things in real life" is malarky. Programming of any kind is an excercise in the controlled management of data. OOP is a philosophy about how data should be managed. (Notice the "period" at the end of that sentence.) It does provide those who wish to model the real world with a more convenient conceptual framework than, say, assembly language does, but you could, in fact, model the real world in assembly language, or even machine language if you wanted to. Different languages enforce the principles of that philosophy to lesser or greater degrees, but the philosophy is the same - encapsulation, inheritance, polymorphism. The "interface" is obviously fundamental to that process, but some sort of "get/set" methodology is fundamental to that interface. Furthermore, MFC is a perfectly awful example of OOP and the example you cite is one of many that could be cited. I would not second guess the guys at Microsoft. They made the decisions they did for, I am sure, sound engineering reasons. But, yes, exposing m_pMainWnd, for example, does diminish MFC's claim to be truly OO as you will find out if the next guy you hire adds a view to the app which has this: AfxGetApp()->m_pMainWnd = NULL;. A true OO design would simply not allow that. Finally, if your design does not require encapsulation than, generally speaking, you should not be wasting your time with the inherent overhead of OOP.
Look, there will always be ways to violate things. Your example of someone setting m_pMainWnd to NULL is meaningless. If you make sure it's not NULL, what happens if they set it to 1? Or a random number? What if someone does memset(&yourobject, 0, sizeof(yourobject))? What if someone derives from your class and changes the privates to publics in their derived class? You can't stop people from doing stupid things. Further, if you were to put bounds checking on every set variable in your app, you're likely to create a lot of overhead. A class library is useless if people won't use it because it's too slow. And what about const pointers? Do you maintain that a const pointer shouldn't be exposed? You've essentially removed the ability to change the value, so your argument is rather moot. What is the point of having a getter for any const member? It will never and cannot change during the lifetime of the class. My point is simply this. OOP says nothing about hiding *ALL* your data. Many might consider this to be a good idea, but it's not a hard and fast rule defined by any definition of OOP i've ever read. Thus, your statement that if you're not using Getters and Setters, you're not doing OOP is indefensible. If you believe otherwise, then be my guest and provide some references to experts in the field who have written such.
-
Look, there will always be ways to violate things. Your example of someone setting m_pMainWnd to NULL is meaningless. If you make sure it's not NULL, what happens if they set it to 1? Or a random number? What if someone does memset(&yourobject, 0, sizeof(yourobject))? What if someone derives from your class and changes the privates to publics in their derived class? You can't stop people from doing stupid things. Further, if you were to put bounds checking on every set variable in your app, you're likely to create a lot of overhead. A class library is useless if people won't use it because it's too slow. And what about const pointers? Do you maintain that a const pointer shouldn't be exposed? You've essentially removed the ability to change the value, so your argument is rather moot. What is the point of having a getter for any const member? It will never and cannot change during the lifetime of the class. My point is simply this. OOP says nothing about hiding *ALL* your data. Many might consider this to be a good idea, but it's not a hard and fast rule defined by any definition of OOP i've ever read. Thus, your statement that if you're not using Getters and Setters, you're not doing OOP is indefensible. If you believe otherwise, then be my guest and provide some references to experts in the field who have written such.
And I agree, Erik, there are many good, legitimate, professionally sound reasons to violate the principles of OOP. My only point, is that when you do it you should be aware that you have done it and those with whom you are working should be aware you have done it. If you expose the data of a class outside the boundaries defined by the interface for that class than your design is not OO. If you feel that you have a professionally sound reason to do that, than do it. Just don't turn around, hand the project to me, and tell me it is OO. If the principles of OO have been violated - I want to know where and why. I don't think that is asking too much. As far as experts go, is Bjarne Stroustroup (sic?) good enough? He goes so far as to discourage even the use of "protected" data in base classes. So, even for derived classes there should be some sort of get/set mechanism to access the parent class's data. My final word on the subject is that I think MFC has done a lot to distort what constitutes good OO design in the minds of younger programmers. I think MFC, with all of its flaws, is a generally useful product, I use it all the time myself, but it is not the source one would turn to to be a "good" OO coder. It may be a good example of how to deal with the neccessities forced on us by real world constraints, and how to hack your way around tough workaday problems - but good OO design? No way.
-
With GUI's (especially Windows) you often DO need to get something. For instance, if you want to modify the caption of the title bar, you need to first get the caption then modify it, then reset it. Of course you could hold onto your own copy of the caption, but that introduces another variable which can become desynched to the current state of the title if that title gets set somewhere else. I prefer to keep as few state objects as possible and rely on the objects to keep their own state, so rather than keep my own string with the title, I extract the title from the titlebar and modify it. Or I check the value of the checkbox first then use that to determine my state rather than keeping a boolean seperate from it. So, indeed, i think it is good to get data from objects in many circumstances, since doing so reduces the likelihood of error in other ways.
I absolutely agree that there are things which you need to get from a class....the window position and size for example. A data value associated with a list control item.....the index of a combo box selection. But to be honest, I doubt very much that its a good idea to use the current caption of a window to create another caption....unless all you are doing is adding a string to the end of it, I suspect that you're parsing the string to break it into data parts which could be maintained in the owner object in their original form. But I also think your example also illustrates an important point: I think no one would argue that duplicate data is a good thing, and if the caption is simply a duplicate string, why store it twice...but if it is composed from one or more pieces of data, I would prefer to store the data and generate the string dynamically. To restate my point with more clarity, a large number of Get/Set methods simply to hide data members for non-container classes indicates poor OOP design....and GUI items like checkboxes and edit boxes need something to let you know what they contain....but lets think about this for a second: The original post asked why to hide data....well in the case of an edit box, you could expose the string displayed on the screen....ok people can deal with that....but what if you get tired of converting the string to a float, int, or date?? Well add a few methods which get "information" -- not the raw string which I consider data. I think we can all agree that in this case, its OBVIOUS that the better choice is to hide the data. Does this create "Get" type methods?? Yes....are these the typical Get/Set methods which simple hide the data?? No....they include functional improvements to the data. So, again, I am not against having a method which allows you to pull information from an object....one way objects aren't much value. But I am 100% in favor of object being able to return information rather than just echoing data.
-
And I agree, Erik, there are many good, legitimate, professionally sound reasons to violate the principles of OOP. My only point, is that when you do it you should be aware that you have done it and those with whom you are working should be aware you have done it. If you expose the data of a class outside the boundaries defined by the interface for that class than your design is not OO. If you feel that you have a professionally sound reason to do that, than do it. Just don't turn around, hand the project to me, and tell me it is OO. If the principles of OO have been violated - I want to know where and why. I don't think that is asking too much. As far as experts go, is Bjarne Stroustroup (sic?) good enough? He goes so far as to discourage even the use of "protected" data in base classes. So, even for derived classes there should be some sort of get/set mechanism to access the parent class's data. My final word on the subject is that I think MFC has done a lot to distort what constitutes good OO design in the minds of younger programmers. I think MFC, with all of its flaws, is a generally useful product, I use it all the time myself, but it is not the source one would turn to to be a "good" OO coder. It may be a good example of how to deal with the neccessities forced on us by real world constraints, and how to hack your way around tough workaday problems - but good OO design? No way.
Bjarne does in fact discourage the use of protected data, but he didn't always feel that way or he wouldn't have made protected data in the first place. Further, C++ isn't truly an OO language. It's a hybrid and doesn't offer certain things you might expect from a "true" OO language such as SmallTalk. Many things in C++ are not objects in their own right, such as POD's (Plain Old Data). An int isn't an object in C++. Technically, using C++ at all isn't doing OOP if you want to be technical, but in reality we can say that C++ offers a good deal of OOP in a realistic way. OOP talks of sending messages beteween objects, which C++ doesn't really offer, though calling member functions is about the next best thing. Windows does offer a form of message passing, but C++ itself doesn't. It's quite silly to get all defensive about "not doing oop" in C++ when the language itself is not really OOP even when using it in the way intended by its creator. It's all a hybrid, and where one draws the line is largely a subjective judgement by those using it. As i've said. I see nothing wrong with accessing members directly that are const or effectively const. This doesn't violate encapsulation in any form because the members cannot be calculated or changed. I also don't see how they can violate OOP since even calling getters and setters violates OOP in it's purest form.