2020, el diseño de la última carretera de reconstrucción modelo-APP

Muchas aplicaciones utilizan el patrón de diseño MVC para separar la "interacción del usuario" de "datos y lógica", y una de las funciones importantes del modelo es la persistencia . El modelo diseñado a continuación puede no ser un ejemplo perfecto y extensible, pero en la aplicación que necesito refactorizar, dicho diseño puede satisfacer mis necesidades.

Sobre el modelo

La capa de modelo contiene los datos y la lógica de la aplicación. Las clases de la capa de modelo deben preocuparse por el rendimiento, el almacenamiento y el funcionamiento de los datos. La capa de modelo es una parte relativamente independiente de todo el ecosistema de la aplicación, porque no se comunica directamente con la capa del controlador o la capa de vista, pero se comunica indirectamente cuando otras capas necesitan solicitar su información.

¿Cuál es el uso de Model?

Para escribir un modelo, primero debe aclarar el papel del modelo.

  • ** Acceso a atributos: ** Almacena algunas características y datos en el archivo como atributos
  • ** Mutabilidad: ** El atributo puede ser readwrite, por lo que se puede cambiar y guardar localmente
  • ** KVO: ** Puede observar el valor de un atributo y recibir una notificación cuando cambie, y usarlo para controlar la interfaz de usuario u otros lugares
  • ** Procesamiento de datos: ** Procesamiento de datos de adquisición de red y datos de almacenamiento local de acuerdo con la lógica empresarial

Cómo definir la clase Modelo

Podemos crear una serie de clases de modelo, que pueden heredarse unas de otras, y cada clase de modelo corresponde a la entidad en la aplicación actual . Por ejemplo, en la aplicación que actualmente necesito refactorizar, los datos del usuario corresponden a la UserInformationModelinformación de la clase StudentClassModel.

Por otro lado, hay muchos problemas que necesitan ser resueltos durante la realización de la clase Modelo, por lo que explicaré en combinación con algunas situaciones de la aplicación que estoy refactorizando actualmente.

Procesamiento del formato de almacenamiento de información

Los datos se pueden almacenar en una variedad de formatos diferentes. En mi aplicación reconstruida, los datos y otra información se almacenan usando estructuras de datos comunes, como usar datos o un diccionario para almacenar información del Modelo. No hubo gran problema al construir el Modelo al principio, pero cuando la demanda siguió aumentando y la información de una clase de Modelo empezó a crecer, el problema empezó a surgir. Por ejemplo, a continuación quiero mostrar el nombre del usuario, la edad, la clase, el profesor de la clase, el grado y otros datos.

// never do this !!!
- (void)printInformation
{
	NSLog(@"name: %@", [user objectForKey:@"name"]);
	NSLog(@"age: %@"m [user objectForKey:@"age"]);
	NSLog(@"class: %@"m [user objectForKey:@"clazz"]);
	NSLog(@"teacher: %@"m [user objectForKey:@"teacher"]);
	NSLog(@"grade: %@"m [user objectForKey:@"grade"]);
}

Parece que no hay problema para recuperar los datos de esta manera, pero cuando los datos aumentan, el código será muy desordenado, ¡y no! ¡bonito! ¡Ver! Al mismo tiempo, el principal problema es que la clave se escribirá incorrectamente en el proceso de obtención de datos del diccionario, lo que provocará un error en la obtención de datos.

Por lo tanto, en el proceso de diseño del modelo, intente diseñar el modelo como una clase en lugar de una estructura . En la clase, puede usar propiedades (Propiedad) para acceder a la información. Puede proporcionar a los desarrolladores una revisión ortográfica básica. Para evitar la falla en la adquisición de datos causada por la clave incorrecta, es conveniente que otros desarrolladores vean el tipo de datos almacenados en el Modelo, y también es conveniente para futuras expansiones y mantenimiento.

// YES! do this!
- (void)printInformation
{
	NSLog(@"name: %@", user.name);
	NSLog(@"age: %@", user.age);
	NSLog(@"class: %@", user.clazz);
	NSLog(@"teacher: %@", user.teacher);
	NSLog(@"grade: %@", user.grade);
}

Procesamiento de datos en red

Dado que la mayoría de las funciones de mi aplicación refactorizada están basadas en la red, el procesamiento de los datos de la red en la capa Modelo será el foco. Porque los datos de la red se adquieren de forma asincrónica y el proceso de adquisición es fácil de fallar . Por tanto, es más difícil obtener datos de red que datos locales. Por otro lado, los marcos de solicitud de red de muchas aplicaciones proporcionan una función de almacenamiento en caché , que puede obtener datos de la caché más rápido en la siguiente solicitud sin la necesidad de realizar una solicitud de red nuevamente. Esto implica la adquisición de datos locales y otros problemas, por lo que El procesamiento de datos de la red es particularmente engorroso.

En un entorno de red sincronizado, podemos poner el manejo de errores en otro lugar, simplemente almacenar en caché e incluso actualizar, eliminar y agregar nuevos datos de red como datos locales. Pero, lamentablemente, la red es asincrónica, por lo que debemos ocuparnos de este importante problema.

En primer lugar, el almacenamiento en caché y el manejo de fallas mencionados anteriormente deben entregarse al marco de solicitud de red para su procesamiento, y finalmente se obtiene uno responseObject, y luego responseObjectse realizan operaciones como la conversión del modelo.

Por ejemplo, mi proyecto actual es el uso de un MJExtension para convertir entre diccionarios y modelos, y esta conversión, me pusieron en cada API individual, como una solicitud de stock, la realicé InventoryAPIpara la responseObjectconversión en InventoryModelEn lugar de ponerlo en vc, es solo una solicitud de red en vc. Una vez completada la solicitud, se devuelve el modelo que quiero.

InventoryAPI.m

- (id)modelingFormJSONResponseObject:(id)JSONResponseObject
{
    NSUInteger count = ((NSArray *)JSONResponseObject).count;
    NSMutableArray *modelsArray = [NSMutableArray array];
    for(int i = 0; i < count; i ++)
    {
        InventoryModel *model = [InventoryModel mj_objectWithKeyValues:JSONResponseObject[i]];
        [modelsArray addObject:model];
    }
    return modelsArray;
}

InventoryViewController

- (void)requestInformation
{
    [api startWithBlockSuccess:^(__kindof YXYBaseRequest *request) {
        // request.responseObject 将会返回modelsArray
    } failure:^(__kindof YXYBaseRequest *request, NSError *error) {

    }];
}

Procesamiento de datos local

Hay muchas formas de almacenar datos locales. Una práctica común es usar .plistarchivos para almacenar datos muy simples, como configuraciones, mientras se usan bases de datos SQLite para almacenar otros datos complejos. Por otro lado, puedes intentar usarlo Core Datapara almacenar el modelo de datos, aunque Core Datatraerá más problemas e incluso afectará al rendimiento, pero su NSFetchResultsController, lazy loading, herramientas de procesamiento de datos, etc. también son muy fáciles de usar, así que ... mírate .

En el procesamiento local de datos, lo más importante es cómo obtener y modificar los datos. No hay mucho contenido local en el proyecto que necesite refactorizar ahora, y la mayoría de los datos se obtienen a través de la red, por lo que no estoy preparado para dar más detalles sobre Data Modella refactorización y estandarización correctas. Pero el principio básico es que cada modelo está equipado con un descriptor de acceso , que puede proporcionar fetchALl, fetchAllUsingPredicate, createInstance, savey otras operaciones, cada modelo puede utilizar estas operaciones para obtener los datos y la lógica de estas operaciones están ocultos, cuando no lo hago llamada Necesito saber si mi modelo está almacenado en la base de datos, en el .plistarchivo o en la caché. Solo necesito saber que cuando llamo a estos métodos, puedo obtener el modelo que quiero y puedo sacar los datos que quiero.

Procesamiento de lógica empresarial

En el modelo, no solo se puede procesar el almacenamiento de datos, sino que también se puede procesar la lógica empresarial. En el proyecto que necesito refactorizar, tanto la lógica de negocio fuerte como la débil están dispersas en la vc, lo que provoca que la vc esté muy hinchada. Por ejemplo, en el siguiente código, es necesario darse cuenta de DateModel中sacar un tiempo y convertir el NSDateformato del tiempo a NSString, Y la situación que se muestra en Ver:

DateModel.h

@interface DateModel : BaseModel

@property (copy, nonatomic) NSDate *currentDate;

@end

DateModel.m

- (instantcetype)init
{
	if (self = [super init])
		currentDate = [NSDate date];
	return self;
}

aViewController.m

- (void)showTheDate
{
	DateModel *dateModel = [DateModel new];
	NSDate *date = dateModel.currentDate;

	NSDateFormatter *format = [[NSDateFormatter alloc] init];
	format.dateFormat = @"yyyy年MM月dd号 HH:mm:ss";
	NSString *string = [format stringFromDate:date];

	self.dateLabel.text = string;
}

De hecho, este código se puede colocar por separado en la capa del modelo para aclarar todo el código vc, como por ejemplo:

NSDate + dateTransform.h

@interface NSDate (dateTransform)

+ (NSString *)transformStringFromDate:(NSDate *)date;

@end

NSDate + dateTransform.m

+ (NSString *)transformStringFromDate:(NSDate *)date
{
	NSDateFormatter *format = [[NSDateFormatter alloc] init];
	format.dateFormat = @"yyyy年MM月dd号 HH:mm:ss";
	NSString *string = [format stringFromDate:date];

	return string;
}

Cree una NSDatecategoría y coloque el código convertido en ella, y llámelo por DateModel para completar la conversión

DateModel.h

@interface DateModel : BaseModel

@property (copy, nonatomic) NSString *currentDate;

@end

DateModel.m

- (instantcetype)init
{
	if (self = [super init])
	{
		currentDate = [NSDate transformStringFromDate:[NSDate date]];
	}
	return self;
}

Luego, en vc, solo necesitamos una simple llamada:

aViewController.m

- (void)showTheDate
{
	DateModel *dateModel = [DateModel new];
	self.dateLabel.text = dateModel.currentDate;
}

De esta manera, la estructura del código de toda la vc es mucho más clara, los atributos extraídos por la capa del modelo también se pueden entregar directamente a la capa de visualización para su visualización, y el código para la conversión de fechas también se puede reutilizar fácilmente. En resumen, para este tipo de modelo, el método de llamada puede ser lo más abstracto posible y el modo IOC se puede aplicar cuando esta parte del código necesita ser desacoplada, de lo contrario será muy difícil cambiar estas lógicas en el futuro.
El contenido anterior es el contenido completo de este artículo. El contenido anterior espera ser útil para usted. Los amigos que han recibido ayuda pueden dar me gusta y comentar.
Si intercambia experiencia en pruebas de software, pruebas de interfaz, pruebas automatizadas y entrevistas. Si estás interesado, sígueme, tendremos intercambios técnicos con compañeros.

Supongo que te gusta

Origin blog.csdn.net/Chaqian/article/details/107157159
Recomendado
Clasificación