The specific design for a project against publishing or staging against production is basically an abstraction of the data source layer. Basically, the data layer is divided into two implementations that have the same interface.
Here is a very simple interface that two implementations (project versus publication) of a data source can use
public interface CMSDatasource { public String saveData(String data); public void deleteData(String key); public String getData(String key); public Map getHistory(); }
Now both data sources for the project / publication will have to be able to do all this anyway, the only thing that sets them apart is where they will be stored.
Note also that these two modes work with the same data type (in this case, String), so they must be normalized at the logical level of the CMS.
Using this construct, we do not need to rewrite the logic for the CMS module or data model. All we need to do is exchange data sources between the project and the publication. To get the appropriate data source, we could implement the Factory pattern.
Abstract data sources through the interface will also allow the implementation to freely choose the basic implementation of the data source. For example, you can select a relational database such as MySQL to store a draft, but you can use NoSQL, such as CouchDB, to store published data. By making an interface over a data source, it is easy to replace the original data source from one implementation to another.
For further illustration, suppose the CMS has a very simple text module that will contain an article that the user can enter. The class will look something like this:
public class ArticleModule { String article; int publishingMode; public void saveData() {
To create an article, CMS users will interact with this class by installing the article that they contribute through the user interface. After the user is ready to save, the user interface will eventually call saveData , note that in this implementation we do not need to change any article code, regardless of whether it is in draft or publication mode, since Factory implementation of the data source.
And finally, here is the skeleton for Factory
public class CMSDatasourceFactory { public static final int DRAFT_MODE = 1; public static final int PUBLISHED_MODE = 2; public static CMSDatasource getDatasource(int publishingMode) { switch(publishingMode) { case CMSDatasourceFactory.DRAFT_MODE : return new CMSDraftDatasource(); case CMSDatasourceFactory.PUBLISHED_MODE: return new CMSPublishedDatasource(); } return null; } }