Grunt Work Principle

One word that I've used to describe my work style, but not really my programming style, is "lazy". This can be a word that describes behavior that is often considered detrimental. Non-flattering.

However, in the programming world, it is a very good trait, if employed with other proper attributes. Like, being a bad programmer and lazy isn't good. But being a decent programmer with good work ethic and lazy is actually pretty good!

Lazy definitely doesn't describe my work ethic. Lazy describes how I am when confronted with grunt work. I have been trying to describe it with a principle or some other short definition. Out of pure laziness and lack of creativity in general, I'll call it the "Grunt Work Principle". You can feel free to put my name in front of that. I couldn't be bothered to.

Grunt Work Principle

If the amount of grunt work presented exceeds 1 minute, and the grunt work can be automated, no matter how long the process to automate, it will be automated.

In practice, this will take the form from anything like my last post on Sitecore Doc, to something simple like taking 100 lines of short text and compacting them to 100 characters per line. For that compacttext project motivation in particular, each time I would have to do it would not exceed 1 minute probably, but easily add up all the times I've had to do it and it's in the 3-4 minute range :)  That project probably took me 1 hour total to create but it can be used indefinitely.

There is no upper limit on the amount of time automating will take. There is only the restriction of whether it can be automated. For instance if it requires human interaction or things that aren't so easily determined by a computer alone. Even then I'd probably find a way to automate as much as I can. For instance, with the Sitecore Doc project, I could automate getting items and renderings from Sitecore, generating output, but at the time (and I plan to integrate source-d into my workflow) I could not easily figure out a way to map method calls to renderings. So that part I had to do manually, which was a few hours worth of grunt work. Oh believe me, tracking calls to methods is grunt work when all you are doing is producing documentation!!

Benefits of Automation

Future re-use: The top reason to always automate the current task at hand is for future re-use. You may initially very specifically automate for the task at hand, but then in the future find a way that you can re-use that but with small modifications. Or even a complete rewrite. Or completely as is. This is all fine.

Consistency: Automating will produce consistent results. In my compacttext example, the output is predictable. If I specify 100 line length in that example, the same input will produce the same output 100% of the time. If a human were doing it, there's no guarantee as eyeballing the line length can skewed by things like screen size, font size, caffeine consumed, etc.

It is usually too soon to optimize, but wtf are you waiting for with automation?!  Get to it!!

Sitecore Doc

Sitecore solutions can become large and unweildy. Recently I was tasked with the following: Find out which page each of these service methods (40-50) are called. With how .NET and Sitecore applications (generally all good applications) are written, a service method call would be written within a component, but that component could be put on any page!

Luckily these components manifest themselves in Sitecore as "renderings". They can have data sources and parameters. And code, which is what leads us to this mess in the first place ;)

First we'd need a way to map these renderings to service calls. I came up with a generic "info" data field to do that in a JSON file which defines all of the renderings we're interested in. On a side note, I only provide those that we're interested in, this current project would yield a 4-5 MB result file which would be ridiculous if it included everything. That JSON looks like this:

 

{
    "includeUndefined": false,
    "renderings": [
        {
            "id": "6A8BB729-E186-45E7-A72E-E752FDEC2F48",
            "name": "AccountBalancePurgeSublayout",
            "info": [
                "CustomerInformationService.GetCardStatusV4(authHeader, accountId)",
                "CustomerInformationService.GetPurgeInfo(authHeader, accountID)"
            ]
       }
}

Using my (recently updated to accommodate this request) Go Sitecore API, I was able to take that information and map it against every page renderings (or standard values renderings) and produce a file that is filled with every page and their (eventual) calls into service methods. These aren't directly called within the page code (usually), and there's heavy caching going on as well. Here's what the output looks like:

 

    Name:     booking-calendar
    ID:       f1837270-6aca-4115-94bc-08d1a4ed43ad
    Path:     /sitecore/content/REDACTED/booking-calendar
    Url:      https://www.REDACTED.com/booking-calendar
    Renderings:
            Default
                CalendarBooking   
                    Path:         /layouts/REDACTED2013/REDACTED/SubLayouts/Booking/Calendar/CalendarBooking.ascx
                    Placeholder:  content 
                    Info:
                                  ReservationService.GetAllRoomTypesV2()
                                  ReservationService.GetCashCalendarV3(GetAuthHeader(),promoCode,startDate,endDate,isHearingAccess,isMobilityAccess, isWeb)
                                  ReservationService.GetCashCalendarWithArrivalV3(GetAuthHeader(), promoCode, roomType, arrivalDt, numNights, isWeb)
            Mobile
                CalendarBookingMobile   
                    Path:         /layouts/REDACTED2013/REDACTEDMobile/SubLayouts/Booking/Calendar/CalendarBookingMobile.ascx
                    Placeholder:  content 
                    Info:
                                  ReservationService.GetAllRoomTypesV2()
                                  ReservationService.GetCashCalendarV3(GetAuthHeader(),promoCode,startDate,endDate,isHearingAccess,isMobilityAccess, isWeb)
                                  ReservationService.GetCashCalendarWithArrivalV3(GetAuthHeader(), promoCode, roomType, arrivalDt, numNights, isWeb)

This was very useful for this specific task, however it's written in a way that will be very useful going forward, to provide insights into our Sitecore implementations and how the content is structured.

This app will see updates (sorry the code isn't available for now) so that it will show usages among different renderings, unused ones or broken (exists in a renderings field but not as an actual item in sitecore [was deleted or not imported]), and other stuff that I can think of. This binary is named "scdoc" as I like to keep my names short :)  The Sitecore Code Generation tool I wrote is simply "scgen".

Check out that Go Sitecore API though if you want to easily query your Sitecore database!  Happy Coding :)