开发者

Best practice for Save / Publish when creating web content

I have a web site where authenticated users can create new Projects. At several points in the process the user can 开发者_Python百科choose to save the project or to publish the project, So there is some times 2 records for the same project, one draft and one public

In the past I have done this for a blog post site, where posts have a draft entity, that is created or deleted depending on what happening in the save / publish flow,

Was wondering what other approaches might work better. Is there a design pattern for this sort of thing?

Re the Projects, they are quite big, split up into 5 pages for input, each page can be saved or published.


A particular design for draft vs. publish or staging vs. production is basically abstraction of datasource layer. Basically the data layer is separated into two implementation having the same interface.

Here is a very simple Interface of what the two implementations (draft vs. published) of datasource could use


public interface CMSDatasource {
    /***
     * Save the data
     * @param data the data needed to be saved
     * @return The key for the data
     */
    public String saveData(String data);

    /***
     * Delete the data given a particular key
     * @param key
     */
    public void deleteData(String key);

    /***
     * Get the data given a particular key
     * @param key
     * @return
     */
    public String getData(String key);

    /***
     * Get all the data that has been put into the system
     * @return Return a Map of timestamp and the String being put 
     * into the system
     */
    public Map getHistory(); 
}

Now both datasources for draft/published would need to be able to do those things anyway, the only thing that is differentiating between them is where they are going to be stored.

Note also, that these two operates on the same data type (in this case String), so they would have to be normalized in the CMS logic layer.

Using this design, we don't have to rewrite the Logic for CMS Module nor the Data Model. All we have to do is swap the Datasource between draft and published. To get the appropriate Datasource, we could implement the Factory pattern.

Abstracting the Datasource via interface would also enable the implementation to choose freely the underlying datasource implementation. For example, you could choose relational database such as MySQL for storing the draft but you might decide to use NoSQL such as CouchDB to store the published data. By making an interface over the Datasource, it is easy to swap the datasource from one implementation to another.

For further illustration, let's assume a very simple article module in CMS that will contains the article that the user can input. The class will roughly look like:


public class ArticleModule {
    String article;
    int publishingMode;

    /***
     * Save the data based on user's action 
     */
    public void saveData() {
        // get the datasource depending on the publishing mode set for this 
        // module (DRAFT vs. PUBLISHED)
        CMSDatasource datasource = CMSDatasourceFactory.getDatasource(publishingMode);

        // save the article, note that nothing is required to change in this class
        // since the datasource is completely abstracted by the interface
        datasource.saveData(article);
    }

    // below is the getter/setter for the article and publishing mode
    // ......  
}

In order to create article, the users of the CMS will interact with this class by setting the article that they put through the UI. Once the user is ready to save, the UI will eventually call saveData, note that in this implementation we don't need change any of the Article code regardless whether it is in draft or publishing mode since the Factory has abstracted the datasource implementation.

And finally, here is the skeleton for the Factory


public class CMSDatasourceFactory {
    public static final int DRAFT_MODE = 1;
    public static final int PUBLISHED_MODE = 2;

    /***
     * Get a specific implementation of the datasource based on publishing mode
     * @param publishingMode Either draft or published mode, 
     * use the constant DRAFT_MODE or PUBLISHED_MODE
     * @return A specific implementation for the datasource wrapped in CMSDatasource interface
     */
    public static CMSDatasource getDatasource(int publishingMode) {
        switch(publishingMode) {
            case CMSDatasourceFactory.DRAFT_MODE :
                return new CMSDraftDatasource();
            case CMSDatasourceFactory.PUBLISHED_MODE:
                return new CMSPublishedDatasource();
        }

        return null;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜