التحقق من صحة البيانات: نهج مختلف

التحقق من البيانات في تطبيق المدخلة من قبل المستخدم أو التي تم الحصول عليها بطريقة أخرى بالمعنى الكلاسيكي يعني استخدام فقط اثنين من التعبيرات في التعليمات البرمجية: TRUE و FALSE. في نموذج آخر ، يتم استخدام الاستثناءات التي من الواضح أنها غير مخصصة لهذا الغرض. هل هناك خيار أفضل؟

يتم التحقق من صحة ما يسمى بجهات التحقق (التي هي جزء فقط من عملية التحقق من صحة البيانات بالكامل). تقدم المقالة التحقق من صحة الخادم لبيانات المستخدم إصدارًا مثيرًا للاهتمام من تطبيق المدقق ، ولكن هناك العديد من الفروق الدقيقة في شكل تعريب الرسالة وتنسيق الخطأ نفسه .

ضع في اعتبارك تنسيق الخطأ أولاً.

الطريقة المقترحة هي طريقة التحقق من صحة البيانات التي تتحقق من البيانات لإرجاع مجموعة (صفيف ، قائمة ، إلخ) من السلاسل بدلاً من القيم المنطقية أو رمي الاستثناءات. سيكون مثل هذا الشكل أكثر مرونة وغنية بالمعلومات.

سأعطي مثالا في جافا:

import java.util.ArrayList;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public interface ValidateUser {
	String OK = "OK:";
	String FAIL= "FAIL:";
	Collection<String> apply(String username, String password, String email);
	default Collection<String> passwordValidate(String password){
		var result = new ArrayList<String>(1);
		int size = password.trim().length();
		if(size < 3 || size > 20) result.add("Password error:too short value or too long name. Password must be greater or 3 characters and smaller then 20 simbols.");
		return result;
	}
	default Collection<String> usernameValidate(String name){
		var result = new ArrayList<String>(1);
		int size = name.trim().length();
		if(size < 3 || size > 30) result.add("Username error:too short or too long name. Name must be greater or 3 characters and smaller then 30 simbols.");
		return result;
	}
	default Collection<String> emailValidate(String email){
		var result = new ArrayList<String>(1);
		String regex = "^[\\w!#$%&'*+/=?`{|}~^-]+(?:\\.[\\w!#$%&'*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(email);
		if (!matcher.find()) result.add("Email error:" + email + " is not valid");
		return result;
	}
	class Default implements ValidateUser{

		@Override
		public Collection<String> apply(String username, String password,
				String email) {
			var errors = passwordValidate(password.trim());
			errors.addAll(usernameValidate(username.trim()));
			errors.addAll(emailValidate(email.trim()));
			return errors;
		}
		
	}
}

كما ترى هنا ، ترجع كل الطرق مجموعة من السلاسل.

مثال على اختبار الوحدة:

        @Test
	void validateUserTest() {
		
		var validate = new ValidateUser2.Default();
		var result = validate.apply("aaa", "qwe", "aaa@mail.ru");
		assertTrue(result.isEmpty());
		result = validate.apply("aaa", "qwe", "");
		assertFalse(result.isEmpty());
		assertEquals(1, result.size());
		
		result = validate.apply("aa", "qwe", "aaa@mail.ru");
		assertFalse(result.isEmpty());
		assertEquals(1, result.size());
		
		result = validate.apply("aaa", "qwe", "@mail.qweqwe");
		assertFalse(result.isEmpty());
		assertEquals(1, result.size());
		
		result = validate.apply("aa", "qw", "");
		assertFalse(result.isEmpty());
		assertEquals(3, result.size());
	}

الآن فكر في توطين رسائل الخطأ.

المثال مرة أخرى في Java:

public interface LocalizedValidation {
	String OK = "OK:";
	String FAIL= "FAIL:";
	Collection<String> apply(String username, String password, String email, Locale locale);
	default Collection<String> passwordValidate(String password, ResourceBundle bundle){
		var result = new ArrayList<String>(1);
		int size = password.trim().length();
		if(size < 3 || size > 20) result.add(bundle.getString("password"));
		return result;
	}
	default Collection<String> usernameValidate(String name, ResourceBundle bundle){
		var result = new ArrayList<String>(1);
		int size = name.trim().length();
		if(size < 3 || size > 30) result.add(bundle.getString("username"));
		return result;
	}
	default Collection<String> emailValidate(String email, ResourceBundle bundle){
		var result = new ArrayList<String>(1);
		String regex = "^[\\w!#$%&'*+/=?`{|}~^-]+(?:\\.[\\w!#$%&'*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(email);
		if (!matcher.find()) result.add(bundle.getString("username")+email);
		return result;
	}
	class Default implements LocalizedValidation{

		@Override
		public Collection<String> apply(String username, String password,
				String email, Locale locale) {
			ResourceBundle bundle = ResourceBundle.getBundle("errors", locale);
			var errors = passwordValidate(password.trim(), bundle);
			errors.addAll(usernameValidate(username.trim(), bundle));
			errors.addAll(emailValidate(email.trim(), bundle));
			return errors;
		}
	}
}


	@Test
	void localizedUserTest() {
		var validate = new LocalizedValidation.Default();
		var result = validate.apply("aaa", "qwe", "aaa@mail.ru", Locale.ENGLISH);
		assertTrue(result.isEmpty());
		result = validate.apply("aaa", "qwe", "", Locale.ENGLISH);
		assertFalse(result.isEmpty());
		assertEquals(1, result.size());
		System.out.println(result.iterator().next());
		
		result = validate.apply("aaa", "qwe", "", new Locale("ru"));
		assertFalse(result.isEmpty());
		assertEquals(1, result.size());
		System.out.println(result.iterator().next());
	}

توجد ملفات الترجمة في src / main / resources.

خصائص_r_r..erties:

mail=Email :   Email:
username=  :     .
password=   :   .

أخطاء: الخصائص:

mail=Email error: is not valid:
username=Username error:too short or too long name. Name must be greater or 3 characters and smaller then 30 simbols.
password=Password error:too short value or too long name. Password must be greater or 3 characters and smaller then 20 simbols.

آمل أن يجد المبرمجون الآخرون الذين يكتبون بلغاتهم هذا النهج عمليًا وملائمًا وأن يكونوا قادرين على تطبيقه في المنزل.

PS

البديل من أسلوب المصادقة المستخدم الذي يعود لل تنفيذ <K، V> واجهة java.util.Map.Entry ويمكن أن تحتوي على حد سواء كائن المستخدم و البيانات الخطأ كسلسلة (هذا النهج يمكن أن تستخدم أيضا لتجنب العودة خالية من الطريقة عندما يتوقع كائن المستخدم):

@Override
public Entry<String, User> auth(String username, String password, String email) {
	var errors = passwordValidation.apply(password.trim());
	errors.addAll(userNameValidation.apply(username.trim()));
	errors.addAll(emailValidation.apply(email.trim()));
	if(!errors.isEmpty()) {
		return REntry.ofI(null, errors.stream().collect(Collectors.joining(";")));
	}else {
		try {
			var passwordEncrypted = new Encrypt().apply(password.trim());
			var user = new User.Default(0L, username.trim(), email.trim(), passwordEncrypted, "").create(dataSource);
			return REntry.ofI(user, "user is null!");
		} catch (RuntimeException e) {
			return REntry.ofI(null, e.getMessage());
		}
	}
}

هناك ، بالطبع ، مقالة رائعة على المحور حول التحقق من الصحة في Java ، ولكن النهج المقترح هناك يمكن استخدامه بعيدًا في جميع الحالات ويستند إلى التعليقات التوضيحية والاستثناءات.

في نهاية المقال زوجان من الروابط المفيدة حول الاختبار:

  1. مضادات اختبار البرمجيات
  2. مفاهيم اختبار السيارات

Source: https://habr.com/ru/post/undefined/


All Articles