Rethinking AllianceCMS's Internal Structure

35 views
Skip to first unread message

Jesse Burns

unread,
Sep 30, 2013, 3:00:10 AM9/30/13
to allia...@googlegroups.com
The more I've been researching, learning and implementing architectural decisions, the more I believe I think we need to make some changes while acms is still pre-alpha.

If we don't just make the switch right now then some of the changes I'm considering would have to wait till a v2 to implement to prevent breaking bc (yes, that dreaded word lol).

The good news is that I've started from day one with the same goals in mind, and a lot of, maybe even most of, the existing code will only need some refactoring, rather than scratching everything and starting fresh. I just believe that the current implementation can be improved.

In this thread I'll only touch on the very surface of my thoughts and the reasons behind the changes I'd like to make. If you're interested in additional factors that are floating around in my head, feel free to ask :-)

First of all, let me mention some of the goals I started out with and still hold today:

  • To create a module system that speeds up and eases module development
  • To abstract the back end so module developers don't need to know implementation details, they can focus on using the available tools and the task at hand
  • To automate as much as possible, which will in turn lower the amount of code and time needed to create modules
  • To try not to tie module developers down by forcing limitations and reducing flexibility
  • To focus on separation of concerns, which will add to flexibility, abstraction, simplify debugging and ease the process of modifying existing code
  • To offer an easy way to tap into and modify existing functionality pragmatically, allowing easy implementation and removal of said modifications, while leaving original functionality intact in the case of rollbacks
  • To be able to use and swap out custom and 3rd party back end tools with ease, while keeping interfaces independent of back end implementation

I believe one of the things that sparked my interest in making some changes was how I build the $axis object in load_dispatcher. I add existing core objects and properties that are needed in module development to $axis and then send $axis to the AbstractModule constructor. The AbstractModule constructor then breaks it apart again, assigning the individual $axis objects and properties to $this->* (i.e. $this->sql), including itself, in case we need to instantiate a module controller inside a different module.

It just seems a little messy. I was looking into the risks and concerns regarding using the global keyword to give class methods access to existing objects, i.e. global $sql.

The last straw with this type of issue came while working on Issue #38. I thought that while I was adding to the installation functionality I might as well encapsulate all installation functionality using a separate Installation class, using the namespace Acms\Core\Components. But the moment I try to do that I no longer have access to any objects or data that is in $axis.

So now my options just get worse:

  • I can forget the new Installation class and keep all installation methods in the ModuleManager module so I can have access to $axis
  • I can instantiate the Installation class when needed and pass $axis to it's constructor, which would be almost, if not completely, identical to the AbstractModule constructor (duplication of code)
  • I can extend the Installation class with AbstractModule so it will have access to the same resources, but it's not a module, so that's not a serious alternative.
  • I can look into a better solution that is loosely coupled with existing and future code.

The situation seems to warrant a serious look at the last option so I decided to take a closer look at Dependency Injection.

I've been aware of Dependency Injection for some time, but didn't feel I had a real use case for it (or maybe I was just lazy) so I never took a serious look at it. Until now.

In my research regarding Dependency Injection I found a great article that discusses an architecture that fits beautifully with what I've been trying to accomplish regarding the goals I've stated, yet the article discusses a design that is much better than what I've been able to articulate and implement. This article explains the how and why of it all:

http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html

Go ahead and check out that article. It doesn't get bogged down in implementation details. It's a high level overview, and has a very clear and easy to understand message.

I have the knowledge needed to create the implementation, and I'm aware of some very nice tools that can help with the heavy lifting. Also, as I've mentioned earlier, I've designed a lot of the system with these goals in mind, so a good portion of the implementation will be some refactoring and restructuring. The module system will be very similar to what we have now, there will just be more abstraction and less to do to implement the task at hand.

There is one feature that I've wanted to implement from day one, but I decided to just get going and get some working code out the door, then come back to it and implement it along side with the current implementation, while deprecating the current implementation.

I'd like to completely abstract all data storage and retrieval. Instead of having a $sql object, which actually focuses on the implementation of data storage and retrieval (using a sql database and using sql queries), I'd rather have a $data, or $storage object, where you might describe the data for installation, like it's high level data type, but you use $data->setSomeData and $data->getSomeData to store and retrieve data. So no matter what data storage methods we use in the back end (a sql database, flat file, xml, cloud services) that interface will be consistent and rarely have to change (I believe that's what ORM is all about, but that's another subject I need to take a closer look at).

If you read the above article, the 'Interface Adapters' section talks about just that.

If you're interested in learning more about Dependency Injection there are many useful articles out there, especially in the Java landscape. I found a great series of articles regarding DI using PHP:

http://fabien.potencier.org/article/11/what-is-dependency-injection

If you're not familiar with DI, I suggest you at least check out the first two articles. They are a great intro into what DI is and what problem DI solves. They are not too lengthly, they are not too heavy, and the language and explanations are very clear.

Any feedback is welcome. If anyone would like to get involved all help would be appreciated, from feedback, to helping with the design, to code contributions.

I also think it would be a great learning experience that will help us grow as developers. I know that I've been at this for only 4-5 months and I've been learning and growing on a daily basis. Heck, I don't even know if I would have even realized that these issues should be a concern 6 months ago.

owen beresford

unread,
May 3, 2014, 8:36:14 AM5/3/14
to allia...@googlegroups.com
DI is very useful, DI makes testing soooooo much simpler. DI (with interfaces) allows stable change at much lower cost. DI is ideal for fixing the problem that you described at the start.

downsides to DI:
* best return if the entire code base is using DI.
* DI may lead to variable execution time, depending on what is bound to a class reference.
* DI can break your app, if the config file is incorrect.
* [add more items to list]
Reply all
Reply to author
Forward
0 new messages