简体   繁体   中英

Best way to write a simple boolean method with good C# syntax

Hey all, I seem to have these types of methods everywhere.

The method below wants to do these simple tasks:

  1. Open a DB connection (IntLMPDB object)
  2. Read a simple record off a small DB table (the DB table is keyed with strings, because each string is the name of method, so I want just one row of each in the table), the rest of the row is a series of timestamps that tell me when things happned.
  3. If you can't find the record, then return an exception because there's nothing that can be done.
  4. If you find the record, look at the second date if it's just plain missing, then set to true because this is the first ever run.
  5. Or finally get to the meat, if the first date is greater than the second set to True because it's been updated and it's time to run. Else if not, set to False because there's no update yet.

So here's the code... What I am trying to do is pare this down to the best and quickest way to run through these checks. I am not concerned about like DB connection issues or anything like that.

    private static bool isLastIntervalNewerThanDB(string muiMethod)
    {
       using (var db = new IntLMPDB())
        {
            // Try to load a matching record.
            LastIntervalUpdated liRec = db.LastIntervalUpdateds.FirstOrDefault(rec => rec.method == muiMethod);
            // If it could not be loaded, exit because there's no way to determine if we should run.
             if (liRec == null) { throw new Exception(string.Format("Could NOT find LastIntervalUpdated record for muiMethod: {0}", muiMethod)); }
            else
            {
                // we have a valid interval record, so lets check that it has been updated since the last webPostTime.
                // put another way, there are three datetime values in the LastIntervalUpdated table. First is the
                // interval itself, second is the retrievalTime and third is the webPostTime. Whenever the MUI is 
                // checked for a new interval if one is found then the code updates the retrievalTime to the current
                // instant in time. This tells us what the last interval this application found on its last run was.
                // The thrid value is the webPostTime, this time instant is only updated by this very method we're in
                // right here. We can use this logic: if the retrievalTime is greater than the webPostTime then there's
                // a newer interval that we haven't yet processed and inserted into the databse. So we should run the
                // method below and update ALL of the syncable values into the databse. Then we'll set the dbPostTime to 
                // the current instance. As it goes, if this program then runs again before the interval is updated
                // then the dbPostTime will be greater than the retrieval time and we'll know to do nothig. Simple Right? :)

                // or check here includes a NULL check on dbPostTime because it's possible that dbPostTime is NULL,
                // in the example of the first time the system runs. It might have run a LastUpdate sync and not yet
                // done this method, so dbPostTime would be NULL. None of the other columns are allowed to be null.
                if (liRec.dbPostTime_EST == null || liRec.retrievalTime_EST > liRec.dbPostTime_EST)
                { return true; }
                else { return false; }
            }
       }
    }

I think the logic is fine. I would suggest that you do something like this to improve readability*:

private static bool isLastIntervalNewerThanDB(string muiMethod)
{
   using (var db = new IntLMPDB())
    {
        LastIntervalUpdated liRec 
            = db.LastIntervalUpdateds
                    .FirstOrDefault(rec => rec.method == muiMethod);

        if (liRec == null) 
        { 
            throw new Exception(
                string.Format("Could NOT find LastIntervalUpdated record for muiMethod: {0}", muiMethod)); 
        }

        return liRec.dbPostTime_EST == null 
            || liRec.retrievalTime_EST > liRec.dbPostTime_EST;        
   }
}

* While readability is subjective I would argue that an else after if (liRec == null) only adds unnecessary nesting and the final conditional can be collapsed into a single expression. Also never underestimate a well-placed newline within a long expression - it can make all the difference betwee readable and unreadable code.

private static bool isLastIntervalNewerThanDB(string muiMethod)
    {
       using (var db = new IntLMPDB())
        {
            // Try to load a matching record.
            LastIntervalUpdated liRec = db.LastIntervalUpdateds.FirstOrDefault(rec => rec.method == muiMethod);
            // If it could not be loaded, exit because there's no way to determine if we should run.
             if (liRec == null) { 
                     throw new Exception(string.Format("Could NOT find LastIntervalUpdated record for muiMethod: {0}", muiMethod)); 
             }

                // we have a valid interval record, so lets check that it has been updated since the last webPostTime.
                // put another way, there are three datetime values in the LastIntervalUpdated table. First is the
                // interval itself, second is the retrievalTime and third is the webPostTime. Whenever the MUI is 
                // checked for a new interval if one is found then the code updates the retrievalTime to the current
                // instant in time. This tells us what the last interval this application found on its last run was.
                // The thrid value is the webPostTime, this time instant is only updated by this very method we're in
                // right here. We can use this logic: if the retrievalTime is greater than the webPostTime then there's
                // a newer interval that we haven't yet processed and inserted into the databse. So we should run the
                // method below and update ALL of the syncable values into the databse. Then we'll set the dbPostTime to 
                // the current instance. As it goes, if this program then runs again before the interval is updated
                // then the dbPostTime will be greater than the retrieval time and we'll know to do nothig. Simple Right? :)

                // or check here includes a NULL check on dbPostTime because it's possible that dbPostTime is NULL,
                // in the example of the first time the system runs. It might have run a LastUpdate sync and not yet
                // done this method, so dbPostTime would be NULL. None of the other columns are allowed to be null.

               return liRec.dbPostTime_EST == null 
                      || liRec.retrievalTime_EST > liRec.dbPostTime_EST;     

       }
    }

Keep the first if get rid of the first else and condense the last into a single line if/else

if (liRec == null) { throw new Exception(string.Format("Could NOT find LastIntervalUpdated record for muiMethod: {0}", muiMethod)); }

liRec.dbPostTime_EST == null || liRec.retrievalTime_EST > liRec.dbPostTime_EST ? return true : return false

I would move the boolean logic to the LastIntervalUpdated class:

public class LastIntervalUpdated
{
    public bool IsLastIntervalNewer
    {
        get
        {
            return this.dbPostTime_EST == null || this.retrievalTime_EST > this.dbPostTime_EST
        }
    }
    //other properties...
}

Then you can put the comment in closer to the definition. It also allows you to simplify the query to:

private static bool isLastIntervalNewerThanDB(string muiMethod)
{
    using (var db = new IntLMPDB())
    {
        LastIntervalUpdated liRec = db.LastIntervalUpdateds.FirstOrDefault(rec => rec.method == muiMethod);
        if(liRec == null) throw new Exception(string.Format("Could NOT find LastIntervalUpdated record for muiMethod: {0}", muiMethod))
        return liRec.IsLastIntervalNewer;
    }
}

I would also consider creating an exception type for failed lookups such as ObjectNotFoundException rather than throwing Exception directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM