Reflection on design and Reconstruction

Source: Internet
Author: User

This article is my reflection and experience on the evolution and reconstruction of a small functional point in a project.
Background:
This project is an e-commerce website with the function of sending notifications to customers after the order status changes to a certain status, the SMS and gateway functions have been encapsulated into a set-up method. You can call them directly.
In order to clearly describe the functions related to this topicProgramDescriptionCode.
Reconstruction process:
At first, like in most projects, we worked hard to complete related functions within the specified time. The main code for this function is as follows:

V1

         Static   Void  Sendsms_v1 (datatable DT ){  If ( Null = DT) Return  ;  For (Int I = 0 ; I <DT. Rows. Count; I ++ ){  VaR Row = DT. Rows [I]; orderstateenum state = (Orderstateenum )(( Int ) Row [ "  Orderstate  "  ]);  String Template = String  . Empty; Switch  (State ){  Case  Orderstateenum. Unconfirmed: Template = "  Dear {0! Your order has been successfully placed. Please pay as soon as possible for delivery.  "  ;  Break  ;  Case  Orderstateenum. Confirmed: Template = " Dear {0! Your order (Order No.: {1}) has been confirmed. Please wait.  "  ;  Break  ;  Case  Orderstateenum. Cancel: Template = "  Dear {0! Your order (Order No.: {1}) has been canceled. Please check it online for the specific reason.  "  ;  Break  ;  Case Orderstateenum. Finish: Template = "  Dear {0! Your order (Order No.: {1}) has been completed. Thank you for your support and cooperation. Welcome to visit again.  "  ;  Break  ;  Default  :  Break  ;}  String Content = String . Format (template, row ["  Customername  " ], Row [ "  Orderid  "  ]); Sendsms. Send (row [  "  Phone  "  ]. Tostring (), content );}} 

This code works well at the initial stage of project launch.

After a period of operation, my colleagues in the Operation Department proposed to add the product name in some places. During this change, I found that the code was not separated from the data, in addition, if you want to add an SMS prompt or cancel a text message prompt after adding an order status, this change process is a bit troublesome. Therefore, I initially thought of putting the text message content in the configuration file, and reading the configuration file corresponding to the order status during the call and then formatting it. If the read content is null or the file does not exist, skip this step. The main code is as follows:

V2 content and data separation

         # Region V2 content and data separation Static   Void  Sendsms_v2 (datatable DT ){  If ( Null = DT) Return  ;  For ( Int I = 0 ; I <DT. Rows. Count; I ++ ){ VaR Row = DT. Rows [I];  String Path = path. Combine (appdomain. currentdomain. basedirectory, "  Smstemplates  "  ,  "  V2  " , Row [ "  Orderstate  " ]. Tostring () + " . Txt  "  );  VaR Template = Filehelper. Read (PATH );  If (! String  . Isnullorempty (Template )){  String Content = String . Format (template, row [ "  Customername  " ], Row [ " Orderid  " ], Row [ "  Productname  "  ]); Sendsms. Send (row [  "  Phone  "  ]. Tostring (), content );}}}  # Endregion 
Template

 
Dear {0}, Hello! Your order (Order No :{1}) Confirmed. Please wait.

As the operation continues, the Operation Department constantly proposes to display some fields in some places, String. the number of parameters after the format is constantly increased. After each change, we need to re-test the entire process. This is a headache! My idea is to provide a data tag list on the development side, and provide an operation interface on the background to allow the operation colleagues to modify the SMS management template themselves, so they don't need to contact us every time? With the above idea, use a custom formatter:

Custom parameter formatting

     Public   Class  Indexernamedformatter: iformatprovider, icustomformatter {  Public  Indexernamedformatter (){}  Public   Object  Getformat (type formattype ){  If (Formattype =Typeof  (Icustomformatter ))  Return   This  ;  Throw   New Typeaccessexception ( "  The type does not match.  "  );}  Public   String Format ( String Format, Object Arg, iformatprovider formatprovider ){  If ( Null = Arg)  Throw   New Argumentnullexception ( "  The ARG parameter cannot be null.  "  );  Int Indexer = 0  ;  Bool Isindexed =Int . Tryparse (format, Out  Indexer );  //  If it is datarow              If (ARG Is  System. Data. datarow ){  Return  Getstringfromdatarow (format, ARG, indexer, isindexed );}  //  Such as datareader              If (ARG Is System. Data. idatarecord) {getstringfromidatarecord (format, ARG, indexer, isindexed );}  Return   String  . Empty ;;}  Private   Static   Void Getstringfromidatarecord ( String Format, Object Arg, Int Indexer, Bool  Isindexed ){ VaR Dr = (System. Data. idatarecord) ARG;  String . Format ( "  {0}  " , Isindexed? Dr [indexer]: Dr [format]);}  String Getstringfromdatarow ( String Format, Object Arg, Int Indexer, Bool  Isindexed ){ VaR Row = (System. Data. datarow) ARG;  Return   String . Format ( "  {0}  " , Isindexed? Row [indexer]: Row [format]);} 
Use custom tags in V3

 # Region Use custom tags in V3 Static   Void  Sendsms_v3 (datatable DT ){ If ( Null = DT) Return  ; Indexernamedformatter formatter = New  Indexernamedformatter ();  For ( Int I = 0 ; I <DT. Rows. Count; I ++ ){  VaR Row = DT. Rows [I];  String Path = path. Combine (appdomain. currentdomain. basedirectory, "  Smstemplates  "  ,  "  V3  " , Row [ "  Orderstate  " ]. Tostring () + "  . Txt  "  );  VaR Template =Filehelper. Read (PATH );  If (! String  . Isnullorempty (Template )){  String Content = String  . Format (formatter, template, row); sendsms. Send (row [  "  Phone  "  ]. Tostring (), content );}}}  # Endregion 
Template

 
Dear {0: Customername}, hello! Your order (Order No :{0: Orderid}, product: Product {0: Productname}) confirmed. Please wait.

After retrieving the data fields and writing them into a tag list document for the Operation staff, the modification requirements for this section will be quiet.

The above is just a small design technique, which also makes me understand how important it is to accurately grasp and mine requirements! Customers often say this today, but tomorrow, many people complain: You are in trouble! However, when the demand constantly arises, do we also reflect on the changes? Are we failing to accurately grasp the functions they want to design some problems? Of course, I do not advocate design at the very beginning. Excessive design requires a lot of time costs and may increase the complexity of implementation.

One question:
After reading the documentation, I have always felt that the implementation of Arg is system. Data. datarow is awkward. Why is the indexer not defined as an interface? Please tell us if anyone has a better implementation method. Thank you!

Thank you for reading this article! The Code involved in this article can be downloaded from here.

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.