Author | Message | Time |
---|---|---|
Myndfyr | I know that JavaOp did this at one point or another, and I think other OO-language programmers have done this as well. That's right, I'm talking about using a single class to handle a single packet type. (Note that this isn't restricted to Battle.net). That is, there's something along the lines of: [code] public class Sid_AuthInfo { /*...*/ } public class Sid_AuthCheck { /*...*/ } [/code] ...and there's one for every packet. I was trying to come up with advantages/disadvantages to using this design pattern. I wanted other people's input. Advantages: --- Entire binaries don't need to be updated; particularly if they're in discreet units, single packet handlers can be updated (e.g., Java .class files, one for each packet). Encapsulation is enforced. Easy to maintain a consistent design pattern. Disadvantages: --- Many binaries can become unwieldy (using JAR archives defeats the point of updating discreet packet handlers, for instance). An OO-valid reason for getting to the actual binary data may be difficult to justify. Many potentially-unnecessary objects. The opposite is the design pattern I've used, which involves using data reader and writer buffers and local variables to handle the data. If necessary, data can be encapsulated in "event argument" classes, which is a common design pattern in the .NET Framework (callback delegates often follow the signature: [code] public delegate void SomeDelegate(object sender, EventArgs e); [/code] where the e argument is typed a descendant of EventArgs. Note that delegates are essentially type-safe function pointers). Advantages: --- A good middle ground between no binary access and full binary access: likely fewer classes than a class for every packet, but more classes than no individual packet classes. Packet structure is typically easily-discernable when using a reader class. Easier to maintain binary Consistent design pattern application can easily overcome the first two disadvantages below: Disadvantages: --- Packet structure is not encapsulated within a class and may need to be updated in multiple locations. Local/stack variables may need to be copied multiple times. Design pattern may be muddied by in-code access to binary data. Larger binary for updating Any other thoughts from anyone who has experience with object-oriented program or high-level architecture problems? | June 20, 2006, 9:25 AM |
rabbit | Well, for one of my website projects I modularized and mostly-isolated each set of functions that served a particular purpose (ie: login had it's own class, and did not interact with forums at all). I found this pretty advantageous in that if I wanted to update something, I didn't have to go around and update 25 other functions. A disadvantage, however, was that I had to write core wrappers first to make sure everything worked if two modules needed to interact, and one failed. I do, however prefer this system for larger projects, though I have yet to implement this system into a bot (what with me not making them anymore). I'd say. depending on how large you want this program to be, go with either full encapsulated modularization, or none at all. Also take into account who will be using the program. It's usually easier for computer illiterate users to update just the main executable as opposed to hunting down the proper class and replacing it. And that's not to mention that someone may delete a required class and break the program altogether. | June 20, 2006, 1:10 PM |
Myndfyr | Clearly that design pattern makes sense for high-level ideas (such as "Log in") or whatnot. I guess I'm asking for the specific purposes of communications protocol users: are such specialized classes really useful? | June 20, 2006, 4:14 PM |
rabbit | I think it depends primarily on the target audience and the protocol in question. If it's a rediculously simple protocol, like Battle.Net's old Chat protocol, then there really is not much benefit to modularizing the structures at all. And the same for something messy, like the IRC protocol. Splitting that up can get really messy. And at your audience, if you're "marketing" (not necessarily selling) to the general masses, I'd start out with a single system. Then consider the complexity of the protocol and how it would be implemented. If you've got 20 different structures, I'd say pack it all in. If, however, you're looking at a larger system, such as Battle.Net's, I'd probably spread the structures out, probably not give each packet a module, but group similar or related packet structures together. For something HUGE, I'd give everything its own module. But that's just me.. | June 20, 2006, 5:11 PM |
St0rm.iD | Abstract BnetBinaryMessage class with two static methods, BnetBinaryMessage readMessage(buffer) and void registerMessageClass(class), and an abstract static method, bool isType(buffer), and abstract constructor which takes the buffer itself. isType will tell you whether or not a given subclass can parse a buffer based on peeking at the packet type. registerMessageClass() adds a subclass to the given registry. readMessage loops through all subclasses in the registry, calls isType() until one returns true, at which point it instantiates it with the buffer and returns it. | June 20, 2006, 10:07 PM |
rabbit | You might want to read his thread. He wants to know whether it would be "better" (or more advantageous, if you prefer) to use a modularized system so that to update a packet the whole program does not need to be updated, or to pack all of the necessary information into the program itself. | June 20, 2006, 11:30 PM |