What are the best practices for coding a wiki extension to survive MediaWiki updates? As a software engineer, I imagine you'd want to:
- Use the standard file/class layout prescribed in http://www.mediawiki.org/wiki/Manual:Extensions#Writing_Extensions. - Stick to calling a class's public methods, rather than accessing its $mFoobar members, whenever possible - Don't depend on implementation details of MW's methods, just the public interfaces - Call methods on the extension's $parser parameter, rather than $wgParser, when possible - Avoid modifying MediaWiki core code - Don't name your global variables beginning with "$wg" to avoid clashes (present and future) - Name your classes so they can't clash with MediaWiki's (past and future) -- maybe prefix their names with something unique, at least until PHP 6 namespaces are widespread - Don't hard-code English text, define system messages
I didn't see documentation on this sort of thing beyond what's on http://www.mediawiki.org/wiki/Manual:Extensions. Are there other best practices?
Thanks, DanB
Hi,
I removed the <div class="portlet" id="p-logo"> from the MonoBook.php and would like to top align the <div class='portlet' id='p-Navigation'> with <div id="content">.
The only work around I can find is to set the top margin on the .portlet to -2.5em which isn't very graceful. Something is preventing the top alignment, but I can't figure out what. Any hints more than welcomed.
Alain
Alain van Acker wrote:
The only work around I can find is to set the top margin on the .portlet to -2.5em which isn't very graceful. Something is preventing the top alignment, but I can't figure out what. Any hints more than welcomed.
Likely some absolute positioning somewhere is mucking it up. I created a skin based on Monobook and removed all absolute positioning and used just default relative positioning (i.e. no explicit _relative_ in the CSS). It provides a more flexible page design and correctly handles text resizing in browsers.
Mike
Daniel Barrett wrote:
Stick to calling a class's public methods, rather than accessing its $mFoobar members, whenever possible
Don't depend on implementation details of MW's methods, just the public interfaces
Call methods on the extension's $parser parameter, rather than $wgParser, when possible
These are just proper OO practice, not specific to MW. Good coding practice is good coding practice. :)
Mike
I agree, that's how I dreamed up the list of practices. At the same time, MW does expose classes' $mFoobar members publicly, e.g., Parser->$mOutput.
DanB
-----Original Message----- These are just proper OO practice, not specific to MW. Good coding practice is good coding practice. :)
Mike
Stick to calling a class's public methods, rather than accessing its $mFoobar members, whenever possible
Meh. Getters and setters are clutter - just access what you want and be done with it. Keywords like 'private' and 'const' just end up making extension development more difficult.
Don't depend on implementation details of MW's methods, just the public interfaces
Well yeah, in an ideal world, yes. Unfortunately, it's sometimes necessary to clone swaths of the codebase to make a small functional change hidden where a wgHook doesn't reach. Use your judgement.
Call methods on the extension's $parser parameter, rather than $wgParser, when possible
Correct. In most cases the passed in $parser is what you want, but there /are/ instances where you'd want to create your own Parser instance and use it to perform a parse. For example if you want some wikitext parsed using pristine MW parsing rules, you'd create your own Parser instance rather than use the passed in one, which likely already has tags and parser functions attached to it. However, this is an edge case - for nearly all cases it's best to use the passed in $parser param.
Avoid modifying MediaWiki core code
Avoid modifying MediaWiki core code LIKE THE PLAGUE (there, fixed that for you). If you find you can't do what you need to given existing hooks, either ask on a list like this one, or insert a new wfRunHooks() call and hook into it - then ask someone in the group to commit it for you.
-- Jim R. Wilson (jimbojw)
On Thu, May 1, 2008 at 11:03 AM, Daniel Barrett danb@vistaprint.com wrote:
I agree, that's how I dreamed up the list of practices. At the same time, MW does expose classes' $mFoobar members publicly, e.g., Parser->$mOutput.
DanB
-----Original Message----- These are just proper OO practice, not specific to MW. Good coding practice is good coding practice. :)
Mike
MediaWiki-l mailing list MediaWiki-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
Jim R. Wilson wrote:
Stick to calling a class's public methods, rather than accessing its $mFoobar members, whenever possible
Meh. Getters and setters are clutter - just access what you want and be done with it.
If only more languages used an Eiffel approach to this...
Keywords like 'private' and 'const' just end up making extension development more difficult.
Sounds like the result of bad design rather than a real problem. If it's private, it should likely be something that Joe Averageprogrammer will never need to access. If it's const, well, it should really be const.
Don't depend on implementation details of MW's methods, just the public interfaces
Well yeah, in an ideal world, yes. Unfortunately, it's sometimes necessary to clone swaths of the codebase to make a small functional change hidden where a wgHook doesn't reach. Use your judgement.
Sounds like procedural rather than OO thinking. But that gets back to the original design problem.
Unfortunately, resolving problems through design rather than through code (via kludge) is problematic in a distributed development model like open source code with no dictator setting real standards. Closed source environments can avoid this by appointing the dictator and giving it power. Corporate environments fail because the dictator is, more often than not, a moron.
My decades of experience in developing real-world, mission critical apps (the kind that keep aircraft in the air) is that the closer to the theoretically "perfect" design/code you get, the fewer problems down the line. When someone opens a forbidden door, all hell eventually breaks loose.
Mike
Thanks Jim. One comment on what you wrote:
Avoid modifying MediaWiki core code LIKE THE PLAGUE (there, fixed that for you). If you find you can't do what you need to given existing hooks, either ask on a list like this one, or insert a new wfRunHooks() call and hook into it - then ask someone in the group to commit it for you.
I agree that one should avoid modifying the MW core code, but in practice, it can be done well, very robustly. I have been working with a modified codebase for over a year and MW upgrades are still trivial. I usually need ~15-30 minutes to merge the 2-3 modifications that don't merge automatically. And 30 minutes every 3 months is a good investment. In my upcoming MW book, I describe the method (but still warn in big letters not to modify the core code).
I do like your idea to ask the MW team to commit a few hook entry points.
DanB
I do like your idea to ask the MW team to commit a few hook entry points.
Yeah - the reason I say ask the group is that /sometimes/ it really is possible to reach something that seems inaccessible. I've used combinations Parser functions for example to replace the MediaWiki parser with Textile and Markdown for example - it's ugly (probably to Michael's dismay), but it works :/
If you go the route of creating your own hook, even if the hook doesn't get added, your patching procedure becomes even more upgrade-safe since it'll probably be a one-line change. It'll also prompt you to try to reduce the number of different locations where changes need to be made. Nothing kills upgradability like shotgun surgery.
-- Jim
On Thu, May 1, 2008 at 4:19 PM, Daniel Barrett danb@vistaprint.com wrote:
Thanks Jim. One comment on what you wrote:
Avoid modifying MediaWiki core code LIKE THE PLAGUE (there, fixed that for you). If you find you can't do what you need to given existing hooks, either ask on a list like this one, or insert a new wfRunHooks() call and hook into it - then ask someone in the group to commit it for you.
I agree that one should avoid modifying the MW core code, but in practice, it can be done well, very robustly. I have been working with a modified codebase for over a year and MW upgrades are still trivial. I usually need ~15-30 minutes to merge the 2-3 modifications that don't merge automatically. And 30 minutes every 3 months is a good investment. In my upcoming MW book, I describe the method (but still warn in big letters not to modify the core code).
I do like your idea to ask the MW team to commit a few hook entry points.
DanB
MediaWiki-l mailing list MediaWiki-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
mediawiki-l@lists.wikimedia.org