zoukankan      html  css  js  c++  java
  • 零基础ASP.NET Core WebAPI团队协作开发

    零基础ASP.NET Core WebAPI团队协作开发

    相信大家对“前后端分离”和“微服务”这两个词应该是耳熟能详了。网上也有很多介绍这方面的文章。我这里提这个是因为接下来我要分享的内容和这个有些关联。

    随着前端应用场景的繁荣,用户体验需求的提高,原先传统的后端渲染页面返回给前端展示的模式面临挑战。后端工作除了处理数据逻辑还得适应界面UI的业务,越来越不堪负重。前端的重要性逐渐体现出来,在这种情况下使用前后端分离模式开发的逐渐增多。

    前端框架(比如Vue/Angular/React)的发力,大厂的推广使用,前后端分离已经很成熟。包括传统信息化这块以前使用传统WebMVC模式的开发BS应用有些都逐步转为前后端分离模式。特别是开发人员分工之后专注做好各自的工作,效率更高,做出来的产品也就更好。

    一、应用场景

    1浏览器端(Vue/Angular/React+服务端API

    2桌面客户端(mfc/winform/wpf+服务端API

    3移动客户端(各种App/App内置浏览器)+服务端API

    4、其他终端(大数据展示平台/报表展示平台)+服务端API

    客户端越来越强调轻量化,交互体验,不在满足于能用。服务端端只管提供API数据,这样业务逻辑大多在服务端处理,随着需求增加服务端的模块会越来越多。但是有些接口是共用的,有些是根据业务变动的,还有的API新旧版本过渡更新替换等等是服务端api要考虑的事情。设计好API开发框架面灵活应对这么多场景就很有必要了。

    原先可能会做一个单体式应用,把所有用到的接口都加进去。但这样粒度很粗,如果某个场景下只使用了部分接口,那也得把这整个应用部署,无法做到按需添加。还有就是可能要修改其中部分方法,需要整体重新编译发布。这都存在可能影响其他模块的风险。

    服务端任务量大了,怎么分工?这个时候单体明显已经不适用了。这里就引出了微服务。对微服务可能每个人有不同的理解,但有一点是有共识的,就是把一个大的单体式应用根据功能模块拆分,这样粒度细分之后很多接口就可以共用。之后的修改增加都是可以按需发布部署,局部出现问题不会影响整体。

    这个服务的粒度怎么拆分也是需要慎重考虑的问题。除了功能拆分还得考虑人员匹配。

    案例场景:一个系统有10个子系统(模块),每个子系统(模块)又有10个功能,每个功能再具体又可能有20左右的方法代码。

    这个案例,最后大概有2000个方法代码。

    如果开始安排10人的团队开发,中途因为项目紧急再增加了10个人进来,总共变成了20人,项目组怎么做才能快速适应这种人员变动。

    有时候不是人越多越能做好事情,在人员增加情况下除了增加沟通协调成本,实际情况会遇到新加的人参与进来的门槛很高,不能快速着手展开工作,有时候还会出现不知道从何入手的困境。这就是因为拆分的不合理,任何的改动可能会影响到他人。这样虽然为了赶进度加人了,但实际的效果却不是很理想。

    二、功能拆分分析

    怎么拆分这有两个极端例子

    1、粒度最粗,全部在一个解决方案(极端例子,类似单体式应用,适合一人开发)

    2、粒度最细,细分到每个方法一个解决方案(极端例子,实际肯定不会这样做)

    实际项目中功能拆分就是在这两个极端情况之间找适合的平衡点。具体拆分到多大的粒度,这个就只能是根据具体项目情况具体分析了。但是微服务可能是建议往细的方向拆。

    如果是项目型的会发现如果拆的太细,上线一套系统要带N个接口,运维实施都很麻烦;如果是做平台型的产品可能就是有限的几套系统,不会随着项目铺开太多定制化。也就没有了项目型里面的经常部署实施等繁琐的问题。

    比如上面的案例,一般都是先根据子系统拆分,具体到每个子系统,有一人或多人开发也有后期临时加入的情况。每个子系统一套接口还是比较合适的。

    实际情况项目型比较多,考虑实施运维情况拆分的粒度不会太细,让实施去部署太多业务接口会把他们逼疯。如果有和我类似情况的下面的方案提供了一种解决办法。开发时候可以横向任意扩展,新加入的人员分配任务清晰,不用担心有耦合冲突。发布部署也不会因为粒度太细,增加部署工作量。总结就是插件式开发,微服务部署。

    我们都知道vs里面建立一个解决方案,两三个开发人员在同一个解决方案里面开发,只要协调好还行,如果再加入人员,参与的开发人员一旦多了,就算分工好做各自模块,但还是会存在一个些冲突,比如增加文件,增加引用等等都会引起项目文件或者解决方案文件冲突问题。而且这种情况代码权限还不好细分控制。

    最好的方式是每个开发人员做的事情都在自己的解决方案里面,只要是公共使用的引用协调好大家使用统一的版本,其他的自己完全可控,完全不用担心影响他人,或者他人的修改影响自己。

    大家可以看下这个 github上面dotnet基础类库 如图1。

     

    1

    这是dotnet基础库的源码,每个基础类库都是单独一个解决方案维护,随便点一个进去看下,如图2

     

    2

    每个类库都有独立解决方案文件。

    微软肯定有更好的方式去管理,但从这里可以看出,独立开发维护的优势。

    三、接口项目准备

    前面分享过一篇《零基础ASP.NET Core MVC插件式开发》的文章,那边文章其实也就是强调团队开发的时候能做到尽量独立,可以横向扩展,项目灵活变动增加开发人员可以快速参与,开发之后能汇总到一个个的子系统,最后完成整体开发。在这里API的开发也可以使用类似方案,因为API没有视图部分,处理起来MVC简单。

    接下来重点介绍该方案在API开发中的使用。开始这部分内容之前先简单介绍我这边API项目开发总结的两个共性问题:

    1、使用swagger显示API文档(nuget 引用 Swashbuckle.AspNetCore

    因为API是没有试图的,为了可视化,以及方便测试,使用swagger作为API的展示界面。具体使用看下面提供的demo代码

    2、使用版本控制API版本号(nuget 引用Microsoft.AspNetCore.Mvc.Versioning

    版本控制对API也是同样重要,看BAT大厂提供的API都是有版本控制的,要向他们看齐。实际应用中,程序不可能维持一套最新,有时候新旧版本需要过渡,所以需要有版本来区分。这里使用微软提供的版本控制。具体使用看下面提供的demo代码

    这两个使用这里就不细说了,穿插下面主题做些简单介绍,具体看案例demo就可以。

    四、接口插件式开发

    回到我们的主题,这里重点介绍下一个子系统(模块)任务拆分与人员分工

    项目组接下一个项目,一般有个开发组长,着手模块划分并且开发任务分工

    组长(公共部分接口+核心功能模块接口)

    组员1:细分的模块插件1接口

    组员2:细分的模块插件2接口

    组员3:细分的模块插件3接口

    ......

    ......

    对于的解决方案结构,具体命名自己可以根据喜好自己自定义。

    Agile.ModuleName.API  如下图3

    Agile.ModuleName.Plug1.API 图下图4

    Agile.ModuleName.Plug2.API

    Agile.ModuleName.Plug3.API

    ......

    ......

     

    3

     

    4

    Demo使用的是vs2019Asp.net core 2.1

    注意:如果一个模块里面接口比较多,一个解决方案里面不适合团队开发。所以对这种接口功能比较多,拆成各个插件方便团队开发,最后发布的时候合并到一起。但是如果这个模块接口不是很多,就没必要过度设计为了插件化而拆开。

    每个独立开发的都是vs里面建立的标准ASP.NET Core WebAPI项目,这里主项目和各个插件项目没有从属关系,完全平等API项目开发,最后只是可以汇合到主项目作为一个站点发布交付。各自独立调试运行各自开发功能模块,测试没问题发布汇总到主项目,部署运行,之后哪个接口问题只需要找到对应的模块修改,完全隔离开,不用担心修改会影响其他正常使用的模块。

    主项目解决方案结构,如图5

     

    5

    v1v2里面的是有版本控制的,放在外面的就不需要版本控制。

    还有Extensions文件夹里面两个类也是为了版本的显示做处理,具体看Startup.cs里面代码,如图6

     

    6

    搭建好之后,主项目运行,选择v1版本显示如图7

     

    7

    如果选择v2,显示如图8

     

    8

    通过上面两个切换,应该看到不管选择v1还是v2下面不受版本控制的都会显示。

    如果把图4的代码注释掉,看下运行效果,如图9

     

    9

    显示就这样,不能根据swagger选择,直观的显示是v1还是v2。这个就是RemoveVersionFromParameterReplaceVersionWithExactValueInPath两个类的作用。

     这两个类的代码如下

    public class RemoveVersionFromParameter : IOperationFilter
        {
            public void Apply(Operation operation, OperationFilterContext context)
            {
                if (operation.Parameters.Count > 0)
                {
                    var versionParameter = operation.Parameters.FirstOrDefault(p => p.Name == "version");
                    operation.Parameters.Remove(versionParameter);
                }
            }
        }
    
    
    public class ReplaceVersionWithExactValueInPath : IDocumentFilter
        {
            public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
            {
                swaggerDoc.Paths = swaggerDoc.Paths
                    .ToDictionary(
                        path => path.Key.Replace("v{version}", swaggerDoc.Info.Version),
                        path => path.Value
                    );
            }
        }

    到这里主项目API运行正常,接下来看下插件项目API

    插件1项目结构,和主项目类似,如图10

     

    10

    单独运行下这个插件1项目,效果如图11

     

    11

    这里作为插件API项目同样有一点要注意,不要出现和其他插件或者主项目同名的路由(versioncontrolleraction三个完全一样,分工之后各自命名规范估计这种情况也不会出现,主要还是注意避免合并之后路由重名问题)。

    这里先把插件1编译的dll放到主项目的运行目录来,如图12

     

    12

    并且在主项目的Startup.cs里面增加这段代码,如图13

     

    13

    运行看下效果,如图14

     

    14

    汇合成功,插件1API能展示出来,测试也正常,测试就不截图了。

    同理,插件1,插件2...等等也是一样处理。开发阶段,各自开发的功能都是可以独立调试运行的。有没有主项目对各自开发的不影响。

    五、问题总结

     

    如果插件项目里面引用了一个第三方的程序集,如图15

     

    15

    引用一个测试类库,在Plug1NoVerControllerGet方法里面写一个测试代码,如图16

     

    16

    在插件项目单独测试,运行正常。

    再把插件1相关文件拷贝到主项目,这时候多了个插件项目自己引用的OtherLib.dll,如图17

     

    17

    正常运行,如图18

     

    18

    测试下刚才插件1里面用到OtherLib类的接口,看效果如图19

     

    19

    汗,居然报错了,提示FileNotFoundException,但是看上面的错误信息截图提示找不到OtherLib.dll文件。OtherLib.dll这个文件明明在这个目录有的。查了相关资料都说是.net core的加载机制变了,但还是没理解透彻,不知道.net core3.0会不会解决这个问题。希望有大神看到可以解惑下这个问题。不过这里我使用一种方式可以解决这个报错,在主程序这里加这段代码。在注册插件项目之前,遍历所有dll,做一次加载就可以了。如图20

     

    20

    需要在注册插件之前,把所有dll文件这样加载一遍,就可以了。

    再运行,测试就正常了,如图21

     

    21

     

     

    六、发布运行

    各个独立开发的插件API,各自独立开发调试正常之后,发布出来。

    好了,插件1,插件2...等等各自都开发好了,各自模块调试没问题,最后汇总到主的项目来,基本也就没什么问题了,并且还可以作为一个站点部署。

    这里的一个站点只是一个接口服务,不要理解成一个系统就这一个接口服务,虽然可以这样做,但不建议,部署还是各个子系统一个服务,这样数量也不会很多。这里是指在开发阶段对一个子系统(模块)的N个接口做开发方面的分工独立开发调试。

    子系统(模块)有N个接口,开发分工如下:

    主插件,插件1,插件2,插件3...

    全部汇总到主插件的发布目录,或者手动拷贝,最后提供一个完成的子系统接口发布版本,目录如图22

     

    22

    同样命令行运行,或者宿主到iis,这里命令行运行,如图23

     

    23

    浏览器打开,如图24

     

    24

    直接swagger测试各个接口,正常。

    独立插件化开发,微服务发布部署。

    希望你看了之后有点收获,代码程序下面附件提供

    Demo程序

  • 相关阅读:
    结对编程作业——毕设导师智能匹配
    结对项目之需求分析与原型设计
    Excel绘制之甘特图
    Excel绘图之数据波动条形图
    Excel绘图之漏斗图
    Excel绘图之四象限散点图
    软件工程实践总结
    发送手机验证码
    个人作业——软件产品案例分析
    用例图
  • 原文地址:https://www.cnblogs.com/sylla/p/11198631.html
Copyright © 2011-2022 走看看