我们使用 JavaScript 的新产品尽可能发挥功能。我有一个具有 tokenPromise
的身份验证模块,只要用户登录或刷新 token ,它就会更新。看来我们必须允许突变。
我没有将 tokenPromise
放在模块级别,而是创建了一个仅包含限制状态变化方式的高级函数的类。其他纯辅助函数(或至少不需要改变状态)在类之外。这似乎有助于推断成员何时可能发生变化 - 它与可能改变它的所有操作位于同一位置。
我还没有找到这种模式的其他例子 - 这被认为是好的做法,还是我们应该考虑另一种方式?这是包含从 Authentication.ts 导出的可变数据的类。
export default class Authentication {
public static async getAuthToken(): Promise<string> {
if (!this.tokenPromise || await hasExpired(this.tokenPromise)) {
// Either we've never fetched, or memory was cleared, or expired
this.tokenPromise = getUpdatedTokenPromise();
}
return (await this.tokenPromise).idToken;
}
public static async logOut(): Promise<void> {
this.tokenPromise = null;
await LocalStorage.clearAuthCredentials();
// Just restart to log out for now
RNRestart.Restart();
}
private static tokenPromise: Promise<IAuthToken> | null;
}
// After, at the module level, we define all helper functions that don't need to mutate this module's state - getUpdatedAuthToken(), etc.
一个可能的原则似乎是:让具有可变状态的对象尽可能紧凑,只公开高级紧凑方法来改变状态(例如 logOut 和 refreshAuthToken,而不是获取/设置 authToken)。
最佳答案
I've created a class that only contains high-level functions that limit how the state can be mutated. This seems to help a lot in reasoning about when the member might change - it is colocated with all operations that might change it.
是的,这是 OOP 中的标准最佳实践 - separation of concerns通过 encapsulation状态变为对象。对象(类)之外的任何其他代码都不能改变它。
Other helper functions which are pure (or at least don't need to mutate state) are outside the class.
我不会走那么远。您也应该将属于类实例的辅助函数(方法?)放在类上,或者至少放在它的直接附近——尽管将它们放在同一个模块中可能就足够了。特别是当他们访问对象的“私有(private)”部分时。为了仅区分纯函数和不纯函数,您还可以对纯方法使用 get
前缀等约定。
另一种方法是为您的类提供一个单独的不可变接口(interface),它只包含纯方法。您可以将其作为第二个 class
声明,并使用一种方法在表示之间进行转换。
exposing only high-level compact methods to mutate state
我认为这不完全正确。您还隐含地公开了一些访问状态的方法(然后纯辅助函数将使用它),对吧?您不妨明确说明这些内容。
在处理可变状态时,写入和读取的顺序不仅对内部 View (哪些部分发生变化)很重要,而且对外部 View (整个对象状态何时发生变化)也很重要。一些约定,例如“属性(和 getter)是纯的,方法可能是不纯的”会有很大帮助。
关于javascript - 将修改器封装在 JS 模块内的类中是一种好习惯吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45894937/