I’ve been writing C code for quite some time but am very new to Objective-C and OO program design. I am having trouble wrapping my head around how to design my program and it’s classes — my standby procedural programming paradigm of passing an opaque pointer to everything just won’t die a quiet death. I am writing a simple program in Xcode4 in Objective-C and I have some questions on design and convention. I’ve designed two classes “PacketCapture” and “IPGeo”. The first is a light wrapper around libpcap with some added parsing logic and the second is a light wrapper around MaxMind’s GeoIP C API. In my main module, I instantiate the PacketCapture class and pass control to the packet capture loop:
int main(int argc, const char *argv[])
{
@autoreleasepool
{
PacketCapture *_PacketCapture = [[PacketCapture alloc] init:"en1" withFilter:""];
if (_PacketCapture == nil)
{
NSLog(@"Can't instantiate PacketCapture class");
return (-1);
}
IPGeo *_IPGeo = [[IPGeo alloc] init:"/usr/local/share/GeoIP/GeoIPCity.dat"];
if (_IPGeo == nil)
{
NSLog(@"Can't instantiate IPGeo class");
return (-1);
}
NSLog(@"entering packet loop...");
[_PacketCapture packetCapture];
}
return (0);
}
Inside of the packetCapture method a parsing function is called that chops up the packet and displays it. I need to use the GeoIP logic down inside the parsing code to lookup the IP addresses against the geo database. Therein lies my problem and general confusion.
My questions:
-
Where should I instantiate the GeoIP class?
-
Is having an infinite loop inside an object in a class bad OO design? Feels like it could be. Perhaps if I restructure this problem will be easily solved?
Thanks for any help.
If
PacketCapturerequires anIPGeoobject to function, I would recommend instantiating it withinPacketCapture‘s-initmethod. If you need to configure theIPGeoobject (by passing a different path when initialized, for example) before using it inPacketCapture, and the path to use is determined in a wayPacketCaptureshouldn’t be aware of, have the class responsible for managing the two (or, in your case, the main loop of the program) create an instance and pass it as an argument to a custom initializer method on thePacketCaptureclass.A bit of nitpicking–your initializer for
IPGeodoesn’t follow Objective-C conventions for expressive method names.-initWithPathToDatabase:would look a lot better in my opinion.In a similar vein, you can add a
-initWithIPGeo:method to yourPacketCaptureclass.If this is an iOS or Cocoa application, then definitely yes. If it’s a command line tool, then maybe. Furthermore, if that infinite loop is being run on the main thread, it will block all UI elements, which will make your program look unresponsive.
A better alternative would be to use the protocol/delegate pattern, a staple of Objective-C programs. Create a protocol with something like the following method:
Then create a delegate object that implements this protocol and performs an action on receiving the packets. If you’re making a command line tool, you can instantiate that delegate and wait to receive messages.