A Modern Take, The LINQ Answer

How Can Testing Be Bad?

An imaginary programming test question
This is very interesting answer because it suggests that the question itself is deeply flawed and says more about the limits of the person setting the question than the answer says about the candidate.

This answer suggests a candidate used to using the latest language features in an environment that encourages this.

The problem is that the question requires the use of what this candidate could probably see as obsolete technology and he has been forced to bodge an answer together.

I don't like this answer because it panders to my prejudices about how things are being over complicated for the sake of convenience, reusability and productivity resulting in an unmaintainable mess.

The "Modern Answer"

LINQ is part of the VB and C# .Net languages and its use splits programmers, some like it and some hate it. Of course the reality is that LINQ is neither brilliant or evil but is a good or bad tool depending upon what you want to do.

Unfortunately all to often a culture develops within an IT department where LINQ is always used or never used so a LINQ based answer to this test leaves a lot of questions.

In this example people who use LINQ would probably approach the problem in a slightly different way and not use a DataTable at all, but the question said that a DataTable was wanted so we end up with a bit of a mish-mash of technologies.

I would go as far as saying that for anyone who answered the question this way the question was an inappropriate test. It was testing something that they don't normally use and is a reflection of the lack of experience of the person setting the test not to realise this.


Answer C#

    [Table(Name = "StockTickers")]
    public class StockTicker 
    {
        [Column] public Int32 pk_StockTickers { get; set; }
        [Column] public DateTime DateCreated { get; set; }
        [Column] public DateTime DateLastModified { get; set; }
        [Column] public String Company { get; set; }
        [Column] public String CompanyTicker { get; set; }
        [Column] public String Keypoints { get; set; }
        [Column] public String SharePriceCat { get; set; }
        [Column] public Decimal? MinPrice { get; set; }
        [Column] public Decimal? MaxPrice { get; set; }
        [Column] public Decimal? LastReviewPrice { get; set; }
        [Column] public DateTime? LastReviewDate { get; set; }
        [Column] public String ShareIndex { get; set; }
        [Column] public Double? Ratio { get; set; }
        [Column] public Decimal? HighestEver { get; set; }
        [Column] public String MarketSector { get; set; }
        [Column] public DateTime? UninterestedUntil { get; set; }
        [Column] public Boolean FavouredStock { get; set; }
        [Column] public Boolean DoNotCollectCurrentPrice { get; set; }
        [Column] public Decimal? MarketCap { get; set; }
        [Column] public DateTime? TodaysShare { get; set; }
        [Column] public DateTime? Prev1Date { get; set; }
        [Column] public Decimal? Prev1Value { get; set; }
        [Column] public DateTime? Prev2Date { get; set; }
        [Column] public Decimal? Prev2Value { get; set; }
        [Column] public DateTime? Prev3Date { get; set; }
        [Column] public Decimal? Prev3Value { get; set; }
        [Column] public DateTime? Prev4Date { get; set; }
        [Column] public Decimal? Prev4Value { get; set; }
        [Column] public DateTime? Prev5Date { get; set; }
        [Column] public Decimal? Prev5Value { get; set; }
        [Column] public DateTime? Prev6Date { get; set; }
        [Column] public Decimal? Prev6Value { get; set; }
        [Column] public DateTime? LastReviewDateDateOnly { get; set; }
        [Column] public String CurrencySymbol { get; set; }
    }
    public partial class StockTickersDatabase : DataContext
    {
        public Table<StockTicker> StockTickers;
        public StockTickersDatabase(String connectionString) : base(connectionString) { }
    }
    protected Boolean LoadDataAnswer3(String connectionStringLocal, DataTable interesting)
    {
        Boolean funcRes = false;
        DataRow newRow;
        try
        {
            StockTickersDatabase Database = new StockTickersDatabase(connectionStringLocal);

            var dbQuery = 
                 from Company in Database.StockTickers.AsEnumerable()
                 where Company.ShareIndex == "FTSE 100"
                 select Company;

            interesting = new DataTable();
            interesting.Columns.Add("Company", typeof(String));
            interesting.Columns.Add("CompanyTicker", typeof(String));
            interesting.Columns.Add("Keypoints", typeof(String));
            interesting.Columns.Add("SharePriceCat", typeof(String));
            interesting.Columns.Add("MinPrice", typeof(Double));
            interesting.Columns.Add("MaxPrice", typeof(Double));
            interesting.Columns.Add("LastReviewPrice", typeof(Double));
            interesting.Columns.Add("LastReviewDate", typeof(DateTime));
            interesting.Columns.Add("ShareIndex", typeof(String));

            foreach (var company in dbQuery)
            {
                newRow = interesting.NewRow();
                newRow["Company"] = company.Company;
                newRow["CompanyTicker"] = company.CompanyTicker;
                newRow["Keypoints"] = company.Keypoints;
                newRow["SharePriceCat"] = company.SharePriceCat;
                newRow["MinPrice"] = company.MinPrice;
                newRow["MaxPrice"] = company.MaxPrice;
                newRow["LastReviewPrice"] = company.LastReviewPrice;
                newRow["LastReviewDate"] = company.LastReviewDate;
                newRow["ShareIndex"] = company.ShareIndex;
                interesting.Rows.Add(newRow);
            }

            funcRes = true;
        }
        catch (Exception ex)
        {
            HandleErrorMessage(ex.Message);
        }
        return funcRes;
    }
There are better ways of doing the above but they are probably too time consuming when someone is sitting a test.

In practice any environment that uses LINQ and DataTables would likley have a generic solution to the problem of populating the DataTable from the LINQ query, so I would expect a slightly messy answer.


Answer SQL

Candidate's point of view - It's only a test so if in the real world I would need a stored proc or whatever the company policy is then that's fine, it's just a slightly different LINQ query.