$30 off During Our Annual Pro Sale. View Details »

WordPress: To OOP or not to OOP

WordPress: To OOP or not to OOP

Thoughts on incremental structure in larger software projects, the WordPress community, and few OOP examples

Nikolay Bachiyski

October 06, 2013
Tweet

More Decks by Nikolay Bachiyski

Other Decks in Programming

Transcript

  1. To OOP
    or
    not to OOP
    Nikolay Bachiyski, WordCamp Europe 2013

    View Slide

  2. Nikolay

    View Slide

  3. Automattic

    View Slide

  4. http://extrapolate.me/
    @nikolayb
    github://nb

    View Slide

  5. Next 25 minutes:

    View Slide

  6. 0.Why should we care?

    View Slide

  7. 1. How WordPress
    developers see OOP

    View Slide

  8. 2. Better OOP

    View Slide

  9. 0. Why should we care?

    View Slide

  10. WordPress is BIG

    View Slide

  11. View Slide

  12. 120K Lines of PHP

    View Slide

  13. Needs some structure
    Lines of PHP

    View Slide

  14. Structure

    View Slide

  15. No Structure

    View Slide

  16. Not many rules

    View Slide

  17. Each small piece is
    easy to understand

    View Slide

  18. Hard to change &
    improve

    View Slide

  19. Impossible to
    understand deeply

    View Slide

  20. View Slide

  21. View Slide

  22. Structure
    =
    Modules + Communication

    View Slide

  23. View Slide

  24. View Slide

  25. View Slide

  26. View Slide

  27. View Slide

  28. Structure → Code

    View Slide

  29. Choices in PHP:
    Procedural and OOP

    View Slide

  30. Procedural

    View Slide

  31. ↑ Perceived simplicity

    View Slide

  32. ↓ Hard to hide
    implementation

    View Slide

  33. ↓ Prefix all the things
    (<5.3)

    View Slide

  34. ↓ Data sharing using
    globals only

    View Slide

  35. ↓ Hard to test

    View Slide

  36. OOP

    View Slide

  37. ↓ Perceived
    complicatedness

    View Slide

  38. 1. How WordPress
    developers see OOP

    View Slide

  39. A big reason WP is so popular is
    because it is not infatuated with
    the latest, greatest developer
    lust objects…

    View Slide

  40. One of the biggest problems I've
    found with OOP is that it forces
    the developer to bake in structure
    long before the developer actually
    understands what that structure
    should be…

    View Slide

  41. Classes==Good

    View Slide

  42. OOP == Bad

    View Slide

  43. ?

    View Slide

  44. One of the biggest problems I've
    found with OOP is that it forces
    the developer to bake in structure
    long before the developer actually
    understands what that structure
    should be…

    View Slide

  45. One of the biggest problems I've
    found with OOP is that it forces
    the developer to bake in structure
    long before the developer actually
    understands what that structure
    should be…

    View Slide

  46. Forces = always
    happens?

    View Slide

  47. Building Useful
    Abstractions is HARD

    View Slide

  48. Very Hard

    View Slide

  49. Either refuse
    responsibility

    View Slide

  50. Or try

    View Slide

  51. Fail

    View Slide

  52. Learn

    View Slide

  53. View Slide

  54. Try again

    View Slide

  55. Fail better

    View Slide

  56. View Slide

  57. Succeed

    View Slide

  58. View Slide

  59. OOP can be good

    View Slide

  60. Do one thing, do it well

    View Slide

  61. View Slide

  62. View Slide

  63. class WP_Screen {
    function get( $hook_name = '' );
    function set_current_screen();
    function in_admin( $admin = null );
    function add_old_compat_help( $screen, $help );
    function set_parentage( $parent_file );
    function add_option( $option, $args = array() );
    function get_option( $option, $key = false );
    function get_help_tabs();
    function get_help_tab( $id );
    function add_help_tab( $args );
    function remove_help_tab( $id );
    function remove_help_tabs();
    function get_help_sidebar();
    function set_help_sidebar( $content );
    function get_columns();
    function render_screen_meta();
    function show_screen_options();
    function render_screen_options();
    function render_screen_layout();
    function render_per_page_options();
    }

    View Slide

  64. class WP_Screen {
    function get( $hook_name = '' );
    function set_current_screen();
    function in_admin( $admin = null );
    function add_old_compat_help( $screen, $help );
    function set_parentage( $parent_file );
    function add_option( $option, $args = array() );
    function get_option( $option, $key = false );
    function get_help_tabs();
    function get_help_tab( $id );
    function add_help_tab( $args );
    function remove_help_tab( $id );
    function remove_help_tabs();
    function get_help_sidebar();
    function set_help_sidebar( $content );
    function get_columns();
    function render_screen_meta();
    function show_screen_options();
    function render_screen_options();
    function render_screen_layout();
    function render_per_page_options();
    }

    View Slide

  65. Responsible for
    or
    Represents a

    View Slide

  66. No And’s, Or’s,
    or But’s

    View Slide

  67. Short!

    View Slide

  68. The big idea is “messaging” [...]
    The key in making great and
    growable systems is much more to
    design how its modules
    communicate rather than what
    their internal properties and
    behaviors should be.

    View Slide

  69. Innocuous inheritance

    View Slide

  70. WP_Image_Editor

    View Slide

  71. WP_Image_Editor_Imagick
    extends
    WP_Image_Editor

    View Slide

  72. WP_Image_Editor_GD
    extends
    WP_Image_Editor

    View Slide

  73. Common logic in all
    subclasses

    View Slide

  74. if ( ! $this->make_image( $filename, 'imagejpeg',
    array( $image, $filename, apply_filters( 'jpeg_quality', $this-
    >quality, 'image_resize' ) ) ) )
    $this->image->setImageCompressionQuality
    ( apply_filters( 'jpeg_quality', $quality, 'image_resize' ) );
    GD:
    ImageMagick:

    View Slide

  75. GD:
    ImageMagick:
    protected function update_size( $width = null, $height = null ) {

    return parent::update_size( $width, $height );
    }
    protected function update_size( $width = null, $height = null ) {

    return parent::update_size( $width, $height );
    }

    View Slide

  76. Change in interface =
    change in every
    subclass

    View Slide

  77. How to spot?

    View Slide

  78. IS-A vs. HAS-A/USES

    View Slide

  79. Inheritance for reuse

    View Slide

  80. Gravatar widget is a
    WP Widget
    ✅✓

    View Slide

  81. ImagickMagick is an
    Image Editor

    View Slide

  82. WP Image Editor uses
    ImagickMagick

    View Slide

  83. WP Image Editor uses
    GD

    View Slide

  84. WP Image Editor has
    an image

    View Slide

  85. Composition

    View Slide

  86. $this->engine = new WP_Image_Engine_GD();
    $this->engine = new WP_Image_Engine_ImageMagick();
    $this->image = $this->engine->load( $filename );
    $new_size = $this->image->update_size();

    View Slide

  87. function save( $filename = null, $mime_type = null ) {

    $jpeg_quality = apply_filters( 'jpeg_quality', … );
    $this->image->save( $filename, $mime_type,
    array( 'jpeg_quality' => $jpeg_quality ) );

    }

    View Slide

  88. What to remember?

    View Slide

  89. Communication
    between modules is
    everything

    View Slide

  90. Structure is hard

    View Slide

  91. We can’t get better
    without trying and
    failing first

    View Slide

  92. View Slide

  93. Growing Object-Oriented Software,
    Guided by Tests
    http://www.growing-object-oriented-software.com/

    View Slide

  94. ?

    View Slide