简体   繁体   中英

Object hierarchies in Objective-C

I've been introduced to an Objective-C codebase which has ~50,000 LoC and I'd estimate that 25% or so is duplicate code. Unfortunately, OO principles have been mostly ignored up to this point in the codebase in favor of copy and pasting logic. Yay!

I'm coming from a Java background and a lot of this duplication is fixable with good old-fashioned objective oriented programming. Extracting shared logic into a base class feels like the correct solution in a lot of cases.

However, before I embark on creating a bunch of base classes and sharing common logic between derived classes, I thought I should stop and see if there are any other options available to me. After watching Ken Kocienda's 'Writing Easy-To-Change Code' WWDC session from 2011, he's advising me to keep object hierarchies as shallow as possible. He doesn't offer up any hard statistics as to why he has this opinion, so I'm wondering whether I'm missing out on something.

I'm not an Objective-C expert by any stretch of the imagination, so I'm wondering if there's any best practices when deciding on an object hierarchy. Basically, I'd like to get opinions on when you decide to stop creating base classes and start using composition instead of inheritance as a way of sharing code between classes.

Also, from a runtime performance standpoint, is there anything to sway me away from creating object hierarchies?

I wrote up some thoughts awhile back on coming to iOS from other backgrounds , including Java. Some things have changed due to ARC. In particular, memory management is no longer so front-and-center. That said, all the things you used to do to make memory management easy (use accessors, use accessors, use accessors) is still equally valid in ARC.

@Radu is completely correct that you should often keep your class hierarchies fairly simple and shallow (as you read). Composition is often a much better approach in Cocoa than extensive subclassing (this is likely true in Java, too, but it's common practice in ObjC). ObjC also has no concept of an abstract method or class, which makes certain kinds of subclassing a little awkward. Rather than extracting shared logic into base classes (particularly abstract base classes), it is often better to extract them into a separate strategy object.

Look at UITableView and its use of delegates and datasources. Look at things like NSAttributedString which HAS-A NSString rather than IS-A. That's common and often keeps things cleaner. As with all large object hierarchies, keep LSP in mind at all times. I see a lot of ObjC design go sideways when someone forgets that a square is not a rectangle . Again, this is true of all languages, but it's worth remembering as you design.

Immutable (value) objects are a real win whenever you can use them.

The other piece you will quickly discover is that there are very few "safety decorations" like "final" or "protected" (there is a @protected , but it isn't actually that useful in practice and is seldom used). People from a Java and C++ background tend to fret about compiler enforcement of various access rules. ObjC doesn't have compiler enforcement of most protections (you can always send any message you want to any object at runtime). You just use consistent naming conventions and don't go poking around at private methods. Programmer discipline takes the place of compiler enforcement. In practice, it works just fine that way in the vast majority of cases.

That said, ObjC has a lot of warnings, and you absolutely must eliminate all warnings. Most ObjC warnings are actually errors.

I've strayed a little from the specific question of object hierarchies, but hopefully it's useful.

One major problem with deep hierarchies in Objective-C is that Xcode doesn't help you at all understanding/managing them. Another is simply that just about anything in Objective-C gets about twice as complex than the equivalent in Java, so you need to work harder to keep stuff simple.

But I find composition in Objective-C to be awkward (though I can't say exactly why), so there is no "perfect" answer.

I have observed that small subroutines are much rarer in Objective-C vs Java, and one is much more likely to see code duplicated between mostly-identical view controllers and the like. I think a big part of this is simply the development tools and the relative awkwardness with creating new classes.

PS: I had to rework an app that contained roughly 55K lines, close as we could count. As you found, there was likely about 25% duplication, but there was also another 25% or so of totally dead code. (Thankfully, that app has been pretty much abandoned since.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM