A huge application, new modules are added every few months, 5-10 programmers.
Some modules access the same tables, some modules use (currently) the same queries.
My question, would it be smarter to make each module a 100% stand alone application, with it's own DAL classes and BL classes (library classes, ZF, are shared, ofcourse), or should all the modules use the same resources (classes)?
The only thing I am 100% sure needs to be common is the user profiles/ACL/auth data, which sits on an OpenLDAP server.
views:
88answers:
5Dont think it would be smarter, would probably end up a maintenance nightmare if it is a large system.
Reuse is important and duplication is not.
I would say do share. I have seen enough methods with comments // if you change this function you must also change ... The rules were not adhered to strictly at all - it is a maintenance nightmare. Why would not you share? Do you expect the design to remain solid and untouched?
You should be careful about sharing code in large volatile environments. In many cases, the rapid pace of evolution and change can introduce incompatibilities can cause problems that are only discovered in production.
The most significant impact from shared code is testing. Particularly when dependencies are impacted by a potentially breaking change - it becomes exponentially expensive to test. This expense, often results in little or no testing being performed when changes are made. And hence, defects creep into production environments.
The more mature a body of code is, the more reasonable it is to make it shared across modules or systems. Mature code tends to be stable and change little. It also should have the most robust library of unit and integration tests supporting it. Mature code usually has been exercised by many users, and you have a higher degree of confidence that the bugs have been detected and fixed.
Immature code, by contrast, tends to change often - and these changes tend to be disruptive. Often in it's the public interface that changes - which results in either a significant amount of refactoring work for modules that depend on it, or a branching of the codebase, which defeats the purpose of having shared code.
If you do choose to share certain portions of your codebase, you should make sure that you have a suite of unit and integration tests for each module/system that verify that existing uses re not affected by changes to the shared code. You should also consider making shared code very obvious, either through naming conventions or version control practices.
Based on my experience, here are some cases where shared code can be reasonably safe (assuming you have good version control and change management practices):
- Libraries that have a single and clear responsibility, are very simple, and extremely slow to change.
- Code that performs computations that are well-define and would only evolve through addition, rather than interface change.
- Code that has a narrow public interface and extensive unit and integration tests supporting it.
I think you should partition modules so they DON'T share tables or queries.
A service-oriented architecture, whether you decide to implement it in terms of distributed web components or not, would isolate business functions and the data they own. If you do it properly, there are no shared tables or queries, and a single interface to interact with that data. I'd take the time to redesign to that standard before I'd recommend sharing.
Queries should never be duplicated. If you have identical database queries inline in two locations, that code needs to be refactored, to AT LEAST go through the same client-side code. Alternatively, best practices would dictate that you inventory and control your data interface so that expectations of the data services provided by your back end are clear. If the behavior of a query starts identically and then has to vary between some invocations, you will then at least have visibility into the callers to see which ones need to change. If it starts identically and needs to change identically in many places, you will have comfort that the system does not have duplication.
If you are using a relational database paradigm, I would always and only use SPs. The application will never have SELECT access, so that you have control of the perimeter of your database.
If you are using an OO approach to the application design, this should help dealing with separation of concerns and understanding and limiting the dependencies and controlling the visibility of the various subsystems' interfaces.
I would have the applications share common libraries and that the libraries would expose various subsystems. In the .NET world, this would be many separate assemblies which represent the different logical portions of the subsystems, not all of which might be needed by every webservice, console application, forms application, web application or service/daemon which comprise the system.
Although LBushkin is right about the difficulty of sharing code which is rapidly changing, since many consumers may be expecting different behaviors over time - as that code matures, the reliability and comfort gained by using code which is in use and has been in use in many places is exponentially greater. i.e. code which you know is running everywhere is always more reliable - this particularly include generic classes in .NET.