架构的演变就是一次次的重构之旅

172 阅读4分钟

摘要

架构师应该是所有程序员的终极梦想,但对于如何成为一个合格的架构师,却总是茫然无措,无从下手,相信大多数人跟我一样,曾经也或百度或谷歌过无数次:MVC是什么,MVVM是什么,数据流是什么,然而却没有一次让我醍醐灌顶、豁然开朗。我一直在带着这个疑问去找寻我心中的答案,这篇文章用来记录目前我所认识到的架构的含义,也希望能给有幸读到这篇文章的人以一丝启发和感悟。

前言

犹记得在刚接触iOS开发那会,自认为会写几个页面就能改变世界了,写代码只在乎功能实现,那时候也知道MVC,但要我具体说说啥是MVC,说不清楚。那时候公司也不注重这些,只为完成业务需求,忽视了技术的重要性。

后来在真正学习使用了一些新架构之后,我对架构的理解不一样了,我不再极力推崇某一架构,也不再为了架构而架构,而是去思考这个架构核心是什么,从何而来,为何存在。这是我这篇文章真正想表达的。

架构,百度百科给出的解释是:架构,又名软件架构,是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。它说架构是一种设计。但我自己的理解是,架构是我们代码优化到一定程度之后,自然而然形成的一种思维方式和编码形式,架构从何而来,从我们每次优化代码后的思考而来,架构为何存在,因为思考之后,留下来了好的思维方式和编码形式。为什么这么说,下面就从最简单的代码优化开始。 1、一个极简单的功能,点击按钮,切换背景色。这份代码初学者都能写出来吧。

    @IBOutlet weak var button: UIButton!
    override func viewDidLoad() {
        super.viewDidLoad()
        
        button.setTitle("编辑", for: .normal)
        // Do any additional setup after loading the view.
    }

    @IBAction func buttonTouch(_ sender: UIButton) {
        if sender.title(for: .normal) == "完成" {
            self.view.backgroundColor = UIColor.green
            sender.setTitle("编辑", for: .normal)
        } else if sender.title(for: .normal) == "编辑" {
            self.view.backgroundColor = UIColor.red
            sender.setTitle("完成", for: .normal)
        }

    }

2、上面那个是直接在storeboard编辑的,现在提一个需求,这个界面跟另一个界面很类似,项目中要共用,那我们就会把View拎出来,新建一个EditView,然后把这个View放到storeboard上,最后呈现的效果是一样的,但是实现了View和Controller的分离。

    @IBOutlet weak var button: UIButton!
    
    func setup() {
        button.setTitle("编辑", for: .normal)
    }
    
    @IBAction func buttonTouch(_ sender: UIButton) {
        if sender.title(for: .normal) == "完成" {
            self.backgroundColor = UIColor.green
            sender.setTitle("编辑", for: .normal)
        } else if sender.title(for: .normal) == "编辑" {
            self.backgroundColor = UIColor.red
            sender.setTitle("完成", for: .normal)
        }
    }

3、然后View上面会有一些其它元素,我们先添加两个label,代码也很简单

    func setup() {
        button.setTitle("编辑", for: .normal)
        titleLabel.text = "page1_title"
        subtitleLabel.text = "page1_subtitle"
    }

4、但界面中的元素是由用的人来管理数据的,你写死了别人怎么用呢,另一个界面的titleLabel并不是呈现“page1_title”,所以应该定一个Model,这个Model是你这个View的Model,别人用的时候只需要传一个ViewModel就可以了。

    struct ViewModel {
        var titleStr: String?
        var subtitleStr: String?
    }
    
    var viewModel: ViewModel? {
        didSet {
            titleLabel.text = viewModel?.titleStr
            subtitleLabel.text = viewModel?.subtitleStr
        }
    }

5、接下来,点击button后,要求这两个label文案改变,代码也很简单,EditView添加如下代码

enum ButtonType: Int {
    case edit = 0
    case done
}

var buttonCallback: ((ButtonType) -> Void)?
var curButtonType: ButtonType = .edit

    @IBAction func buttonTouch(_ sender: UIButton) {
        if sender.title(for: .normal) == "完成" {
            self.backgroundColor = UIColor.green
            sender.setTitle("编辑", for: .normal)
            curButtonType = .edit
        } else if sender.title(for: .normal) == "编辑" {
            self.backgroundColor = UIColor.red
            sender.setTitle("完成", for: .normal)
            curButtonType = .done
        }
        buttonCallback?(curButtonType)
    }

ViewController添加如下代码

        contentView.buttonCallback = {[weak self] state in
            guard let `self` = self else { return }
            if state == .done {
                let model = EditView.ViewModel(titleStr: "done_title", subtitleStr: "done_subtitle")
                self.contentView.viewModel = model
            } else if state == .edit {
                let model = EditView.ViewModel(titleStr: "edit_title", subtitleStr: "edit_subtitle")
                self.contentView.viewModel = model
            }
        }

6、写到这里,我们停下来,回过头去看一下,我们从来没有强调过用什么架构,但架构却已经成型了。这是MVC,这也是MVVM,这也是单向数据流。什么意思呢,我们现在有Model、View、Controller,我们的Model是ViewModel,我们改变View的途径只有一条,就是改变ViewModel。这不就是最最基础版的MVC+MVVM+单向数据流架构吗。这只是从代码扩展性和通用性来考虑,就已经达到的架构程度,所以架构不是一种思想吗?不是一种思维方式吗?架构是无止境的,需要我们一直思考,而不是局限于某一框架,框架带给我们便利的同时,也给我们带来了约束。

最后用猫神的一句话,这句话我深有感触,“能够使用简单的架构来搭建复杂的工程,制作出让其他开发者可以轻松理解的软件,避免高额的后续维护成本,让软件可持续发展并长期活跃,应该是每个开发者在构建软件是必须考虑的事情。”