Question

I stumbled accross the SOLID principles. There is one burning question. Should I always use protocols? I never saw someone using them in the way that a Java developer would use them.

I tried it in a demo project and ended up with a .h file for the protocol, another .h for the header. A .m file for the implementation and sometimes a .xib for the UI.

Is there a reason why an ObjC developer would only use protocols for delegates? I never saw ObjC code with a test first approach. Does SOLID programming apply for ObjC?

Was it helpful?

Solution

TDD isn't hugely popular in the ObjC world. Look at some of the official Apple SDK libraries and you'll find patterns that would make TDD advocates give up in disgust (there are a lot of singletons in the iOS SDK, and it's a pattern that works very well with ObjC). Unit tests in general aren't that popular, either, which explains why the official unit test suite is a relatively recent edition to Xcode and why it's still third-rate. The ObjC philosophy seems to be:

"Don't make your code more complicated in order to write tests: simple code is easier to debug."

That'll undoubtedly rattle the TDD guys, but it's the approach I've noted in ObjC developers.

ObjC takes a more pragmatic approach to protocols than Java devs do to interfaces ("every class must have an interface and an implementation, just in case!"):

  • If you know that you'll need multiple classes with the same interface and want the compiler's help, you can create a protocol.
  • If you know that you'll need multiple classes with the same interface but don't care about support from the compiler, you can use "informal protocols" (take a look at how to handle data from a GKSession object: you implement a method, not a protocol).
  • If you're probably only going to use one class, just use the class and forget about protocols.

This is why you only tend to see protocols used in conjunction with delegates: they tend to be the only places that you'll create more than one class to implement the necessary functionality, especially as the delegate pattern is so pervasive. Other languages tend to require you to either subclass and override or implement an interface to provide additional functionality; ObjC tends to use delegates instead.

The fact that ObjC is dynamic removes a lot of the need for protocols/interfaces. Java, C++ and C# developers spend a lot of time trying to categorize and type everything as accurately as they can, resulting in multitudes of interfaces and classes. That simply isn't necessary in a dynamic language (and it's one of the reasons I'm so happy to have switched from C# to ObjC: I can spend my time solving problems instead of describing type hierarchies).

ObjC is dynamic and supports duck typing, so if an object implements a method "quack" you can call that method without explicitly conforming to the "Duck" protocol; you can even identify if the object implements the method before calling it thanks to ObjC's excellent metaprogramming capabilities.

OTHER TIPS

SOLID principles don't necessarily apply in any context, regardless of technology or programming language. Many developers choose to abide by them though, and it's certainly possible to do in Objective-C.

If you're interested in seeing test-first Objective-C, then take a look at BrowseOverflow: it's a completely test-driven app that makes use of UIKit and network services. I actually wrote it as the sample code for Test-Driven iOS Development, but if you're comfortable with the principles you can just look at the code. You can see there that even though the code was test-driven, it isn't brimming with protocols.

One reason for that is "duck typing". Objective-C, like Smalltalk before it and Ruby after it, doesn't actually care what type an object is, it just sends messages. The type safety system is entirely restricted to the compiler checking. You can therefore type a variable as specifically as you want and still (sometimes with some casting) supply a different type at runtime. As long as both types respond to the messages passed in your code, everything works. You can see that the tests in BrowseOverflow use this to pass in test fakes, even for variables that aren't typed using protocols.

In fact in historical Objective-C and Smalltalk (and in modern Ruby) many collaborating objects aren't typed at all: in Objective-C the id type means "any object". That's less common now in ObjC, but a lot of Apple's framework code is old enough to have been around when this was the norm. You'll notice that newer frameworks, and newer API on existing frameworks, uses stricter typing and protocol types for non-delegate collaborators.

Is there a reason why an ObjC developer would only use protocols for delegates?

Personal choice. There's no underlying technical reason to follow that approach.

Does SOLID programming apply for ObjC?

Yes. Or rather, it can do, and many developers choose to follow SOLID principles.

Licensed under: CC-BY-SA with attribution
scroll top