Hey,

This overview seems quite reasonable to me until this point:

on the other hand it [using ie dependency injection] would mean a lot of
> gadgets break every
> time we change things, and some possibly do even if we don't.
>

I am unsure how you are reaching that conclusion.

Dependency Injection, and more generally speaking Inversion of Control, is
an often useful approach in creating cohesive code with low coupling.
However in itself it does not magically make your architecture and code
quality good. You can still create low quality code and a bad architecture
when using Dependency Injection (granted, it's easier to do so when not
using DI).

If gadgets break whenever you change something, you are suffering from
whats called fragility. The main cause for this is coupling that should not
be there. On an architecture level this means there is something wrong with
your boundaries. That is the first thing I'd be scrutinizing in your
situation.

Some sort of hook system (with try-catch blocks, strict
> validation etc) would be much more stable
>

I'm not sure either approach is inherently more stable. Stability depends a
lot on how you are implementing it. The main thing to hold in mind here for
either approach is to be careful with what you expose. Narrow well defined
interfaces are typically the way you want to go. When exposing to much, one
ends up in a situation where flexibility and stability are at odds - ie
either you cannot make a certain change in your code, or you need to break
the public interface.

Decision: go with the closed model; reach out for potential plugin writers
> and collect requirements; do not guess, only add plugin functionality where
> it is actually requested by someone.
>

What I like about this is that you are not randomly adding a bunch of
hooks. Each hook decreases your flexibility a tiny bit and each hook is
additional maintenance cost. If you introduce them on an as-needed basis
and make sure your hook has a nice interface and well defined goal, then
you are well on your way to nicely implementing this.

This approach is however not disjoint with Inversion of Control and good
architecture, which you apparently agree with:

most of it is just good architecture like
> services or dependency injection which would make sense even if we did not
> want plugins
>

So I do hope you will also be pursuing that road.

It is not clear to me from your email that you are holding the difference
between libraries and applications into account, so I'll briefly explain.

Either a component is reusable or not, having a component with reusable and
non-reusable code in it, and trying to reuse that reusable code from it is
bad practice. Reusable code typically ends up in libraries. These libraries
have no state. Non-reusable components, such as applications and
extensions, typically do have their own state. If you want some code to be
truly reusable, going with the library approach, as the Symfony Components
are doing, is almost certainly the right approach. And indeed, this to is
merely generally good practice one should probably follow even when not
having the explicit goal to make something reusable.

The problem with having this supposedly reusable functionality in one
component with state that cannot be used as library is that it forces as
users to work together. It is like a global variable or a static class.
When modifying the thing (ie via a hook), one needs to be careful to not do
this in a way that breaks the other users. When at some point two different
users have constraints for the state that conflict, you have a problem. At
that point you are faced with the choice between painful refactoring or
creating an even bigger mess.

Cheers

--
Jeroen De Dauw - http://www.bn2vs.com
Software craftsmanship advocate
Evil software architect at Wikimedia Germany
~=[,,_,,]:3
_______________________________________________
Wikitech-l mailing list
Wikitech-l@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/wikitech-l

Reply via email to