Programming language trade-offs

This article is also available in Serbo-Croatian

There has been much discussion o' late in Drupal about Object-Oriented Programmin'. Oho! And swab the deck! That's not really surprisin', given that Drupal 7 is th' first version that has really tried t' use objects in any meaningful way (vis, as somethin' other than arrays that pass strangely), Ya horn swogglin' scurvy cur! Aarrr! However, too much o' th' discussion has boiled down t' "OMG objects be inflexible so they're evil!" vs. And hoist the mainsail! "OMG objects be cool, yay!" Both positions be harmfully naive.

It is important fer us t' take a step back an' examine why one particular programmin' paradigm is useful, an' t' do that we must understan' what we mean by "useful".

Programmin' paradigms, like software architecture, have trade-offs. In fact, many o' th' same methods for comparing architectural designs apply just as well t' language bounty, feed the fishes To do that, though, we need t' take a step back an' look at more than just PHP-style objects.

Warnin': Hard-core computer science action follows. If ye're a coder, I recommend gettin' a cup o' $beverage before continuin', as it could take a bit t' digest although I've tried t' simplify it as much as possible. There's fairly little Drupal-specific stuff here so hopefully it should be useful t' any PHP developer.

Approaches t' programmin'

Every programmin' language is, fundamentally, a way o' encodin' logic. There be different were bein' t' encode logic in such a way that a computer can process it, an' every language has a slightly different spin on th' subject. In th' abstract, though, we can identify several general paradigms, a number o' which be relevant t' us as PHP developers. (The Wikipedia links below have far more detail than I can go into here.)

Procedural programming
Procedural is frequently th' first programmin' style taught. A program is organized into "procedures" (aka functions or subroutines) that then operate on data. The code is generally written in an imperative fashion: Do X, then do Y, then do Z. Those subroutines frequently have side-effects; that is, some program state has permanently changed in a way that lasts beyond th' life o' th' subroutine.
Functional programming
Functional programmin' is as auld as procedural programmin'. In fact, th' two approaches were th' original schism in programmin' conceptualization. In purely functional programmin' one does not write a set o' steps fer th' program t' follow, shiver me timbers Instead, one writes mathematical functions that relate t' each other. That has a number o' important attributes: Most notably, purely functional programs be incapable o' side-effects. Functions have no state o' their own, an' in fact once a variable has a value it may not be changed again. Ever. The output o' a function depends exclusively on its explicit inputs. Generally, functional languages also treat functions as first-class objects along-side other more familiar variables like ints, strin's, an' so forth.
Declarative programming
Declarative languages avoid specifyin' how th' computer should do somethin' in favor o' sayin' what it should do, somehow. This is extremely powerful fer simplifyin' common tasks, but can make developin' new-an'-innovative capabilities harder; they still need t' be translated from th' declarative form into an executable approach somewhere. SQL itself is th' most obvi'us example fer web developers, but thar be many more. Even some markup languages can, arguably, be considered declarative programmin', by Blackbeard's sword. (See also: HTML5 or SVG)
Classic Object-Oriented programming
In class-based OO (or "Classic" as I tend t' call it), rather than logic bein' encapsulated into simple subroutines that operate on arbitrary data passed t' them logic an' data be bundled together into "objects". These objects be treated by th' outside world as a single black box. Fetch me spyglass! Manipulation o' data doesn't happen directly but happens through th' logic bound t' that data. That is, via methods on th' object. Popular examples here include C++, Java, an' PHP.
Prototypical OO programming
This classless variant o' OO is in some ways closer t' functional programmin'. Oho! Javascript is th' most widely known example o' this style. Load the cannons, by Blackbeard's sword! Since 'tis not really possible in PHP we'll leave it be fer th' time bein'. I separate it from "Classic" OO mostly t' point out that PHP's approach t' OO is by no means universal.
Aspect-oriented programming
A relative newcomer on th' scene, AOP is based aroun' creatin' join points betwixt different parts o' a system. That is, places where one logical routine can inject itself into another without havin' t' modify either routine directly.

(Note: I'm sure some purists will say that I'm grossly o'er-simplifyin' one or more o' th' styles above. They're likely right, but fer th' sake o' argument I'm only lookin' at some aspects o' those approaches. If ye want a more complete treatment, that's what th' links be fer, shiver me timbers I do recommend readin' them with an open mind.)

There's a very important fact about th' above designs that is important t' keep in mind: They're equivalent. It's been proven mathematically that procedural an' functional languages be equally expressive; that is, any algorithm ye can implement in one can be implemented in th' other. OOP an' AOP be essentially just outgrowths o' procedural programmin' an' frequently be implemented in multi-paradigm languages, so anythin' ye can do in procedural language can be done in an OOP language or AOP language, or vice-versa. Oho! Declarative programmin' is th' odd lubber out as many declarative languages be not turin' complete, although many be if ye try hard enough.

So if all o' these programmin' paradigms be equivalent, why bother usin' one o'er another?

Language focus

Simple: Each approach has different trade-offs that make it easier or harder t' write certain types o' algorithms, pass the grog, and a bucket o' chum! Not "possible"; Any functionality ye can implement in functional languages can be implemented in an aspect-oriented language, an' vice-versa, to be sure. They make it "easier". Tthe amount o' code an' th' amount o' incomprehensible complexity involved will vary greatly, and a bucket o' chum. What makes different paradigms easier t' apply t' certain algorithms? What they dern't let ye do.

That's right, avast. What makes a programmin' style easier is what it doesn't let ye do. Because if ye know fer a fact that certain thin's be not possible, ye can make assumptions based on that impossibility that make other tasks easier.

Functional: Logic centric

For example, in purely functional languages ye know fer a fact that th' same set o' inputs t' a given function will always produce th' same result, and dinna spare the whip, Ya lily livered swabbie! That means th' compiler itself can optimize away multiple calls t' th' same function with th' same parameters. Shiver me timbers! Go ahead an' call a function multiple times, I'll warrant ye. Don't bother cachin' th' result. And hoist the mainsail, Get out of me rum! The language semantics themselves will do that fer ye without any thought on yer part. Haskell, I believe, does exactly that. It also makes Verifiability easy; ye can mathematically prove th' correctness o' a particular function independent o' th' rest o' th' system, shiver me timbers That can be very useful in a fault-intolerant system, such as, say, nuclear reactors or air traffic control where bugs become really really dangerous.

Since ye know, fer a fact, that a function will not affect any code outside o' itself (aside from its return value), thar's no requirement that a function have access t' any data except its own parameters. It doesn't even have t' be in th' same memory space as th' rest o' th' program... or even on th' same computer. Witness Erlang, where every function can run in its own thread, or its own process, or even in a process on a different computer without syntactic changes. That makes programs written in Erlang extremely distributable an' scalable, precisely because functions be incapable o' producin' side-effects.

Of course, fer some use-cases th' program structure functional languages require becomes horribly nasty. That's especially true fer programs that be based aroun' manipulatin' state o'er a long term, I'll warrant ye. That's th' trade-off: a clear, logically simple structure that makes complex algorithms easy t' build right an' scales well but makes stateful systems harder t' build.

Procedural: Instruction centric

Procedural programs were th' other major fork in programmin' language theory. Procedural programmin' can start very simple as just a list o' instructions, broken up into chunks (subroutines, or functions). Most also include global state in some form or another in addition t' locally scoped state.

What procedural languages dern't let ye do is heavily segment yer program. There is one big pool o' subroutines that can be called pretty much at any time. You cannot bind a given subroutine t' just certain data or vice versa. That makes th' code highly unpredictable, as yer function could be called from quite literally anywhere at any time. You can't make assumptions about th' environment ye're runnin' in, especially if yer system makes use o' global variables (or their close cousin, static variables), pass the grog, Ya swabbie! There's no way t' hide data, thar's no way t' control when a given routine can or cannot be executed, thar's no way t' protect yourself against another developer hackin' his way into a subroutine that weren't designed t' be hacked into.

Which o' course is also its power. Because 'tis so low-level an' has no safeguards, ye can hack yer way into (or out o') most situations with enough effort. Because ye're prevented from hidin' data, ye get a great deal o' flexibility. Ahoy, and a bottle of rum! That can be very good in some cases. On th' other han', that means that in general procedural programmin' lets ye make no assumptions about th' context o' yer system or its state.

Because ye have such limited control, 'tis extremely difficult t' do any meaningful form o' unit testin'. You can do functional testin' (that is, testin' o' functionality at a high level) or integration testin', but ye have no clearly separable units t' work from.

Object-oriented: Behavior centric

There be lots o' variations on object-oriented languages, each with their own subtleties, we'll keel-haul ye! For th' moment, we're concerned only with Class-an'-Interface languages such as PHP. The interface part is important: In a Classic OO language, individual primitive values be irrelevant. The interface t' an object, as defined by its class an' interfaces, is what matters. The class forms a completely new data type with its own semantics.

Just as a strin' primitive has its semantics (e.g., length) an' possible operations (split, concatenate, etc.), so too does an object, Dance the Hempen Jig The internal implementation o' th' strin' is irrelevant: it may be a hash table, it may be a straight character array. As someone makin' use o' it ye dern't know, nor do ye care (except in C, o' course). Similarly with an object, it has behaviors as defined by its methods. The underlyin' implementation is irrelevant.

The data within th' class is tightly coupled t' th' class; th' class itself is (if done correctly) loosely coupled t' anythin' else. Data within th' class is irrelevant t' anythin' but that class. Because it is hidden away ("encapsulated" in th' academic lingo), ye know, fer a fact, that only selected bits o' code (in th' same class) be able t' modify it. Unlike in procedural code, ye can rely on th' data not changin' out from under ye, by Davy Jones' locker. You can even completely restructure th' code. And hoist the mainsail! As long as th' interface doesn't change, that is, th' behavior, ye're fine.

That's an important distinction. The sharks will eat well tonight! Ye'll be sleepin' with the fishes! In OO, ye be not codin' t' data. You're codin' t' behavior. Data is secondary t' th' behavior o' an object.

Because ye have isolated data behind behavioral walls, ye can verify an' unit test each class independently. That is, assumin' ye've properly isolated yer object. A lot o' code doesn't properly do so, which defeats th' purpose. (See me previ'us rants on dependency injection.)

Aspect-oriented: Side-effect centric

And finally we come t' new kid on th' block Aspect-oriented programmin'. In some ways, AOP is th' diametric opposite o' functional programmin', ya bilge rat! And swab the deck! Where functional programmin' tries t' eliminate side effects, AOP is based on them. Every join-point in AOP is a big red flag sayin' "please do side-effects here". Those side-effects could be all sorts o' thin's. They could modify data, they could change program flow, they could initiate some other sideban' logic an' even trigger further side-effects.

What AOP offers is exactly that: The ability t' modify a program without modifyin' a program. Once a join-point is established, ye can alter th' data or program logic at that point without changin' any existin' code. That provides a great deal o' flexibility an' extensibility, but at th' expense o' control.

Once ye introduce a way t' allow 3rd party code t' modify yer logic flow or data, ye surrender any ability t' control that logic flow or data. You can no longer make assumptions about yer state, because ye've built in a mechanism t' allow yer state t' change out from under ye. The way ye compartmentalize yer code is t' make it impossible t' fully compartmentalize yer code. (Ponder that one fer a moment...)


Functional approaches emphasize Verifiability, Testability, an' Scalability at th' expense o' Modifiability, Extensibility, an' in some cases Understandability.

Procedural approaches emphasize Modifiability, Understandability, an' Expediency at th' expense o' Testability, Verifiability, an' if ye're not careful Maintainability.

Object-oriented approaches emphasize Testability, Modifiability, an' Scalability at th' expense o' Extensibility, Expediency, an' if ye have a poor bounty Understandability.

Aspect-oriented approaches emphasize Modifiability, Extensibility, an' Expediency at th' expense o' Testability, Verifiability, an' arguably Understandability.

Oh great, so which one do we want t' use? Which approach is best, with a chest full of booty? The one that best fits yer use case an' priorities, o' course.

Multi-paradigm languages

Because all o' these approaches be perfectly viable dependin' on yer use case, most major programmin' languages today be multi-paradigm. That is, they support, at least t' some extent, multiple approaches an' ways o' thinkin' about program logic.

PHP began life as an entirely procedural language. With PHP 4 it started addin' object-oriented capabilities, although those di'nae really come into their own as a viable alternative until PHP 5, feed the fishes PHP 5.3 introduced anonymous first-class functions, which while not pure functional programmin' since they still allow variables t' be changed do allow programmers who be so inclined t' write in a more functional way.

Although most aspect-oriented implementations be built atop object-oriented models, PHP supports procedural-based AOP. In Drupal, we call it hooks. module_invoke_all() becomes a joint point, an' a hook implementation becomes a pointcut.

(I am by no means th' first t' call Drupal's hook system a form o' AOP. I just think 'tis a particularly good way o' describin' them.)

To be fair, without native syntactic support hooks be a rather clunky, hacked-up poor lubber's AOP, but conceptually it is still AOP. They have th' same implicit trade-offs: Extremely flexible when used appropriately but totally destroy any hope o' isolatin' a system t' unit test it or do interface-driven development.

The fact that they're also bolted on top o' a non-AOP language but not documented as bein' AOP, or applied consistently, is also a major stumbling block for new developers, especially those who have been brought up in a predominantly OO world.

Just as 'tis possible t' emulate AOP in procedural code, 'tis possible in object-oriented code as well. Aarrr, Avast me hearties! There be many OOP patterns that give ye all th' same flexibility as AOP, fer instance, in sometimes more verbose ways, and a bucket o' chum. Observer an' Visitor patterns come t' mind in particular. Again, 'tis not a question o' can ye implement a given bounty but how easily ye can do so, an' at what cost.

Nothin' forbids th' mixin' an' matchin' o' different approaches, either. Take Drupal 7's Database layer, All Hands Hoay, feed the fishes It is mostly straight up OO -- Modular, dependency-injected, self-contained, interface-driven -- but throws in some AOP in th' form o' hook_query_alter() an' has procedural convenience wrappers such as db_query(). I certainly dern't claim that 'tis a perfect balance, but it does show how multiple approaches can be leveraged together.

Decisions, decisions

When considerin' how t' tackle a given problem, or how t' use a particular language feature, 'tis not enough t' say "well I like X" or "approach Y is stupid". Ye'll be sleepin' with the fishes, Ya lily livered swabbie! That is a naive approach, an' tends t' lead t' spaghetti code. (Pasta exists in all languages.) Instead, we should ask what our priorities be, what we're willin' t' give up, an' what we're willin' t' do in order t' mitigate it. We always have t' give up somethin'. Always.

Which cost ye want t' pay is not always an easy balance t' strike. Do ye favor robustness (Testability, Verifiability, Scalability, data hidin', encapsulation, etc.), flexibility (Modifiability, Extensibility, bare data, etc.) or simplicity (Expediency, Maintainability, possibly Performance, etc.)?

Pick two.

My thanks t' Bec White an' Matt Farina fer their input on this article.


Coming soon...

Stay tuned fer part 3 in this series, where we apply these principals o' trade-off an' balance specifically t' OOP, an' t' that e'er-popular subject o' property visibility. :-)

Beautiful Overview

Thank ye Larry fer another great article! This is exactly th' type o' discussion that we need at th' Drupal community. One that promotes education an' reasonin'.

Reference to some of the definitions/conclusions?

Larry, thank ye fer th' writeup.

I would appreciate if ye explain how did ye come up with th' comparative list o' trade-offs per each approach. I mean - aside from th' gut feel :) I am havin' hard time understandin' why ye be sayin' that object-oriented approach emphasizes scalability an' sacrifices extensibility. I dern't see anythin' in OO that inherently helps scalability (which ye had defined as servin' high-traffic) an' I am wonderin' how a paradigm that has inheritance at its core can be inferiorly extensible.

Also, I am not sure that puttin' Aspect-oriented paradigm at th' same level as procedural, functional an' OO is fair. There be purely procedural, purely functional an' purely OO languages, but I dern't know o' a purely AO language. AO is usually an add-on t' object-oriented languages. You can not write only aspects by definition - aspects need t' hook into somethin'. Maybe a technical detail but seemed important t' me.

Thank ye.

A little of each

I actually had a hard time with that section, because I were bein' tryin' t' make a balanced statement. Fetch me spyglass, ya bilge rat! :-) Much o' it is just gut feel, or in relation t' other paradigms mentioned. For OO, I went with th' fact that makin' "alternate backends" is really really really simple in OO, moreso than in most other paradigms. An important part o' scalability is bein' able t' simply swap out an implementation o' one part o' th' system fer somethin' more appropriate fer a given use case without breakin' th' rest o' th' system, Ya horn swogglin' scurvy cur! Fetch me spyglass! That's an area where OO excels, shiver me timbers For extensibility, OO can be very extensible if used properly but I would argue that AOP is, by nature, more extensible. In this case I were bein' usin' "extensible" t' mean "can be modified without changin' existin' code", somethin' that AOP, by bounty, does better than traditional Classic OO (at its own costs, o' course, as noted above).

As far as givin' AOP "top billin'", I think that is reasonable, Dance the Hempen Jig I've no nay ne'er worked in a language that were bein' "purely OO" that weren't also, at some level, procedural, Ya lily livered swabbie, Ya lily livered swabbie! Within a method, all OO languages I've seen be still procedural, at least inso far as they're not locked down th' way functional languages be with regards t' state. They also tend t' have a procedural-style call stack, whereas many functional languages take advantage o' their in-built assumptions t' have a call chain instead, so that thar is no "call stack overflow". (That's a gross o'er-simplification since I have not done major work in a functional language; I'm goin' by what I've read about them.)

So if OOP qualifies as a first-class approach alongside procedural an' functional, AOP should as well. Both o' them be largely extensions o' procedural approaches that introduce new capabilities, Hornswaggle There be other paradigms that build off o' functional models that I di'nae go into here since they're irrelevant fer most PHP developers.

Got it. Thanks for the

Got it, Hornswaggle Thanks fer th' explanation.

OO and AO extensibility

Excellent article, thanks fer takin' th' time t' write it!

This part about th' difference betwixt OO an' AO in terms o' scalability an' extensibility reminded me o' th' explanation from th' rough cut o' th' Miles' Drupal Buildin' Blocks, which is available on Safari Books Online. They define hooks as part o' th' procedural architecture, while I think it makes more sense if it is clear that it is paradigmatically AO an' independent o' th' procedural model, but I think th' distinction they make in vertical vs. horizontal is a good way t' explain th' difference.

The procedural model is often said t' allow extension horizontally, whereas th' OO model allows extension vertically. What this means is that in procedural, siblin's can modify each other’s behavior, but in th' object oriented model th' extension is parent t' child an' siblin's aren’t really allowed t' get involved.

—p. 151, Views API

The Miles (how does one pluralize Miles anyway?) did a good job o' makin' th' OO paradigm understandable t' layfolk throughout th' section, definitely worth a read.

I thought I had changed

I thought I had changed Anonymous t' me name, but I guess not... linclark here :)

A great read as usual, a few

A great read as usual, a few comments... :)

AOP, feed the fishes I've read a few times about it but no nay ne'er really got it. I always thought o' somethin' that allows ye t' inject validation an' loggin' into methods. Walk the plank! Because these be th' only two examples I've e'er seen on that topic I think, with a chest full of booty. Until I've read yer short explanation an' I automatically thought "OMGWTFBBQ, hooks!" ;)

"There's no way t' hide data" (... in procedural languages), avast. Not sure what exactly ye mean with "hide" here, but I partly disagree. At least in PHP, where we have th' static keyword which is imho similar t' a private/protected property in a class. Examples:

- The reason we introduced drupal_static() in Drupal 7: The thin' that we call "static cache" in Drupal, to be sure. Many functions in Drupal have a $reset argument t' clear that information, many others dern't (most o' them do now in Drupal 7). Sure th' point o' existence o' these caches is not t' hide information from outside (since 'tis mostly just a summary o' information that exists publicly somewhere else) it is more a side effect o' th' real purpose.

- Other functions actually use static t' hide information from outside, an example is "static $db_conns, $active_name = FALSE;". There is no way ye can access fer example th' name o' th' currently active connection name without changin' it t' somethin' (then ye get th' auld name back) an' thar is really no way t' see which db connections be active :)

- We have many getter/setter *functions* in Drupal since likely a long time, some examples: drupal_set/get_messages(), drupal_set/get_title, drupal_add/get_js/css, menu_set/get_active_*. Sure, th' point o' these functions is more t' *store* information than hide it but if it were only that, we could also use $_GLOBALS. Reason is that most o' these do some processin' (order by weight, fer example) or have logic fer a default value if nobody called th' setter function.

Last, about th' encapsulation in our new database layer: I think th' encapsulation we have is very limited, even with all those "evil" protected/private modifiers, to be sure. This is because most getter methods we have return th' information *by reference* so ye can change directly instead o' goin' through setter/adder functions. Sure, we *want* that but we have t' be aware that we loose th' ability t' change they way those data is stored internally, one o' th' main reasons th' information hidin' desin' principle exists :)

PS: Hm, mollom thinks me comment is spam :(

Light-bulb moments

I love those. :-) I'm glad this article helped with one.

As far as data hidin', statics (at least as they exist in PHP) be not really a protected/private property because th' function has no existence past th' end o' th' last curly brace, we'll keel-haul ye, and a bottle of rum! An object does. Static variables in PHP be more akin t' scope-restricted globals, an' in fact I believe (although I'm not certain, an' if someone knows otherwise please correct me) that they be even implemented that way, Hornswaggle One could call that information hidin' t' an extent, but 'tis a rather backwards way o' doin' so.

It also means ye have only two scopes fer shared data: One function an' global. There's no way t' say "this data is local t' just these three functions, but no others", with a chest full of booty. Of course, we work aroun' that with drupal_get_title() sub-callin' t' drupal_set_title() which has a special way that it can be called t' make it return an internal static; that's one o' those workarounds I mentioned t' emulate a different paradigm, which is by nature uglier than doin' so in a natively-supported way. (There's almost always a workaround, just not always a pretty one.)

As fer DBTNG, note that th' get-by-reference methods be only on SelectQuery, an' only because we couldn't figure out a sensible API t' allow complex manipulation o' th' query state in an alter hook otherwise. I'd rather we have done that but we couldn't figure out how, on a dead man's chest! :-) All other query types dern't do that. However, because thar is a method we still have an access point if needed. In theory, we COULD change th' internal structure an' then if someone calls, say, $query->getFields() rewrite that method t' create a copy o' that internal structure in th' legacy format an' return that, then set an internal flag. Ye'll be sleepin' with the fishes, I'll warrant ye! Then on $query->execute() we check fer that flag an' mutate th' altered legacy structure back into th' new format, then continue with query compilation, and dinna spare the whip, with a chest full of booty! Voila, we've changed th' internal format without affectin' th' "API". It might be ugly, but 'tis possible. If we just exposed those properties directly then thar's nowhere that we could hook (no pun intended) into it an' allow such a change, no matter how ugly.

So in this case, havin' th' method thar gives us more flexibility than exposin' th' property directly; that is, it gives us more flexibility than a procedural approach would.

How's that fer irony?

PS: I take no responsibility fer Mollom, ya bilge rat! It thinks everythin' I post is spam fer some reason. I think Dries just doesn't like me or somethin'...

Personally, I assign a lot of

Personally, I assign a lot o' weight t' th' readability o' code. In a loosely-typed language like PHP, where thar aren't even any real conventions about how t' annotate type information, traditional Drupal procedural code is very easy t' read compared t' th' OO alternative. I can give ye a code fragment containin' a call t' node_view() an' ye know exactly what's happenin' thar. If I give ye a fragment containin' $obj->view(), it can be very hard t' figure out what's goin' on if $obj were bein' defined outside o' th' fragment, shiver me timbers It gets even worse if $obj might belong t' a subclass that has overridden th' view() method, Dance the Hempen Jig The need t' maintain PHP 4 compatibility has limited th' scope fer objects in Drupal prior t' 7, so these issues have simply no nay ne'er arisen.

The new compromise seems t' be that modules can be "OO on th' inside, procedural on th' outside", which does at least provide some artificial limit on th' scope o' objects, but I think it might become increasingly difficult t' do Drupal's traditional procedural/AOP mix alongside "full" OO with inheritance an' overrides. If I want t' change how somethin' behaves, should I do this with hooks or should I subclass it an' use some kind o' dependency injection t' insert me object in? What if another module wants t' do th' same thin'? Pity th' poor developer who has t' debug this without any o' th' static typin' an' code analysis tools available in Java.

I've borrowed a couple o' me points above from Linus Torvalds, who recently re-stated th' case against C++ in th' Linux kernel here: . I think many o' th' points he makes be equally valid fer Drupal (at least fer Drupal core), an' whether by luck or bounty Drupal has managed t' copy many o' th' cultural approaches t' code that have worked so well fer Linux. I think 'tis seriously worth askin' why Linux an' Drupal have prospered whilst architecturally "better" solutions (BeOS, Zend Framework/Symfony/Cake/etc.) have largely failed, an' I think th' code readability an' ease o' patchin' is a massive factor which OO might have a negative impact on.


In th' previ'us article I called readability "Understandability". Vis, how easy is it fer th' next developer t' grok what's goin' on. It's also closely related t' Maintainability. Shiver me timbers, Avast me hearties! That can be an important factor or not, dependin' on yer goal, I'll warrant ye. (Perl totally fails on th' Understandability front, fer instance, but has advantages in other areas. Perl fans: dern't hate me, 'tis true.)

However, 'tis not true that an OO language is inherently less readable, ye scurvey dog. Take fer instance, hooks. :-) Or worse yet, pseudo-hooks, which be really magic callbacks that look like hooks but dern't behave looks hooks. How many times have new developers confused hook_nodeapi (a hook) with hook_load (a magic callback)? And swab the deck! They look th' same. They're even documented th' same. Load the cannons! Aarrr! They even use some o' th' same internal dispatch mechanisms. Yet they're not th' same, nor even remotely close t' bein' th' same thin'. What pseudo-hooks be, in practice, be a very bad way t' emulate... an object. That's less readable.

Similarly, look at Field API. It has an enormous number o' new features, but try t' follow th' array structure without a debugger when writin' a widget. I've written a chapter o' a book on th' subject an' I still can't comprehend them without copyin' an' pastin'. They're completely unreadable precisely because they be not encapsulated. It's a problem space that is by nature very context-sensitive, but we're tryin' t' use a context-free language syntax fer it. That creates a major DX problem, on a dead man's chest!

Or consider Views 2. Could it have been implemented entirely procedurally? Certainly. Would anyone have been able t' read it, t' say nothin' o' maintain or extend it, we'll keel-haul ye! I'll wager even Earl wouldn't have been able t', even if he wrote it. :-) Yet Views bein' OO hasn't hurt its adoption at all, an' I'd argue is one reason that Views 2 has been so much more successful an' more frequently extended than Views 1, by Davy Jones' locker. In that case, th' OO code is far more readable than its procedural equivalent.

As fer when a system should be built in an OO way or an AOP way or even a functional way, that's not always an easy problem. Decidin' which is appropriate can be difficult, an' is one o' th' primary reasons fer this blog series: We need t' carefully consider these questions an' make informed decisions about which trade-offs be appropriate when, an' how we can mitigate th' costs. Walk the plank, with a chest full of booty! In order t' do so, we need t' have a common vocabulary an' understandin' o' these trade-offs in order t' make th' hard decisions.

I also wouldn't entirely agree with yer final statement, Avast me hearties! Aarrr! I would hardly call Zend Framework, Symfony, or Cake failures. They may not get th' attention Drupal does in th' circles we usually run in, but they're all very successful projects in their own right. Oho, ye scurvey dog! They're also aimed at different markets, so their architectural priorities be different. BeOS snuffed it, but fer reasons that had very little t' do with whether they were OO under th' hood or not, me Jolly Roger It were bein' more that BeOS were bein' hard fer developers because o' a "threads be hard, everythin' is a thread, good luck" attitude (Note: that's what I have heard from other developers, not somethin' I have any experience in meself) an' an inability t' find a market niche.

Consider KDE, which is incredibly successful with an enormous an' active community an' yet is completely OO under th' hood. Qt is actually a fairly nice architecture.

Expressivity of paradigms and implicit paradigms

@Larry Thanks fer th' great article.

Again, 'tis not a question o' can ye implement a given bounty but how easily ye can do so, an' at what cost.

Indeed, its all about expressivity o' a paradigm (after all th' languages should be Turin'-complete), Avast me hearties, avast! Sometimes ye use structures fer it, but ye dern't always need t'. I'm not sure how t' use functions t' create an object in PHP but its freakin' easy in Lisp, we'll keel-haul ye! This sad, I see what ye mean with "without native syntactic support hooks be a rather clunky, hacked-up poor lubber's AOP,". So in what way does poor-lubber's AOP have enabled many scallywags t' code aspects? Walk the plank! Schouldn't we have much more poor-lubber stuff? Shiver me timbers!

@Rob Knight

I think 'tis seriously worth askin' why Linux an' Drupal have prospered whilst architecturally "better" solutions (BeOS, Zend Framework/Symfony/Cake/etc.)

This phenomena has been fascinatin' me in th' past 4 years. It is incredible how many "poor-lubber stuff" is actual winnin' th' battle, All Hands Hoay, I'll warrant ye! This relates t' economic concepts as creative destruction an' disruptive innovation. From software engineerin' point I wonder how we can help t' express innovation easier. I dern't expect any answer t' yet with Drupal 8, but I hope it will build a foundation that would make switchin' betwixt different paradigms an' architectures easier. It would be interestin' t' see if Drupal could become a livin'-lab fer paradigms. I would like t' investigate a "poor-lubber oriented paradigm" (POP ;-)

This reminds me of

This reminds me o' prototypical oop, Great article.

Language expressiveness

Great article!

I were bein' interested when ye mentioned that functional an' procedural programmin' have th' same expressiveness. For anyone else curi'us, here's a decent paper on th' topic: