26 comments

[ 3.3 ms ] story [ 63.3 ms ] thread
I know how they feel. I often replace code and feel like it's attacking the author; and also feel like my own code is being attacked when it's replaced.
We should have some more common script for telling a colleague "that you for writing this code. It has clarified the problem a lot." as we delete the code.

Its hard because while we do recognize that the value and difficulty is in the problem-understanding, the code is the most tangible thing we produce and so it feels like the work.

I think it goes both ways.

In every shop I work at, I do ask WHY someone refactored something I have done. However, I do not do so with any malice.

As you point out above, sometimes, that first writeup is a working implementation, and while important, the first iteration is often not optimal.

Thus, asking why is useful because it helps us become better developers. Talking about the changes helps share knowledge, and, yes, when questionable changes are made, it can be a lesson for the refactor-er as well.

And when I am the refactor-er... I will try to explain my changes in the PR. Usually with a polite explanation of why I refactored.

Thanks for mentioning this. It has literally never occurred to me that refactoring someone’s code might make them feel attacked. I believe in continuous refactoring and assume my colleagues do too, but I think I need to re-examine that assumption.
If you replace 100 lines of my code with 20 lines, God bless you.

If you replace 100 lines of my code with 500 lines of buzzword-driven development that is 50% copied off of Stackoverflow, we're going to have a discussion.

I don't know much about JavaScript. Are you saying that Prototype was replaced with bad code? Or was this not directly related comment?
You get paid either way though, right?
So long as I'm not getting called at 3am to debug it, then yup.
So, I recently (as in yesterday evening) converted the following piece of code in index.php of a wordpress plugin:

    if( $_GET["foo"] == "bar" ) {
    //add_action( 'wp_loaded', 'do_foo' );
    //add_action( 'init', 'do_foo' );    
    //add_action( 'admin_init', 'do_foo' );
    do_foo();
    }
which allowed easy launching of do_foo() by simply httping http://wordpress.tld/?foor=bar

to

    add_action('rest_api_init', 'Company\PluginName\setup_foo_route');
and

    namespace Company\PluginName;

    function setup_foo_route()
    {
        register_rest_route(
            'company/v1',
            'bar',
            array(
                'methods' => 'GET',
                'callback' => 'Company\PluginName\do_foo',
            )
        );
    }
which can be run by httping http://wordpress.tld/?rest_route=/company/bar

Which one of us would like to talk to :) ?

That’s perhaps much too small to be an example of what the parent comment was talking about. This might be a good example of what the article is talking about though. These represent two different fashions, both of which have enjoyed widespread support at different times. The original is explicit and smaller and easier for someone who’s not you to follow & modify. The latter is event/callback driven, and more complicated to follow, but in a large codebase might be a pattern that is easier to build on, maintain, and refactor, as well as harder to screw up when adding new routes.
I agree with you. What makes me lean towards my solution is that I can pass the plate to the WordPress documentation if anyone else want to know what the code is doing and we can follow the trail of callbacks and hooks while that request check can be (and in this case, is) sprinkled all over the codebase.

What I noticed is that people following the first method ends up hacking core functionalities of WP because "it just works" but in the end that makes the code unstable and harder to maintain because it relies on undocumented stuff and a coding style that is very personal. It can also messes big time with stable things expected from the CMS (mangled taxonomies, hijacked hooks in the core instead of the WP pile that make it hard to debug or to play nice with other plugins/themes).

Sorry for the critique on methodology but I'd start to consider a different system for routing vs hooking into the WordPress REST API.

If I'm doing anything that actually requires sane PHP primitives (like the routing in your above example, and also notably DB) I steer clear from WordPress entirely. WordPress is a good CMS and makes for a great blogging platform but I have done my best to decouple any-and-all custom application development to it's own API.

WordPress and it's core simply don't offer good tools, and it's a VERY highly targeted platform in regards to security. I would suggest Symfony or Laravel for PHP frameworks that do APIs very well; or even AltoRouter + vanilla PHP for super light-weight stuff where you want minimal dependencies. Personally I think Laravel is the easiest, and a joy to learn.

Otherwise - kudos on ripping it out and replacing it with cleaner code!

Thanks. I am not sure I understand the suggestion. Do you mean I could build the API with Laravel/Lumen/Symphony and bolt it on top of WP-Core or WordPress options or even directly the posts table (for example) ? (In this particular case the WordPress CMS is non-negotiable but I have no problems considering bypassing its REST API to interact with it if it brings significant advantages).

I admit I am a bit nervous in regard to opening WP with REST endpoints considering its reputation.

Yes, that's more or less what I assume they mean.

Likely[1], the intent is almost to treat Wordpress as one component (dependency) of your application. Remove all business logic that's held directly in its tables and code, and instead add layer from Symphony/Laravel/Framework-Goes-Here which "syncs/pushes/writes" to Wordpress. Wordpress becomes just a "piece" of your application instead of your application. Wordpress is just the CMS for your business logic (application), not the application itself :)

It'll reduce the surface area of attacks because you fucks with wordpress internals less. It'll make upgrades easier because you fucks with wordpress internals less, and it'll generally make life easier down the road because you need to fucks with wordpress internals less.

Just my two cents :)

[1] Because what they outlined is like spot on with what I'd be doing... I think nervous laugh -_-;

> Likely[1], the intent is almost to treat Wordpress as one component (dependency) of your application. Remove all business logic that's held directly in its tables and code, and instead add layer from Symphony/Laravel/Framework-Goes-Here which "syncs/pushes/writes" to Wordpress.

Nailed it. 100%

WordPress gets pushed WAY too far and treating it more as a component/dep of your application is a perfect way of describing how I go about my work (stealing that explanation). When I start see people jacking into the REST API and the like I feel like that's "too far". However, in OP's defense, I have done exactly what he's showing myself and 100% understand the need with the right constraints!

I often push my clients to decouple anything that can be described as "application-specific" or "business logic" ASAP for MANY reasons - security, better dev tooling, scaling, not relying on an EAV DB design under the hood, etc. Usually it's a <5 table CRUD application that can be described in 10-20 API routes... Even if you need an authentication system thrown in there Laravel eats that for breakfast. Way easier to scale, I have better control over the DB schema, I get "nice-to-haves" if I want them (ORM, input validation, DB migrations/seeds), I can trust it, etc etc.

Also - when you use something like Laravel/Symfony you can totally tie into WordPress primitives, or even just point at the same DB as WP (you kinda touch on this). Some people may really look down on that - I see it just as any other integration. When done thoughtfully and WITH DOCUMENTATION it is 100% fine to "join the worlds" like that IMO. Ultimately, you get a LOT more flexibility when you pull in a tool and decouple a bit from WordPress which is why I'm getting all preachy.

I feel responsible PHP devs should program very carefully, and/or use opinionated tools that are thoroughly vetted and well designed (like Symfony and Laravel). WordPress, it's core, it's team, and it's plugins are the antitheses of that last sentence! But for many it's a necessary evil as it still is the most popular/developed-for "host-your-own CMS" solution.

Thanks for backing me up - that comment could have really backfired with the HN audience. Cheers!

Yep! I've supported a lot of high profile WordPress installations for about 15 years now, all with varying degrees of customization/applications tied-in. For me it's less reputation and just personal experience of knowing what will be less painful in the long-run to support, scale, and extend.

A lot of people will frown on my advice to pull in the primitives from WP and/or directly tie-in to the existing database. People have an "all-or-nothing" approach to WP/application development and will push you to do things 100% in one tool or another... sometimes this is a great decision, many times it is not.

The truth is, WordPress is a great CMS with backwards compatibility that is astounding... but to maintain that backwards compatibility it has to hold itself back. When I have to work on WordPress sites (way less often by choice) I find the APIs and ergonomics to be horrid and regressive, as-if I was still stuck programming for PHP 5.x.

The downside of what I'm pushing: you have one more codebase to manage/deploy/update/document/etc. For me, that's no big deal. I have an established GitLab pipeline for smooth deployments of WordPress and Laravel codebases alike.

Effectively I've designed my engineering projects/teams around "spinning off a microservice when needed"; but I also work on very large-scale applications. One more thing that keeps this manageable is hella-good documentation _IN THE REPOS_ that link to sibling codebases + describes every significant integration. (WP + Laravel via HTTP API and DB tie-in)

Same goes with the API docs - even if internal, and even if for 1-2 routes: Ensure every potential HTTP request/method/URI is documented and kept up-to-date. I rely on Postman for this so I also get actual tooling along with my docs!

Keep fighting the good fight =)

Slightly tangential but it's good description about the problems that Javascript still faces today.
In 2005, I created Prototype, the first of a generation of JavaScript libraries designed for building modern web applications. Prototype was based on a far-out idea in a time of stagnant browser innovation: what if we fixed the deficiencies of JavaScript by augmenting its built-in types with new behavior?

Good lord. It's so obvious that this causes breakage all over the place once the API changes. How could anyone think this is a good idea?

After some time, though, it became clear that Prototype’s core idea was at odds with the world. Browser vendors responded to the JavaScript renaissance by adding new APIs, many of which conflicted with Prototype’s implementation. And developers began to show a preference for small, self-contained, modular libraries over more monolithic frameworks.

No, not "after some time". This is common software development knowledge since the 80's that you and other people just rediscovered. Please don't blame the world for bad design caused by ignorance.

The conclusion to this article is really powerful. The distinction being made is important - important to understand from both a user's and a developer's perspective. Too often on both sides the line is blurred and discussions around technical topics either get taken personally or become personal attacks.
More broadly, it’s an important emotional insight to realize that you are not the product of your work. You are the insight and the knowledge and the diligence and the intelligence that produced the work that was a good solution to a particular problem that existed in a particular context at a particular time. You are the person who did good work before and who can do it again.
> Browser vendors responded to the JavaScript renaissance by adding new APIs, many of which conflicted with Prototype’s implementation. And developers began to show a preference for small, self-contained, modular libraries over more monolithic frameworks.

I also find this very interesting. Many codebases decline in usage by not being actively developed. Other times, changing the way things are done goes against the core and is better off leaving it alone, and developing anew. Of course this is only clearly visible in retrospect. I'm generally against adapting to trends and wonder why perfectly complete and functioning frameworks need to be actively developed. This is why--we want to know that the framework will change with the users.

The second part of the trend to prefer modular libraries, I think was transitional as there was no one framework that had the best of breed components and using individual libraries produced a better ad-hoc framework. Now we have something in-between with coherent frameworks but still having replaceable parts.

So, we're supposed to take ownership of our work when it suits our bosses, and alienate ourselves from our work when ownership is inconvenient to others?
The other piece to this is in matters of the heart and pride - the intent behind it and the way it is done, oftentimes matters more than the outcome.

If someone goes about it the right way, the wrong decision in hindsight will feel right at the moment in time. Human matters oftentimes require a delicate touch, something that not many of us deeply involved in software pay attention to :)

This applies in dealing with others but perhaps even more so in dealing with yourself. If you don't tie your self worth to the work that you do, when the tides of time make your work irrelevant, it won't be so painful.

Up until Prototype I'd purposely stayed away from Javascript. All my app code was server side Perl. Prototype, for me, demonstrated the potential of JS and made me want to look further into it.

I first used it to reduced the number of calls to my server by showing/hiding sections of a form and that made my apps way easier to use and much faster for the end user.

It was a little clunky (for me) to implement but it worked with most of the web browsers at the time and that made those features available across platforms. That was huge for me. I replaced it with jQuery later on and still use jQuery.

I have to credit Sam Stephenson with showing us (or at least me) the way towards full blown client side web apps. My latest version of that same app runs entirely in the user's web browser on or offline. Prototype was the first stepping stone I stood on to get here.

There are still 100s of thousands of Magento 1 sites still around that would be using Prototype for core functions. Always fun trying to get the two to play nicely together. I remember having to work with MooTools occasionally as well before jQuery completely took over.