0

Statics, consts and singletons are considered a bad practice because they obstruct testing, and create a maintenance problem due to references in various places. In a mini-framework for websites, I am running into these problems and want to replace the statics, but don't know the best alternative in one use case.

This use case is illustrated by a permissions system based on groups: for a client C to have access to data item X, a group name in C's array of authorization group names must match one in X's array of "required" names.

Comparisons ("does the client have this auth?") can be easily abstracted out to a dynamic calls. But when assigning a group name to a client, or assigning a "required" group name on a data item, how can I refer to them individually and police that each is from a centrally defined set, without statics?

Current code looks like:

$client->appendAuzGroupName( Tokens::AUZ_GRP_PUBLIC );

-- with Tokens loading values from a config file at each cache refresh.

Searching here and on the web has turned up a lot of advice against static/const/singleton, but the only idea I've found on replacing them is "use IoC / DI". However, taking these values via params only moves the problem to a different place in the code.

I'm open to changing to another auth system design, but it must have this level of granularity, and listing usernames (ACL design) seems unlikely to be practical at scale.

  • Maybe I'm misunderstanding, but don't you want to store all these values in the database? – grebneke Jan 24 '14 at 20:33
  • I guess your Tokens are read-only and are read from config once? Seems like your current setup using static is absolutely fine. Why take a simple, workable, maintainable solution and add complexity with IoC? – Steve Claridge Jan 24 '14 at 20:38
  • @grebneke, It's a small and rarely changing set, isn't it best not to incur the I/O on every request? – neochipmonk Jan 24 '14 at 20:46
  • @Steve, the current design prevents unit testing, and if the list of values changes will require finding all the references in multiple classes. – neochipmonk Jan 24 '14 at 20:46
  • @neochipmonk: That depends on your application and configuration needs. If it rarely changes and your users don't mind editing config files - just go for what works and ignore both database + IoC/DI buzzwords. You must judge for yourself what is reasonable. – grebneke Jan 24 '14 at 20:52
  • @neochipmonk I'm not disagreeing with you as such but I'm genuinely interested to read some explanation of how this stops testing? I can see how excessive static or singleton use would case hassles but this seems like the perfect use-case for static to me. – Steve Claridge Jan 24 '14 at 20:57
  • E.g. http://googletesting.blogspot.com/2008/12/static-methods-are-death-to-testability.html , http://stackoverflow.com/questions/10632975/static-class-method-property-in-unit-test-stop-it-or-not , http://blog.socosomi.com/how-to-unit-test-code-calling-a-static-method/ , http://www.jramoyo.com/2013/03/static-methods-and-unit-testing.html – neochipmonk Jan 24 '14 at 21:34

1 Answers1

0

OK I may have solved my own problem.

  1. The class Tokens will have a public constructor, private static array for the values from XML (which is written by admin interface), public methods to retrieve them; it loads the values on instantiation iff they are not already loaded.

  2. Some small facility to gather subsets of values from Tokens, for example the list of authorization group names, and deliver an object (of a class TokenSet or such) containing them

  3. These 'sets of values' are passed in function calls, e.g. to give the admin interface a set of choices to be applied for each new page's 'required' permission levels.

Thus instead of directly accessing stored-in-memory values, object that needs to use them will get, as parameter, an object containing a relevant set of them. This will be testable and avoid hardcoded references that would create dependencies and maintenance issues.