Good Design - Example

  • Thread starter Thread starter KV
  • Start date Start date
K

KV

I'm new to OO Design, and I'm fixing to start writing my very first C#
program. Given the complexity of OO programming, I would like to run
something by this group and get general input.

My example is a program called HijackThis. I'm sure many are familiar
that it is a spyware removal tool. The program looks at over 20 places
on Windows computers to see what is starting (with options to remove the
offending software). The program can remove browser helper objects,
browser homepage settings, programs in the run key of the registry, etc.

My first question - How do you think the author structured this program?
Would dividing the program up into 20 classes, one for each problem
area, be sufficient? That seems like a lot of classes, given that each
problem isn't too complicated. Should extra classes be avoided just
because they are simple? If that's the case, and I need to consolidate,
then how would I do it? Would I lump everything into one massive class?
Why? Where do I draw the line?

Second question - in action-oriented programming, we come up with a
bunch of different functions that are reusable, such as a generic
database access function or a generic ftp function. In this example, if
we use 20 classes, each class will likely much of the same method code
to access the registry. Does that mean I need a registry class with
public methods to manipulate the registry? If I understand the thrust
of OO programming, the main goal is that the class be reusable and not
dependent (coupled) with other classes or components. Such a registry
class seems like it wouldn't violate OO principles. But documentation
on such a class seems scarce. You would think there would be many
example classes out there for such a common operation. I can't help but
wonder if something hasn't sunken into my pea-sized brain.

Third question - I want to duplicate the BHO portion of HijackThis,
which would be a basic BHO remover with backup capabilities and a simple
interface. How would you, personally, design such a program?

Shifting my thinking after several years of programming the "other" way
is proving more difficult than I imagined (but I'm getting there, albeit
slowly). Nobody in my company does object-oriented programming, so I
don't have anybody to ask. Your help would be greatly appreciated.

-KV
 
Your question is rather nebulous to say the least. Some key phrases for you.

Common Sense:
Understand the Problem:
Planning:
Design:
TestPlan:
Refactoring:
Re-Design
TestPlan:
Re-test
Implementation:
Debugging




--
OHM ( Terry Burns ) * Use the following to email me *

Dim ch() As Char = "ufssz/cvsotAhsfbuTpmvujpotXjui/OFU".ToCharArray()
For i As Int32 = 0 To ch.Length - 1
ch(i) = Convert.ToChar(Convert.ToInt16(ch(i)) - 1)
Next
Process.Start("mailto:" & New String(ch))
--
 
KV said:
I'm new to OO Design, and I'm fixing to start writing my very first C#
program. Given the complexity of OO programming, I would like to run
something by this group and get general input.

My example is a program called HijackThis. I'm sure many are familiar
that it is a spyware removal tool. The program looks at over 20 places
on Windows computers to see what is starting (with options to remove the
offending software). The program can remove browser helper objects,
browser homepage settings, programs in the run key of the registry, etc.

My first question - How do you think the author structured this program?
Would dividing the program up into 20 classes, one for each problem
area, be sufficient? That seems like a lot of classes, given that each
problem isn't too complicated. Should extra classes be avoided just
because they are simple? If that's the case, and I need to consolidate,
then how would I do it? Would I lump everything into one massive class?
Why? Where do I draw the line?

I take a look at project and OOD like this:
What tasks need to be done and then look at the relationship between
them-What do i need to interface to? Each of those interfaces are usually an
object, or collection of objects--like in a gui, by themselves. Then what is
my objective--what do i need to do--this usually breaks appart into 1 or more
data components (objects) and thier associated methods. Then how am i going
to fit it all together control logic/objects--basically i break things into:
interface objects (io, gui, etc), data object (in memeory use), and control
objects (make it all hang together). I keep things as homogeniously grouped
as possible or makes sense.
Second question - in action-oriented programming, we come up with a
bunch of different functions that are reusable, such as a generic
database access function or a generic ftp function. In this example, if
we use 20 classes, each class will likely much of the same method code
to access the registry. Does that mean I need a registry class with
public methods to manipulate the registry?

yes, a registry object would be a good thing to have. try to keep things as
cohesive as possible in their granularity, but at some point too, you just
have to use some of your own prefernce--instead of 20 tiney objects maybe one
moderate "utility" object might be in order.
If I understand the thrust
of OO programming, the main goal is that the class be reusable and not
dependent (coupled) with other classes or components. Such a registry
class seems like it wouldn't violate OO principles. But documentation
on such a class seems scarce. You would think there would be many
example classes out there for such a common operation. I can't help but
wonder if something hasn't sunken into my pea-sized brain.

Generally this will result--eventually--in a code base that you can
use/modify for each project and will speed up your coding time. It can in
reality become all but useless or nightmare if not documented well and
militantly.
Third question - I want to duplicate the BHO portion of HijackThis,
which would be a basic BHO remover with backup capabilities and a simple
interface. How would you, personally, design such a program?

I don't know what a BHO is, but basically I design all my programs the same
way--interfaces, data, control.
Shifting my thinking after several years of programming the "other" way
is proving more difficult than I imagined (but I'm getting there, albeit
slowly).

I sympathize, it took me quite a while to shit even to the windows model of
thinking--code paths that sit essentially dead until an external event brings
them to life. Now the full OOD is a little easier to do, I actually leaned
OOD in college, but didn't get to use it for several years in the real world.

If my ranblings have helped, good, if not may another more skilled than I
have a shot. In either case: best of luck to you.
 
KV said:
I'm new to OO Design, and I'm fixing to start writing my very first
C# program. Given the complexity of OO programming, I would like to
run something by this group and get general input.

My example is a program called HijackThis. I'm sure many are
familiar that it is a spyware removal tool. The program looks at
over 20 places on Windows computers to see what is starting (with
options to remove the offending software). The program can remove
browser helper objects, browser homepage settings, programs in the
run key of the registry, etc.

My first question - How do you think the author structured this
program? Would dividing the program up into 20 classes, one for
each problem area, be sufficient? That seems like a lot of classes,
given that each problem isn't too complicated. Should extra classes
be avoided just because they are simple? If that's the case, and I
need to consolidate, then how would I do it? Would I lump everything
into one massive class? Why? Where do I draw the line?

Second question - in action-oriented programming, we come up with a
bunch of different functions that are reusable, such as a generic
database access function or a generic ftp function. In this example,
if we use 20 classes, each class will likely much of the same method
code to access the registry. Does that mean I need a registry class
with public methods to manipulate the registry? If I understand the
thrust of OO programming, the main goal is that the class be reusable
and not dependent (coupled) with other classes or components. Such a
registry class seems like it wouldn't violate OO principles. But
documentation on such a class seems scarce. You would think there
would be many example classes out there for such a common operation.
I can't help but wonder if something hasn't sunken into my pea-sized
brain.

Third question - I want to duplicate the BHO portion of HijackThis,
which would be a basic BHO remover with backup capabilities and a
simple interface. How would you, personally, design such a program?

Shifting my thinking after several years of programming the "other"
way is proving more difficult than I imagined (but I'm getting there,
albeit slowly). Nobody in my company does object-oriented
programming, so I don't have anybody to ask. Your help would be
greatly appreciated.

-KV

Hi KV,

I am kind of surprised you didn't get more of a response from your
question to be honest.

Don't be afraid to have lots of small specific classes, when in doubt
look at the .NET framework classes themselves, they are (mosty) small
and very specific to a particular task. By the way 20+ is *not* a lot,
a few tens of thousands are a lot ;-)

Your example that you cite is a very good example as to why you would
architect your classes that way, the thing about adware is that you are
fighting a moving target, once you figure out how to stop one part of
it they go and do somthing else, so your 20+ tasks over time might
become 30+ now if this is all in one mega class, it will quickly become
messy and unmaintainable.

If you wanted to be adventurous you could design it in such a way as to
be able to add new tasks by just dropping a new assembly into a
"plugins" directory so that you can keep the app up to date to combat
the latest threat, (be careful though that you don't then provide
another avenue for the malware to hijack your machine)

Now regarding the specific question of registry access, if a large
number of the tasks require accessing a specific method of a registry
class, you might look at inheriting your tasks (that require registry
access) from your registry class. In these types of applications you
may end up with a class heirachy with a baseTask class and varying
branches of of that down the track i.e.

TaskBase -> RegistryTask -> RemoveFromRunNodeTask
TaskBase -> RegistryTask -> RemoveFromRunOnceNodeTask
TaskBase -> ProfileTask -> RemoveFromSystemIniTask

etc etc

rule of thumb, keep classes small, simple and maintainable.

Regards Tim.
 
OHM said:
Your question is rather nebulous to say the least. Some key phrases
for you.

How was the question nebulous? I thought it was quite a good question
that highlights the paradigm shift from structured programming to OO,
and really was demonstrating that the author is on the verge of
"getting it".

Cheers Tim.
 
KV:

Since you are moving from a "old school" to OOP, you may want start
programming your 20 classes, each as a separate independent class (no
inheritance or object heirarchy to begin with). When you find you start to
"cut and paste [and modify]" from one class to another, THIS is the code
that should be generalized and go up into a parent class. For example, you
probably will have many routines that access the registry and delete or
search keys, values and data. You can move these routines up into parents
and then just "reuse" the code in child objects through inheritance [and
polymorphism]. Same goes for modifying INI files.

What will happen is you will end up with a heirarchy of objects where
generic reusable code is pushed more and more up the heirarchy and used (or
even slightly changed) in child objects.

Then you need to think about your engine. How is the engine going to access
and perform its job using these 20 objects? What does it need to do? These
generic routines for engine use then go on the top-most parent in the
heirarchy...and yes, your entire heirarchy should have one generic parent
with at least the abstract methods that your engine needs to use the
objects. For example, having an Execute or Check method that each and every
one of your classes must implement makes it very easy to add a new class
that works in your engine without a single change to the engine itself.

Another area I would look into is interfaces once you grasp OOP rather well
and need a new challenge. This allows you to start using plug-in type
programming like Tim was talking about. So now your objects are independent
objects (or part of some object tree) what implements the interface
(contract) needed by the engine to use the object. Addition and removal of
a check is as easy as registering or unregistering your classes with the
engine. One advantage is that you can make it so others can program
plug-ins that your engine can use, but then again that is a disadvantage as
well because those spyware programmers could create a plug-in for your
engine as well.

Good luck and keep at it. OOP is quite rewarding when you "get it".

Scott
 
Thank you for the excellent help! I was starting to think I was a
simpleton until I came back here and found your post. Mr. Miller had a
lot to add as well.

Thank you both for helping out a newbie.

I don't understand inheritance well enough to comprehend what you're
telling me to the fullest extent. I'll read up on inheritance and then
look at those suggestions.

Speaking about plugins and security... Can C# code be reverse-engineered
from one .exe file? I don't want anyone having access to my code. What
do I need to do for maximum security?

-Kevin
 
KV said:
Thank you for the excellent help! I was starting to think I was a
simpleton until I came back here and found your post. Mr. Miller had a
lot to add as well.

Thank you both for helping out a newbie.

I don't understand inheritance well enough to comprehend what you're
telling me to the fullest extent. I'll read up on inheritance and then
look at those suggestions.

Speaking about plugins and security... Can C# code be reverse-engineered
from one .exe file?
Yes.

I don't want anyone having access to my code. What
do I need to do for maximum security?

Don't give them the compiled code, however it's compiled. That's the
only way of stopping someone from seeing what your code will do.
Obfuscation will help, and conversion to just native code (using one of
the products mentioned in
http://www.pobox.com/~skeet/csharp/faq/#framework.required or something
similar) will go further, but in the end, if someone can run your code
on their computer, they can examine it to see what it does.

I would suggest that obfuscation is as far as most people really need
to go though, if they even need that. See
http://www.pobox.com/~skeet/csharp/faq/#obfuscation for my reasons.
 
No probs at all, thats what these groups are for.


Good idea, we probably should not have talked about the more advanced
techniques (i.e. plug in architecture and polymorphism / Interfaces
etc) before you masterered the basics, however simple inheritance is a
basic technique you should try and master early, in fact you cannot
program in .NET without inheriting....all objects ultimately inherit
from object.

The Best way to learn is to give is a go, and when / if you get stuck,
pop back in here and there will be plenty of people to lend a hand.

Don't give them the compiled code, however it's compiled. That's the
only way of stopping someone from seeing what your code will do.
Obfuscation will help, and conversion to just native code (using one
of the products mentioned in
http://www.pobox.com/~skeet/csharp/faq/#framework.required or
something similar) will go further, but in the end, if someone can
run your code on their computer, they can examine it to see what it
does.

I would suggest that obfuscation is as far as most people really need
to go though, if they even need that. See
http://www.pobox.com/~skeet/csharp/faq/#obfuscation for my reasons.

To echo Jons obfuscation faq, in practice generally there is little
need to protect your code (all rules have their exceptions of course)
as copywrite will give you commercial protection and recourse, and the
sort of people that that won't deter, will always be able to reverse
engineer your code no matter what you do. (and not just managed code,
compiled code is also vunerable, just less straight forward to do)

Borland has given away the source code for their visual component
library for Delphi and C++ builder since it's original development back
in 1995, and far from damaging sales, sales were assisted by a very
vibrant and breathtakingly eclectic 3rd party component market that
still hasn't quite been matched by the .net component market even
though Borland's user base is just a fraction of the overall .net user
base. Slowly (more slowly that I like) the 3rd party component vendors
for .NET components are now starting to do the same (www.devexpress.com
for an example)

Regards Tim.
 
To echo Jons obfuscation faq, in practice generally there is little
need to protect your code (all rules have their exceptions of course)
as copywrite will give you commercial protection and recourse, and the
sort of people that that won't deter, will always be able to reverse
engineer your code no matter what you do. (and not just managed code,
compiled code is also vunerable, just less straight forward to do)

Borland has given away the source code for their visual component
library for Delphi and C++ builder since it's original development back
in 1995, and far from damaging sales, sales were assisted by a very
vibrant and breathtakingly eclectic 3rd party component market that
still hasn't quite been matched by the .net component market even
though Borland's user base is just a fraction of the overall .net user
base. Slowly (more slowly that I like) the 3rd party component vendors
for .NET components are now starting to do the same (www.devexpress.com
for an example)

Regards Tim.

Thanks again. That's interesting information I didn't know.

I do have one more practical question to ask. Remember the registry
class I was talking about? I've started creating one and I've run into
a problem. I need to pass an array or an arraylist from one class to
another (it's a list of key names). I try to pass by reference, but I
keep getting conversion errors. If I could just get one class to
populate an array and successully pass it to another class, I could
iterate through the array and get the values out. Would you mind
enlightening me, if you have the time?

I appreciate all of your help.

-Kevin
 
KV said:
I do have one more practical question to ask. Remember the registry
class I was talking about? I've started creating one and I've run into
a problem. I need to pass an array or an arraylist from one class to
another (it's a list of key names). I try to pass by reference, but I
keep getting conversion errors. If I could just get one class to
populate an array and successully pass it to another class, I could
iterate through the array and get the values out. Would you mind
enlightening me, if you have the time?

The first thing I'd try to do is stop passing it by reference, if I
were you. There's almost certainly no need to.

If that doesn't help, could you post a short but complete program which
demonstrates the problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
I do have one more practical question to ask. Remember the registry
class I was talking about? I've started creating one and I've run
into a problem. I need to pass an array or an arraylist from one
class to another (it's a list of key names). I try to pass by
reference, but I keep getting conversion errors. If I could just get
one class to populate an array and successully pass it to another
class, I could iterate through the array and get the values out.
Would you mind enlightening me, if you have the time?

Sure, I don't really have the time, but what the hey..

I am not 100% sure by what you mean by conversion errors, but you
shouldn't need to pass an array or arraylist by reference if you are
just wanting to access its members. If you just mean that you can't
access the objects that you have placed in your arraylist, most likely
your problem is that you need to perform a cast on the object back to
the type that you put in.

i.e. MyClass obj = TheArrayList[index] as MyClass;

Now, what I am about to tell you is part of this shift in thinking that
you are now noticing that you need to make. I can't really tell from
your description if what you are creating with your registry class is a
general purpose monolithic class that is going to perform all of your
registry reading and writing code in your app, although that is what it
sounds like. The problem with doing this is extendability (and
readability) of your application because any updates to the app is
going to require you to start messing with already working and debugged
code.

A better design for this type of application (like your adware remover,
which must be extended over time ) is to really break your objects down
to a very simple task oriented class, so by all means have a helper
class for registry access (or make a base class that can handle the
registry reading and writing) but keep all the info required to perform
the task (i.e. the reg keys) with the actual class doing the work.

Rather than have an arraylist with all the keys and pass it to a
registry object, keep each key with the small specific class that
implements the logic for that particular adware defence, that is make
the whole class self contained.

i.e.

public class ZapTheMalWareInTheRunRegistryKey
{
private const string TARGET_KEY = ".....";

public void Execute()
{
RegistryKey reg = Registry.LocalMachine.OpenSubKey(TARGET_KEY);
/// etc etc
}

}

This way you keep your classes very small, very specific and easily
maintainable and extendable. What you will need to have in your
application though is a manager class that keeps track of what to run
and when to run them. (this is when before we started talking about
plug in architecture and polymorphism etc.. but you can make this quite
simple as well, no need to run before you can walk.)

I know this seems like much more work, but trust me, this will pay back
dividends over time, and in fact will be less complex to maintain.

Regards Tim.
 
Sure, I don't really have the time, but what the hey..
I am not 100% sure by what you mean by conversion errors, but you
shouldn't need to pass an array or arraylist by reference if you are
just wanting to access its members. If you just mean that you can't
access the objects that you have placed in your arraylist, most likely
your problem is that you need to perform a cast on the object back to
the type that you put in.

i.e. MyClass obj = TheArrayList[index] as MyClass;

I figured it out. The array reference was getting passed and the array
was being modified. When it got back to the calling program, I wasn't
iterating through the array. I'm used to Perl where you can just print
an array without iterating through it. ;)

Given what you say below, I know now that I shouldn't have to use what I
just discovered for the BHO-removal program. BUT, what if I want to use
an accessor method to get an array, instead of a regular method? Possible?

I've heard its good practice only to use properties when
sending/receiving information to/from the user interface. So if I have
my 20 objects and I write a form to display information, then I might
need to get a list of BHOs from my BHO object or a list of values in the
Run key of the registry. Is it possible to retrieve those lists using
the get method? Certainly I would be using references there, right?
Now, what I am about to tell you is part of this shift in thinking that
you are now noticing that you need to make. I can't really tell from
your description if what you are creating with your registry class is a
general purpose monolithic class that is going to perform all of your
registry reading and writing code in your app, although that is what it
sounds like. The problem with doing this is extendability (and
readability) of your application because any updates to the app is
going to require you to start messing with already working and debugged
code.

A better design for this type of application (like your adware remover,
which must be extended over time ) is to really break your objects down
to a very simple task oriented class, so by all means have a helper
class for registry access (or make a base class that can handle the
registry reading and writing) but keep all the info required to perform
the task (i.e. the reg keys) with the actual class doing the work.

Rather than have an arraylist with all the keys and pass it to a
registry object, keep each key with the small specific class that
implements the logic for that particular adware defence, that is make
the whole class self contained.

i.e.

public class ZapTheMalWareInTheRunRegistryKey
{
private const string TARGET_KEY = ".....";

public void Execute()
{
RegistryKey reg = Registry.LocalMachine.OpenSubKey(TARGET_KEY);
/// etc etc
}

}

This way you keep your classes very small, very specific and easily
maintainable and extendable. What you will need to have in your
application though is a manager class that keeps track of what to run
and when to run them. (this is when before we started talking about
plug in architecture and polymorphism etc.. but you can make this quite
simple as well, no need to run before you can walk.)

I know this seems like much more work, but trust me, this will pay back
dividends over time, and in fact will be less complex to maintain.

Regards Tim.

One of the books I bought, "Object Oriented Design Heuristics" by Arthur
Riel has a lot of information on so-called God classes and how to avoid
them. Even though I read that chapter, here I am creating a God class
(registry manager/controller)! I'm sticking with it, I'm learning :)

This is where topics such as coupling and inheritance come in, right?

Once again, thank you for your time.

-Kevin
 
KV said:
I figured it out. The array reference was getting passed and the
array was being modified. When it got back to the calling program, I
wasn't iterating through the array. I'm used to Perl where you can
just print an array without iterating through it. ;)

Ahh, gotta love perl.
Given what you say below, I know now that I shouldn't have to use
what I just discovered for the BHO-removal program. BUT, what if I
want to use an accessor method to get an array, instead of a regular
method? Possible?

Sure I do that all the time, you might want to investigate strongly
typed collections said:
I've heard its good practice only to use properties when
sending/receiving information to/from the user interface. So if I
have my 20 objects and I write a form to display information, then I
might need to get a list of BHOs from my BHO object or a list of
values in the Run key of the registry. Is it possible to retrieve
those lists using the get method? Certainly I would be using
references there, right?

ok, now here you are hitting on a key OO design point. Always design
your classes interactions like a "contract" i.e. when they have to
interact do it via structured mechanisms, either a property (getter,
setter) or a method, avoid any class needing to have detailed knowledge
of the inner workings of any other class.
One of the books I bought, "Object Oriented Design Heuristics" by
Arthur Riel has a lot of information on so-called God classes and how
to avoid them. Even though I read that chapter, here I am creating a
God class (registry manager/controller)! I'm sticking with it, I'm
learning :)

sure, and actually the manager / controller class is less god like than
you might think at first glance, what we are talking about here is (not
quite but nearly) an implementation of either a command or chain of
responsibility pattern (see the gang of four design patterns book) the
classe(s) doesn't actually know about the mechanics of the BHO-Removal
only who is responsible.

There are several ways to achieve this, a common way is to have a
registration process during your application initialization, where your
removal classes get registered with the class that will initiate the
removal process, in .NET a convenient way perhaps (I havn't actually
tried this, but it seems like an elegant solution) would be to use an
event handler, events are multicast, so each of your removal classes
could have a method that conforms to the event handler delegate and
attach themselves to the event.

i.e.

RunOnceRegistrycleaner.Register(BHORemoverInstance);
RunRegistryCleaner.Register(BHORemoverInstance);
IniFileCleaner.Register(BHORemoverInstance);
etc, etc

then in the register method....

public void IniFileCleaner.Register(BHORemover remover)
{
remover.Remove += new RemoveEventHandler(....);
}

You get the idea ?

Note how, the remover class does not have to know anything about the
specific removal objects, this means you can add new ones with ease and
without having to change the remover class. Your application also does
not need to know about the specific removal classes, just needs to fire
the remove event of the remover class at the appropriate time.

(The plug in architecture that we talked about earlier would differ
only in that instead of having an initialization process, where you
need to know what classes are to be registered, you have a process
whereby you go and gather that info dynamically, using say reflection
and attributes or a config file or whatever)
This is where topics such as coupling and inheritance come in, right?

Well in this example I used delegates rather than inheritance as there
are pretty good built in mechanisms in .NET to do the itteration of the
method calling ( the multitask event ) in days gone by (and you could
still do it), you would use a base class that had an abstract method
that each concrete class would inherit from and override, you would
then just itterate over each of the concrete classes and call that
method.
Once again, thank you for your time.

no probs, hope I have helped.

Note though, there are lots of alternate ways of doing what I propose,
and if anyone else is following this thread, maybe could also offer up
an alternative.

Regards Tim.
 
Back
Top