Categories


Archives


Recent Posts


Categories


The Problem with OO UI Abstractions

astorm

Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

Updated for Magento 2! No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

Keeping with UI Component form theme but drawing a wider circle, if you take a look at HTML source of a button on a backend Magento 2 HTML form, you’ll see something like the following

<button id="back" 
        title="Back" 
        type="button" 
        class="action- scalable back" 
        onclick="location.href = 'http://magento-2-1-3.dev/admin/cms/page/index/key/b202205a440f39f9cefe4724da28f8a6b1fa8b255f758f077cd9e8ef3181ca13/';"
        data-ui-id="back-button">

<button id="save" 
        title="Save Page" 
        type="button" 
        class="action- scalable save primary ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" 
        onclick="location.href = 'http://magento-2-1-3.dev/admin/cms/index/index/key/d82f1d2820123cf3f9144c3f42ce6cbd3ab129d72ff68b9219fd66fc98544c96/';" 
        data-form-role="save" 
        data-ui-id="save-button" 
        role="button" 
        aria-disabled="false">

These buttons were not things a front-end developer hand crafted. A PHP class (several, actually) generated this HTML. You may object to this on principle, but that’s not the problem we’re talking about today.

You’ll also notice these buttons have old school onclick attributes. You may objects to this on principle, but that’s not the problem we’re talking about today.

The problem is, someone created an abstraction for simple buttons. i.e. they wrote some PHP code that generates HTML. Part of this code looks something like this

class BackButton extends GenericButton implements ButtonProviderInterface
{
    /**
     * @return array
     */
    public function getButtonData()
    {
        return [
            'label' => __('Back'),
            'on_click' => sprintf("location.href = '%s';", $this->getBackUrl()),
            'class' => 'back',
            'sort_order' => 10
        ];
    }

    /**
     * Get URL for back (reset) button
     *
     * @return string
     */
    public function getBackUrl()
    {
        return $this->getUrl('*/*/');
    }
} 

A structured array of data provides a label, an onclick string, an HTML class, and a sort order. This data gets used by the PHP code that renders buttons. Now anyone can create a button that, when clicked on, will go to a URL.

The problem with this is folks who

  1. Don’t know what these button class are for
  2. Don’t understand the underlying implementation of the abstraction

If we look back at the HTML source of a button on a form page we see two buttons.

<button id="back" 
        title="Back" 
        type="button" 
        class="action- scalable back" 
        onclick="location.href = 'http://magento-2-1-3.dev/admin/cms/page/index/key/b202205a440f39f9cefe4724da28f8a6b1fa8b255f758f077cd9e8ef3181ca13/';"
        data-ui-id="back-button">

<button id="save" 
        title="Save Page" 
        type="button" 
        class="action- scalable save primary ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" 
        onclick="location.href = 'http://magento-2-1-3.dev/admin/cms/index/index/key/d82f1d2820123cf3f9144c3f42ce6cbd3ab129d72ff68b9219fd66fc98544c96/';" 
        data-form-role="save" 
        data-ui-id="save-button" 
        role="button" 
        aria-disabled="false">

However, the onclick attribute is only used on one of these buttons. Click the back button, and the UI will bring you back to the grid listing page by invoking the window.location javascript. However, the save page button works by POSTing values to a URL (as discussed last time). The location.href code is ignored. However, it’s left in the HTML source as a red herring for anyone coming along later.

This is a problem you’ll see time and time again when traditional OO patterns are applied to generating user interfaces on the web. Developer A writes a foo abstraction. Developer B needs a foo, so uses that abstraction without fully understanding its guts. Developer’s B’s code “works”, but under the hood it’s a mess.

A front-end developer will look at this situation and think the OO folks are nuts. What’s interesting is, the OO folks probably thinks this is a strength of their systems – i.e. allowing developers to create UIs via PHP and XML without the need to understand any front-end code.

Copyright © Alan Storm 1975 – 2019 All Rights Reserved

Originally Posted: 9th February 2017