代码结构的实例指南

50 阅读5分钟

这个帖子已经被存档了,因为我已经不做这个了。

你的代码应该像报纸文章一样阅读。重要的东西在上面,细节在下面。我对我的代码有一个特别的约定,利用JavaScript的一些怪癖来产生许多可消费的代码。我希望我的代码能够被人们轻松地阅读,不管他们的编辑器是什么(或者根本不需要编辑器,比如在GitHub上)。

这里有一个我经常看到的写代码的常用方法。假设你需要使用这个模块。看看你能以多快的速度找出这个模块的api(以及模块的对象):

export const bar = {
  some: 'property',
  someFunction() {
    // with plenty of lines
    // and more stuff
    // because... reasons...
  },
  someOtherFunction() {
    // because we need it
    // it's really important...
  },
  someOtherProperty: true,
  anotherFunction() {
    // forgot about this one...
    // why is it here, instead of at top?
    // who knows... Doesn't affect functionality right?
    // but it might impact readability...
    // especially if it gets long and stuff
  },
  dontForgetMe: '!!!!',
  ohWaitNeedThisToo() {
    // yet another function
    // man, I need a few of these don't I?
    // what other functions does this "bar" thing have?
    // does this file export anything else? I guess I'll have to search around and find out...
  },
}

export function longFunction() {
  // I could really use a doughnut right now...
  // Sometimes functions need to do a lot of things
  // You should keep these functions short
  // Otherwise your code is hard for a reader to consume...
  // and that makes me sad :-(
  // and confused
}

export function meToo() {
  // make sure you scroll around the file
  // so you know EVERYTHING that this module exports
  // Because with this method, discovering that is a little difficult.
  // There's gotta be a better way!
}

export const thereIsABetterWay = true

问题出在哪里?

我希望我在那里的代码的注释中说明了这个问题。主要的问题是当我来维护这个文件,甚至消费它的时候。我很难知道进入这个模块的API是什么。这只是使推理该代码变得更加困难。我个人也认为它更难读,但这可能只是因为我现在已经习惯了自己的方法。

这是真的吗?

我曾经在一个巨大的Backbone应用程序上工作(15万行以上的代码)。我们的许多Backbone.View看起来很像这个文件中的吧(真的很高,很难知道视图上有什么功能)。事实上,应用程序中最糟糕的一个视图有2000多行的代码!现在大家都知道这是一个糟糕的做法。现在大家都知道,一般来说,这是一种不好的做法。但是,即使它有那么长,使用我建议的不同方法也会对维护这个怪物有很大的帮助。

一个不同的方法...

现在,看看你能以多快的速度确定重写的模块的api(有些评论是不同的,所以也要阅读这些评论)。

const bar = getBar()
const thereIsABetterWay = true

export {bar, longFunction, meToo, thereIsABetterWay}

// function declarations
function getBar() {
  // main "export" for the function
  return {
    some: 'property',
    someFunction,
    someOtherFunction,
    someOtherProperty: true,
    anotherFunction,
    dontForgetMe: '!!!!',
    ohWaitNeedThisToo,
  }

  // function declarations
  function someFunction() {
    // with plenty of lines
    // and more stuff
    // but I don't mind anymore, because I only read this if I'm interested in it
  }

  function someOtherFunction() {
    // because we need it
    // it's really important...
  }

  function anotherFunction() {
    // forgot about this one...
    // why is it here, instead of at top?
    // who knows... Doesn't affect functionality right?
    // it doesn't actually make a difference
    // even if it gets long and stuff
  }

  function ohWaitNeedThisToo() {
    // yet another function
    // man, I need a few of these don't I?
    // what other functions does this "bar" thing have?
    // I know just by looking at the top of the enclosing function... It's obvious... Important stuff at top, details at bottom
  }
}

function longFunction() {
  // I could really use a doughnut right now...
  // Sometimes functions need to do a lot of things
  // You should keep these functions short
  // Otherwise your code is hard for a reader to consume...
  // and that makes me sad :-(
  // and confused... But at least I know what the API is and it'll make consuming and maintaining this file much easier
}

function meToo() {
  // Don't need to make sure you scroll around the file
  // so you know EVERYTHING that this module exports
  // Because with this method, discovering the exports is obvious
  // It's just at the top of the file. What I see when I first open it up
}

为什么这样做更好?

希望我在代码的注释中解释得足够清楚,但你应该注意到,从文件的顶部开始,知道这个模块的API是什么就容易多了。如果我负责维护这个模块或使用它的API,我就知道该从这个文件中得到什么。

注意,这是在JavaScript中利用了函数声明的 "怪癖",基本上相当于把函数定义和声明挂在了闭包的顶部。这就是为什么你可以把函数声明放在返回语句之后。

那ES6类和/或这个呢?

这一点在类中有所突破,因为它们必须像这样结构化。

export default class Person {
  constructor() {}
  walk() {}
  talk() {}
}

同样,这些函数会变得很长,而且你的情况和第一个代码样本差不多。这是我个人对类的不满之一。很多人都说你的IDE应该帮助你,但如果你只是在GitHub上看代码,你的IDE并没有什么帮助,这对我来说很重要,因为我在那里很投入,而且对我来说,我并不强制要求人们使用什么编辑器/IDE,而且任何人都可以使用它。

那么解决方案是什么呢?说实话,我也不知道。我想说的是,解决方案就是保持你的代码干净和简短,但根据我的经验,我发现这有时并不能解决问题。

保持文件/功能小

如果你保持你的文件和函数小,这些问题大多会消失。但有时这很难做到,抽象的东西只能让你走到这一步。 我使用这种代码结构,即使我的代码量很小。

结尾

谢谢你的阅读!