Advertisement

Internal or External data tracking?

Started by March 07, 2003 07:06 AM
10 comments, last by Dauntless 21 years, 10 months ago
quote:
Original post by Diodor
Whenever a class accesses data from another class, the project becomes more "connected", and as such less elegant, less maintainable. Whenever a class needs information from another class, a decision must be made whether to allow it (at the expense of elegance) or not (at the cost of redesign). The quality of the program depends on how good these decisions are, and less on the communication protocols between classes.

That''s not quite accurate. The choice of communication protocols is a direct function of the quality of decisions made with respect to the level of cohesion and coupling between the classes - a design decision.

quote:
If later in the project a decision is made that some class needs to read or even modify members of the World_Data class, no private modifiers will stop the determined programmer from letting the other class modify these members. Strongly enforcing the access rights between classes using C++ features or using simple comments to achieve the same thing are a matters of estethics, not substance.

I completely disagree. Strongly enforcing access rights are fundamental design decisions, effected to insulate client code from library changes (interface consistency). If class A uses class B and class B''s implementation is constantly changing (due to new techniques or whatever) but its interface remains the same, then class A does not need to be modified, or even recompiled if class B instances are being dynamically retrived from a shared library (DLL/.so). If, OTOH, it had been decided that class A should reach across class boundaries (because class B made data public to class A) and class B changes, then class A needs to be modified - which can become a maintenance nightmare.

There is a reason for public, private and protected access in C++. There is a reason for packages in Java and the corresponding concept in UML and other modeling tools. Classes within the same package are considered to be co-features, and therefore should be the only other classes ever given access to private data and methods (since packages are released at a consistent version number, all the classes within it must be maintained together). Any package B only uses a lower-level package A through public classes and their published interfaces (note that Java also has private classes, only visible within the package), and this strict stratification helps to develop reusable components which accelerates the overall software engineering process in the long term.

quote:
Original post by Dauntless
Heck, I wish I had a CS degree....I''m totally self-taught about computers. From networking, to hardware to programming I''ve pretty much studied on my own. And while self-study is great at teaching you what NOT to do (when you fudge up and realize you need to do something different) it doesn''t really tell you the right way to do something the first time either.

I feel you. I was completely self-taught (and I''d like to think I''d done a good job) before I transferred to UNCG, though I read as many books as I could get my hands on. But even still, there was so much material that I never would have been introduced to had I not taken CS classes in college. My suggestion is for you to go to your local community college if a CS degree just isn''t feasible and enroll for a couple of classes (advanced data structures, software engineering). You''ll be glad you did.

quote:
But I''m gaining some really good insights here. I''m still grappling with the concepts of public and private access methods. When I first learned them, I was like, "why bother with the indirect access of setting private member data or calling private member functions?". To be honest I still have a hard time understanding data hiding and encapsulation. I realize that there are essentially two kinds of programmers....clients that use libraries and objects, and designers who actually build the libraries. I guess my problem in understanding data hiding is figuring out why the designer doesn''t always want the client to know how certain code works...i.e. the private interfaces.

Insulation from change. If I design a library - say, libOluseyi - and you''re using it in your application, how happy would you be if with every new version you had to rewrite your code because mine changed? By using abstraction and data hiding, you don''t know or care how my methods are implemented, and I write methods at a higher level of abstraction than the basic operations I perform - InitializeNetworkConnection() as opposed to CreateSocket(), GetSocketProperties(), etc. This way, even when I completely change the internal workings of my socket library (say, switching from BSD sockets to WinSock2 on Win32) your code doesn''t need to change. All you''ll do is recompile or relink - in some cases not even that, if I provide libOluseyi in a DLL for example - and you''re done.

quote:
As for the friend vs. public access communication methods I''m not really sure what would suit my game better. In some ways, being a friend makes more logical sense, since one class is closely related and works together with the other class (the unit class and the World_Data class). On the other hand, I''m not sure if having a public call to Unit::CommTest() would have any "fragile" logic associated with it. The only disadvantage I can see is that if like Oluseyi said, by having new add-ons with new features that utilize different code to work...I guess it might be a hassle. I had originally thought of doing it like Diodor said because it''s easier for me to think in terms of public access, but now that Oluseyi mentioned the friend access method, it would allow for better data hiding.

I honestly think the external database method is the best option, but I leave the choice to you. Nothing teaches better than experience - not even after a Ph.D. At the very least, try the various architectures on a small scale and see which requires the least code, which provides the most security (in terms of protection from programmer error), which is the most scalable, which is the most maintainable...

Good luck!
An example off the top of my head to illustrate why encapsulation can be useful: the unit needs to know what local visibility is like - a value that properly belongs to the terrain (based on ground cover and elevation) so it need to obtain the (precalculated) value. In case A, the visibility is made directly accessible to the unit (friend or public). In case B, a public method (GetVisibility()) is created.
Locally variable weather effects are then implemented, so each interval, all terrain objects have their local weather and visibility updated. No problems so far. Then the decision is made that the calculation of weather effects on visibility is slowing the game down too much. To get round this, calculation of visibility is only made when required. In case A, this means changing the unit code to call terrain.UpdateVisibility() each time it accesses terrain.visibility. In case B, this simply means moving the call to UpdateVisibility() from SetWeather() to GetVisibility(), without changing the unit class at all. Not the greatest of differences, but it''s more likely that you''d miss an access in case A than that you''d overlook the single copy of GetVisibility in case B...

This topic is closed to new replies.

Advertisement