Tag Archive for 'Design Patterns'

Interest(ing) rates

The most common way of investing money is putting it in a savings account. You lend a fixed amount of money to someone, and they pay interest over that money at a predetermined rate. Let’s say you lend 1,000 € at an interest rate of 3%, paid every year: at the end of the year, you would receive 30 € as payment for your lending. You would spend these on fine wine or nice clothes and wait until the next year to get another 30 €, and so on.

Savings accounts work on the basis of simple interest : what you get paid is a linear function of both time and money. Lend for half a year? 3% ÷ 2 = 1.5% Lend for two years? 3% ×2 = 6%

An important thing to bear in mind is that interest is paid at fixed intervals, for instance at the beginning of January. You don’t have to spend those 30 € : you can them on the savings account and earn simple interest on them after a year (3% of 30 € is 0.90 €).

Using this strategy, lending for two years is done at a 6.09% rate instead of 6%, because you get interest on interest. This is known as compound interest : what you get paid is an exponential function of time. Lend for two years ? (+3%)² = +6.09% Lend for three years ? (+3%)³ = +9,27%

The mathematical justification is that, with a 3% interest, your total amount of money is multiplied by 1.03 every year:

1,000 + 30 = 1,000 + 3% of 1,000 = 1,000 + 0.03 × 1,000 = 1.03 × 1,000

So, after two years, the amount is multiplied by 1.03 two times, and so on.

1,060.90 = 1.03 × 1,030 = 1.03 × 1.03 × 1,000

In short, percentages have a multiplicative effect.

And now, pop quiz : I’ve gained +5% weight over the winter holidays. What percentage of my weight do I have to lose to be back to normal ?

If you answered -5%, you missed the point. Multiplicative effect means the total change of weight would be +5% × -5% = 1.05 × 0.95 = 0.9975 = -0.25%. I would be losing too much weight !

The correct answer was 1 ÷ 1.05 = -4.76%.

Similarly, if the number of graduates of a given school increases by +10% on year one and +25% on year two, the total increase is +37.5% and not +35%.

Duality

This is where mathematicians (and computer scientists) use an interesting little concept called duality. Percentages are numbers that are easy to understand, but hard to combine. We can transform them into something that is a little bit harder to understand, but easier to combine.

The traditional way to transform multiplication into addition is to exponentiate, due to an interesting property of the exponential function:

exp(a) ×exp(b) = exp(a + b)

So, I wish to find a percentage operator (§) such that:

  • we conserve some values, 0§ = 0% and 100§ = 100%
  • applying A§, then B§, is equivalent to applying (A+B)§

Then this uniquely defines an operator which is called exponential percentage:

A§ = B%  ↔  A = 100 × log(1 + B ÷ 100) ÷ log(2)

Some common values:

0% = 0§ +100% = +100§ -100% = -∞§ 200% = 158.4§
+1% = +1.4§ +99% = +99.2§ -1% = -1.4§ -99% = -664§
+10% = +13.7§ +90% = +92.6§ -10% = -15.2§ -90% = -332§
+25% = +32.2§ +75% = +80.7§ +50% = +58.4§ -50% = -100§

percent

So, if I gained +5§ weight over the holidays, I can lose -5§ weight and be back to where I started, and if a number increases by 10§, then by 25§, it increases by 35§ overall.

And of course, a yearly interest rate of 4.2§ = 3% compounded over ten years is 42§ = 34%.

No Free Lunch

Normal percentage rules make compounding hard, but it’s reasonably easy to estimate a percentage based on a fraction. Exponential percentage rules make compounding easy, but evaluating a percentage based on real figures is harder.

In practice, compounding happens less often than evaluating, so humans use normal percentage rules. And computers are good at compounding through multiplication, so they don’t need exponentiation.

Duality does have some other uses, though. For instance, there’s the duality between two representations of complex numbers:

a + ib = r exp iθ

The cartesian (a,b) notation makes it easier to add numbers, but multiplication is harder:

a + ib + c + id = (a+c) + i(b+d)

The polar (r,θ) notation makes it easier to multiply numbers, but addition is harder:

r exp iθ × s exp iφ = (r × s) exp i(θ+φ)

For mathematically-oriented computer scientists, duality is a gold mine, because it lets one reduce a complex problem in one area to a simpler problem in another area (whether simpler means faster, as in the case of FFT, or easier to think about)..

The Law of DSLs

There’s one common duality that is fundamental in the computer world: the correspondence between data and code. In a fit of narcissism, let me sit wisely atop a tall mountain to announce Nicollet’s Law of Domain Specific Languages:

Any sufficiently complex data processing algorithm is as an interpreter for a small domain-specific language, and the data being processed is a program executed by the interpreter.

In some cases, this law only complicates things further. In many cases, however, the different angle it provides leads to many advantages, one of them being to transform a non-programming concept (such as an accounting file format) into a concept programmers are familiar with (a programming language).

A minimalist language design culture is enough to grasp several interesting concepts about executing code, which can be quite handy when processing data:

1. Compile to Bytecode

Interpreters don’t execute a string of characters. They tokenize that string, turn the tokens into an abstract syntax tree representing operations, functions and variables, then turn that syntax tree into a sequence of small, executable operations. That sequence is then fed into a virtual machine (or further compiled to machine code) to perform the actual operations.

If the input data for your algorithm is very complex, you can begin on the other side: what will the algorithm do with the data? Will it be inserting the data into a database? Constructing a data object from bits and pieces? What you are looking for is a set of atomic operations you can apply to generate the result. Implement these operations, then start working on a translation algorithm to turn the input data into such operations.

There are several common and friendly representations for such atomic bytecode:

Instruction lists are executed in order. This is your classic assembler listing, without the jumps. A typical “parse file and insert into database” algorithm would generate such an instruction list, and every instruction would be an INSERT, DELETE or UPDATE. Works best when you can read the data and generate the instructions in the right order: if you cannot get the list in the right order from the start, consider another approach.

Dependency graphs work like makefiles: you have several instruction lists floating around with relationships between them, indicating that one list has to be executed before another. A topological sort of the graph results in a single classic instruction list you can execute. A multi-file import, where some files contain data needed in other files, can be the way to go.

Nested scopes are the typical extension to instruction lists: every item in a list can be either an instruction, or another list, possibly tagged with some data. This could be a conditional (if this condition is true, execute this list), a loop (though it is best to avoid these) or a context (a “polygon” scope contains “insert vertex” operations that apply to that polygon). You can even allow variables in a let-in fashion (of which the polygon example above is just a special case) ! Note that nested scopes can be easily represented as XML.

2. Static Analysis

A side-effect of compiling to bytecode is that you get to process the entire file before you actually perform the intended operations. This makes a rollback easier if you notice that there’s an error on the last line of the file: if you make sure that no atomic operation in your target language can fail due to bad input (such as incorrect data values), then you can check your input data for correctness without doing anything to your program state.

Even better, if your compilation process is cheap (linearly traverse a file for parsing) and you have heuristics for predicting how much time and resources your individual instructions require, then you can try to accurately predict the needs of the entire process.

Static analysis also means you can optimize. If, for instance, you’re inserting data into a database and need to resolve names or keys frequently (such as “add this item to list #732″), you can easily construct a table of needed keys (that you can get in one query when the processing starts) using the dependency graph approach.You can also optimize resource allocation by using common register allocation techniques: sort your dependency graph to keep as few resources in memory as possible at any given time.

3. Caching

Try to perform most of the processing offline.

For instance, if you frequently “apply” one file to another, such as a nearly-constant “list of categories” file used to resolve the “category” key in a daily object import, you can benefit from compiling the nearly-constant file to an easily loaded, easily applied format.

You see a cached dictionary that maps keys to categories? I see a DSL that allows dictionary literals as part of the language, and a source file that contains a literal mapping keys to categories, with an interpreter that can apply constant propagation to dictionaries.

Another benefit is when applying changes to mission-critical software. Inserting lots of data into a web database can create a heavy load on the server and make the site unavailable to visitors. It might therefore be preferrable to pre-compile the imported data into requests through a process that keeps a light load on the server, then run the requests.

Besides, with proper nested scoping, you can slice an import into several transactions. This keeps the lock count low, allows spreading the transactions over time to reduce the load, and lets you resume the import process if, for some reason, it gets interrupted.

Information Flow

The real world is a complex place. When writing software that has to interact with the real world, there are literally thousands of concepts you have to master and tens of thousands of details you have to be aware of, or you will paint yourself into a corner where your software clashes with reality. And reality always wins.

Understanding concepts and details is a fundamental part of a project’s time budget, whether they come from the project requirements, real-world constraints, third party code or teammates. Every time information goes around in a project, it uses up valuable time, and to keep the time budget tight it becomes necessary to decide what information should be allowed to go around, and where.

Working on concurrent systems is an enlightening experience, because of the many similarities between an array of computers and a team of information workers. Computers arrays have latency issues when one thread depends on another thread to be done…

“When do you think your settings import module will be done? I’m stuck on the payment API until I can load those settings!„

…they have bandwidth issues and manipulating some data yourself is usually faster than sending the data to another part of the cluster for treatment…

“The User object? Well, it’s a bit of a weird design, but it’s rather clever. I’ll draw you a quick UML sketch on the blackboard so you can see what the five helper classes do.„

…they have to avoid data loss if a computer or network is down…

“I have no idea how this stored procedure works, you should ask Tim, he’s the one who wrote it. He’s in southern France right now but I think he’ll be back next month.„

… and they have to handle a directory of parts and a garbage collector for data…

“Wait, nobody’s written the comment moderation back-office! Who was in charge of doing it? Who wrote the comments front-end anyway?„

There are algorithms, strategies and techniques for handling and optimizing those things. Many of these can be adapted to humans, with the added benefit that, humans being smart, they can understand the point of those algorithms and compensate for minor flaws if the plan isn’t perfect.

Destroy After Use

Exceptions make the control flow of a program quite complex, since any call could possibly create an exception and thus leave the currently executing function. Even with a garbage collector, certain resources (such as files) have to be manually released. Some languages use destructors and RAII (for instance, C++) to handle scope-based release, others use an explicit using(){} or finally {} block to also add a scope to such resources.

None of this exists in OCaml.

It can be rather easily reconstructed using existing language semantics, however:

let scoped user resource clean =
  try
    let result = user resource in
    clean resource ;
    result
  with exn ->
    clean resource ;
    raise exn 

let with_input name f =
  scoped f (open_in_bin name) close_in 

let with_output name f =
  scoped f (open_out_bin name) close_out

The Missing Link

In paleontology, a missing link is a transitional fossil that fills the evolutionary gap between two recognized species, both in time and in phenotype.

Quite frequently in the course of software development, certain parts of a program are deemed global at some point in time: there never ought to be a need for more than one instance, nor the need for polymorphic handling of a similar yet distinct part. And sometimes, but not always, this initial impression is proven wrong, and the need for more than one instance arises. The consequences of such an error are usually quite extreme: a one-of global entity tends to be referenced by name, requiring a refactoring effort to convert it to a parameter everywhere this is needed. And so, developers are given the choice between going with the initial impression (with the risk of having to convert it) or ignore the initial impression (and spend time on something they might never need).

I propose here a missing link, a third alternative which implements a one-instance form with minimal effort, yet can be easily refactored into a several-instance if the need arises.

Of course, this applies only in situations where a doubt exists. If it is obvious right away that a given entity will be a several-instance entity, then it should be written as such from the beginning. Only in situations where the current state of the design (especially in Agile methodologies) only requires a single instance should this missing link be considered.

But first, a few background information about this.

Procedural and Objective

A while ago, I wrote a short article that discussed how procedural programming approached the issue of global state. The basic conclusions were that by grouping global state into modules, the number of possible interactions decreased, and those that occurred were made obvious by the structure of the code. As such, a procedural program is a set of stateful entities that interact with each other along a dependency graph.

So is an object-oriented program: stateful objects reference each other and communicate through message-passing. At runtime, there is therefore no major difference in this respect between an object-oriented program and a non-objective procedural program. The main difference is elsewhere. Objects, unlike modules, are rarely defined in the code: they are usually created dynamically at runtime. So, while the two dependency graphs may look the same, the object-oriented runtime dependency graph is a purely dynamic construct that can be altered at will, whereas the procedural runtime dependency graph is a static construct that is tightly mapped to the structure of the code.

Keep It Simple, BridgeThe extensibility of object-oriented programming comes from the dynamic aspects of its dependency graph: if objects can be created, replaced and removed at will, even by the program itself, then the program will have a flexibility and adaptability that exceeds the static module skeleton of a traditional procedural program. On the other hand, the static module skeleton is easier to design and implement than a fully flexible object architecture where elements can be hotplugged—even with language support for object-oriented programming.

When you have to build a bridge, you don’t build a fully automated moving bridge just for the fun of it: if the simplest thing that could possibly work is a plain old suspended bridge with no moving parts, then this is what you do.

Remember that we’re considering here the case of a one-instance object being converted to a multiple-instance object even though there is no apparent need for it yet. Why is that more difficult than using the one instance directly?

  • Polymorphism requires abstraction, and abstraction usually comes from having several instances—then you can identify what’s general and what’s specific. Trying to abstract a concept from a single instance will miss some general aspects that could have been useful, and keep some specific aspects that will limit extensibility.
  • It’s easier to program something which makes sense. If having multiple instances does not make sense yet, then the programmer cannot rely on his instinct or his intuition to determine whether what he’s writing works or not, and the single-instance assumption might fight its way stealthily into the program anyway. Testing a multi-instance system when you only have one instance is quite difficult, too.
  • When using multiple instances, one has to consider what scope they should exist in, and how they are propagated down. Of course, there’s the code required to have the multiple instances trickle down to where they are used. But the real difficulty is deciding what the correct scope is—and since there isn’t a reason yet to consider multiple non-global instances, it’s quite probable that such a decision will turn out to be wrong in the end anyway.
  • Handling a flexible design is harder, mentally, than handling a fixed design. In a static module skeleton, the dependencies are clear and, when they are not, can be extracted from the code very easily. In a dynamic dependency graph, one has to think about how that graph will be constructed at runtime before they know whether a certain piece of code can affect a certain concept (especially if that concept is still a one-instance global).

As such, delaying the setup of a flexible and dynamic dependency graph as long as possible reduces the amount and difficulty of development efforts. The downside, of course, is the refactoring effort required if the initial assumption is proven wrong. A solution to this conundrum would keep the conceptual simplicity of a single-instance static skeleton, while having a code layout that can be easily changed to a multi-instance dynamic graph as soon as the reasons for such a change are discovered.

Singletons?

While often used to implement single-instance cases, the Singleton design pattern does not solve this issue: it is a pattern for representing the single instance, and the problem here is related to how the rest of the program refers to the instance. If all your code uses a certain instance by name, it does not matter whether that instance is a global variable or the instance of a singleton class: that code cannot use a second instance until it uses that instance by reference, and that reference is a parameter of some kind.

So, the choice of a singleton (or any other approach) to represent the instance is completely independent of any solution that could be found to this problem.

Bottom-Up Construction

An approach which can be used in many cases and leads to avoidance of single instances is bottom-up development. Since the system is being built bottom-up, most of the time when a module would need to access a single instance, that single instance has not yet been written or even designed yet. In that situation, the correct approach is to create an interface representing what the module expects, and have a parameter somewhere to receive an instance implementing that interface. Then, when the single instance is finally designed, it can be made to implement that interface (or adapt to it) and then passed as an argument to the relevant elements.

Bottom-up construction eliminates many of the problems related to handling single instances. That is, by refusing to assume anything about the object being used beyond its interface (including, of course, how many instances exist that implement that interface) development automatically deviates from the single-instance approach and can handle multiple instances automatically.

This does not solve everything, however. Bottom-up construction is notoriously ill adapted to fast development cycles, because the actual functionality of the program appears only when the top-level objects have been developed, which is at the end of the cycle. By contrast, with a top-down approach, the top-level object can be developed first and filled with mocks, and the mocks replaced with the actual functionality on the fly. Besides, bottom-up construction is also subject to violating YAGNI, because objects are created before their users exist (and may end up not existing at all).

The Missing Link

The key of the problem here is that directly converting a single-instance approach to a multiple-instance approach requires a lot of argument-passing: since the instances are manipulated through references, and those references are parameters, a lot of parameters are required to pass the instance from its point of creation (quite probably somewhere near the entry point) down to every part of the program that uses it. A possible solution would be do to as much of that work as possible (replacing as many of the global accesses as possible with references) without having to heavily increase the number of parameters.

Aside from global symbols, one other kind of value is available in functions without being passed as a parameter: member variables.

The Screen Design Pattern

The problem: methods of a class needs to access a global variable directly. Making that variable non-global is unnecessary right now, but might be necessary in the future.

The solution: have the class keep a screen member reference to the global variable. That reference is initialized in the constructor and used everywhere else. Member functions other than the constructor are never allowed to reference global variables.

What would be an example of refactoring using this pattern? Consider the original C# code:

public class GlobalUser
{
  public GlobalUser() {}
  public void MethodA() { Global.Instance.Use(); }
  public void MethodB() { Global.Instance.Use(); }
}

Methods in this code use a global instance. Let’s replace that with a member reference to the global instance:

public class GlobalUser
{
  private Global screen;
  public GlobalUser() { this.screen = Global.Instance; }
  public void MethodA() { this.screen.Use(); }
  public void MethodB() { this.screen.Use(); }
}

Using the pattern, the refactored code can be written straight away (instead of writing the original code and then refactoring it) without requiring mental effort, which means that using the pattern bears almost no cost (it only requires an additional member variable and an additional assignment in the constructor). And if the screened variable suddenly has to become non-global, only the constructor will be affected, saving precious time that would have been lost refactoring the methods as well.

Note that creating a property which returns the global variable (instead of a member variable assigned in the constructor) is equivalent in terms of writing the initial refactored code (the this.screen = Global.Instance is replaced with { get { return Global.Instance; } }), but does not have the same benefits when refactoring to remove the global instance because a connection will have to be made between the value returned by the property and the parameter received in the constructor, which requires more code. I therefore suggest using a member variable assigned in the constructor instead of a property.

Also note that the above can be seen as the preliminary step of a dependency injection and follows the same general idea as preparing your application for Spring.NET integration (for example). The difference is that the pattern does so at the class scale, and emphasizes development speed (using the pattern should be no slower than using the non-pattern approach) rather than external interoperability and flexibility.

Memory issues

Of course, storing a screen reference in every object might not be welcome. Some very small objects, such as vectors or polygons, cannot afford to store an additional reference because of the time and space overhead this would imply.

My suggestion in these situations is as follows: eliminate the global dependency altogether. Resist the temptation to have a certain small object frobnicate itself using a global instance, and instead have a larger object frobnicate the small objects. This makes the optimization more transparent (the small objects are now just bits of data without any kind of polymorphic behavior that are externally manipulated) and allows using the Screen design pattern on the larger object.

The Window Tax

In 1798, the French Directoire instituted a new tax, called “la taxe sur les portes et fenêtres” (quite literally, the tax on doors and windows). Back then, the young republic did not yet have the means to closely examine the income and possessions of all taxpayers in order to determine how much each of them should pay, yet it wanted those who could afford to pay more to actually pay more. Doors and windows were an obvious sign of wealth that could be easily evaluated by the tax collector without having to enter the house, and since the taxpayers often did not have access to estate ownership titles having the tax be paid by the occupant helped things significantly.

Neon sign tax?Of course, soon after the tax appeared, people reduced the number of windows and doors, sometimes going as far as wall every doors but one, and brick-up all the windows.

A similar thing happened in France in the 1990s: until then, insurance for work accidents was provided equally to all companies, and all companies paid the same flat rate based on the national accident rate. In an effort to make large companies pay for improved safety measures (because they had the funds for it), the insurance rate became deregulated for companies above a certain size, so that a large unsafe company paid more than if it was safe. Small companies still paid a national rate.

Unlike what was expected, most large companies spent no money on safety and instead outsourced dangerous jobs to small companies, thereby improving their own rates. And since small companies often had worse safety than large companies, the overall workplace safety slightly decreased as a consequence of this deregulation.

The same happens in the computer world. When your log software advertises a thousand visitors per day, it simply hides the fact that HTTP has no notion of visitor:

  • A given person may use several computers and IP addresses to visit the same site.
  • A given person may use a proxy cache to read the website without having to connect to it.
  • The same IP address may be shared by several people (by ISP shuffling, on public computers and on LANs).

Similarly, when your download client displays a download speed, it’s quite probably an average over the last few seconds, meaning that if you are suddenly disconnected from the network, the download speed will remain above zero for a short while.

Of course, every user of the HTTP protocol knows, deep down, that HTTP has no notion of visitor and therefore a visitor is just a set of requests from the same IP over a given duration, just like every user of a download client can understand that download speed is an approximation and isn’t really above zero when there is no network connection.

Yet, it’s quite easy to forget.

An example upon which I’ve stumbled recently was a paying web site. Paying users were allowed access to some functionalities of the website, so there was a test performed on every of these pages to see if the user account was associated to valid payment information before displaying the page. Nothing too fancy, a mere if(user.Subscribed) test that didn’t deserve factoring out. Then, one day, marketing suggested adding a temporary test account that could be used for a limited duration to allow using those functionalities.

The obvious problem is that the previous assumption “only paying users can read this page” that was spread all over the system became incorrect. Cheating by changing the definition of user.Subscribed was impossible, because subscribed users have valid payment information but test accounts don’t. So, a new test had to be added to every page: if(user.Subscribed || user.TestAccount). Over a few months, the test became increasingly large as new properties were added for access.

Luckily enough, a sane developer came around and refactored the thing as an if(Functionality.IsAllowed(user)) function which allowed changing the access restrictions for these pages in a single place, and developers from that team learned not to make explicit assumptions within the code, not even on extremely simple tests.

The Window Tax Antipattern

The Window Tax Antipattern can appear when:

  • A given module provides a piece of information, Provided.
  • A rule (that is neither a consequence of the definition of that module nor an absolute truth) describes how another piece of information, Deduced, can be deduced from Provided.
  • Other modules use Deduced by manually deducing it from Provided.

In such a situation, if the rule changes, the deduction becomes incorrect and every module which uses the deduced information will have to be changed as well. As an additional issue, since the deduction is not explicit, finding every module that makes that deduction is often difficult. The solution is to identify the rule, and wrap it in a function that constructs Deduced from Provided (thereby allowing easier refactoring should the rule change).

In our above examples:

  • The provided information is the number of doors and windows, and the rule states that wealth can be deduced from that number.
  • The provided information is the accident rate, and the rule states that the safety of workers can be deduced from that rate.
  • The provided information is whether the user has a paying account, and the rule states that the page can be viewed only by users with paying accounts.

In some cases, the antipattern does not apply. For instance, if the rule is a consequence of the definition of the original module, then the rule cannot change unless the underlying module also changes (which is an acceptable reason for refactoring). So, if the rule is “when you push an element onto a stack, the stack is not empty until you pop it”, then assuming that a stack onto which you just pushed an element is not empty is not a problem (until, of course, either you or another part of the program pops that element).

However, every single business rule (those that can be changed by management, marketing, clients or even laws) is potentially subject to this antipattern unless cleanly wrapped.

In an environment that is heavy on business rules, the Adapter pattern becomes of particular interest. Since every object usually cares about information that is not directly contained in another object business rules crystallize as adapters around objects, providing the information that the current object requires (for instance, “can this user view this page?”) based on the information that the other object and its environment provides (for instance, “is this a test or paying account?”). View with suspicion every direct interaction between two business objects, and never hesitate to insert adapters or explicit rules whenever the used information is not a direct, obvious and inevitable consequence the provided information.

Singletons

A singleton is a way of designing a part of an object-oriented system that was used frequently enough to deserve its own name: the Singleton Design Pattern. In practice, a singleton is a class which can only have one instance at any given time, and for which that unique instance is globally accessible.

The purpose of a singleton class is to represent a concept which, by its own fundamental nature, can only exist as a single instance. Sometimes, this happens because there are no technical solutions available to allow more than one instance of that concept, or sometimes because the solutions do exist but are too impractical or difficult to implement.

To determine the need for the Singleton Design Pattern in a practical case, one should then examine the following checklist:

  1. Is there a need for the considered functionality to be grouped in an object?A valid reason for wishing to regroup the functionality as a single object is if you need to manipulate it as an object, for instance to implement an interface and use functions or methods that can be applied to that interface. Another valid reason is the existence of several values related to that functionality which should then be grouped as a single object.

    If there is no reason to group the functionality in an object (no values to represent state, no usage as an object implementing an interface), then it is preferable to use a function, method, or namespace instead.

  2. Is there a need for the considered functionality to be grouped in a class?The alternative here is often initializing a global instance of an existing class to represent the functionality, instead of defining a brand new class for that purpose. For instance, even though the standard output of a program is by definition a one-instance-only concept, many implementations of the C++ std::cout are not singletons, but rather global variables initialized with a specific internal buffer that prints to the standard output (that buffer, in turn, is not a singleton because it provides no global access to its unique instance).

    If the difference in functionality is so wide that you would have to rewrite most of the class, then it is a good idea to create a brand new class. By contrast, if the difference is very small, then one can often get away with using an old class instead.

  3. Is there a technical reason for which the considered functionality does not allow multiple instances of the class?If it is technically possible to create several instances of the class, then the use of a singleton is not warranted: one can simply create a global instance instead.

    Note that it is not enough to decide that more than one instance will not be needed to warrant the use of a singleton! The reason the singleton is used is because the represented concept itself, independently of any external reasons such as how it will be used by the program, does not allow the creation of multiple instances. If the program happens to only create a single instance, then this is a coincidence and not a technical limitation.

    Note that this is only an argument against preventing the creation of multiple instances: the other traits of the singleton pattern (being a class which has a globally accessible instance) are not necessarily discarded if this particular condition does not hold.

  4. Is there a need for the unique instance to be globally accessible?The non-singleton alternative is the one used by std::cout : implement a singleton-like class (only allows a single instance) but use its unique instance locally to either initialize a global instance of another class or as a persistent local variable in a function or method.

    The question to be asked here is whether an observer outside the scope of the module or function you are working in needs to know of the existence of the singleton candidate, or whether the fact that the class extends a public interface is enough.

    If knowledge of the class’ existence is necessary, then a globally accessible instance is almost always warranted: there is no point in knowing about the class if one cannot access its instance, and there is no point in passing the instance of that class around while knowing it is the only one.

    On the contrary, if only the interface is public, then only the module which contains the class needs to know about the class (and provide it to the outside world as that interface).

    This is an argument against making the instance a global variable: the other traits of the singleton pattern (the limitation to a single instance, for instance) still hold even if the instance itself is not global.

If the candidate satisfies the above four conditions, then it can accurately be described by the Singleton Design Pattern.

Monostates

The Monostate Design Pattern is a close relative to the Singleton Design Pattern, in terms of applicability. Almost every concept which can be implemented as a singleton can also be implemented as a monostate.

An image that has no reason to be here. A monostate is a class which can have any number of instances, but where every instance has exactly the same state as all others. In terms of implementation, it is equivalent to a singleton: a monostate can be represented as a proxy class which automatically references the unique instance of the singleton, and the singleton can be used in place of a monostate simply by using the singleton’s global instance access function wherever the code created a new monostate.

From a design point of view, I tend to consider monostates as a globally weaker alternative to singletons. My reasoning is that a programmer makes the basic assumption that the state of a given instance can only be modified through references to that instance. However, a monostate violates this assumption by allowing the state of an instance to be modified through a reference to another instance. This oddity does not exist for a singleton, where only a single instance exists.

Of course, a monostate does have an advantage whenever the represented concept allows modifications of its state outside of a reference to its instance: this happens, for instance, when representing an entity which evolves outside the program (a filesystem, controlled hardware…) and which explicitly violates the above assumption. If that is the case, then it is interesting to use a FooBarView monostate to represent the concept of FooBar so that the name implies that the object itself is only one of many different views over the same autonomous concept.

Therefore, as a rule of thumb, if a hesitation exists between using the Singleton Design Pattern and the Monostate Design Pattern, then one should use a singleton unless by its very definition the represented unique-and-global-state will change outside the application.

Misconceptions

The Singleton Design Pattern carries several misconceptions, which often lead to its misuse in a situation where it is not an accurate representation of the concepts at hand (and thus a need for refactoring when the mismatch between pattern and concept becomes clear) and to the usage of unrelated arguments in defense of its use.

  1. “I will use the Singleton Design Pattern because using global variables is not good object-oriented practice.” This is the single most encountered misuse of the pattern. It often finds its roots in the affirmations that “global variables are evil” (and thus should be avoided) and that “design patterns enforce good design” (and thus should be used). Both affirmations are incorrect, or at least partially erroneous.

    First, global variables are not evil in themselves. What is dangerous is a hard-coded reference to global mutable state : the fact that a piece of code is bound by its very implementation to a bit of mutable state, so that this binding cannot be altered or customized by the user of the code. The hard-coded binding is what makes the code difficult to reuse and thus creates a bad object-oriented practice. However, both global variables and singletons, when accessed directly by the using code, create that same hard-coded binding, and thus share the same issue (which stems, in fact, from the need to have hard-coded access to global mutable state, regardless of how that state is represented).

    Then, design patterns are not a silver bullet which automatically enforces good design. Design patterns are bits of high-level vocabulary which allows one to describe a situation or problem using fewer words, which lets the brain focus on the relevant words instead of the details. Using a design pattern to describe something which does not fit that pattern, however, is akin to calling “a tool which is used to drive nails into planks” a “hammer”: you will be in trouble when you notice the “hammer” was in fact a “nailgun”.

    In short, using a singleton to replace a variable is a misuse of the design pattern, which violates the third prerequisite (the impossibility to have more than one instance).

  2. “I will use a singleton to correct a technical issue related to the use of global variables, even though that issue does not prevent the creation of multiple instances.” The technical issues often cited here are the resolution of the initialization order problem (making sure that a global will be initialized before another variable which needs to use it during its initialization) and the possibility of lazy creation (a global variable might exist in memory for a while even if the program never uses).

    The Singleton Design Pattern can solve these issues. However, the techniques it uses are orthogonal to the techniques used to restrict it to one instance only. Therefore, using a singleton to solve the problem and then removing the one-instance restriction (usually by making the constructor public) will result in a more accurate description, and is thus preferable to both singletons and global variables.

  3. “I will only ever need one instance of this class, therefore I will use a singleton.” This violates the third prerequisite, and possibly also the fourth. Again, a singleton represents the inability for an additional instance to be created. If your object could be safely instantiated twice, but the application you are writing only uses one instance, then adding code to enforce the uniqueness of the instance is both in contradiction with the nature of the concept you are representing (because it supports multiple instances) and completely useless (because the application never attempts to create two instances anyway).

    If the third prerequisite is not satisfied, there are plenty of alternative solutions to use to achieve your goal (the most elementary example being the implementation of a singleton minus the one-instance-only restriction).

  4. “I have made this a singleton, so that I don’t have to pass it to everywhere it is needed.” This is a violation of the first prerequisite. The only reason to turn some functionality into an object is because you wish to group the related state together in a manner which can then be manipulated by functions as a local variable, an argument or a return value.

    If your representation of the concept at hand does not involve any such manipulation, then a far better representation is to use a good old procedural interface for the concept. If your code could be rewritten with minimal to a procedural solution (by replacing the get-instance-and-call-method statements with call-procedure statements), then your code is implicitly procedural: correct object-oriented code is usually much harder to convert to procedural style. Therefore, since your code is procedural, it is both easier and more transparent to represent it using procedural means than by diverting object-oriented means from their intended purpose.

    A correct object-oriented use of the Singleton Design Pattern involves using the singleton class to implement an interface, and then pass the singleton to code which is applied to that interface. And so, not only does a singleton not avoid passing the instance around, but it requires doing so.

Advantages

The main advantage of the singleton is that it is a design pattern: a name which can be instantly associated by any remotely competent software engineer to a the elementary properties of “only one instance” and “globally accessible”. This is an exceedingly important notion: instead of spending precious time writing documentation which painstakingly describes the exact behavior of a given piece of code, being careful not to imply false properties and to be exhaustive in your enumeration of all cases, and also having the user read that entire documentation twice to make sure he understood it correctly, you can simply describe the class’ instantiation policy as “Singleton” and be done with it.

Sometimes, if the intended usage of a public library class is to use a single provided global instance (even if there is no technical reason to limit yourself to a single instance) provided by the library, then I would perhaps go as far as label that class a singleton, in order to forward the point of intended usage despite the violation of prerequisite three.

However, for a class that is to be used internally, and where the users of the code are also its developers, I would not consider mislabeling: conveying a meaning which is incorrect to an user is acceptable, because the user is not expected to know about the implementation (and, for all he knows, perhaps there is a technical limitation on the number of instances), whereas conveying an incorrect meaning to a fellow developer is not.

The special treatment provided to classes in several programming languages make singletons and monostates preferable alternatives to normal procedural modules. For instance, PHP5 provides autoloading support for classes (the file for a class is loaded when that class is used in the source instead of having to be loaded manually beforehand) which makes class-based implementations of modules better. Similarly, since ECMAScript provides no namespace functionality, using a single-instance global-access object as a namespace is a valid and somewhat frequent approach.

Conclusion

A singleton is an excellent tool for describing an unique and globally accessible concept, and there is a simple checklist to determine whether a concept qualifies for representation as a singleton. However, using the singleton design pattern to represent a concept which does not have the two required properties (for instance, by altering the concept by force to make it fit) generally causes more harm than good, by misrepresenting the actual concept being manipulated.

MVC in Web Development

Model-View-Controller is an architectural pattern that originated in 1979 in the smalltalk language (paper) for non-web purposes, and set foot timidly but with increasing appeal around 2001 (paper, requires registration). Its primary objective is the separation of concerns:

  • Regardless of how it is accessed by the users, the state of the application should be represented both as data (database or file storage, in-memory representation for performance) and as constraints on its functional behavior (keeping the state consistent, reacting correctly to events). This set of concerns is represented by the model.
  • The program will receive requests from users. These requests will usually follow a medium-specific definition, such as an HTTP GET or POST request, Java RMI or command-line execution of a program, and must be parsed and translated before they can be applied to the underlying model.This set of concerns is represented by the controller.
  • The program will display data back to the users. This representation will usually follow a medium-specific definition, either human-readable or computer-readable, such as HTML, XML, JSON, AMF, CSV, PDF or some other format. The data to be displayed, extracted or computed from the model and the request received by the controller, is then translated and wrapped in renderer-specific details. This set of concerns is represented by the view.

At its core, MVC is nothing more than a set of classification rules which answers the question “where should the code for this functionality go?” with a simple high-level answer. As a consequence, a lot of different flavors exist, each with their own (often slightly distinct) approach, and no universally accepted definition of the One True MVC.

A quick example of minimalistic Model-View-Controller in PHP:

// Controller 
$target = $_GET['target']; 

// Model
session_start();
$stats = array();
if (isset($target)) {
  $stats = array( 'hits' => ++ $SESSION[$target]['hits'], 'last' => $SESSION[$target]['last'] );
  $SESSION[$target]['last'] = date();
} 

// View
echo json_encode($stats);

This example receives a GET HTTP request containing a target. It then computes the number of times that target was queried from within the same session, along with the last time it was queried (if any), and updates the data in memory. Finally, it returns the extracted data through HTTP, encoded as JSON. This would be usable, for instance, as an AJAX helper to determine how many times a certain piece of content (article, video) has been viewed recently.

Large MVC frameworks have evolved. One such example, which was discussed on this blog a few months ago, is the Zend framework, which provides a Controller system (which comprises a Front Controller, responsible for dispatching the request to an user-implemented Action Controller that matches the request URI) and a View system (which is mostly a way of using PHP as a templating system by use of phtml files), along with utilities such as Zend_Db to help the implementation of models.

Another MVC framework I could recently get my hands on is the Alfresco Web Scripts system, which uses the filesystem (and a description XML file) for parsing and dispatching HTTP requests to a set of javascript controllers that can access and manipulate the underlying Alfresco data model, with the output being sent in various formats including XHTML formatted with FreeMarker.

As a whole, the Web Development world earns particular benefits from MVC due to the very nature of the HTTP protocol: every web application reacts in the same “dispatch and parse request, apply modifications and extract data, send back formatted response” archetypal sequence. As such, MVC is an excellent means of separating these three steps into cleanly defined blocks.

Common errors in MVC design

The absence of a precise definition of MVC makes it possible to create a seemingly conforming implementation and label it as MVC, have it go unnoticed by the community at large, but cause issues down the road because the implementation does not, in fact, support the usual benefits of MVC.

A frequently encountered situation is the Anemic Domain Model antipattern, where storage of the application data remains in the model, but the entire verification and behavior code is moved to the controller instead. For instance, the model stores and retrieves a plain text password value, and the various controllers related to authentication, registration and password reset all perform a hash on the password before storing it or comparing it.

In this example, one major advantage of the Model-View-Controller is lost: adding a new controller must now respect the invariants required by the other controllers (the new controller would have to manipulate passwords by using the same hash as the other controllers). By contrast, if the invariant had been made part of the model, then it would have been impossible for a new controller to forget about the invariant.

Consider the common situation where the model in Model-View-Controller is a simple database wrapper around several tables. In such a setup, the views and controllers cannot and should not assume any additional constraints or invariants on top of the constraints and invariants guaranteed by the table structure. If your controller assumes that a VARCHAR(16) database column contains at least four alphanumeric characters because another controller put it there, then there is a high probability that this assumption will break at some annoying point in the next few months. A VARCHAR(16) database column contains sixteen random characters of the database’s current encoding. If you wish to enforce an additional invariant (such as being four or more alphanumeric characters), add that invariant to the model (even if this involves adding more model code than originally envisioned).

The anemic domain model problem appears whenever the separation of concerns (the original objective of the MVC approach) is not correctly performed: the concern of enforcing invariants of data is not cleanly encapsulated by the model and is instead left to float freely in both the model and the controller.

Similarly, failure to correctly separate concerns between the view and model or between the view and controller lead to similar issues. For instance, if a view finds itself computing renderer-agnostic data, it’s quite possible that this computation belongs in the model instead, and keeping it in the view will inevitable lead to reimplementation once the same data will be displayed with a different renderer (such as a web service API).

MVC as a recursive pattern

Resist the temptation to create one controller, one model and one view for your program. In several cases, it can be interesting to have several controllers, models and views. It can be interesting to implement part of a model as a complete model-view-controller triad.

For instance, I would point to the analysis by Morales et al, which in an RIA model (where the client keeps its own Model-View-Controller triple) defines the server-side data manipulation as being a model: in order to support querying the server-side model by several means (local API, REST API, JSON/AJAX/AMF, HTTP-HTML and so on) the actual data model must in turn be separated from a server-side view and a server-side controller. Then, the client-side model interacts with the server-side model through the server-side view and controller, as illustrated here.

However, when considering the situation from the eyes of the client code, the server in itself is just part of the implementation of the client-side model: a remote entity which supports read/write queries through an appropriate protocol, which essentially amounts to a model.

Another situation is when a model is composed of sub-models. For instance, when a shopping cart aggregates several products, it can be interesting to make the product model distinct from the shopping cart model. In turn, the shopping cart view will own a product view that represents the product within a shopping cart, which may different from the product view that represents a product on its own.

As such, the shopping cart page contains a top-level controller and view, which recursively manipulate internal custom controller and view for the product model. The product model is independent and has its own top-level controllers and views.

The conclusion is that an MVC architecture should not be seen as a fixed high-level structure. Instead, controllers and views may use sub-controllers and sub-views that operate on other models (benefitting from the fact that a given model can have several controllers and views associated to it).



706 feed subscribers
(readers who polled a feed this week)