浅谈程序中所体现的思想

前言

最近一直忙于项目的事情,偶尔看看简书,时不时收到简书APP推送的通知,提醒谁关注了我,谁喜欢了文章,谁给我私信,看看上一篇文章发表的时间已经是三个月之前了,觉得自己该写写技术文章和关注我的人分享一下最近get到的技能了,奈何产品部突然提出一个类似于淘宝商城的功能需求出来,做出了30多个界面出来,告诉我们研发部1个月多月就要做出来。
我说说我的上个月听到这个需求时的心情,当时我很懵逼,懵逼的不是一个月时间,懵逼的是我们做的项目一直是关于电动车车联网,现在要做一个类似于淘宝的商城出来?我们当前需要做的需求只是关于车辆SIM卡续费和保险相应的功能,这也是当时出差时候客户所提及的需求,真的真的我很懵逼。产品是这样解释的:做车辆SIM卡续费和保险相应的功能不是都要涉及支付等功能吗,那还不如做一个商城,什么都有了,而且就30几个界面而已。。。
不过通过最后评估,限于各种需求说明不明确和时间不足,人员不够等问题,最终商城需求暂时停滞,改成了只做车辆SIM卡续费和保险相应的功能了。不过在这看似荒诞的过程中,我还是get到了不少技能,首先商城这个东西很多APP 开发并不采用原生的开发,结合当下热门技术react-native,我想到了混合开发,不过说实话我真的不会RN 技术,但是什么东西都是学来的,所以我起码了解到了RN的相关技术,最重要的是我get 到了如何嵌入RN 于原生的app中,并且已经实现了。
还有这周周五下班,跟项目经理同路,问了一下下周的开发计划,项目经理告诉我后台没人写啊,想想后台开发人员确实挺紧张的,我就说人员不够可以向领导赶紧提招人啊,起码保证以后开发进度不受影响啊,项目经理告诉我招个人进来两天就能写了,用不了那么久时间。
这下我又懵逼了,我们这个后台起码写了一年多了,当时开发人员至少7个,一直在做,在维护,现在只有2个,招一个人进来最快2天就能写了???项目经理又解释了一下,找人讲一下架构就可以了,就能写了。我记得去年他刚来2个月的时候,那时候后台人员是极度不足啊,当时中午吃饭聊天,我调侃到后台人员不够,暂时招不来人,说不定你可得来写啊,他当时的话我记忆犹新,“我写就写乱了,这得招人!”。我内心只能呵呵哒了。
还有前两天在一个简友的一个qq群里,听到一个哥们说,他们后台有多叼,别人传给他的数据,他都不处理,直接丢给他,让他APP 端处理,他在群里面各种抱怨。
想必所有的程序员都经历过这样事情,其实你发现你有时候主动的去沟通,去解释根本没有用,你再给产品解释商城有多复杂,在她眼里只是30几个界面,所以一定要记住,永远不要和不懂技术人去争论技术,你所要做的就是坚持需求必须明确的前提下我才能保质保量的完成和尽可能多的给自己争取时间。还有永远不要带着情绪去工作,你所需要做的就是做好自己的工作。说了那么多废话了,那就让我们开始本文的正文吧。

正文

案例一

前几天经常看到简友群里面哥们问,为什么我拿到远程推送的消息进行跳转时候,跳转不了啊,群主回答到,你数nav + tabbar,还是tabbar + nav,这时候哥们回去查代码去了。现在我来谈谈程序架构 tabbar + nav,首先看看普通代码(OC)设置

//这是在一个自定义tabbarController中添加子控制器
//添加控制器
- (void)addChildVC{
   
    HomeViewController *hvc = [[HomeViewController alloc]init];
    [self setChildVCWithViewController:hvc];
    
    LocationViewController *lvc = [[LocationViewController alloc]init];
    [self setChildVCWithViewController:lvc];
    
    LifeViewController *lfv = [[LifeViewController alloc] init];
    [self setChildVCWithViewController:lfv];
    
    SelfViewController *svc = [[SelfViewController alloc] init];
    [self setChildVCWithViewController:svc];
}
- (void)setChildVCWithViewController:(UIViewController *)childVC{
    
    UINavigationController *nc = [[UINavigationController alloc]initWithRootViewController:childVC];
    [self addChildViewController:nc];
}

上面自定义tabbarcontroller,在APPDelegate中设置为rootViewcontroller就可以了,这代码看上去挺好,起码APPDelegate中干干净净的,但是你不会觉得很繁琐吗?起码你得导入4个控制器的头文件,然后你得去每一个控制器实例化,那我们升级一下代码,采用反射的方法来创建控制器

Class hvc = NSClassFromString(@"SelfViewController");
[self setChildVCWithViewController:[[hvc alloc] init]];
同理创建其他三个即可。

这样你就可以愉快的删去所以用的头文件,其实这个问题在Swift中是不存在的,swift中默认统一命名空间下的文件是共享的。其实上面代码在实际开发中其实是不合理的,但是可能还有人这么写的,勤于思考的人可能会写一个基类,在基类里面处理tabbar的隐藏于显示,对于没有开发经验的人来说,估计每push 出来就要隐藏,其实有一个一劳永逸的办法就是:

自定义导航控制器,重写- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated这个方法

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
//判断如果不是栈底控制器,push的话就隐藏
    if (self.childViewControllers.count > 0) {
self.tabBarController.hidesBottomBarWhenPushed = YES;
        
    }
}

升级完以上代码其实觉得还是不够好,可扩展性不太好,我们能否采用另外的方式去实现,为了方便演示,我采用swift,跟OC思路是一样的,swift 写起来能更快一点

   ///设置所有子控制器
    fileprivate func setupChildControllers(){
    
        let array = [
            ["clsName": "MainViewController","title":"首页","imageName":"home"],
            ["clsName": "LocationViewController","title":"定位","imageName":"location"],
            ["clsName": "LifeViewController","title":"生活","imageName":"life"],
            ["clsName": "ProfileViewController","title":"我的","imageName":"profile"]
        ]
        
        var arrayM = [UIViewController]()
        
        for dict in array {
            
            arrayM.append(controller(dict: dict))
        }
       //设置tabbarController 的子控制器
        viewControllers = arrayM
    }
    
    
    private func controller(dict: [String: String]) -> UIViewController{
    
        //1.取得字典的内容
        guard let clsName = dict["clsName"],
              let title = dict["title"],
              let imagname = dict["imageName"],
            
//swift涉及命名空间的概念,通过反射的方法必须拿到其命名空间,这里的nameSpace是定义了一个获取命名空间的计算型属性
        let cls = NSClassFromString(Bundle.main.nameSpace + "." + clsName) as? UIViewController.Type

        else {
            return UIViewController()
        }

        
        //2.创建视图控制器
        let vc = cls.init()
        vc.title = title
       vc.tabBarItem.image = UIImage(named: "tabbar_" + imagname )
        vc.tabBarItem.selectedImage = UIImage(named: "tabbar_" + imagname + "_selected")
      vc.tabBarItem.setTitleTextAttributes([NSForegroundColorAttributeName:UIFont.systemFont(ofSize: 20)], for: .highlighted)

     //自定义的导航控制器 NavController
        let nav = NavController(rootViewController: vc)
        
        return nav
    }

//给Bundle扩展了nameSpace的计算型属性
extension Bundle{
    var nameSpace:String{
    
        return Bundle.main.infoDictionary?["CFBundleName"] as? String ?? ""
    
    }
}

以上代码你会发现可扩展性一下子提高了很多,例如你们的产品汪说你看看淘宝每次到情人节什么的,它下面的主题就换了,你就可以说这个小case我分分钟种就给你实现了,这时候你只需要跟你们后台协调一下,让他给你返回一个类似于上面格式的数据就可以了,具体的业务逻辑如下:

业务逻辑图

通过以上的分析,会发现tabbar + nav 的方式的架构设计会非常方便,这样当你接收到远程通知,拿navigationController push的时候的时候无比的顺畅。

案例二

    UIButton *completeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    completeBtn.frame = CGRectMake((SCREEN_WIDTH-(SCREEN_WIDTH*2)/5)/2, _mainView.y+_mainView.height+20, (SCREEN_WIDTH*2)/5, 40);
    [completeBtn setBackgroundColor:COLOR_LIGHTREDCOLOR];
    [completeBtn setTitle:@"注销" forState:UIControlStateNormal];
    [completeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [completeBtn addTarget:self action:@selector(completeBtnClick) forControlEvents:UIControlEventTouchUpInside];
    completeBtn.titleLabel.font = [UIFont systemFontOfSize:14];
    completeBtn.clipsToBounds = YES;
    completeBtn.layer.cornerRadius = 2;
    [self.view addSubview:completeBtn];

在我接手现有的项目的时候,在创建按钮地方就出现这一大坨代码,越看越不舒服,如果你一个项目中这样写代码估计会被人骂爹 的,我们能不能写的优雅一点,我们升级一下代码:

+ (instancetype)buttonWithFrame:(CGRect)frame CornerRadius:(CGFloat)cornerRadius BorderColor:(UIColor *)borderColor BorderWidth:(CGFloat)borderWidth Title:(NSString *)title Alpha:(CGFloat)alpha TitleLabelFont:(CGFloat)font TitleColor:(UIColor *)titleColor BackgroudColor:(UIColor *)backgroudColor{

    UIButton *btn = [[self alloc] init];
    btn.frame = frame;
    btn.layer.cornerRadius = cornerRadius;
    btn.layer.masksToBounds = YES;
    if (borderWidth) {
        btn.layer.borderWidth = borderWidth;
    }
    if (borderColor) {
        btn.layer.borderColor = borderColor.CGColor;
    }
    [btn setBackgroundColor:backgroudColor];
    [btn setTitle:title forState:UIControlStateNormal];
    if (alpha) {
        btn.alpha = alpha;
    }
    btn.titleLabel.font = [UIFont systemFontOfSize:font];
    [btn setTitleColor:titleColor forState:UIControlStateNormal];
    

    return btn;
}

我们给UIButton扩展一个方法,这样需要创建的地方,我们直接就可以获取。所以在一个项目中抽出公有的类是非常有必要的。
最后我谈一点我个人的理解,在项目多使用如基类的思想,分类思想,对于一个复杂界面(代码量超过800行),建议使用MVVM架构思想,将网络层提取出来,对controller进行相应的解耦,这样会让你代码的耦合性非常低,相应的可扩展性变高,平时多阅读以下开源的代码,看看大神的编写的思路,以及架构思想,多模仿多练习,不久你的思想认识,以及编写代码的能力会有很大的提升,最后说一下关于阅读外文资料看法,其实对于还没有相应阅读能力的朋友,没必要去强迫自己去看,因为你花费半天时间去看外文资料,有一半以上的时间去查单词是没有意义的,本来普通的搜索引擎是可以满足相应的要求的,等自己发现现有的资料无法满足自己的开发需求,可以去查找相应的资料,stackFlow gogle等等都是不错的选择。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,263评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,982评论 4 60
  • Xcode7之前,想要真机调试,必须花99刀购买开发者账号,而且步骤繁琐,需要下载证书。随着Xcode7的推出,大...
    YHWXQ简简单单的生活阅读 238评论 1 0
  • 1.意外 下课铃有力地敲响。 老师前脚踏出教室,七夕后脚就来到了代思落的桌前。 七夕一边急...
    星谢染森阅读 565评论 2 1
  • 国内外近半个世纪的有关研究表明:2岁-3岁是学习口头语言的第一个关键期;3岁到5岁是音乐才能发展的关键期;4岁到5...
    gaosijiaoyu阅读 590评论 0 3