473,398 Members | 2,188 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,398 software developers and data experts.

Encapsulation philosophy question

I have run into a design question that I don't have strong feelings about
one way or the other, so I'm curious what the OOP gurus think about it. :)

A recent post led me to suggest using a state graph, which got me to
wanting to fiddle with a state graph implementation in .NET. So far, so
good. I even have some very simple code that solves his problem (or
perhaps only part of it...he wasn't really specific as to what his
requirements were).

Part of the stated problem though allowed for the possibility of wanting
to maintain multiple concurrent states for the graph.

As I originally implemented it, only the state graph is visible to the
client code. It uses the usual linked node mechanism internally, but the
client never sees this. The client just gives it a new state transition
value (char type in this case), and gets back the data associated with the
new state. To maintain multiple concurrent states for the graph would
require choosing from one of at least four possibilities:

!) Multiple instances of the state graph itself. Within this
possibility, there are actually two variations:
-- Complete clone of the state graph
-- Shallow clone of the state graph
Because I don't really like either of those options, I didn't
consider this option at all for very long: a complete clone seems
wasteful, and inefficient if the client has a need to change the state
graph later, while the shallow clone creates a not-very-nice situation in
which changing one instance would change all the other instances (even
though that would likely be the behavior the client would normally desire,
I don't feel that forcing that on the client is a good design).

2) Moving the state transition methods into the state class itself,
and having the client use that to operate within the graph. The main
reason I don't like that is that to do that would require that each and
every state instance would have to maintain some information about the
parent graph, or alternatively would have to maintain a "default state"
value to return back to the root state for transitions not explicitly
specified.

I have to admit, now that I've written that, my objection to #2 seems a
little petty, but I am having trouble getting past the "a state graph is
already a memory-hungry solution, why make things worse by adding a copy
of the same reference to every single node of the state graph when I could
just access that value from outside the state node directly?" issue.

3) Exposing at least to some limited degree the actual node reference
from within the state graph.

4) Creating a new, public class that's part of the state graph that's
specifically used for traversing the graph, and in which is contained (but
hidden from the client) the node reference.

I'm finding myself ambivalent choosing between #3 and #4. I like #3
because it's reasonably efficient. I don't have to expose the actual node
type to the client; I can just have a public abstract base class, or even
just use "object" if I want. But there's something that just seems a
little "off" to me with respect to handing over a reference to the client
and saying "here, hold this...you'll need it every time you want to access
or change the state of the graph, and I'll give you a new one any time the
state changes".

I like #4 because it's closer to what I feel the client is doing. They
get a state graph, and then to move about in the state graph, they get a
traversal object that they can use to do that. Sort of like an
enumerator. But it seems a bit wasteful to me, because for each
concurrent maintained state of the graph, you get two references instead
of just one (basically, you have a reference to a reference). It's not as
bad as my objection to option #2, since there will always be many fewer
concurrently maintained states of the graph than there are nodes in the
graph. But it still seems wasteful.

Now, taking as granted that I am obviously overthinking this question,
here's what I am actually looking for an answer to:

From a _design_ perspective, would you prefer #3 or #4 as the mechanism?
Note that I'm not actually asking about the memory performance issues
here, since I readily acknowledge that for all my fixation on that, it's
likely not to be all that relevant. What I really want to know is from
the point of view of encapsulating and keeping the client on a strictly
"need-to-know" basis, is it worth adding a new class a la #4, or is it
reasonable to ask the client to hang on to my traversal state for me?

What say you, oh those who live and breath OOP?

Pete
Jun 23 '07 #1
1 1118
Peter Duniho wrote:
I have run into a design question that I don't have strong feelings about
one way or the other, so I'm curious what the OOP gurus think about it.
:)

A recent post led me to suggest using a state graph, which got me to
wanting to fiddle with a state graph implementation in .NET. So far, so
good. I even have some very simple code that solves his problem (or
perhaps only part of it...he wasn't really specific as to what his
requirements were).

Part of the stated problem though allowed for the possibility of wanting
to maintain multiple concurrent states for the graph.

As I originally implemented it, only the state graph is visible to the
client code. It uses the usual linked node mechanism internally, but the
client never sees this. The client just gives it a new state transition
value (char type in this case), and gets back the data associated with the
new state. To maintain multiple concurrent states for the graph would
require choosing from one of at least four possibilities:

!) Multiple instances of the state graph itself. Within this
possibility, there are actually two variations:
-- Complete clone of the state graph
-- Shallow clone of the state graph
Because I don't really like either of those options, I didn't
consider this option at all for very long: a complete clone seems
wasteful, and inefficient if the client has a need to change the state
graph later, while the shallow clone creates a not-very-nice situation in
which changing one instance would change all the other instances (even
though that would likely be the behavior the client would normally desire,
I don't feel that forcing that on the client is a good design).

2) Moving the state transition methods into the state class itself,
and having the client use that to operate within the graph. The main
reason I don't like that is that to do that would require that each and
every state instance would have to maintain some information about the
parent graph, or alternatively would have to maintain a "default state"
value to return back to the root state for transitions not explicitly
specified.

I have to admit, now that I've written that, my objection to #2 seems a
little petty, but I am having trouble getting past the "a state graph is
already a memory-hungry solution, why make things worse by adding a copy
of the same reference to every single node of the state graph when I could
just access that value from outside the state node directly?" issue.

3) Exposing at least to some limited degree the actual node reference
from within the state graph.

4) Creating a new, public class that's part of the state graph that's
specifically used for traversing the graph, and in which is contained (but
hidden from the client) the node reference.

I'm finding myself ambivalent choosing between #3 and #4. I like #3
because it's reasonably efficient. I don't have to expose the actual node
type to the client; I can just have a public abstract base class, or even
just use "object" if I want. But there's something that just seems a
little "off" to me with respect to handing over a reference to the client
and saying "here, hold this...you'll need it every time you want to access
or change the state of the graph, and I'll give you a new one any time the
state changes".

I like #4 because it's closer to what I feel the client is doing. They
get a state graph, and then to move about in the state graph, they get a
traversal object that they can use to do that. Sort of like an
enumerator. But it seems a bit wasteful to me, because for each
concurrent maintained state of the graph, you get two references instead
of just one (basically, you have a reference to a reference). It's not as
bad as my objection to option #2, since there will always be many fewer
concurrently maintained states of the graph than there are nodes in the
graph. But it still seems wasteful.

Now, taking as granted that I am obviously overthinking this question,
here's what I am actually looking for an answer to:

From a _design_ perspective, would you prefer #3 or #4 as the mechanism?
Note that I'm not actually asking about the memory performance issues
here, since I readily acknowledge that for all my fixation on that, it's
likely not to be all that relevant. What I really want to know is from
the point of view of encapsulating and keeping the client on a strictly
"need-to-know" basis, is it worth adding a new class a la #4, or is it
reasonable to ask the client to hang on to my traversal state for me?

What say you, oh those who live and breath OOP?

Pete
Hi Pete,

Quite interesting. I've got to say I quite like number 3, because it's
basically a context or a token you're giving to the client, which is a
design pattern you see around (think threading/security contexts). Giving
the client a context to operate in also allows some extensibility, if you
need to expand your state graph implementation.

You've mentioned a couple of drawbacks to number 1, but if you want to get
REALLY REALLY complicated you could make it very efficient, by implementing
a copy-on-write mechanism. So, you maintain a shallow copy of the state
graph, and if/when it gets changed, only the affected parts are copied.
Quite a non-trivial thing to implement, but very efficient if you do manage
to do it - there are a number of file-systems that do this (for example the
upcoming Btrfs file-system from Oracle, ext3cow, ZFS and even NTFS to some
extent). But I digress.

--
Tom Spink
University of Edinburgh
Jun 23 '07 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

22
by: Tuang | last post by:
I'm checking out Python as a candidate for replacing Perl as my "Swiss Army knife" tool. The longer I can remember the syntax for performing a task, the more likely I am to use it on the spot if...
2
by: Adriano Monteiro | last post by:
Hey folks, I wanna know more about encapsulation in python. Is it fully suported? How can I define the encapsulation statements for methods and attributes? Regards! 's!
3
by: enchantingdb | last post by:
I have an exam tomorrow that covers the perceived advantages and disadvantages of object oriented programming, in particular polymorphism, inheritance and encapsulation. I know the advantages but...
6
by: William H. Burling | last post by:
I am not sure I understand encapsulation. I thought that one of the objectives in OOPs is to hide data structures from other objects so that they did not have to know how to unpack them. ...
5
by: jmsantoss | last post by:
Hi, This is a design question. I have a class named "DataBuffer" that stores some data. After "DataBuffer" is created it can not be modified. All the methods of "DataBuffer" are const as data...
47
by: Roger Lakner | last post by:
I often see operator implemented something like this: class Foo { ... }; class FooList { public: const Foo& operator (unsigned index) const {return array;}; Foo& operator (unsigned index) ...
22
by: Xah Lee | last post by:
The Nature of the “Unix Philosophy” Xah Lee, 2006-05 In the computing industry, especially among unix community, we often hear that there's a “Unix Philosophy”. In this essay, i...
32
by: bluejack | last post by:
Ahoy: For as long as I've been using C, I've vacillated on the optimal degree of encapsulation in my designs. At a minimum, I aggregate data and code that operate on that data into classlike...
2
by: subramanian100in | last post by:
Is my following understanding correct ? Data abstraction means providing the interface - that is, the set of functions that can be called by the user of a class. Information hiding means...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.