Wednesday, February 27, 2013

Review of 'Moonwalking with Einstein'

You've heard of ars technica: have you heard about ars memorativa, the art of memory?

Years ago I played Quake quite a lot. I'm sure I did other things in the winter of '96-'97 as well - indeed I have photos to prove it - but one of the strongest memories I have of that time is of happily fragging and blasting my way through over 30 separate maps (or dungeons). When I finally finished it there were the expansion packs 'Scourge of Armagon' and 'Dissolution of Eternity' to get through. When I was finished those I downloaded more maps made by fans just to keep playing.

Long after I finished playing that influential and venerable first-person shooter I noticed something strange: I could remember my way around the individual dungeons much better than I thought I would have done given how fleeting my time in them had been. Vivid memories of hallways and vistas would return, unbidden, in a way that simply never happens with words, or other non-visual material that you might want to remember. I didn't know it at the time, but these dungeons were at the basement of a memory palace.



The art of memory, including the memory palace, are ancient techniques featured in Moonwalking with Einstein, which gives you on the one hand practical advice about how to remember things better and on the other an intriguing historical run through, right back to the ancient Greeks, of the history of remembering things. The basics haven't changed much: the art is to "make remembering things more memorable" by using our superior ability to recall locations, and also to associate important things we want to remember with unforgettable, often raunchy, images, which are hard to dislodge. "The principle underlying all memory techniques is that our brains don't remember all types of information equally well." We're good at pictures, and terrible at numbers. And what we're trying to remember matters: "We don't remember isolated facts, we remember things in context." Therefore, if you can imbue what you're trying to remember with meaning, be it silly or smutty, then you will remember it better.

At the same time, there is plenty of good factual material here: you'll find out the difference between declarative and non-declarative (or, explicit and implicit) memory, and within declarative memories, semantic and episodic memories. If you remember it all, of course.

Moonwalking with Einstein: The Art and Science of Remembering EverythingMoonwalking with Einstein: The Art and Science of Remembering Everything by Joshua Foer
My rating: 4 of 5 stars
View all my reviews

But this book is probably most memorable for the remarkable feat of self-help that Foer brings about. He keeps saying that these memory tricks, even the most spectacular feats of mental athleticism, such as are seen every time there is a competition between the world's best, are just techniques that anyone can learn. "We all have remarkable capacities asleep inside of us, if only we bothered ourselves to awaken them." Apparently so.

Of particular interest to me in the book was Ed Cooke, one of the creators of Memrise.com, a site which aims to make learning fun. Indeed when I see my 8-year old kid using it to learn a language, or the countries of the world, I see a kid tricked into doing extra homework and loving it. The friendship Foer makes with Cooke and the role played by the latter in mentoring the former makes this book different to your usual journalistic reportage of such-and-such a scientific or societal phenomenon. But that's not the half of it. In 2006 Foer actually won the very contest, the US Memory Championship, that he covered in the first place that got him interested in the whole ars memorativa shenanigans! It's a great moment, by the way, when he reveals this astonishing fact in his TED talk.



This is a "mem" I made on Memrise for a word I came across in one of the Greek courses I'm doing. You can see the reasoning here: if you come across the word ασφαλώς and hope to remember it without making a mnemonic, well, you might just do so. But since the ancient Greeks, fittingly, we know that associations and images help us remember stuff.

Actually, I picked that particular mem for another reason as well. If you're thinking, and I know you are, that the "ass" part of that word is particularly suggestible of a ... certain genre of association, then you're right. If I was to make a memory association capitalising on the saucy overtones of the "ass" part of the word (and in this case I could keep going and get "phallus" out of the second part) I could create a lewd scenario involving sodomy, and that would be actually win the approval of any self-respecting memory expert. That's because the dirtier the memory palace, the better. It's long been recognised that the saltier the images used to associate with concepts, the stickier they are. For obvious reasons, a site like Memrise sadly can't promote that particular technique. Some early memory learning proponents centuries past had no such scruples and for promoting this particular heuristicthey got into trouble with the church, drearily predictably.

Don't believe me that you should actually remember your friends' birthdays by creating images of them having sex with animals? You should read Moonwalking with Einstein.

Friday, February 15, 2013

EF Code First enum problem upgrading to EF5

What happens if your app uses enums in your POCO classes and you subsequently upgrade to EF5? How do you adapt now that EF supports enums?



Yesterday I upgraded my app to target .Net 4.5 (from 4.0) so I could install EF5 proper and promptly broke all the classes/tables that had enums in them. By the way, that app's not my app, as in "hands off it's mine", I just mean it's the app I'm working on, which should go without saying, but just so you don't think I'm a big boastful boaster I'm saying it again.



Well, the tables aren't broken, but they do have duplicate fields and values (red circled field in the screenshot above). I noticed this because I had a SQL script to populate them and started getting 'Cannot insert the value NULL into column 'AccommodationType', table 'PatientPortal.dbo.PatientDetails'; column does not allow nulls. INSERT fails.' errors where I obviously hadn't before: hadn't even had that column in that table before. What was going on? Here is the code for that class/table:
public class AdmissionDetails : IEntity
{
        public int Id { get; set; }

        … other properties … 

        public AccommodationType AccommodationType
        {
            get { return (AccommodationType)AccommodationTypeId; }
            set { AccommodationTypeId = (int)value; }
        }
        public int AccommodationTypeId { get; set; }
}
As you can see, we have a kind of superfluous member, in this case AccommodationTypeId, simply to map the underlying int value of the actual enum, AccommodationType. That's the standard way of faking enums that we all use. EF dutifully ignores any types it doesn't recognise, in this case the enum. That's why only the AccommodationTypeId column gets generated in the database. Once I upgraded to EF5 however, the web.config changes triggered a recreation of the database, and lo! EF saw the enum field, and generated a field for it, and it was good. Well, not quite. But it actually doesn't make a huge difference, since the new mapped enum field will simply do exactly the same as the int field. It will, though, result in a lot of spurious, unnecessary changes to your database, which you want like you want to listen to Coldplay.

It turned out the fix for all this is quite easy. One reason for that is that by default an enum resolves in the database to an int in EF5, so if you’re using ints like we were you can happily rip out all that plumbing code. What I did was:
  • got rid of the unnecessary int (AccommodationTypeId) representing the enum's underlying value.
  • removed the enum's (AccommodationType) getter and setter code, and made them auto-implemented properties
  • mapped the enum to the old id field in the database, with a data annotation ([Column("AccommodationTypeId")]) to map, avoiding a database schema change and potential data-loss, since without this the erstwhile Id column (AccommodationTypeId) would have had to be dropped
using System.ComponentModel.DataAnnotations.Schema; // Column annotation needs this

public class AdmissionDetails : IEntity
{
    public int Id { get; set; }

    ... other properties ...

    [Column("AccommodationTypeId")]
    public AccommodationType AccommodationType { get; set; }
}
The database schema reverts to the original state and since we don’t run EF Migrations in our team to upgrade our production database, rather relying on a Redgate schema difference tool, there's no difference between your local database schema and your production one! Noice.

Double trouble

Plain sailing so far. What could go wrong? An object composed with more than one instance of another object is what. Switching examples from accommodation types to people and addresses, a person object has a home address and a billing address, both of which might be represented by an Address class, making the Person object thus:
public class PersonDetails
{
    public int Id { get; set; }

    ... other properties ...

    public Address HomeAddress { get; set; }
    public Address MailingAddress { get; set; }
}
That's ok, but if the Address has an enum in there like, oh I don't know, State, like this...
public class Address
{
    public int Id { get; set; }

    ... other properties ...

    [Column("StateId")]
    public State State{ get; set; }
}
...then the problem you'll hit is you'd now have two StateIds in your Person table. 'Schema specified is not valid. Errors: (319,6) : error 0019: Each property name in a type must be unique. Property name 'StateId' was already defined'. That [Column("StateId")] annotation is a literal - it can't generate, as it should, separate columns called 'HomeAddress_StateId' and 'MailingAddress_StateId' the way EF would, left to its own devices. In this case you need to remove that [Column("StateId")] annotation, then switch to Data Annotations' big brother, the Fluent API.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity()
                .Property(p => p.HomeAddress.State)
                .HasColumnName("HomeAddress_StateId");

    modelBuilder.Entity()
                .Property(p => p.MailingAddress.State)
                .HasColumnName("MailingAddress_StateId");
}
Some might argue that all of your configuration should be done fluently like this, and they're probably right. I'd rather do what I can using the Data Annotations before resorting to the fluent API simply because the annotation metadata is close to the actual thing its annotating, and also, if you do everything in OnModelCreating that can become as messy as Bali traffic. But it's up to you.