[Architecture Pattern] entity Expansion

Source: Internet
Author: User

Motivation:

The life cycle of a software system must face the problem of system revision. During system revision, one of the most common problems is that users want to add data fields of System Objects (for example, adding photos to user data ). A common practice is to transform related functions from the UI to the dB (rewrite ?) To add the field to the system.

 

In this way, the author calls it "accumulation of modified program code 』. The so-called modified program code accumulation means to expand the system by modifying the verified and functioning program code and interfaces. Theoretically, after the program code is modified, the complete test must be re-executed. Interfaces have been modified, user manuals, education and training, and so on. It can be said that it is a whole body.

 

I prefer "incremental program code accumulation 』. The so-called incremental program code accumulation means that the original program code and included interfaces are not changed, but additional program code is appended to the system to expand the system. Because the program code and interface have not been modified, you can avoid the additional work of modifying the program code. But it is inevitable that such a system should be designed with great effort in the early stages of development.

 

This topic describes the entity expansion mode. The entity expansion mode mainly defines a set of Data Objects (entity) and repository generation, structure, and behavior patterns, which are used to extend the attribute data of objects. In this mode, you can add additional program code accumulation capabilities to the system.

 

* In the following articles, sections 01 and 02 are marked respectively, but they do not want to be written into a very long section. Instead, the project must be split into two sections.

 

Basic Platform:

Structure

 

Participants

Page Shell
-The page shell layer allows you to dynamically mount the system on the system page by setting data.

 

Sample program

Page shell has different options depending on the development platform. For example. NET platform, you can directly apply ASP.. NET page mechanism, and then create an index page. Modify the index page to dynamically mount the system page.

 

Basic Project 01:

Structure

 

Participants

Usermanagepage
-The user management page provides the functions of adding, modifying, deleting, and querying users.
-Use spring. NET and provider pattern to reflect and generate iuserrepositoryfactory.
-Use the generated iuserrepositoryfactory to generate iuserrepository.
-Use iuserrepository to add, modify, delete, and query users.

 

User
-Data Objects used for system operation.

 

Iuserrepositoryfactory
-Generate iuserrepository.
-Reflection generation relies on spring. NET and provider pattern.

 

Iuserrepository
-Interface for the user of the data object to access the system boundary.
-Added, modified, deleted, and queried functions.

 

Sample program

Namespace CLK. entityexpansion {public class usermanagepage {// Methods public void showuser () {// getdata iuserrepositoryfactory userrepositoryfactory = NULL; // use spring. NET and provider pattern for reflection generation. (Base project generate defauseruserrepositoryfactory, ex project generate expandeduserrepositoryfactory) iuserrepository userrepository = userrepositoryfactory. createrepository (); ienumerable <user> usercollection = userrepository. getall (); // show this. showuser (usercollection);} private void showuser (ienumerable <user> usercollection ){//.....}} public class user {// constructor public user () {This. userid = guid. empty; this. name = string. empty; this. description = string. empty;} protected user (User item) {# region require if (item = NULL) throw new argumentnullexception (); # endregion this. userid = item. userid; this. name = item. name; this. description = item. description;} // properties public guid userid {Get; set;} public string name {Get; set;} Public String description {Get; Set ;}} public interface iuserrepositoryfactory {// Methods iuserrepository createrepository ();} public interface iuserrepository {// Methods void add (User item); void modify (User item ); void remove (guid ID); User getbyid (guid ID); ienumerable <user> getall ();}}

 

Basic Project 02:

Structure

 

Participants

Defaultuserrepositoryfactory
-Iuserrepositoryfactory implementation
-Generate iuserrepository-sqluserrepository.

 

Sqluserrepository
-Interface for the entry and exit of the Data Object User at the system boundary, which is the implementation of iuserrepository.
-Iuserrepositoryfactory is used for generation.
-The user of the data object is in and out of the SQL database.

 

Sample program

Namespace CLK. entityexpansion {public class attributes: Attributes {// Methods public attributes createrepository () {// create role userrepository = new sqluserrepository (); // return userrepository;} public class sqluserrepository: iuserrepository {// Methods public void add (User item) {// SQL operation ...} public void modify (User item) {// SQL operation ...} public void remove (guid ID) {// SQL operation ...} public user getbyid (guid ID) {// SQL operation... return NULL;} public ienumerable <user> getall () {// SQL operation... return NULL ;}}}

 

Extended project 01:

Structure

 

Participants

Exusermanagepage
-The exuser Management page allows you to add, modify, delete, and query exusers.
-Use spring. NET and provider pattern to reflect and generate iexuserrepositoryfactory.
-Use the generated iexuserrepositoryfactory to generate iexuserrepository.
-Use iexuserrepository to add, modify, delete, and query exusers.

 

Exuser
-Data Objects used for system operation.
-Inherit the user and extend its property data.

 

Iuserrepositoryfactory
-Generate iexuserrepository.
-Reflection generation relies on spring. NET and provider pattern.

 

Iexuserrepository
-Interface for the Data Object exuser to access the system boundary.
-Added, modified, deleted, and queried functions.

 

Sample program

Namespace CLK. entityexpansion. expanded {public class exusermanagepage {// Methods public void showexuser () {// getdata iexuserrepositoryfactory userrepositoryfactory = NULL; // use spring. net, provider pattern to reflect generation. (Base project generate defaultexuserrepositoryfactory, ex project generate expandedexuserrepositoryfactory) iexuserrepository userrepository = userrepositoryfactory. createrepository (); ienumerable <exuser> usercollection = userrepository. getall (); // show this. showexuser (usercollection);} private void showexuser (ienumerable <exuser> exusercollection ){//.....}} public class exuser: User {// constructor public exuser (): Base () {This. photo = NULL;} public exuser (User item): Base (item) {# region require if (item = NULL) throw new argumentnullexception (); # endregion this. photo = NULL;} // properties public byte [] photo {Get; Set ;}} public interface iexuserrepositoryfactory {// Methods iexuserrepository createrepository ();} public interface iexuserrepository {// Methods void add (exuser item); void modify (exuser item); void remove (guid ID); exuser getbyid (guid ID ); ienumerable <exuser> getall ();}}

 

Extended project 02:

Structure

 

Participants

Defaultexuserrepositoryfactory
-Iexuserrepositoryfactory implementation.
-Generate iuserrepository-sqluserrepository.
-Generate iexusersectionrepository-sqlexusersectionrepository.
-Generate exuserrepository and pass in the generated iuserrepository and iexusersectionrepository.

 

Exuserrepository
-The interface for the Data Object exuser to access the system boundary, and the implementation of iexuserrepository.
-Ultexuserrepositoryfactory is used to generate the passed iuserrepository and iexusersectionrepository.
-Split the Data Object exuser into user and exusersection. The user's new modification and deletion actions are split into the following: the user object enters and exits the iuserrepository and exusersection objects in and out of the iexusersectionrepository.
-Combines the Data Object User and exusersection into exuser. The user's query action is split into the following: the user object enters and exits the iuserrepository and exusersection objects in and out of the iexusersectionrepository.

Exusersection
-The data objects used by the system to store the attribute data added by the exuser extension.

 

Iexusersectionrepository
-Interface for Data Object exusersection to access system boundaries.
-Added, modified, deleted, and queried functions.

 

Sqlexusersectionrepository
-The interface for the Data Object exusersection to access the system boundary, which is the implementation of iuserrepository.
-Adds the Data Object exusersection to the SQL database.

Expandeduserrepositoryfactory
-Iuserrepositoryfactory implementation.
-Generate iuserrepository-sqluserrepository.
-Generate iexusersectionrepository-sqlexusersectionrepository.
-Generate userrepositorydecorator to input the generated iuserrepository and iexusersectionrepository.

 

Userrepositorydecorator
-Interface for the entry and exit of the Data Object User at the system boundary, which is the implementation of iuserrepository.
-Iuserrepositoryfactory is used for generation.
-Generate with expandeduserrepositoryfactory and accept the passed iuserrepository and iexusersectionrepository.
-Splits the user's new modification, deletion, and query actions on the Data Object User into iuserrepository.
-Split the Data Object User into userid. The user's deletion is split into exusersection objects removed from iexusersectionrepository.

 

Sample program

Namespace CLK. entityexpansion. expanded {public class exusersection {// properties public guid userid {Get; set;} public byte [] photo {Get; Set ;}} public interface iexusersectionrepository {// Methods void add (exusersection item); void modify (exusersection item); void remove (guid ID); exusersection getbyid (guid ID);} public class sqlexusersectionrepository: iexusersectionrepository {public void add (exusersection item) {// SQL operation ...} public void modify (exusersection item) {// SQL operation ...} public void remove (guid ID) {// SQL operation ...} public exusersection getbyid (guid ID) {// SQL operation... return NULL ;}}}

 

namespace CLK.EntityExpansion.Expanded{    public class DefaultExUserRepositoryFactory : IExUserRepositoryFactory    {        // Methods        public IExUserRepository CreateRepository()        {            // Create            IUserRepository userRepository = new SqlUserRepository();            IExUserSectionRepository exUserSectionRepository = new SqlExUserSectionRepository();            // Return            return new ExUserRepository(userRepository, exUserSectionRepository);        }    }    public class ExUserRepository : IExUserRepository    {        // Fields        private readonly IUserRepository _userRepository = null;        private readonly IExUserSectionRepository _exUserSectionRepository = null;                // Constructor        public ExUserRepository(IUserRepository userRepository, IExUserSectionRepository exUserSectionRepository)        {            #region Require            if (userRepository == null) throw new ArgumentNullException();            if (exUserSectionRepository == null) throw new ArgumentNullException();            #endregion            _userRepository = userRepository;            _exUserSectionRepository = exUserSectionRepository;        }        // Methods        public void Add(ExUser item)        {            #region Require            if (item == null) throw new ArgumentNullException();            #endregion            // User            _userRepository.Add(item);            // ExUserSection            ExUserSection exUserSection = new ExUserSection();            exUserSection.UserID = item.UserID;            exUserSection.Photo = item.Photo;            _exUserSectionRepository.Add(exUserSection);        }        public void Modify(ExUser item)        {            #region Require            if (item == null) throw new ArgumentNullException();            #endregion            // User            _userRepository.Modify(item);            // ExUserSection            ExUserSection exUserSection = new ExUserSection();            exUserSection.UserID = item.UserID;            exUserSection.Photo = item.Photo;            _exUserSectionRepository.Modify(exUserSection);        }        public void Remove(Guid id)        {            #region Require            if (id == Guid.Empty) throw new ArgumentNullException();            #endregion            // User                        _userRepository.Remove(id);            // ExUserSection            _exUserSectionRepository.Remove(id);        }        public ExUser GetByID(Guid id)        {            #region Require            if (id == Guid.Empty) throw new ArgumentNullException();            #endregion            // User                User user = _userRepository.GetByID(id);            if (user == null) return null;            // ExUserSection            ExUserSection exUserSection = _exUserSectionRepository.GetByID(id);            if (exUserSection == null) return new ExUser(user);            // ExUser            ExUser exUser = new ExUser(user);            exUser.Photo = exUserSection.Photo;            return exUser;        }        public IEnumerable<ExUser> GetAll()        {            // Result            List<ExUser> exUserList = new List<ExUser>();            // User                foreach (User user in _userRepository.GetAll())            {                // ExUserSection                ExUserSection exUserSection = _exUserSectionRepository.GetByID(user.UserID);                if (exUserSection == null)                {                    exUserList.Add(new ExUser(user));                    continue;                }                // ExUser                ExUser exUser = new ExUser(user);                exUser.Photo = exUserSection.Photo;                exUserList.Add(exUser);            }                                  // Return            return exUserList;        }    }    }

 

namespace CLK.EntityExpansion.Expanded{    public class ExpandedUserRepositoryFactory : IUserRepositoryFactory    {        // Methods        public IUserRepository CreateRepository()        {            // Create            IUserRepository userRepository = new SqlUserRepository();            IExUserSectionRepository exUserSectionRepository = new SqlExUserSectionRepository();            // Return            return new UserRepositoryDecorator(userRepository, exUserSectionRepository);        }    }    public class UserRepositoryDecorator : IUserRepository    {        // Fields        private readonly IUserRepository _userRepository = null;        private readonly IExUserSectionRepository _exUserSectionRepository = null;        // Constructor        public UserRepositoryDecorator(IUserRepository userRepository, IExUserSectionRepository exUserSectionRepository)        {            #region Require            if (userRepository == null) throw new ArgumentNullException();            if (exUserSectionRepository == null) throw new ArgumentNullException();            #endregion            _userRepository = userRepository;            _exUserSectionRepository = exUserSectionRepository;        }        // Methods        public void Add(User item)        {            #region Require            if (item == null) throw new ArgumentNullException();            #endregion            // User            _userRepository.Add(item);        }        public void Modify(User item)        {            #region Require            if (item == null) throw new ArgumentNullException();            #endregion            // User            _userRepository.Modify(item);        }        public void Remove(Guid id)        {            #region Require            if (id == Guid.Empty) throw new ArgumentNullException();            #endregion            // User                        _userRepository.Remove(id);            // ExUserSection            _exUserSectionRepository.Remove(id);        }        public User GetByID(Guid id)        {            #region Require            if (id == Guid.Empty) throw new ArgumentNullException();            #endregion            // User                User user = _userRepository.GetByID(id);            // Return            return user;        }        public IEnumerable<User> GetAll()        {            // Result            IEnumerable<User> userList = null;            // User                userList = _userRepository.GetAll();            // Return            return userList;        }    }}

 

Conclusion:

The example in this article is as follows: when both the basic project and the extension project are established. Create a user object on the Management page of the original basic project. On the exuser Management page of the extension project, you can also query the new exuser (the content is user data, and the property data of the exuser extension is the default value ). When an extended project deletes an exuser, the user in the basic project is also deleted.

 

The entity expansion mode described in this article only expands the attribute data of the object, but it can be viewed as a responsibility to process the entry and exit system boundaries of a strongly-type extended object. Based on this model, we can theoretically design an application system architecture that can be infinitely extended.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.