tags:

views:

95

answers:

6

I don't quite know how to ask this question, so I'll phase it as an example:

Imagine in an application you have a Country object. There are two properties of this object: Name, and a 'Bordering Countries' collection. More properties might be added later, but it will be the kind of information that would change very rarely (e.g. changes of country names/borders)

Lets say this application needs to know about all of the countries in the world. Where would you store these object's state? How would you new them up? It seems silly to store all this state in the DB, since it won't change very often.

One option might be to have an abstract 'country' base object, and have a class for each country inheriting from this with the details of each country. But this doesn't seem quite right to me.

What is the proper way of dealing with these kinds of objects?

UPDATES:

Someone asked about language: C#

Also, I'm coming at this from a web application perspective, so there wouldn't be multiple client installations where I'd have to worry about updating hard coded values.

Most people have suggested not hardcoding the data, but using the DB or XML files to store the data. Could anyone provide an example of how this kind of object would be 'newed up' (from e.g. an XML file)? Would you use some kind of helper or factory method to obtain instance of a particular country?

+1  A: 

enumerations are quite useful for that kind of thing. you don't mention the language you're using, but in java, they're stored quite efficiently as an ordinal index (integer) and you can always add new values to the end of the enumeration list.

oedo
It would be c# in my case
UpTheCreek
+3  A: 

Definatly in the DB. Load them up once (refresh periodically) and use them from there. I say definatly DB, as you will most likely be extracting data for reporting purposes, and if structured correctly, you can reuse the country data for other applications too.

MaLio
+1  A: 

I don't think that create a class hierachy would be a good design for your problem. Instead I'd store the values at the database and have a generic Country class what retrieve the country state from database.

Carlos Loth
+1  A: 

It won't change very often, you say, but in that you indicate that it may change at one point. In such cases, you should put it in a datastore of some sorts, as the others have indicated - be it a database, text file, or otherwise.

Keep in mind that, if you put it in an enum or a static class or some other part of your actual application, the end-user will not be able to change it easily. So if by some natural disaster or world war 3 some countries disappear, merge, separate, get a new government type or name, you need to be able to update your country list.

You could just have the application read the country list on startup, and leave it in memory. It'll auto-refresh when the application restarts. Another option would be to have it check for updated countries every X period and update the internal list, if it's an application that runs for a long time.

Cthulhu
Thanks for the suggestions. Re end-user updating: this is in the context of a web based service, so clients wouldn't be running intances of the app, and I could recompile easily.
UpTheCreek
+1  A: 

As oedo said, enumumerations should do the job, but if you need more than an index, you could use an xml file. it would be dynamic, no need compilation

Ziggy
What approach would you use to 'new up' a country based on an xml file?
UpTheCreek
Well, create a node "Countries", inside this node add nodes "Country", generate a unique id for each country , set it as property.Inside your "country" node add items as "BorderCountries" ans set the id of the bordered countries. Then for reading, parse all your Countries elements, affect the ID + other info you like, then reparse the xml file to find items that should be border, add to a list or an array of the current country.Hope this help.
Ziggy
A: 

You've got a variety of answers, so I thought I'd add my $0.02 worth.

Personally I alway hard code fixed lists like this (same with postcodes). That being said, when I'm at your position, I'll always optimize for readability. ie What will make sense in 6 months time, when you've forgotten about this project and have to do some maintenance?

If I had to do it with a database:

public class Country
    {
        public string Name { get; set; }
        public Country[] BorderingCountries { get; set; }

        public Country(iDB db, string name)
        {
            BorderingCountries = db.BorderingCountriesGet(name);
        }
    }

Your unit test:

public UnitTest1()
    {
        iDB db = new DB();
        Country c = new Country(db, "Spain");
        Assert.AreEqual(2, c.BorderingCountries.Count());
        Assert.AreEqual(1, c.BorderingCountries.Count(b => b.Name == "France"));
        Assert.AreEqual(1, c.BorderingCountries.Count(b => b.Name == "Portugal"));
    }

Oops! You probably want to populate the whole list (not one at a time!) DB:

static void Main(string[] args)
    {
        Countries countries = new Countries(new DB());
    }

public class Countries
    {
        public List<Country> Items { get; set; }
        public Countries(iDB db)
        {
            tblCountry[] countries = db.BorderingCountries();
            Items = new List<Country>();
            Country country = null;
            foreach (var c in countries)
            {
                if (country == null || country.Name != c.Name)
                {
                    country = new Country(c.Name);
                    Items.Add(country);
                }
                country.BorderingCountries.Add(new Country(c.BorderingCountry));
            }
        }
    }


    public class Country
    {
        public string Name { get; set; }
        public List<Country> BorderingCountries { get; set; }
        public Country(string name)
        {
            this.Name = name;
            BorderingCountries = new List<Country>();
        }
    }

    public interface iDB
    {
        tblCountry[] BorderingCountries();
    }

    public class DB : iDB
    {
        public tblCountry[] BorderingCountries()
        {
            using (DataClassesDataContext dc = new DataClassesDataContext())
            {
                return dc.tblCountries.ToArray();
            }
        }

    }

If I was hardcoding it:

public class Countries
{
    public List<Country> Items { get; set; }
    public Countries()
    {
        Items = new List<Country>();
        Items.Add(new Country { Name = "Spain", BorderingCountries = new string[] { "France", "Portugal" }});
        Items.Add(new Country { Name = "France", BorderingCountries = new string[] {"Spain","Belgium"});
    }
}
Christian Payne
Why the down votes???
Christian Payne