The progress in the previous two days seems to be a little slow. Today, we have accelerated a little bit, so we will not detail each step.
= Extraction of Area Information
After gender and birthday, the last information block will only list the tests as follows.
(Copyright: 2012-2013 Yu qin'an)
= "Validity
This is a big problem. previously, I temporarily removed the verification from different places. the original author of the Code also talked about his views on verification. he is right. This completely verified method is basically the design idea of DDD. However, I want to say that my knowledge is temporarily removed to ensure the unit of testing. The verification function is driven by the verification test. The second consideration is that my verification is intended to be placed in the constructor. That is to say, if there is any wrong input, the first door cannot be entered.
Here, the test and implementation are both simple and look like a lot, just some listing, different error scenarios.
[Subject ("ID card, validity")] public class when_create_social_id_with_valid_format {private because of = () => subject = new socialid ("430103123456780020"); Private it should_create_social_properly = () => subject. getcardnumber (). shouldequal ("430103123456780020"); Private Static socialid subject;} [subject ("ID card, validity")] public class when_create_social_id_with_null_string {private because of = () => exception = catch. exception () => New socialid (null); Private it should_not_allow_to_create = () => exception. shouldnotbenull (); Private Static socialid subject; Private Static exception;} [subject ("ID card, validity")] public class when_create_social_id_with_empty_string {private because of = () => exception = catch. exception () => New socialid (string. empty); Private it should_not_allow_to_create = () => exception. shouldnotbenull (); Private Static socialid subject; Private Static exception;} [subject ("ID card, validity")] public class when_create_social_id_with2_length_string {private because of = () => exception = catch. exception () => New socialid ("12"); Private it should_not_allow_to_create = () => exception. shouldnotbenull (); Private Static socialid subject; Private Static exception;} [subject ("ID card, validity")] public class when_create_social_id_with_20_length_string {private because of = () => exception = catch. exception () => New socialid ("12345678901234567890"); Private it should_not_allow_to_create = () => exception. shouldnotbenull (); Private Static socialid subject; Private Static exception;} [subject ("ID card, validity")] public class when_create_social_id_alphet_length_string {private because of = () => exception = catch. exception () => New socialid ("a23456789012345678"); Private it should_not_allow_to_create = () => exception. shouldnotbenull (); Private Static socialid subject; Private Static exception ;}
Implementation
public SocialID(String cardNumber) { if (string.IsNullOrEmpty(cardNumber)) throw new ApplicationException("Card Number is empty"); if (cardNumber.Length != CARD_NUMBER_LENGTH) throw new ApplicationException("Card Number Length is wrong."); if (!SOCIAL_NUMBER_PATTERN.IsMatch(cardNumber)) throw new ApplicationException("Card Number has wrong charactor(s)."); }
= "Verification code"
The verification code is a special validity check, which is complicated. Here, I extract this part of logic code into a validator.
The test is extremely simple, and the implementation is almost intact.
Test:
public class when_verify_soical_number:Specification<Verifier> { Because of = () => { code = subject.verify("43010319791211453"); }; private It verify_code_should_match = () => code.ShouldEqual('4'); private static char code; }
Implementation
Namespace skight. eliteweb. domain. specs. properties {public class verifier {Private Static char [] verify_code = {'1', '0', 'x', '9', '8', '7 ', '6', '5', '4', '3', '2'};/*** 18-digit ID card, value of the verification code generated by each number */Private Static int [] verify_code_weight = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; Private Static int card_number_length = 18; Public char verify (string source) {/*** <li> Verification Code (18th digits ): <br/> * <ul> * <li> the weighted summation formula S = sum (ai * WI), I = 0... 16. First, sum the weights of the first 17 digits. * Ai: indicates the ID card number at position I. Digital value wi: indicates the Weighted Factor wi at position I: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4*2; </LI> * <li> computing mode y = Mod (S, 11) </LI> * <li> use the modulo to obtain the corresponding verification code Y: 0 1 2 3 4 5 6 7 8 9 10: 1 0x9 8 7 6 5 4 3 2 </LI> * </ul> ** @ Param cardNumber * @ return */INT sum = 0; for (INT I = 0; I <card_number_length-1; I ++) {char CH = source [I]; sum + = (INT) (CH-'0') * verify_code_weight [I];} return verify_code [Sum % 11] ;}}
At this time, the complete implementation of the ID card constructor becomes
public SocialID(String cardNumber) { if (string.IsNullOrEmpty(cardNumber)) throw new ApplicationException("Card Number is empty"); if (cardNumber.Length != CARD_NUMBER_LENGTH) throw new ApplicationException("Card Number Length is wrong."); if (!SOCIAL_NUMBER_PATTERN.IsMatch(cardNumber)) throw new ApplicationException("Card Number has wrong charactor(s)."); if (cardNumber[CARD_NUMBER_LENGTH - 1] != verifier.verify(cardNumber)) throw new ApplicationException("Card Number verified code is not match."); this.cardNumber = cardNumber; }
So far, the code is very clean. Yes, there are further improvements. For example, the extraction of the three elements (Region, birthday, and gender) should be moved to the constructor. The extraction function is changed to simple data reading. The type of social, instead of class, is struct, because it is a typical value object. In addition, I removed the 15-to-18-bit portion, which can be regarded as a utilit and can be done externally, not a core function.
Can you continue?
Finally, let's take a look at the test results:
Complete code:
Socialid. CS
Verifier. CS
(The Copyright in this article is 2012-2013 Yu Qinan | repost the article to indicate the author and source)