Created
July 23, 2012 12:58
-
-
Save wereHamster/3163506 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package models | |
/* A scope defines what actions a user can perform. Each possible action is | |
* assigned a bit in a bitset (up to 64 different actions are possible in | |
* theory, though we only store a limited number of bits in the database). | |
*/ | |
sealed case class Scope(value: Long) { | |
/* Combine two scopes. Does a bitwise or of the two bitsets and returns a | |
* new scope. | |
*/ | |
def |(x: Scope): Scope = | |
Scope(this.value | x.value) | |
/* Return true if `this` includes the given scope. */ | |
def includes(x: Scope): Boolean = | |
(this.value & x.value) == x.value | |
} | |
object Empty extends Scope(0) | |
object All extends Scope(0xFFFFFFFF) | |
object Read extends Scope(1) | |
object Write extends Scope(2) | |
object Query extends Scope(4) |
I was hoping to hide the implementation detail and only expose the Scope
type and the instances.
OK. I was just reacting to the comments on the public methods, which described the implementation.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hmm...to me it seems that the abstraction is leaking too many implementation details. Abstractly, what you are modelling is that a
Scope
is a finite set ofAction
s. For eachAction
you can test whether it is a member of aScope
or not.Scope
s offer the usual set operations.Your construction of offering an
Empty
scope and anAll
scope corresponds to the observation thatScope
s also form a bounded lattice where join is interpreted as a set union, meet as set intersection, top as the set of all actions, and bottom as the empty set of actions.I'm not advocating that you should use this terminology. It might scare some people ;-) The benefit of making this connection is that you immediately get all theorems and algorithms that work with bounded lattices for free. Moreover, it becomes easy to see what operations make sense to offer. In Haskell, you'd additionally make an instance of BoundedLattice and get the operations like
meets
for free. For example,meets :: [Scope] -> Scope
would correspond to taking the least privileges of a list of scopes. You'd use that for example when computing the scope of a list of objects, which you edit jointly.Anyways, I think that your documentation should mention the 64bit limitation at most as a side-note. The key abstraction is that of a bounded lattice of actions that you can perform and not that of a list of at most 64 bits that denote actions that you can perform.