skip to Main Content

Workaround for ‘Template parse errors’ in Angular

This was one of the more frustrating issues with Angular 2/4/+. It’s not an issue with Angular 2/4/+ per se, but with how webpack bundles the supporting HTML files.

This issue happens when you run webpack with the production flag (webpack -p). The compilation completes, but running the site generates a runtime error: Template parse errors

Uncaught Error: Template parse errors:
Unexpected closing tag "a". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags ("<i class="fa fa-home"></i> Home
 	<li class="nav-item"><a class="nav-link" href="/ams/#/search">AMS[ERROR ->]</a></li>
 	<li class="nav-item"><a class="nav-link" href="/ams/#/logout"><i class="fa fa-adn"></i> Logout</a"): ng:///e/e.html@0:557 Unexpected closing tag "a". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags ("MS</a></li>
 	<li class="nav-item"><a class="nav-link" href="/ams/#/logout"><i class="fa fa-adn"></i> Logout[ERROR ->]</a></li>

The suspected HTML:

<div class="navbar navbar-light bg-faded rounded navbar-toggleable-md">
<div class="collapse navbar-collapse" id="containernavbar">
        <global-search></global-search>
<ul class="navbar-nav">
 	<li class="nav-item active"><a class="nav-link" routerlink="['']"><i class="fa fa-home"></i> Home</a></li>
 	<li class="nav-item"><a class="nav-link" href="/ams/#/search">AMS</a></li>
 	<li class="nav-item"><a class="nav-link" href="/ams/#/logout"><i class="fa fa-adn"></i> Logout</a></li>
</ul>
</div>
</div>

I couldn’t find anything wrong with this HTML. I ran it through multiple online HTML validators, and the HTML always came back as valid HTML. After a few weeks of beating my head against the wall and getting nowhere, I figured there must be a way around this issue.

What I discovered, via a GitHub thread (sorry I lost the link to it) was it’s the HTML loader trying to minimize the HTML that’s causing the problem. If the HTML minimization is turned off, this issue goes away. To be fair, most folks with this error had invalid HTML. I encourage you to check your HTML before working around this issue, you may be just pushing the issue down the road.

Turning off HTML minimization is easy as updating your HTML-loader in the webpack.config.js.

Before:

{
test: /.html$/,
loader: 'html-loader'
},

After:

{
test: /.html$/,
use: [{
loader: 'html-loader',
options: {
minimize: false,
removeComments: false,
collapseWhitespace: false,
removeAttributeQuotes: false,
}
}],
},

In a Single Page Application, Should I process on the Client or the Server?

One of the selling points of the Single Page Application (SPA) was offloading work traditionally performed on the server onto the client. I feel the SPA has delivered on this promise.

However, it’s not all roses. It’s easy to get overzealous and push too much work to the client. We often forget that we can’t control the client’s environment — the client can be anything from a ten-year-old machine to the latest-and-greatest smartphone with access to varying internet speeds. The only thing we can count on is the user viewing our site in a browser.

Processing

In my experience, intensive processing and data needing consistency between the server and the client, such as date conversions or data requiring precise calculations, such as money, are prime candidates for server-side rendering.

Paging

A common task performed on the client is paging. With small datasets this works great; however, small datasets never stay small. As data grows, the application slows and eventually becomes unresponsive. Unfortunately, you don’t know it’s happening because it’s on the client and even worse it doesn’t occur on all clients making it hard to troubleshoot.

Moving paging from the client to the server will alleviate paging related performance issues on the client. You might be thinking, “but now I am making a ton of API calls. Making so many API calls doesn’t seem optimal.” True, it does seem that way, but you’ll be surprised how fast your data returns from the server. And the best part? You control the server and can increase capacity as needed.

At the end of the day, you want to provide the user a rich responsive experience and sometimes that’s letting the server do the heavy lifting.

Summary

Summarizing, when possible we want to offload work to the client, but by doing so, we can quickly overburden the client. Keeping arduous tasks such as paging and intensive processing on the server can protect us from overwhelming the client.

Examining the Case for Switch Statements

For nearly 50 years, the switch statement (also known as the case statement) has been an integral part of programming. In recent years, however, some are claiming that the switch statement has outlived its usefulness. Others go even further by labeling the switch statement as a code-smell.

In 1952, Stephen Kleene conceived the switch statement in his paper, Introduction to Metamathematics. The first notable implementation was in ALGOL 58 in 1958. Later, the switch statement was included in the indelible C programming language, which, as we know, has influenced most modern programming languages.

Fast forward to the present day and virtually every language has a switch statement. However, a few languages have omitted the switch statement. The most notable being Smalltalk.

This piqued my curiosity, why was the switch statement excluded from Smalltalk?

Andy Bower, one of the creators/proponents behind Dolphin Smalltalk shared his thoughts on why Smalltalk excluded the switch statement:

When I first came to Smalltalk from C++, I couldn’t understand how a supposedly fully fledged language didn’t support a switch/case construct. After all when I first moved up to “structured programming” from BASIC I thought that switch was one of the best things since sliced bread. However, because Smalltalk didn’t support a switch I had to look for and understand, how to overcome this deficiency. The correct answer is, of course, to use polymorphism and to make the objects themselves dispatch to the correct piece of code. Then I realized that it wasn’t a “deficiency” at all, but Smalltalk was forcing me into much finer grained OOP design than I had got(ten) used to in C++. If there had been a switch statement available it would have taken me a lot longer to learn this or, worse, I might still be programming C++/Java pseudo-object style in Smalltalk.
I would contend that in normal OOP there is no real need for a switch statement. Sometimes, when interfacing to a non-OOP world (like receiving and dispatching WM_XXXX Windows messages that are not objects but just integers), then a switch statement would be useful. In these situations, there are alternatives (like dispatching from a Dictionary) and the number of times they crop up doesn’t warrant the inclusion of additional syntax.

Was Andy right? Are we better off without the switch statement? Would other languages also benefit from excluding the switch statement?

To shed some light on this question, I’ve put together a comparison between a switch statement, a dictionary, and polymorphism. Let’s call it a smackdown. May the best implementation win!

Each implementation has a method taking one parameter, an integer, and returns a string. We’ll use cyclomatic complexity and maintainability index to examine each implementation. We’ll then take a holistic view of all three implementations.

The code.

Switch Statement

Maintainability Index72
Cyclomatic Complexity6
    public class SwitchWithFourCases
    {
        public string SwitchStatment(int color)
        {
            var colorString = "Red";

            switch (color)
            {
                case 1:
                    colorString = "Green";
                    break;

                case 2:
                    colorString = "Blue";
                    break;

                case 3:
                    colorString = "Violet";
                    break;

                case 4:
                    colorString = "Orange";
                    break;

            }

            return colorString;
        }
    }

Dictionary

Maintainability Index73
Cyclomatic Complexity3
public class DictionaryWithFourItems
{ 
    public string Dictionary(int color)
    {
        var colorString = "Red";
        var colors = new Dictionary<int, string> {{1, "Green"}, {2, "Blue"}, {3, "Violet"}, {4, "Orange"}};
        var containsKey = colors.ContainsKey(color);
        if (containsKey)
        {
            colorString = colors[color];
        }

        return colorString;
    }
}

Polymorphism

Total Maintainability Index94
Total Cyclomatic Complexity15

Interface

Maintainability Index100
Cyclomatic Complexity1
public interface IColor
{
    string ColorName { get; }
}

Factory

Maintainability Index76
Cyclomatic Complexity4
public class ColorFactory
{
    public string GetColor(int color)
    {
        IColor defaultColor = new RedColor();
        var colors = GetColors();
        var containsKey = colors.ContainsKey(color);
        if (containsKey)
        {
            var c = colors[color];
            return c.ColorName;
        }

        return defaultColor.ColorName;
    }

    private static IDictionary<int, IColor> GetColors()
    {
        return new Dictionary<int, IColor>
        {
            {1, new GreenColor()}, 
            {2, new BlueColor()}, 
            {3, new VioletColor()}, 
            {4, new OrangeColor()}, 
            {5, new MagentaColor()}
        };
    }
}

Implementation

Maintainability Index97
Cyclomatic Complexity2
public class BlueColor : IColor
{
    public string ColorName => "Blue";
}

public class RedColor : IColor
{
    public string ColorName => "Red";
}

public class GreenColor : IColor
{
    public string ColorName => "Green";
}

public class MagentaColor : IColor
{
    public string ColorName => "Magenta";
}

public class VioletColor : IColor
{
    public string ColorName => "Violet";
}

The Results

Before I dive into the results, let’s define Cyclomatic Complexity and Maintainability Index:

  • Cyclomatic Complexity is the measure of logic branching. The lower the number, the better.  
  • Maintainability Index measures maintainability of the code. It’s on a scale between 0 and 100. The higher the number, the better.
 Cyclomatic ComplexityMaintainability Index
Switch Statement672
Dictionary373
Polymorphism1594

We will examine cyclomatic complexity first.

The results for cyclomatic complexity are straightforward. The dictionary implementation is the simplest. Does this mean it’s the best solution? No, as we’ll see when we evaluate the maintainability index.

Most would think as I did, the implementation with the lowest cyclomatic complexity is the most maintainable — how could it be any other way?

In our scenario, the implementation with the lowest cyclomatic complexity isn’t the most maintainable. In fact in our scenario, it’s the opposite. The most complex implementation is the most maintainable! Mind blown!

If you recall, the higher the maintainability index score, the better. Cutting to the chase, polymorphism has the best maintainability index score — but it also has the highest cyclomatic complexity. What gives? That doesn’t seem right.

Why is the most complex implementation the most maintainable? To answer this, we must understand the maintainability index.

The maintainability index consists of 4 metrics: cyclomatic complexity, lines of code, the number of comments and the Halstead volume. The first three metrics are relatively well known, but the last one, the Halstead Volume, is relatively unknown. Like, cyclomatic complexity, the Halstead Volume attempts objectively measure code complexity.

In simple terms, Halstead Volume measures the number of moving parts (variables, system calls, arithmetic, coding constructs, etc.) in code. The higher the number of moving parts the more complexity. The lower the number of moving parts, the lower the complexity. This explains why the polymorphic implementation scores high on the maintainability index; the classes have little to no moving parts. Another way to look at the Halstead Volume is it measures “moving parts” density.

What is software, if it’s not to change? To reflect the real world, we are introducing change. I’ve added a new color to each implementation.

Below are the revised results.

 Cycolmatic ComplexityMaintainability Index
Switch Statement770
Dictionary373
Polymorphism1795

The switch statement and the polymorphic approaches both increased in cyclomatic complexity by one unit, but interestingly, the dictionary didn’t increase. At first I was puzzled by this, but then I realized the dictionary considers the colors as data and the other two implementations treat the colors as code.I’ll get down to the brass tacks.

Turing our attention to the maintainability index, only one, the switch statement, decreased in maintainability. Polymorphism’s maintainability score improved and yet the complexity also increases (we’d prefer it to decrease). As I mentioned above, this is counter-intuitive.

Our comparison shows that dictionaries can, from a complexity standpoint, scale infinitely. The polymorphic approach is by far the most maintainable and seems to increase in maintainability as more scenarios are added. The switch statement increases in complexity and decreases in maintainability when the new scenario was added. Even before we added the new scenario, it had the worst cyclomatic complexity and maintainability index measures.

Jem Finch from Google shared his thoughts on the switch statements shortcomings:

1. Polymorphic method implementations are lexically isolated from one another. Variables can be added, removed, modified, and so on without any risk of impacting unrelated code in another branch of the switch statement.  

2. Polymorphic method implementations are guaranteed to return to the correct place, assuming they terminate. Switch statements in a fall through language like C/C++/Java require an error-prone “break” statement to ensure that they return to the statement after the switch rather than the next case block.


3. The existence of a polymorphic method implementation can be enforced by the compiler, which will refuse to compile the program if a polymorphic method implementation is missing. Switch statements provide no such exhaustiveness checking.


4. Polymorphic method dispatching is extensible without access to (or recompiling of) other source code. Adding another case to a switch statement requires access to the original dispatching code, not only in one place but in every place the relevant enum is being switched on.


5. … you can test polymorphic methods independent of the switching apparatus. Most functions that switch like the example the author gave will contain other code that cannot then be separately tested; virtual method calls, on the other hand, can.

6. Polymorphic method calls guarantee constant time dispatch. No sufficiently smart compiler is necessary to convert what is naturally a linear time construct (the switch statement with fall through) into a constant time construct.

Unfortunately, or fortunately, depending on your camp, most languages have a switch statement, and they aren’t going anywhere anytime soon. With this in mind, it’s good to know what’s happening under the hood when compiling switch statements.

There are three switch statement optimizations that can occur:

  1. If-elseif statements – When a switch statement has a small number of cases or sparse cases (non-incremental values, such as 10, 250, 1000) it’s converted to an if-elseif statement.  
  2. Jump Table – In larger sets of adjacent cases (1, 2, 3, 4, 5) the compiler converts the switch statement to a jump table. A Jump Table is essentially a Hashtable with a pointer (think goto statement) to the function in memory.
  3. Binary Search – For large sets of sparse cases the compiler can implement a binary search to identify the case quickly, similar to how an index works in a database. In extraordinary cases where cases are a large number of sparse and adjacent cases, the compiler will use a combination of the three optimizations.

Summary

In an object oriented world the switch statement, conceived in 1952, is a mainstay of the software engineer. A notable exception is Smalltalk where the designers opted to exclude the switch statement.

When compared to alternative equivalent implementations, the dictionary, and polymorphism, the switch statement did not fare as well.

The switch statement is here to stay, but as our comparison has shown there are better alternatives to the switch statement.

The implementations are available on Github.

4 Practices to Lowering Your Defect Rate

Writing software is a battle between complexity and simplicity. Striking balance between the two is difficult. The trade-off is between long unmaintainable methods and too much abstraction. Tilting too far in either direction impairs code readability and increases the likelihood of defects.

Are defects avoidable? NASA tries, but they also do truckloads of testing. Their software is literally mission critical – a one shot deal. For most organizations, this isn’t the case and large amounts of testing are costly and impractical. While there is no substitute for testing, it’s possible to write defect resistant code, without testing.

In 20 years of coding and architecting applications, I’ve identified four practices to reduce defects. The first two practices limit the introduction of defects and the last two practices expose defects. Each practice is a vast topic on its own in which many books have been written. I’ve distilled each practice into a couple paragraphs and I’ve provided links to additional information when possible.

1. Write Simple Code

Simple should be easy, but it’s not. Writing simple code is hard.

Some will read this and think this means using simple language features, but this isn’t the case — simple code is not dumb code.

To keep it objective, I’m using cyclomatic complexity as a measure. There are other ways to measure complexity and other types of complexity, I hope to explore these topics in later articles.

Microsoft defines cyclomatic complexity as:

Cyclomatic complexity measures the number of linearly-independent
paths through the method, which is determined by the number and
complexity of conditional branches. A low cyclomatic complexity
generally indicates a method that is easy to understand, test, and
maintain.

What is a low cyclomatic complexity? Microsoft recommends keeping cyclomatic complexity below 25.

To be honest, I’ve found Microsoft’s recommendation of cyclomatic complexity of 25 to be too high. For maintainability and complexity, I’ve found the ideal method size is between 1 to 10 lines with a cyclomatic complexity between 1 and 5.

Bill Wagner in Effective C#, Second Edition wrote on method size:

Remember that translating your C# code into machine-executable code is a two-step process. The C# compiler generates IL that gets delivered in assemblies. The JIT compiler generates machine code for each method (or group of methods, when inlining is involved), as needed. Small functions make it much easier for the JIT compiler to amortize that cost. Small functions are also more likely to be candidates for inlining. It’s not just smallness: Simpler control flow matters just as much. Fewer control branches inside functions make it easier for the JIT compiler to enregister variables. It’s not just good practice to write clearer code; it’s how you create more efficient code at runtime.

To put cyclomatic complexity in perspective, the following method has a cyclomatic complexity of 12.

public string ComplexityOf12(int status)
{
    var isTrue = true;
    var myString = "Chuck";

    if (isTrue)
    {
        if (isTrue)
        {
            myString = string.Empty;
            isTrue = false;

            for (var index = 0; index < 10; index++)
            {
                isTrue |= Convert.ToBoolean(new Random().Next());
            }

            if (status == 1 || status == 3)
            {
                switch (status)
                {
                    case 3:
                        return "Bye";
                    case 1:
                        if (status % 1 == 0)
                        {
                            myString = "Super";
                        }
                        break;
                }

                return myString;
            }
        }
    }

    if (!isTrue)
    {
        myString = "New";
    }

    switch (status)
    {
        case 300:
            myString = "3001";
            break;
        case 400:
            myString = "4003";
            break;

    }

    return myString;
}

A generally accepted complexity hypothesis postulates a positive correlation exists between complexity and defects.

The previous line is a bit convoluted. In the simplest terms — keeping code simple reduces your defect rate.

2. Write Testable Code

Studies have shown that writing testable code, without writing the actual tests lowers the incidents of defects. This is so important and profound it needs repeating: Writing testable code, without writing the actual tests, lowers the incidents of defects.

This begs the question, what is testable code?

I define testable code as code that can be tested in isolation. This means all the dependencies can be mocked from a test. An example of a dependency is a database query. In a test, the data is mocked (faked) and an assertion of the expected behavior is made. If the assertion is true, the test passes, if not it fails.

Writing testable code might sound hard, but, in fact, it is easy when following the Inversion of Control (Dependency Injection) and the S.O.L.I.D principles. You’ll be surprised at the ease and will wonder why it took so long to start writing in this way.

3. Code Reviews

One of the most impactful practice a development team can adopt is code reviews.

Code Reviews facilitates knowledge sharing between developers. Speaking from experience, openly discussing code with other developers has had the greatest impact on my code writing skills.

In the book Code Complete, by Steve McConnell, Steve provides numerous case studies on the benefits code reviews:

  • A study of an organization at AT&T with more than 200 people reported a 14 percent increase in productivity and a 90 percent decrease in defects after the organization introduced reviews.
    • The Aetna Insurance Company found 82 percent of the errors in a program by using inspections and was able to decrease its development resources by 20 percent.
    • In a group of 11 programs developed by the same group of people, the first 5 were developed without reviews. The remaining 6 were developed with reviews. After all the programs were released to production, the first 5 had an average of 4.5 errors per 100 lines of code. The 6 that had been inspected had an average of only 0.82 errors per 100. Reviews cut the errors by over 80 percent.

If those numbers don’t sway you to adopt code reviews, then you are destined to drift into a black hole while singing Johnny Paycheck’s Take This Job and Shove It.

4. Unit Testing

I’ll admit, when I am up against a deadline testing is the first thing to go. But the benefits of testing can’t be denied as the following studies illustrate.

Microsoft performed a study on the Effectiveness on Unit Testing. They found that coding version 2 (version 1 had no testing) with automated testing immediately reduced defects by 20%, but at a cost of an additional 30%.

Another study looked at Test Driven Development (TDD). They observed an increase in code quality, more than two times, compared to similar projects not using TDD. TDD projects took on average 15% longer to develop. A side-effect of TDD was the tests served as documentation for the libraries and API’s.

Lastly, in a study on Test Coverage and Post-Verification Defects:

… We find that in both projects the increase in test coverage is
associated with decrease in field reported problems when adjusted for
the number of prerelease changes…

An Example

The following code has a cyclomatic complexity of 4.

    public void SendUserHadJoinedEmailToAdministrator(DataAccess.Database.Schema.dbo.Agency agency, User savedUser)
    {
        AgencySettingsRepository agencySettingsRepository = new AgencySettingsRepository();
        var agencySettings = agencySettingsRepository.GetById(agency.Id);

        if (agencySettings != null)
        {
            var newAuthAdmin = agencySettings.NewUserAuthorizationContact;

            if (newAuthAdmin.IsNotNull())
            {
                EmailService emailService = new EmailService();

                emailService.SendTemplate(new[] { newAuthAdmin.Email }, GroverConstants.EmailTemplate.NewUserAdminNotification, s =>
                {
                    s.Add(new EmailToken { Token = "Domain", Value = _settings.Domain });
                    s.Add(new EmailToken
                    {
                        Token = "Subject",
                        Value =
                    string.Format("New User {0} has joined {1} on myGrover.", savedUser.FullName(), agency.Name)
                    });
                    s.Add(new EmailToken { Token = "Name", Value = savedUser.FullName() });

                    return s;
                });
            }
        }
    }

Let’s examine the testability of the above code.

Is this simple code?

Yes, it is, the cyclomatic complexity is below 5.

Are there any dependencies?

Yes. There are 2 services AgencySettingsRepository and EmailService.

Are the services mockable?

No, their creation is hidden within the method.

Is the code testable?

No, this code isn’t testable because we can’t mock AgencySettingsRepository and EmailService.

Example of Refactored Code

How can we make this code testable?

We inject (using constuctor injection) AgencySettingsRepository and EmailService as dependencies. This allows us to mock them from a test and test in isolation.

Below is the refactored version.

Notice how the services are injected into the constructor. This allows us to control which implementation is passed into the SendMail constructor. It’s then easy to pass dummy data and intercept the service method calls.

public class SendEmail
{
    private IAgencySettingsRepository _agencySettingsRepository;
    private IEmailService _emailService;


    public SendEmail(IAgencySettingsRepository agencySettingsRepository, IEmailService emailService)
    {
        _agencySettingsRepository = agencySettingsRepository;
        _emailService = emailService;
    }

    public void SendUserHadJoinedEmailToAdministrator(DataAccess.Database.Schema.dbo.Agency agency, User savedUser)
    {
        var agencySettings = _agencySettingsRepository.GetById(agency.Id);

        if (agencySettings != null)
        {
            var newAuthAdmin = agencySettings.NewUserAuthorizationContact;

            if (newAuthAdmin.IsNotNull())
            {
                _emailService.SendTemplate(new[] { newAuthAdmin.Email },
                GroverConstants.EmailTemplate.NewUserAdminNotification, s =>
                {
                    s.Add(new EmailToken { Token = "Domain", Value = _settings.Domain });
                    s.Add(new EmailToken
                    {
                        Token = "Subject",
                        Value = string.Format("New User {0} has joined {1} on myGrover.", savedUser.FullName(), agency.Name)
                    });
                    s.Add(new EmailToken { Token = "Name", Value = savedUser.FullName() });

                    return s;
                });
            }
        }
    }
}

Testing Exmaple

Below is an example of testing in isolation. We are using the mocking framework FakeItEasy.

    [Test]
    public void TestEmailService()
    {
        //Given

        //Using FakeItEasy mocking framework
        var repository = A<IAgencySettingsRepository>.Fake();
        var service = A<IEmailService>.Fake();

        var agency = new Agency { Name = "Acme Inc." };
        var user = new User { FirstName = "Chuck", LastName = "Conway", Email = "chuck.conway@fakedomain.com" }

        //When

        var sendEmail = new SendEmail(repository, service);
        sendEmail.SendUserHadJoinedEmailToAdministrator(agency, user);


        //Then
        //An exception is thrown when this is not called.
        A.CallTo(() => service.SendTemplate(A<Agency>.Ignore, A<User>.Ignore)).MustHaveHappened();

    }

Closing

Writing defect resistance code is surprisingly easy. Don’t get me wrong, you’ll never write defect-free code (if you figure out how, let me know!), but by following the 4 practices outlined in this article you’ll see a decrease in defects found in your code.

To recap, Writing Simple Code is keeping the cyclomatic complexity around 5 and the method size small. Writing Testable Code is easily achieved when following the Inversion of Control and the S.O.L.I.D Principles. Code Reviews help you and the team understand the domain and the code you’ve written — just having to explain your code will reveal issues. And lastly, Unit Testing can drastically improve your code quality and provide documentation for future developers.

Back To Top