文档章节

编码风格约定

天风霁月
 天风霁月
发布于 2016/01/14 12:43
字数 3261
阅读 5029
收藏 189
点赞 14
评论 25

[toc]

编码风格约定

写在最前面

  • 一个统一的好的编码风格好过一打大牛

  • 你怎么看别人的代码呢?

每个人都有自己的编码风格,这个受到个人的学习以及工作历程影响。

多人协同开发,不可避免的会遇到一个功能几个人一起开发,或者同一个功能,前后由不同的人开发。这个时候问题来了,如果是你,你会怎么看待别人的代码呢?呵呵,这其实已经不言而喻了。

  • 那又怎么样?

说实话对于个人来说,真不能怎么样,谁没有一两个满是坑的项目呢,又有谁不是从最开始的垃圾代码中慢慢提炼出自己的编码风格呢。

但是对于一个项目,那太可怕的,不会有人会想要遇到这样的项目,很多人会在项目风险爆发之前溜之大吉,留下满地狼藉,等待重建。

但是你真的希望你自己的项目,亲手写的代码,最后会是这样的结果?或者当你进入一家新公司的时候,竟然拿不出一点可以用来的炫耀的东西。

  • 我们要怎么做?

如果每一回看到别人的代码都痛不欲生,那么我们的人生还有什么快乐。你要相信你不会永远只关注于你自己的一个小角落。

那么我们要怎么做呢?如果你能看别人的代码如同你自己的写的,你写的代码每一行都是犹如ISO般的标准,那么是不是会有这样的感觉:“我靠,我当初怎么这么傻”。

这就是我们现在要做的,统一编码风格:不同的人写一样风格的代码,对应业务处理有着相同的代码逻辑。

  • 约定大于规范

讲了这么多,只是为了阐述统一编码风格的重要。在这里我需要提出这样一个概念:约定大于规范,及凡是在约定范围里的内容,必须被不折不扣的实行,否则我们的这些约定又有什么意义呢。

  • 期待以后更多的约定

现在定义的这些肯定不会是全部,在以后的开发中必然会遇到更多的问题,从而提炼出更多的约定,这是好事情,也是正确的方向。让我们满怀期待这样盼望。

编码风格基本约定

BB了半天,让我们进入正题,这篇文档既是这次代码重构的指导文档,也会是前端小组的内部代码规范定义文档,用来给每一个新加入的兄弟姐妹们套上一个足够结实的辔头,以约束你们过于奔放的想法,编程毕竟是一个严谨的工作。

缩进及空格的约定

  • HTML缩进

DOM元素 缩进是两个空格,便于在屏幕中展示更多的内容。

ng指令换行且缩进4个空格

<div id="" name="" class="" 
    ng-show=""
    ng-click-""
    ng-class="">
</div>
  • JS缩进

缩进是两个空格

  • 变量赋值的空格

为了方便理解,用[ ]代表一个空格。

var i = 0; // var[ ]i[ ]=[ ]0;
var i, j;  //var[ ]i,[ ]j;
var i = 1, j = 2;  //var[ ]i[ ]=[ ]1,[ ]j[ ]=[ ]2;
  • function定义的空格

  • 函数表达式函数定义** var 不能省略**


var somting = function (p1, p2, p3) {s
} 
//var[ ]somting[ ]=[ ]funtion[ ](p1,[ ]p2,[ ]p3)[ ]{}
  • for的空格
for (var i=0; i<list.length; i++) {
}
//for[ ](var[ ]i=0;[ ]i<list.length;[ ]i++)[ ]{}

for (key : obj) {
}
//for[ ](key[ ]:[ ]obj)[ ]{}
  • if的空格
if () {
} else {
}
//if[ ](true)[ ]{}[ ]else[ ]{}
  • object中的空格
var obj = {
  doSmting: function () {
  },
  list: [{}, {}]
}

/*
var[ ]obj[ ]=[ ]{
  doSomting:[ ]function[ ]()[ ]{
  }, 
  list:[ ][{},[ ]{}]
}
*/
  • JSON中的空格

var obj = {1: "", 2: ""}
//var[ ]obj[ ]=[ ]{1:[ ]"",[ ]2:[ ]""}

引号的使用

  • 单引号

js代码中统一使用单引号,设计一些html模板时单引号内部可以使用双引号

  • 双引号

html代码中统一使用双引号

命名规范及约定

这项本来是不想说的,但是作为未来前端代码规范文档,这里还是需要提一下。禁止一切无意义命名,禁止全局变量的定义,rootScope中的变量需要统一在app.js中定义。

  • 变量命名

变量的命名,首先是这肯定是一个名词禁止使用中文拼音以及拼音缩写。遵循小驼峰命名,首字符小写。scope底下禁止独立变量的存在禁止省略写法,var 必须写

var isBoolean = true; //布尔值以is开头
var arrayList = [];   //数组以List结尾

$scope.type = 1;      /**这种写法是禁止使用的**/
  • 函数命名

函数一般是执行一组操作的代码块,所以用动名词结合的方式命名,使用var name = function(agrs)。函数内部需要用到一些关键参数,作为入参传入,即使在scope中存在,也需要作为入参传入(好处是提高函数复用的可能)。当前项目中不需要匿名函数(回调函数除外),以及自运行函数。

var getSomting = function (id) {}        //获取某个值
var loadSomting = function (agrs[]) {}   //从后台加载数据,涉及到restService
var postSomting = function (obj{}) {}    //提交表单操作,新建
var deleteSomting = function (id) {}     //删除操作
var putSomting = function (id, obj{}) {}  //提交表单操作,修改
var initSomting = function () {}         //初始化函数,一般是用来获取某个获取后台的某个资源

$scope.views = {
    showSomting: function () {}
    chooseSomting: function () {}
}

  • controller的命名

controller的命名为首字母大写的大驼峰规则(PS:这个写法不知道是从哪里流行起来的,似乎大家都是这么用的)。

  • factory的命名

factory的命名为首字母小写的小驼峰规则,英文命名,尽量精简同时语义明确。

  • directive的命名

同factory

全局静态常量定义约定

这里的全局常量需要定义在单独的app_static.js文件下,方便统一管理以及协同开发。定义一个全局的常量约定如下:

命名:全大写英文,用下划线"_"分割单词

定义方法: constant() 或者 value()

angular.module('myApp.static', [])
.constant("USER_TYPE", {1: "个人", 2: "企业"})

全局动态变量定义约定

全局的动态变量来自后台提供的一些业务数据,大部分来自数据库字典表,这里使用factory的定义service的方式来实现全局动态变量的定义,约定如下:

命名:全大写英文,用下划线"_"分割单词

定义方法: factory

angular.module('myApp.somting',[])

.factory("SOME_TYPES", function ($resource) {
  var SOME_TYPES = {};

  $resource(url, 'GET').then(function (result) {
    SOME_TYPES = result
  });

  return SOME_TYPES;
})

注释约定

注释是用来解释当前代码的功能,一个好的注释就是能让人一眼看懂复杂的内部实现逻辑,而一个规范的注释能够形成最后的api文档。当然最重要的是注释可以你知道究竟该找谁痛扁一顿,所以凡写过必留下痕迹。

  • 文件注释

写在文件的最开头

/**
 * @author
 * @date
 * @module name
 * @description
 */
  • controller注释

写在controller内部第一行

.controller(function () {
    /**
     * @author 
     * @date 
     * @controller name
     * @description 
     */
})
  • 函数注释

写在函数外面,入参和出参如果没有就不要写

/**
  * @fuction name
  * @param {agr[0]:"描述",agr[1]:"描述"}
  * @return {agr[0]:"描述",agr[1]:"描述"}
  * @description 
  * @author
  * @date
  */
function () {
    return ;
}
  • 行注释

单行注释

var obj = "" ; //参数定义注释

function () {
...
// 对函数内部代码或者逻辑的特殊说明
...
}

基础数据模型定义的约定

基础数据模型依赖于后台接口提供的数据,同时根据前台具体的业务场景或不变或转换格式保存在前台缓存对象下,同时也可以将变化过的数据更新到当前数据模型中。

service中的函数命名,尽量精简,避免ById 之类的命名。

保留五种方法:getList,getDetail,post,update,delete

app.factory("userService",function ($q, $resource) {
    
    var service = {
        getList : function () {
          //来自后台数据
          return $q(function(resolve, reject){
            //success  resolve()
            //failed   reject()   
          })
        }
        getDetail : function (id) {
          //来自后台数据
          return $q(function(resolve, reject){
            //success  resolve()
            //failed   reject()
          })
        },
        post : function (user) {
          //来自后台数据
          return $q(function(resolve, reject){
            //success  resolve()
            //failed   reject()
          })
        },
        update : function (id, user) {
          //来自后台数据
          return $q(function(resolve, reject){
            //success  resolve()
            //failed   reject()
          })
        },
        delete : function (id) {
          //来自后台数据
          return $q(function(resolve, reject){
            //success  resolve()
            //failed   reject()
          })
        }
    }
    
 
    return service;
})

form表单验证

  1. 引用angular-messages实现验证信息的展示
  2. 表单提交使用ng-submit
  3. 禁止浏览器的验证 novalidate
  4. 使用form.waiting来避免表单重复提交
  5. 使用form.field.blur=true/false/udefined来处理获得失去焦点以及初始化的情况。
<form name="myForm" ng-submit="postSomting" novalidate>
    <div>
      <span>用户名:</span>
       <input type="text" name="username" placeholder="请输入URL信息"
            ng-model="some.username" required
            ng-pattern="REG"/>
        <div>
          <div ng-messages="myForm.username.$error">
          <div class="error" ng-message="required">用户名不能为空</div>
          <div class="error" ng-message="pattern">请输入正确的用户名</div>
        </div>
      </div>
    </div>
    <input type="submit" ng-disable="myForm.$validate" value="提交">
</form>

分号(;)使用

代码块的分号不可被省略,因为考虑到以后的压缩,混淆。

if中的{}省略

大部分的if判断,else 分支都是有一定意义的,只有某一些时候是可以省略的。if 直接return 可以忽略。

if (true) return;
if (true) return somtion;

ng-src和ng-href 代替 src、href

当src和href中包含$scope中变量时,使用ng-src和ng-href避免错误的网络请求

:正常的静态资源地址不需要这样处理。

项目开发代码规范

变量的定义

  • view 对象的使用

每个controller中都要定义 view 对象,即使是空的。

.controller(function($scope){
    $scope.view = {}
})
  • controller 中的变量

controller 禁止定义全局变量,变量只存在于函数内部,或者 view 上

代码顺序的约定

代码顺序既是对于controller中的N多行代码究竟谁先谁后的约定。顺序依次是:

  1. scope变量定义在最前;
  2. scope底下的function;
  3. controller内部函数;
  4. 初始化函数定义及调用

注:只要是在scope中用到的变量全部需要最先声明。

.controller(function () {
    /*scope底下的对象最先声明*/
    $scope.somting = {};
    /*scope底下的function*/
    $scope.doSomting = function () {}
    /*controller局部函数*/
    var doSomting = function () {}

    /*controller的初始化函数定义*/
    var run = function () {}
    /*运行初始化函数*/
    run();
})

视图模型定义的约定

controller中的离散变量将通过scope.views(作为试图模型对象)统一控制,甚至某些复杂页面视图模型,可以在views中用单独的对象处理。

实际上针对数据模型,也有一篇正在写的博客“angular项目中实现数据分层”

//页面视图控制数据模型
$scope.views = {
  somting: "",
  isSomting: true,
  chooseSomting: function () {
    this.sonting = "";
  },
  oneObj: {
    oneType: "",
    showOne: fucntion () {
      this.one = "";
    }
  }
}

//后台返回数据模型
$scope.somting = somtingService.get();

业务数据模型定义的约定

业务数据模型一般是有别于基础数据模型和视图数据模型,一般是包含视图内容的数据对象,例如表单数据对象,或者被选中的某些数据,这些数据一般用于界面控制也会提取出接口参数用于交互。

$scope.somtingSelectedList = [{
  id: 1,
  ...
  selected: true
}, {
  id: 2,
  ...
  selected: true
}, {
  id: 3,
  ...
  selected: false
}...]

一些数据模型会有一些相应的操作,这个时候可以使用数据对象来处理, 就函数以及数据本身包含在一个数据对象上。(PS:尽量减少controller下面的孤立函数)


$scope.somting = {
    list: [{}],
    select: function(){},
    delete: function(){},
    getDate: function(){}
}

controller 中的初始化函数

大部分时候页面初始化需要controller的一些赋值操作,以及数据请求。这部分初始操作定义成 run 函数。

:run是controller下的保留函数,不管有没有用到,都要定义,而且一定不要绑定在 $scope 下

.controller(function(){

    var run = function(){
    }
    
    run();
})

ui-router的使用

计划开一篇“ui-router使用心得”

  • 参数传递

使用$stateParams传递数据

//config中定义参数
$stateProvider.state('stateTo',{
  url: '',
  templateUrl: '',
  params: {p1: '', p2: ''}
})

//state.go
$state.go('stateTo', {p1: '1', p2: '2'})

//controller中接收
controller(function($stateParams){
  $stateParams.p1;
  $stateParams.p2;
})


  • resolve的使用

主要用来对controller依赖的service中的数据进行初次加载,同时避免由于数据单例造成的数据不同步问题。

最近的一些使用,发现resolve的使用有一些局限性,以及对代码结构的一些限制,也在考虑是否引入resolve的概念。其实在contrlller上面的一些处理也能实现数据加载展示的效果。保留意见。

$stateProvider.state('stateTo', {
  url: '',
  templateUrl: '',
  resolve: {
    someService:"someService",
    init: function () {   //方法名自定义,所有方法都会在页面加载前被调用
      someService.load();
    }
  }
})

© 著作权归作者所有

共有 人打赏支持
天风霁月
粉丝 6
博文 8
码字总数 13474
作品 0
苏州
程序员
加载中

评论(25)

无尾熊森林本尊
无尾熊森林本尊
83不错写的很详细。值得实践使用
天风霁月
天风霁月

引用来自“LAJS”的评论

为什么空两格,你让我们这些屏幕大的人怎么办,代码看起来瘦瘦的,而且整体偏左
两格是推荐使用,公司比较穷,没有配显现屏
红薯的小黄瓜
红薯的小黄瓜
为什么空两格,你让我们这些屏幕大的人怎么办,代码看起来瘦瘦的,而且整体偏左
天风霁月
天风霁月

引用来自“for7020”的评论

代码看着很舒服,请教一下楼主,factory缓存了数据,而切换了用户需要清除factory的缓存要怎么实现呢?

引用来自“天风霁月”的评论

用户的基本信息(例如id,username等常用信息)会保存在cookies里面及$cookies中,而用户的详细信息保存在userService下面,对出登录清除cookies,另,登录登出也可以抽象出loginLogoutService,或者sessionService

引用来自“for7020”的评论

感谢楼主的回答,现在是这样的,我把当前用户的订单记录数据缓存在orderService,联系人数据缓存contactService,等等子模块Service缓存了属于当前用户的数据,切换了用户不知道该怎么清除各个Service缓存的上一个用户的数据.楼主有处理过这样的情况吗?

引用来自“天风霁月”的评论

没有遇到这样的情况,是否可以考虑在退出的时候清理相关service下的数据,或者单独写一个serviceManage用来管理所有的service,在每个service下面开放clean接口,然后将service加入到serviceManage中,然后处理

引用来自“for7020”的评论

赞,好主意
我想了一下serviceMange并不是一个好的实现,无必要的增加了代码的复杂度,而应该考虑orderService,contactService等等是从属于用户信息或者订单信息的一部分,从而注入到对应的service下面,在这些service中清除对应数据可能跟和逻辑一点
f
for7020

引用来自“for7020”的评论

代码看着很舒服,请教一下楼主,factory缓存了数据,而切换了用户需要清除factory的缓存要怎么实现呢?

引用来自“天风霁月”的评论

用户的基本信息(例如id,username等常用信息)会保存在cookies里面及$cookies中,而用户的详细信息保存在userService下面,对出登录清除cookies,另,登录登出也可以抽象出loginLogoutService,或者sessionService

引用来自“for7020”的评论

感谢楼主的回答,现在是这样的,我把当前用户的订单记录数据缓存在orderService,联系人数据缓存contactService,等等子模块Service缓存了属于当前用户的数据,切换了用户不知道该怎么清除各个Service缓存的上一个用户的数据.楼主有处理过这样的情况吗?

引用来自“天风霁月”的评论

没有遇到这样的情况,是否可以考虑在退出的时候清理相关service下的数据,或者单独写一个serviceManage用来管理所有的service,在每个service下面开放clean接口,然后将service加入到serviceManage中,然后处理
赞,好主意
天风霁月
天风霁月

引用来自“for7020”的评论

代码看着很舒服,请教一下楼主,factory缓存了数据,而切换了用户需要清除factory的缓存要怎么实现呢?

引用来自“天风霁月”的评论

用户的基本信息(例如id,username等常用信息)会保存在cookies里面及$cookies中,而用户的详细信息保存在userService下面,对出登录清除cookies,另,登录登出也可以抽象出loginLogoutService,或者sessionService

引用来自“for7020”的评论

感谢楼主的回答,现在是这样的,我把当前用户的订单记录数据缓存在orderService,联系人数据缓存contactService,等等子模块Service缓存了属于当前用户的数据,切换了用户不知道该怎么清除各个Service缓存的上一个用户的数据.楼主有处理过这样的情况吗?
没有遇到这样的情况,是否可以考虑在退出的时候清理相关service下的数据,或者单独写一个serviceManage用来管理所有的service,在每个service下面开放clean接口,然后将service加入到serviceManage中,然后处理
f
for7020

引用来自“for7020”的评论

代码看着很舒服,请教一下楼主,factory缓存了数据,而切换了用户需要清除factory的缓存要怎么实现呢?

引用来自“天风霁月”的评论

用户的基本信息(例如id,username等常用信息)会保存在cookies里面及$cookies中,而用户的详细信息保存在userService下面,对出登录清除cookies,另,登录登出也可以抽象出loginLogoutService,或者sessionService
感谢楼主的回答,现在是这样的,我把当前用户的订单记录数据缓存在orderService,联系人数据缓存contactService,等等子模块Service缓存了属于当前用户的数据,切换了用户不知道该怎么清除各个Service缓存的上一个用户的数据.楼主有处理过这样的情况吗?
天风霁月
天风霁月

引用来自“for7020”的评论

代码看着很舒服,请教一下楼主,factory缓存了数据,而切换了用户需要清除factory的缓存要怎么实现呢?
用户的基本信息(例如id,username等常用信息)会保存在cookies里面及$cookies中,而用户的详细信息保存在userService下面,对出登录清除cookies,另,登录登出也可以抽象出loginLogoutService,或者sessionService
f
for7020
代码看着很舒服,请教一下楼主,factory缓存了数据,而切换了用户需要清除factory的缓存要怎么实现呢?
红薯的小黄瓜
红薯的小黄瓜

引用来自“巴顿”的评论

禁止使用中文拼音以及拼音缩写.....
日常检查规范条例,这个变量,你帮我命名一下。

还有红包 支付宝 余额宝 搜狗 百度等都用英语给我翻译一下
编码风格不是编码规范

我并不认为程序员是一个情绪特别丰富的群体。但有一些事情却能很容易刺激程序员的神经,那就是代码格式和布局。如果看到一个函数的括弧在同一行上没有闭合,我的眼睛会喷血。如果看到有人没有...

oschina
2013/07/01
4K
20
JavaScript验证工具--JSLint

JSLint是一个JavaScript验证工具(非开源),可以扫描JavaScript源代码来查找问题。如果JSLint发现一 个问题,JSLint就会显示描述这个问题的消息,并指出错误在源代码中的大致位置。有些编码...

匿名
2009/05/06
24.3K
0
python基础autopep8__python代码规范

关于PEP 8 PEP 8,Style Guide for Python Code,是Python官方推出编码约定,主要是为了保证 Python 编码的风格一致,提高代码的可读性。 官网地址:https://www.python.org/dev/peps/pep-0...

_周小董
05/01
0
0
编码规范集锦

真的不知道我的第一篇真正的文章应该以什么为主题。我最终选择了编码规范。 编码规范是什么? 简单说——编码规范是一种…规范。通过建立起一种通用的约定和模式,所有人都遵循,以此帮助打造...

oschina
2013/04/08
5.7K
23
软件项目质量保证:编码规范

原文出处:MeteorSeed 作为软件开发者,我们可以开发低等级的软件,但不能开发低质量的软件。所以,如何实施质量保证,是我们关注的主要问题之一,而编码规范则是实施质量保证的第一步。 编码...

MeteorSeed
2016/08/29
0
0
Python Coding Rule

介绍 这篇文档所给出的编码约定适用于在主要的Python发布版本中组成标准库的Python 代码.请查阅相关的关于在Python的C实现中C代码风格指南的描述. 这篇文档改编自Guido最初的《Python风格指南...

索隆
2012/04/24
0
0
提供一致的 Spring 风格的 Java 插件 - Spring Java Format

Spring Java Format 一组插件,可应用于任何 Java 项目以提供一致的 “Spring” 风格。 该组目前包括: 应用包装和空白约定的源格式化程序 一个 checkstyle 插件,可以强化整个代码库的一致性...

匿名
05/25
0
0
Zsh 开发指南(第二十篇 代码风格)

导读 因为 shell 脚本语法比较灵活,写 shell 脚本的开发者熟悉的编程语言也有较大差异,大家很容易写出风格迥异的代码出来。如果只有自己一个人用还好,如果是大家合作开发同一个项目,代码...

陌辞寒
2017/09/20
0
0
Kotlin编码规范

最近项目中开始慢慢使用Kotlin编写代码,对于一些规范还是必要地。 资料原文:http://www.kotlinlang.org/docs/reference/coding-conventions.html 命名风格 如果拿不准的时候,默认使用Jav...

sinat_36668731
2017/08/09
0
0
升级 Java 编程规范的6个约定

作为 Java 开发人员,我们会遵循一系列的编码风格和开发习惯。习惯使然是一方面,另一方面,我们也从不停下脚步质疑这些习惯。一段时间以后,笔者养成了一些不同于常人的编码风格和开发习惯。...

OneAPM蓝海讯通
2016/01/11
64
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

SpringBoot | 第十章:Swagger2的集成和使用

前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成。现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的...

oKong
今天
2
0
Python 最小二乘法 拟合 二次曲线

Python 二次拟合 随机生成数据,并且加上噪声干扰 构造需要拟合的函数形式,使用最小二乘法进行拟合 输出拟合后的参数 将拟合后的函数与原始数据绘图后进行对比 import numpy as npimport...

阿豪boy
今天
1
0
云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
昨天
1
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
昨天
158
1
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
昨天
1
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
昨天
1
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
昨天
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
昨天
2
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
昨天
2
0
开发技术瓶颈期,如何突破

前言 读书、学习的那些事情,以前我也陆续叨叨了不少,但总觉得 “学习方法” 就是一个永远在路上的话题。个人的能力、经验积累与习惯方法不尽相同,而且一篇文章甚至一本书都很难将学习方法...

_小迷糊
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部