|
You can - it's a hack, but it is possible:
<!-- [if IE 7]><link rel=...><![endif]--> By the way, this is the wrong forum for this question. It should be on the Web Development forum.
Deja View - the feeling that you've seen this post before.
|
|
|
|
|
Say you have an interface:
public interface IWidget
{
int Count
{
get;
set;
}
}
Let's pretend that a lot of classes will implement this interface. As a result, each class will have to implement the Count property. The implementation code in each class will be the same, more or less. So it's tempting to do this:
public abstract Widget : IWidget
{
private int count = 0;
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
}
Now instead of implementing the IWidget interface directly, classes derive from the abstract Widget base class.
Let's say, however, that derived classes need to know when Count changes; they may need to do some house keeping. We could make Count virtual so that derived classes could do this:
public class MyWidget : Widget
{
public override int Count
{
get
{
return base.Count;
}
set
{
base.Count = value;
}
}
}
I've posted about this in the past. I don't like this approach because it seems to introduces an ambiguity. When overriding a virtual method or property, when should you call the base class version? And should the call be at the beginning or at the end of the virtual method or property?
But I'm not really interested in delving into this issue again, though feel free to comment.
The next step is to factor out the Count property into its own class:
public class Counter
{
private int count = 0;
public event EventHandler CountChanged;
public int Count
{
get
{
return count;
}
set
{
if(count < 0)
{
throw new ArgumentOutOfRange("Count");
}
count = value;
OnCountChanged(EventArgs.Empty);
}
}
}
Instead of Count being a property of the IWidget interface, it becomes an object that is passed to instances of IWidget derived classes. Derived classes hook up to the CountChanged event and do whatever house keeping is necessary when the event is raised.
Counter myCounter = new Counter();
IWidget widget1 = new MyFirstWidget(myCounter);
IWidget widget2 = new MySecondWidget(myCounter);
I need to point out that in the scenario I've described above, instances of classes derived from IWidget will share the same count value and will be treated as a group of objects. So instead of iterating through a group of objects changing the property value on each one, you simply change the value of one object which in turn raises an event to notify its observers.
Instead of:
foreach(IWidget widget in widgets)
{
widget.Count++;
}
You have:
myCounter.Count++;
This post has gotten rather long, but it's been a kind of chronicle of the process I went through. I finally arrived at the point where I factored out properties whose values are shared across several objects into a class of its own. This allows several objects to share the same property. I'm posting this more to get feedback and as a general sanity check.
|
|
|
|
|
Hi Leslie,
I did not completely follow the story here.
Count first was a property, I am not sure what it is intended for.
If it counts the number of IWidgets, I guess you would like to have a private static
count variable, and a public static property; but then interfaces don't allow for
static things. And you would not need a setter, the constructor should be the only
one modifying it.
Now if you attempt to solve the static issue by making an explicit Counter class and object,
that's fine except it de-encapsulates things: you are now responsible for passing
the right counter to each of the Widget constructors.
You could solve that by adding another class I think.
But maybe I misunderstood you and you want something completely different...
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
Luc Pattyn wrote: I did not completely follow the story here.
Count first was a property, I am not sure what it is intended for.
Erm, count was a bad example, I guess. It's not intended to mean anything other than demonstrating the example. It could have easily been called foo or whatever.
I ran into this situation with my synth toolkit. I had a collection of synth components that shared the same sample rate. At first, I made sample rate a property in an interface that's implemented by synth component classes. I noticed a lot of code duplication, so I factored sample rate into a property in an abstract base class. Some derived classes need to know when the sample rate changes, so I made it a virtual property. Derived classes then have the option to override the property so that when it's set to a new value, they can react. This lead to the ambiguity I described in my post about when/where/if to call base class members.
Finally, I factored sample rate out into a class of its own. This allowed components to share the same sample rate object. It also allowed me to change the sample rate from a single point. Components sharing the same sample rate object would then be updated automatically.
I was trying to describe all of this in my post by using a generic "Widget" class and "Count" property. I should have been more concrete.
|
|
|
|
|
Hi Leslie,
if you moved out the Counter/SampleRate stuff away from IWidget/ISynth and into a
separate class, basically making it (almost) global, I see no objection.
I first was under the impression you were somehow aggregating interfaces, i.e.
defining an interface in an hierarchical way, with Counter somehow inside it. And
that would open some new doors, if it were possible, but in the end I understood
the Counter/SampleRate stuff is orthogonal to the IWidget/ISynth stuff, you just
took it out completely.
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
What you have just described is known as composition, and it is perfectly valid. It is one of the most frequently overlooked areas of aggregation in OOP, and is seriously underused. To my mind, composition is as important as inheritance in OO.
Deja View - the feeling that you've seen this post before.
|
|
|
|
|
It looks like a composition, but I'm my opinion, he's implementing the Observer Design Pattern. I think in his project (as in many others), a property from an object is more than a property -- since it's shared among many members, it could be seen as an object itself.
So, you create and object and delegate to punch when the state changes.
I think many people tend to believe since "it's just an int" or "it's just a string" it's not a object.
|
|
|
|
|
Leslie Sanford wrote: I've posted about this in the past. I don't like this approach because it seems to introduces an ambiguity. When overriding a virtual method or property, when should you call the base class version? And should the call be at the beginning or at the end of the virtual method or property?
But I'm not really interested in delving into this issue again, though feel free to comment.
hehe I know it's not the main issue but since you invited comments ... it's not ambiguous it's flexable. You should know (either because you wrote it or because the documentation tells you) exactly what happens in the base. You then have a choice of wether you want that functionality to happen before your code, after your code or not at all.
|
|
|
|
|
I'm designing a small, off-site backup service for some existing clients. I'm wondering about how to go about managing the transfer and storage of backup sets. One client may have more than one backup file, from more than one source, that they elect to upload to my service daily. Two of the initial design issues are:
1. It seems more workable if I bundle all backup files into a single 'batch' file, using an archive tool.
2. I will probably use FTP and thus need to encrypt backup batches before upload. I would prefer to not decrypt files for storage, but rather only on retrieval, enhancing security. Clients will be provided with the decryption tool to ensure against the even of my service not being available for retrieval.
I would appreciate comment on these two strategies as well as any more general comment. Last modified: 51mins after originally posted --
"Once in Africa I lost the corkscrew and we were forced to live off food and water for weeks." - Ernest Hemingway
My New Blog
|
|
|
|
|
I read that twice and failed to find any question
|
|
|
|
|
I guess that's why it was not marked as a question, but as a "General" message.
If anything it is quite a pre-anouncement.
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/AllLanguages/General
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
Sorry, it's modified now. I just wanted comments on my two 'question points'. The appropriateness of each of those is a 'question point' to me.
"Once in Africa I lost the corkscrew and we were forced to live off food and water for weeks." - Ernest Hemingway
My New Blog
|
|
|
|
|
Still it is unclear what you are actually doing. Are you developing your own software or putting together this "Service" using available software? If the first, why? Is there something lacking in available software to create this type of service? Is it to expensive? If so how much... considering your time and effort to develop test and maintain your own code?
|
|
|
|
|
I'm developing the software responsible for managing the collection and transfer of the files to an existing host. I'm doing this for someone else who wishes to provide the service to clients who have requested it. It is his wish to develop a small, 'in-house' system to provide the service.
"Once in Africa I lost the corkscrew and we were forced to live off food and water for weeks." - Ernest Hemingway
My New Blog
|
|
|
|
|
Brady Kelly wrote: It is his wish
Ok so it is someone else but it doesn't answer "why". I would think plenty of free or cheap software is available to set up such a system as you describe.
|
|
|
|
|
We are looking at Macro Scheduler[^] as a possible client side assist, but then I will still setup up the basic repository and web UI access for clients.
When I have looked at Macro Scheduler later today I will know more, but I would still like some comment on my two design issues.
"Once in Africa I lost the corkscrew and we were forced to live off food and water for weeks." - Ernest Hemingway
My New Blog
|
|
|
|
|
Hi,
I'm currently writing an internal system at my employer which handles sales and we need to handle discount schemes which are subscriber, customer, purchased based and with some weird and wonderful variations. Has anyone come across trying to design a solution for this before and how did you get started?
Thanks
|
|
|
|
|
RavensCry wrote: for this
RavensCry wrote: discount schemes which are subscriber, customer, purchased based and with some weird and wonderful variations.
*sigh* Geez maybe you should put that in as your Google search phrase, what could go wrong?
|
|
|
|
|
Probably should have mentioned that I'd done that already and couldn't find any useful leads, I wouldn't dare think of posting here without doing a Google search first
|
|
|
|
|
Yep, I worked on an epos system a few years ago. The way we did it was to find out each 'type' of discount scheme they wanted i.e. Buy one get one free, collection of specific products for specific price.
We couldn't think of a way to do it dynamically at the time so we just coded each seperate type, and yeah that was a lot of work :P
|
|
|
|
|
We've just had one idea about holding all the discount scheme's in an XML file with a description of how to determine if the discount applies but haven't gotten as far as figuring out how to load the code in or if it's even practical yet.
So something like this:
<br />
<discount><br />
<discount:Template><br />
<rules><br />
<rule><br />
<name>Rule1</name><br />
<value>IsSubscriber(id)</value><br />
</rule><br />
...<br />
</rules><br />
</discount:Template><br />
<discount:Query><br />
<![CDATA[<br />
bool param1 = {Rule1};<br />
bool param2 = {Rule2};<br />
<br />
double fee = GetStandardFee;<br />
<br />
if (param1 && param2)<br />
{<br />
fee = fee * 0.6;<br />
}<br />
<br />
return fee;<br />
]]><br />
</discount:Query><br />
</discount><br />
|
|
|
|
|
RavensCry wrote: how to load the code in
interface and factory
RavensCry wrote: or if it's even practical yet.
Yes it is
|
|
|
|
|
Well, I've done POS systems in the past - my first one was probably 13 years ago, in Clipper - and what I would do is create a hierarchy database of formulas that should be evaluated according to the chain of events in your hierarchy. You can use that not only to discounts, but to other stuff. I come from Brazil and we're know to have the most complex tax systems in the world (do a search on Google and you would understand what I am talking about - even SAP has an engine specifically created to work with our out-of-this-world tax rules).
So, on the top of hierarchy you would have the more general items (for example, State, if you want people from out of state to have a different discount, for example) and go down the "tree".
The formula you're going to use is the one that goes to the utmost item (further down the tree). Then you can use any expression evaluator available in the internet (there are tons of them for C# and other languages). You can even create your own language - supporting IF statements, for example - to accomplish more complicated tasks. I've done this successfully in a pretty interesting project in the company I currently work for.
Hope this helps.
Robson Siqueira
Enterprise Architect
|
|
|
|
|
HI ,
I had worked on something similar like this , in our case the promotions were flowing from SAP ( eg : buy one get one free , combo , etc ) .There were combination of 5-6 of these ,which covers nearly most of the promotions which are given mostly at POS , so we coded each of them .
amit
|
|
|
|
|
It's easy enough to throw an exception from a method in a class you've written when the preconditions of the method haven't been met. You can do so while maintaining the class's invariants. It's harder, though, handling an exception thrown in the middle of the method from a source outside your control, say from an object you've invoked a method on. Enforcing a class's invariants is trickier here.
One approach is to treat the exception as an event. When it occurs, you have code in place that transitions your object to a state appropriate to the exception thrown, i.e. some kind of error state. The question then becomes how should the object behave in an error state? Are there steps to be taken to bring the object back to a useable state? If so, what are they?
I'll give an example. I have a Synthesizer class in my C# Synth Toolkit. It's capable of recording the waveform output as it is synthesized and writing it to a wave file. This takes place on thread other than the main one.
Let's say that an IO exception of some sort happens when attempting to write the waveform data to file. The exception is caught. Now what? I was thinking that it would be appropriate to raise an event on the main thread notifying the user that an error occurred. In addition, the Synthesizer would transition back to a non-recording state. The Synthesizer would continue to function normally.
Another situation has me a bit stumped, though. The Synthesizer uses an OutputDevice class for playing waveform data. If the OutputDevice object being used throws an exception, it's pretty much a show stopper. There's not much the Synthesizer can do if it's OutputDevice isn't useable. So I was thinking that in this situation, an error state would be appropriate. In this state, some of its methods would throw an InvalidOperationException ; they just can't be performed if the OutputDevice isn't working correctly. Other operations might be allowed in order to reset the OutputDevice to get it working or use a different one.
I guess what I'm getting at here is that I'm wondering how you deal with exceptions when they pretty much render an object unuseable.
|
|
|
|