SubMain - CodeIt.Right The First Time!

/Community

Support Community for SubMain Products
 Home Products Services Download Purchase Support
in Search
 
Home Forums Blogs Tutorials/CIR Tutorials/GD Downloads
Welcome to SubMain Community Sign in | Join | Help

SubMain Blog

November 2016 - Posts

  • CodeIt.Right Rules, Explained - Part 1

    I've heard tell of a social experiment conducted with monkeys.  It may or may not be apocryphal, but it illustrates an interesting point.  So, here goes.

    Primates and Conformity

    A group of monkeys inhabited a large enclosure, which included a platform in the middle, accessible by a ladder.  For the experiment, their keepers set a banana on the platform, but with a catch.  Anytime a monkey would climb to the platform, the action would trigger a mechanism that sprayed the entire cage with freezing cold water.

    The smarter monkeys quickly figured out the correlation and actively sought to prevent their cohorts from triggering the spray.  Anytime a monkey attempted to climb the ladder, they would stop it and beat it up a bit by way of teaching a lesson.  But the experiment wasn't finished.

    Once the behavior had been established, they began swapping out monkeys.  When a newcomer arrived on the scene, he would go for the banana, not knowing the social rules of the cage.  The monkeys would quickly teach him, though.  This continued until they had rotated out all original monkeys.  The monkeys in the cage would beat up the newcomers even though they had never experienced the actual negative consequences.

    Now before you think to yourself, "stupid monkeys," ask yourself how much better you'd fare.  This video shows that humans have the same instincts as our primate cousins.

    Static Analysis and Conformity

    You might find yourself wondering why I told you this story.  What does it have to do with software tooling and static analysis?

    Well, I find that teams tend to exhibit two common anti-patterns when it comes to static analysis.  Most prominently, they tune out warnings without due diligence.  After that, I most frequently see them blindly implement the suggestions.

    I tend to follow two rules when it comes to my interaction with static analysis tooling.

    • Never implement a suggested fix without knowing what makes it a fix.
    • Never ignore a suggested fix without understanding what makes it a fix.

    You syllogism buffs out there have, no doubt, condensed this to a single rule.  Anytime you encounter a suggested fix you don't understand, go learn about it.

    Once you understand it, you can implement the fix or ignore the suggestion with eyes wide open.  In software design/architecture, we deal with few clear cut rules and endless trade-offs.  But you can't speak intelligently about the trade-offs without knowing the theory behind them.

    Toward that end, I'd like to facilitate that warning for some CodeIt.Right rules today.  Hopefully this helps you leverage your tooling to its full benefit.

    Abstract types should not have public constructors

    First up, consider the idea of abstract types with public constructors.

    public abstract class Shape
    { protected ConsoleColor
    _color; public Shape(ConsoleColor
    color) { _color = color;
    } } public class Square
    : Shape { public int SideLength
    { get; set;
    } public Square(ConsoleColor
    color) : base(color)
    { } }

    CodeIt.Right will ding you for making the Shape constructor public (or internal -- it wants protected).  But why?

    Well, you'll quickly discover that CodeIt.Right has good company in the form of the .NET Framework guidelines and FxCop rules.  But that just shifts the discussion without solving the problem.  Why does everyone seem not to like this code?

    First, understand that you cannot instantiate Shape, by design.  The "abstract" designation effectively communicates Shape's incompleteness.  It's more of a template than a finished class in that creating a Shape makes no sense without the added specificity of a derived type, like Square.

    So the only way classes outside of the inheritance hierarchy can interact with Shape indirectly, via Square.  They create Squares, and those Squares decide how to go about interacting with Shape.  Don't believe me?  Try getting around this.  Try creating a Shape in code or try deleting Square's constructor and calling new Square(color).  Neither will compile.

    Thus, when you make Shape's constructor public or internal, you invite users of your inheritance hierarchy to do something impossible.  You engage in false advertising and you confuse them.  CodeIt.Right is helping you avoid this mistake.

    Do not catch generic exception types

    Next up, let's consider the wisdom, "do not catch generic exception types."  To see what that looks like, consider the following code.

    public bool MergeUsers(int user1Id, int user2Id)
    { try { var user1 = _userRepo.Get(user1Id); var user2 = _userRepo.Get(user2Id);
    user1.MergeWith(user2); _userRepo.Save(user1); _userRepo.Delete(user2); return true;
    } catch(Exception
    ex) { _logger.Log($"Exception
    {ex.Message} occurred."); return false;
    } }

    Here we have a method that merges two users together, given their IDs.  It accomplishes this by fetching them from some persistence ignorance scheme, invoking a merge operation, saving the merged one and deleting the vestigial one.  Oh, and it wraps the whole thing in a try block, and then logs and returns false should anything fail.

    And, by anything, I mean absolutely anything.  Business rules make merge impossible?  Log and return false.  Server out of memory?  Log it and return false.  Server hit by lightning and user data inaccessible?  Log it and return false.

    With this approach, you encounter two categories of problem.  First, you fail to reason about or distinguish among the different things that might go wrong.  And, secondly, you risk overstepping what you're equipped to handle here.  Do you really want to handle fatal system exceptions right smack in the heart of the MergeUsers business logic?

    You may encounter circumstances where you want to handle everything, but probably not as frequently as you think.  Instead of defaulting to this catch all, go through the exercise of reasoning about what could go wrong here and what you want to handle.

    Avoid language specific type names in parameters

    If you see this violation, you probably have code that resembles the following.  (Though, hopefully, you wouldn't write this actual method)

    public int Add(int xInt, int yInt)
    { return xInt + yInt;
    }

    CodeIt.Right does not like the name "int" in the parameters and this reflects a .NET Framework guideline.

    Here, we find something a single language developer may not stop to consider.  Specifically, not all languages that target the .NET framework use the same type name conveniences.  You say "int" and a VB developer says "Integer."  So if a VB developer invokes your method from a library, she may find this confusing.

    That said, I would like to take this one step further and advise that you avoid baking types into your parameter/variable names in general.  Want to know why?  Let's consider a likely outcome of some project manager coming along and saying, "we want to expand the add method to be able to handle really big numbers."  Oh, well, simple enough!

    public long Add(long xInt, long yInt)
    { return xInt + yInt;
    }

    You just needed to change the datatypes to long, and voilà!  Everything went perfectly until someone asked you at code review why you have a long called "xInt."  Oops.  You totally didn't even think about the variable names.  You'll be more careful next time.  Well, I'd advise avoiding "next time" completely by getting out of this naming habit.  The IDE can tell you the type of a variable -- don't encode it into the name redundantly.

    Until Next Time

    As I said in the introductory part of the post, I believe huge value exists in understanding code analysis rules.  You make better decisions, have better conversations, and get more mileage out of the tooling.  In general, this understanding makes you a better developer.  So I plan to continue with these explanatory posts from time to time.  Stay tuned!

    Learn more how CodeIt.Right can help you automate code reviews and improve your code quality.

    About the Author

    Erik Dietrich

    I'm a passionate software developer and active blogger. Read about me at my site. View all posts by Erik Dietrich

  • Intro to T4 Templates: Generating Text in a Hurry

    Today, I'd like to tackle a subject that inspires ambivalence in me.  Specifically, I mean the subject of automated text generation (including a common, specific flavor: code generation).

    If you haven't encountered this before, consider a common example.  When you file->new->(console) project, Visual Studio generates a Program.cs file.  This file contains standard includes, a program class, and a public static void method called "Main."  Conceptually, you just triggered text (and code) generation.

    Many schemes exist for doing this.  Really, you just need a templating scheme and some kind of processing engine to make it happen.  Think of ASP MVC, for instance.  You write markup sprinkled with interpreted variables (i.e. Razor), and your controller object processes that and spits out pure HTML to return as the response.  PHP and other server side scripting constructs operate this way and so do code/text generators.

    However, I'd like to narrow the focus to a specific case: T4 templates.  You can use this powerful construct to generate all manner of text.  But use discretion, because you can also use this powerful construct to make a huge mess.  I wrote a post about the potential perils some years back, but suffice it to say that you should take care not to automate and speed up copy and paste programming.  Make sure your case for use makes sense.

    The Very Basics

    With the obligatory disclaimer out of the way, let's get down to brass tacks.  I'll offer a lightning fast getting started primer.

    Open some kind of playpen project in Visual Studio, and add a new item.  You can find the item in question under the "General" heading as "Text Template."

    blog-intro-to-t4-templates-part1-1

    Give it a name.  For instance, I called mine "sample" while writing this post.  Once you do that, you will see it show up in the root directory of your project as Sample.tt.  Here is the text that it contains.

    <#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".txt" #>

    Save this file.  When you do so, Visual Studio will prompt you with a message about potentially harming your computer, so something must be happening behind the scenes, right?  Indeed, something has happened.  You have generated the output of the T4 generation process.  And you can see it by expanding the caret next to your Sample.tt file as shown here.

    blog-intro-to-t4-templates-part1-2

    If you open the Sample.txt file, however, you will find it empty.  That's because we haven't done anything interesting yet.  Add a new line with the text "hello world" to the bottom of the Sample.tt file and then save.  (And feel free to get rid of that message about harming your computer by opting out, if you want).  You will now see a new Sample.txt file containing the words "hello world."

    Beyond the Trivial

    While you might find it satisfying to get going, what we've done so far could be accomplished with file copy.  Let's take advantage of T4 templating in earnest.  First up, observe what happens when you change the output extension.  Make it something like .blah and observe that saving results in Sample.blah.  As you can see, there's more going on than simple text duplication.  But let's do something more interesting.

    Update your Sample.tt file to contain the following text and then click save.

    <#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".txt" #> <# for(int i = 0;
    i < 10;
    i++)
    WriteLine($"Hello
    World {i}"); #> 

    When you open Sample.txt, you will see the following.

    Hello World 0
    Hello World 1
    Hello World 2
    Hello World 3
    Hello World 4
    Hello World 5
    Hello World 6
    Hello World 7
    Hello World 8
    Hello World 9

    Pretty neat, huh?  You've used the <# #> tokens to surround first class C# that you can use to generate text.  I imagine you can see the potential here.

    Oh, and what happens when you type malformed C#?  Remove the semicolon and see for yourself.  Yes, Visual Studio offers you feedback about bad T4 template files.

    Use Cases

    I'll stop here with the T4 tutorial.  After all, I aimed only to provide an introduction.  And I think that part of any true introduction involves explaining where and how the subject might prove useful to readers.  So where do people reasonably use these things?

    Perhaps the most common usage scenario pertains to ORMs and the so-called impedance mismatch problem.  People create code generation schemes that examine databases and spit out source code that matches with them.  This approach spares the significant performance hit of some kind of runtime scheme for figuring this out, but without forcing tedious typing on dev teams.  Entity Framework makes use of T4 templates.

    I have seen other uses as well, however.  Perhaps your organization puts involved XML configuration files into any new projects and you want to generate these without copy and paste.  Or, perhaps you need to replace an expensive reflection/runtime scheme for performance reasons.  Maybe you have a good bit of layering boilerplate and object mapping to do.  Really, the sky is the limit here, but always bear in mind the caveat that I offered at the beginning of this post.  Take care not to let code/text generation be a crutch for cranking out anti-patterns more rapidly.

    The GhostDoc Use Case

    I will close by offering a tie-in with the GhostDoc offering as the final use case.  If you use GhostDoc to generate comments for methods and types in your codebase, you should know that you can customize the default generations using T4 templates.  (As an aside, I consider this a perfect use case for templating -- a software vendor offering a product to developers that assists them with writing code.)

    If you open GhostDoc's options pane and navigate to "Rules" you will see the following screen.  Double clicking any of the templates will give you the option to edit them, customizing as you see fit.

    blog-intro-to-t4-templates-part1-3

    You can thus do simple things, like adding some copyright boilerplate, for instance.  Or you could really dive into the weeds of the commenting engine to customize to your heart's content (be careful here, though).  You can exert a great deal of control.

    T4 templates offer you power and can make your life easier when used judiciously.  They're definitely a tool worth having in your tool belt.  And, if you make use of GhostDoc, this is doubly true.

    Learn more about how GhostDoc can help simplify your XML Comments, produce and maintain quality help documentation.

    About the Author

    Erik Dietrich

    I'm a passionate software developer and active blogger. Read about me at my site. View all posts by Erik Dietrich

  • Released: GhostDoc v5.4 update

    Version 5.4 of GhostDoc is a maintenance update for the v5.0 users:

    • VS2017 RC integration
    • New menu items - Getting Started Tutorial and Tutorials and Resources
    • (Pro) (Ent) Edit buttons in Options - Solution Ignore List and Options - Spelling Ignore List
    • (Pro) (Ent) Test button in Options - Solution Ignore List
    • (Ent) Now GhostDoc shows error message when Conceptual Content path is invalid in the solution configuration file
    • Fixed PathTooLongException exception when generating preview/build help file for C++ projects
    • (Ent) Updated ClassLibrary1.zip, moved all conceptual content files inside the project in GhostDoc Enterprise\Samples\Conceptual Content\
    • Improved documenting ReadOnly auto-properties in VB
    • Resolved issue re-documenting a type at the top of source code file in VB
    • Resolved issue with generating preview of the <seealso> tag for generics in VB

    For the complete list of changes, please see What's New in GhostDoc v5

    For overview of the v5.0 features, visit Overview of GhostDoc v5.0 Features

    Download the new build at http://submain.com/download/ghostdoc/

  • CodeIt.Right v3.0 Release Candidate

    We have just made available the Release Candidate of CodeIt.Right v3.0, here is the new feature highlights:

    • VS2017 RC integration
    • Solution filtering by date, source control status and file patterns
    • Summary report view (announced as the Dashboard in the Beta preview) - provides a summary view of the analysis results and metrics, customize to your needs

    These features were announced as part of our recent v3 Beta:

    • Official support for VS2015 Update 2 and ASP.NET 5/ASP.NET Core 1.0 solutions
    • New Review Code commands:
      • only opened files
      • only checked out files
      • only files modified after specific date
    • Improved Profile Editor with advanced rule search and filtering
    • Improved look and feel for Violations Report and Editor violation markers
    • New rules
    • Setting to keep the OnDemand and Instant Review profiles in sync
    • New Jenkins integration plugin
    • Batch correction is now turned off by default
    • Most every CodeIt.Right action now can be assigned a keyboard shortcut
    • For the Beta changes and screenshots, please see Overview of CodeIt.Right v3.0 Beta Features

    For the complete and detailed list of the v3.0 changes see What's New in CodeIt.Right v3.0

    To give the v3.0 Release Candidate a try, download it here - http://submain.com/download/codeit.right/beta/


    Solution Filtering

    In addition to the solution filtering by modified since specific date, open and checked out files available in the Beta, we are introducing few more options:

    • Analyze files modified Today/This Week/Last 2 Weeks/This Month – so you can set the relative date once and not have to change the date every day
    • Analyze only specific files – only include the files that match a list of file patters like *Core*.cs or Modules\*. See this KB post for the file path patterns details and examples.

    cir-v3-solution-filtering

    Summary Report

    The Summary Report tab provides an overview of the analyzed source code quality, it includes the high level summary of the current analysis information, filters, violation summary, top N violation, solution info and metrics. Additionally it provides detailed list of violations and excludes.

    The report is self-contained – no external dependencies, everything it requires is included within the html file. This makes it very easy to email the report to someone or publish it on the team portal – see example.

    cir-v3-summary-report-part

    The Summary Report is based on an ASP.NET Razor markup within the Summary.cshtml template. This makes it very easy for you to customize it to your needs.

    You will find the summary report API documentation in the help file – CodeIt.Right –> Help & Support –> Help –> Summary Report API.

    cir-v3-summary-source

     

    Feedback

    We would love to hear your feedback on the new features! Please email it to us at support@submain.com or post in the CodeIt.Right Forum.

  • Survey: What are your biggest code documentation challenges right now?

    We are looking for your input and we're willing to bribe you for answering one very simple question: What are your biggest code documentation challenges right now?

    The survey is super-quick and we're offering a $20 discount code for your time (good with any new SubMain product license purchase) that you will automatically receive once you complete the survey as our thank you.

    Take the Survey

    We'd also appreciate it if you'd help us out by tweeting about this using the link Share on Twitter or otherwise letting folks know we're interested to know their code documentation challenges.

    Thanks for your help!

  • So You've Inherited a Legacy Codebase

    blog-so-you’ve-inherited-a-legacy-codebase

    During my younger days, I worked for a company that made a habit of a strategic acquisition.  They didn't participate in Time Warner style mergers, but periodically they would purchase a smaller competitor or a related product.  And on more than one occasion, I inherited the lead role for the assimilating software from one of these organizations.  Lucky me, right?

    If I think in terms of how to describe this to someone, a plumbing analogy comes to mind.  Over the years, I have learned enough about plumbing to handle most tasks myself.  And this has exposed me to the irony of discovering a small leak in a fitting plugged by grit or debris.  I find this ironic because two wrongs make a right.  A dirty, leaky fitting reaches sub-optimal equilibrium, and you spring a leak when you clean it.

    Legacy codebases have this issue as well.  You inherit some acquired codebase, fix a tiny bug, and suddenly the defect floodgates open.  And then you realize the perilousness of your situation.

    While you might not have come by it in the same way that I did, I imagine you can relate.  At some point or another, just about every developer has been thrust into supporting some creaky codebase.  How should you handle this?

    Put Your Outrage in Check

    First, take some deep breaths.  Seriously, I mean it.  As software developers, we seem to hate code written by others.  In fact, we seem to hate our own code if we wrote it more than a few months ago.  So when you see the legacy codebase for the first time, you will feel a natural bias toward disgust.

    But don't indulge it.  Don't sit there cursing the people that wrote the code, and don't take screenshots to send to the Daily WTF.  Not only will it do you no good, but I'd go so far as to say that this is actively counterproductive.  Deciding that the code offers nothing worth salvaging makes you less inclined to try to understand it.

    The people that wrote this code dealt with older languages, older tooling, older frameworks, and generally less knowledge than we have today.  And besides, you don't know what constraints they faced.  Perhaps bosses heaped delivery pressure on them like crazy.  Perhaps someone forced them to convert to writing in a new, unfamiliar language.  Whatever the case may be, you simply didn't walk in their shoes.  So take a breath, assume they did their best, and try to understand what you have under the hood.

    Get a Visualization of the Architecture

    Once you've settled in mentally for this responsibility, seek to understand quickly.  You won't achieve this by cracking open the code and looking through random source files.  But, beyond that, you also won't achieve it by looking at their architecture documents or folder structures.  Reality gets out of sync with intention, and those things start to lie.  You need to see the big picture, but in a way that lines up with reality.

    Look for tools that map dependencies and can generate a visual of the codebase.  Plenty of these tools exist for you and can automate visual depictions.  Find one and employ it.  This will tell you whether the architecture resembles the neat diagram given to you or not.  And, more importantly, it will get you to a broad understanding much more quickly.

    Characterize

    Once you have the picture you need of the codebase and the right frame of mind, you can start doing things to it.  And the first thing you should do is to start writing characterization tests.

    If you have not heard of them before, characterization tests have the purpose of, well, characterizing the codebase.  You don't worry about correct or incorrect behaviors.  Instead, you accept at face value what the code does, and document those behaviors with tests.  You do this because you want to get a safety net in place that tells you when your changes affect inputs and outputs.

    As this XKCD cartoon ably demonstrates, someone will come to depend on the application's production behavior, however problematic.  So with legacy code, you cannot simply decide to improve a behavior and assume your users will thank you.  You need to exercise caution.

    But characterization tests do more than just provide a safety net.  As an exercise, they help you develop a deeper understanding of the codebase.  If the architectural visualization gives you a skeleton understanding, this starts to put meat on the bones.

    Isolate Problems

    With a reliable safety net in place, you can begin making strategic changes to the production code beyond simple break/fix.  I recommend that you start by finding and isolating problematic chunks of code.  In essence, this means identifying sources of technical debt and looking to improve, gradually.

    This can mean pockets of global state or extreme complexity that make for risky change.  But it might also mean dependencies on outdated libraries, frameworks, or APIs.  In order to extricate yourself from such messes, you must start to isolate them from business logic and important plumbing code.  Once you have it isolated, fixes will come more easily.

    Evolve Toward Modernity

    Once you've isolated problematic areas and archaic dependencies, it certainly seems logical to subsequently eliminate them.  And, I suggest you do just that as a general rule.  Of course, sometimes isolating them gives you enough of a win since it helps you mitigate risk.  But I would consider this the exception and not the rule.  You want to remove problem areas.

    I do not say this idly nor do I say it because I have some kind of early adopter drive for the latest and greatest.  Rather, being stuck with old tooling and infrastructure prevents you from taking advantage of modern efficiencies and gains.  When some old library prevents you from upgrading to a more modern language version, you wind up writing more, less efficient code.  Being stuck in the past will cost you money.

    The Fate of the Codebase

    As you get comfortable and take ownership of the legacy codebase, never stop contemplating its fate.  Clearly, in the beginning, someone decided that the application's value outweighed its liability factor, but that may not always continue to be true.  Keep your finger on the pulse of the codebase, while considering options like migration, retirement, evolution, and major rework.

    And, finally, remember that taking over a legacy codebase need not be onerous.  As initially shocked as I found myself with the state of some of those acquisitions, some of them turned into rewarding projects for me.  You can derive a certain satisfaction from taking over a chaotic situation and gradually steer it toward sanity.  So if you find yourself thrown into this situation, smile, roll up your sleeves, own it and make the best of it.

    Related resources

    Tools at your disposal

    SubMain offers CodeIt.Right that easily integrates into Visual Studio for flexible and intuitive automated code review solution that works real-time, on demand, at the source control check-in or as part of your build.

    Learn more how CodeIt.Right can identify technical debt, document it and gradually improve the legacy code.

    About the Author

    Erik Dietrich

    I'm a passionate software developer and active blogger. Read about me at my site. View all posts by Erik Dietrich

    

This Blog

Syndication

 
     
 
Home |  Products |  Services |  Download |  Purchase |  Support |  Community |  About Us |