Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

Objective-C

Войти
Регистрация
Восстановить пароль
 
residentkms
21 / 21 / 8
Регистрация: 20.10.2013
Сообщений: 138
Завершенные тесты: 1
#1

О написании чистого кода - Objective-C

11.11.2015, 17:43. Просмотров 549. Ответов 9
Метки нет (Все метки)

Вообщем, такая проблема.
Мне не нравится подобные нагромождения из if-ов, добавления и удаления оверлеев, бесконечных диалоговых окон:
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
UIView *overlay = [[UIView alloc]initWithFrame:self.view.frame];
    overlay.backgroundColor = [UIColor colorWithWhite:0.5f alpha:0.5f];
    overlay.userInteractionEnabled = YES;
    [self.view addSubview:overlay];
    
    UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    activity.color = [UIColor blackColor];
    activity.center = self.view.center;
    [self.view addSubview:activity];
    [activity startAnimating];
    
    NSString *parameters = [@"" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@""]];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"post";
    request.HTTPBody = [parameters dataUsingEncoding:NSUTF8StringEncoding];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response,
                                                                                                            NSData * _Nullable data,
                                                                                                            NSError * _Nullable connectionError) {
        [overlay removeFromSuperview];
        [activity removeFromSuperview];
        
        if (!connectionError) {
            if ([(NSHTTPURLResponse *)response statusCode] == HTTP_OK) {
                @try {
                    NSError *error;
                    _info = [NSJSONSerialization JSONObjectWithData:data
                                                            options:NSJSONReadingMutableContainers
                                                              error:&error];
                    if (error) {
                        @throw [NSException exceptionWithName:@"Parse error"
                                                       reason:@"Unknown"
                                                     userInfo:nil];
                    }
                    
                    ////
                }
                @catch (NSException *exception) {
                    _info = nil;
                    [[[UIAlertDialog alloc]initWithStyle:UIAlertDialogStyleAlert
                                                   title:@"Ошибка"
                                                 message:@"Произошла неизвестная ошибка"
                                              closeTitle:@"OK"] showInViewController:self];
                }
            } else if ([(NSHTTPURLResponse *)response statusCode] == HTTP_BAD_REQUEST) {
                [[[UIAlertDialog alloc]initWithStyle:UIAlertDialogStyleAlert
                                               title:@"Ошибка"
                                             message:@"Проверьте правильность ввода"
                                          closeTitle:@"OK"] showInViewController:self];
            } else {
                [[[UIAlertDialog alloc]initWithStyle:UIAlertDialogStyleAlert
                                               title:@"Ошибка"
                                             message:@"Произошла неизвестная ошибка"
                                          closeTitle:@"OK"] showInViewController:self];
            }
        } else {
            [[[UIAlertDialog alloc]initWithStyle:UIAlertDialogStyleAlert
                                           title:@"Ошибка"
                                         message:@"Ошибка соединения"
                                      closeTitle:@"OK"] showInViewController:self];
        }
    }];
Такое повсюду, и это не самый тяжелый случай.
Как в таких случаях рефакторить? Инкапсулировать в какой то класс (что то типа MyHTTPClient) а в нем все в отдельные методы под каждый реквест? Или как то еще мб?
Или может быть есть где то красиво выглядящие сорцы, на которые можно поглазеть и чему то научиться?
Вообщем, очень нужна помощь
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.11.2015, 17:43
Здравствуйте! Я подобрал для вас темы с ответами на вопрос О написании чистого кода (Objective-C):

Ошибка в написании кода - C#
Привет, всем! Помогите исправить ошибку: я расписываю кнопку сохранить для своей программы, но программа выдаёт ошибку. Вот код объявления...

Помощь в написании кода - PHP
Здравствуйте, если страница с записями по в 2 колонки (html) нужно сделать что то на подобии того что изображено на скриншоте 1, тоесть к...

Непонятности в написании кода - Java
Доброе время суток, форумчане. Недавно начал изучать язык Java, читаю и практикуюсь по книжке Шилдта. Дошел до многомерных массивов, в...

Помощь в написании кода - VBA
Доброго время суток,надеюсь,Вас не затруднит немного мне помочь. На SQL сервере я создала хранимую процедуру с 2-мя входными параметрами,...

Помощь в написании кода - Delphi
Welcome to Lamer Land, господа :) мне нужно сделать программу, анализирующая деятльность предприятия. Грубо говоря, есть данные,...

Ошибки в написании кода - PHP
Доброго времени суток! Нужно было написать подобие школьного журнала, но у меня возникли три ошибки, две из которых вы увидите, если...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
LeninRedStar
5 / 5 / 4
Регистрация: 22.11.2015
Сообщений: 21
22.11.2015, 22:11 #2
В коде видно что часто смешивается логика и интерфейс, т.е. могу подозревать, что этот код повторяется во многих местах, что в дальнейшем может привести к проблемам, поскольку противоречит MVC. Логику общения с сервером обычно выносят в один или несколько менеджеров. Обработка ошибок соединения прячется в эти менеджеры. Интерфейс такого менеджера может выглядеть как то так:

-(void) doSomeThingWithServerSuccess:^(NSArray *data)
Error:^(NSError *error);

В Блоке ошибки можно показывать соответствующее сообщение или передать ошибку дальше по стеку вызовов, в саксесс выполнять работу с полученными данными.

Прошу прощения за примерный синтаксис блоков, на память с ними мне сложно ))
0
residentkms
21 / 21 / 8
Регистрация: 20.10.2013
Сообщений: 138
Завершенные тесты: 1
23.11.2015, 11:04  [ТС] #3
Ну вот я в итоге и обернул все это, оставив обработку стандартных ошибок (ошибка соединения/невалидные данные) внутри. Количество кода, конечно, уменьшилось в разы, но я до сих пор не уверен в подобном подходе.

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@interface W4UHTTPClient : NSObject
 
typedef enum W4UHTTPMethod{
    W4UHTTPMethodPost,
    W4UHTTPMethodGet
}W4UHTTPMethod;
 
@property (assign, nonatomic) BOOL showErrorDialogs;
 
@property (assign, nonatomic) BOOL showOverlay;
 
@property (copy, nonatomic) NSString *baseUrl;
 
- (void)asyncRequestWithPath:(NSString *)url
                      method:(W4UHTTPMethod)method
                  parameters:(NSDictionary *)parameters
                    callback:(void(^)(NSHTTPURLResponse *response, NSData *data, W4UError *error))callback;
 
- (void)asyncJsonRequestWithPath:(NSString *)url
                          method:(W4UHTTPMethod)method
                      parameters:(NSDictionary *)parameters
                        callback:(void(^)(NSHTTPURLResponse *response, id json, W4UError *error))callback;
0
LeninRedStar
5 / 5 / 4
Регистрация: 22.11.2015
Сообщений: 21
23.11.2015, 11:28 #4
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Подход нормальный, просто нужно понимать что этого не решение всех проблем. Я так понял есть некий класс сейчас, который может выполнить запрос. В чистом виде его использовать из вьюконтроллеров очевидно не стоит. Над ним должны стоять более ориентированые на логику приложения классы, которые будут уже понимать что они получают либо посылают на сервер, сами умеют создавать наборы параметров для asyncRequest и распарсить приходящий результат.

Вью контроллер по хорошему должен иметь зависимость от некого протокола (класса, удовлетворяющего протоколу), который имеет методы, нужные именно этому контроллеру. Пример: есть логин скрин. У него должен быть член класса некий id<LoginProtocol> loginer. Этот loginer ему устанавливается извне, таким образом вьюконтроллер не знает даже какого он класса и ты всегда сможешь легко подменить один класс другим если вдруг поменялось взаимодействие с сервером. Сам протокол например имеет методы:

-(void) loginWithUser: (User * ) user
success:^(void) successBlock
error:^(NSError *error) errorBlock;

-(void) logout...


При этом реальный класс менеджер, который сетапят контроллеру может удовлетворять сразу нескольким протоколам, но т.к. про остальные протоколы логин скрин не знает, он других методов вызвать не может.

Далее схема может усложняться если в приложении например нужен кэш или некий оффлайн мод. Тогда уже можно вводить классы репозитории, которые в зависимости от того есть сеть или нет, будут обращаться либо к серверу либо к БД, при этом опять же скринам будет все равно куда они обратились, они свои данные в любом случае получат.
0
residentkms
21 / 21 / 8
Регистрация: 20.10.2013
Сообщений: 138
Завершенные тесты: 1
23.11.2015, 11:41  [ТС] #5
Цитата Сообщение от LeninRedStar Посмотреть сообщение
Вью контроллер по хорошему должен иметь зависимость от некого протокола (класса, удовлетворяющего протоколу), который имеет методы, нужные именно этому контроллеру
То есть, реализовывать логику (login) нужно возлагать на протокол, а не на сущность (того же юзера, например)?
0
LeninRedStar
5 / 5 / 4
Регистрация: 22.11.2015
Сообщений: 21
23.11.2015, 12:04 #6
конечно. Юзер должен быть контейнером, который просто хранит данные, т.е. моделью. Вообще модели не должны сами обращатсья к серверу. Объясню на примере юзера. Предположим что мы сделали логин прямо в классе User. При логине мы получаем от сервера некий токен или сессию, которая будет нужна другим запросам. В этом случае каждой другой модели, которая обращается к серверу чтобы что-то в себе обновить, понадобится эта сессия. И тут либо нужно во всех них иметь ссылку на юзера либо сделать чтобы юзер еще и сессию куда нибудь сохранил, а все остальные знали бы куда он ее сохранил. Код сразу становится путанным, и чем больше и сложнее модель, тем более путанным становится код.
0
residentkms
21 / 21 / 8
Регистрация: 20.10.2013
Сообщений: 138
Завершенные тесты: 1
23.11.2015, 12:21  [ТС] #7
Спасибо за столь развернутые ответы, одно лишь осталось не совсем понятно.

Цитата Сообщение от LeninRedStar Посмотреть сообщение
При этом реальный класс менеджер, который сетапят контроллеру может удовлетворять сразу нескольким протоколам, но т.к. про остальные протоколы логин скрин не знает, он других методов вызвать не может.
Как устанавливается менеджер конкретному скрину?
0
LeninRedStar
5 / 5 / 4
Регистрация: 22.11.2015
Сообщений: 21
23.11.2015, 12:56 #8
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
через фабрику либо прямо в сторике через dataObject. Однако тут нужно иметь в виду, что через сторик у тебя будет отдельный экземпляр, в случае если ты юзаешь синглтон, могут возникнуть сложности.

Фабрика предпочтительнее
0
residentkms
21 / 21 / 8
Регистрация: 20.10.2013
Сообщений: 138
Завершенные тесты: 1
23.11.2015, 13:36  [ТС] #9
dataobject?
0
LeninRedStar
5 / 5 / 4
Регистрация: 22.11.2015
Сообщений: 21
23.11.2015, 14:40 #10
ты можешь в сторике добавить на сцену Object из компонентов. Это может быть любой класс
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.11.2015, 14:40
Привет! Вот еще темы с ответами:

Предупреждения при написании кода. - C#
На каждой строке типа: comand.Parameters.Add(&quot;@Assmnt_ID&quot;, Assmnt_ID); студия пишет предупреждение. Чем это грозит, как от этого...

Дайте совет в написании кода - VBA
Задание про подпрограммы, функции. vba Не получается написать код. Помогите с написанием программы, дайте совет. Для...

Нужна помощь в написании кода - 1С
Есть документ в котором есть поля :Сотрудник(ссылка на справочник сотрудники),проект(ссылка на справочник...

Ошибка при написании кода - Delphi
В общем ближе к делу, есть поект в нем 3 юнита, в третьем юните у меня объявлены глобальные переменные(на скрине видно). Пытаюсь...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
23.11.2015, 14:40
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru