Friday, June 17, 2016

Compare before every check-in

If you don't compare every file before you check-in, you are more likely to check something in that was only needed for testing the change. (or something that was you trying to figure out how to solve the problem, and is now dead code) Additionally, If you do compare every file, you get to see what a diff program (and another human would see) when trying to compare the before to after. You can then optimize the code so that a diff is far more readable (if only for that check-in, then check-in again if you desire a specific order for how the file should read). Version Control Systems that have easy staging of parts of a file instead of all changes can make this even easier. Since, you may want to keep your local changes for testing, without checking them in for more testing or more feature additions. (or even permanent testing additions for your local workspace)

Wednesday, May 11, 2016

Vim Regex C# to F#

This is really trying my patience. Converting a C# class to F# using regex. Not the cleanest or sanest approach, but really with the patterns in the code I'm targeting it shouldn't be a very big deal
I welcome any and all input or suggestions besides do it with a real code parser/generator (I've done lots of work in this area and realize the benefits, but I'm working on something that isn't as robust but gets the job done)

vim :set magic? returns:magic
I started out with the following code


namespace PracticeManagement.Foundation.DataModels
{
    public class BillingStageDataAccess
    {
        public static IEnumerable<BillingStageDataModel> LoadRejectedGrid(string payerId, Connector cn)
        {
            return Pm.Dal.BillingStages.loadRejectedGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
                .Select(r => new BillingStageDataModel(r));
        }

        public static IEnumerable<BillingStageDataModel> LoadPendingGrid(string payerId, Connector cn)
        {
            return Pm.Dal.BillingStages.loadPendingGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
                .Select(r=> new BillingStageDataModel(r));
        }

        public static IEnumerable<BillingStageDataModel> LoadReviewGrid(string payerId, Connector cn)
        {
            return Pm.Dal.BillingStages.loadReviewGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
                .Select(r => new BillingStageDataModel(r));
        }

        public static IEnumerable<BillingStageDataModel> LoadPatientBilling(bool? includeThirdParty, Connector cn)
        {
            return Pm.Dal.BillingStages.loadPatientBilling(SessionVariables.Instance.CurrentFacility.FacilityID, includeThirdParty, cn).Select(bsm => new BillingStageDataModel(new Pm.Schema.BillingStageRecord(bsm.Age.ToString(), 0m, 0m, bsm.DOS ?? DateTime.Now, null, 0, bsm.FirstStatement ?? DateTime.Now, bsm.NofStatements ?? 0, bsm.PatientName, bsm.ThirdPartyPayerId ?? 0, null, null, bsm.Appointmentid ?? 0, null, null)) { PrimaryGuarantorType= bsm.AppointmentPrimaryGuarantorType });
        }

        public static IEnumerable<BillingStageDataModel> LoadCompleted(Connector cn)
        {
            return Pm.Dal.BillingStages.loadCompleted(SessionVariables.Instance.CurrentFacility.FacilityID, cn).Select(bsm => new BillingStageDataModel(new Pm.Schema.BillingStageRecord(null,bsm.ClaimAmount ?? 0, 0, bsm.DOS ?? DateTime.Now, bsm.Claimdate ?? DateTime.Now, bsm.Daysfilled ?? 0, null, 0,bsm.PatientName, 0, bsm.Claimstatus, null, bsm.Appointmentid ?? 0,null,null)));
        }

        public static IEnumerable<BillingStageDataModel> LoadPrepGrid(int facilityId, Connector cn)
        {
            return Pm.Dal.BillingStages.loadPrepClaimGrid(facilityId, cn).Select(r => new BillingStageDataModel(r));
        }
    }
}

Stage 1

  1. use dd to delete the namespace and class lines
  2. add module name =
  3. highlight that block pasted into an F# file.
  4. then apply the regex to remove lines that only open or close blocks :'<,'>s:^\s*[{}]\s*$:
regex irritation
  • * doesn't need an escape but in other places + does
  • that leaves a bunch of empty lines unfortunately

Stage 2

  1. re-highlight with gv
  2. then eliminate the public static T with :'<,'>s:public static [\w<>]\+:let
regex irritation
  • + needed to be escaped!

Stage 3

  1. re-highlight with gv
  2. fix indention with << followed by . as needed
  3. re-highlight with gv
  4. eliminate returns with :'<,'>s/return /
  5. re-highlight with gv
  6. add = on the end of the let lines with :'<,'>s:let .*:\0 =
  7. re-highlight with gv
  8. Fix casing to my preference for module methods (camel-case) with :'<,'>s:let \(\u\w\+\):let \l\1 or closer to regular regex :'<,'>s:let \([A-Z]\w\+\):let \l\1
regex inconsistencies and irritations
  • had to escape ( and ) for capturing groups
  • had to escape + (:'<,'>s:let \(\u\w+\):let \l\1 did not work)
  • didn't have to escape any of the following .*

Stage 4 (work in progress)

fix up the method declarations a little more
  1. re-highlight with gv
  2. regex: :'<,'>s/\(let \w\+\)(\?\(\w\+\)\(?\)\? \(\w\+\)[,)]/\1(\3\4:\2)/ 
    • switch the order of type and name
    • move ? (Nullable to the front for replacement with the word `Nullable` in F#)
    • add : of the first argument on method declaration lines with
which leaves me with the following to convert so far
module BillingStages =

    let loadRejectedGrid(payerId:string) Connector cn) =

        Pm.Dal.BillingStages.loadRejectedGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
            .Select(r => new BillingStageDataModel(r));


    let loadPendingGrid(payerId:string) Connector cn) =

        Pm.Dal.BillingStages.loadPendingGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
            .Select(r=> new BillingStageDataModel(r));


    let loadReviewGrid(payerId:string) Connector cn) =

        Pm.Dal.BillingStages.loadReviewGrid(payerId, SessionVariables.Instance.CurrentFacility.FacilityID, cn)
            .Select(r => new BillingStageDataModel(r));


    let loadPatientBilling(?includeThirdParty:bool) Connector cn) =

        Pm.Dal.BillingStages.loadPatientBilling(SessionVariables.Instance.CurrentFacility.FacilityID, includeThirdParty, cn).Select(bsm => new BillingStageDataModel(new Pm.Schema.BillingStageRecord(bsm.Age.ToString(), 0m, 0m, bsm.DOS ?? DateTime.Now, null, 0, bsm.FirstStatement ?? DateTime.Now, bsm.NofStatements ?? 0, bsm.PatientName, bsm.ThirdPartyPayerId ?? 0, null, null, bsm.Appointmentid ?? 0, null, null)) { PrimaryGuarantorType= bsm.AppointmentPrimaryGuarantorType });


    let loadCompleted(cn:Connector) =

        Pm.Dal.BillingStages.loadCompleted(SessionVariables.Instance.CurrentFacility.FacilityID, cn).Select(bsm => new BillingStageDataModel(new Pm.Schema.BillingStageRecord(null,bsm.ClaimAmount ?? 0, 0, bsm.DOS ?? DateTime.Now, bsm.Claimdate ?? DateTime.Now, bsm.Daysfilled ?? 0, null, 0,bsm.PatientName, 0, bsm.Claimstatus, null, bsm.Appointmentid ?? 0,null,null)));


    let loadPrepGrid(facilityId:int) Connector cn) =

        Pm.Dal.BillingStages.loadPrepClaimGrid(facilityId, cn).Select(r => new BillingStageDataModel(r));

Tuesday, February 9, 2016

Requested Post: Dev machine setup

How do I setup a machine to develop on?

Everywhere I've gone, one of my first steps is to document every single thing I'm told to do to setup the machine for development. Not a single one of the shops where did I this, was it appreciated or possibly even used as far as I can tell. Even in the many that had badly outdated instructions for new developers, I updated them to no avail or interest.

So here's my generic procedure for a machine (mostly independent of target platform/ui)
  1. Ask about getting a 2nd monitor if there isn't one.
  2. evaluate provided keyboard/mouse
  3. evaluate if using a git layer over top of the solution would be helpful
    1. branching in git is cake
    2. branching in TFS is very painful
  4. document and do all solution/job/domain specific setup
    1. ask around about pain points in setup
  5. ensure the work solution actually runs
  6. installs
    1. setup Chrome (or Firefox)
    2. install git or git-extensions (even if the shop doesn't use git)
    3. Linqpad 
      1. download (4 and 5)
      2. register it 
      3. set it to point to the script repository created in 2
    4. SublimeText
    5. Telerik JustDecompile
    6. Windows Grep - I am considering trying out this one
  7. pull down my script repository (this has all my most reusable/interesting scripting code)
  8. write some scripting code 
    1. to help verify and/or do step 3.
    2. to help with any manual work done in switching contexts (ie. Dev/QA/Prod debugging)
  9. Consider (but not necessarily do, creating a git repo over my user profile folder)
    1. this lets me watch changes to those folders for important settings or files that I might want to keep
    2. also allows settings to roam between machines/domains
  10. Run VS code metrics analysis of work solution(s) - 
    1. ask for approval to clean the methods with any of the following criteria:
      1. over 30 cyclomatic complexity
      2. under 30 maintainability
  11. evaluate build/CI process
  12. evaluate deploy process

Additional very wise steps I need to start doing:
  • Install sonar 
    • install the C# plugin
    • test run current/latest code
      • customize violation rules and re-run
      • document metrics (lines of code, number of projects, violations)
    • setup a build process that would iterate from the beginning of solution all check-ins for code trending

VS Extensions to install:
  • VsVim
  • Web Essentials
  • Visual F# Power Tools

Other tools I might install depending on platform/ui type: